From 78ee8d1c4cdad7a56dbf50f1c8ade75531ce620c Mon Sep 17 00:00:00 2001 From: Julian Grajkowski Date: Tue, 19 Jul 2022 09:15:34 +0100 Subject: [PATCH] qat: Import a new Intel (R) QAT driver QAT in-tree driver ported from out-of-tree release available from 01.org. The driver exposes complete cryptography and data compression API in the kernel and integrates with Open Crypto Framework. Details of supported operations, devices and usage can be found in man and on 01.org. Patch co-authored by: Krzysztof Zdziarski Patch co-authored by: Michal Jaraczewski Patch co-authored by: Michal Gulbicki Patch co-authored by: Julian Grajkowski Patch co-authored by: Piotr Kasierski Patch co-authored by: Adam Czupryna Patch co-authored by: Konrad Zelazny Patch co-authored by: Katarzyna Rucinska Patch co-authored by: Lukasz Kolodzinski Patch co-authored by: Zbigniew Jedlinski Reviewed by: markj, jhb (OCF integration) Reviewed by: debdrup, pauamma (docs) Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D34632 --- share/man/man4/qat.4 | 127 + sys/contrib/dev/qat/LICENSE | 46 +- sys/contrib/dev/qat/qat_200xx.bin | Bin 0 -> 1062072 bytes sys/contrib/dev/qat/qat_200xx_mmp.bin | Bin 0 -> 120452 bytes sys/contrib/dev/qat/qat_895xcc.bin | Bin 0 -> 1321568 bytes sys/contrib/dev/qat/qat_895xcc_mmp.bin | Bin 0 -> 119808 bytes sys/contrib/dev/qat/qat_c3xxx.bin | Bin 0 -> 1062072 bytes sys/contrib/dev/qat/qat_c3xxx_mmp.bin | Bin 0 -> 120452 bytes sys/contrib/dev/qat/qat_c4xxx.bin | Bin 0 -> 4777880 bytes sys/contrib/dev/qat/qat_c4xxx_mmp.bin | Bin 0 -> 127044 bytes sys/contrib/dev/qat/qat_c62x.bin | Bin 0 -> 1592872 bytes sys/contrib/dev/qat/qat_c62x_mmp.bin | Bin 0 -> 120452 bytes sys/dev/qat/include/adf_cfg_dev_dbg.h | 12 + sys/dev/qat/include/adf_cfg_device.h | 75 + sys/dev/qat/include/adf_cnvnr_freq_counters.h | 11 + sys/dev/qat/include/adf_dev_err.h | 80 + .../qat/include/adf_freebsd_pfvf_ctrs_dbg.h | 10 + sys/dev/qat/include/adf_fw_counters.h | 40 + sys/dev/qat/include/adf_heartbeat.h | 33 + sys/dev/qat/include/adf_heartbeat_dbg.h | 11 + sys/dev/qat/include/adf_pf2vf_msg.h | 182 + sys/dev/qat/include/adf_ver_dbg.h | 11 + .../qat/include/common/adf_accel_devices.h | 585 ++ sys/dev/qat/include/common/adf_cfg.h | 79 + sys/dev/qat/include/common/adf_cfg_common.h | 211 + sys/dev/qat/include/common/adf_cfg_strings.h | 132 + sys/dev/qat/include/common/adf_cfg_user.h | 46 + sys/dev/qat/include/common/adf_common_drv.h | 368 + sys/dev/qat/include/common/adf_transport.h | 27 + .../common/adf_transport_access_macros.h | 169 + .../include/common/adf_transport_internal.h | 58 + .../include/common/icp_qat_fw_loader_handle.h | 53 + sys/dev/qat/include/common/icp_qat_hal.h | 196 + sys/dev/qat/include/common/icp_qat_uclo.h | 558 ++ sys/dev/qat/include/common/qat_freebsd.h | 156 + .../include/common/sal_statistics_strings.h | 33 + sys/dev/qat/include/icp_qat_fw.h | 292 + sys/dev/qat/include/icp_qat_fw_init_admin.h | 222 + sys/dev/qat/include/icp_qat_hw.h | 326 + sys/dev/qat/include/qat_ocf_mem_pool.h | 142 + sys/dev/qat/include/qat_ocf_utils.h | 61 + sys/dev/qat/qat/qat_ocf.c | 1228 ++++ sys/dev/qat/qat/qat_ocf_mem_pool.c | 564 ++ sys/dev/qat/qat/qat_ocf_utils.c | 172 + .../qat_api/common/compression/dc_buffers.c | 116 + .../qat_api/common/compression/dc_datapath.c | 1790 +++++ .../qat/qat_api/common/compression/dc_dp.c | 545 ++ .../common/compression/dc_header_footer.c | 237 + .../qat_api/common/compression/dc_session.c | 957 +++ .../qat/qat_api/common/compression/dc_stats.c | 90 + .../common/compression/icp_sal_dc_err.c | 33 + .../common/compression/include/dc_datapath.h | 186 + .../compression/include/dc_error_counter.h | 25 + .../compression/include/dc_header_footer.h | 44 + .../common/compression/include/dc_session.h | 278 + .../common/compression/include/dc_stats.h | 81 + .../common/crypto/sym/include/lac_session.h | 622 ++ .../common/crypto/sym/include/lac_sym.h | 356 + .../crypto/sym/include/lac_sym_alg_chain.h | 294 + .../crypto/sym/include/lac_sym_auth_enc.h | 87 + .../common/crypto/sym/include/lac_sym_cb.h | 55 + .../crypto/sym/include/lac_sym_cipher.h | 312 + .../crypto/sym/include/lac_sym_cipher_defs.h | 182 + .../common/crypto/sym/include/lac_sym_hash.h | 559 ++ .../crypto/sym/include/lac_sym_hash_defs.h | 344 + .../sym/include/lac_sym_hash_precomputes.h | 176 + .../common/crypto/sym/include/lac_sym_key.h | 184 + .../crypto/sym/include/lac_sym_partial.h | 121 + .../common/crypto/sym/include/lac_sym_qat.h | 209 + .../crypto/sym/include/lac_sym_qat_cipher.h | 291 + .../crypto/sym/include/lac_sym_qat_hash.h | 309 + .../include/lac_sym_qat_hash_defs_lookup.h | 139 + .../crypto/sym/include/lac_sym_qat_key.h | 189 + .../common/crypto/sym/include/lac_sym_queue.h | 51 + .../common/crypto/sym/include/lac_sym_stats.h | 191 + .../common/crypto/sym/key/lac_sym_key.c | 3021 +++++++++ .../common/crypto/sym/lac_sym_alg_chain.c | 1860 ++++++ .../qat_api/common/crypto/sym/lac_sym_api.c | 1130 ++++ .../common/crypto/sym/lac_sym_auth_enc.c | 197 + .../qat_api/common/crypto/sym/lac_sym_cb.c | 545 ++ .../common/crypto/sym/lac_sym_cipher.c | 416 ++ .../common/crypto/sym/lac_sym_compile_check.c | 45 + .../qat_api/common/crypto/sym/lac_sym_dp.c | 1080 +++ .../qat_api/common/crypto/sym/lac_sym_hash.c | 783 +++ .../crypto/sym/lac_sym_hash_sw_precomputes.c | 353 + .../common/crypto/sym/lac_sym_partial.c | 75 + .../qat_api/common/crypto/sym/lac_sym_queue.c | 165 + .../qat_api/common/crypto/sym/lac_sym_stats.c | 139 + .../common/crypto/sym/qat/lac_sym_qat.c | 227 + .../crypto/sym/qat/lac_sym_qat_cipher.c | 889 +++ .../common/crypto/sym/qat/lac_sym_qat_hash.c | 942 +++ .../sym/qat/lac_sym_qat_hash_defs_lookup.c | 491 ++ .../common/crypto/sym/qat/lac_sym_qat_key.c | 196 + .../qat/qat_api/common/ctrl/sal_compression.c | 1554 +++++ .../qat_api/common/ctrl/sal_create_services.c | 105 + sys/dev/qat/qat_api/common/ctrl/sal_crypto.c | 1837 +++++ .../qat_api/common/ctrl/sal_ctrl_services.c | 1344 ++++ sys/dev/qat/qat_api/common/ctrl/sal_list.c | 99 + .../qat_api/common/include/lac_buffer_desc.h | 252 + .../qat/qat_api/common/include/lac_common.h | 847 +++ .../qat/qat_api/common/include/lac_hooks.h | 234 + sys/dev/qat/qat_api/common/include/lac_list.h | 137 + sys/dev/qat/qat_api/common/include/lac_log.h | 46 + sys/dev/qat/qat_api/common/include/lac_mem.h | 577 ++ .../qat_api/common/include/lac_mem_pools.h | 278 + .../qat/qat_api/common/include/lac_module.h | 13 + sys/dev/qat/qat_api/common/include/lac_sal.h | 498 ++ .../qat/qat_api/common/include/lac_sal_ctrl.h | 100 + .../qat_api/common/include/lac_sal_types.h | 198 + .../common/include/lac_sal_types_crypto.h | 179 + sys/dev/qat/qat_api/common/include/lac_sync.h | 376 ++ .../qat_api/common/include/sal_qat_cmn_msg.h | 209 + .../common/include/sal_service_state.h | 94 + .../qat_api/common/include/sal_statistics.h | 102 + .../qat_api/common/include/sal_string_parse.h | 66 + .../common/include/sal_types_compression.h | 150 + .../common/qat_comms/sal_qat_cmn_msg.c | 219 + sys/dev/qat/qat_api/common/stubs/lac_stubs.c | 413 ++ .../qat_api/common/utils/lac_buffer_desc.c | 492 ++ .../common/utils/lac_lock_free_stack.h | 87 + sys/dev/qat/qat_api/common/utils/lac_mem.c | 118 + .../qat/qat_api/common/utils/lac_mem_pools.c | 430 ++ sys/dev/qat/qat_api/common/utils/lac_sync.c | 123 + .../qat_api/common/utils/sal_service_state.c | 46 + .../qat/qat_api/common/utils/sal_statistics.c | 203 + .../qat_api/common/utils/sal_string_parse.c | 59 + .../qat_api/common/utils/sal_user_process.c | 84 + .../qat/qat_api/common/utils/sal_versions.c | 177 + sys/dev/qat/qat_api/device/dev_info.c | 135 + .../qat/qat_api/firmware/include/icp_qat_fw.h | 1333 ++++ .../firmware/include/icp_qat_fw_comp.h | 1029 +++ .../qat_api/firmware/include/icp_qat_fw_la.h | 2280 +++++++ .../qat_api/firmware/include/icp_qat_fw_mmp.h | 5926 +++++++++++++++++ .../firmware/include/icp_qat_fw_mmp_ids.h | 1555 +++++ .../qat_api/firmware/include/icp_qat_fw_pke.h | 418 ++ .../qat/qat_api/firmware/include/icp_qat_hw.h | 1552 +++++ sys/dev/qat/qat_api/freebsd_module.c | 68 + sys/dev/qat/qat_api/include/cpa.h | 677 ++ sys/dev/qat/qat_api/include/cpa_dev.h | 144 + sys/dev/qat/qat_api/include/cpa_types.h | 244 + sys/dev/qat/qat_api/include/dc/cpa_dc.h | 2461 +++++++ sys/dev/qat/qat_api/include/dc/cpa_dc_bp.h | 320 + sys/dev/qat/qat_api/include/dc/cpa_dc_dp.h | 746 +++ sys/dev/qat/qat_api/include/icp_buffer_desc.h | 77 + sys/dev/qat/qat_api/include/icp_sal.h | 40 + sys/dev/qat/qat_api/include/icp_sal_iommu.h | 84 + sys/dev/qat/qat_api/include/icp_sal_nrbg_ht.h | 66 + sys/dev/qat/qat_api/include/icp_sal_poll.h | 366 + sys/dev/qat/qat_api/include/icp_sal_user.h | 871 +++ .../qat/qat_api/include/icp_sal_versions.h | 97 + .../qat/qat_api/include/lac/cpa_cy_common.h | 649 ++ sys/dev/qat/qat_api/include/lac/cpa_cy_dh.h | 514 ++ sys/dev/qat/qat_api/include/lac/cpa_cy_dsa.h | 1443 ++++ sys/dev/qat/qat_api/include/lac/cpa_cy_ec.h | 766 +++ sys/dev/qat/qat_api/include/lac/cpa_cy_ecdh.h | 358 + .../qat/qat_api/include/lac/cpa_cy_ecdsa.h | 839 +++ sys/dev/qat/qat_api/include/lac/cpa_cy_im.h | 339 + sys/dev/qat/qat_api/include/lac/cpa_cy_key.h | 1207 ++++ sys/dev/qat/qat_api/include/lac/cpa_cy_ln.h | 519 ++ .../qat/qat_api/include/lac/cpa_cy_prime.h | 450 ++ sys/dev/qat/qat_api/include/lac/cpa_cy_rsa.h | 907 +++ sys/dev/qat/qat_api/include/lac/cpa_cy_sym.h | 1844 +++++ .../qat/qat_api/include/lac/cpa_cy_sym_dp.h | 986 +++ .../qat_direct/include/adf_kernel_types.h | 20 + .../qat_direct/include/icp_accel_devices.h | 157 + .../qat_direct/include/icp_adf_accel_mgr.h | 172 + .../qat_api/qat_direct/include/icp_adf_cfg.h | 127 + .../qat_direct/include/icp_adf_debug.h | 136 + .../qat_direct/include/icp_adf_esram.h | 30 + .../qat_api/qat_direct/include/icp_adf_init.h | 215 + .../qat_api/qat_direct/include/icp_adf_poll.h | 52 + .../qat_direct/include/icp_adf_transport.h | 286 + .../qat_direct/include/icp_adf_transport_dp.h | 82 + .../src/lac_adf_interface_freebsd.c | 424 ++ .../qat/qat_api/qat_kernel/src/lac_symbols.c | 74 + .../qat_api/qat_kernel/src/qat_transport.c | 426 ++ .../qat/qat_api/qat_utils/include/qat_utils.h | 851 +++ .../qat_api/qat_utils/src/QatUtilsAtomic.c | 78 + .../qat_api/qat_utils/src/QatUtilsCrypto.c | 152 + .../qat_api/qat_utils/src/QatUtilsSemaphore.c | 169 + .../qat_api/qat_utils/src/QatUtilsServices.c | 113 + .../qat_api/qat_utils/src/QatUtilsSpinLock.c | 45 + sys/dev/qat/qat_common/adf_accel_engine.c | 267 + sys/dev/qat/qat_common/adf_aer.c | 342 + sys/dev/qat/qat_common/adf_cfg.c | 574 ++ sys/dev/qat/qat_common/adf_cfg_bundle.c | 377 ++ sys/dev/qat/qat_common/adf_cfg_bundle.h | 55 + sys/dev/qat/qat_common/adf_cfg_device.c | 1102 +++ sys/dev/qat/qat_common/adf_cfg_instance.c | 156 + sys/dev/qat/qat_common/adf_cfg_instance.h | 19 + sys/dev/qat/qat_common/adf_cfg_section.c | 1144 ++++ sys/dev/qat/qat_common/adf_cfg_section.h | 19 + sys/dev/qat/qat_common/adf_clock.c | 187 + sys/dev/qat/qat_common/adf_dev_err.c | 319 + sys/dev/qat/qat_common/adf_dev_mgr.c | 406 ++ sys/dev/qat/qat_common/adf_freebsd_admin.c | 602 ++ .../qat/qat_common/adf_freebsd_cfg_dev_dbg.c | 78 + .../qat_common/adf_freebsd_cnvnr_ctrs_dbg.c | 179 + .../qat_common/adf_freebsd_heartbeat_dbg.c | 106 + .../qat_common/adf_freebsd_pfvf_ctrs_dbg.c | 137 + .../qat_common/adf_freebsd_transport_debug.c | 209 + sys/dev/qat/qat_common/adf_freebsd_ver_dbg.c | 149 + sys/dev/qat/qat_common/adf_fw_counters.c | 411 ++ sys/dev/qat/qat_common/adf_heartbeat.c | 213 + sys/dev/qat/qat_common/adf_hw_arbiter.c | 186 + sys/dev/qat/qat_common/adf_init.c | 730 ++ sys/dev/qat/qat_common/adf_isr.c | 345 + .../qat/qat_common/adf_pf2vf_capabilities.c | 147 + sys/dev/qat/qat_common/adf_pf2vf_msg.c | 896 +++ .../qat_common/adf_pf2vf_ring_to_svc_map.c | 74 + sys/dev/qat/qat_common/adf_transport.c | 747 +++ sys/dev/qat/qat_common/adf_vf2pf_msg.c | 275 + sys/dev/qat/qat_common/adf_vf_isr.c | 393 ++ sys/dev/qat/qat_common/qat_common_module.c | 46 + sys/dev/qat/qat_common/qat_freebsd.c | 135 + sys/dev/qat/qat_common/qat_hal.c | 1848 +++++ sys/dev/qat/qat_common/qat_uclo.c | 2188 ++++++ .../qat/qat_hw/qat_200xx/adf_200xx_hw_data.c | 541 ++ .../qat/qat_hw/qat_200xx/adf_200xx_hw_data.h | 128 + sys/dev/qat/qat_hw/qat_200xx/adf_drv.c | 280 + .../qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.c | 415 ++ .../qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.h | 127 + sys/dev/qat/qat_hw/qat_c3xxx/adf_drv.c | 269 + .../qat_hw/qat_c4xxx/adf_c4xxx_ae_config.c | 167 + .../qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.c | 2302 +++++++ .../qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.h | 570 ++ .../qat/qat_hw/qat_c4xxx/adf_c4xxx_inline.h | 599 ++ .../qat_c4xxx/adf_c4xxx_misc_error_stats.c | 106 + .../qat_c4xxx/adf_c4xxx_misc_error_stats.h | 12 + .../qat_c4xxx/adf_c4xxx_pke_replay_stats.c | 100 + .../qat_c4xxx/adf_c4xxx_pke_replay_stats.h | 12 + sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.c | 1345 ++++ sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.h | 20 + .../qat/qat_hw/qat_c4xxx/adf_c4xxx_res_part.c | 195 + .../qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.c | 94 + .../qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.h | 76 + sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c | 268 + .../qat/qat_hw/qat_c62x/adf_c62x_hw_data.c | 420 ++ .../qat/qat_hw/qat_c62x/adf_c62x_hw_data.h | 117 + sys/dev/qat/qat_hw/qat_c62x/adf_drv.c | 270 + .../qat_dh895xcc/adf_dh895xcc_hw_data.c | 405 ++ .../qat_dh895xcc/adf_dh895xcc_hw_data.h | 146 + sys/dev/qat/qat_hw/qat_dh895xcc/adf_drv.c | 262 + sys/modules/Makefile | 2 + sys/modules/qat/Makefile | 9 + sys/modules/qat/qat/Makefile | 24 + sys/modules/qat/qat_api/Makefile | 75 + sys/modules/qat/qat_common/Makefile | 29 + sys/modules/qat/qat_hw/Makefile | 27 + sys/modules/qatfw/Makefile | 10 +- sys/modules/qatfw/qat_200xx/Makefile | 10 + sys/modules/qatfw/qat_c3xxx/Makefile | 10 + sys/modules/qatfw/qat_c4xxx/Makefile | 10 + sys/modules/qatfw/qat_c62x/Makefile | 10 + sys/modules/qatfw/qat_dh895xcc/Makefile | 10 + 255 files changed, 99110 insertions(+), 11 deletions(-) create mode 100644 share/man/man4/qat.4 create mode 100644 sys/contrib/dev/qat/qat_200xx.bin create mode 100644 sys/contrib/dev/qat/qat_200xx_mmp.bin create mode 100644 sys/contrib/dev/qat/qat_895xcc.bin create mode 100644 sys/contrib/dev/qat/qat_895xcc_mmp.bin create mode 100644 sys/contrib/dev/qat/qat_c3xxx.bin create mode 100644 sys/contrib/dev/qat/qat_c3xxx_mmp.bin create mode 100644 sys/contrib/dev/qat/qat_c4xxx.bin create mode 100644 sys/contrib/dev/qat/qat_c4xxx_mmp.bin create mode 100644 sys/contrib/dev/qat/qat_c62x.bin create mode 100644 sys/contrib/dev/qat/qat_c62x_mmp.bin create mode 100644 sys/dev/qat/include/adf_cfg_dev_dbg.h create mode 100644 sys/dev/qat/include/adf_cfg_device.h create mode 100644 sys/dev/qat/include/adf_cnvnr_freq_counters.h create mode 100644 sys/dev/qat/include/adf_dev_err.h create mode 100644 sys/dev/qat/include/adf_freebsd_pfvf_ctrs_dbg.h create mode 100644 sys/dev/qat/include/adf_fw_counters.h create mode 100644 sys/dev/qat/include/adf_heartbeat.h create mode 100644 sys/dev/qat/include/adf_heartbeat_dbg.h create mode 100644 sys/dev/qat/include/adf_pf2vf_msg.h create mode 100644 sys/dev/qat/include/adf_ver_dbg.h create mode 100644 sys/dev/qat/include/common/adf_accel_devices.h create mode 100644 sys/dev/qat/include/common/adf_cfg.h create mode 100644 sys/dev/qat/include/common/adf_cfg_common.h create mode 100644 sys/dev/qat/include/common/adf_cfg_strings.h create mode 100644 sys/dev/qat/include/common/adf_cfg_user.h create mode 100644 sys/dev/qat/include/common/adf_common_drv.h create mode 100644 sys/dev/qat/include/common/adf_transport.h create mode 100644 sys/dev/qat/include/common/adf_transport_access_macros.h create mode 100644 sys/dev/qat/include/common/adf_transport_internal.h create mode 100644 sys/dev/qat/include/common/icp_qat_fw_loader_handle.h create mode 100644 sys/dev/qat/include/common/icp_qat_hal.h create mode 100644 sys/dev/qat/include/common/icp_qat_uclo.h create mode 100644 sys/dev/qat/include/common/qat_freebsd.h create mode 100644 sys/dev/qat/include/common/sal_statistics_strings.h create mode 100644 sys/dev/qat/include/icp_qat_fw.h create mode 100644 sys/dev/qat/include/icp_qat_fw_init_admin.h create mode 100644 sys/dev/qat/include/icp_qat_hw.h create mode 100644 sys/dev/qat/include/qat_ocf_mem_pool.h create mode 100644 sys/dev/qat/include/qat_ocf_utils.h create mode 100644 sys/dev/qat/qat/qat_ocf.c create mode 100644 sys/dev/qat/qat/qat_ocf_mem_pool.c create mode 100644 sys/dev/qat/qat/qat_ocf_utils.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_buffers.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_datapath.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_dp.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_header_footer.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_session.c create mode 100644 sys/dev/qat/qat_api/common/compression/dc_stats.c create mode 100644 sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c create mode 100644 sys/dev/qat/qat_api/common/compression/include/dc_datapath.h create mode 100644 sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h create mode 100644 sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h create mode 100644 sys/dev/qat/qat_api/common/compression/include/dc_session.h create mode 100644 sys/dev/qat/qat_api/common/compression/include/dc_stats.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_alg_chain.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher_defs.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c create mode 100644 sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c create mode 100644 sys/dev/qat/qat_api/common/ctrl/sal_compression.c create mode 100644 sys/dev/qat/qat_api/common/ctrl/sal_create_services.c create mode 100644 sys/dev/qat/qat_api/common/ctrl/sal_crypto.c create mode 100644 sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c create mode 100644 sys/dev/qat/qat_api/common/ctrl/sal_list.c create mode 100644 sys/dev/qat/qat_api/common/include/lac_buffer_desc.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_common.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_hooks.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_list.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_log.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_mem.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_mem_pools.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_module.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_sal.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_sal_types.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h create mode 100644 sys/dev/qat/qat_api/common/include/lac_sync.h create mode 100644 sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h create mode 100644 sys/dev/qat/qat_api/common/include/sal_service_state.h create mode 100644 sys/dev/qat/qat_api/common/include/sal_statistics.h create mode 100644 sys/dev/qat/qat_api/common/include/sal_string_parse.h create mode 100644 sys/dev/qat/qat_api/common/include/sal_types_compression.h create mode 100644 sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c create mode 100644 sys/dev/qat/qat_api/common/stubs/lac_stubs.c create mode 100644 sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c create mode 100644 sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h create mode 100644 sys/dev/qat/qat_api/common/utils/lac_mem.c create mode 100644 sys/dev/qat/qat_api/common/utils/lac_mem_pools.c create mode 100644 sys/dev/qat/qat_api/common/utils/lac_sync.c create mode 100644 sys/dev/qat/qat_api/common/utils/sal_service_state.c create mode 100644 sys/dev/qat/qat_api/common/utils/sal_statistics.c create mode 100644 sys/dev/qat/qat_api/common/utils/sal_string_parse.c create mode 100644 sys/dev/qat/qat_api/common/utils/sal_user_process.c create mode 100644 sys/dev/qat/qat_api/common/utils/sal_versions.c create mode 100644 sys/dev/qat/qat_api/device/dev_info.c create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw_comp.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw_la.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp_ids.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_fw_pke.h create mode 100644 sys/dev/qat/qat_api/firmware/include/icp_qat_hw.h create mode 100644 sys/dev/qat/qat_api/freebsd_module.c create mode 100644 sys/dev/qat/qat_api/include/cpa.h create mode 100644 sys/dev/qat/qat_api/include/cpa_dev.h create mode 100644 sys/dev/qat/qat_api/include/cpa_types.h create mode 100644 sys/dev/qat/qat_api/include/dc/cpa_dc.h create mode 100644 sys/dev/qat/qat_api/include/dc/cpa_dc_bp.h create mode 100644 sys/dev/qat/qat_api/include/dc/cpa_dc_dp.h create mode 100644 sys/dev/qat/qat_api/include/icp_buffer_desc.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal_iommu.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal_nrbg_ht.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal_poll.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal_user.h create mode 100644 sys/dev/qat/qat_api/include/icp_sal_versions.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_common.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_dh.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_dsa.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_ec.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_ecdh.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_ecdsa.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_im.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_key.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_ln.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_prime.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_rsa.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_sym.h create mode 100644 sys/dev/qat/qat_api/include/lac/cpa_cy_sym_dp.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/adf_kernel_types.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_accel_devices.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_accel_mgr.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_cfg.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_debug.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_esram.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_init.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_poll.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport.h create mode 100644 sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport_dp.h create mode 100644 sys/dev/qat/qat_api/qat_kernel/src/lac_adf_interface_freebsd.c create mode 100644 sys/dev/qat/qat_api/qat_kernel/src/lac_symbols.c create mode 100644 sys/dev/qat/qat_api/qat_kernel/src/qat_transport.c create mode 100644 sys/dev/qat/qat_api/qat_utils/include/qat_utils.h create mode 100644 sys/dev/qat/qat_api/qat_utils/src/QatUtilsAtomic.c create mode 100644 sys/dev/qat/qat_api/qat_utils/src/QatUtilsCrypto.c create mode 100644 sys/dev/qat/qat_api/qat_utils/src/QatUtilsSemaphore.c create mode 100644 sys/dev/qat/qat_api/qat_utils/src/QatUtilsServices.c create mode 100644 sys/dev/qat/qat_api/qat_utils/src/QatUtilsSpinLock.c create mode 100644 sys/dev/qat/qat_common/adf_accel_engine.c create mode 100644 sys/dev/qat/qat_common/adf_aer.c create mode 100644 sys/dev/qat/qat_common/adf_cfg.c create mode 100644 sys/dev/qat/qat_common/adf_cfg_bundle.c create mode 100644 sys/dev/qat/qat_common/adf_cfg_bundle.h create mode 100644 sys/dev/qat/qat_common/adf_cfg_device.c create mode 100644 sys/dev/qat/qat_common/adf_cfg_instance.c create mode 100644 sys/dev/qat/qat_common/adf_cfg_instance.h create mode 100644 sys/dev/qat/qat_common/adf_cfg_section.c create mode 100644 sys/dev/qat/qat_common/adf_cfg_section.h create mode 100644 sys/dev/qat/qat_common/adf_clock.c create mode 100644 sys/dev/qat/qat_common/adf_dev_err.c create mode 100644 sys/dev/qat/qat_common/adf_dev_mgr.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_admin.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_cfg_dev_dbg.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_cnvnr_ctrs_dbg.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_heartbeat_dbg.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_pfvf_ctrs_dbg.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_transport_debug.c create mode 100644 sys/dev/qat/qat_common/adf_freebsd_ver_dbg.c create mode 100644 sys/dev/qat/qat_common/adf_fw_counters.c create mode 100644 sys/dev/qat/qat_common/adf_heartbeat.c create mode 100644 sys/dev/qat/qat_common/adf_hw_arbiter.c create mode 100644 sys/dev/qat/qat_common/adf_init.c create mode 100644 sys/dev/qat/qat_common/adf_isr.c create mode 100644 sys/dev/qat/qat_common/adf_pf2vf_capabilities.c create mode 100644 sys/dev/qat/qat_common/adf_pf2vf_msg.c create mode 100644 sys/dev/qat/qat_common/adf_pf2vf_ring_to_svc_map.c create mode 100644 sys/dev/qat/qat_common/adf_transport.c create mode 100644 sys/dev/qat/qat_common/adf_vf2pf_msg.c create mode 100644 sys/dev/qat/qat_common/adf_vf_isr.c create mode 100644 sys/dev/qat/qat_common/qat_common_module.c create mode 100644 sys/dev/qat/qat_common/qat_freebsd.c create mode 100644 sys/dev/qat/qat_common/qat_hal.c create mode 100644 sys/dev/qat/qat_common/qat_uclo.c create mode 100644 sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.c create mode 100644 sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.h create mode 100644 sys/dev/qat/qat_hw/qat_200xx/adf_drv.c create mode 100644 sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.c create mode 100644 sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.h create mode 100644 sys/dev/qat/qat_hw/qat_c3xxx/adf_drv.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ae_config.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_inline.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_res_part.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.c create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.h create mode 100644 sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c create mode 100644 sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.c create mode 100644 sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.h create mode 100644 sys/dev/qat/qat_hw/qat_c62x/adf_drv.c create mode 100644 sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.c create mode 100644 sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.h create mode 100644 sys/dev/qat/qat_hw/qat_dh895xcc/adf_drv.c create mode 100644 sys/modules/qat/Makefile create mode 100644 sys/modules/qat/qat/Makefile create mode 100644 sys/modules/qat/qat_api/Makefile create mode 100644 sys/modules/qat/qat_common/Makefile create mode 100644 sys/modules/qat/qat_hw/Makefile create mode 100644 sys/modules/qatfw/qat_200xx/Makefile create mode 100644 sys/modules/qatfw/qat_c3xxx/Makefile create mode 100644 sys/modules/qatfw/qat_c4xxx/Makefile create mode 100644 sys/modules/qatfw/qat_c62x/Makefile create mode 100644 sys/modules/qatfw/qat_dh895xcc/Makefile diff --git a/share/man/man4/qat.4 b/share/man/man4/qat.4 new file mode 100644 index 00000000000..c6082f873a4 --- /dev/null +++ b/share/man/man4/qat.4 @@ -0,0 +1,127 @@ +.\" SPDX-License-Identifier: BSD-3-Clause +.\" Copyright(c) 2007-2022 Intel Corporation +.\" $FreeBSD$ +.Dd June 30, 2022 +.Dt QAT 4 +.Os +.Sh NAME +.Nm qat +.Nd Intel (R) QuickAssist Technology (QAT) driver +.Sh SYNOPSIS +To load the driver call: +.Pp +.Bl -item -compact +.It +kldload qat +.El +.Pp +In order to load the driver on boot add these lines to +.Xr loader.conf 5 selecting firmware(s) suitable for installed device(s) +.Pp +.Bl -item -compact +.It +qat_200xx_fw_load="YES" +.It +qat_c3xxx_fw_load="YES" +.It +qat_c4xxx_fw_load="YES" +.It +qat_c62x_fw_load="YES" +.It +qat_dh895xcc_fw_load="YES" +.It +qat_load="YES" +.El +.Sh DESCRIPTION +The +.Nm +driver supports cryptography and compression acceleration of the +Intel (R) QuickAssist Technology (QAT) devices. +.Pp +The +.Nm +driver is intended for platforms that contain: +.Bl -bullet -compact +.It +Intel (R) C62x Chipset +.It +Intel (R) Atom C3000 processor product family +.It +Intel (R) QuickAssist Adapter 8960/Intel (R) QuickAssist Adapter 8970 +(formerly known as "Lewis Hill") +.It +Intel (R) Communications Chipset 8925 to 8955 Series +.It +Intel (R) Atom P5300 processor product family +.El +.Pp +The +.Nm +driver supports cryptography and compression acceleration. +A complete API for offloading these operations is exposed in the kernel and may +be used by any other entity directly. +For details of usage and supported operations and algorithms refer to the +following documentation available from +.Lk 01.org : +.Bl -bullet -compact +.It +.Rs +.%A Intel (R) +.%T QuickAssist Technology API Programmer's Guide +.Re +.It +.Rs +.%A Intel (R) +.%T QuickAssist Technology Cryptographic API Reference Manual +.Re +.It +.Rs +.%A Intel (R) +.%T QuickAssist Technology Data Compression API Reference Manual +.Re +.It +.Rs +.%A Intel (R) +.%T QuickAssist Technology Performance Optimization Guide +.Re +.El +.Pp +In addition to exposing complete kernel API for offloading cryptography and +compression operations, the +.Nm +driver also integrates with +.Xr crypto 4 , +allowing offloading supported cryptography operations to Intel (R) QuickAssist +Technology (QAT) devices. +For details of usage and supported operations and algorithms refer to the +documentation mentioned above and +.Sx SEE ALSO +section. +.Sh COMPATIBILITY +The +.Nm +driver replaced previous implementation introduced in +.Fx 13.0 . +Current version, in addition to +.Xr crypto 4 +integration, supports also data compression and exposes a complete API for +offloading data compression and cryptography operations. +.Sh SEE ALSO +.Xr crypto 4 , +.Xr ipsec 4 , +.Xr pci 4 , +.Xr crypto 7 , +.Xr crypto 9 +.Sh HISTORY +This +.Nm +driver was introduced in +.Fx 14.0 . +.Fx 13.0 included a different version of +.Nm +driver. +.Sh AUTHORS +The +.Nm +driver was written by +.An Intel (R) Corporation . diff --git a/sys/contrib/dev/qat/LICENSE b/sys/contrib/dev/qat/LICENSE index 266294fd427..2d9af4268f0 100644 --- a/sys/contrib/dev/qat/LICENSE +++ b/sys/contrib/dev/qat/LICENSE @@ -1,11 +1,39 @@ -Copyright (c) 2007-2016 Intel Corporation. -All rights reserved. -Redistribution. Redistribution and use in binary form, without modification, are permitted provided that the following conditions are met: +Copyright (c) 2021 Intel Corporation - Redistributions must reproduce the above copyright notice and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse or promote products derived from this software without specific prior written permission. - No reverse engineering, decompilation, or disassembly of this software is permitted. - -Limited patent license. Intel Corporation grants a world-wide, royalty-free, non-exclusive license under patents it now or hereafter owns or controls to make, have made, use, import, offer to sell and sell ("Utilize") this software, but solely to the extent that any such patent is necessary to Utilize the software alone. The patent license shall not apply to any combinations which include this software. No hardware per se is licensed hereunder. +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +* Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of Intel Corporation nor the names of its suppliers + may be used to endorse or promote products derived from this software + without specific prior written permission. +* No reverse engineering, decompilation, or disassembly of this software + is permitted. + +Limited patent license. Intel Corporation grants a world-wide, +royalty-free, non-exclusive license under patents it now or hereafter +owns or controls to make, have made, use, import, offer to sell and +sell ("Utilize") this software, but solely to the extent that any +such patent is necessary to Utilize the software alone, or in +combination with an operating system licensed under an approved Open +Source license as listed by the Open Source Initiative at +http://opensource.org/licenses. The patent license shall not apply to +any other combinations which include this software. No hardware per +se is licensed hereunder. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. -DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sys/contrib/dev/qat/qat_200xx.bin b/sys/contrib/dev/qat/qat_200xx.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d1ba6ffc5f695f1b24ce1d6f07dae6039b8d8aa GIT binary patch literal 1062072 zcmdqK4}2U~b?AR~wbHJnjWn?xTXlpp`V&bcA|5-&7KsTHJB0)SY!X6D31ss>&;Z-~ z0Yd|fV#iTz6V}Cm8>e&#ens^QWuGxT*DviGLkfntu(1tDvJ6Y1ZQif^V4J3priQ%l zxihmXuOgiE&-=X3bMo*7{-B`Hp_pZO|y6bN~@6NlK=f*oe zSh(wb(ZApKp28hB-+AY|-uK?9;qE){df$7Ng*VY)TvGg}e{`P9-gxor#>}0_PqJZq zbX$9V`)Of&{5*uF-aofEggk!U9SsnVzhW?JTH@!gh@QXp%~xOb+1H17>UjY?#n4=J z+3O6Ru8sO#(vmd)irf9@K5o~CtE09S{{30=wo*f6lP5Ai)oXuzG^B$|Tlj>3{3rbR z!}YJw^ozH?=eC6}dv);*fAOu4f9=Gvzy8tJ&-wV3fBuoh*Z$TO zA4uG=@Zz7Ip8E60zWS%1T6w|uT3>f_?-`%zyz(cH-SFJ9Cm;OVm5+@6#hrit@}FJp z{=tC{|Iw~jzvkih-FM>4n=bu>kKA|unFo7sx&FU=fBDDWxbFQI?l?Q~vu}K)|N5Q{ z2RB__UbW@OtzUiD!&^T7isZ6ezx@xL8(w`;rT5`K{D*U{`mBH1J74zP(<}3LeWP=% z`{HxYIK1GBo^O1*|M|if4!wJO+jP^x%Rh9{Yu>V8&%69H|Mg`b-r9TV-S&Y)A8ePu z+cI(8KQCQ8yy3^?uE}2(`hGR~gY{RHZy*2myxq_HdoTRLM}Pb;P4D>8KRn8G{;S`4XxZlqzerrX`F9Tg z*>jx>uKUC-?tP>4cCRgc@zz^^wSC?1wpn|g-n{bNUkomI+ZzUd_1ErME57vhv%d4_ z*{|(>{nsY`?A3qv7r8ZGpZe*%2M_%G9UuSPuUEhS>sLSg=*nGf>n?lpm)*a6?Z7vG zwfXY9|Hs>!e)+?rOWwNSmL-?}x1Q&Z-|(3~@3{BBzTx>Zf4c1*fAIRBjt#!!ORKJ& z`pDk=E3Q2H%&njN*9-sUZ=YNIlhNzD|NgB1ziIc~3$1tl<>B+>*|T~#{`S)!%YE;( zH?92mXTEgdg!7jl{pI?X{w9mW2xvnn$I>!HFf7ZO~z1QFILHqhU@4WdvH{5>nP4@fVYhPTr z!(Mj2z1&&8+`j%U{&~T&S6y)aEA6}QeAjz#weNc0`)4Hb;o-?aQz)O$B!=H*|L%I9DDi7SKWBSE0?c$)pa*G=l$P^zAjazwn(>LElK2C zLn!S~#flqUFXgIylZ&pu>A7ml-}GGh@i#qJJ^Y)VH=p9U>fqnhKYfblJg)VR$N4{U zZEBKgpwK@$=D}X{ zJieapx=j;STD-I+RX;7KdqLAgpzk?m{L=$BHBnCT+?A@`!gvQ#6M2S9=cQT}Io-Xu zd7{wF^8(Mg_YO3h`O?Mkd2n&dL_z!eQuP=&WqBpKOVjNwCkg=5DXa^sw=+KPCED#^ zzlWwyZ3l_+tu3ZJq7(WBp58ZD%_Jj<$>CI4zQdVJrEx*sZqpkjuCk zIjzKEy+lXX?qbTkx2)8}dm?*ccf6&YdE(c!4Q#MnDKHO)jI^LNs`~}_G-15!}berc^My-St=UY;>lF~e1 z+-J%ykl*!64(p$1Ey;MWfy=m76ZFyXo5Z$KOETrOWIA&}Nm`^?F89VQri<2@T7V`R zPf61v+wfar5#uWVogt;&@PQ<}#S3SEzFG{DFUlu_xrE}C@ zq{a3&>Q~0S~E#Ze>eAx74-X{v7QKt?@13K_1MNi>#wL zo3Yj$Of#&)3x7xBfd6$q>u4M&ab_;qUrNt8P7N;>cmZ!cnPOi#Z^l6mxMrY39`r59 zmUct;OagrQv}d^wnx#GAoju{#`Lj#>feBZ{ZX2>60?(CFT&4|_OHN4QNJ12CH)oU-%#%D_6p-SNh-yO`(x)}2Kk1WB1T?Z`nxd#pE-b~aIU zTd*IF>@9+q4k!0e5k5hVd-CXqX#AwB?={c)UNXn?+}z{b-su>7+pKVazZkxPwin>% zhW5M6`|xc;J9>b5n$+IOUI%)p9Do=*1H8&lF~7~y$CtdW%z9$^O18satP?t3KH;l= zsq@i()lc3UDM5$lPfy*uk#Q4={MreR_BO{Y>a}Ae_mBs_bym`Y74QQ8>~~t^`3=d! zF6f>}xR*>YD$kn+ZR~0%a$}qK6N8nIZ(}}dm@j!>RqeR@+6l!|XQg@2W<2bBsS14} zxLXtM#S>-pF$ zf3mLVd2h#%y&1ZQ>L1n*p3zUrpP~Lqw!tUi`pmjebe^yL9nBAaUOHic?>XopofTvE zq!W8kqF*#G_^oUUL|)aIlc(~mzg5mqIJ%^A&4i$bzK3D}j^ue+_n8v%7TJy3^K(wX zr{HO>=l_rPPd2O@|Kn|C=+pG;)4ZyOT~a>`{%`vASw>%^?&aQtZyWuNPW%o@*W@mh z#qWUsq)jTL*cD6V68?0L^SeZ;IXqFY7Rs0n0JMou_ z@R>w@T1;;@DW5OFR|)@}6UYSvIJ*nHx5*Z-ik~ONdyoHKi#%}nWx$`5q?^2KAMzy9 z>zR4l?EJP$Le{le*#iamtu~&0{e;3j*Lcq{UIjjxYrKp!1$I&{Q9siGp4i{3kAKrd z!0>a8f6fx{2)~|U{2E?r<5q5&0RMB2`&Pz9PV3_)Js-Uy$&viFg0TmQYNc65)h{fe zCnI^a(UY6GPiAdzkDrpEwjtSBM!xX>ZRi%;_n}KayRnQsCf43)?7@|r3hpN@#{UD` z^&Hl-m~jH8+kib~oLS?wSqlajtqFblG;lSk9R+_g@Atc^UwfrgY?kL+Q_1^)JCO+9 zGvVpD=sO=eZ@_NnTcqg(@mDS>oqgCh*4<=#?q0@kOSl^+fJfZr@Q?QQ3ln+lpVFhG z{NsuTKh*f=Y4BD^NsnE<+xTrt7oYKEx#w4~kI5bRZ4P+1houy7O%(3Z_)E@p;k&ey zmoh(mCQEJi83#P}yWS&Z{I+v^*;%B0SRB8MJ{=P4mYmwjFdl19xOW=AFHydGg6B2+ z6ZdbUzXzW-^zXIZ50zPe9iHm?i5&Ap@KhBZ=idTP@PP@J`4YJgO<44g>||{{bHLMQ z2OlX{dB2XI4^N#rw z@$4ji72{(^H!HvPB$p&K{_IVz=87Mi?12AUXdgx%XUyv+ozIoPr<*K&&S5=nulL{b z%`#v8l(PCA!B+L3k;9J}Iml$&OW?b9pXEM>9%9G}^IE~hAD_sBzd8Jdo=i|V>?XwW zc+bdpP?_?GlLUQNO`&nsuCcx|S+@&35ne6tvu8{ek#l{{TVpF`v>Q8Rp3=oK?n^Tco7xO}*d5FRHJ7Mwf(apD3qg$r9cx zUGbYg&we<{!a3%3y)t_$8h_eg)N}~AbiBejYo?SHYkvy*O(T)Rm!r>CrHDd=Q zSLLMAe4>()^jSYmpD2oWyi&2DgJc(-Q2O*SPnm1nU)LQNe=K{#LVxK!_zPZS9!FM; zvrg>95cvWDKZ)X>PB`%G2>B2Xe>Q4QB)o?w6uvC)Ip{~dr(c(Ne>%Z?*^WxZN8ii2 z<;r*t{|5>J}c+YhC73NEIb@^qknW6BS9SPg5OT+sG>%#l4 z+rn%2`mlXyNPL%hhgrXeeHzN%k{Dtfn{lg*-_N)K*KF#B#CrI_-W29ftc^d*u>N@6 z_8Hy}Go>c^rosnZ>;>C@p0UB7WV(Hu@l##h#(&NXh1cvz*lt}K-Y-}e-gn&=Uc1+a z?G5nBW;yIxN~i3t7w-cuoAH4IIJL*E9 z3nmNnkMnc`;*VAUw;TQo=y#?BUne1Cd^WL-YBVU~GWd>frQw6;o z<0pnUlfA~>q41py?~M7sr13WKs?m3`|8uY2vyKgVMLsv`75TkSuU=9%=@mV3zg|_I zGXsWxl3m&5yXbA1mkCNqX_0wN0dS%pzhd;5wF!OzKMUS3em*II_Ae&ofL<#}`Kn&+ zqlq(}O@Mh{p?Sulvcbz1O?a{DHVn&;qosY%Yz_mI=S8T8~S;3Z!C%L()V ze0ka=@-pN4ea##5{6`bEx&GY*)a{bs=MxoOxBJf;|8oD&8b{La7ZZ847v8_B{hl#S zG;WZXv|p%w*1XaCZrdbs!1zCn^o41cz6$hX-F?J~K71GF4bRo}BR5g}*K_R|-!GTR zBSq`3^M!Rl`Qn<5h33s>9XalsWmC4RDF82D*J~bm?r`$k%HTQciC;6?u|eMQOS z-6it(+7gwoPdLQu$sN^g0)J-<;rvTWCZ8X_*PbZ+~vrdjk0I z%rD>1wM+8f(KxPO$E!BU=xN#Baq!fy;}(%Oz0b|G6ZyjvdGH_gkLQc^!VBcduyx^-XRH_Y?s7RAeE=JA_!p3ya9=#8Pz z8+~do*oD1Sy%ynXHedhP006x_+ozi9kgd)Jth zO6Y~|9mY>_HU24q_lPfM>CL#^R=)=R>EB2Hlj#2s6CUf0@F5X=((mFQDV!Dfj`@ZP z=3a*L27cZ%aPuC1isG&Ip1J2e^W5n}AD};K@W=XQ7T&C%PvqQ($Mm;QoZ z1N=2SMtG{@J$QP;XC2aF_$}VYX|(fVy*9M_3*H*O*L91z*5L1cfA~DcholW(NorAO zw;SxYSg#A)7hDs**LAD8*2num_&ge~27m27#9I;rup2%}X?qoZj-EGbyzP)@P<;6_ z`OJAv^j1qKJCC)r>85E0vtoEBM)2=KgRr7!*9%w4*aR_4Y3Yi`8?#ym``WCAM&lkI(RSk zBZAIy7>CVa7i;n!!Hq%;hFRmPzc!^XFEZsvdFQvLKB6Ec{9I z3wAF(30-BuSJ;ODFI~5Y9{|6F|EGF)!GD)hf%~po#rM-P#Qe{eoAv5Fo5NbjA@5n_ zKkbx!_3ve=Um347N!vNTy^H=Wb`*yVY8T(ev9n!h9-$-xgo z{8%`t-|3Ss&*zE@GsJOY^qUorc=IQ{nQ_{j@yM+gcY*(gc%&A0_fgMKflek*!#wTi zZ=3gHJr~FGQG3s|7k{Fx@)hxkQqcIfvD~Vhl<6PwSz4bXm)Jw_g`MBHV)2v3w6y9y z{1n5H=%b&{{@VEC_LICvUftg25+Ao`7izW?I{nuvm*<;u)h+O&_n9|hHx%FAnUgMg zk+F?EPgYLq_vsY!F{58$i=B|s{q%EN#MOKX`5D@_ze z)cV0sth+_Lg>ORN=z82wgz-(-KH5vWt^66b*Y%dYX-a@Y@mi(?@cin>bswe9uU`M8 zr|Ssyz((D7aZLTh*^@r>joRU(AMU5($^*USTNigs7mAM)Yz?dY8%>r=lxP=Av468&QSypZ+fOkOR@ zzm%Lw;l0#I=r72G@fYMm9gl88eT~byQ`Flahor-}XS@|Q_gt;lhV2X98ouY;(yMus zcW$bjF;+lMR=mGg^C{PDs-7{XcpBNnJ@c*p6z?_5%iD^*yO8q-S{-{=j`8dPTm3G{ zuD5-qN9H!}xsJTm_KQk)|CN*Zgj~HT$9RCH_|7w)qeT(ZXIA0gGFSsUr z&$+eN_meZ={6MeP0oCEWpL^h0{b}Ay)!_W5!m0SO2W=m?>u>^Zk@k^mY`;1izB*ll zm6P=I(!`Mk<%{yFNsoRtIG)j;HS1VkKly;WGHNFVXyj48Jzy%b~Z1eAx|uIN+fR{!sk(4|3&?y^40O z(YS$*o0nPR%JAz#{u#O^=)nB;i zYxqv}V(|@=6`c<`H~JygC#T}O;Ej_m`O;IaWB4sHV)*0DN)O;E?X=ieJXOEiI)<-y z$Ibdpzxq0YoXQV;eTDi_@p?|Vj!yVc`KYt6`xtb{gO>)nuFG~M4piA^(E26# zS`zNnljsWsNGb*RsXgC(B4GT8ugNcLn)2{x^u9v7+a$V=C>cL6d7jj;yH{wB_d_Co zE8fqkwXdQ-eBYB@@wO++$XQz{x7k77w+~6Fj32nF?C!0?XB&gJJ()9h?RV5(Sl)r( znJlUQ;J*FIlF~bPdziPgt~K^5nh$$v?qk0=zNd}~c~U%w&sn$0v)1C3EcxUBG$eBG znDkN-tg7IzsD3WyP2OTv89PUQP4N|A_Y>|rCj+%-;q#O}FOd(8>cMz^-DE}W>B;?L zeDgd%3AW#V z7p%88L#K2{!QBkp58^xnuS?6;@w4RsZ(;9tS+wAr$)0(`A@xoG1r z>ON;cyNCVGF;C3T4SXE)b#I$Zokc?WbbqFbA6Cm}c(*H_B_mf#hC1O_lE?CaKOwhI z=2S1q@RX~3X1#YZ4z%PKFUNgysJspSPi6wo*a7OIpJrUtCU5~}!XBRTTG;;a@q^S327jaa zJvlZ6f2CR9us6;)GuC&9@+)$ArL5O=$eokAz6gHWuX1(&L>_jvzo+^4e1iOY@k5gq z%|j0RgERAza<`6$zP?-awRCtBqXF-Ac+;Z-eeOM4-d33Te&GX?dC&si?uTDwsidB< zh~Lh;t+J(J_ESHgdbwp~k^CC@wv|QlUo-hTSg-M=JXk6hEv;W1%da`8a^-$d`CT^C z4nAnVehur;{I&XtE$U|n*bxCAdHiFom#idMUoqHUJc<6luXYOg`TfZNyfm(7pa?x? zuBZB8wFe0ur^I?XSr4(oD%Xv6wzIuR9KrYl z#Zs}%xY^;4xMp5=)1*({RQI`oH<1W7PJ+M2{xQEuw*O9dO!+(P*Z5xJJiP;%!<*qp z=KHA2dg^w~yMMB*`Zhl{8Q?di(T`=|uIY`~KGP1qjd+_upHFB$dj@^B zO$IEuq5lie$MkD_uW_DP^r`8^@^-arGw}OK!zV8tzn?Vzegl5f8>nlppiXP^$&PT} z%szXHRtid@x&-n?hEL-5PowXlZ|YX@v8OVCT|n+)yD+z&&+k;ZXqDA&3H>Cc9a1V7 z|9z**zYO>jqwo{g=~3iYI?Cm3)tPiF{n2Cvev0+jAad`erEOrSvITh1AAd9nKP6X| z#+R@lQTK>9Vd>$feG=%D$o(KcW8KRB@-r`lIKu-A-xV z1Uln~urEl*%y*IB7FqMkvb!Jc{!*{#w=Zix2>x<#ldVjSy_=R6oIf?tZ zpriud)amZ-3D;NIGYP$6X!5S`U23J2Y_5VoQs9zWC1D;#oJXM}<9u$oOpcefaX2$2i=l0Qx5IFP=CMu9QYZz?^AweT=+NF3tZ%bOk8Y> zEfvB4)%qIbyhZIN>-JiuYn=Xb?VqIYW!xflV|6)suk8rq+aIyZX$hqN?7x8@#6mym zI1A8Efj*ZjdUJ_W&L6Z&x1J-KYro|M=6|1U!B6e>M{U+ypC3J_NL_#)^x2Oz_+Xz} z;m#R+bPO<0oi9pXQ@kY=AJSCA-;8y7y^N1s@Se^mqrI#*_A^?NBc@)7{dePs^>(md zAJqNnb1AFa9Vj1_4yk>L@tx_%?`GbXU;VM%hd(Xj8T@4BACLFYZ~M^072@80@6eOZ zOux@NI0^Lg*2p*2?t(FMUayN18NpAXoyxP;>*b%A44P{3 ziIg->AZxZ#Bh~UYeJQfDzfk8#UtXZ|o4m?*HI7YQ zWSMhoTp!&cGvN=uXX5V%E9GKQ_3c=B&A8f2_xmQlyqR_Z51nIAuEDRA9$P9!@;1g_ z2fhgJ(CNVeJ1MPs#jo0<9C(KgHg@l%^}17LKesktro3j%zZC&p`R zPiD^({6y_M`y?;PFN@`!{U7%kp^k;Z%56F1s8z~d6}oAh3tl8+dwzjy6z5_FO1o)~ zxhLt@pXvOG3oBuqJ4;T>KU026UZ8YE zuUw#XooUyks{W-sSVm41FT{oGl@C4Ibse-TaWu|dhrDT=3qF$?=T__bY3?{Tcslg2 zt$)(^{nT-;^Uvz9&W>}D`?BT{a{sLOMURee$+IqvbCH9(-t&H8;_0YfMl{adr+g&8 z4A+Al;eFb#U$XZM~ZQ~yTwk=n9no* z(%f(d$tf$$bIb+zfattsnev-wz`d*aFm#?9?jSYAx)kn#P~XS!)!-fojGV;nHMqn1 zLb&VkbTK_ug|8wy5VvPEzvi;vr~Cg&xt)BU){REz7*n)+TIU_M1OH-;gZkP%@;o!` zT&ZnJ>hX}UDNusWP@4S)m7{Xol->_uZ(ZbQ0DH^0t;rqbZTNR}I#sh%HuiQ_ekbO8 z>$E9_XKudlmT@BviJP-VTV9h#{2RjLWb$kVu(iMAjy7Eh7o}`Ya zGJ1gZMR|!C{pU^L$I*ZOlucc+!83AO!!!8{_&PZUo^y(4YobK?ne!#X{e6ddzeVkhL;fbxXPhTp zKE?AozuERwzMx4DNpsZ z-Dmds8}cb4C+AV>{oH;%hk||!>k8I9h@H{``^jB4rTC7{{lx9$K~_((9JZ-SyFK)t-n&Xy_cGmg zsh#_|ka{zh{7~)O5Bm)8O}gc$)Uh|qH6zj#RA&0?&LvYm^74)!$+j~7KYpUt16^|g z>$UI;=Bn?KvG80@Y6ta>&?z$>UbFkccI#kxzhEM~?|Le{c0U`o4;`cqA36`SexFlg zBU^7t5PylyxacA2XI!2qvm0+n=swV_I-L3prFMkpb28)MHM=itw+@E) z3ns$*uBXCl_p@Pp1AMW+4xG1MJOX?+<6G$Ye#VD>@pIt4@#6I`d1KvLd${kI()!GT z^0RlP@^M{mgAQAAI2Vb@KLOxaf zuY9k5`F@XCGvp({FXzYJG!^K)z*E6S=zAs7NZ$3iDb){~#2ziOUiK&U;~$}4a);p) z^vM;fckQ}g&5PO1-R&gNvi3jXW% z;hL$O>fslz4~yFat^e|XBhmxlW8Gm(^|m32Ju7QJT@spygH#_jpTz;l{&8v0lDPdTss;_s6rqwkp1 z>FC~M{LT&bJ2NHpOS>ofeVt^l7k*cy&&l_xzKz;X)Al_1uRgcX2VE;ruHy4o=6lrb zDtz{>>gP)K@521C^$YX|^w?lumnrIg;jHnm@5|vg&mRBx`kba2TYnIdOu0-If{{TIZtJuEHcs?2g?1$@f*7E|- z69)q1%sgkD$R087=m8gcnQ_4v1$4XlyQgD9Hj^JnS*yJgc!v)Pdj3;3Ia0K#W1|XLqRFo@VpDukU+zOjWT5snznBjk;93=fQ8$_}XuC1v|R} z|Hc8&ogx3R?t<>?^zdDyhwPd0j`w?0;7PJJ`kQrm{qM|JM!wCww4*PX*XzG7gMRtB zj#t)kp0c+b^T3(#MyD7zURUFK z>ip?_U<&%2Cd2ErUUBw!dhA?}r}{1$Uxu&s!T$@qcSVn%kPiQn4<1I3RCQh8C09h|AambXAH?@WpeOk5Q#?bLh^{@o8QJVY=hfg#pU3#B?RyrzDd?0`ImZvcP_Ogz zyf*8*K;Q>C1wW%x9{i~I@!^-*?_JU3s6RD&?-c7yZA@)Aj2^(=ZBRXL*XkC-`}~Wn zTa4vq@S?1x#!I#yE~vj;+&U%b#hSeh z?`PXv>XM2|hlYBkNWZ)@L;W21?#l$lZ>c=*$aMKiw}-pB{1R7hq|2wbY#i$Hkxv<0 z*JbK>w_e(1>UxXoO*?w-lZM{gZwud#?764o=jpeJb8UWIKiV1R6W_8J|3d0Ui^TgQ z)OYf{=YpraoyuR4UYWPbm1nBxJK7&oeLN!ggN&24!gEkv1DrSE{cg?==eVxmoK02c zK5x9KR*&D?48H?6@uR87FK?+(S9Hr4Og&o6N9w6m%zNJFG;dRyYS<~UEL-R?TvK%0qfm3)a_Tfj;-T- z6ZqVEDd(QJ7T240{FKj5X}|5ah3`jn36w4l@6Do1^^a%LB~ZFl(Oajc3;r+k$#U+; zX56kp=HuGE3OKl~;2e;Xocla>oi3kih7L36lG~E!dzj1rjPu^CBjQ_uFcsFBRR3AW zPXyyrIp%NhpX&0K`@HJW_&b~l_RDwX;rHk}OGQ0LQ6$e9eU}3N)67T-Q2!qYr1Up`#Y@snSkDlp%sT;TzqYbp5hVMoXR>X)aAjJqk9 zd!WKNd%dq5&hs6WT!eo`IMu6mH+3OkM>kQGoNql zS3-Of4^jWB_lz%*JkE-TVm|K|+ZWBxaqim&ze6_X31G}&$DF$m$2Iq9xi+ug`N+ua zc|AASD);1l@HXf8wRmu@xN(R1UX-M66LX#Gk@A!V-39ikH_)ben-wWeB@|C7uUE+H1CY~2~9^-kA>%27w zzOMTa_yyJ77JgpBoz(b>@8L{NRatiohiINh@58)LoCkXGd7o!RLSy^iQM@-D8J?H2TUtHie#}J<^9VeK?06OD3i@{-r(ChYfOr-bPQ; zZ`?bsamf5N_a2`rn*F>;AG$v{jNHxt>Y5)+6^&kv^r8Ilu%BT3rXNnBeQNq}j`8b! zd$koHKYE#)~990w9aN!zk`8Ys`=@W-#*v( zftKC$d%rx)y5jEyJ+JvN^iu2x&3#^Ji2OPDZ{PYB8Df9Dfo_fZzNdHW6z8Af@rEyv zr&v$#Sg;eg8ppj>&mjfyef|50|DtkP|30Fa@5&Lkh2Ph__kUvNpqtBg5sUEEM&=2) z&sa?da=<@!)ANU2zN#Y2J-o%)TQXTzL+oj+C+Ah zbsQZxDao~K$=6`VWa~OTuZMj~Jp-R5=h@T+6DN}w(7MfJ2Xzt^_^-Y%?5x>m@_LD5 z!hT`zSb3)f9Ajg|hg`SrAYSBJ9PcvcGPm#R@_oje@g2;E0_Gvlyr&@InD1cX7q^c& zc45YN>JL@nkD5G2@oJO@t+mf}4$Q=v)C=hOfV|lk{piFp^j*6&J%!xh7p9MSW}oS! z6Wi2Jl!mL@ehhldZug!z4qa!o|HE+~ywBqEArrUaXM}NTM&neze|6dA@{G!7oNw;q zJetdGAN*WKO`hn)p9X&k?|ah+^n`e?x8LRchVK!=H{Y9H7V?XJKX6^9Yc$A%FYi+7 zDmlk@nphj@9e>XnzQ`4okK*qP&oO^pFGP8QjklRP$2k68*5%AUqVUa!zpBXJB9C~7 z`q8sE&!BqULLUH6eD3%Dmlfr##kt`6IiTulI)GM||+tmt6hGcmaE2Wt{N)bl$>a0rMBRFKV7A zyl-BJUzBgr?=LSr=JGo_de8jvee*o-t6FziTzITv@|EsG@XOiSZfkqkk36HJ^}24_ z4Zn9VAN;@{vHm#S@R`0}{pNA_inzDeukcuIzrpw5cbUFH=^xiK4`yBGNP+&bzZzdx z%ugIBlAXyyPx$JPg&rw2%Xb!ZB?91zzpL1jb-Irf8ShN^#;v#4?iaWw|J{^ammk&V z^Uw>dpM4F__weVU@0{EEz40pkHU9D*Q3OcJI9<}=8Ns}Qu_wkn4@mC=Z5?z ztJEbg&IekTFN^clZP430({6gI%>G8ta&Nl}T=SKmRZgszAM>D-+%9^Kt#+T&dzG)~ zxyyY;VL z8#(!{yi+V1dW8DFcJ9*~J{Ev}n*q@;6k6YVz@x5X?ONIEP@gf+&8a?aw%lM3bn2gX zDc>dL_4(*y;E(Aa&!0#*&N28>x^MTi4y|!s@?Fj`xPG(xBPt(VK7K%2zN&iHGy3+G z$MVV-?nl*r;Ez71>zi@?=5gEHM^|_8@w`FHJC55kukPPZoBr`Q5{(-)^#9HGk}d=# z0nW2jp4soq44eE;O^%va2WX4!aWnQfDB}MXx34-vKh7bVbHmrFy~&}klbQS|bdfgX zEdWnh@l?+>>eZH%(xXLAbn=}Zmw3J-bKho*{hVKOa>)VzuRZ;~Ew<)m(60e-@!hg# z&;yKT{K+1Duflt`Y~x&g6MBhtO0B}<(?cdIrkMbvM}(e7v1w`1PefBEPG&YE>bZm&KTP`|(U zw(?FJye~rDpcC=*rN`huk^9M8gNM|o$!E{jmzrPLQ^krKeW`hOl^F8T|W8$w^54<|lf8!DOw^!xBQ9muT^AaQ- z-FF}_v`+O}LN;FWW8@<7wd51~krN4ChTjBwQpArg*E#ZH!~qh1mp}jZW59#pIpKHt z9rIml>`rm|ij+L?ndA8R%CF14QjRMJKlJ-3S9Dm-n}JGtv-nwQ(t=OE?Fk!s)A%CC zc=5ckervo|fU~0f|6<|v^P$|#0q4^SCwzHII8VRs3FPlZ!x{UrXW~c0zp>s1KiGZX0hmaxxbk8u1X_+wKFmJz;?l@VQ&{!LK`I7y6V2PwQnG{d3#>>@82g zKl0nB-{%Fa8@#KZE_2~^&Ur7p{fRRDUi7@zzx##eRsJ*QM{9Wu?1HV|8G*iKg&+H; z{1W@2DdI%vpz&v*>)2kr=Lq&nOU$g%LJTYAH zeq|j0MfmEO*G*giSPAd0V>;jUqrdG5`!h@Kk-aqcELk7Mr)P!V^Nh!<`89EUrpNEc zc+BV3eiz~1jRl5Hc<)#LDY=2)naOj$!_;T-Uc&p}v7EyDBI~YF>#0M5Z&Z%?yJtxz zxsi1y62*It(xDnh3=>|FpoYW9xr zO%#C>d$)E%_1K89bG5j$6M4z;Jfimi1vf7gXU2Rx0KbRd4e^OPna8q{K>@lYyE3DB zt{N9XWr^aVX6thDJHWL_+9JVN54N5R|TB_%ztP|!R@&$9DN+e^f4%hm?l%lO3|1=0Kx&#Rlk zU+iDh{jq{qveW>wn&n$mT{XOhMgFhzA&JXmw56g_cw^DfE zSOt8%%yWu9a5ngB#P1InJK1TAez!QOei?e%RXjqMN;=Q}1@d$za_Vr6@cJ!_`kxZ~ zGDMu{(LR^|#`(&U>ccMSG4+RhzgoXr$oJ~5_pPMV{I@RrHxIbG@!P=5^9ZHZ5e^OD zw-xE{lTXn39v(6ASo-mTe+0P_`_sKz5Ae;i{oY+UenYdH-+uxAZ+GL@p+{Or=8x)q zQ*u0vKbI7Y|IyYB{-IxMw`ctBuD)VWvKc=)Zoa>fT>GU!^HS0ezgM`%{C-~K-_^%9z&03+{wTl=vtyEE4^Fk`$~?cL!#Bj$Y_ zhfj7?@b6}~uk6pK=Eh5`?`P>#|BsKUe9zF28qc0ezj7|-3&)gh5&nA?t}}WkeK6Q{ zqym3X7pMFIpNt;x1pe3of1oFNL;h%0{(w%_S@4I_Ik_IcpUc`$gnH11FAB8Bd@&H| z!LthC`L!kRg^ON$u)uj=jhjNgi0MS!`321bwT#K`BQALs z&ZFcd47`DGPUoy*;O7;dJKG#d|TiX;K_@!-$PaHztF?El(zo7Re&Y6La8a(5i zt0B+1a9ywyy0q#(rK9y~m$M(oxva!`$K>g{#nb!~>nuE4f)0t?7mgusl05j`QToOB zO0L}y!qMG;mtK{Z7QWLB94^DmftQ#*H9dLn3h>Q*mevaZcf$G7u@c-K#bbJ|bbpcY zPAk9C^TFezsV^Nt8d|(p%UVkUN1Or61(js?K^{$=HD3imj17~NzSb`X70gF735 zKlG{M&!Jwo*A4T}^O?s7FCAs*$^3ErcGkh%8iEesF732a*aiG|kNwe(Txm0M$Gxxq zJNLon9QRvCMC}OomCeX4&-2>@_P;uE{^lI^XGiIO90~h5+XL-~-|xd;QT~db!}uRZ z7(dhHdRj;7Yh3MtpD50*)ltQHxL96Nyce+UIR1|7o6kZI!OwBtP_~ZPzT#UGC$Vf*%V;k9^a*nVcHe`@2#a@#Qy?8yJ7cxCU`j~wbNch&{MHlj z`HT1Ge{}GPD)aoiVloMK-2enfn2-hP|O56ed0SAD)Oyf!5-&5u@iPQ8}qGwS|$^?S#1 z)D>x+mg2XSI0U{qw1D|-?CDwf={oMIbw4=jQSY)GIWJe);xYdsH`s6Cug_zCVSNv} z=DQjx_V3nabYBfT&6qc(@&=w#DI0$lx-`afkv@#~DQE28{Oz$yS_bA}hoSRea;vwm z$b7adCJyQkzxVU+hqwGs$5=;gT)R^z(Po|k)Mw_Ue8@jey5 zH}Q|hg#NX4duHFD<_|T}X#hGQw`aFJ?CI}6G^?LngzsZNxeq#xvEF%?nz;Dvg*o_% z_u0=e^-_)N?PI;`;G=n$ntkqC{5T)|>VluhPR_;y=PVrfE&C}^|E5bS|I6%SG~l7W zuKyT%#&nd}K0hqKIHLOFw_L~L+PDv$;=40DJ=Uk+p8;RwAKYHxWgO$5)$DX^R~q8x z+55AOv2*fp>A55DPm|_-RIb{(G6$;AF=Ls$tCyf|vI<{C`@EZ5xVKF`8T%p1H{t$n zypPh;*0n>wYe^mb_olZ|UwJo-$|rC*pI))40*6{mjr$i0eS*T#bKt9?>g4 zm(peQQBrF43LDp%IIm>^`WZNyl4Iyw#_J#-Q6}D5;Cbp7W)d04E2#gquDIQ6Ax?i< zj@o*ETd>`uj%=ap>F-zJ_=^}pKLRa*= zFsa3*>O%#y{^WE({H^fOk370rpRem z5&J00mkZcO;r-chx$RCf-nHo*{u}FFqeS7A#OPqSnxQVk8{9Nbmvf-nS zX&3l~{RLn35Bm#6+SgtsdyDKNEX;mc<)JF|7K?231pB-Ta%5#_%PQ0asH=&z_GTF|@9Q|^f2w*OYgYSf z`-ltl=``cj{5RsIQov$s`Sq=0^6PQ^SM+;Xeyb3Qe`xCp**iC3fi z&s=;F(~11g$aEfkSl2Hj(>qdLInRMTh)F z#E0>^V|lE_E%)BV_`Kgweg!@wzjD#Egb;I$VJn6M0uf_UFpTH6w%Lv%wzGLAk7Qu z`eQj-G?rVl1ABeWxXG_1RKK{YUjpXi_r#4}p-v>yE2%}U@$cu-E5dmRm1Fi%)=t~l zN3D~pDE#i4X(2A)2l1+T?lphn=)SzYcG_!}Z)skR`)}#*D)cbUzUJ%@SX_z!ljQ zxsd)gdCDE-{80yZbl=QlJ&y+Yquiysso$$mZ_|&yDAS+tdUu{Yaw2!_v;`fz^5_xP z+og4l*h{Jgr;A#Dg#7^@66xg{{1HBCd9hREEj4egdB%Tl-qKZkRT(G7=N$6Xvyl1= zn>ahFvml+=Yw%^cy;}Dv8%Ly+Z;@ALSKN8jW_?c1#NBZ{Mzj3%2DATF&u`wWeiHf3 zn||V<2WRCso#3S3bBXB~?~}kgVO@rO+jIc`&6VGLH^1L)_+SnG4)4Wv8S|*i!2W3- zPV?T5yX}@k@R!DkrY@rs`j=SO9QYvaFyA{D&he{#_7#udXBOYZ@J8e0JV^$?E~gkD zKk&|J8@g2D`i~cj55HjS(Omd=8hqrKUrvRO)8BUpI=)zZ)bbJMM)}?-&RsU_-F;N~ zLj@$ydTROJ<>)ECw|iRZ-i;OLpYZOUwy~E{zPIIL`wH8UA4#~MH}VwYaR+g6Rrzf^ zl;c=#V*hC{)GM-3@}rC=?`7Y^fzDaiD_Q7+s7}3ZpGqH^4j9jJ&;z`;(97#Nt6ue| z%Bpwm-=B8z=gtr9SA4ENq4y==Rk+Ywy~Fa+qrUEIOq8})7$+egou-|B)!m}&vp+nY zZ;{bv^oR`~TG$EU_gq(&1N~k@b`|w?IpWNs?g|>qlaLJJNfJO?Ji~P;QHhy;Gmp3UN z`1l9v$2y7!?3Lm@GeI5}e_{lGBWRW<@J|EmeADp!(V&c6CNC|I=BZP6<|hI-Ez5?U zxnKRUrsQqq(SUI-$`ME5$JqB!SDlvSL&27#Li@sMejE6b3o0g0ogArnTIVu!!Bb&e za3OI4^CVZ(?vww}c3!tHBp%2?Ka2Jfc1YU`+D<%xK2NW%uwMMZ3y33_mvO^5B6^Pe z7N=bXTIj%s@Le>26Z5P8o*b!qdy1SVzUbL7-hT~n@P6jPDtQR(>qU&~X*^O5_orV2 zJghTm(GNau)_%NizXo{n_>UvN1Dtcg6MvUGk*IE)b~#T*ow52YPf*8T^ifoosQcr7 z1$ye?CJzwJ+;9#G0Pi1Di))B!Uy6m9B>d^A9hEa83lK;QS_ zKTGAXO8W}(<<%B>K+iRKnrAs*_F|9Y`uddS;Y;|{Tp#jj@AO<-pbzKg!g|5t!_yV& z5e9aIdB+Ur7^=XT@E)FK{iy|)dp`J&zoQlZp75#X@pE>CICo%&@#m?hrJi`kdbJ** z1i#hl5vae)Lx0Ed_6YK!^#ua{JLQ)CeB$3wM^O3fbP@TE^aWRcXC8dj;>gR1Bf(3Q zkCypbr^WMH{YLa%CW!mnYM<(Qk$X1*p9J_J=!-~y zH1bLRJopH?C69mav}^Q_(ZBq@fQdu+UDIAYPgmO~{K$EUst0&Aza&*U3P0BO2^;L` z9CqGzTOU2-K>u0$b<4f|Hgu_d-$%$d^ZhTkXZIlo{%F{*o70ZZIqx^WcnH1p;^+O* z7Y9hI(?9Z;$8KDja!}hmPV=>nj>Z z#&D4*_^WC9r?wX!KgzUxh7ms#ID+-mLox2~{KVr$=1aJbPgjXEsB_weo|c#UVg2Jd z9&tYRQJyU+j~Ts{Id32GL|$lVq_=F(*o92*SlHf&oE4~J(%+r7m?y?lY*+gfUyK{k zub!{*9-A(Jx0+l%7RuFm`@;IirIB1kK~QBr+2TEEIr4Ae}ulp zKl)3}=frYU-*5E}O!J=I7wxOYacJx>H^3>Web`&%NBu+o?m18QRY6}O_xQA3=MSmj zt)U*w_RaaZTHfb8%?IMQoa>Rt0RCR`<7Mdapl9lS(u3p9+V$wYNUzlWuH0X#eE^I= zG$e^+f(!>y!fWndBdWVp_hVSNO(3QSOGH<7;Y1^@m4Y z{vscTP;6xp5|xBm-MkN4}0Gm z=V!uo$+=_h+S@c=TmF&qXS^@>%I?R1bX4HqSTCl0_!~IR#eY)yjQJ<>kDtGgJOT66 z_gm#j#mm6rz|(kTF!>n!t;*-XU1ohwiF^WfdF|Km6BsV4&#S?`T=y&Bm$~3x3f#|X z9wzrg^+#j4&t4p!f8uxEj;g;~i;u^^rwjbA7`{RFHJSZM-KXqr*l)e>RqVH7zr?zw zSIs`uvhoI}q315FtvKHU0!u|z}8^Jpp z4<*^_LNDv<$eEUX=D(}?x<)+wN7FN=W6X~+zoi}yesom%?rd?qJaWEv1N*`F5&HeU zfMsc%Q=(pptJ!z$<9AT1hA&F``;&EfE&q-31^yO(rqWlwqIts_UK;kHTcp?9FRZ)a zylm=W=kJfACq(ySk;i7;k7blo@5cszr}6Nq_G3l;P2?x8)8!mJ^3Hu`$ix>h-6TFo z71=#s`+2|-`Kh)2+35MVyF&fbqUS;t?yS`mAP17QsGo#i3#TUzxZo?fF24=@@}S_m ztTR#lndW`u4E$M(eOtvJ?@33PFRs;@MET*GUR{V@4d|D;mihtqUlzj874D;b$8?5z z$}v5M1pii8-+^bP!ao^Q^*HFpntC81xdZR($8MY!)>-$&zj7{P1W&Ut&# zFa2g;P}mnF&IJC9*ivEMX8nF|nQ@HYioC{jO~@I?u^%m&P;SX{{gcV#XYxj06&GPY z6|ajL^j}|SKNFjC<(=3g`=-l&aR~iBJ1#B%V!EPr5)F00i?E{w;EC)g7$qJ~YMj|L z=%-m`^;z8yj_HxuK)eaw+o{(Ms+>dDe4fL)i6;+K*-x|XdhRIpUiZraKUu4fZPWcT z;973UzaC}%$ny!a@7f#glcn)1w%OPR8+{T0Pt@L&JjnUOW{IC?@h|jubCy|`B)$v( zB<&!qPhNg7jQ`HJk^>%e?h68~PaaxMJdoo(CkW%e^Yh68^qFOz^PWEUW*cu(K5Q?HOZ#%kffDh=0{k4-*RFm}0N(ow$pP#L^4xM9c~-c$A>X~r5Au62 zyw~Od&Jy1RQ1$P(tOP?FK`*a@iuzSFlDBlWtZIKu}#qy9;zUFzIufyk57I=GryS{H6BnK5= z4)254w2lW~+l&09f3YE1*j3T}B6r?#4}W7r1-U}6 z{Tua1i^lcvi~g?W{!+74G*7@fS`*&W)1|t;O0MmLufWd`aeRfmMqG!{hF@a=Unl*! z@_Q5G<~yXZevj(z(w9@lgKU+XPWah zsZ3Wg08VMMGNU=pWxPiB;|DogUl z4qSXzDbRiI*e=|k9LC>bypaJhzel^8n(BaYHE)O9$}$qfdB#gPeaEZ(UQz}-ha7QU z2>ZvrO?3X+(mW`5ZL|6P6R3s$?>i2ixktaU|IyvX_tG&x39tXS(z*M0MEUuC-AABb zM)8%$F7jp9Y7rO|4~$d8U+gc>!Yg*&hfl_y!r#~W1l#a4@r3BUYkD>H5>}Ipz8ZW3 zPnT5I9nY)3!g?+EZtI&8O2;iUYue)>5{*`V*sjQ2B&AN1-j-uK7@>if2?gZEk2 zefqwq`ZF5e;(fG5>ti}Te{`QS$NLWXrGWcHaOH965`Wil);c5mn%K;D5Iynm2dW?D~kM$8Gh~8th`b>JR3L@;0pOWV^T`zfA2>}RPxEMpHfA7JsC+QSO=aD{jNci{`xz2Z3ZlMbK!D{QI1cM+gp@N-m;#O<*? zjGt#!A2`^<6_3B_y9Ml6wqWeVjCu`zx&!{`gpZ-~kk)Iss_)}^jl8ilmU#}G`n)pp zxohlAoBCT-?7rsLT%9LA?}I(`(G%o3A93NoHojxWJa#+wu&DI+E;?S(yz_eGkNp5W zzgXt|Y!UmA*56?Z?e?H$>~6+d(R#|r{%bqu?z9~_skO_nwVmi zZd<`TR!Y93d{V&wkL!q{x^I5}$SYNlZ-vJdeQ)#t^pxoNe->S#qsfcTIFDuMDf}*P zDFE&^=-`uQ%-Es-)9x9%Cg;M-to2t|KmDWjjN(NUFW7zbUvenKW4#@_>ZInD>qx#* z^IYg1%B|LqNJ8Fpyo{XG{DIZ77y9&So*KTWop+1uNrHMDlOIw)&!t}~OFkO?7yX`h zru#!rY1|R-56!mcK~BHxQM2a_`N#W{=yBwrHQ`=)ysC8|xwjm5*_ZErx3?R4i1irx zsNv%-_FV3{P3z8T_N-yNS?%YAaY>_{uf;uW#64xcTF^4gd2W?U?7ZSBw(lca-_CrI zKIQke)*Wa4_g_%K{%L))J$xKJfZybe`z7f;q>QD8Bu8m2o>t z{B9%kU3Ec&n6)aU}YA8MnFA@2r-wo6NpMFUe6*bAtZLC-xR| zTdNZLe+l{s^KI(5)-3`*HK%o%A}&eIbpm@b)JGa(tF+x<_HC5J zBf(DqZ{TMpZgdcSGxs9lcSxmkU41@g)0}MJe_3_EmZyoHz@AP>{Vf-J!OFbnXom5e zpVe`TcS}8g4?VaCJp?|(d+Y-+uJ%V&5jpkMH!=PS@~9&p=r!sgCGjc5FImH$$Z4;5 zRPlaqQTv4l@A-YJ;xO-!Zq2$$sHYvV!&F+@X;fRKUHE}YJ)*~H`~#-FrnKW0otPSY ziuQckw~P8a=C36FXHdRpT`R@+@Cjo_o9~gAuE2Y6LcW*!Rz={(`yu?%lZgA3edNmj zcNG3s#ZOM}s~Nurbdo<>M$hd-o@bzA`K`!$c+8PF(k8Kg8RrWtfCtZwz57o1{BQ+- z{es&(t#>cD&E6w;68+8>I~qSezv@!_7G?VHC^BB?ppE&Z!E?XF(V+)g?yX1lIxIYK zw9LG(`~&6_SIK_a7Zg9X^Zui}7fY9rTi{RjwTpmjWhkGh)3ZBIKV2pDU>bWayw5(s z2ZRqL7nJ;`O8CK7@O>ts-l_M+@qe7I8abR4{FG#VnGXtIY!bOy zLT*ZYWw}AUb2WMu@JQT1enDC69`(VadG?QQV4UT-gUs zuBkXrX7Hn|EIE7f@W*wh$48t)e8g^_?cyt-7w}=Pbe%5d2fXe$%6<5!FLlZ-85j69 z{aKc}6_8(O(w&ORB;D!Mro@sfaGr{W5RH z5uS4#Tnhlp%uChym07o8Jh?L@^32*YUJ$yG%&YKVKw^*gSwZ5Ke?3R6P=;eNqH%i@-JVpDjy&rY&QQ$DMpY%tiPFN;( zaob}#=4aZk!C#BSx3E5|>)6f6IoXB}x3oX$>hqOCI%EBA)o_f~se1S*e6k8>?*W;g zp(C{fya(&c75`=OqP+8@5_(e3o)U0f_bH|GFcx|`4+C`gyA}LmK^{MkBAy$1;FD+Vb~>2f@Eu0=>BKXG1UHbNfwY`vC_&9>xVXTh8vI75JAqe>S||Vr6$7^`VcD zUQBzn@~O(F%3F?>X}5+?Rp(Rq??>r3A$;7E-vL+ZB_&(z8oZnyw*i^^yItB9J5BJ? z60GwyGb=mL-e*X_30ALbuvpLjJUzPPdeYLw^PC#!tRoo#tOM^b+a8wRHoU75;zd zERG)RFiBHaCe(wQ+tGt>uCHGjy%PQ6z)_EQq8hzd4FCt$gR-(u94&(1D8B!r_>F)^ zN0~Spx)r_GrG7%Mhh7f6mgIpKa$fR2gx--rzadIjf{2X^dA?DI5vF-uCm z#EEgALx;`nC+@WC`;BYu zxoZ7j^|hl#;#-6tI8bXHeh}5sHu^xf@N>Y`E%HmL8Fi9o)B`S#e$!+9{U28kSRFa) zGViD!aB$stKKq3^ssGEhN=&N<99%a>^?=hyj(WiV+*LL8fP?qA|El$X4P8aQVLf1# z%IUa-H-vs@FY-HMPualn2VcDVW!Aamul}IOeu(&Q^2GhOkhf|>mpGiIzOs2ftscek zZ)U)oAJrfHmdu~}gOmT1!@igi=WgT2;r*7dUlX?z`itP>VVrwz>L~I6eJ`xzVJnyQ z5cvg;eGokxetX6`9wSG;#=K(UKahEte(U&c#GcUg`+EPvsuXB`Tfg?Vzd5z-pM!Z4 zpDyb=UNet6?NPt)rLRHHGvnGsUd~(})bIPBUt?X?#CU#_xBT;K>vz+M+4?o{ zbY{Jq`uXCqsZ`=>V?S{M`Gk5`s=Z;j1l^vKp)MNwMQH(>bfue=%`P8 z+KhD{y!VT)`-Vl>RTa)(vGN}r8zEk!rY`uqwin*GqpZ|-7Ws`QcuHK_zl*=6`m25_ z`Yry54~}gnF3|_?;IBKi{)44W$Q5bd6}`$iCHr6>k@^A-__owdW1EnFW?wjrD=~f` zl`Q*uA1;iuH+E^N#bqBEe$)s5fftx~R^me)(?Qw z#m!QG5585K$1mf`vh1t;u*+jz*XHr7Rqt0G?GxE|v()cZs}BeMhZV(sT|XrC9{36H zQ6JF#tN35yhs16bI5I!{UCWM@f!piQ`(6BpiKqEq{8`k`D_PMw6x*#<{G#yLbx-K^ zWiKvjJ-ux!MFySTr-xvax4XWVBbr;3at^jmaZu_rC~Nv|RPvqHOTkRwIm zC)bAYhJk;;w6kQr72BriGe7TGg>hYdvOE;Dr{k5ZE1SrR0**HRmjcbKk@HKFYQuK& zrSjU^@qEsm z%Hr=++vdHbpi}#4_t7HzhU%2_d0+4yz@cS(k@2t}V7C@OlLnvCj?4U3+gw-UiUdx3 za{`C#>yH)reyw$tn_=B8IHmSi*q;f%Gwlj|cYwc^IP(BL)FWMR%$9NA65ulhy#SBa zR_MvYKZ2bu@f0cIQuaWf2EVDxTi2^wu}8L7@Kt)6r+Hc?iKN@%t{P6$A?QY`^<`rG{x{Y@__{GBSoMgc- zR+vX$8G6J|=Mv{!iK}zs+!s3OgI+T-&VXJ``CUUj`ok)>q^g`1PcS?_#_?=x6X{qo2h^k7FDO(f3NUw}Nxppu1){ zkB#rn5jgwwCv+z3+foaUrQ-^DaMccv;i;YY@f+c*p6_Lao_Rl`R9UWh+AQ-;({8q}F|Lw~D;Q_pafNU?Q~UT4mLCJ|wf)qiucayPvcq}uu~sO5 zZz-l4?dx4H+o0gnT8^3XgLcR@bZ_!??$pmMW%6o1EZ4qLe0-AC2_0&<|Yp#6P~Jq2I(Aw1d7 zXMNdyH|x49#{WpX-}+-he|@3+4dZeWnOm+<8>{nC9q$k7xc5Jz>rkqJ&jr_+uLRdC z4hPq(UJ8C!|0uYxk{w=|amFvu=aEt9GWc!fd`|8YZ$y0|{`Fj~{q^zHW%h?zPpeAs z1ID$g&@Ssj4e-1IyjK_0e#Lc9QO8elfC2Yuesx9dm-l(D_n$66?}CpJ-*ct#X|q)#IbZTD? zJi)(#r;~)waBcLGrS1M(57R#MOnn@Fx96^Lp_7K#3G|tmDqOC7Px#Ba)B91#$D_o&37#?^&zWt=LM=S9L{SsyB~%@QUhw#DQBL_=I`s zDh)nL*v*%<$A?RR@3PbmzYIQCDe4S>C*gNKcr@oo^l%^f%>KZvbqI{!YFWj%9fO~k zy2R#}c34kZzezukWgLP>){DWTkq?GGmZzS*?r@oLY}=#vi^$Jv7hkxB+hdBS6 zt#=&GqlY#3+Ye-guF6_I)Z%`RHv$_$T{n z>ccm9ImVgE>-;d);cL6UYRA6sj}A-!cDYOTLl(+B`RWq+^?_ex$Gh)7rm)}Cv+sII zp$GlKcD(m{$6W9g+3^|t!g}8>*x!HV<5mT@oY{__d;QmeV}sc7f{!!U@pbKGqbJVr zHE&!F%3DrSmfj8`0Yt-o4i-k&}ilS6_&p?7{EMzNYa@hx?sI zk0C!&>$AuSt*@E)y=cEQr}dVyT<52?S0n$UdWvq!_I%*Et=-mjWnW{x*@kA$69nJM zX3p_~Kf2Oyh4wBC#^KBL^m)~cBU)Ex9B1mkNA~lfcPsziV;=CXseik{RVhD{PYJ&W z^yJQkX?J-!Jd*KYtkboI9U$bv@*q<$qA@n`Ir(e*SQt{SBE<4!b7w z8`T|#Ye!uw1^v+WCoVwdzpH&a1X(#;%_DB-_Ug~8M$0h9*@wbNcxTQ|O z=RM#a_D8*?vYcztagm!i!ML+}ze((Z^4-V4t6FJ0FBjtq3p`eF8&yg4wp{(^6?qQ7 zsrP+a+V@2tn!WvuJWtQ^-2ZJ&FX@#w--}&Z?|Yu7>p#!S_l}U^?B5sUIqRZ!-YYJG zUKRZ5BIK(p>+%Ko7Vll8^uEF?-RPIBGxL07=dJ2K=zXKTL*1)npBp)tAzn~@*L^%! z%>yxU2KMDjy~kl6SL`OAyc5g)>@n5{-{tkbz2!V`tVq9?JLv7~ub{W-JQ?E50=*SK zPfp?u)At{P-jf|Ay-$bze!r{()4vMy0FwiG*K>t#zw1bRR#cBH%=?D}#9#KI&nq(I zZ!)j=w_J&rY`By-J!YXkQqt#fG)n$vKg~$oWIh3eu6Oq^&a|>MA0fU*=LaTM<;brP zf1i3>#*R#;_^`qTx@}ZVqJ%Er3OAx zySCRZ`Ka~VE$+F?22WADd$Q}Eo7tXPDRcomRtTJla|nN%)Q6GNReUrFKEP9x&=0=` zPQ-(J;u!Q`%e?s>e^5r}F<9VB;J;e@h=LF2Z;qvT9>OgRq$IB`rM~4z{gG&1wfpdw z2K(>^UP|EQ&!nSTIMvR}&{az20rpd?D?xmG&3M&nm;8F-+d_Iu$v&$>{t>Uz13#?d z_X*Ys^j$mN@O+L`{Au?o1^gE?Ug%7Hq)0w?Tp7Br9j}3d8K=R6i6>$G>39MBZy!Cz zcvPq#0N2kS%fhD(pI7kt0`bj;&o2tniT}+Rr>6eaW+wBXU&%mzwVy z77}k!soM3wDnErU_A~Psmf!L$eu|W%{THe|+u^zRziZ-6l*F6(YFgaB*wvEv0^K{n zRlUJ2W|VSdACvpaw;B@ajLOWiQ+@y0uI*l&rB-JZ}-xc?F9N8tGZ z=<{83@gIYCWvQ=-9KnD5<(JCU`Ivb8YMw$i-bX*NE#%9Tv^^Q*F}J7{T}9FFWSuu? zKfqlc`6jvBpF8Zt_+9(8!#?dsdMa>pxU8|G`kJw?bDZD7dD%YHNrSW6&&EzRzqR(a zxo>{)r;Q#f1HT0H;Im)2z3`5^%ILjY%T`~G>4*4#OyZ3S@Ok2sx-&A~aK9qN%aSHr z?^krDN-rLEcr5x^p7-XX59HBf=b~3a50>SQ9;4lM!E*(=KLefxPx`zFD?56uNPAI! zLQp3rg`Oz>=jr&}A@d2_or$L$cxqH{zH#l*!|8-7wUn7R?HYL3*r9Hc_Omh{(OYER zq26Nl&Cbo_hDw&y{qemDbW&622esQ5eczLO8yEgL2mRQA547Va0RN`l>iS6p^%3Lz zW_T|pzs#>y?nAF>exWDT#;?tI+T~Z|tK4UJcKF*9-tU)R-W!nne3#)@+F8M`w7W`v z>1Vav7kt2%Y|%f%{q|#Du(ZD|#4~!0*5jNcdU1vCF90sUu}Z((&(Y2Ww38uEu|?`i zFut9kz5G}TJDKayPVR4Z;Kz)oa5Hu?exzpjb18EmG*=;MMTeJ=mknOFecgnFYkL{m}+>pAUY*_TZD>JC*@YivoOk zGR_j?ly)+}134&mlgU>x?IwF}S)uj-rvdg)p<~s5zY>0G>IEd!EgL;w^ilM>48LK$ z0BccJ=LeMh_)t%hcrN%%4V>9$`LXP$srVxr&h0Y(Z2flX z;mg3eL*q&8+0*^-3Gu@VzI%5D`0f*YSLNHBkQ* zaZuCr#VW8bp=~{4D54t{1Z9+6SPe3SBjcf5MwSE>F+H z*ptbDV147C=$wLHiCb28@xJj-G+la)lJhPkzro9h-Hd+%`klo;F))Sx(JcOnEbH^iZ#?dtlk+S|c8kK)WP^@w{X-%#LEp?`r3^jQm+w1xxz z2Z2vU{Coj?qISdc3G268Kt3|K&_9t7f6xiwQPZBWA&^G~c4KG7up2@Pjw*;Em_3E^h!mL~B}l&1S90(haA z1%BJmKVjfSe%_wDa?|G((9xOZW#$q2S;Rl#FpsK#LXTJWkA=PsJvE7cBCq`unI6`K z;qOshwT_zchW?2r@lQa{YO&x~^pwCqVd%bgyaoOTa2!pJ{?-n7%x{)raN*Nwcd^K0KY=p4z!)N=Xt z8K<%5!u_Wuzme1NPu7Jh|8P;_nMzkou^yE3cI_X>K3Fpqd8@m8`C+knn zld%#a`)usT=(w@p!0s;qf6Kp0_%oW?Rp0TMPdKjF z)>301>u9Fkf&K5XKDK1ZGeG}7e`8SB^#bgFuNn^^c9NX$tEBF5h2Lq{;s;gk+t9C- zdgZ)$?Dm}KUFyF~mC?Jlmg$%LzO#f=HSR0@)~PglQxx}g3;I=64-vQ-_(nhdRR>&SH z!9Onq&t+b_5IGLrxW9oN<^XPs_8t0>`N{J$(809%T{p!z&vt&u%NsP^hV5r1ua4Gx; z`zpNa(YtbPCQb)>bZ*spsB(6MzdOVGdxAI~=Sl8EKhATy?yz#kf_*jT1iy^W`H9Y> zQcf!H?>X&3ypq$;FYC@(#eG@d*K|lefpRu>==iP>PPO(LdabYh8pgi9K;o4o4p3>m z`nA((_J*kf<9y9@df!7w;NL_P<7aAwUI!mK0-dTbFXc_`&)#~Z$o%Fx_zl>nn~$HS zEcR9q|8Aen9#{`5oQ=YYNId~R7U zt>{zC+wkcQ?Cs~+ca-NY-*wS5w0S)|cgmKyqBQYdvDWUrg*bVVGEUrE;qMuri@%faJ;AFD zT#bJv#KSAXzjE{^=ff%BQs;cQ2>u3twZG|#j`P8<`prAaqOaTJu~hx6gCCi)#GX-m zpbzlb)$zWM9TE73^c(rj_HQJ9iTm@ixgm$TITtw4G5Wv-&@*&jZ++%veZn8@3j({h z_Pw}1x6D%2_nvdQTO7w_7<+EGvG3_p1FF9 zpv#LSo}j8fsIdQ6mJ}VSPlLUq_k)z>Z=EXYI#Bm(dHE6BxeGYP25hw#`i=LX-}>TL z^S4d09vY<%L=m`K&h1kL!Aptn;3M1lu0p$ZP)CyIcT5%ZwJ-a_uUwGF@5Xv)3-U!c zXXP(N{>1K-@3?>JL)w49d#;Y#3g45u0#hzWeAP6DmM|?4#@Ps!rD#%2_IA z%Xk~qz<__pky1h}8d!hl5!d2++dW4rmRi>C-XngQCFi-$y}*Bt=vzhbV`c9VyAXM< z<61c%QRjc)xB06n8@}AlHS-|f_`_51EBtBqOeyB2Zc(C#MAvbybNEB$d!_wV9}#(3 z`@B`2XV_=4oV%x>!{~WRzSr={e98ge%>Prsow^q8KIT;&hZ>p!FXp=#dhJtr;#6du zC0&=|9+3y;xh2nwGCzKO{4ktrBYI1s13Y-l!*cJRg3b~h+-E%-JS7DF+;6f9_llhu zyB|C;-h|+(Ap9u6lX)*?x%UbE@Z6O+ibQOqU&vJHN}ZQ=hO*$P4LsRm?>Zk7zgR~6 zZyw-0lit#Bvn%zmvhAwD2mY}un_7p3|C{d&|Il$%(8+~49p4q{2O)k9f0R1t5{G2o zv)fWFeu+A5=cl#|gJ<;6^aDAqkJ=AFU*Mx%_NC!NADK;EA24>$Tl)lYj(whO%2 zfKc|&&((fL#%mQG(d#eNC)LBq&kFm6?b%NqajN~XexI0fSm$3)ZW*qC=Z~kJ*`|a( z-AASz+6lkwYWE*L0^Xzd5A!~BXQwBgcrk-McZlmU{>OCUkr!Q|>#*IgaG&)bUC)bc z8BVi|!+wcFT-|_4Aap%Q+q)JO1XyF3E)+_6FMG9 z-}4!-)|m+k4=L4FZ% z>^_}u+VZ^th=A+rbKaD;TmNkxA>{7TxZ>V zHhe1@hx_{I84)`&7qOP}lK^sZtfM#y_j%J)d?o-0H{URpb8p_5M!3ybs^7 z*3BNjSA9RF<>i}hT>Jeaz~S8gF8*=Wm6iRX(1V=cr{m1`2;Ih^+uYxaJ!Q!{0?yEf ze`iJbOW_Ms9_#Ccq~*J;`|$m)cIT-h8ChT9^KbB6@!o4*S7}w2?@D}MK%YwA`Gptr z3F!RlFTCha>;GAvr}3w!W0s!-AL07PuSb0t(XTH)aYQw!EloE3H>tLsW9#!L;@^1j znHQmV_~8*PSHka%pCs#q)3RdUbQSxiLWjXP;)BmU^CI*T z|7P;Ui+)nQ@kZ;L!Vju^!~fD$rBU{?KfS}I49JbvSB^k;u>tCUW~Dxq_vI&UsP_<0Xb6}W%ul{wnp6M4lrnylP`sSM}2QLphS7r#(9`n*p+9SZ#k`PnLROUuFM zwV$Jv`#$4DKazU!ychOgpnp9+{Kdr8g#D7o`qe3)bM5;oW2ffAe56k}8iW`RyA1Mi4WN8Qf6T-!e z*R-cnS#5W7KG8-U2Rxs4_|CF2C#K5qH+7Si!zxa`P6a-oI`n%+e_O5f3EneyiLviO zIT-EVg?=mhb-5ruJbd4a?3zH1m*qM?t-Wx4n)MBJHh^xW++Q+2{9NL&OVm9&m-uks zB0ijck=I7Q@#Px$NAs!~hZ#>ajx)uFw+H@J;=})^_UqJ(53dkvXy8(>AJwr6 zyNdQ&bN)Yop8oa~|8hk5!_V0#WnC}%jf{J*E5Cui7QG999&vB*P4Q>;o|~!M=Ok5e zj-NbHqMe#~Fuw20dQ|P{;@_~2tJmbKrkTct$WQo$vRAvGFAE+|Z$AaU`HTxbFI2_P z*tj=aDH2E_@_s5 z$i<(1$h{Xn`aL;M*B3n~{i7+qi$6{LF>qd%yZy&U%D@RdMf=$-|EFSaRQZwn$i2_*$Z>uC#^O$!akesUdCyWmn*z>nY;)$7 z)*?@$_2bMN+Xvpl_moxox#)dr;J*a+x{+TDD~OZ!e?G;0n1@qLH>gY7_=3h`Y4|Mg zLN2PYO(HK_9m!{kt?n%Ym$c9m?OSe(^b>cL z)|2Asg_3WcX~C`(dZ`niX5c~oh4Wy6{r!20`cL4|ydTPQ zi*ZEygr6Sk6#kH#J2ryfr$(PJ?V5Hj75W?mzS3S+;?tqeLD-7XH^Oz!ysjTx3LHau z>n0uiq6}+3a?fMjat&3f`DOg4Qcog?M>G5z`rIUZTJ7n#y)y4Vw#t@z4k~rCt>fZa zZ?!!IeP!Nli$63j{>2=6Q%$~+C;hn7`mN!!h99aT{h-&V{q&PXzX{u!(cb|5m9QVf z{+8ajYe5NkMtm@g$BT6hcwQDiZ)~-tJjTD-KbLk z*gl=F>O7E*sf*=4dKc9_4@>dLw>`PRQ^ zUc4`H=7nm!IrQJ5>HkUgn^>phC1VFSNM17bQ-k`7IZ?1Pk`r=Kwn@MGv{<&C@6mXO~ub?OGa&&fj2 z^~2))X1PC4_J5#WgRgsXVsOiKA(G@$_*CL1J}*&x2&Gm!@BV${w59m!G}#A z^t^0&2>OWhdqsUR1-#=mdjI*%v&6V+=|J*5SvMQzoqj&J5_)5Hk$kKDF1(&eKYW*E zJVq{7>F2Fu7X8l$ZyDtHeCQ_+ze__u1@ws-^g}!Dv~~>r%!huU&-i@y%RHWk-_M|* z#Oq_S?_ZrqAeY@U$fpQCPi{mmvJRfU26+vAq{I(Jy%j6JW^6-4-Sz0y@=pV|2oBE1 zu|eo!Kl~GXsv17(NuIDG?@;(D>!==Is`69(ui!P}r!{s;b^f8AV&Zj0zky#x^F^K( z>CfQJPT}A8#lN!ecS}n}4&&$d@%K0P>v{NF7ofdcWph$sJ`C4hrh8)&H1r)>ju>HXW&MCzdw3zP^Q=F?ai=1`tv#J;dK4^Qs3_npF`iQ?H9i* z=P$uOsk0#GI;hpX_@}6%DDtWToupPOsl(OT`o2Fd4O8b`?iYctdQVVCB>sVRIcMmV z`RJW#&J&-@Rzx0n^z&Vo_gY)2-@<(R@dr83^#J~$Jn>y(FXZ5JRyIF2m%5#%?tL=D zel_pSfo_V7$Iy+ja}7KU-GuKMx~WGmugLeTCp9PSylm5KEBrJUhfklH^Kwq?*yU<} zn)su0GeI7EnAdW#_-6~q=Q;2}N9f(wa+p6foiPvmgJNbDHjj;oe(`+rD@*8SiR*RVH|Mo-ek|`j#5ySe=P3=rsVmyv_m`!U^tW>ddI)}X(Ien%#9Qn97Uq@tl(gf- zil55xp7W>fzA}1>_-oSQXZMH3hUNL&)T0^k|9IO4544lno1vfW3VlKQ$AbDOZyShJ zZ0JJdJ@nM5-sXz^*cjWP>mPDoJz4}WR(Z$RN#Q$2?#g;IfWCV%&i%$5Cd>JL+fjP;s~-R4PLQsYA6 zjUD=B*JupB9Q9*+dVNQE*S+L(r|B>Lko#1QcY1FlQpLnS$9jrz|ndi4cG=V6=ufUvG!^A$dI81bs>y3oQ` zgFGu!2hNh`&=u!{{`GSfel^k0pd*uK%6R{JY%}t><{Y$EsSjNN4mEZAsBd)d*ixxG z_}zrAYZpEzUs>m$64&882^J9yfjwPQSASuf`$*{|{hhxt|FIl#3R_FbzASz>u?x%W z=SX~MzCj%v;CvM)t`4qlX9tG*=>zizW&f`^_GD?$W*>}m)_kaUY1@iVlz?kY4@-P5ik=eC*W_>~_S8^Jz} z?LjXGEMfn|ySqh~b_Xi%OVeMroT0e!$FKJsle~4hj<0;I>2dl#gV)Udky39 zC60veXs=biQ;cT~_i~+B;k&z`%ht<^oHHZv@H9LU8G&C+y-na$W?yXy zsYexgpZm05g{!)>ClCMHT6$++5q`Fe{_@~i;0QdbaP)5Kg&y#G|DEv39ZPWJf*-Y{ zto>q!-px8O>##PdGZ zA@pOn#UB@YxJl@hb=V|vwBSRz_h^0hm5VuV9z0moPZ+~bpV(T4zV-h9X?&r175G;T zsusTW;3W5VSFlS3-esZ7)8XAL@Gi>z0N%~1{_%dXk^W$ZG~ zm3q0&9n3E$aQ7aSe$6>J&8$~BH>0~P^Oe#Nc(q^9d{}i9kSkpG7qy;j@LlD*6=y%| zMy)QX&!^!xmzJp~!uzJ)aL9MfxyY70&(ZviO<#KM_^jtMd`bLswR~5Z^J`bKU*!QW z*0I$LWPNSroaaJ9t!OKM zwKRgA5uWdSj+}3mryi{6AH{@vLC*cME%@yF4wUwx7Rh;*Y53AA&SL_Pt#Y1aIw5@a z`O=8?lOG&IziAOZon?LX7WBDeEj=alQ{*YxXgLT(6)X@X##%FmJn$@iDHJ6^yTd7W5j&*Yi5~I`W~) z*Zr39LHKFJ*X^e9J1UGlSnkT)kt3)LF02<84w8vJBt8Tyfqdc{XkP|55ha zILDInOEuonli7W+`M%VkURZ_RoS|;SD)%2n4kr|OgjtqRR98~Y=Meu!Ify5!Sug5x z_-Yn9F?@IDPn50)7rxgj=YSO&)r+gp16bGUiehfi<@d6(mg6nt&xwDiMb6KxaDFD^ z8P3z*Wu?+!8vL#XKYU*uPl%s2jK^-^KKSvG+pEd}9bFE7GL2*j$#dkLJTFau4xS3t zc5MwW3wS|48P?4TzT>x5z5~D2c3n+>GvOoWg3wPme(LAqM@+CU>AqANq#yN=`*@!5 z3!RjOPO`B+q3iH|i`=gS^wXzA?|BG)9y$)`t4W?a@?6fX)_IN%G*${efUmiK@0b$*tr>T#%olvym;154jHOn#`9CTRS?tTEe^6Qr+%GL@yfh6I zT#tFF9_pnQkvF~29e8f)DY{R2(EUJ}{52h?_pf7{;Gd zUB#rjZk37;yD|^EVf-Zht;pKq@4s$9;uEn~`X5lT|A2m<_mC!*<$Ql^gQe~a2!F{9G7}o?6hcH zeT)mZvd{Rk?6W3?e>lj;KE~xFR5Y#`c>U$Z^~Sb>H8L!GIl!C2bBo~Fhi)!+Vtw%8 z#0u7t&{uR{&Zj{SIs=}QeP!p#G-BNq)g*eW(B&FWpYLnzC-}A2%bPD9 z3-p~{R3j3|DztizuZ+#j%sr`;| z-gj3erh2nqK6eB;+Lvu?A34tUT_5_c&~+c{6gWofROkizFnqJB@4AWcVP1>$-KW)l zg}hq)q?T7|3HolCbrZE0+G)$tbFsii~Z0f;|%m6=EW)2`$qeq1OnK%dX{y6^vdhHiELcdynIrxmAP*`hw4cU)7UUIzF`r ze^Ei?pxK`W|2eMvaypNpUDhFVprUmX_*sU%Acc6m?yZ~Wi6aF33Qd)Fo8`FgZR3FvX; zE%m*6j^j@;<3g{u`m*A0*qIyh(PR32trwd0S(Q&|)ysGcpQ_%kSbcn#$UxtWt6JAR zt9r{x>Km=SWCXi~ei}t@5qM3{3trQv-Z)~3-gx7pkxjr$T^qtprG$^&CF|6eycTC* zd|2YBvIFCrd2iqWCFdHW{|}68NUB9wJf`+L4Qh_mpQ-R16=U22Um;u~dq3146LQ{K zmiI(%K(|TY`fx_E94*m1D&P@%miTAn+KTZ(uEV+q)GJgs z`9imaH;iv!-)@oT7yZ+oXKwPbGk~zfJuGdDziDKI=lAYZBDdnp+3%~+&y4dqJ^%3v z-9k?~K7Eno4M?7v9qfM;_&x_59}9jLrmkK!vI+YYyZvLVTktjXtqqoPKl0naiTQlJ+!z2C3utdCa~u}|xA-o+&;b$c3khwp9d->J5-el{*hw+=Jzjkap=p>H$p9mB88 zd6|9_x9{}tW3H;#D~tcn?o-sa7Jlsc9_=4nwdWydIMOvhtQqWGfA6IUlgFhPkr+26Gpsb6~UQ~T{rYnv9(UI5uu2J&- z@`}7ahR8hJi};Ryn-|>bJXqnoj=Z)nnl8#XUAFi+Onp~>-S}Gcd^>0-DeZt)(~jNd zUNtgAIh;2C>X8xrbK9O>KQe?rV;lF^0vFC{f4l^Ko)|KkadTtT_g#F0>GcuR^ zVciGGbM(si6T)+Zs_-s=H^vv@P2{Wa>!!uP8~6&|1l~41mxaIC_v^R|^{~)$Om+46 z*Nz;o#`)pL@OA>UeU#T%=$6>Ql5)n@EVc(`Kta` z<&WujFHlRM_dd=zr}4*luU(z@OuAL&K`)^)GJlsz_OL!(;3)Hljt$+emvv-wzur1p z!a9QP%=3){DYXs!Z0t~a-Pk~|tOEW&Sd@JOL;p`GIXA6}kAVKocq00j@i9oMXN_k6&OR=lu#EFH-T|4D}J})BpOeGW1)e|KA-S2A(tNU$?WeP5s`;NyZ)0 z`7}C?_rYJ=mH&I=L$f_E@m%(|Zn?n&&u351y*J4EI$L@+@H-PdqgSCX3tc|~T{D}t z!Tynxgib5T2%kouZ(NAnv$cM6+mvDs(qC+^naeam_8ICgVv-5=sFVt!#ATRAc7 zWf#1>E*I4MT9niKXNlLbf0hLd9qc<+7{^C)djBlJ{@J=Q-k-65mc>7d{@aFswv66p zxi<&nxD|Z~JuJkZWjTL5zCq;2`u85kpBjxP+-IvDPcnXs-e*g^j(s-x9z2oL_lRBX3%ot} zTVJ5p8F=Fl_#b2N!?HZj&wOs)tM?0jZxFl2lkaVjZ?)~a7izo2__=C+na^AGb9Dp$ z5%3$*8-d zeT`?v5z+_rYGd~XFh3dd#V4t(&yKKN2s>u!nr?ELxNYJY+L{%GiS zm-k*-d!KtR{4D89d>Hsae-?Zt3wc9|9(3@II@|0HT(1p-N1u!HrnkC z&lZ_)nT>Q8xDxOGvJ2j9^hO!K<+|f*xvg&5a-82z$xkitem8cq!|f1G=-*q8FNIzV zKEr(@_)g=gH0_1{T^-WLCw#0m80-txi$Uc2?` z!P0%ScV2g~=>+`q6`2R?C)LMqp0G91i}}S*T^Qd?zcuZh?e+X;`2INbgh z;{QkfvJMO5=pP$?o{SG?(Whdqwzjis`k5cI=wIp-$oGx%J$_liXY@V!-Dm&3j6=?w ztlLh4aR@&P$5A_e8HenD)tyJPd|$<%8K>#j3fq6hZoTKgQr1IAr|;^*UQ_6yA${8G z2Zs(UMGqrB;Q<$at*!1E*$3UQ-|~Q+RF?@pJGt&~?;C;7K&Kh6DE5hapUAIjd|C}% z7{9FGyHuq+qNMLT06q-;pqIZeev)+(($nIr2P^j#iF55PG@VGJmn8S7{YBxE>5q*w z59@s9T^4!?ujg@{7d(g8=W?AB{@}bI{N2E}-gRe(@z0QE4rV+xc8K#;)Bs0Dtn(PX}CA;sDiva=k3| zwbp*^(F4c%u8q9CGIpWm?3MM_xpwW|1G{2s-ZR6W7Pz@|UAE!V%Y*#L+n17e!22fe zK-J_W#I79hqDY5vhr@pqf_ahbV+_|)LtfQdy2d$k()XCX(OJOajSO>S3X`s&s>(Z_t?bq zx21@G#2;p5AJ_h$HsIq6es6OmPs4ULJaJ$U{bs=R#SdlRfX04&uOs+(SU5SK+~& z-k;7tkgL*fEuPUwp%bQU`Ck|peiPCse!edVK5N_Q?2kV)Vu`;vu(!!$`{MX!)^9KS z0njaa+n2|ef`8(?9>hLUefY=W4^h0BdTgWT(2t3??3H*+^x}9BFQz1340xyx@l%4o zFkVdk?q@Pr-m2}BFOQ48UhV%&<4ci8y{rfDAN79^{oAag8U4SY>r~h8zl0vmcQg7w z;9U76^q{7oSLBR($kFFF5byS&&Fx5!n%$3SC-6^t*p>aN!56q}+NFjn$c@kswQ(W& zdW_$+WAyb}Jw26cYVgxaefBrU4<0xPoI-xMy3KiEWLRl^bSM2>)|TBevWaoN^Bns} zvfe|vn^N!CavXjj`o@pSjJuBh1V2ZQjf)%g zU&(y<=z(4E9ix9OL;p$>ACf5?9T~*073yKxZORgQT`KryJ=XiR1>dYgqd&k;j*l;8 zy_C^k%Ft>2Z1tCs;|I_W3|&KqO%o@DE&{!N@!QbDGI4chcd6+Fa>bgz13OCak^QIf z4a7Z(9_9(32(LvC%ZPpwUW*=P%loQnVgus};auw3wfLT*&` zs~5E%X!NRDdas4Af$N&(1!uq5KfUmE2ptdth^*HwSj*l-i%B z-B8a1e&3gU#;BcezSvp+e0-YT43__8eC@RU9HZ}f-y7e+x~Qk`9r}w{#YP@P`raY8 zDDyGv=u+kf{x|lZe`SETk*Ajyb3?g=TC-d^d%&Ms;j5>z;{ROnzeo1T`wBjZ9V~EX zEXh9J1K$bsH`zB=Vn6cS?pB}csR*A4=;XR(vM-GvcIJCu=_#J}-j-p-I_nPY0Eq`y zjl=_c&VJgH{jtv%>8H0?dXV;_aT`4#v_ma z)uA8kC><{>`wcoDEPRiBsHDUXBLIpH~q;@=G8%2INl^-Ua4qPNWcfGvE6{nakwh04%@?FMm3-8|3Bx_43& zLeE{2*T?*N-I88^w(AzTZTg$$pVs3@bpy{ddWXc3`Rr3fac;ltc0e88`ep9K8NvBEbPuSpHSqv2%d#L`|MyJFpT?WUgu2+|26CGHU7@O^2+ljI;(Q7 zYTxJ1n;1%-*-x>B??=cJnBk|0zJGN;Ma}m{&Q<*sHSL7@jG1rk_-FblqVEHL%M3q7 z@Z9uk^rctq7ZyB^z7+Z8&e|V0-u^sxSv`N8kpu9p*G+5yZ)TmE-!uB-`~`=WLa>G( z8M~yOzn~61*tt6vJinQB75OE}kMrTjYK!|6{1E<_mpWC(A86-xbqG9+d_mr8|Eb}R zosPBS`F-%^^-XUOeZbiDuk>O6q*-s4-8*6NtK;&jeyBBldFNpt`&`EFvmOM_S>b>1 zLG;~do_)~2!+65^WO4_(pI=LVp&pYIe<$k)z31YIeSsfjHh*VQ;G1Qhk-syq{TL$0 zv>!NJUq>Q#1Z<2R>2NdzH=jJ-v=kUxzA;R}%kfR^way#q73c7auxF z`_tq=P?vm*DyFHQ(MeoBasfSW@dWmOiOW}_N2kF@?!ev8Bgc*3%3WC*K{NA zUFNw^^f0Dt^po0kwb0Y&du_~!pPTo?_ma!~KtEYt)Ny$Yi}5q$u?INUW8x%qYU*$d z_`d8j#FmL40yb|I-ZZf<8O069mbt!shd=D{iMh-(g`b0Q$HYH^Tr=l-M9(vM_Jy&l zm)YK4k@Mks9}SDi1IXYv3gdCicUAv}yLMt1&1-)L{a6my_&b*4??`iP^bRxsP|q>+ zsI!Qi?_~AU{ap?cBq`#4b+J40guAJ94 zXSuKQo3<~@`{I`}d_nvuC!X>$8@dKm3sG$;iMyL-Y`inX~+Lm~&GV5T8cYiPK zvtM!7#L_C?ir`s?FaM&?P5(;z&;0uPS3R;cEF7lbYxwGX@uW6j7|7rZ`*9-qM z^QZsN@tFDl68!0x8lUNZ2L8_;->;QF>GAg4{@sVryU^?JJ~TJ3c66uF_uvm_uurOa z5dKFdcA;NIc@Ph&{T_a;FuqTP`z%p=b@UqJAH_b?aWdxG>@#$?#d}7v+ZMGwyKoe} z%RD!~ksa7AdYr^_+;PRh!5HxzL#6xRW53;3Y(9}^pH}q19Q=C`@yF_e+wJjWKkpUZykfb2(LkA?f()4o65 zKC2n${F?70KS#ZGX81`?AHR%4@`a6^K5ZOz{3O9VO}~+!q~`_i`AzH}^eFGparT?Y zf0aDaSGLCT50|kQEai!x!{oadd;ML#>^l^yc5dzd0{)3B4(=nY^Xj3>ed(mSqp#3> z0)5R&K1W=G_UC?jVky_v_>15=vLn;Mb!11nS4^@F44$EfS+A@9kRX1-_&e70ao&j7 ze~Z1Ku2<-%Q;Wr)h}Mu6^L^_c zSMsS;>Q-(4v7fnD?4_jS{bb4C5ql7Q$=G=WmZR_K_-CDe(V5xyokLbq^=60m9|CS0 z!hPB62JqKHZ%XoVa@aLtUXGmGD0)tE33e=SO)k&tx&+u?uH*^K!mon-lYY;Yyxx?= zy)!R+5qT*#@^l6FZT$6ezk>eUuMYL(fLDLB(($>nZ|g|BfV)rZ+$dj9_6;>Y%ljtw zF&^0$#m__D0e=7Fw0ymweI@NH?3+cBug5smWA5YFYyEN`yVzbNd4$kgIG*Z##^dSz zq01+S66!kgASExSFKaz{2!0d6r{if?_Io6c?MVf{7yw@m&-;N>1-mBW>-i^_Jr~S# zIrI0hBaFVi*aI&3pBByNPv_+rJ62i#lM}nhzwYt>UiaUMeVd~n%l&)dx8{C-cKE47 zYl(Xg;U2-4_Iqs|S9JO0Qu2@SPYeU!M1RSZx)Djq-|!Xr+zPzKCI9%Vht`5O$v=jF zH%b0^iM(bTx`Mu5SOJ}Yht3u5R}bw&FAwuTs(Is*f85CaLP_f^z}# zy}~g6mAvOcKOI*uu3*0)4?SL12>kFS&y~DLv0IuXf7em+p7!UMJom&Z=B22=Ci5zR z=ap&l!-*5QobeQaSG_!T{TzRUJcs_tiwyJJogj}mY}b}{%h1)ztj?2c$&je7nYbN}Awl*HqjaaZ#~ee#c!l7BpLXhU4`j}ISO zOMA42)Yti>BNNA2@1Z}+&}((v-l1MESa&-A zILsqOANY=}dlkk7Rr8N)`Gzw(F#t-SgBj$DtyDP&Uk>?XO86xA?T}BV27Kby z<-7^!+Y^@XSL|%ovEkQMJQ+F<=;Jz*f1JVZm&V_&UT}(vac2VhPcBEE<%AB9V|nCj zM!9=^_=C_Zd}S7ToLz23d^^B*z4d9Wf&-0n&Cy?%A_ z*tuYIuG9l5%o~L+4PQSKpRUSd|D4I;SCz-#?)9eC1Bv9Z*F8zUXO_qQoXL~3$zwY` zIl}(Rf1Er%4c;^PncFsr{yLMNmD^-qb@|yZFON?f7kX6J=&OYv|(la@PK5g{$zA!HAtmD4a(8LA{zT;xYqfd2*c~HhK z3+F5OGpE-p%e`TAbKtKL{is>$mATl1q1~dW3n_7OOWR&vJh~LUU+l%4rM@olVAwxm zKg#~uvNm_g=#cnh${De%6>(LP53XW6OGA0+nEfcp%a88=`M%s>j_dF_b;Pi@rJrZt zIJyBk?Gd?(9FFYybgWmQ@AaX_x!8FNvExcw{s#5Nu=m9ekk-#x-}2n2oqjKT?!jaP{RKV0X>o0gkA43Bg7$m7*72EoWd`r)A46hy^!K<|h#&Q}*S&GB zm>dLek-wMv5gv7m!+EPk64wuY!}uKI&o%uUe{N6PH~wlAJ<7yS4YWP`(a{m;yaPW6 zbYWS!wIV-^f7krt*WGvUIC*+uoOpA0zU2h)HGbW=&~ur13ei(5LU+zvCpXh>jsNXz zujg;!`;)}K*srE;-A3$~R z3!FNgx!F~JA}@vbrg2^_j%BF7j*g*|F_ zyOr*Oj^Fs5$)&&0_oeRA^!fVlo}4S^&AmFGHh5KSJG&&#N3}f(yczC*`|eTrD|tYl z-eD6L6V`1o>uyb-i+@_?MZR2)-#T)@v~TiJI)q_WHN{$-$H4 z;avh9->R>;zsSC*ZRtPIJv7mpDG`p*VcH0G$~BxRFD$ULEd->y-Gt zO$XP)H^cb7l*I34Wk1^f!%6s86#r)034c>+cToQ_toOtDI68hWCGmSU@Cx^R%s!3k zm-s!M=NrcDIe#qlwx*l$X5mk9@R4CUXMk5G_m=k@+*Hk*sE*gWc@lbz#%tOMe^U~# zhn=XpO+01(^mxN=*`I=cg!~6O)bV*d<2r0d&m zEmJp%IJ|Yi`NWTPMd#j)bf>{j-E;2>n?;Y{VB|2q+2&U%{}RrS-Z_^q|Ba#`YdVQV5Wy<;r<-W3tTPHigXBek>oy2Jt(Ay+l5InEwCLU42 zHw_+Y@cT-i)IXB-6yQI5F?En^+(kXaBhnB4q&p{<^1ZdgD+oPA@I$}KL4SR~FU@_! zm->V+LGK~H$!Ge@gC_(2Gre8|`t2Q)CxNTUqc-grdQNzxZyfl0lD@yc&=1;UC33^ELDsu2b?cKRn9kz%MTP zxZ54nNlJF@a2|B^`qcXzsykf zRqM88h9(CY{!K&FZ4)?1-8Segs@wJu`<=`yw0BH?YgD%_#7h)!O1{Sfc3i#dVyW9k zdzOFCH{Tb2HE zAJcSU`tKzlCQtj$xztHxTsG_6!Jg^%wH!5kwqN)x{n+roUgTs#eb|+HRn_~{o6BOC zWZ=tb>ZcgK+)ceX^z}7urAJ3QX+O*}S>D$3iBaSr{4?OU-6|z<5_feW=diJ{Kx{v5v&-(R5_%YSroP~$mRPe$I}!X4g43ScH@VbX2Q+0z+qZj#-^ZhRa)ErbMLznxL_d%7 z+oSQ!Wp}ExD+6_h-!D|Zxp#D~j`#CF2H%Fy1@+_p_Ioj%7Zll5&ff_ix7K}B?JqQ_ zYW=J;=)Jv+!-enJZlzP`Is86x`&oV$>C4IyeaL+O3-n*=Ea*H<-A;Ag6rY%cerw}I zjD2bBNArsvdEnrtcvSCYw7b}H!lUkk=m`~|+9&Zrth+_%U+_!#+!rThof|&;8h?oo z`r@QTd{2+mYa#z2s`ui3adPBr@~HS8{$cc1qgP|+nD5UNA9ULHCZDNpJ2T^hP8+|m zBkRs%Mjll#PSbA`A7pRyMV=Zwvfd9&&K3Gq&rhCy|I0$RCT}VkhYw~T{xj%1nOxJe z2ayBDj;Pi>%6)lqsJ>oaFV6}2t@E19`10N0f$mbv3B`Ji>e7_HCUjhliwdu!xTx^D8W%M- zxdFZ%(mU&5)@z}o;rwgKuR%V*Pl!K1JsuS-QmYPGCIWi-^TS)zTK_#FDZHCz-uq5RV1+_UhP#lG~C@I%Ar z#6IwgqGv|mzq-Gy=6l0$>b6tsFRK~9;d6E8F~eULjMMZR`OEBU|Lq`pQosG|cScVN zeWp)Ljv!}N-LHzs9krU@4F0K&L;q_Oec?mhE_N6GvWmPra z_{Y|LfATnaOB>(uFQX%@iyr)7E_%RqYyV|*uE?$2_oW|s|E_YQ{yy}B{p;vv^q8oA z=pO36^8G@opUL)~(1Xi$zvMYE&cz<}GbL`VQ0exhUFZ9go7EZh<%oWaKHIhjzZLps zlwTL<9n@bUF;`N_eP(Ct;kF=DT)Q*(-Y71x&i z!^z_k4}w3cg8%8Nxx|m5r=1~>R`uCh?-e|XyiWDFO7dNk(r$(JE$7FRyChGnHeXaJ zH_P)-PN+VI^;NC&X4??C$LDWcMc7Br6GU_l0B$OL7xJvO>h0gd!;F z04mEP!i0DFpbjrew5WHJOZun_?Xi+nCxuH%e`k6elm@zT!~DrmasM z6fLEx`G0@s-aE6I&63d8|L6Jiv-v=7?wNbe`JLbU?|0tlH?*Vh<=oL1p?CNmJ95%@kyFVB7!~n8+h+;z%#}h~o8--mRU@^+#H%7v?)o9lsZzZ1c5$s_}X1xV`vPni zSAQ?@V$s76hx9JxJ=)>JJi`m=RgT+>jiZkO_wOujcg<0QJb-$t>8DG|{EIyw5`U2R z+n4jPYu3B@ooOv6`G>RUrFQj=Hl7H&Dip9EvL4!$^%n38a$llfJ5Laib$H&$2`8mQ#zmmSJh`VO4r#|*F@)yeS zOsW1U;-VAlM|OMCb|%C{C&C~33zLpxLR=KU8TDI^i>^HXz>DQ`TWjN|8}B@Lp7?u_ z-H75H(Ssg#2|4N-Jy@2jvfMKdq0n=sd58)-R)KfojMpF7W|ZQLZ?>DsqY8d6#Tn+3 z(XSEbm-k-;@1-~+{Jk7!yna;dciBFi^j+xkyNNTFEkDvL@yKb%8QbTlMUR>*#GYJr z>NsQ9eDoD@#_Nxu$A}ZUk5F%-|6d5t+jbbgtV65J;|1q!zpF1z{17Yo`;)~7ksSX* z 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 z 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�aOM4# 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

=DD)mcHwLvd1{!i`Y;8tkU&bt8cIED}7mQzkqss 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

^kJIG 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 H@8ACiPw{@v literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_c3xxx.bin b/sys/contrib/dev/qat/qat_c3xxx.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d1ba6ffc5f695f1b24ce1d6f07dae6039b8d8aa GIT binary patch literal 1062072 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 z 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 z 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�aOM4# z9pGW$%1`LHLEAjy^P!BtwsZ`|*QgaI!HdKJ4>$A2X`>g^(ep< z?Tg6Y3~s@XC0;wUr{ESvZk^w*Jr4uF;i{>ywOy6_26ZsP@29DQ0q!~aDd>LM=j^9r z+tXK`EYtpIyk8t~!z-ss;L+f#Gj+DQy(;qWe?)p8%ysy8;4kq{uERe8UlwnU;H?Z@ zH{s3Vi+Y%=rULBh1aHBbDe!kOyv-B56;l7^c(eU9PtktDNtKJW3s?PPoXY;7I8xdY?S=uZtc`^svjiNxw}! z(;cY&%%@tXhQc~ww>71Ao~$DOT&_#tRdo%7v_H@LInLQ79m*O|=uh;QG)}QI;$-H*ew46-huh&Jjhl?^#V*k)N$`{+K!>WtXiYx z5Op0!4yA`YTfiLWY`raCLfaCd70eUZoJrgSFNBfu9*LMj0 zd{fqKasQj+a^5lck>?@uPu{Om=fQJX-;G^$*Hi=={f4wkAFK@%}X2-yEWY5X?wP?gYUaXs?pX6JQ=;gb!}_Fc?3J_ zA3j;ocCNo8fbB-A;a29idoa-Qy5p(n!zV-R)TVQbl6d4b=ppE+!1IV}#rMpsJYG&vEwl7R0jsPL^~O;dZY1FYu}rET;qHvfd_Er;Gcm(>QpM2-6o!@`l(kD ze0CMJKi;T+ShM{k^RJe8gR&mM)~$4^zrR!J%vBP1RriY=pnm1P@9^&%kGpd*P`mL1!SMn>j#&W~rqotnbl8+swoi4!#`tM@!ilET-=d1DK zi}Y*!;w#rgpF9b@_edPN%D&H12LWHT#-W2xOo9KoK4{scej{r6P2=Q&4WNfmpN_O{%MzmJ`s=)wBqQy%ALsE>NG z9z*q%e95y9F1@=NpQGVFF%>z<`L%7LAIrLKQ0wJ3(YIws4UT!?$rAGNfdiEtA>(zt zaH_z*1W6sB|DUE@)-Sj7zAOEGh5iWdt*Atzr@F}NNxs@S{O9qvM@hRuXpY+kgGyQYhtERJt+#ciCjJTm zH2DjRTgm$^^)v50kZ1fRf1MWkEaDGH{u=)5R)6nFotv!pk@(`X;}VBRt7q3>?|8%| z*ncJ}0`ICw`&UQTalhiID~I>*Jy}C8TwROnrq@>WFX!W6M`zWl;o$Qp1D^MI{sh-* zMX4(1u4MCqfAZxT|M({>@lW8RbUui7f#=++3Uy7uyAr>o3Viu;w9CgHUCaF<{>n=H zk`m#F^$NWN+_H`mxv26Lb+C@#VxAM{+BX&PJn6rp;Y*L>H!|+Dz`^@1aJWwe62I(R zMZ0DETxqu?a9VgO(JrAQfrs(i{?hBIPllcxfv1kVm+yiGJkWJzZzy(YWxwcy?ll$S z(%>0;Q_IN}F?<>KeSw^Fml^l*Z?QjR{Lop)Qu?b>hp-Yq3%J#M;3(lY%YE=8aE#W; z8zlXN|5g0Z_5eC6HR#CZ!)=~k^%VSx5ImW@c$>}xLzI^lwLc*F0)0MUPv}p$tRoq# zeDx%7s6_?s2XuCY;4_2&gq*0upHfd;bksw#PL1(5$4lEJUJ89T;-!J-D&jHPZWldQ z{HoBu=zSeO&9N>8K8F9lIt58D^6*{MwM6X0vXps?r2YcGI1l~x#`SYOc|Y0}V%IM%sK?=N?!R}~r*1{^5{h}S z^?p`9Sh;HSsl)-|y1MXbv6rlT;WvD|2wx=i7VlE~=_jfCvh^!T`$q2!N&J}kF>?9b zdK7)`L`&XNeM90huV3Hfb>7eseFL79Q+!7BzUt~!A@ihyloI|?iM|;P0^|pN)N@*{ zi{8mIKcaWwgND3T&uO`K5qj({Pck2pf2w_UN@=+m>jm+v^6>d^elP_8NnUkky;H9M zSCUsvpE{{hKS5r#<6B27j5En^eq8M?NWIXi;Gp0kiO-jHeBSj2sz;GSHow^+ar$E0 z+;+?y_Lb{B^TN?GbddD>1?p18uAyJ(q0w(e=c8Tkr4vWX(4EPv&Xay?;3>(gK7pSG z{*7PIV)q*T-kMjXZbRYs_UGH80{B$qt!m&q$*Ypr37PjDQr`hwo8maXIw1NVdmy#W zpFkcVPqdzBllVfNX1c>d;49+coUaPqH0*@@l*H$ivD1m8{`aXG{??Al_fImvD%wN* z5ICZzgVi|@!fo)&&JaP()RNXG?N z+j`|d#|0a8veoZS)xlHOe^3%fSHYc1`!BD41G|vh+Ac(VCUvs4zt!&#t4`T}A~PKG z?d#rOGJOO;96V%Ao$M;|-Qbsa^7kcwZ0S&~DC>16G?74!$-&Dx8|q<_M4m^WPh_e3mq>A{1M};fyd~8()%rP z9*M*avrldM(Mj;B#tTa4V+s}GALoo~OyXeJ-!d-fvS(F|dPwpN?7t@KgE{AjeYt7Z zjH_)W`$Dgi_(y);bfEQsj$^*nP0xEl$VBYX68@L$zXiTp?9!EDr&DjeLGs|>D_PI! z{gcSuk)>7r-Dv7)aG-*`DFAmwyK5pP^prY$BGT(K4ctjSc&$tP4!SgOr!?I3Z{c1I z+ql|4H^2KX?;=B%d@ToxN zE3=mQ@{p_Me2_LX?t!b%YCGkM5#|;8xq|)LDkT~30pule(u{ZBYQ}p6KjG@LvEH|S zYQ^;r0v*D{#it8pks6v3e2EIAwGsz3CmAqhs4%ru( zy1@n==44!x4f?b6Xz4Bcgqrt46}owIq~*GE_!CO6hm`&Q;O8z`Cm{68ug-^$%6Uh+ zJssa|@N2$nI>62renp?auTxVroA}pF^#R?Y4~vXD(ZinBhuJ4e`4`H>=S2^?N_9w{ z9KODIo?Nl+QTqLt^W^R7UFcK#HTABl3w;y`{?U6O_#P6z1MGEQ$A1EkM!z=JDN3A# z_Y8m9{ns+<=1)X+R-O+eVRRYsM-=FSz7Q z(6xADh0kBoUDPFslQ)!w&t1Ubof`VwQ}n*nbHHuK(R~7u5vc^Zq*zmZ6Jrm%3f<|AcaF-Y{{;BKF>JEs(m*c>(*9)YwPPi55@Ou9c&9 zy+fzSY5yEMaRqi_k^KwOUkMII#F1AZr|Zm@)jN+=sNdoKP1I?wLw@GQY7(!q`+>}3 zKZ1k258i%mI>5_NH_#5_N!Ha>kyFIgL|^)1PsHoPdb;wg55s+v^)6RmRIuU@!g=Odjct*nNgzKnFN1>ZC&j(|Db^Q?fs)*YuaKxXH^Ayuzcf59bN#Ptgk4k|DL!Od_%weDtvevcj#{0>Y1ZR&n`AHGiB&)tqaL*984@7MW!oc9Cp>heB#ctG9{#Xm9a=Xu|y{^tqa zFA={NJQV164eLsZg3sWA={)jjq4BG&{ba`}`0$YPnT^y>62E*;$Ge}aVkfr5(aZ0i zhL2kGwT+LN^<6Sz(brZ!H1ss|Q|4*1uFH?(H%3qQRO|i=A@eSJI>atEdO9O|8vG*R zfRj2St*7DBr$2P(3*f=77qW5G=a)b?0sM1B-St8wc=g{i?Llv5zkqb=W%M+4Ho~6; z@M`YcbvfzOmg@GJqk3K9k>z&!x$(DNfPZ_5i)%fh>)y~~L+I%;@k;k*;@`+Et*42H z=L7UGcF&Nn^+m5I&$+(<{m8gjC#HnoS$~!q35avbx;~ft689{~_x3q@+Qprhb!BDN zAIf?&#^o+VPY2pgf4|rtQkS(II0pxBs>(jHbHmw%zGYgpo<{Bpob_x1XF8vcb}8ik zf?}MHG4Lhp4&NYr$7CHBc=9PKL$h;P?4;IP1@|*YL=Zj@t zrTzqXYm7_at)e#<%X}hVhJYt8acsV0K6y_`-Lbnk(DX1DURuXrWBiN*yzHvNHw!F& zu}2hf9Ko;jliWw&ga7hkkpsYC_%)GtMh;~2_d<`d-oVDogWsRd!_P^4?W1Zx-3~6j zxB7S$Id-|^(V!>Oo;}a7Q|c8W@&RW5?=H?em-zmJ3rc%*-5_n$Jf64M8D1dqffhT% z>bV^8v^?aS^^qsQwU~HUg~m2}+7E5m8^L{|7gR*tP4rD4c19jJo9v8CA9hBOcADbC z52iTZk9o!Kc|i0L{`Z4o|2(+L*!M=h5-0q%X~p-2(pc!Xw$t3My|#MMu6y9z;*DXA zc@#e}K;D@;`3EzyzL7X(Q=R<0b=1k{kY5IlPAA$r4L?12b&a@($Ore=rbG0S`bw}T z6#X0PKlH{U(-Cwhc82sPc1DePH0!Ui(;k@?ye?v&1C=Hobr+4MT5bQ#FJC3TQ3uTyN38%S?cItuiXS@pnLWi z*LIV$F0Xb&hwbWp#2px)q3`UHuW*e&xv*=Mx*NEx|1EY>2|F*f(cfO+zRBAuyU(0H zHxharAwKSA)g_}L_7m?d^RTC|W0s>I<$B#GHNAEquMX8XmuxZiOdfgZ)IT*{V4jTq z)w%vs**TfHTAj^ zfBD;v|Gv@3ArHWLR!pBw+iwwE0*QIEhrCEumJNb)C7csedJ zCU9_Hz6Y;NC~;bTOns64K0W3IVO6P#%=@Vu5&WOO4^&R-8}i`asqB)ta%2Al$vP)j0>-*1kgFI?i%Vqfz7d5KS#v+DLW^Cu3~v8R@PG?X}A zcIijmJ+;O-+ftKp-Kz2Xy9-t91pF1oDfN!T&r2b6+v#}!c^dj;|FrK;tE`%MKjT48 zbuA$d>LT|X^=ATq7QcE|ggvt;!av3?SdD&kiBI4+@2gS=#yKup51RYL=k`uV__<5Y z277(%6M2t$yItO^p>LA+!uqt=z{kYr=^wZ(e5{N5oY+MTe5$9WYf^vlE>HY12R~5q z=E@1aI9;XA%zFa+0XmiEb@;*H@tB;qL%+uae|(>n`Qd%XsefUb>3vS(`bFaVQqKu~ zZeLHFrG{L%Gp;Yie*eNWbiuWbo44TI-PiBo+l@I*45N*PohY6-iyzOe`({$jrsqNj;vd0;HUcKX_s*r zdbM&tx~$y#vU%>@^i{5A^9A{%f_Ld3Ud_#q~7n6!8!G zy{<+)N8&_*H<;J;uU{6uW$TiiYv2c$I;(^Zqc7`tyxcE}T~^n2*6r859MjVVp-1}X z{w^Q8cu}4E*em9KTHdd+&xE`W-PrrcY3PrAa{rcbhtPRK7txVv+5-;!H1Ut)>m=UX zRL_+f5`NeG^0a*CXQJ}sCBd7YeFc7@-ZJ}2fu9Y)A3^`WddPhYI28LhhY@unPH=b{ z_?*?~?F#g4?$2||Uz>K3ce!@fLuh$%WIB{~q}}vS&`PKHf z_f`&Ad1~dL<*NofrK;r9=9IUIJn*X1$Vn>?&iVd@X`lOZ$mN87n({b)rdAgFTV2Dv zD)8S#FV4hS_pt)^*NMN3ymizI(-rv3o?mb7&vWu8MP6EZvGdrjz7IZ;v)2$mP!czd z^#j=XlGd+Ha;h<&;*7}Kj(+$YykwT%OdTK)^=~V%lf68XwU2mUtW#Br9=-yA7$>_xQmfj zgBjwzCFJINo;mv*cxsKi6#r(rM*gHZPh#W48>C(085-Xr51aENQBz#DqWvWHQ(!+G z@w4JQNw?S$(9xK-BY3@U3OBidW4L?2q&!T^lx|hUXe+55)_|;ZbeYhs{@f7Rdpq8ZF3)fM%`sM1!(-HI99RD|T zoX@H#^x+@z*Gj;>xvu%IQ7>J5O~+$%2Z{gFKhZS3?r=SRIrFDp#YQer&$%9dobjvd z)tswDNbR9*mF96Ss+YObD zZ}fKEsLp252kZRpm5d5{{Ydr+%c!L~4&v1Q0(%;1C-F__t;@-MAc$zsDRj(Kl=6C+ zf5Asr5c?NhW%vc`svi6q{BrUCiug6PZuVPO_=m;LnQ}@!(uJK(JKWdt?q0FGYQXK3 z=gsi_$0e`na^9M@m&MPHdS+_ixf=)Cm-oD`8Rjo78h#`ZstPKFF$@gO`2q z^A_GOfj1}Wo+%OkTFLvhtSa*RvZsH8m!X$Vbu@UnAojSIpAq`#Dk+f{p2VRlwAYV6 zuf1= zG5c>vZ<^uz2c(~n@#X2q6+QgRk=QXg_4m{b%eo1JzXjkgLSGV}(DhOa(09zA-LIj0 z@mc?djp(hlle(U!OX$iKI#RC2n^_moyk9Qok45_`*pm|14taTDf5{EGUOS2X!Z>U^ z4#4#~kE^6Uhx?<Zm9A8sZCg&G?MBt4jWb z`CR)5`555rFU0YYB}JV_k^D^POMZv%z;^Q8INxzSaVy{DMgD}NGd1LTzpwK+YDtMa z4Sbx8-yNMPLoUKc5&f9>Wma9M4wf0m;&>eDa(;pTxpl&~*jwTkMG|*(-#n9N-y2y6 zP-&Ms1nN{W@*KXQy>%hCgDlJ>#`N z?41Vw0^XBx=5L&FiMxD_@zv0~l1Hu}UnE}~Fh3@rj$i%G8MjSMoZ>y7@wqP0cpyzL3JX&{(c^q)_Z#|{pt5^O)?GD6`F0P#kkP3o-_+!wG-g*jp zviI|H-)~bxuDAA76}w8V^>+rZ?+4xzanO8~aY2`BCs|L59di}qt+1{_?kg=9;_;gM z$#@^(d!eVdRPtr!r_H+-JqZ1oaS?A>JrhxX<=hm=z9njaa&Q;EW?hNY4cPf1uDW7| z`;K~_CvvCTn+`(e#jYQ1oTt-duUa}z^xsYu0*=*x9mG?1gSXe_7m(Y?eez2O>eOkt zULbjJD_@i=c0N*1WZ@(7+*ua}1=^K( za)_Kv>d;E)dH7!J{Tkwhdc^}O`I zS;hX0*zK~fcW#BQ(APQFTA4)*m`zOIYu@vx6w zsYl~E0(=%0G01YYcT@ND~Q+_&QpIGN_e|FCe{amYBqkBo!)Y>e|_;~<{JIC^Cq(3^Wz zFvmFJ`)YnO+}QPHsY7~2?XO84QkUA}L$}!TyWrE_>u8txcdrUH-m=#)pC$D5RdsJq z6*x_My@H3j;0u2M_^=`wj2;Qyju5ydLU{zUbTnJUk7ol5k)0w-d( zs5ST#j8m<_kBAtj^&?*WpW45`A9?3NANEI#$a&$}0{$`bIJLSINnAdCRTaC9@7A); zj_)5`UCNyG&{IgPI`nPzwbkE^I9{adZl%3_%2CvDsmFcrzj~cN=;=D#@Npk{SoFT& zv5Ls4-w*Z{k$Z=29B{7h$BKhB#Gl!RlkauD{Plm|?+u3Nm63QKRO$cm0(AAd`_B~y zJ>;0w6T86Q|339t2z`3b1qT&)xAxg6_LOQG+oLG`eNxq<)ldq*dGk6o?7=EyFq`RMdd4+zE z-{l&3?d(6h)y00m9XbD;Dc|G^<8!7YPpJ3T$UUa>$ExdURVm>&b>V-M$b&e=4~c!) zA#o}CS6v?YDdszeT~j1}?Bst}^lNT@A(A?lakll|%lzgX?;|r{0XyI$GteOSSs#TN zr0p<%o#4YWep;=P_iN-En%?KWUU!?4_sjCW`n?(G?;Y|!cy4~5``TV?)Nj+jmuh+6 zzDN8o{R;XOgG~EPD?5V1Cf?6w#;6ZRZg!Sx6ZBi27wfzBd7P8Z__H}TkbI$=Q`hB6 z;KQ!}HtpopHsIh~>mUD;+8=>G(ck>4d|C5hhjUZ?Pim4+@RZ~&)TN$2w>+2k0-cYX z?`LE^t(7eyTCoK1J@ysx#_uk5dE5j#-L_poPZXJLSSN1pX^+2>ov*>q0Wn>Z)T}55M~H zAJwosWj_$$vh$Ok$3AYz75L1RbJy&1&iz*6w_Tfi`je-Mz>)0Z;BB9gcGRZwccFr0 z9|xgdk362xt=FKNX1Y~LoXFoHc$_m%wBrB7-j?U90v#U``>xD6Bt7ioK))*4$Km)N zJM+v+o=k7(=k4m}TXFm0O34EJ%i?ZLs!F)>HEB%(JmuSY{oc+Gz)4H9c-&wW0 zBJ0@cx31-lv0H0#J-&CxpJ+HuzjAKN!4SD>)=T2&=<@*WxtjJoK>Wrxo$(l7le}+N z@1`CWx-|8SjXDqHMS=G%+#mS?^0YBF4|RMe!1R%lM1=M zuKz=OPWimQ6aOYa4vO9{(9bCH1i48*q43!X^yQ^0pOyLZRs~;-updNTEAiW-ecE2~ z?0zBPlQYmI?U?;S3VI%rc;ua*Ck}z14n7XRKUwtw;(X*)QhWUEfTg@U)sqG61gG|A zGoh{zVxJA}Z*FR5GwswFci$G`5zM<&+BX9o*mg7OPV8jj?y`?t$oK}-u0Y;*qW?To z;d)5q9Ql;Pt0T!bBi}bl-4y&mJreodo{)Hx)Ke7n{#Tu{Z*7(FFUb+d1wW6(`);X! zFXvI=Ck*;HY}mW0kA{0n?AJY5#$MphiM}{f$1gSgsIicBhm249De<@`&pumRkJ3*; zt}F4ra37rN8v$Q)R~AbtI5=McLI=PtNVhuC96e<-L{AL6vx}#OJ|p@8Zzg z4V`onPk1uIzrSv>`Y_+KpF`#q+PC&~QeU0nxx#*b&pQr0&wH(YWA(sHjrc=TzNcH_ z_TUANne&L~Z*!=&gvdds@+FC@_DFw>(>@;{Zu3~4eYh9<H9g4fpKuZ;iQ$UkL9Jm_a-9XnC#B4`)> zO|P$e2jNTdKADjSKVyk}hrE>UO5)GSK7a6^tna8ZpL4*|E$0{rUk?@{k@xM6SDT^T zwp@-p0DR_nlM>%bT`l86?g$)3A3?7P{p8jKvhP)T40>?M zpEc;=?ZXA=#N2PDpM*}9K_@caIp_qv_`JmL<-7&iPX#*1u7SP z;`vC0bvEb|S@+>VcaHb%83q2wfxm!WU50-j;yyOXarguOpS;Qv#+TRe>2JEF8_LL`iI7N|zth=!E5UfNWxY!emBX7UVJL|fijDT+i zaTj^NIgTjtVc{3_!Q&<7gZ%&Vl?&;E;@?P|q*)&*6Gu$sJ@JN}%(vqdzN`HMTaRM& z1$Mo9%)Nj<=tUnCp-=HEqc*j?KX~O-1^-~t-TtR|-_m_!9S8H5*YBJ2;R@QGK@YTz zGX6FFg?~5&y|jsb0B)PVPf4DW@ex7Sep$Dy<6zv#|N1HDuSeG5x~%7r^9Ay-57&o$ zk^kNgPSvD-BmCh^0A70vx_*{@E~?uD^epR^50;n*bH79Oxn>^i^Lbqb=r=__oBro1 z54!D&<=Z)WL&yDcy%p#LIWBV7!!AhlfUo28dHo!|YLUyHUTMy?W1mpjA9YOnDZ+1woCVI1 zYvjA=l^)p-wgUfCSS{-r+Q#`V#9w-Y@D0m;^1^=&eY1A9a<0A!SIJz++z?*CEe=?d@5dC|PrE%RT44qU$XbzLs@0&>0( zb)K#=ALNnuF)s~#Nd1S@2R|3+^ZuIaYfN2b;s@-URFx`n-n`dCop0n)w`%HF)mrvd z18?e_daVj{*S((ipi|zX9viw}Rfqn-v()S5SvT4|KUX1d;E%CYW_}7$tOrfKOkO`H z-X+f?@RK}`=gGF)Trbl*9?P*F`A(htU7+cx6+cpU(tzLEpKJT0?$Z_Ynpz*@Q|N?o zxxK~Is7oH--0znArI>z31LntFPn{3;o}n-Hk0K5&`d{MEI={bc7CLTMe-Y@o!AcW1 zu<>PMH!FL8#{pFl`Y`j_BX|^gT^*%H!*+F5zgl|Q&#Jff7k}<_3A`J-PtI!!=@+qv zzD95LK-b98&aNWyKjbOvOb!ACb!~mKb>u={0lh2y1YZO^Pv8z$3BTO7+56JNm8`n0 zpwfq!H}bv9W}!1RUL+pD{XTV{oX5rjZTvyxxguX5$a>gd!EBV4{r>fSNbJw3{Y2td z3ub-v<-%fA@z5unbG!$5?f(C*aFk=dZJ7_B`4Bl2^K)Y#>GSd33YWKdww7wZC2}1+ zAwL(-`oJUdL*ODWD|v+ku9kWI>EL>6e|7A12|L2t>t>$2WuAqus1FmmN{_=w@Ll76 zJid#~bGA3~bUk!0{#OCIr4C=)Ba-)Eyf*J){Xpw4H0+-cxsH9%R|zB^2)$e}TZNAL z3Q?$pznbaA;ytDh=;lu!uBX*)z`S>nAL71^8`$}1$OonM)CKJ0x6ZosW9(yl-U;o# zIup|0Sg68?VGLs*B4;mPzg{JBvSGhszf^&bvM#BI$9`Qmt32N z&SRR0n9sH%>yJX@WFK<1(x9_!FZhdyCoRPP^T-o+RjH#xe~m%kfYBJQp+9rKK}Y7k zkq-&IcBvbNUHWU0i{6G=zx_h;XTxj_IR5SA&ke&h(L?U?Sud9B4;6?iZH}Ucee6+# zpSC6IgNln^jQkV%(bg5>M}vnk@Kgc+?7Jv>qEoN8g)bK}eiwNFUUrqRS9&B~q(tvE z_xGm{m9TD2e=X+_8-8jZWS*f{)~EmCY!!Rf#_L@2Ovn%A1h>yJpEf>b<8VnmRuA=9 z9(8*r4%eg4kK(%}FP|5O>m?5Nww=@)4mQW(iuhCLY4NAP1M$lLMeH}#w^LQ}@X;`E zfIsxx&7$9OYSZoCQw?}*ybc15*8%n@;)3Wy6R%SeudCC}5;RT~elYPmhj`uFj!@@5 z0z7#=PpVc$Pulq42ylhshcW(8sq1^a>{(yyt=ngntmA7s*V*6`ef{SWFKbuqOJ0F* zn)XrV`FCa_o(DWHwmwhnLmM|}`h}j}E_$<(FCxCo{MqmNm3sSZ#5kM2v)A@{>$%#I z_M5KjKe_QVkc5Dp}qKA-w#=larywh=d;5T*Uj?wGbBgk?5!$o%&A9EeGS?q7< z7wmud#ak5e?UvdO=EuV0`W<&1iMtYmgmT_Zf$__)NB=`&*GW9Y=!+rjiz=69{00A0zj3URQX3Zf-fq8Lxso^Wh+Dt+ zQ|()8QZH5WMgB_vA@VM1&$OFS_mO`Go*~B1dunr_>w09LY*}YI)_3E3PM3uq?7B|o zqX1uu{l#}}ef@1uhtOG#4T=@(r@-uwcstXlO1r^}a-zFtd0(lge)D@(#&7Bmm5mdb zagbm7&F_Vb*UqbnC$YbH`zvMeY3y0%H+b>NEa!2ePq8E0W#85k-sno^T6lPc5r%xePzsmv;RR&W3I3mRGasLq+6Ds>_u;XLCREQ`gf!@^YB(OYQRg zL*xg{5!|; z_%Vh~e|15*eQO!HZ|Kv#@z95kdDK625kINm@AY}VbGoeg&40|zs;gx_i`0L0MfaXA z(jWOD+26)-qI+kd*OJgh5&6?h7nXlyzP*M#asA`>9`m_2^g}%C3(}6gUh(!@>W>2N zcNZ43XA8*P>`t{GxTrt)sQ4|;0>)jFc`?_Qa$OR+YOZ^@_C-DfUziOV^E}t}K$my_ z>9YC>#?cWRgT5Ma=HqHV?MQxq)@M9M-q>;3dB!sNgYVTCzrmw&fbFR zeA+>eN_?w8dz(X@|4;I2J%8`iBkUc?tL3Gx<38lrx%3ci68$zX>}@(-kowo!rdjCu zmI3&pPM+8B1J~GBX}Q+)tpe8<{56$}Ios?2F z7df#~>JZx1{coY}fcd3f+zr7mE3w>ArPQx%E?%}JB;Izzco-I8qtyCvkB=Rbxfwmn zYkB%9$$Gc&W3$Msw#|j|L$q7G4}Z4`p1Sr>r_VTY*pngt^vbResGG1yH&@CMKOR`I zuKci~&VMuSds*_zhdyzvq|_zCM^)CNrM`k6?x=Q&%fb)yoahs?z*W2we3r@Y5pLfb zK(CHhp7p3B0VEk$GaOVvqt_YV#o{{$7!UYx9QBFW0Jy)xbwEGnx_w1$*It>2{L6z< z7o48yfwX-!T?MVXZB}Lx;+}w6~7jUhdI8?^D(gkGuNEvo)pV%1+w1@+GbJgQa~Z z__VeUm)B$YupGS$og{kK(39mG6^yCS1^(ncldmxEZDK!6U56{@hIr6{6Fffaiu|V^ z@Wei}?>ty!+!yPQ5{13c!>?{ePWtKs^I7?{=o1SE_1n6hU-FBO`RO_5xkK=qCqC(@ z&xrkQ>65yY&&)>Pr>UKR;T!+-G{0x@8c5ysG`BKNG)lD8o4dE@&Hy z_bEvoz8}B5jW5V==cPOXJC=E#H&|g`M(UN)+o+q6Yx3I_;8=3R7P8K>Azc_cgK7zIcx0b zxc?r>dvAds)GYMGZ#q!A-f=LfJPo*+)^sExy_P3r5^9oyA* z#_x=l@e|wBMp?&)T(s?U^xs_znNMq{cl2$n$@>1B-_aJ)-SjnE{{nx~< z10S~D3pkg}{oe~5d+Y52$A#Mw`=|mQ68r0X_^ll^ z=Qzavsxzc&6Uqg4efUha4)vFYL=vsY5@5 zYK!cf-LS8|ihYHCFm{#Y2m9NMUyIibD+6yoa44$yv|VHL$Gt<~3;KAyexK_XqW9t=F#pWmAG7^n3g&3N&%p8Fp1#m*N~e{7b1llQ!R>dCU`h1zk^E68i= zsCa*Kr2S{`Iq~B5jCv^ZV_mOj&kvfXzJ{D*T&5qjit$z3)katRL(#`ZpRNl1?Zu4R zu(Is!QP`7(iaN-51AQMlC4S~cSG7g-n-#p5h?@@)N2?NV9&3&hssA$Ui`z5aT=w?Y;h*7(dXjeM4elY%ioCXPTlsGM(0Li2 z``97x={R!?_y&ZZpvR4wpnYpm)8(02=&>b_yd1q)()<5vyi(_F^2nu09oI1V8jE-F zmoJz{w*Ipj2m0}gvy7v8|DHrX55;;(>;hePv~#1<=NVY~XsJU2{|b4O#0B!yAz?of z*Oh&J)20roSL!-K^4zNJsKi0-dA`reem})FIX`eBszMhdCF+c@F6BHy-oLW{N8dRO z{uTQnO}Na*vOw1%W!Hp{;v%{ZX>d!t{$@z(kbtL; z`z~}N_anvnH7_$#C7-h-em^Jo6@KQBoTEdXZXfZ-0Qy@%evfP7ka6B{ACoLB&pT5E0`8TBgX%_mnda)4? zaQ|r*ezAU>Ggn;WKE4N^t#OUy`+qsE(e%C5i;cKOQ#;LZjVAb8;~L5LaeSsFt`R@C z{aX9#wZ3g_M_$UPlE{;YxD<5yI^%agK2{-`y3qA@d&m=`ms1kIgMO{vK+e6Y>Cy75 z`Atduj_(_M>g#nF8HwMaFUR_Vw(1@5v6WxOKbbR5G6y}l{yW-^Y>(qKaUAmx)$W?u z^|!J=JTwN$~fjEP)lgR@s$yeC; zOTxz{9@{DL*lI(6Qs1|r`bF{@q6d(B9q56B9&%ItvXXOEUb{@rchUL#`IFnxbSS31Gq>g?C&lUR9DGy9C zkG7sDwZf02zLmVj(BvhIGe`WT1YRX>Q%fu2{Mvp>o{yLHI;7MJH{1(-tFaRC8sz*k z>Ip;Y^yU2^n|yap+~v)aFX7)N=kj=5GoLH#_|f3O)~{H;F!qGKv%oMgb9 z!=s$yn6Y$ko?-sIzC8TNU!^M9QxayRhzH-N+5af-jx;dlw7YUN3tHw zu1Dw?10MzAAN~JfPY8VvxKF>cx}EmTIc=Rze);48ary<=q0BG#_wvc(T5jlgfXy$^ zUg^mSbnFzzCqEsj^X zc$`D-|Fq9-|5@q3u72kIt0d1GuA3adY%=)h5O|nJce%=p_+l4UKRF8DS-f!nlOv({ zk3SurY=7sBU)z@rxa!vmoo0taU1!*_%-Ex2VQh~k@YOS;@ZTGS)ApZ{@diJ8{1f-{ zDk3jjl10{^?})aeg~)D2aJDW!@TwFeVZp0P%emcH;y>jaU^Yb(9 zzaa<0cTXOQ`9tJ&E4@}fH=36?MvNEa)8|G)$wU5hc)Gy&o8{A;GM{gNUf&R$w*PbF z)6W$Dt@5c7>?%t92l*6f`SfoJj~##Oe7|n_^i#oS`~TOIPvuDVNBS4!sfKr~FZyux z5PG-&=?_=8x2Y`>FAlJmtp8%|y(T~CochS$6@RKxAGwWnO4vo_9BXCrKS_IY*f%y_ ziyf=$ckH#ze+>2C*n9k*tXkfmUT_@#w9oBt;#V6u$NYCJf95k%XEITJG@n-gFjUH& z4aql)e63^8kE)d32Wz=X%Xs16&6C@?KL>mlyFdSi`!`R%L_EgUi5Nec@ob*FQu}dn z9AnOS4BuaZojw-lNo@Z8obN9Zk2(MQB%WgO_$}?U#AD8fU*M2DiH!%G^L;#ymUv7& zPTOx1k8!)U9l4VF5!ZXT`bF{uE$1GnEt9tpAH2V*4t7-Raq57w=vVv!^j}HV^{dSl z;u^$l#UCwm?G(38-of+SUM2Me?9xNt5PdpK9c&&u{MB!;{|Q#R_@g29&ckxTvj^~3CC^bTPu>F^)smh{N&^<$PrmD$9?OUT7NQ2 z9e|uOWc|v4@u$C4y``PH>*JrU-h-b#80V#Lll{<{H%IDGi4Ukg{KYcYW6Ur8XP4tI z*A(^RF8lvFDn)(BUKjh%_z8~K&EOq7HLgn?F5^!DFL8VA&y31_#!=ut?Iq{y4y$hs z`{DoBBVceHr@XR8yeOV#*c z-N}-t0$HDzHTzX}kJXqj_HP{qPa$#d@rsVW_sBZL0611M{tEsk=YH*~a=xqVU!89U zj+Xv(y{`3_m7{h~-obh+SN&=A66mLk`VpV`cOveSk2Lqkiq7Xa7=!j>ym!br#c!ki z5m)#?jlBq;C+nYvBRvltvhG3NYpj3TSG``TjI4jkvrcF3^-ue%1K45I!Tf8kf9jU? zPqlN`Kh=Ga4|e@iZ=tH|Wjkg4Q=raS|5Vd?k@Qcw{;5;eF)`oi*SY?wN7g^#7qqUM z3f}1Yr!Q6UJ6h?K^-uWM_I|g_Yf0#ubt({t-A_0@&b-67z4APg=a#O#Z%xAQ|BCCM zzFvhdSpRgWI)R)p>u9pnjcNHlTvoFFN%m=%b2ae4bX+*YK9I5x66;yMGI>36e@qcy z1J8zDmB7t-+|lq`BO!GMt?Qq@H7Ro0u74WCKg%O$#}=s&{-&b7B>SB@PVkqL_nfo- zN&GV4Ab$OqlgF{o<=h{U8_V$z~5eiC{4Q^Ljir>fYKcHS)iHr6@Kx&G-}!;D8Y z&9BJc0~OX4jS{a%KBwVNS?|=?KMuLayeQXIHRv)c=Pw}#JB2PH=-tT4#<`WToXm`| z{>gWQUY?sAa8xgG#V|s?8Tp=(d4m5Nbna{VfNsuP|CEvSPi6M6ll4yldSfN?55H!Y z*EF8t-(YW@~oc`{SwD9dqp3M9B9(V4f;NRTnYaT zt8Wkc!dD+5e}MiL`elBh-xtLWya4^aIC)&=AN&bljg~w)mnPvWGhYom;39lw-am)0 zzC9d@{z~v=^zotD>PyHG!H*9;i#~>4tUd-G(cU8C5Pe()FNV$>(Z?SAo#^8r*i~fx zyy)XH`G!%(e|~>W`Z%af9%8?DH+V_x<%T}?UYdNVaeu5h@$D*fYw776ef;eaSL}<| ztB*hQ59jJ*CHlCGymOITAzqd2zZ=SWWbYq-Hu~80C(77sW<7FB^sx&+|NmScD}i58 zZz%Z}_-k#y_e0DyW%;^6kLT;-gl~*KR_+sloTF#?{@i(w=_=}Z5&QKg)yIxrrwaWh z>yd-har{^0`j4xhK|Uw?*bVgllTGqEC33e;oH^0Q>i?ZQgnTjU11-IFYWa#?I2wL? z1p2zIMIYCCUPPa^>f?ht??_z^asz+TQU5IYv_x(s`q=+x@mm`DxN^SSFmiaFz)=@C zE+RKt^|9gO7~dE0FJ7CxGTVS_H1RLgiU{AI@&Brk)b(4vc#eKEc#r7=y1Ae}w)+V+^f7gA9{%n)>kmBEMK$T;oX|l*)8l#i zcrO03eA~>QmM)w8Eay#pNn)at_j>}Q^=3jV!l>mF5 z@g{X{bzR?)ZtSnJ=s5O)>|=YNMm@DTAEjINS1D0PuH`EHF8iy%&+MNoP+B^x8!#YM(~ZfuRijUKT&Hu z?~%HqiuAK-@c4G<)D{2eT>n3hf5yJ4L)a~O*6)qr_hAYuKMI_M5;X_FD~lUoLR6&O_=vEBO1;5A8Ji0nQ57!}Q|TzvZ;@hWJI!VPCC# z@gC@=Dc<&aujk+3tb6ee;>D)k=awsEU7}t;vF^p=jdfT_-A_|L^Y7#P?Zk`iy2dN8 z(}0usmHqxA@#6EpxAp13ap87a;>G8~Z|m^p97jvMIEK^qo5YKUk6!!CM3!}7zY^>S z(UY}AjZK54TV@wQq(Pt?dX%X$dk5*5MyGZ z9iY{n!N!TUHGOK+F-DueVtBsSd6`*uS&998`v3et&wo&IbKdUzy04eteO=f6GU!9J zuIU%uX4|ujk47u&|J3#EQGF-v_q_gzFVk;+{bpy?kSI?)X&>Gj%SYJnX^*_|3GzF0W9wgA zhM$N+s*F3)KD;}1AD&G;;rYK)&j*g3aUWjcjpY$=He4UZ4|<5}QD2Juu*2;&mv50V z_)y;;=)SRhtM0=);OsT&pX#Nf=V<7B0Ph*zrR9y#SzourK4}-CqjQ|6u3M5#!TPn~ z=)G|NSoq%PD%NLt;M_{`=T+J%+vQ}gVWo~z`bV!g(nsFr@c$%kq~Dg;qvy912M53ZwkpqlD86f9A7Pd8Y*lGo z_h(7(80)&|$2~>%W0CjT@I>~KF+a|GYx!2r1FF|o?Qv`PIa(h$-nOd1xuV1aVSR0@ zYMd(yJ9@`O&s&Y^Yv1s%xl49)9qx~0-{RZKKSmDqeSstF3)Ft+t}7p5U2VVa59Ix> zanU?=Quo=F{5;sDW%5nQe#Qm#pZ*DB7*zfv2v<2)#6YL}W zy`7E)^jqL>eIHtu-@CobP`_R?$nUaL8P8rjhy1SUMR;!il=I+DUi=DY7kWNR@dy3lyfvq2j~?d{`(zOf1PM_ZgAqn?_B!? zddA7>{7x!-te=-)`}1N6T~BIZ7Rz(4Yx?7fQ{KsX%;>y{<$B%({$khY^+(8WMEoOv zd29Jrk+WMk*9QJcc&-i4S*N1&BEj=z`rKhP?Q&gVV2kx(<{^rY<=NsPp zgkhXUp6>h99$vmYYrbC_{qA?-#NXwg02ijqGw-k8j(*qWO!ADLPnGkT&WjK|FT&>= z=S4W+rk)p}c4ych&^Sz9=6Mm3ybODe;ej{C>~)U*zQ;`Rz<=`3kN94<-S%t^oNzeT zqKN#u!Ql+{8ji2v?C*Y$`jT=D@`A4E&x_xqm88S-(rKS>*7cQB`Ov7}xk2~c&fLDN z^!;dE7Xcn8)elko59y#E{&P#8L*Go#ko@GMn< ze}nvvBz7)KbFC*F`X?)yPlQn&_|y74`hA3Oy~HrT+rG;o{?K*uXk*IAY%5>EKB|=Z zrNr$y@G^@$J81{I1`qBm0ez> z>d%SyIRD4uxsI39pBuW*zs1()^e22yy(5RRjPp6I7d;HuG0V1$zuzv-@5An6oD;*| zS?;6$gzXgJV)T0`(eJzx--_-NlOBiPPX*_DM=weh!E61U3zKyNhFK^R-?Tr>!RfA! z2ict(cXtQ}VP%Q0^t~K;LPK^c9@n2c&{fjkb)(F%-mk0psUsJI!`>yVyXL#hEc6qy zvuS>(jl8-|Ddg4X<>a9PajX80ZVCMAaWYGV@zQF^@5@4`;Z({O!v@_KZb9E^-tTji z-rxE36T~a+9&{HOKkNRMv%7qVxU$i|do^ztozsKgTTwkZP5*YQpHP1u_OE^&_A{cV zP3ea(5&ez!3SUzDH0I^;f0Zw9-FpPwirPc}_LhH){;Hnm;nyNc8@|@g!)P%eL7BN82_(-;&V@Igs$oN z8CU(QY5NkR^W>Ibrw;4;;+|Q zyg4{mdP#6zKm%W{W`836UZm@9=vSBz8k-Ma@(ulwF4gzA6cpzih>qf^X#H5o_kQI| zP5E-y`04p#{z-W?d8sMqz(@XwEP^j4IHi0+j{JTaa%Y|9Tsyl5d$vsY!t=sB=umr| zr+n16LqBbv%7<|xwEIci5T))9_#Gx8Z{o=+++S$_JMVa0_JOyN{L%^brMSeghW!`i zBZ^nf!SbA!(N4(U;p>gqXaRbR;(_uA?cX?3-RaOSc|JX#CEBN((tSsapL$>8rRbcE zzLwqxT+oU8zFk4Ge+~!h3;q7Ty)U(86uTG0K3E11*;oD5XXZ5MpUG~{$frm@Xy5-` zUnBcB=ycN$+qyR7py9KYWF8}QYoK105yxM#?vk3PeA6wx)4 z-C1gPF72Jk?&^FspD1rczIDC^c9+t9S`PgR@mT5h`5M+cc8{#z>Z;s>@k{JS-T{aa@Zs#_!id_n5)B zS>io|ahCQQzxxipc&x)QZSN~Z;!po~--$P;{Ob`j$9+vltNsLzmN6PcRoTn}Er}Xz8UT(jXuE1VO-|_YG*OV*AYX-lUGEZ>;J&OD< zjcf5=;!2mLCHosa^h5A}7#B~@NyN6+keBKM{j`=;=^y7=y58|4_!)`0J!2lvJLaYm zhrpxuxv4FOa(r%@JukU+vzF!`J-}7q0I5CqRhx~r~Hi?ZEef;4&=&j!m^tJD$ zS($yV`g8X8G_R}Y4IL;!Pu*WCRCS&vu>ksVexC4|@=pB51!;f(+NAO2nev>ZoqHrvv3Gpu>(^-0PMO;ii55>q~!$iE|;uS=FtD} z{XVnnxg)nG#OYuhLi?CMc&>b_FGu1Unho1a>T{EJ^xCDJ2>-+1qnhqN+5f5WM1=oi z9pESWEcG}o^jktZ?`s*tPczhidVU7~=_jZ4pE~gCl+MsEgCl`oNxtkMm-gDN>>lX0 zQut5EaYj0{e_7-kjgR-Fv!l6{Kj z;rB81D^2`0x>C79{bGAo<;(b&XKH7<|I<-<2L1i-^M7Vl4yj*xY5M!vdqlr6gMPeR z`Wxe~X-=v_pA9rq*oP2+23 zfy!NOycmBSIv9`LY|A9S#KvEz{&1Y0=2wPx8I6a1_!k(pm>-KrOieBIw) z&2`wXnfUs0>2L70w5ZZYy;JNi`W+Do^X7HGGHk!$R|ew?zjGJ*mDb|Qmx;&JuPjpU zHrvm)*ZsP8?#a)kaCuMnG!48MO zLI3xxJDiMFB98`(t2Vgy>&tJTvJrc`adma4OG$rSJ3dK%8Lx=_P3FTXer1^FtILn` z`Zcfh_F2eJ?bz_nu3XHxD~Yqe|6|6vkbhP;ekJyw=%PPWezzp*Pdk34t$rx}TLJu0 zzY;FJ+Q5@($x_ktz)!Z}Pv$kA z$evrdl~sG{f12bMy74QKv#s(_zoKrBQ}8gne@@GN59oTmq1fFIjJpbp&QB}!+w>0Q zCvpif9a&wuI4P#y$1XtUpH{3^%8{Q|>=vF=79k6cRcSvOcf}F>E$lNqFDfY-uO!54 zt%B3cC$ySgvB>+an(sxsp3<3N zo)o{X({c{Ft@4i@nf7P7pG;&O{e9D<{3v;X{&l|QN3AFD<9g$Xd22F$IcE*@a^1NG z{!`9cQ^d=UCpy;9Z_2hcd9)^;XkAnE-%GB^``^Xa9K6Hq~M@m^y469 zeg2`{s_D8O>EL&tpi??B_%W@-H_U&ODE0S0X}2!V5ErB08z!G^SH28CLtIPD!|yEU z?;1O=so<9*hovt4CNB2$oVw_Fn^AjpWkl%+o=+{6PJKUWr_B)m{TEdpR>Q99cpc$t zB$v^3qUXQrIjAa+7P+TW_m8*qGM{6TCkIz_zki(HSs5>4x1oHa>*#l>V*HLwQJ^1x z|6q}M+AckhM1My&dwJyubVPAbCw%j;Z{=H-Qs>cx{zdblA#TLgFGrs6=eH|6iH|~h zGwQ9e%pt{TjX zg?ecE_RYFDBXdgyzq@m3-hRjfuN4<^>_64t3&+mn+WQMTYii%S$wR>ZkUrwj;N0Rc zzm{26@N~R0m)YL_JoYrhdkM^VKlXrr<|_A7|Bx+ijyO~8k^9)w#>x@wr7O5E=j42U zUd}1xRqibVIY;wL6Jn0QCR7#3{Ul^*v zKHz;t-Z#9PD+c57Kw@#q=K37hER>K#_&xJ%H!E(juG=d@S3>cisCd9QDfpcsPDgTX zGn{u+?g#&-;e>g$;*9k1vz6FWQRQD{9xjx>lcc_^`e)FA{G)cbUX>~|+U5G9R7vv- z0Ucbwi7v@vM*b?e9o>&`Qk+NEe7}!*ZRvH2ChbS#IHK2aE8Yq}t2+M32P(JH|8TsD z@)wL(w^wfEyJ%d}cHw{Yyv-=yRxyzCOyiRJ54<0>gS>C8kO!{kS3)|5lct|Hk%SfC z5A7Vp9-?s#P4M#!FLqX$H$;xnI5ER~jEwFUx4?VOI`PlN49A@g9oGs5zgx+;hCKOw zL;Msy2me0CwO0Hdkr!Rj(s|L+-*3L$dC{cQ_iByzlH4yAcsUx+LVJ&^z30@vWJ`to zn{-?Le5!OaKB3>_U;X)$#{9VLXg-;7x65^*H{#Lqv+^*7Sri0(GS{z&Bz+)ib%BSZ5G-d^akX0Iz~z6iDF_oi7#2?VW%ACX+} zM?dK24We}fAwLw+s#r^X9YHisOX!C-%fKIR@}bEGQ?03K7k+%&XyQN<2bwt0 z#DOLbG;yGb15F%g;y@DznmEwJfhG<#aiECXyQN<2bwt0#DOLbG;yGb15F%g;y@DznmEwJfhG<#aiEC< zO&nXyQN<2bwt0#DOLb zG;yGb15F%g;y@DznmEwJfhG<#aiECXyQN<2bwt0#DOLbG;yGb15F%g;y@DznmEwJfhG<#aiECXyQN<2bwt0#DOLbG;yGb z15F%g;y@DznmEwJfhG<#aiEC(zzd{_Agi^6-h{-+bn= z<)3`>S3kD!>fgBHL&miWF8ed3K9KKQEL zXB*Fb{bK_g`|fyr+vTMTb{xCuk(=+^@yT;zt8e<&zjfa6>WixV_x<6&Eq}}X?i=2D z*3X|`o4ft%onyThub6+d>x#aw-#c(J|D~tiwX6NR@y9R!{fl1n)~>JI>@NDnSs%T- z|FREQho1Uyhy2TqiEDm3yl~|mKPdH-|1-bzmm^PaeoN_=@o&xDf6{&ERbTq}5B{I{ zJD&OJ&*xvW=wmlOZou6IpI&jn^>Zf{KDue`4fZcS{jop#&iC`5$-nT4*SvJjz19al z`mHtH^IGP9_ULQYKlY~efBVRDnR8cP_1d>3zIW;S%uHeHZRb34|5xWvob&ueHy!`e zM}BwD+4r8ac=O4xe{I2*qi^};oD+L*y8qk%ndyJ)xr;uM1VrPMT(S0wyZ&*Nu!o;btvDZY*mAUU3P#w!--7v;fPoOV9qe4zy2!**KJwDWA-e_li%_4zpUq~_J6R)uf#kh|;a zW1uhdkXMOz!|&mo$Jelbm9f%ou2Deci8kNak+D_#{IeG z_>LUk-D8&uCjC#R%=Me$Q(Eaozr%Xq{|1-$XK6k8xXhYcs_rPXiqUO*2jS-|t%q`I zJ$1gM;7curd<#oUZd?++d=tnAIpknpSGu_0j!DXZU&tYm=Gse2hvA$(!TXVZ_K3S| z!WQH?WbLt#Z~Ke(cIb|t_qV@jZMRz_VXpKZ_FAN~y=HH>q4V%kIY2#~?N)XVd~Zu- z?1R`>eD*ro>mj#}Qs=Nu*(tMEmC(18*!#1{cR@z>TG)4Zzy4jwpCSFeiXMf}CzXp= znnvC3t&S@7w@M;GztBt3eion;Ik-X@_P@=Lfe91+i*P5ztKnIh%q~ZyFa1xiC}9`k zEtO&weLQ@LjMEPZ--~rhZ9lE14Cj>-^h;*jb|C{l=U$fG!}s7q`ULiJhvEzT>1oZP z_vlf#RC=9OB9sjpLdeLL)w_*2DVqn<5V58s(uPXRg9>oLWt zB`^=_$@=xghdt5yI)`aDq9gjA`^GR#p-c{YaWT|hD5L(g8TnNc&~3zNpYLPP^E`Zv zDLuT`BlOobkeligcI5Mu>yQsAU!PjgCs{X9Wn2pFr$?;cobZtE+{=7@O3mGkKEcoM zdH>wqzCNYQ3%!SP;L+@Yy&e5A4zG~|(AzfK&hA03QNL1&yOC$3{Wil{J5dBL4Dj2= zw^2F4mv|>QVl#TA!5=Rs-}UdKk5lePI5o>k8#O1%c$JX@IgwejGub^^^bXuOr(o3U zpJnTN;Li;2&C2o|e4Od|Eu9&u(VwK!0be8f@_Iin)9&Byzi&*t4^Gey^6IeU0R5Y# zc86T76!gNMx_(a?SNl?lHwi(4Jhe89qb*54w-B34JuOZ=A@`uT+Kcl<&Qx;?}6fl#U|(oMl?i?&mr6 zcMg}Zx6Z0DZ1Vn;cDBq7-fL6)adkX}ep~6O^D(xyrv8w1#e~K8Fa4*C(2q{-N6zPC za=7Hn)hpJp&rm*XhIi?NnZyo}lY<_s9io?UwZkIz5XvvEc9=y52dNQPmgqi|CI`@vl;`q3TZLdVNP$o>l!DNzK>sgmLIv9oJ*u25<`^ zu~ljN1;x*BJgz@qe!{3h*No5qFa16?rQfO1>UE`jT;eaya%v9ay^b63HU82P9~To_ zxOT8>_2(Sqa0Y)a6??oog58;lKj=k-SE0xyZcO#yT@%#O7h7!9 zu($r$g_H@N&&F?S;r>eSiWj2x>{#ZHi{OwQEBNR$4I?tR{&SM68 zElC-B6LBDNy?vgEoESgUe=fDi=5DTY$gNw)LHIRK-kZv_h}CVrQ^Wimf2%e4Bd-JB zkzeA2qW(1k&FJ_lhVy}mY(f?<<~`bj&a=v;N&Q)h{7Tqmx8?J{rAspVJia%~4^P04 z;XcRbPurvC2JujYlcC((y6|V{k91d)C(y6fB|mCCQ4n#IF3YE*`$U$DB|$q8&bIq} zLBHhk^a)e(6+Sqv;&qqM2k7p`kIzub<$)g`win@soWEO&f?qK}d_n({hPgxiL|M0q z`}iN>edPHu#pm`O-b0TPdYw~0NOnwENMm8O>M|b6V5vHujY-FrTbv^OXpcSUj8_TU zTkdm;j>uI568C5ae?0Hz@z;#n)(P}Y-mz15a^Dy%__N_MO=@j4HrSX#k zUZ-|Fmok;_sU8=7mqbsGi+m+D6qM<8!F}_x;JRx=aNV;hD0?>t_lI_in}gn!^xtWr zpXnQo3Fxq>w+6oksMm|r-^8`XX83Py3*xQR=yR!}A7}afwq`lsOCh%>ls@EdrFZ>D z%7r{h^|}^xCVF~Zr8hMcl<9TBee<&5x@$vl-Lokudp8I7r_d+c<)~w-JkmE^d>M3G z)SrQ_0qPgZ@HzBeck#2dXWiMWX}#YG#+ip$Gb=Upqb>*)|I|eHYhz)`QsEOa$S)mHJ{RM%Maz6#?$8qZ9Muy2*{Y=zlWkhsF}YLA4E3j$`SO$W+8)w9ieHZ67JSDvSD?unCe&C?R5<;M%ewM3C>z6_vut# zC?5iM8D9_IL7oY_>Jji6^8Ne}Wxq*&h&)Q-7DwYBV`e+|7UepTa;h_3^^J?TUFn4H&}ihJ~q ze8E9KAJuCzE=e8dq}K%h8~9U~cW6J2`mKj2kn`|a#2p@SQOjm$uc*Hl($kw|JX9R0 zUo-v~VlTm8Lcb#UPP5O*ZhJP1pP%U+lOp}M2l=i@e+Jd>@Z+Dr?-&g1t$yFqaTh)f zj7!m+Y)9rJ6GFQopCqJDEZfI#_<`QR?}0qyIrR_ae0lPoPdD%Nx<&0z{XNE2^mZuM ztNF^Pp9!r$@B5dbAL2bWkyCnGg8IVz>eO*V%-03uNY|CYdp$S$Wxc)L4+hU8`lZ#^ z14(oT2O|s}266hv+x&`+VnpUk(vn(Rj%FfgHkq zytK6T$rsT3lS^uyH8Ux#+CFk4k4^qT^8uNo6V-$)QTp}%3UCwrlwqZ}MNVp2BTqQY z{p{ra$>00-G@$)Zzas2MUC%?ki1cP9dXz_B2ecpXA=IBppQ3(5`Xejphti|{!2Y~N z>SsgOqAB`bmwy=Vgmg!Kd&7?p{Pt+vZ`f_FqJGcG!CGAX-r;kLVSI&OQu6itxQ?gN z^#$yY_ItMB&#M1|A5o;=U0;-9iR+#_Md#CoX#YhIGZ+@qXp+6w^*M?k!+M8*Bj?A|1@DI zWNUAa;aN%9+SfCpafp~VNzoShn%>8LzNYtG@aHU<>*V3DQTXSH40&966L>)$SnVc9 znn?XJ^sCLV|79Z6s@J~XCyVp$PK$g~Z_#lbaHl^{K8JWHy!I4V;d4iCp7{>svjo4y zfsSZirJm0T^|VL&{rq2@&!Ik@vH$X;35$M&{ok5AA)41ie*doi+19gqj6*fmk8R*D zbVhv8_t2}a>2sA2`ctIe-e5I|CpA7p|79@rr>4+d??;c>@8%5IFq)Iy1^Cq?*J>V4 zdIkNZUSm`3vx2;P@^YY>ly<`Q{m@I^tTvIwPgXutiWS5yhG9Oh{?&%Xk~mbrA6#nT z_cPuv#r{=ZR;J(0`u+3Ahu{CVFPXl-_cHlbw`bokg{~#Y2R=peG1Pyu;nTugZKuie zu-_ZDnYFvPHjvYPkNZ(vAGYg-^`*4FqSkwQc}MjjAYb10qO2cx#B^S}gg?@gbNul# z@?*pL@h5BhYntzLeyM(aWPb_eCwwOldP4nT=vwN!d(~uj~VnbvfqdwFQ30&?Jn>wt^6&b4=2qXX5w(^+Eh2&2LM4S@2J%<{4&@ zXHfgKG=8L9ioKLjOCOi;+YM)4xk@{O+_&*x2hj)g8GV?m{!@cKFI~2<$rTyq=V*6D zuJwfJw>!J+k-yaY1^OA@uj}blyZ45={Bh?DWux89oU#plGrXVbx%*0EOmW-cJ>(wd z3%GyP#Xb1xs+T$XL%cDbBi|V2jiP=s57tpO$uBK+e0`7j0=~4DvDXG2URT*guDu0c z&QX4e_;!9E|AH^yC~q;<|BC#rMt#yhYs2Ea!-KX2^GuXCXhO^4{kAD^@)ZJF64rH8 zdEQ+G=h6EpKNQ8~QQk1T-*@$)+e;bb7v3jM#21SMKoakYK zx~$)gJ$lX&)#Ju@_a?xPN#EsnR9j`_BEHMCioMhf;+&-+E=T!+rGY(3cz>|vBM+z_ zwJdha1LNTM9PgQBW%}PC-}C2VB;k-RZRlIVLhtge($Vi!_g2y0nd%Si$kP0%>-#Co z%U)bIXr45KJi_nDZ_sZ;oITKODIdJsHBO4|k9gt#FF{ zuPkFf5w4EvJPCY3|IaP!cOl+x)%*73^#snUGV;cs7%mHWWAxdd{|Nnpqk#ZrIj{1tR;zs_<+Dx^`N?1|h!-_}tdh4MC^*GD{SWU)e(;Mc&`;I775YA9q@Ncc zuk2*IuB|I8-xI`_LOt@hA7{!1d}pC=!a5^cpR?{LPdSAD0N*8Ju?~sn=Ies{T~`M0 zWp4DJzjIr4{+QBr{s;RtPkha`+Waw>@78VO8a`h58Qx3EIm-(D`)u;oXJ@Q^@J*~` zmio_<-fX$Tb!rpWl`6mxZibE z@LuMoe%FmjgU%22yM@>!I`8Bfxn6iL?4e?_{aSaG<<^X8 z^flxvuPGOq$Cp1to~jq7?Z@e%oa`0IRi6*Jfm|c`h5FyXL3@4KNyrYRrv`t9;F}9w zb$SB6Vb7P8RjwDpKlCr++mrg8zCT1iJieduom@yia`F26rZeZYeW?&{zUzmI=+YfT7CVYtBw>;>EG{^9oEJ4 zuXI&!;;{?e@f_`@Ukv6~Qfhz1M=S2WUS3puD_o&C-M4JFyB9u8|Ly>Jcl0y-E*kec zR@{Aqy&+luuAz6{o6G2TQoe-VvF=SuZ}D*}(l6D!DmZgSy^|};7V+H~`?2z^vRTLX z(p74&^rN`f!atw(UFwwnNBxi$E8k`hN&UMRNkzYOOcW%M5dl4_oM2Xo02CG2hllqY`YzX~zl;BKO&R&hfHmajVFofou1Ee<->>n#_s8TZnAaF6d5S~riTmsW ziaSw!AJRX3j_b$w_4{l19-QtQI{&&O;Ec7bn%(X~=PvSzHP#cZ@%%h@V$|cg>YIJN z=Bb&ly}nF;5~KDFNAk*N?*{dc!KoX|F3pDRMc3q;uzT%C@I0p1)E`~LFXoxZJ86l1 z!mf;q+*sFpQ`u>i>Y6I}pngf=U1f)Ut?~T0nR;vcZJi&tHwAnOo+tDHhPZ zb^Mz8eIzHoe^(hTiJnK_r~G;*kAu#;%a*=ZdbjGUa{+X@hPYbhS>F=Mo%J#ADZ9ue z97l;!JGA?eFB785krpA46a;ko>LGKIPUsjNv zs;6fc{B@-%;sIUvDh}g5a;w|HR9p+M`W{3g@HTp}xopu+;xkfoAv26u`0g$CI_7coyBvCIcpp-~G5Sst_liI7 zI*|48yzlH>{$BL-n@v=odi=By)5^`AVe0PNRWXq$aou{;) zA5r@=(A$GWe;iD_!1uG3KVID-inE20vIW|lR~X-sWtGQyg$H*a?}mK5EgJvGJudS+ z%x`s#<#e70yT7Asqi5T>k6gIFaXtM=%jMuD`2<~Wf!#*&qoa9|68^R7O<{80z}c$& zz<#!tJ?NX-pJj#8&g|s;bL~#GGmS_6{w$Hi3uaPgEv7#Ot;ZZIBd_!_`h&hwKDfg~ zZR&BLeV5Pwd-CWp^6aKRyH#I2?rVRz?=U=e)1L!L^kH*trv+X>zwRr@i6zx6?Jq+9 z;N-~T9-M>nTS@@T@Q(Wvy7G#5QVSd&h z7y1_j>s*$`dcpb0IFkE(*#Q?6=ZfG-5q}AM0DnI3=ZBWN6C+jRvE2Rch(-I$Ja8;I zNp8h2s-H0($A+pq;0yTiMa84odByP^Hn@CV(VsV-B=nebQahVN{?M09AXG?or&9_KydBN8c-owutl#R=a)ZbOWK9o-n!Y6P={Ril7H@t_` zUK{;!i#i_8hEIDLCkD=YytD`YS!=B9a=y2yO4kz(wRnZSrnXc1vidXF2kYKwe~op; za_WoT8`t-2_!B;l{Mdx%{T!vkWxS`-)Yq8rNyz%uo_$d5_17#7!~0v!H-fic^79AU zzYKgdoP*{3WPNo1O5@Mj%dFB454kS)N_z^#i_`j70B>}hR=iO>v%jkT#Pt609`!`; zMg5yrPU&Anuc7@ff&&Ki=ipQ5*VxKuYcl@Z539WqXFOcC&@1^2b_7l&zJT8XJ_-Iv zmir0j50SeJO6EcOO}$>(!w(Am)0AF2u8imB#qo&$(_+4T2KaM~T>u+TwgLYZepHq6wC$*ofH?fQ8Pebpl zuj~EU3$y5RT$V1_P}&1sR<~qTpHFt}YCyF%^fOznH~ zrFY!ryBXFCoTmNv4b`yEZtLSirc7!d9JG;V7dR-)t1Wa(d!eI$`FLrM(zAknNAR`5 zx8gT7UlUV)@cwLlAO7{}``XVH;w-0r?1J~`?+O`NPJdIe-Lli8oyhP0<=@HHT&pzv z>A>Gyu?)G{8rKxR?fXaCj@RHjIOQmwq{dVJJ}kplo>wgG z$S_~K+%4_N`u%)*RSCPasE2l)t2xlY^oG1XRZBlj=m z5`5||dAi?^d^hWCC-=iD>$uUjK;^^usr=>||C#&f!2C^<#$Ku*J;}Sp8A7E)cysu4-U>++f&_9^xOZQ;;8XTb6ov)$_Let zZ?x}KH6JARlu8BkEj2h+T8|LH$!FAGlkMCW=CcOJj;vqDdwrHv3(T`A?o)5Xcl7a| zRVBu=obs3X79$JaxwaVhs+0Y5`=2zfZM2sv1>>y8ed@2bmpZb(hj=6WUiw6;=!Lb0 zcCy+pmwqLt(E+LdUan!jb${OZp~{Ex?T7w2K1H7C*yE+0r@UYLSJms8{Rs1at6X9l z4^@fFG#;|hZ@N^qCXY|fzXf~^yAf;cy=aW3|53|Nlu#|;K?F7b46Kk6LCxoM4m z(1-Re@C3Qf9OrsJ(Rm8u+}lVksD8cR+eIVJ#V>C7HI9yRIkn%?FUr&}J?i&N)?52$ zI!}Xr{mhRum#Lj1gk@@{jGtTn9{MNiUGYW5BjbY76gwp@bd-Ok7t1cI8P}?v`XzQc zxjp&0pHIKXD-|->Lp{!QxKF#=x$j~>XNq%uyCKe1e*t@I=&5%i%!mEbpO>B5AMo(h zI5%_B?@#D=;3p8bvwwUU{Xst9*Ga!W%jr*vR+giu=49M)qyi4fJq3S#W+ToOqkQv#$o-(x&r! zeE+7E;0$_&KhJ#Tww$*kr{izxTPusIC-wXG4&>fwFYuRUrrS$bO33|J(7g)#K@Zz2 z;8la}eVs??&s1D!(Cy8xRDJs1w5q86uG3eidsW6C2crJe=?>Zp=x)T*g*g@a8OedT zeQpIUP0C-ho{DwD!nq1I3RaK*$%8R|ME9Y8pn~4~_Mk(a_!Rr=syO7WRG#!x><#|< z3e{ANv-z&8Vu6cO^gbOM$BrlCYHdL!hdih0y~cTdey6+QX*_`5=a}D6y>}y;MH>IT>^w;$f6-epeJ-3;smA&K zZ{Tx-pSJQDc_cO8cp5%$RzA~iLmz5Oel?#>OZEE9e9rV&T=ZZ@K4<$?FJ|Vmx3uDb zBO$&hpD*b-g^#{|PUiC^2TqZL&u7PdFrJ(Yuo>$4e{Cwc>{DSvs`d1pv#GcKt4{yHd=>CwC^B+=CGoE6izF(Z-nZLzTp}+0ji8@mR&4EefM2F_#RY0dIu6zxJ{o=Wf}=J4-dtD7 zDNZxrlF@z#*Ezk;wTi7JesX<&V(R=xIIlOjEZ@K1g5Ifmb%6X}m3iF(x%Q|zd3?2B zRk6S!NDAYkYqcNs?|Gnc5&iS;M|r$x-Gb}`QItO}aZwfh$w+3u=lhx0Rto<5my0UU z-KpzeT;!F&KLQ`3byx|Fi)@}RE3p2BcB6UasDIdj&XY&LA;K#=M z*$;?)VgDK@n$G=i(eZ1;a!DUjI_mWW>yF8!2lH^@KFAKerXFvw7Hb93( zy(REufO^5}*wE;;#wL_$+WNDg-_zD7M*I9^EZCoz*d6RwOpOO+`ap2sd_1`Bnh36Y zo(;<07lZp#=!^2$(0S9voOlPFtj~kq0qVCXqj|TX(d#aL5j>u{-YwLFgzhr{KgDpa zuH+|=&+;~%-^PD^o7%0I%l&z3>7umY#~}G5)!Q@a6Q_0f`S<#J;rjSc?_=19p5ws0 zou5BV7|w=@OXcE&9~~jwGF?*brP-1@|NZ~BRpv6rSp!8#rTv-zmsIGK7Xf=BO#x;e~o>> zr{|qV!9VD^M*ZHCT7Qn_R-k#8Oq6ck?-sNh`q6r^~a^tt}D|# zf3V(c%KEa=N5Mb8{p#aDyp_y=9Ywb*^i|DJfwkWCfvvHqUNdt68Fwd;FDeb2tRg52xxm9#$O9@ZD( zTHnB~cOA_rF3)0|RXr%ZOTQC6Z>5T!>bWen$$D+Sx8k91cUbRC+2r9?cyb_*UY+M< z_gI+8noMp*LGd=YZ|ME3-na8B@RzHIvg-1m)B18JBtD;B|E()ZiAnW$i(A0%(m!PWh4#$<^!dGVnOFU^w8~>^?AWu|IqiQy z=Yfn&kKv&&b^H(UeA4p~4;+hGj0ZXDoBrH5R3eXJ>+{C=NWCM6viN&B9arFIE9VuV z$9=1MWIOy#m=A;N*v~Nc6?e83r64U5U&+3IQ^!f~LzN8rGv&Sbwv3GBlz#b$>Z!rF zy06%(IP?+!{lvraupqbLqNn-LsDAx!dzJbBM3H$~__GH4@}M_tzwf-qWe;>rvfDqX zMzGsZE#IKTTzq) zS>&~RufBoAsQP7z zQIAsnIeV*)=d2IfS}7@x+1rkqz8|v`x?jecJUzo4hiuX_HluwCO>Q9F0(Z=F8{IiUKttPt4m z0Q{*bJ@DJXj_drH_TCleAYaoNxw~RQ-)Q0!NAudx>?aiGt-&h&Qu_|Bb9$XS^Lod~ zt_CkkqtCQ&*q_w6gt+yS74&X!E&gk!Ro9`Oy#u*O=)bky!TCWh`W&q%i^ipB9hmaZ zo;-h5_#YJ~F2iTnGNbu~bhhkf-!k7Xlj;cd76yq|9p>Q&@$31Hcwv{ukup%gZb-{5 zC+|gnJ7cNph^=zTARpr9@crn$JM=x79QVs-G`_Y5n(jo^<3mHgY!Z{T;aLD zkC<)6qJCd}ybb$d$j4bP9+!^~7ww1g;5~MJ(8G>bTFhgUFE9?&K5K$!E75>fI0m~mYD6Zx%EOWYLKRQ?A3ZcN81=$zwiysuIK_tjrV?vgmYziz0%o~50- ze;uCJ7}8&FH}uaN_FMbYiih2Y{`youy|EtM{=Dil`sY@V8~S(u(Tw6!_Wnu^{?_B9 z;Ci|rQ*Ak+{fpv=NMAxeymLVJwYAF90q67IK<{LCs>gNU*L^)bZjsVi*W>cFj1Kj< z=!1-H=<(N8-+ft+zs|a_*}sq8{E44G*tIEmKlGCvtsi@qZEkKS{fO+@8mN8o8y@vt zz&hRn=YgKjdRv$Hd+mg?SNR>%Id_dMFXV#zdkV<+eDU{ROSJE{XIZdswU=`$vV51Z z{p%UewP@^f=ug5==q4_2)x2S8hh>QKl|K_bA0v_*9FeMT7xn=^k99}1-&Vd-$+aSv zi@#Js5AiR*6v)N=vx=+vJ;epZ-{AVcE*JYN-vFPGORsA~*L^*`uJY4a*Xw%pcXX)N ztx=9`VBa(Hy8ANrLsJ$u`}gsS{?gAI@7ff+AIim3xu`s*$))(vH*EME%EeQ;Q2)!2 zi@%Q#YTzG~PIK-@LoR=utf_w2<&xDr;mF7SoVXNv zBm0FVRr(oId6?91IDf6zMBtMgnj+<3z^Xx>n&S0l=haOb3vgxVzo*^ z*Bv?FT6o?O=L>-!G1>7;&JXj5C%YcHCpedYb{y7s#&&~;jDy{Zhv4Uw@1E4}zz@Fr zWQuyDbxqPe#U4XCqxUXK z^PU*bUeG*-;8z9bN_mGXqWXF1Bbu*ge0fCkQNM1y5!DNRG2hJiYslA>pXk@ubi6pJ z{#8}=hWMojd21*w+EITZ@B7vMcVfsBl|1y0d5;|h|K_dt9;+0&W`ELMRn8wRIA1@C z+~z&vd|mNQ?eZ=c``l$euKxSH*u{@mEdRcDSC#M1#~-Bs)caJWp!|~WsQtB!drutA zaBkQ7N1mu;eEZJdmE*gj^Npi<>Um_#H#84S{n@)L>Uqe1@+ke97rW$1%`0%yr9%3O?ngIel*h~7t^qjmRFPS*{#%Plz<{7TD5a;}9OW~zTM81JTzw{`oH z4gR@}l3-n&+DU4YpVwi32=kTbqdDfU8x;y%lbI%CK^wt){p*u+dro) zak)H*-Eh9DU&_*j@@%F>#(wK>u^Z-b)X%qR*Fc}a*OqMsQ9nCYxV+Pk!>9N^F;>g# zxudcoI1en@&3Rz(J+hN%-vM+5>+|D0&+|Ou^9<$O^&`hCRs4%#;!TtI!;t4RpK3bB za}{tT^24Gylm7bWighA^8dmx8^J&le{OnvuJ}n2H7^Q!&nDi&ir$zS-!>ei@xMPU- zZ17F5tBRN2zgMu6dOqz{nonb$b3LDyX5S~1aVr>x6vTWPh#rtgbtfcRWKr zjefE|!Oy3?QuAqyXa8;aG!Vo_Uslq87hG9KK5YWFPRXZ<=F|N9+ota4^!xqamroml zKKK&SSI?KNBcC>g{Ab9gLGN`JU#8FR^v@%)qI1PUyKCU6^JASyY8kWt!^ge#_J35c z1MnxrL#gRGfAb!ZS|#h_Scr#S?Pv-7j2)_}AIbXx9!{|va2uQ^pEPbiAK>Bo=TF5$ z`N>i6YThHUpHxcVW*rZ`pB%No;n?AyRBRt713a9e{)S&`|J0w4jKWSS1@*MRiEPq}y-ELL) zYCAL46WX`ca-mbSL^h<+e;udl?+5wDXg_CCRyswq@jNN3e1AYXz)g#FaUJZJFF^Oy zeUWMQr>Q=tmi7BM_-pQqysNF)zfbA1zR<6@yQ8htzs~_*haT%!e2>;&4eP!S?E9`Z z_U~oUPitAQUoxZn`x5p2dP(OZKaP`5=mrm?eS1^)`R&kps?;;X{y{lk_g$W5zhy`0 zzo$a~y*)LyLpcA-fIh}0iTv`=PoL@Bxz*Qyx#Ji(6P-VIQss}|z?!skgXg0FJouhSoAE<6;<>Sh z<{c~PajLO5959o7f1cxl%kfw$H{z*2YaWf#kOjx#Kj$X1pM^5~eS}C4m$uuokNRW` zet6`)4qw9l4EQ5=Z_s#v6*8O)Pc?J(+%NJXdd@v`8nc;qw|MQIjK5AM(J_`;Kc@bR zx!^c->blLn7Wy|fMm$J)_io}t%EEY$zb|&zfgaZ-e-WPZYw0=C9`&Ux?<`a?t9r*pzN zz!F#70rwUi_q60bbWAUuCC6#^H20mS-RbWmhagU^>-mr$r}niEIeuK43gXhyH(V|+ zs9vBv{(iu2^*6W<^*DZ_6F(UK8SKNkpYxBU-#KXWJd*P^5k21>z1dQ}0vtgv4w}s4 zr8s9N2cI1Dr7yxi4u>SNck zzZJRF_qPrO`)}W|tu%j(_CIlUzJFf@`Zuk9)p7+k5mqy${Yt z-=UY8J$#px_c;Fk`bFraNqeE*&GGe&`2Ztx>(gp~U8cWpATGCD>pHw=vX4OZIdP?* z*B|V1ERIhKb%;q|n# zHwW&qA2D_yH&Ug2)^G33((f+ToiGj>huaB1I`+^4gw)9-h@y;bPxci1mw$dRR1{Mjt~SNh)U?DC*1Jhy^8 z)T@tM^jq%s*TL7XvwE$196q-Cf4z_W*MGl4yf+-Tv>*1p$8D9L-Thrph&5=i+}$NWl(=o=okH#rP#N_IGI|Be}P;E)lQK^ zG|o&Kr}dn(MB%NMAH!bwy$k%3xLlpaZawC&Vm-ML=#<&mUkSVGGO<7MNK`Vb zEpnopbNuLk%YxL_?a0}9>13zQA6T!Ovvr4seRVrNJ&Ep&{Q~-qTztQ;Pv5KZ-ihHKDitN{C+QdOFU8MuHBQ}>DR_+Y{0`3x(DS6?i-#U{NuO)+9`!vB{Sr&} z>HcZXg}}aiy$YVM3veuY-&DCGCy@{JyMn$w^w8UmsXiy}^v}m&p9bgdv0re3_5p*}-$$I*``yWki7kH=p0{hGwx=l||8^o9Lq{yN!C&9~K%V|UH-?O-wYJ;*zJ zomb4W-%|Y;rCa?NC1asfb)78x4t+m{JRa+2>7Tnv{QUGiS$}_P%g67^te;T*DBZ07 zfbQ2)f5upX{gv>44DagWuHx67>ms0+10)9fi zVUIT-&!OiH{@r-orJGawIkjJg^3TC5`ETZ5)Xr4?Mf4}OZm@S1(W?cPxgC1A&g{aD zVhgghJz4d4&0yVFIzt=>e?uI2b^4z^bd2kMwFB&=KJMFb|D160Lhm{5=zP(oxBLJc zF)oRJ^PrQEd?)cOdYaVVJ3x=4IINx*Q#?^SupbHI2rI8R$-bA&{yh4=t?K{I2)H{^ z-q|8|{qLuJe=IF;4))E)IBy@jzhZ%z+)jJapT_TMCEdRBy-!+<;~H03+z;cwI=)3X z7nYlq&MJAQGt&7ybfRuX?gQFi@?69_N~eT=Ye?rs#OGCh&q?V7f54d;=sfcNCv)&c z>BOGSL}%Tvjq-Sd@DF|wuiXE%&F{H=igqpNsmtxskzwv9ZQ zr5@xMwEH=~-8OAEr*e$ib^Z9#vim;%WETAi+toNy*V(K7>Hg`Yknd2sLis1<)#wfH zcQXFbpU5wj1aXCf-%ecW)yQ}5D(pI@e3VV(fx&O9$9UA^(r|ViukqdQ-{1)#|!XdP`D400|va*67T{M-)V_lanqF!3q> zybC5Ii$(G|v-o|YDt2qwJC0l6?mT{vh z@PmyDpEzEFZ|UC>SMk(YPhNq3y>zeRz=t+HFTIN2rSn$ENep-Aaqdf6+Vx!MM4I0r z@>IWS0WL_f?);fEwH^Yf$ApJJ}qvi*~ zaUspPkRyBNkE>)a7VGcNp+Cs)pv!&D4`iX!oe+QiH_Q{vVqCa{^F8YE{0#B#vKV>` zt~B(v8vJgO>M8PC_7d}C(93+^ZBN7ZM2{Ks(9cAyCpD7QbA3+r*V@d>@h|DeU|{#N zq1<0@6x#bN)!z*J`3hb49jl@L$}cBY_t$1^-B8$-Psnd3zOwgNmEY;wy2;y>XTA7> zsc3$3N#|qW z9sCNuDZrcglNr}%}86ZaplYWtQv&v&sU_HInNPyNxnQ0NDL!~gvR_InHw zpQ22(*XI^_Z>pcz#Xjc}dOsBUk(`68zjwv_<3`str0ys7;3qoJ--~|;KTZzo`J$Yw zybAx2x5eEY_!;+Y_VZPQeomstb~Im_=&Csyhj-?#2KU%!AKT>b7mOYLpPru&>ry|6cue&jy=Y(M z2Kv4ziyz6lWA%fw_*0?()4GIw80%)oy1^$0`l7r^gim1{+^6%&8F1+Owm*9^kDsaI zT_z?QTAZZ*P8M?cv*Uuiz%Q3}qf)vRr)V$CHy~-z_2&^@Mfg*Xr&_a~zwf;MJAQc| ze_Fwn10~v@7yKSzD+1Jcv{rCV_xpF6_+QAU;eVMet1^t=)<+zd_FMUZkV84ngEF(C zc4>9nExJD``p#0ntptvDXIoa8?BfmVn|eQ?_p@&$$O z@+Q-8U%u+&WgYi#32=YmrXWwbD8PO2A6v`_a7iK?h|BdR|bbT5kjzjOmJW5RM z*&(gdo%8hfKHFm(&?CmjNRL8)dYT@E{`5?G6v-7o`my8K<*YI1@UeW0=7Wqw7Sf81 z1-KH%MJe(*dOnh_d(wR#s{bB#km|NQH_P~X_$|ao(7n?2&tpYjg7|2G#z!&cSFgrj zLBAFh$9Lqxg}Ppk+v|tGxn;Zk{B}am*QTE6cTE$Q_L)r3H z;urA43UE)1;#0>n=v^2m+REnw#xlS33daKP9~^y3^JTM~cgRE7nXTvVpwEWkJaydW zy$@bd+R67a4(?d+V;_Ev;$t)pc6qGxr+Z3wo^o;U`xwSj+Tnd;K`H!wj3BOTUG#W% z{btrBh3DBZuGqV%uWdo0xV^x>&aE3<9XGi4wwJiRdxPk>!*z9gf!|x)x*@l#$T?sO z3hwq2bnmYH{W0x_#v?`jj(Eg{Pa(d{deHm(V?}V>xhEK3Lfo$B&2{`J(a)ve6zwK0 z+zlK4h53Mbys$cnv(5`g@q6e>v@UFV)}7YrZXvpU!(J zSnt?~pZ-ndHe(z+wg2HY@zW1=9BjlfowCn_e;UUi--bVE`u-sC(?361#4f`)#!&wd zz4$N0PyhC07Co-VPs6egd*T;joP&kQ?FRZ_*?s@|q~b`}uFCnKh5f(W_-UTnQw!S& zz-936t(q6C(SBls6w%^%ml^kH9pDkSN^$GPjLy@@?gIf1?ZW@bLf0toSK-%zpzKip zro?-*@!RQ7BVNe=fh`k70#{Wo)|8Yj*%D@|l-*Y4T zCZRuf6|*O@;AM3|$H`ls*#7FDM_lhctR!x!_KYjpzb4k3tFQ+P$Y(A0Ij41bnf3U{ zdt(oFioSwht-k8$-ihC%<;Yq6Vi4(kSv`JY{A+6`8o5gpx24K(>Uk`cnDJZGn&qL6 z=ME(v4Gu7FHCTaOz~gXE$7LJgZPfD?-Z&0w^lO*E+pF^^*%?pl&KjOBUoQDCS(odz z&Q!qb{ky;qe>&eS`vfpDZFSosu{9T^!IzCE#TH>p2 zVn*OilIMd?Y@V-iT(q}a_It5$2b+h>I613_Y3Gk(! zfUoQ8nw8nt&>3Rf+q7QNcH!lh_<9_dug1>t!0-K2@E>yDjJI=$@$S_5Zfy_6ai)g+ zZ8IKNrzQN|@l}(b@>4V5s}T=s&?64O{YB;z{|SG@Aur(9;@XD(QraH@UNfIbna^E} z%gm$AW3)UPTy&zs{9T&O1$p?#oPX_haqcbz=X8y;Uk%^!`*4VU;r!^ec})+|BO))Y z9Jl(bhrG4m$;h`QB0tN#7ssD`;!nu8M{_GqxYQ+y+$>U_(AAp}IiWhT+Rq9c*a-R&vG$PhBYHLerPTXHj(O1S_MPPSs2^~%Em2ndNt;I{zgC4WT=J*^ z^>fbNT#)0vyLJ{ItT@CCK6&X0thZ@WA^@&NoP}DOVq69O&K4W&$1yd?99t{Q8nV`d#cQ@Hm7V$ttB> zUrBxYt8xw$_)YZ_M^MOX@&9u?w)vxh0QpZIaKOY7+*%x=IZojI%1nj$NP)OOh4zg- zxpvcE4V)1yJpo=M4tNMT(vmn#9tXVKziIdc__2A(4zW8G@?ao} z^tm-_YWPe%{g;vKH_bkH+d}Xb`v+I!AHYA(KoA`a$n*4<$U}gy2ZFNf=b2u&H+TIj zk_RkaHN$<@ZPoHOL)iBoaVqluLPtuGR|&yalDrD@;XHjObrH~cf1vA8fGgS;k-zER zi62Y6c3>|XEDN2T-L5?k1Ha*_nXtKCmH7^JFv9PrsDlCSMf%Cmm%FQx#G}+2?rZt*dF&&uHwzsRKNmY92R_z# z+CH*%eo3LDir5jgIzLNCphC|pbrmt1_f9^U zx}$4L$Rp(8WzcQNwe-ilHTGx6ZTUBjqu;TK@z9@Hx1yZf`)A6~fs8wHlqdCyMS$(h z5%(sJ@u=!SAU3=pRqynos|ZdjCuaKDyvD@T1&<5`I?W0sanlqO~UnvHQUn z99D~$tyMZ+=8P3}yazso?`X&Dhm#)InZN!pe6`_l=@B=nsOLZ)X*-7g(rS~IL)3K` zIg}jmkVC|I7Lh~PGX<#wLeJbX1HP~ms*hK&102tv3DA2P?3qwWKia>jr?xc$rdS>KVrMolfZ= zda?bRJdd^Kuv@(cef-=0a#rGy*sbA%p0;Om5AuEInsRh+1fGoE;JR{e!1?aGs-HfQ z({`@^U;x{#DTntmzn%Some*}hM4vtpVy8BoTNKA5uR#w%U#$WAPC%DxNajQM&75Db zh3661#{W|H-_Al@#%IqlvHNjfgZ)b{Y75_&fM-|vH%}CZKVwNs{X1~{<_X518O9zc z5T_r(k9G-b$iAiUOPiDb%uJs787yi!(msgaE8}va-<-)xzU~jOv(ano=qJm(TYuf) zLoIfWh#iMnr`p%QGup*?)fRkG>^AXK)l0pK;IkvI z{qcJJ!=}j-%)eUY^~-t$Tes4#e(<5N!u>ezs_qmyK>f-cf5pFVJns5Q^;nU(iR11N zI}>`$$-c%mKOV$lSCL(CKQuZ_E2BK0fGf4zQX`_T|`&~aDBW%+3leBh_x z5AdE7-8Tb$)cq&uW+B}*BoSgAfi^n4^J=pfW-RiNN=!fuu86SI9 z@KJ@&c0|<4NWR;|p`QmIuH;wVQ&5$DxDI&w&5M!-ok?-KOOJcnXHUcSWpc8O2X zp7HDBIO72CiJa*w`xE@APuy0X%yN#zsxtN@?d`lBe;+$N)`QhYW<1W#P@nZ=J%;Kk z_>yPuU;VLi?HmpN(V57J&#!F}{aDm>gIX`Qh`ud4s(;uEPZW@scO57_7&2bR3ukid zOAyxq`oBBlvVOUh_g(4lDf%P4H(H8BPj!&jlYF)F^dIUvepmMIh^W^dDQUlJkbOiR zVO;K5HaG0n^TNm*9q-&ZM%+>GG={tg__gxO%y(bv0Q*u?2Y&03-A4<=Nrk?03-i+X zugtir*$)`Q4-hBo~zOt-;IUff*I;}Pg27hoO;CYwlPjIb93uQTX zC7l)glP}l!$3GdvKM5s|9Ynjqb7n({x+dTq!!L2k+hvQt~S+=AOR`FZRbK+e4W+I-){g*U+$r1cU#+?*6c)tk__lZE_m+c#9w}_uB z?G^-13r{K9Ep#OCFn-%#ax?YG(32zZRFU`cT~LPyx-LB)id|aTFZ!T!Q;E1Vc*fq; za&oi=U&{S>Am`krMtuBR>`xg#bk??-{>s!LjNxZN9jXU73i!=(AN&X$V~V(8+)wy_ ziXYkqomo?E2L?^$7fppZn1f;CSP8b>TB&FIoA* zZ}>sM?&q18JB57es zeFL79lRqMQUv;#rQ0Oj5DB&L!>zknRBz<&O?u# z#VO`P@=uko%qT4vYkEQaD&|iOX8S{5;+7__I=9)WmVhhHt0qsLP>G))uiEzf(Guf~ z^P9h=_T)q_YzPht9^&|XQOD<9udjTx0J=?nvrXdk`Ig1)m__U>*E{mU(IRvZ_xp9~ zQpK*JU+AIUZ%OB)UGK#|KUzfZntqo^zZLKl=T#rYPXqtPFKDuRjec*=t5Ub2@Oyi+ zEm019D)Lqp@Ezw>$?Js7`-4*70bC}|uMUX*#~w(G`xD3`XCywajGay#^>1e?_*)N_et3fURncDJhrkh?QL=8JWu(V>CeO7K{BQ=o z=_Ic(>GJ&*rCOcrs9&BaNxX2lJV86Erx;0HR$|SrTAl0=^0A0qMV{`f5dV$u!_Um` z&LQ;u0(fG5KZINZZtE{dT(4Fq8@x1AV!Sc`9##8Y;(jKMt~Q<>@ACk);<650^e=cN zvwQTQ^rt>gehWYPa_VG}Ys4-7O4ji-@vDKOHyuSfF1XRwD+f9*Sg(^Ue{ZG=o;v=s zk~q2wKBTn&^4fQ>3%RZBLd0iWCtLX&{r;e8m;EPFgEhXr;Qb|&hw;O~L)z5IZXn+c zeu*dlQ1Zu?4%KK;uR9?hg#CzIc=~DL?+kyC_`65+UB`>4D%l`$TBg~=i#pbnsIQ`Z z6EEr_Z}GNqoln&HiaI?N|8~ZQzB+P|)E(njbj%_@jt-(0xmNE8)9+&t>cFAm@^?;6J zzQs*0c|piT?9l@Lm+Zd>cc>2%DBLR+;p)!R0#>C%Jr0Z9QtniCSla^N%~u7hmZU=XJ<~&jd1GsVkW;54md22Wc_m?z{So zwo@)&!@NR2m$P46sUYJ$fV@Obn(;2#$aoLqCtQ7|ruVHrzXp9C0hfWdzo8!BuD3>N zzwmSRq>h{Qs_?ZL#dQN7R4zbX1K%R^8RrGBl)PY_4%ru(y1_afW@KDbb^5dPXz4Be zs9N$u8M=9Mq~*Hv^yh2qA!YwR__;&Y2?+i2tMlPQa^8^=yGF-%>-?JSm<_PAgOdbwf`9a02)+k|?*M!JPw}6?qtUPRb&3)v;XT8jcK@~1c+W(Xbz*tc z(c9Y+`B0zKVTb6q!cylD^DO!E$s*s!>sWKWv+%jqd!6{R8b0G+S-F}PJ3K4sLjFY5 zi*8`vkx$NwNZ0>#%egJmt~tk}YZdjPH{#EZ6_5jrZ*>uUiX6YJ9EA%1n*HS`kU!~_ z^e6mm^{z`j0`uPJXSa!;js9u&vt3oG(0*?PdX@DeV!un=1o<0*KS#Z7wn|;XU@h*% zKJ=H)!cSfL+|Q&cYQLQK7V*pb#V^l`Uw+SJ&+=WfU!HYmk>^eMxdy)+&Lw|?K1uBI zCp@{T`P+6KZZ<7=2M@8oovqc|^^{x2BG_=aH1L8;-UNLs=g>MW_}dYFH|qeR9C;)e zH*}xLu`VD-UUYcV(QM_!1y&Q_v*jBohrGqt?^HQB^y1*qKngOGX8 z?8YBL?q{+Ub&&VmYy8A0{dRcroO5zUd7k4v@pGXs{Nvj9xj_488QCvf;EJE;6Qdq} ztoYpl{(9k>VCD?Yf)+O&*6u*<@DppcocX- zo*VwLD> z?N)Dm7WfDE5L2-R>NOOiL1HTts~Go<4TWVf1-coeCxf;X9w{Vy)X45aNF^8 z2;4d7XiRMw@z{@Axmpg`e5ErGpa-xs;FE);qM(k^jv)Z{u_T`m^;Za$m1Av-#?@tdH=h=NA1};&)jdd!BZd2jz(X zJgz80C&0sbM-#52E*gSviahVH>8tAo&{uifPLYe%7Ik-Ggm@?8AO9$JI=`Ej>v};) z;+qleyafb-59Q>x&K96^{DDI*d?xaj_ERJ1apyYpQl5Ca6K$Q%Vctoe z%1x@fN98{DhZDSKwu-)3bx=t?j8t; zGpYnVSibS34ljUCHkWk$_rzPlH}u=9!uw`{$DX5-`uGPN**`!H7gQytVBE&z7+po8suj56r?xP5Ro#$ISXJ8L{YV zD&m4F)_wBlzWMXG|vf`+2 zmw05cm40scKVE=;yNQcyJ)!H~&|?GWX&-yeeJAm6pw^e}eMfUosMwIJJ7dGi`LV~U4avRuy7``*=V;y?k~^R@-YU!c-`R}gzuQF z;{uQE61N4u)LLK3z7+0Cl^D$?&Z zZc)XR5?@2k8GeoBosk3S?CsE_tT%|`YyWLF3*2#h?XzmXpl|i<P2^0Z^@Gy8jYg7f{DSNxv4L?7XQ z-!1mf-5ZR3Z{#a+!e5$Ie4i@}hkkQAw!Ow*s~7FM2hJ_t7FL)?@e>2+&(z7^os#v9 z#3>u<F%p5#685Hc7JI$L@%kQg1w>W-&fmy-pCG2yclEkAvOnbzoOg;&@e)j$}mmx=8k+0ZC(7AfR*XK7T zm*K~5qaWn9?3*O}{++!}zN+)-*6;5YJE%;*UcY)Qi~M)|Nr_|OQQ(i#?haq;i@2`f zwU0a1EOL?W4rJxMe)y4ia)Nd1MdEMQ5PvI59sPycO<)GPXPQ`&bNbv!=y474aW}1&4u#lH zytmfFp2Ch@3veN5U1|uc#vhYz!`?lT5&5U2<%hxJ=%*TfAXlO<08WX2lwTB@XCY|r{%}g z7uoNV!(Jfy+lkaCs2dUdpS=%MM(P`~;NL0jmbh|#{{+d;)9yy_0KGw1yJvyd8Q?ms zuRBnyB8}hg4x=wz;?iPY^87i8PZ!hb=1n~la$Z1c^=Ctgi8*tbJk@XhF&dQWE}O)S?EFL_h1&e zzxvfc@-yizRqp`uEqzVN+Y5ak zEnAoDTmwJ2)LF%J7=2U6AUi z552a_`vLZoxsRNN{@5q?Zy0w7oyT+$9iDX|t82th6aTn&9mks+>bY1iWcC|V&&YRv zDk?rw5WM;6SK$}xEz_^&_}K#d5%_rDA@^b6Q0(IzM%0Zs!PB$A=WIl8m!M~Je~DB4 z_NtKUFD;{jIKHUKRLnpciN2jQeno z`{Uv-BX1q`!fXltvgg;E`%9ec36YnUUhF)!svm++R#wK~3w3i*3Wz`4l__Em{;Ty!IT4*b^x-G&k$5qQLIyq>%rc#Gp+ zu8wwf*}pDUcrnuFC{2^vXrpmnG=!0k0N!yIAaB);Wva z7~%&v#n+U!FO@vcN}Y=9%mvt$V)x28#O}?4he7ZFoXW|5Px2d9uf%!STt(-P+XOD~ z*LG#Gww}-AVcXVJ&3+$6ZTEJ%tY5m3_RPNU#f|t|O7t-FQRKdjyBK-ZpCaB{KyKc8 z+$;OAbNV~){G`>Y1Hs(j7hPZ4=`$_DlzP@^3o-@B|cwXdJo|n-N8$Inu z+jd=P7d~`1;s@uk+sU7YRo2n0)hqYc3 zJ%j&WrGL>sMYun{FK|=W*93PJxaoh3z)k$O32vUFC)_OpH+etPt}E>d+*<^0;uTGB z^PQ`B9_aBl!-=0>75cBi|G!ClMfik%Bz|G_ZT&uedY=5+7NHyH#msLb-B>%l?x$z} zMf6Wx_Y(W-ui^&~XS!FF@2d!XJi+=ms3mUq+;!B=e!2SbY{a}a#{Uf+XVWSQefUTG zwE}SOsA~SJ*GuPL*YViQLE``PPc%)hJKT(4&itv@u#t1rb8f~T54lcX&AAHbMac(* z()1qtjhEbyUqV0PH~Mm(%m(Bx zaCZf|KDt$1%QgMS^?oKE+%5J6^Jwqizms?{_}n?J>nJkI0`SbZ-B9WHMt8>z>P#Aa zFz!#5QYz^7BiSb`rB>@Wh*S9^>}jN(#5a*%9Zu$xK}35_u5GTQSP#bh3qCr6nt#zz zgkQj}>cXGFFBktWk6%;iWWRNVf0%EdD<;$f9oX5l!+jm^?iPDM_|qvandAH4lDwvi zzR>ov_}Nj{Tm?LL;z0ZIp4TzQ{3T_))r89P`$}H_2Cu*eY4y(F6(9Uu!Ta!;a-z<; z0{+Sv?^n_)&+jXq{taG%UfR{s;FX-%<6d@7=%b^cL|%9jhbqxtFa8kn7x=StW$42A zgK2fChTq!N$|?8E<#{ggfAIXBi}52pu6zG?CHuA6eU4H(kHd6|ye{Eat(H8FXqC@u zJE&{5Fi#}z&Ni;>td8TA9|hGpG^!QXQ57ojhSPw0B7<>))+&+gaIx$=yE{WkR0l~cN& zrbFn;6*^L`#+z9e(70bN=Z{7EO630~t{w97ir&I-9zA#E6!r__u<A89dMKuA)jwBe7pYHHRUl6TAIIZ&hvtfq zi||oIKPG;eR@bV7MaHqRHV$ zhi_i7$IPsW+O zVa_G)@@>XfLGMZ)xrBU?d~v}1n0z{Z^}FZX7Bz8__k70Z`p7%vRtNMIaqSeZnX6I{ zk6#@E|9|h!d3$n#FPHY=|IS=c6#V}q-xoxG2lRv8EP0hG{S44$gglV@0eL9755DaE zxc}w9MShHW@fDn#3EdEH)9q5%>4gHuczl* ztqSz~^^HX1Cz;1SH~W^83ch;vkJO$(){*9~oC}Z&f`9m<-;LgK5_+=tvvS{WQ3I}b z<;gO3m0auZ3|>D0yanQ**)rpTF0Y(oJt=m~RgBj|e#?EO55Xe zSi#=)-ijWC{>-?Dw``n?sK0V<3}oLD)kitF3tzLYMCu0Y{18_io#VcvKJJO!>GWoU zka@A|N9*V5G}x<_j${3|OND@A^^`0DZ8@W$@=|Gh_4c7}K4{qg)a>dR^ z>WO?&@XPXux<>pN<9~FBo$oPU#?Ei+z|J3*@q{dVM4mh2VUVL;i6@81$+!-!fS!l% z#on(VKAPgqUM)W$&t2edcY_Jd$F;nBqN6tv6~I$hHZu`X&v6y{sffI|O8h$bsmX4i zBL4wh-g?j5pDQBAn)0RDpPz%Do9y327C_-J(Y!?uzxG;=jvjYyYwS=dxdtgW$JRUudniTT}+pUUGGXg8qXO=w>*ar z-K#vE*R<`r(k|b-S7HBxmsFNGQ@ zJKdXk54d;_y`R!?KdJALcK217FYzBD@l$GkLiZ*`99ZOB6?>BBf=A@0((@qmR_niS z4fLw;D~6!!fcA!<>n!wP>DuU3t9R>uMeqS_cP;QI_CtUD*S=D#Q`#c+_4F6FcW!;% z>`w$A6uYy@pD^}aHqH36@ZT1xuSd=``4i<^=E^+Jv@6l`3Y>`DqBh}AFiy1zKO$nB z){l7YpR|90Kl1K_KJ1Sek@LdSIs9Yfabja3lDK^Gsxo#P-(AT%JHCHtVG zs?fL9*H(Ym<9JbC>TadIeacbPaj8e3Yj@+gzqW+H1 zA6E~D(5Lroa8QAFYo85ap9x)CI=V8dP6jRN;6^WXCXd?hO6-i_hdWniGLnDqY)>Q) z$dxyLao*UoizP1fWJSBMxb&;pfEze}VK<6WS{FJPxwerUP zlCR)gF!;9%_qxdQCA{a7SB=jVQ+Lc|rJk;FzC-34d93FdJ4E0t(66P>hC22pJ7@dH zbl%t6>+5?i#*wTfDBMcHO!hI`*-<9j@IL_BG@hd1bF#FX9?GO&t4viJP$Qvvy9H+;`=E?K|$9 zbHd)m`~z1HdLm#xT9AKWv+1{kb$}J_XZ(JNXIx?G3|fQHK-XuO`BQ)Yt>5}l1-n!B z0|72OKglKRb<&CjhE46xj@0Q=uaGHMQ+?InOa@DMt#Lv;^0orpl?RkLsjhFs~$M_oLeXIHa z^{~*TsfVrCc_1%xyl>(D%*)h+0gvJDxAx}VcPfBhKe4_%nZw@dC@{ZV@4r!nTwmM! zsl6wC-rt3P6Cejg@8{@e2zi3sB%hG`N(uV%5~Z)m{COLKCnM|!k=IK6_Gq8Bmpr>) zNch+sbV)mAzmS}shd3Vjp+6uFfu9aO4!}QY^-1D<*wcx<{v=>2??dXb9Cm_J`Py8l z>x0;5gZn!g+Sx%nRmQz+C-Dg8-6`ywgAQ!FDfS}?UFsTSAGeV4^{L%~yzfN+bFReo zfXF%WDNk>VB;SmD-zIfa@CWrsWyZfMLmU_UJW$(rOZ~E( zM@5{x-^XFY-c5Wq+*@G3?*1b70)I~QAnS_K8_S-Y+mqf{@%GDmW6(jFc&^0f!Eg7<(Axu@ zv=dKwEW*FPcB*_I-?N`X>Q&me_H|reo#MH|e!uk{2cF}-X1}p~V6K9_)sXM$l(;>3 z!DHq;BKq4As+}Qn&?$XG;;LQJALF#o`-s~-oMj*Gl|K1I=GW@MG3+$x(T-znuR3y4 z5qG=fV}&pJ^4|IOvncEQU8ne=&_nW0&SS_*c!Bk_zSKdmzNWxFU3UKp_7RMrldcig zS%v({`lS+ZQpX#4X|=w0eB0U$`3`w0-xb8410LusA?rJ;%;zHTbjmpf!q@$|NaTI1<5lKpwUb%Epnb|0#BDRF~Te{LkZaW!{hd&!^OWq1Vv^I$p2rdNJFcmHU?7 z8|*&dICav8jx@ary|d0m;GqylPW6pN5>|NzRs6E#tLy#*Op1 z*nA{6RhU=!Oy-q&Y@F8?nZGJ_y_we*)~!75Blp*!zsk_572MzRdkb`ibdeEp#H|U4%~1i_b~?Ud~&P{ZycH>>B7> z;0rZ;FV0n%j=`K8DxR+?vCam4BI`ap=+5z8np5C^1o(64)wTHdA?{;?9EU&f|H-SY zVtiR0pZ@L~bYbhPSkDn1EVrtG-s=B-GNM2CD1M{Vi#_3mRk=3#0z(f0LQu}X?p_&r z`(@r)*Zo)oe51r&i5n0 za5-(ypa)vU$_cfpH}`iZp_dlX55R5n_X){!GCm^c+Ar&rbsUTv`CmN={dLJYT$lA6 za=t(o_Tl=FFY@1e`D8`vH^RT43&3kvPS?+}&qaAMK+m#n`Cx(hHuu|PpKIpPK3~$2 zgMJhAv;Ch=deCi0O};JA8#?Zn=`KMh$Z?Uo9(F;j2mFM@=d=1beAOhEJ-yx%{v}?E zeI#@pEtG#!H^B9(oYoWdbK!`aRwb|Cy(;u9aLajf{UX-{->~7)-$w>@Lh<%^akM@l>Ov||LXeY%6Z0F*EiwD zdFVUSF&;?!E#m(blj^;!*E*CJeAmYD9$o(-bs zzV~%qF7^U)J{Ps0Dl;GCk@qn#b$m$uht&T*8|d@?8tZFJU1jVC?3z-gGIHL$*F~Lg zQ~j3?5hUe)Pj1g5_H$OnfD6RuabW|1bk{k75W43Qm>a~-Du5!J!tA>vidpkE_oh-pZIxgo@~2~^)lTfH96KL->HS)1)7eU@gsF7^kd++_UDzo zQRk@=bfPxb@F{e{xZLi1VyuikXYO~({X&g?WSvQ;yO}y4o*VjN|0v?n$gOUPLyP?M z*3Lu6t?G{g9XA*=aRaO0$7*)7viBc6ph`j?W?s7lk3z2-qr@0=eO0eoeacU(xAf-U zbgBT}jol~bHHGwxSVLcjPO28!VrX zlCs~w-VcfW8MU8C{A&5UkG@=yk4hf;gmaGf0*XRSf`Mvw9Np;f*bfaiTJ>`iUYS-(t@q5RZ zf95Z}qU`PUsW%%5gU7kHdcx8{yYNvU{0BUF^hB=KZ=L^azcv0^j6W@%G=2x158YSg z9LoI9{fASPv>M9ab^R%>i`ou{Kdjws`PA3}R&Lhq@aT&967n&&!)yDb^)KI6%LCbU zpmBS(JWz-FIQ9i}VA^fY14U!=U@v(m>&nY@d&9n;O@qfG_v3Y=3VVb00$G>NeJ8tN zzQk_^{wyLFBJAuuaCS&t8SlL|q$c=25nyL$g%4cf0oa8dheKpJ#`NI z_$~7;{TTb$o_9jKug!(@Hyo-kf`A6G50SIyuwSndIa#+~v0uu-M_HHD!(+dW&nuB{ z*sm_~O6=uO@(br~pYxa|BIdIt&-$YfIk^nETB_4ox*PmO#FJLw|9RvIJId72p}&Tq zGr*{i*U+E2U#BB;-^hoUUOUwFBk;>P_R&M7v&Z3tz5a{LGKw zYj**ArAy*PO7vc1f4_H60qfTE*K`iC@k?9#ndcJwXga~q&zG@hZM@DU&xHI?PH^)) z^J(K_HVzlpV|7uFGC)jn_e-wRM19int*9(8TMM#OtcGvkHw< zh96A4&LLj+w!_r9uK}K{__?mCl+lwmKDY+BLYY6t54~U4?WNBkH)-YOc_r)k8qRe# z_(Wg-p~TBt75kEx;G1sZzu?!(FP{I^T*UK$=lSO6_Pxb^f%EO6H|zPL#`e|Q=Oe~x z;A#BrRki2M=W0jVZ@RYk#I{q6*T&)5u{Ag-d==NVsG7XfaeCl4b>)uH>)0d2Q}7Qj z`B?s8*HJsf{)T?R+oz|uD&*VN%7e_0h0FEZZaEey<@R^%mb_2jYadkmbKvVElXnGG z@>|#46+8&OGZFQd5qUy6?w`bZ-sXNHO1J3|?f8J9&0$tZ5`((>H)8S<| z+%Q$@0nc%fTo$e671zkV; ztMdx@Ej(}Vx98j5ug(|I6K+oJt)$h~i}AC4Y1jYN`LIQ8eJ!0llt->4I$X(fHulq# zxQ_mjmxFv?XqE3LBH&!`{T+wE=Y@VRa7g}q(RNb6QDvUYI2+*?IAp)^MaR)D-`DBh z!fE?;O#81dd*`nm%i_lvI(^^rV(Yy{jqt0TJoRG$9G56S*EjuYKJ54{$IF7n8qM!K;4BlGRm<(2Cnzx|lcwV@y4 zVPBVa?Dgo|w^knl-tVo*r_bb&yXjqOKX6fh@LBO&oaKzWBJ*OdFXFl&a@AaSaqWwI z2);fa)aQAz>%I=}&QnG86O5xRI0k(Q9&2*ux72>xk^KI=&v=ZyvE#DyjAinh->)!! zgGc2A|9xKYYWd0gZIci4X$L(j@vR)~?Fe=LKhCRl{lKY4*gKL}%Sv6x9muhT^bl`B+&uKvciqJ2 zj#XRKMc;PrnfJ*%DWxhda)RK8oHu^w71SLtztoGnA^2q_mK&;sdhd?>#XCddZP$;4 zvhRo8mnfNfCwi9Gvh-7s^={$k=8;z|J95Q)Xg7Zc{%#pOb?l{1pK)ZcCqw+{v5rrw z8?i@sl!_8R?i(F1-lwSZ-@*G{n!NI%&mSu&wN&^BxtL8ng&*#yR*B2P4@;cr^Yg%! zUk^TuWyZk@I4-mPs zi}tO2N$UMzY2OLHr0v6X)tY=*hu(!wV!dnV$?}Z~hE?bSfBar8k7wy_JNsekI$Sw7 z#3QcY1dq(SBLC?JJh2b$yAS3W_xbvxMB#Dh;e9)hlfF8~e3rf>`ozLP{kE>>m;BWHQLa1b(%e#fXw)W$Xm$kq2 zHSsG4Qk)~;g0_L$J|&5#@5C=BuPgcOtdvJ!$1=}L`b+G~NWD_>e(EOVn*4SNI944t zdFMc{7wORXZLRmeHXrhSz5lPyN63$U_#t2Ke^B}_(@s z|DF20JLY568DmG+`tOpw_fGgh%|lQ8CIhAG9s7gIBaA1ur>tBWK)-+wODAsXQR1|Y z+BT?Kq`pqwGN~pRzcW{&Md|ErbZP~VptnbhGZ7mV~edFif z^z~y3x-;^5b8qnVQ_Q2-qr1S*)xE`!oT@_3H+Q=K2>n{Un^6ya_AGY2LJCwQ#ZGU}B^o7Oa8~yG1_VwQqyR(IOumU~9ku8<#QrMP@ny$p`%RkmUmrOd9gEN(*8UnruAn!DN6OKu3U-;X!}8k| z^`O)X@ZRIh|6;$c%(sX9iS01;C-Z?)w~HO-qmM4w4qN&s0+*$0>XUvba?)Opz6U$3 z$mNQ1`V9A-o^AM1VrLZ(i=CVlI}ARHuf+~y{^M)0!?gU3emL*KKL*d#8=Uj{ChU+y zIrxQrIZ9RNr(f-qeY5NK)wi&(&=1D0vix9w8}V!Lx@9cz_5+8aici}$Mt|Hs0KTA) z3-$Y4|DI#VD&%)!d+!)_Df3|9!Tx-H-ea8Be>CI8&wBRz$QL_bO#QKW`i)ud#L>#cn}-|YMCyNy z@V=#!n?}(?=#z82_opM}v)&`WAao`23jHW}hyS}*7QOvd_-C-B9`n&t{dg;9nt+ z;gWWS$$i<}=g5tX5fH3jO7urB31 zLEc~A`=h@)1^#6}qzRY#SR3d%q_q1~An~vbz0sLd6(#4h_><^AW%iFt5*N{RNc}r& z>u(064hb)28TVc2M(#(7^=s7qfRE&=+WQ%~ukbSmqz(ytV;S+s0Qy@_ey^b8khQ$w z3Z7@Ry@6bS?w9-i1n}aA=zaWCBF{?o{_5xd*5Jsj0BJ zzVP4Go{HG@?_qy>nve5EfsP-#{w>bot?;$cM>d{l&hW{B{a{kq>qJsOEw=Ib8+PIDR?UwoRng4ixvNbs_^x-2{SBP97&S30h^1w>+ z6*m6j*!ZN0$F@s6wp`br)b}kfKS^Fg^Z;_N4LxwsLvE^HRC2D$>le%UE;@hTGc}1G zZ>;aL`YYY2Z~Ph^OWv^}^iaNd>K2;qSgS(hy$bqk@seeV^IL%DwND2@7J8JtBl0P+ zjQYNa_XPedc=L~Z`tbUsvhh5BMK*KBMW3a2s{NV{%9l(X$L@*adFDEf=b7s`o)>+3 zYAbj({DK{M&TElNhk)Oa`h*BNUydE=EwtOt&IfE+fgOVWQERZD^2qr{`@_Z|))ci~ z+(zBcGlCEEUV5xlvzx|3?*R1CvX=Nq1-r-z`lnuIUOH~4J_EaIxD*}CQ~x^3bA>*4 zihWbeqpc^RNGp>1R`MDHQ%f0VhWJYXyh_}rl2pX`wfz)7A1Uf}NQqH5d>r~#!v*3s z$oaL@6Nc33%liTK@aDS(ahEqwy@-DspUdNM&3ukkb-X{WU$OGb*k2a!YWrcO&s#Kc zl0I_|k8<*Fp1KaYG4>R35-oL+HEDedgWeN!mB(w6#0gbyI!B>6c@NGQZg0>!yxtxuN3$ zHori7g~v+Jv6CN}`m)TM(s=9}-mBx?65n`CF;9-VV#>iTUc0v{_444Y@K_|@McgNj zwRUgi5!X>w;!F=!)9Rb++{_u~89PZ$f`9BJZFeLGL-MQ8|JuFSOZ=`2zc5-BeG>fY z6mmDl<05kZr+sewPfPz*^)v5Z#d+Rve5wz#$>5_+;9(x!b<|rI@rMV>Ul;>#7BAfY z!YKS1=t5~5Kh~FO2!-f z?D0?B&nt<%aFOp3atQqIu2QGpA5u5Oc>bN~(T=})zGHl*#$4o+;6DeS3I4ICk}>{& zI)1VJH_rbXnC}{Vf=B2v4IaY?IVSLW7XWWvKINybONo5CL*k9dr~K5D$gct9PZ=>L zztH~z`LuQF5Q1iL`ShNtFOx56mQUQr?`@Dzzp&2FoXMgW&M%+7Itn~LE#F-zzn)`$ zey07`sY5mX5P989ujQ|f!ABM^$fvK4<|W?s)5-C3jK5JneMsi>4bbZwg46cD zKtBCU@!u?;O2O{D#D9=ak(N*YuJG9LH_!J4%cq|TKHLAloqQ@rvOm(lB2P8E!^@&i zmk*(Td!PAqd9p?A6n_Z)X5+oFziRvg%g+nyBY$1|sd|0n{j5{ME;8p>E0h0;+grrG zvGH2$SY5wkuWkNgp!bIENy58jS&!*M3|r zj$!?{hJJeP;QOW6>BF@=iOs(+`2IZcn6tl+<0&SO-_%Z1Jmzfp1rEuR*m%H#?`z{| zipSK(Y5R@iF>c5Ghu2d-;(GU$pCn(#%TuD6vyY!GZM4t{)2b;wXf9*T$e}dI6{%ATeE@$|Wo%>6g*xX8u_}aL(&`KA~1WV&gYkh{Nv>81LF*%`dh4&#a~HLNWdZy0Uc_ z_@8=TjaJ8dNc^LgwfI%8Qf(RX&wPj9`QX%X?3#{Ufvo?qekOH*Uzpm89Fg^M+_!$I z^(WKR0mwN+*01avdFJ`@)>i7SkAJCr8-8|wEiZkO?1#?0IZ}^Gd_XP3Uo3Jx%>2@S zdL909MNvQQvj4B664Zx0?qdHLKfw{Z8N6es*6LCRi}+K(OWa=jGedG8e=Em*+KbQE z9aPVc2%QXnSFdBR`zkt4^r*xc;&lu{Z#nTh+~1kH4L?Bg!q8uODAMakWM(s=cUbl)t$o?=8OGV2fW-m9;F+E>0#sg$gL%CgRA@%2yp%6-^j)WQ5) zu7B#3^-qz}H=$OpUrsXJHJ^|I}Z{#h0|JA8=>k&{%^7i7Ov z#|i#;>b3>zpTsW%4&v8;JaruVT+aOwxv?(G`WMy%NSrP}J{UM0jbDM|JaWU}yIF43 z@U4c4zq-gdfs1(}e)hD)2b<+t__V}(>+%fwx)3hYPb@EgO1N16R2F;E&YR`m`Z}jY z*FQZ!g8Wtu^DFZAK#6rlL&WQm&q?@G);rbrk3;T7%$w_~3Ury4^Os7*HH0oA=-tT4 z`ni=gIhh(}{gdwqy*xYB=csPtieUtu8+o0Qd4m7zbna{VfNsuO|CEyTPet}+mGw^n zdSi_FhhNj{DjLu5Z}51Lc&pHBRs71D{H*H_;9=ah-!ADF`0M@F=6f;zw0v3TTg#WR zelhEyw$7AaCVyk=^we>gfAA-KHB|8AT$-4#%zV}D zfb;NGvp#-lgz+`&<3sc17m*`^A0K)aeGI)=eGERL$MeVs(Z@1>hRz((#~%D0>*FBU zooD^L=;I>!h9Sm(c7F}}IH*h=V!wAccv0--x<2+^oO-c-e>gw!QW?6n^t3=9zcgAF z`{F|N@u&W7p*~ikkC`9GMQ(+7RkHtXDC?2Ezx&zfW7nT3A_vTR#B7k>W#xjt3` zzoOny@-Fb#mA&5IW2VJ=w=U<;*2gj57=5hVM*}%W&+`4kd9Tq`)HRL$`jhHoN3TbP ze&hAXLEjK zd}%bFIEOy2bWNjAoAvQQop+=z2f3l^oc~4gX|ddh^|Aji;tn;mHGH4Lzj%FWeYy_UQ0!l*>80q0Se`Zb7p9-Oe)#F&!j9@ZehB&9upU{- zJVT9*>yhjCkyB-nZ)e+Eb$v{o1b&s(#|c?~9MIlXMjv~kkCB(A&Oa@50o_|Uxwt-7 z?bEl2|5uKruHWj#1^Uh4y+$85EuxPTWmbC)u#bnUlP7z3wfSoyH%wdD{5-h1b3P#?+*&M?8Cfx)^Q~Kcw!>KllDB z0rouOjqBX1y1pY>-(TgDYpG9Uf0b3oksHLdE|ofK)zA5a&}TZqIk+x#OMd5I1mBqZ>N79; z6P5b&E~zUjNk7~Bk559UuJ}g_{r@cf8Ts@9?3OI+_txO|m3eQlSj#68ACR~~RzIg+ zL!K8FKKBxG4vo#%wM!ivdeG*Rsh`8&=lxZ+y1GuOtMjnO1`2v#7UD`n)7X3JGn1Ud zLH)SwV_U)gbg|zA9ej=#))%~HRWMgExjpO}sYkfY$y#<}WoXti#7 zg8T70{YTaQkkc{ExYdxN>z(oGTZk8%dY`SA%eq9peqwz3czqpKT=&z^PtP5EKS{jU zu4}v;I}JFAU)k@^6E8mddt09l9OrJQDPDXw{I(8n(Q!1zi)(P&e&cxY;L*1pnMkuP z?7hK*A$n5Q<0|-3>OG?iuVc^oZ`yq1x}@4NBX$+>!!CZtZOpY zah%v($8qA|lVT@WdLln@&g*)d_)ALa@Z&f!=hp2naotegZrgj^`!7F#>f^~TBnm*2YPjBK~M~LrSl(_!qroksup(^MdyAJPeS%>G*j@kdWaev^%dDr0; z-!(mfoHg}f9O!|aNP8LL!vVK9zVi;X6FkK01H*Ss-zMwu4g`;68K2N)Ap2-YK7jX} z=!WTAfHSUJVx4pd&~_i^#=0f-v0DAwn0?QzA2aW5AEiDkVm$B9Voz!(Pjt5Gt$0F{v?MVJ@JJTYEZkoQ0 z{ea^3D!pM9J4f2{(0`*v_7%k+FzvOCR@qk+bgbH|ByMEeYv11y-MQLt+LLptm9xeOcQTv?ME*_|BN3w4jnDq z{*mK{u&=mZ!E+5HxJ4==`ZUuhhb!d6cnIn($%Z&SW^w(hd zw&O2S=e$PhypW?E)Ze-AdAF;ijxNuBYLN&1bmf9aij2e1*Onp9WvQUwer_r8U7-uJ zZ-2vnaIatYmf%6?yi?>4^u>N_LCM3uk>3K}#rwUO{Q$br3laSoxsdaZeDH{azi;GD zi>?zD{J6JBoZQNvxE<48^Z6YWT_h*w>=O{H;I^=jwcfoc*PF+G|xGWWIo_ z`FUxcURnd5m(Th9cB!vy#DnEi^y)`s-RB;eP`Mjj{lNf#Lh9t9#*CBOF};;_R2i{L@!NgmWuEyoat?WL_cZqU$1lt2bD>%< z8)ZX*WN40dp`4E-usmP4n1M6-AjXOGr(!r8H_CVDi66yHP92Z zoe9LQ_3xj4GNpEAds)wfd=r1qV|+&5E_jZ=$NoPq&qZH0KX+uEf69~RjK@5u-HAha z^t>!_s54#6F2VYE1_tAdR3rb+oo`+)3dBwj~vQA9(2ArRYoL{y5 z+6?+EDd${dsT**z#cBMT_NUl5JrsSApA^4)iDDzHJpPru=MyJ%)TGGc_;~7y$NO(CV9z}D3lAN^UulnkyM+FX?X6(f^dbDp`uP5b z#O>@pJ=ndcg-*^fzFlG`#Lvz6;%hTb3s0NC4_++%_5O;#FZ}8B6x4x8^x93297k^1 z{-D1{reB7Bh0Y7$YbC!PbSKveIVIOQkyD>lr96CL?ESvgx9fexcV5c8gIDmhN5-jE zF|UR6;&oD&(Oy}pKGBmo^#83#zI5ak=BqhA6N-J+v@X%^CwCcq8c^p?*Odr8+LLD< zvFn!SYj{`|A4IOeA9Z

=DD)mcHwLvd1{!i`Y;8tkU&bt8cIED}7mQzkqss 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

|@RIK^?xSO? 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 XSRAl8U~$0WfW-le0~QDVPjKKruIvsY literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_c3xxx_mmp.bin b/sys/contrib/dev/qat/qat_c3xxx_mmp.bin new file mode 100644 index 0000000000000000000000000000000000000000..0f1f811eef4112fe3810015a97a3e1e1da49a2b7 GIT binary patch literal 120452 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 literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_c4xxx.bin b/sys/contrib/dev/qat/qat_c4xxx.bin new file mode 100644 index 0000000000000000000000000000000000000000..040e31499911918350e6ec2e1ca5e8548a17342c GIT binary patch literal 4777880 zcmc${51d?OdG~#tnc11y|HJM|hGe@r*$unfBuyrel4v3vC`GJT2Svq-Wx_v$APjNG znRCx1OC!F%pFS_N9_IYH@9Vz){;uo3&e;#%d5dhnT*MNQB>%qSJ#W4KZI}JlJFexo z{u+4Ke*OCEZ~Vy88*aVh zv=euKl}~0`s7VFnsYG?dPwuH{-gB0`K_0}=|J>Lvb+Q>AO8xbH?@e z#m`^yws*c`^f&ABSsH@$C{W19qDt?Rn;<)O|HoDeDF%gH~`v3JS{KtR6 zKc_y{H}JXg=NA4`?{&F5zqtCk#~yfO>$SJMeCW1+Ihy{L$3H&z+^(;_c+KkG|Mr6m z-ge|CpSKmGfo4-CEWL*A#q^w9g)zTwmF`;(VHxUIJQ$**ngJ@1N56W&|< z-f->idCLc`{J`yRy5r01zIFLc58c*s@PFO^{?CtJxj*;%_m8~quiyEZWaT#>xbTnL z?!NKYo_W*Xji1-^ft_FYe%BR~i{AX=C!bz+|I|O-xc&oA{%V^IvUgvz^_EBW|IOy$mM`D>?9SAe|NA%ow({ra zUG{|qE50}VmCH6<{>IhGhu`&$3)^4%*l%yOj~xEt=eIuk=w0QXeC3Cq{?reyd-m(! zdvf!dA6z%FYw^MA=0E?z`27#`p8CJP`0(AI{q84rTz=uV*35bI&Q)K^W`F(ocW(Z6 z>SG7~dF3@-fBHW@^Y#yX@2<{yt8QDq{yYCvc;ni~evp~2yd`^L@7uol^+lVX_{d8i zyz?hryZ&bT)^-23`^SfuXYcyU1J0E`kum03T z>GIdV{z7}HeZ{RG`rz-c{m{+k+8eld!O|7>%8OR4xZ%bNR@_i$>C*pmi~9v<>Z`jr z$?MS;>F1criB)Q?4`9dFo%nbqM^&L>eEfOW)eHZ;>&e%+uHO3RJ>T*g*VPyQyyr8o zah=PJ=gm0(mB*@dNUf$^yDD|EnvqO0=j_U5Bq8&qR)rfdtQNG0o6JeA!0M9)ekb|u zNX^&lC8;?HewX>pILS)<+ml)@%{T?uci~Dr&H_s+pDMFPaas?ANv?~8I-b>)-(5*H zeiMqNR?LW%lwhBa^i#6HD{xGDohK_?OhPx$zMSCbrsQ7}9d6CfNTBNp(&FjS(fjPq zlS)@S-hvk94-?XzahyF)i)5{G&!odZsoWCJ2ch*!ZFeand9lx#bkh8Gf_=<;ev9O` zR#|_pxWvm@(q>8DWHl`duDRyiYM7D1YaX9dWt~4u*1Bt~kLS;ubQAKp(pUOV&R@oP z?lbp`6qa~y3*&8^TZJx3dRDCjUweJ4=IXkumaZo+UjL*6GkXipiHgN_m+KjE=Y+95 z7?Yw^y3yEz4gziI62HOTD5cxeW8!%$JdYYz^VbPsIz;(%n`ZDP%Q$W;>n@_V#g0Uc@p&${ppb%J?$Sw{VS`JTPui9^ksd>RtUu;BD5;Mg zWWAu!k4}}~L$~S;^mKczC*cpj+fG(2In|9`hS1ZuT71^KAUi7Ck=syq<8M}T3F+A& zD<`3&Co#5alHZK?&dE|*TJ$;eAur+UCj*O>LT@eg>hmeibAKwUN0!~obE;?OIF(O1 zs-{lhmsw|z?Qe!piJXJnM7SiOjXW&(jgelqjfOjN%+r<~530Hj#=*`ObQU7}8)+@M z_g53rrsEe=4S6M1UR52>me7Sy@pEBnjqE9~j;;dogpcuj>8@454%OEV$$L)oyzwW? zIxB^Z<%A5iI{y7!Z|y1sI}lE)!*)I9NpB3Utcvm__^rvHdF=gr_*O$d6BhhSN$+JG z8OP9L){*Kc1ipjc>MHx2-IQcH@HfF}bXe|hPnIp&+Z`e|wJZ1v?Tuqhced0iwMvWF z-BMZ*a(&}l#CPCnyzVw#x0m<@*4;7ZWRd5kqvK>jk5_e^%&EOHe_8$Ine!+6#NS

DbSL?Bt$1 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

qh*Q%2$wA{P`aqD(XDUx!|gKv2IWE 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

    Jp`_Fz? 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

    -bUe3`0YFHUHug}<79kF#xP z7ye+2U&Q_t_nw;iMKAw+G{4ByKe}I3uXnV5k}>>u)m@{@3(xPaVh08!*j`zVf6|iw zYrbQKJx%u8=)Y*5=(NnA7oKlbZ_P6=%RERPA@i_P@eiv_f5)20eX%JY);RSaPmb^C z<4XOYdR0@O{jBRdbIuri_#@>*Gk=(t-}RHq-5I%Xy85+@r*la3Jk!if^dopA zr?a0nz+US-06WV17xOEXb3ZYS{v|ap7yb}Oq*`Den{nJN@G0Nps+SkeAw}^xnL?t! z%rr}XN1vl#-?euFc?S8#yDAp_>1G~M#QsgkFQ|Ys^RsXsHHUV5@?2)vtZOJA*5Bhh z>p6|%4T$WnEQU^2@c2+qLI(2I6FRRk{UQ$juDy3tU#c-LOiU}MWKQ4qLzNY*-_4t} zLcdekGw2T#jheCDeK_7yV^ z)x0|ytk&nFoO?CRX8iN9O9AVi3ku-Jd{*zl%~{|krj@`+=ciRmGCAS~4t~gB#SQl_ z%Lq84r_ZV;`b$hMb)M*I{|vr)@MS)r_=10%Gu_kudWH`8eZLzzLVxBk&!ioR=999X zcw~`tceGvTb5@^wq_U23vxEA1p6uh&e7Z!czE7Au!e0z6=lv!hJU*>VTxL*GJCr|i zdB=zAQcBO7;%@k*6pq)>Uvm6zGk?#><9%f<-yPDw`TNV4e_fw_tg-_Cv4M-5=%+q2 zzt?>}8Xq_3?g`oPh*_*dYk-L$KBASIllV1srS}3;DldIydF8ov;I&~Ina0l@-!#s zZgCkW_}Ay>)US9co$2Or{d~F)zD_ER9=JF9--2V~cL~eW{&#Q6A>UEE8RkRx2>nQ@ z{1XpWe>6~fJKh~N^+y};ef_2)?O5*Ey*ubfhn~;I`k%P%yKaXs8+gdm({c%UC-VXw zpE=if=OFqf2cCnIh|3ahci`td?KJ3FfzRRpNZ!nOYO-M{%$M4^upX~X4_1us=!<=+=}+)!t3@PNukf-ClCJNT#GF==&Swn6knq+ z3N89Lc-`Kmn48~Qf7i@KVl?uWXf?LE7&E7<9Ihp@ZmxufYF++3r2qVcr) zNrQcZOLoCG3AKlgNN>tsvTI#){%z%uQ{+9x^Bs=P8w+pQyHwYOx+?2X3X&$iTc$I7 z*LMZ-H>>Zw{4VU{fcg!{MV9YQl%cOoFW2QRyk~sTz0uR?jk>)XK>s5DPNs<5QUA@l z?nGQOTK_itWwRORUWSj%d(1yWJ(+Psc}?keac%WiRGyO!``CAeACyJ$t>aS){c`GQ z@sA<+d-g*2)^o-!J*Tpok-ol_f458HN!{o_@GJ({GRKZKvaI>r@yXMs=ZRP+FPc_w^V;oh>Z-n)bQ>G%t_>Mgl??=0d(mUH#q zyWyjmPWv$*{n4`CE}a|Lzt$$b)8*=2ce4&OZ9}-9fbZ;7*A*z=f@{x(EBip*t$SzbJ}u&Z=ojM$tz0xhTot-l_NVqTk8L}P=LNnmeiriW!splp&Et`? zSTBPQ+x5P7VtdWFYUMhWkDJj;_g2v-tLk~s%-0fOK7DwezqaSzxc7GIIWZpT?Og{y zHsg`k@4brPqUsx$ezfFI5|6y$p&jH6{l4)?L|OgN#(Zy%#`TkpxHY(zHZgvSy#Kws zI5#m`ckH=v@#lBV!f!io@#i1f#XiDiZ~gp3M-+$pI${I=4diX2zkFRE!M|wQ$Hw|d zt&`+h4Hk!f9NFVZ?w+idM>>2@m&*iokKS4T}ON;x$7^-r@=#$MMgddyj}*tNeqWYULlNklpeS^G4Pww(dQ`dyRF@^X@!!H{~tw8+&`W zSPswO%T;A5Nm{PI`O1Xu7g0XfbxtF%JyN)9*X{Tng={jYF|U=>w|A|;Zj+z9sm44T zk?e&yj0by;y>I+(+r54`PS(Y!&+@kIU7`B&#dfUsiZ^C=FJ@gjb>6mJJC1+;Vm@r{ zpZ-J7p?TnYhjxYfrSc`8@wV`%MEou6KP*?k=Ps_urDb{dseTdNca0y^gZ&HlT~BA< zwS&Hk?1Ws8Ju87jWY6rG$VrL$XJjv_!K<$$=4D!eyJ#KJ()BKISw#q2^LgOEAMTxy zQG5HtU9>x1^+=U=BEFD0ZdUg{Sn6LDLwSBk?a!$*gE5Dx7W?qf-U-Oz0!e7SC%c!k zI47-4`PY`6QkDJ->vcu$qwg@G?;lY6W$wijsg`u#RFoIrqMxPDX5VsiA4MzQzj9US zs?|B-W;7{Q>D7ARBkbyX_pW2mR^f@gJMThuT&pdmix=Svs91O_2W4i;!W^5`4NXhz0$Bd zm7njuDlux_Jo&1>c<80p!IF*q++Xdz3cgOIezj`?`H*SySKtZs48M~n+LFKW-yert z`RhYV!6(8Synb^CJ&1l{exXXLzFu$eY3PAy{oX3r$sh;YHS#v{$5hW!C3${4V8J>F~C}7f!M&{Q>=G+*h~{^CMmq|9x%W18;a7f1$zG z?_fQ=j6VY@^?L*GwWa&F%y>q-8oq-L6ZS2|KUBVUXg(XO;GAQj1@?N*ENBu^J=ZwqvHy^qsq2~fO_AN$v@`jI0zEV%> z=)%V*U{?xbl0k|2nflir^XG0S*A#!`J~%Fa%W~hKbSIxi_R$~F^YiGxlMHA-BW=1a!22?qKNIC& zElJ|f;U}7N_~>$!hn7!G^GO0YsXex>eX}_CCDQK=`>Xv8^%VS`KRLe`J%Sy)Xx{|Y zv+!A=$%jon_43b0Tc0xZzs&kn*skHr)+_enJx{BA8U4|6<@sMcy)@O_AJQ@(`6KeB z-oI}b=Xs|zUkV&oNtky?zQ{EXFHOoV$^6*EdF6xrhxbir;(YRZ@0xwHn&ZJ=c-i~W z#;thoC^Yj$n(JD&Ti++6{ycOv>kw(pi`4u2@0P|ZU7e5QuiCd1dm6>Z&F`#ZUGq48 zUejJyQ~fY$^S;7;cn?iW_qWPfN-!jm5UUoNjIZ%CrJw0Ju(lO>3`uKU>=UY^L z;r`XW6)J!Ad^ocY$Giu>di&PF>&a501`e-O|IenrSl;3-t+n%{)6tH z4a-}>ihYYuj3=o4^Cj66<#}a2Z-4v^?Xua^xCi-jN7PSz@%%`?v#94gNOaC+uYRYm zO1Td92^E!ZqVl7yt8QnW&v@{^!~DFN$@194Mf@HQJ(CZA-?(pSQ(g@|<~r%z#T)l6 zZX12y&-FaN8#_DNzMts1%5i<)PhsP}Bg8e#zMrW6rcLJy>iRbS2g7W{r1hLmttR9@>-Y9!2aPsoHLU=F#!(~PmlEDGS-70U>@1y z?%Jlfnf)sh6OWho9b(_hAnU5ktF5_JZxj3_3y`yb`2M-mech*>O7q<%pMDHn=IH*5 z=D7$OhfOu!7fZgkZ#lSg4r|hzS-0wm;H-)HH)fz?@slQ_mBIIgy(1f zK>6LAkEnSXM+5jH&H0E0pHZvU?`t_khsbG!{K+<%=nSBhg2StN99M4?>O!} z&*=LT&3@FvbC#O@kh|76;W>>D?z=lYpX$f^EY^{ubG%3I$8QVC%UK_vf7sXWZJK^G z=J$3TZ|USb1n@tO7R^iW8>oZx+Uw`)_AQZ>Wy;SHFU)W6Lr;{j3sOJ-(@Jt2J@Sp**L(!<{xs)o z2FQgA|KTrWG{1m)odr_8jNeQ=$UJBN#FF9V%%?eLZ>!DvgIolT?AvdgLtLIWjC~w! z90r%R5J&QX8sjJ}7+(BxIM&B|(s4LC4%Q)$25;DnzB2l{d7kbsz4|%j-4`kSu+Pp$ zaLCRdxNA*W=MkmzhmSPRWia34^`rzw|3QPrA{cMZa}67A(mu zqCfCC{eOqrH#2T?zH_5|G~SGkw@98$)PHdusRq=8{M;L~3GKgo_i=twYx|rNc#)sO z?l;lY}XH#oAZxp(mh2Gf$pK|ZR zW%v_U4&RRaM*E>D%J;$2s=W;6z2ze7Z018O$n3DSKKx$vk!0v!O|STGj=op-cbI?RhY-xud?xR>-=pVU;y*V8 zIFjVOvex(FIL@=_yS}aKp%Xa&f0+4^X>Wq-ZXRB2$pkOhJd9sAA#lGwyh6+E`1Gst!P{}?@GO14_#2^LCT08r`hjDp^W@D*=vRb3roUrz;W+~`Uf21;bHUv3 zJb;#d$;vZ1kBxqFzE_w(6XDQfcqh+FUIT3K(9ebmY0>)>3a5 zhZF7anYQWt#;1@~`_3@>k^L2k=UntpJM%hU>AG(F@ZFq0pyv`+sNeXbW*nB>KMenx z^RLbLCa)?V3C~xs-1~3cg-RC-){E3upReuK%3odw%ej zCFkw<=Ly6MCgI0Wu1&{XK%YkA-#i(*seGGu#}=#Ws~3&xRQX?Q>QCFZhM(@lyC)`(vKhui3EuaD6#!|CF$O;led437Hu7KP{8=TGn&cuaoU1^5jo1<~Kr*EKpbB zpG3!X!SyaI3ZgnDeL!pAeat;=s?UK4%4q?%?QawR1fOa*^W8aD*N86Q9J{D^EVn~;${Hi)XTGBgmh~ZA@T$I(gP{e;?c~eIYG5(g{?J2~e z&|jurAs=AmklHKk1$g|M;tfuT(i8np^l)8!UjGxwKl7h~ky+T+wWWb4kgwF_0)7c` z7t8&#k#)2`nQ{2wtLGmE#Hq*4tK(wX(??b?zSE2K^E}4k=jB5=e32X(e9=oYN2nkA z&K$X$x>Wy{l>YqAyv4|sKiWw%dG&LtsOQ`f?7W!swZ}WB9D|+>`}AJU z70&Vg>c8*u%gDus1>HV&hVOZF={fJR_FB#x<$Bi;a=Z@a?p-`>{M?H8NpAv@!8 z_3t(_Uj2Tn!F9CXW$ha3rJdV8Onvlk-d~_cxbOZ&Xa~h^56_=9=VF@kZSPn6=rG?) zEe!dx^}EU^{+^xHTR^`=a%2ZPt{IudI9u^rzaU)K>+M+irYBY?8x)p|V1JOy(2h3l zb^T89Q2(r==X<~Y#rsx_y_f1oN3KfC8B^?}^7o>y2j2aJ+P%rpE6@8a{seiZZ{N8t z&AR4CS+4@;$#uDO3eH=1E=|bBF3vZEKJ8rv?`6-O;JY37s@$(CNXciMQ9g&6w|LsV z()q;p-@TLh&`Y%c&YinBw;^i(;nZDgeOu$8S9-_K2e8-ScrVlOBKPlkCF{C*;xFMk zEp(k+<@?>h8R5foYe!z~bN#)K>3g=0TltxCCn@hmxL&07*ysh70!@qsnF8X7d z;)xt`?cM5<$Jc_Nd2fAKALmF#{WiaE)ZdGi&<^X=Y4<(~-QkZGdf%z#OME}E zW&DkHrz+oI7cBRqBlsb$>x1X0-w94mVeu6^cM%Vrik@{)qna;*{lKq)e>tCea$S#` z@?$LTnvvU^`gfyUa_^zv=)Y@1y%zD4p`)vMBL~i%ZfHl_t;+Y*57;xw?Km8SeiQeh zzck9#{o=?G-k$_rJ=#5uaky(*E;%@f! zdFii5R-h-N=jf{&MwU{a<#{7J;8VlLuXNo~5nNuyIjW+5W%UMazh`3i9s0ctQ?E72 z<@*izD-)%6GyK$ezI??SJ@DhZG~suh!KR04E`)ArYuKzcU;BOw+|64|o zSNgwpWXExGcw+x=89BnagnwZFd$s=+^kvllXHyrUFW^IS-jt2qt#ZEoDY^W554^_B zbJT7(o_G4~TO90Rr@MZq>bHrmr{Av;EBM~XA^L0b8KU3sl?z<`4uCVBed1iZly3^O zAH_ZJQ@*M8Nv0|vFm7XKB0m4n6bE_GYS%Jf<9Q@6jcbR!A`s2Tqx}gd@>^cNW1)P~ z(%v%ty+nVb_8je3nQ@r*qjsF<-!9w11A1&3S_UoDwj%+EOG_E;Vv=%#E$EC z0>IBw|02LWQF$pM56fpssYbnxa^1xJnde32m@j>AWF6%!cboE|ta3&77s!O1TMCrV zS@+3N?U{k~C+{;kT92L;{7As5=OmU2C5gSXdSH7>y_>A3$q}aL8PYwM^?B^LnF8#<9 z#vXG<|1O4Qx&Jt_l==)GCaYtP6&Y``I#&G~{` zQYtau(LAW4(ycyE5nj=G^l0BV=^3Zz&l4BCe>{3g{X_rpP%qxK0RM^cw)zw#Dg#Cjms1F;^6^+2o#Vm%P+fmjd3dLY&Vu^x!^K&%I1JrL`GSP#T{;3Rqg7K#7F z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1) z2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e1)2*e2d{~m#b=|qS@n!j%k|7C@L zuku7@C3~G)R*1O#qW`Zy;U9m3KQH`E=jpc>Z}0orq>Jp2-nrnS`);~x{j$q``S^$b zbvXU64}9)br;fY(nF|+8`s&YTzkT1YKY!(a%zD-4e_pvDEmwOt{l#T}zwx~1-+bG~ z)2B?B@z+xlukG3~@saJDe)-0GfA^K=uX)q&4y^k3pZ&+So2I`0YX1x0So?wH^S|&v zKl{s%Y^cq8z>z?mNGjEWPojIiDGO&Bd>M>`ni$`jrzubjR2KW!(8gXT15D&p$fz#=Sqg z_}ULW^40gB{lSramwj&I2S5Fm2PQpvS@48Ec<$+sx?kz}$#38DwFf`@j&TF?*MGtK zi+4ZL{+X}LIWqs_k8kc?zTdxP%#a1TZ$9b_XV2_&KK7roU~d;+uQCg=?OE=jNZBd)J)* zGf{3|_2_rDUH+!SskQe!_Rwcb|NiS6|KZ{ves$rU^Cmoe$vd7L^RetlP9Oi^)Z6}L z-6eDW$6Igh{Oxli-#z8Ph5zfvk9$A7=oepp>!ojh>kqzdr2)m&|ze z4P$>i^ZXB8`D$<5kFQ>Gaq`yb7yQj@eo*?%Q2$q!bA=ceCaEfpEvP=?|h?e!iWFrO>ccOoE36e>IMGgw(;K!IXnFAIOhA{#l`ns zbLqt&zxsn8`_%hp&6xMTIkP`<>H9AJ_^kIW&%N)Gi%;_SeV2aX(kuT29Q@x`<+&fc za{1Mta+Y6n&7~iC{}q>B;(YW<=dH`HcIM1-X6I(lc9wt4nKf(vtaXU}nFIOl)x>W_SK`PG-2XY+YDd&Z!1*4)9t z_g_4F@cng2XZ-gK?)Pk|Gg~j%rB_F!n`_Dzt1zbiyAwTkqw5l`%0l_*`f|@zBfi}8 z7aO5@IdvC~x%=lGf)ry>j_{ojuB zc~7!;b@+B#K9Ycn;eRYaam zb<1{}LTNj{k*l^)Wqi-37Rq+;ka4;EMyL6^WtIDfz+X}_!{>cl+jY{~-s#zz;++;h z;Q2UlZlYhj?`*2J@jP{Uwv-fa4CBmGF5i)e`f2}JAmHisD<9c`H8A8S#mzt`KP4*_ zmmK9Y{+MHdUY)VW1o~tOV~^3U@Kacy(l=;hA|BpHB*H9i;8J0Xr#3mJLDqP{{C4_UdO z+t0%+YyYC#cWGz+r@Q?E_qT20clvSH0x4Hh4P2e%<|$b}#4qP-`>DxNhQ3bHpOR(# z($_A&;+5P!B@4)snSPpN8RWn>y8UXRQO^&xANhp*NUxQo{8QMkq&yVf(~r(~*UM)o zC4&O>be|e z5>NZZb*xo>%aCn}r{kggv#Bd&d#+8=U4>v<5xgd6?SUE|)+9H$*R!PEvfn%ejtS`~ z`n5Jmo(671jJxyQ;`s;^FB6OJG zh?l3FRer}1a+9zfZ)*;`rU09t&&~`!CN||{IvkOc01zhbE~#&$fm!OCH0)p&QvcPm$vJ>^t+q(c)!u!Y5CwD zaBs9b34Zr@-|%}U@(FIe7d~)jh5oIdguH{(M!CTKevS4gNpY*A_1Vvi%;NV>f6Nxf zDHGkoI`H_fE0-^BzX9)1Cayv@>w}wX&%Kjv%J`M)=(;Ay=;|xEuMsF|Ky{ zsd#thy=~y)oMv~o^ zPkT$UsfKpx7yHUWLV9iYuPZLU3;Hoox_h$Sr5?-wwAx!a({YdbmL#X~UO^h~SySkT zN535%$LQ^k)^Gbv7`g(#j@obWhJ5XZ+%Qz8{g!_B*}>{ckba4NJAX4&`P20~ul@E$ zA1`>X8S+8j@;*1D^54?$X|}t*V!u?s{m-la@~6VP6!sf_A06*6syzhnjYIHNYrhBV z;HwoMzB_?WoUaTO;m<#oPo~1(HRNTg>R0rqwFLf7OR3)h@8kO2r~IvYw=T!veaDc1 zo8^6d2!2YQ?#ZUSh%*)buBrS`pY|`3*TfA~u#^5Rlk1P!;)e`QNjtjkef{gq`^-a~1REHF|xX6Dpn38qr z*Y&x=I^@XoH+9t8RzW_W?Zkg`63jPT*$f{)o4v>@!{^db?e-n`{nT7_jSc^dtKGE* zJz?HA?>(Enz$>E%OnK~Ebxof7w7he?{eNIemiij~kMvbZKaY5DO4`VAVQb~#8& z&ndamtwr^Z9L7hh9mQ_n2ftSTW&?f(<-EyN^ep9!9Wd9;pO$i-{!LXoaoqDQYxo^p zIt$&t7y7mJcAQ+dUuw3~Xy3!%2^5#JLjS_}8Pfg9ZXbF#%0=Tc`q+|g+3M3y^t&@& z+@s)Q{154%eNlT|j6wKBiV90PY#-gZ|!r~GdGU? zYCDDWv2sG%lXX8*>{m${ez2w^KPAS&K+2VrSm!+|hbzht@=W9hKCAv&^WOYkztaEg zQNeB}va8o%7o~e{m!D6_N~L!#A*=MtIJ(4NIeY{^Ezx!OW|hyBJK%=`lXjGUt@OZ; z*4Vt?@ovX2aP9o0V8WaQ6R<$isWk6dKHM<}0Bf8)5T zH(7iKe(SL1Uaj|eyIk_p;44yftp;7_e>nf>u_TmN8QWFaME_PN?Zk5~g~j&Dr3CX& z=7-f2@f9ohe};0*Uo7{xL-2zo5B#R;4p@Lw1stOJN`>Sv%PzTiEVBxfpgKgq0RsRE`cF zs%b@Cw8+OfA|14+qT=Zagme>VnRuX0lT;TpUmGLVNlt8IR;>`{WidJwXEb*6>oc-mv?R`ziA|5 zT61sf*YQFrWMcT<`jt{#T#N$v5*1jBJACsY<(m?4%wIgH@X6eF3`QY%T6L@OkGH4s ziz~pN@IMZvRKdUeg-Er=ef;exseNk6(S7>9Q0dpAcRIBy+7WQIP$Z7aFh27FUW;e= zxwe(xyYJ(76aPpae0!Q^xjL-zo-MM<{~Yv2-yqk|f(!e+Y3yw7)P=P10Q|JlKHLmPFhRq4+O#C@# z(nAmAis6yBJua>iNdM0|Rnv;z^67Q=+w+(>ish=O6w-dO@Ppvo( zJUtnAU0m(tLl(_)%MXKpFL%V-Scd+|`=*66!deL4*CTfU^%N;xG3vuFb3)@Ui3^{* zj(lhqeCwy>p6vCJ#u1kOzqq0PrV+(YB1a3~Gw_(^0j9}x=&x|Mo*eYK|ld&qM+x4tRh z_XM6|z7(rn$eeP2dNe$fuPfJ&DPFg&g)TYCX*^T`oyynD$H}`UKFVCUqcr_`E)Ugcu$f)ODli#tC!zV>i0zB z&-zvuW_IM(G0r9PIpl%odR{21efBip7Q+U)B608;?|<;xU=+SS-*JPn3Q8s#mZ%Ef zUQn)Yf`eopPvcC`hcbw?e#2ta zAa7;ydjWc{q5e|*-;^)F?{AFNopbOjnVZ6WRp6@?7>DsM9Pv|Y;frlI{_ZIJ?>rtq zK3W6rCD;=mf3dJRRQZ?|{!&;Io|A*E`Cmw!%Xn>kT&VYR{lQ@`iaBn(%Zr*EA70x! zpNX7TmHv&##{yo{*H{<@;1fC81f0@CUbDjcPWktYHp#Cg@sARIyN@0$+}+}>Uoch2){E<{Y*dMRxhe@pQztNT_J%tySNBHRZboeTdHHhyi=dlEPTZez&IuJ!=k$ZmxJ_-S^U-?PlY|Wz$ zZwKF>9xK6*7TzBczT13e=`SVY$F7!V_l-94aA%CKFb^Tk>2X0QD&OH90 z(r22?JX`+SezVF|p6e|?)7oo$bezVXG4zsbP(Ly+_pE%MiBlV?9+M|&EbRG=)(f^| z@aH_Wms7nb__MJXwAuIkci!V=WUBYb9PkgG|0x}`@|nS`o>-qx{1oQCEg8u+4qiAwyApPe3NyuJRMLjpdw zJ$rmKO5sn=4|j9)h&zTt@(dZ`Ql6hq;%i^5e`TyhQS%b&j3Ic>NA9ZuMjsM3eDp?=-`|&srtJW3UVZYZ3UF`RKI_mK z@VQFICjRFs{~t%egSA)Z;txLve0T6yGkzTSYmPP4uPT3C_2ZQI+X4O}=9edHcqFU& z2otAGgFk9b_(-nDf6mG21*&h!H#pUAj|JHMi_65bnzvcyYn*v{UfZ7hi{ZPuWvSKh zzY;syO}F%gJN!8ZI{wGYh1;PE_{k*mxwu6Bk$h_6m*RKL8jq=GUTp0NaL44qFP#6g znw-d9j6Ftq4BpewJZ=L2qSpMdC(bx{7YqNQ@GQQ| z<{reJK=yOsPyA8~|3csoxo;u#KrVVOzRln@n{(ru%4=b*)WrO5>I4XA>Z{WE(=riU={i)^Op}!;etgra&{6j9@YZ9NmCG(AWhayLMFLL9D z>%=X&QgdTWo;p{O2SV~Houm1kdOYzQab^_?9_cy1Yf4ES&^LytzrZ!IYu@z)2HuXD@ev;DiFDBh>zp+8f1 zF}}?UCVI`g<-oG1%fxHvht9@0FKQRmueV3l5DoAniqA6tIYYl`9>B&;)BD_TcSF#_ zQEpJcTS6a+R+;{k>6wVa1oh6#u}3cN@u62et$I2%b}H}Y2GKV`uF$hT(*6rSHyGvN zOXA4}_N@K>vU&fo`5k-Y@q9(~KktRe-Sa!g&cWXr$D(g;8jq0Q1L02|D&^&iUUA+2 zkjc&{L!Yd;i>k54p_WdkFIW9%@=ZTJUQxbE@=ce6UmvztyH(++`Xq#pG~aaBnfa#2 z(SQ8jr*s5Amr3J+I@nzZ9et9;46XUsg+>3yLn=>;tH!Qo`>J8Bf;^w9l@GxOU+gcE z*TKKJ_^+^k;veS~o~9$&%(ieJc+OqE!=FvD$@16B1q%=Qm~nHL1;B$H zS&Tku64zX?*61_p9HGh6_0d29y@}&*8rOLy{3{DXlh3g4l|J~^SNp%MrSCoFTY+C~ z{GjtKX`CJZ!nkMb|GO3bT$i8Rr+S$8wE6a)x%ExZ`SRlXZ#@M44ru-(776CL{+_DZ zE&tYW;ZKjiC#T%^9;)Z%bX)INZXU0L|Lr5xhdSf6={AS=>GO*YlxH6S{v>{E=OZ$4 zQR~pM5W4xuW3EoT3?FaDPh%YLW%PV1=hZeMPaNZo@DInvM#ke9ZFI>8T;!G>=4kz^ z%zW%{iT5l}JqbS~aox1}m9y+~+YcG(Z^gx%Z}Uu?T)nP!p2U^t?|5@LFAGiH8hJ?K z1UGbkYupuCEt%gs6r|*73UB&66~#MWgs;zYqW6!xDdUemfc!~1@k5!i_902;Yet_{ z)NfY4?ed%H>+(NWXSl>)M!%jvu_!bWAAgbl3cNjrl$PTo_|5M}4 z6Mt&^ICk6C6*_)y3vRLg^-SWE9mc<|Z}q@G{XJT@vH2gXhtN~C@h~e(QUl?RASd{H ze|!jhTYb~XgWlcBSK0Yr!u)~T&L92xC*z*x>B^rOFQdP^^TYJ{8NAK|u731+s?dVV ziT~%g%Jax=27fM*i`G>azLmVaPyMgAvT(bv{##HRm$caYzJ=H3tuQ6=c!WQG%Kx)N z=(#rheb!&y*3$nL{>4f^^x$If8z|l4KOcu*fPddOd}Z~&<%>&m*sUt_P2j(jJk36V z&JPk7K+n{?`EQl$n1|IPNj_~+YSm*q;1}Wpsg<}t^K%O$@Y9Y1k~rslr}FvnCXW{b zF>y?Szi#@b8GlaynRfhax}+~j;(&y2ES_bXJax!}pOe1R)QsW!R`k3_pTK3%v7@($ z3(A^DXvyowjNnhe#~YG-#kR^94#D?Ms#w?`WrhAh^1MpV;^vJ_{D7h6OcS?hzhMo0 zSpRhia_=+Fa+Uvd+s{tBZd&U?*3Zd0g;FSa!T&ydC<3heu8SWIFr%~Grq+o#ipFU@ zJw27jYuMT3+?gFUw?Gd^`voHEB{sk7x~BinnT;RbOv~vxA@%}&;o^s*N66nUoe<`i zz-j9x&$#Fp_%8k6sTbA%A$-R!YTfuIU-RyAv0vZB@0QQ9!)4iCh3^VqGj-^U);lV| zb0z+6`7q{c@%SZ&u+A&xO}<;%|(jCoDeNb)N(;C4(3AUmJh*Z;l6! z3@d*CPHK(^A2OfR+WI>94f$U>5pnLl13kpirIV)uoYM2&2spF;MLqj#9M6fHZigS} zI~{1mwGckKI5;c+lv@=faZ?KqS^3)92z~6V*0>3JU)&^KH+7Em1oT7yq$XVSdxBs3 zb~C4Z?o&HenMgZsx-R!j3I2McxXI?}ZQN9hrfL6Y|HZcv*AV{< z2gF67VIFalzCWpdI~q6nIhkIpgu4Uu#sYc!Kn!1N+{E+Ki#!*T->yGAO`2A^(r)yjvxoy=mb=Ak{O&>l>;*`^KG#`gPDM@b>aZL5}?gTy= z{s4J1=p^J@nySBpv2pYReDYpXZ|;76fah!6Zl8B~PW4Gq^EE2x!M~12%*#HX*qzi2 z&)q1{>%QUA!^*#^r|=)sn=9`)T*YskO}xf2{kZ>*!vb8^t}0%9=r|{!j;C^?=ZyDY zp;ZsV~d)!(5#b;`~*ZParKLRxx z-%b^G!Z@2J>dXcvtjo6KMyiES`)$0zn(;UK2KS=JNhbq&!>9jl2nKRH_~|`=Z+&Z3 zAaN-8h)_f5np$xoBP?G5lbM17(G|LZuu`k8-1zA-D$^s5{L%;mtN@LK!Sul9-O z3VX>Xao-B=^Wn>7t@_eZ@6>-gT!If*mg?)6&oa;d&BGPspgrH{u8ENID;r6lORJyD zk+1niF7Ij9H$jKq+y3S5!$RFx?OX+WG+YiJW4!FW*ue&Q#Vb!5KWqA`M$7(P)ynU^ zdwrDM$oN^cgH@i_`zq+C6?O7t)O}XeP2FdDrXKEYVh^v-d?9@f%dn3jc5yl9Ri#ty zo{1QJmLZ;v$p_4HOa(R^ZVQ29{vjNlczHFt{Uo3(E-CkNGEW&Sc->YIGk zFJkKbPTGqj=(Dh|_Tj@WTNk}v6(aJQe~y>jb775aAN z6Rch5d6Nfi*Z-3Euq_`+Jk{n4p`OLKu1>KZkyRgcDb$eH7oLd9?LzSP6DCk_k0$JdGa!QzBZOu+ZjOI;)4Jn^ry zm+ipbA`gAlmY=u;et<7!$=QCa<%c#OB>sDw4vC(`uTS!F+kEv;Y+f#Vs_|!stBjx8 zZ1S_#Z_D-*pM_etdOS3FZ;yDSjvQV_JQBkfS~tVq5}!RW;hFlyKAlG{$)~sd@Fk&H zkEC%qz0(w~Z+J2e(X(4o5GD3Y7y+;0ZEAN#h z=;;P{S)z7bkE&lBJ#WZPF+0;==K9p<KxS8p-`5^x4gqVEQS0;ep(&ZdJ zfG+7Hitp;*E8nEHg@1pz!g!gx$p-+Z>fM@&=gOCf$*UMShlAppFfZ$$aI2}ewe@!^ zk8Smq&12(GzGmIEy`G?*kFT=MAah3lu-l?b;-Ar148JmHI>|?!(-&O()?x4@Gehp< zX#0Yv(-&OM{lI;}R?qyX)+>~6(%2FB-_g1&e40s@{8Pw*J*R$=eKyLTS-<$VzY9(M zLMC13e@Fcyb+Ce;1xU>Xdih*?Hs@LB_=DP$sr+0oxNgS5;I--iLC?WR*VVV`5ZJTX zlclNqx!%a0V$bG0+i2lY`;yx05yGOWo4qSjOz*EF_qlpGbn%yRuD^x*+I))&GW8-` zKeBv0$A`Ye<4N3S`yHfss~4e{QtugvBDHh<=o{qq!?Vak^VX5<^^a+vQd=)2?`_+G zjJr_tem!5Fo;g`H`g*}6a*Ezwc06Ekr|KNXuGl(-Sa>d1z0A6oH2kddSrWMtFYpR#mQR*+o#pN9Kf$@ZF4!gT z<;aagUsgJ}KY82E5I8m$y{N(X5q-J!Jl>3F>IJf%zFf{1-kx3gtjjppfX^z&B7RFH zEAchhzkqzMJVZW#@m7^iDqYDl+&78-uR zJSf__kBi{jI`m%EG=6A#5#!Vt$Kv-I{3e~BQ+fMj4ZK|=73J5$v}UY*0yk`Mvl}al z2i_ACPpnBU(H)&kn$+4jISf0mj{LEye zVE}k6YaOO_PC=vRRqk6&o>KQ;0N>eHD}d+S6n@%ee!!#a=CWQ-?GM3EW|ha0_#-zz z(*93bk0f&7YkN=)01hJED;LhRLh?yl>byd3@k9dO0Vz)4!zf z)bE&Va3B1*j`G-9X47#MR>Upb-;O8y@4^8E-1po3?@DF~v@t&L`!Q4-L zmEeD^(z(j>3H~!1e0L*!1^$0&vc&Ow$A2(c*SxaDe>Ggsyutr1lQr^$3I5Mh{ENZ= z|1;@1a-QPfGx#^>|8e*){pw^$KHK8I0G>kPQSzh4Z%*)&+t7@+Ru#`J`z(cTn0!NF zZqDBhUBm2yp~m-iUx=JMPQIG^ljn;YLT4mmehcaIQTi@IUPI!!MaXFco)-nCFa2K^ zg%6zqzge%~#C7;P;Y(|OWkt!;{Z@!~etaZ?JjrwZBI4tw>dS|apVyGHOc8$)x)u6c z$Kq`ZHD4+2b*=MZ&x_D&8M!^sd|pAW4|E*+emf857eq1R%H4t10m<)em<&}fweFv$ z{ZxkUy5zi2SfqZe6gm3Hk6U1UA9zT{-Jy7h6%Q@E$f~jz0Sytydn5P(`oCB8U}wCZ z_n7r})?Z8H-dW+sy3Vb8o#%+g@$lV7J^D^NuK%!}GvE9IDmAz1yuNDsyrh8O>imlv zTIcishI$V0&2N}~+E|}MJ{%diN!KaAoO!V2UwUD@I~M4AU8x_gT2YMu$Ftl;{`r4Q z!dDOJb2^O6`>P!7d#OK04gAuDp~*W%3rFZ9?(`*z=6lQdvqRUf*8N88{KNyk3i#>& zl<6aq5^yp<8UAYPcgdS|)#Tx4D!l38NcIHGtG{CAl^(9k9_)e?SBkFpNz0^PD?=Zr zvTYJPrc0$s)k{T@PfP~Do51mM=5g7Bo+r+TcQYaHa^_pr{_{T$H7>CHva~3VKN~6i zZYoB+U6S=8wl1sdM$Gdwu{$-x*FQGW;C8=NnUL3c-BkFgL)ow z|BIzswWNF~($M*5zR~Iz>bZdR_NrGJe>f@doA*RTK ze23+Y z&*hp2;6AI5*I$MGL>@=ve?A*%eYxOmVZ7dy=8yS3L%vw$XKoF-<+*_heiwO0`PzFl zp1n-{cjnjbJ8JjoU;Cu`>*SaBPR8)f4{cpS@E4Oh51U{9;*isf^Hb)Rr}D=gr}6no zuoj#gj@Cbgk-PQ6Zt7|!jp6XAO;qxTVIxYMN z`G4G&&p#x4j6YC0G+D!cO!};+)T8V1$FP%A)dBJs>pD%CFwx6xeP-$0wcdz%j7I7l^-J`IH&03fuJ%3Mf!ymp0j@L}o&A*@-Crq0?B*3pmz7eo zyr;S9Iqc9ZrEfhaGv-KXdz6u7Jx{KB4*qdYRllnIZ~Jw~XMA~*_qXeYi^xY+088t{ zF>0#aKX6@XPNCCh)b1M;pLN{C2Meh`BPY)6vgv<3J%{;~p_AjUI$D9A(%N4^F6_Bh z)-qn;_hooOc+>aW2Uu1oAt)_OfB%elKq*He_HX+AlQx`x#46&aMda*u)zHW5R zn|h8uwbxy}-)Gq5{*sbc80P2Il*y(SCLFCp`= z{zva!@(A=xyXsfrcWFHlxTncM;uzqv{ArI){GG`X{vaXNWP|+;xNo;G{($ZWgnw)N zk_^9GZ}0awRyMDd%T%>&

    _DIGg-zunIZytR^)uU}-8S&2`gTz1 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%0DrsPdak5+ZgP%N(`UUazuC6`hOX(kN>N$u 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

    5T4_6`?hw~blSc_BCL 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%0Av!#R| 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%0A`_CpJo#`=4&;^*plJQddy;@6rtS%;o^ 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

    (JhM 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 z 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 Wu-F_z!sR*-O0! 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 z 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ⅇ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

      BtfKhI8NeZX`!a+d{Rt*1unc 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

      sYms9%0rKXzDz{rI8>N_C;+oCxIg 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

      ;r=w%ylbm4zb-Kh@R=wWKzdql3{$9;R5 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 +#include +#include "adf_accel_devices.h" + +#define ADF_ERRSOU0 (0x3A000 + 0x00) +#define ADF_ERRSOU1 (0x3A000 + 0x04) +#define ADF_ERRSOU2 (0x3A000 + 0x08) +#define ADF_ERRSOU3 (0x3A000 + 0x0C) +#define ADF_ERRSOU4 (0x3A000 + 0xD0) +#define ADF_ERRSOU5 (0x3A000 + 0xD8) +#define ADF_ERRMSK0 (0x3A000 + 0x10) +#define ADF_ERRMSK1 (0x3A000 + 0x14) +#define ADF_ERRMSK2 (0x3A000 + 0x18) +#define ADF_ERRMSK3 (0x3A000 + 0x1C) +#define ADF_ERRMSK4 (0x3A000 + 0xD4) +#define ADF_ERRMSK5 (0x3A000 + 0xDC) +#define ADF_EMSK3_CPM0_MASK BIT(2) +#define ADF_EMSK3_CPM1_MASK BIT(3) +#define ADF_EMSK5_CPM2_MASK BIT(16) +#define ADF_EMSK5_CPM3_MASK BIT(17) +#define ADF_EMSK5_CPM4_MASK BIT(18) +#define ADF_RICPPINTSTS (0x3A000 + 0x114) +#define ADF_RIERRPUSHID (0x3A000 + 0x118) +#define ADF_RIERRPULLID (0x3A000 + 0x11C) +#define ADF_CPP_CFC_ERR_STATUS (0x30000 + 0xC04) +#define ADF_CPP_CFC_ERR_PPID (0x30000 + 0xC08) +#define ADF_TICPPINTSTS (0x3A400 + 0x13C) +#define ADF_TIERRPUSHID (0x3A400 + 0x140) +#define ADF_TIERRPULLID (0x3A400 + 0x144) +#define ADF_SECRAMUERR (0x3AC00 + 0x04) +#define ADF_SECRAMUERRAD (0x3AC00 + 0x0C) +#define ADF_CPPMEMTGTERR (0x3AC00 + 0x10) +#define ADF_ERRPPID (0x3AC00 + 0x14) +#define ADF_INTSTATSSM(i) ((i)*0x4000 + 0x04) +#define ADF_INTSTATSSM_SHANGERR BIT(13) +#define ADF_PPERR(i) ((i)*0x4000 + 0x08) +#define ADF_PPERRID(i) ((i)*0x4000 + 0x0C) +#define ADF_CERRSSMSH(i) ((i)*0x4000 + 0x10) +#define ADF_UERRSSMSH(i) ((i)*0x4000 + 0x18) +#define ADF_UERRSSMSHAD(i) ((i)*0x4000 + 0x1C) +#define ADF_SLICEHANGSTATUS(i) ((i)*0x4000 + 0x4C) +#define ADF_SLICE_HANG_AUTH0_MASK BIT(0) +#define ADF_SLICE_HANG_AUTH1_MASK BIT(1) +#define ADF_SLICE_HANG_AUTH2_MASK BIT(2) +#define ADF_SLICE_HANG_CPHR0_MASK BIT(4) +#define ADF_SLICE_HANG_CPHR1_MASK BIT(5) +#define ADF_SLICE_HANG_CPHR2_MASK BIT(6) +#define ADF_SLICE_HANG_CMP0_MASK BIT(8) +#define ADF_SLICE_HANG_CMP1_MASK BIT(9) +#define ADF_SLICE_HANG_XLT0_MASK BIT(12) +#define ADF_SLICE_HANG_XLT1_MASK BIT(13) +#define ADF_SLICE_HANG_MMP0_MASK BIT(16) +#define ADF_SLICE_HANG_MMP1_MASK BIT(17) +#define ADF_SLICE_HANG_MMP2_MASK BIT(18) +#define ADF_SLICE_HANG_MMP3_MASK BIT(19) +#define ADF_SLICE_HANG_MMP4_MASK BIT(20) +#define ADF_SSMWDT(i) ((i)*0x4000 + 0x54) +#define ADF_SSMWDTPKE(i) ((i)*0x4000 + 0x58) +#define ADF_SHINTMASKSSM(i) ((i)*0x4000 + 0x1018) +#define ADF_ENABLE_SLICE_HANG 0x000000 +#define ADF_MAX_MMP (5) +#define ADF_MMP_BASE(i) ((i)*0x1000 % 0x3800) +#define ADF_CERRSSMMMP(i, n) ((i)*0x4000 + ADF_MMP_BASE(n) + 0x380) +#define ADF_UERRSSMMMP(i, n) ((i)*0x4000 + ADF_MMP_BASE(n) + 0x388) +#define ADF_UERRSSMMMPAD(i, n) ((i)*0x4000 + ADF_MMP_BASE(n) + 0x38C) + +bool adf_handle_slice_hang(struct adf_accel_dev *accel_dev, + u8 accel_num, + struct resource *csr, + u32 slice_hang_offset); +bool adf_check_slice_hang(struct adf_accel_dev *accel_dev); +void adf_print_err_registers(struct adf_accel_dev *accel_dev); + +#endif diff --git a/sys/dev/qat/include/adf_freebsd_pfvf_ctrs_dbg.h b/sys/dev/qat/include/adf_freebsd_pfvf_ctrs_dbg.h new file mode 100644 index 00000000000..d413279fc00 --- /dev/null +++ b/sys/dev/qat/include/adf_freebsd_pfvf_ctrs_dbg.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_PFVF_CTRS_DBG_H_ +#define ADF_PFVF_CTRS_DBG_H_ + +struct adf_accel_dev; +int adf_pfvf_ctrs_dbg_add(struct adf_accel_dev *accel_dev); + +#endif /* ADF_PFVF_CTRS_DBG_H_ */ diff --git a/sys/dev/qat/include/adf_fw_counters.h b/sys/dev/qat/include/adf_fw_counters.h new file mode 100644 index 00000000000..5fddb72eec3 --- /dev/null +++ b/sys/dev/qat/include/adf_fw_counters.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_FW_COUNTERS_H_ +#define ADF_FW_COUNTERS_H_ + +#include +#include "adf_accel_devices.h" + +#define FW_COUNTERS_MAX_STR_LEN 64 +#define FW_COUNTERS_MAX_KEY_LEN_IN_BYTES FW_COUNTERS_MAX_STR_LEN +#define FW_COUNTERS_MAX_VAL_LEN_IN_BYTES FW_COUNTERS_MAX_STR_LEN +#define FW_COUNTERS_MAX_SECTION_LEN_IN_BYTES FW_COUNTERS_MAX_STR_LEN +#define ADF_FW_COUNTERS_NO_RESPONSE -1 + +struct adf_fw_counters_val { + char key[FW_COUNTERS_MAX_KEY_LEN_IN_BYTES]; + char val[FW_COUNTERS_MAX_VAL_LEN_IN_BYTES]; + struct list_head list; +}; + +struct adf_fw_counters_section { + char name[FW_COUNTERS_MAX_SECTION_LEN_IN_BYTES]; + struct list_head list; + struct list_head param_head; +}; + +struct adf_fw_counters_data { + struct list_head ae_sec_list; + struct sysctl_oid *debug; + struct rw_semaphore lock; +}; + +int adf_fw_counters_add(struct adf_accel_dev *accel_dev); +void adf_fw_counters_remove(struct adf_accel_dev *accel_dev); +int adf_fw_count_ras_event(struct adf_accel_dev *accel_dev, + u32 *ras_event, + char *aeidstr); + +#endif /* ADF_FW_COUNTERS_H_ */ diff --git a/sys/dev/qat/include/adf_heartbeat.h b/sys/dev/qat/include/adf_heartbeat.h new file mode 100644 index 00000000000..55ca5815201 --- /dev/null +++ b/sys/dev/qat/include/adf_heartbeat.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_HEARTBEAT_H_ +#define ADF_HEARTBEAT_H_ + +#include "adf_cfg_common.h" + +struct adf_accel_dev; + +struct qat_sysctl { + unsigned int hb_sysctlvar; + struct sysctl_oid *oid; +}; + +struct adf_heartbeat { + unsigned int hb_sent_counter; + unsigned int hb_failed_counter; + u64 last_hb_check_time; + enum adf_device_heartbeat_status last_hb_status; + struct qat_sysctl heartbeat; + struct qat_sysctl *heartbeat_sent; + struct qat_sysctl *heartbeat_failed; +}; + +int adf_heartbeat_init(struct adf_accel_dev *accel_dev); +void adf_heartbeat_clean(struct adf_accel_dev *accel_dev); + +int adf_get_hb_timer(struct adf_accel_dev *accel_dev, unsigned int *value); +int adf_get_heartbeat_status(struct adf_accel_dev *accel_dev); +int adf_heartbeat_status(struct adf_accel_dev *accel_dev, + enum adf_device_heartbeat_status *hb_status); +#endif /* ADF_HEARTBEAT_H_ */ diff --git a/sys/dev/qat/include/adf_heartbeat_dbg.h b/sys/dev/qat/include/adf_heartbeat_dbg.h new file mode 100644 index 00000000000..2d63e62398c --- /dev/null +++ b/sys/dev/qat/include/adf_heartbeat_dbg.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_HEARTBEAT_DBG_H_ +#define ADF_HEARTBEAT_DBG_H_ + +struct adf_accel_dev; +int adf_heartbeat_dbg_add(struct adf_accel_dev *accel_dev); +int adf_heartbeat_dbg_del(struct adf_accel_dev *accel_dev); + +#endif /* ADF_HEARTBEAT_DBG_H_ */ diff --git a/sys/dev/qat/include/adf_pf2vf_msg.h b/sys/dev/qat/include/adf_pf2vf_msg.h new file mode 100644 index 00000000000..9c8462a8f6b --- /dev/null +++ b/sys/dev/qat/include/adf_pf2vf_msg.h @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_PF2VF_MSG_H +#define ADF_PF2VF_MSG_H + +/* + * PF<->VF Messaging + * The PF has an array of 32-bit PF2VF registers, one for each VF. The + * PF can access all these registers; each VF can access only the one + * register associated with that particular VF. + * + * The register functionally is split into two parts: + * The bottom half is for PF->VF messages. In particular when the first + * bit of this register (bit 0) gets set an interrupt will be triggered + * in the respective VF. + * The top half is for VF->PF messages. In particular when the first bit + * of this half of register (bit 16) gets set an interrupt will be triggered + * in the PF. + * + * The remaining bits within this register are available to encode messages. + * and implement a collision control mechanism to prevent concurrent use of + * the PF2VF register by both the PF and VF. + * + * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 + * _______________________________________________ + * | | | | | | | | | | | | | | | | | + * +-----------------------------------------------+ + * \___________________________/ \_________/ ^ ^ + * ^ ^ | | + * | | | VF2PF Int + * | | Message Origin + * | Message Type + * Message-specific Data/Reserved + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * _______________________________________________ + * | | | | | | | | | | | | | | | | | + * +-----------------------------------------------+ + * \___________________________/ \_________/ ^ ^ + * ^ ^ | | + * | | | PF2VF Int + * | | Message Origin + * | Message Type + * Message-specific Data/Reserved + * + * Message Origin (Should always be 1) + * A legacy out-of-tree QAT driver allowed for a set of messages not supported + * by this driver; these had a Msg Origin of 0 and are ignored by this driver. + * + * When a PF or VF attempts to send a message in the lower or upper 16 bits, + * respectively, the other 16 bits are written to first with a defined + * IN_USE_BY pattern as part of a collision control scheme (see adf_iov_putmsg). + */ + +/* VF/PF compatibility version. */ +/* ADF_PFVF_COMPATIBILITY_EXT_CAP: Support for extended capabilities */ +#define ADF_PFVF_COMPATIBILITY_CAPABILITIES 2 +/* ADF_PFVF_COMPATIBILITY_FAST_ACK: In-use pattern cleared by receiver */ +#define ADF_PFVF_COMPATIBILITY_FAST_ACK 3 +#define ADF_PFVF_COMPATIBILITY_RING_TO_SVC_MAP 4 +#define ADF_PFVF_COMPATIBILITY_VERSION 4 /* PF<->VF compat */ + +/* PF->VF messages */ +#define ADF_PF2VF_INT BIT(0) +#define ADF_PF2VF_MSGORIGIN_SYSTEM BIT(1) +#define ADF_PF2VF_MSGTYPE_MASK 0x0000003C +#define ADF_PF2VF_MSGTYPE_SHIFT 2 +#define ADF_PF2VF_MSGTYPE_RESTARTING 0x01 +#define ADF_PF2VF_MSGTYPE_VERSION_RESP 0x02 +#define ADF_PF2VF_MSGTYPE_BLOCK_RESP 0x03 +#define ADF_PF2VF_MSGTYPE_FATAL_ERROR 0x04 +#define ADF_PF2VF_IN_USE_BY_PF 0x6AC20000 +#define ADF_PF2VF_IN_USE_BY_PF_MASK 0xFFFE0000 + +/* PF->VF Version Response */ +#define ADF_PF2VF_VERSION_RESP_VERS_MASK 0x00003FC0 +#define ADF_PF2VF_VERSION_RESP_VERS_SHIFT 6 +#define ADF_PF2VF_VERSION_RESP_RESULT_MASK 0x0000C000 +#define ADF_PF2VF_VERSION_RESP_RESULT_SHIFT 14 +#define ADF_PF2VF_MINORVERSION_SHIFT 6 +#define ADF_PF2VF_MAJORVERSION_SHIFT 10 +#define ADF_PF2VF_VF_COMPATIBLE 1 +#define ADF_PF2VF_VF_INCOMPATIBLE 2 +#define ADF_PF2VF_VF_COMPAT_UNKNOWN 3 + +/* PF->VF Block Request Type */ +#define ADF_VF2PF_MIN_SMALL_MESSAGE_TYPE 0 +#define ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE (ADF_VF2PF_MIN_SMALL_MESSAGE_TYPE + 15) +#define ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE (ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE + 1) +#define ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE \ + (ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE + 7) +#define ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE (ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE + 1) +#define ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE (ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE + 3) +#define ADF_VF2PF_SMALL_PAYLOAD_SIZE 30 +#define ADF_VF2PF_MEDIUM_PAYLOAD_SIZE 62 +#define ADF_VF2PF_LARGE_PAYLOAD_SIZE 126 + +#define ADF_VF2PF_MAX_BLOCK_TYPE 3 +#define ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT 22 +#define ADF_VF2PF_LARGE_BLOCK_BYTE_NUM_SHIFT 24 +#define ADF_VF2PF_MEDIUM_BLOCK_BYTE_NUM_SHIFT 25 +#define ADF_VF2PF_SMALL_BLOCK_BYTE_NUM_SHIFT 26 +#define ADF_VF2PF_BLOCK_REQ_CRC_SHIFT 31 +#define ADF_VF2PF_LARGE_BLOCK_BYTE_NUM_MASK 0x7F000000 +#define ADF_VF2PF_MEDIUM_BLOCK_BYTE_NUM_MASK 0x7E000000 +#define ADF_VF2PF_SMALL_BLOCK_BYTE_NUM_MASK 0x7C000000 +#define ADF_VF2PF_LARGE_BLOCK_REQ_TYPE_MASK 0xC00000 +#define ADF_VF2PF_MEDIUM_BLOCK_REQ_TYPE_MASK 0x1C00000 +#define ADF_VF2PF_SMALL_BLOCK_REQ_TYPE_MASK 0x3C00000 + +/* PF->VF Block Response Type */ +#define ADF_PF2VF_BLOCK_RESP_TYPE_DATA 0x0 +#define ADF_PF2VF_BLOCK_RESP_TYPE_CRC 0x1 +#define ADF_PF2VF_BLOCK_RESP_TYPE_ERROR 0x2 +#define ADF_PF2VF_BLOCK_RESP_TYPE_SHIFT 6 +#define ADF_PF2VF_BLOCK_RESP_DATA_SHIFT 8 +#define ADF_PF2VF_BLOCK_RESP_TYPE_MASK 0x000000C0 +#define ADF_PF2VF_BLOCK_RESP_DATA_MASK 0x0000FF00 + +/* PF-VF block message header bytes */ +#define ADF_VF2PF_BLOCK_VERSION_BYTE 0 +#define ADF_VF2PF_BLOCK_LEN_BYTE 1 +#define ADF_VF2PF_BLOCK_DATA 2 + +/* PF->VF Block Error Code */ +#define ADF_PF2VF_INVALID_BLOCK_TYPE 0x0 +#define ADF_PF2VF_INVALID_BYTE_NUM_REQ 0x1 +#define ADF_PF2VF_PAYLOAD_TRUNCATED 0x2 +#define ADF_PF2VF_UNSPECIFIED_ERROR 0x3 + +/* VF->PF messages */ +#define ADF_VF2PF_IN_USE_BY_VF 0x00006AC2 +#define ADF_VF2PF_IN_USE_BY_VF_MASK 0x0000FFFE +#define ADF_VF2PF_INT BIT(16) +#define ADF_VF2PF_MSGORIGIN_SYSTEM BIT(17) +#define ADF_VF2PF_MSGTYPE_MASK 0x003C0000 +#define ADF_VF2PF_MSGTYPE_SHIFT 18 +#define ADF_VF2PF_MSGTYPE_INIT 0x3 +#define ADF_VF2PF_MSGTYPE_SHUTDOWN 0x4 +#define ADF_VF2PF_MSGTYPE_VERSION_REQ 0x5 +#define ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ 0x6 +#define ADF_VF2PF_MSGTYPE_GET_LARGE_BLOCK_REQ 0x7 +#define ADF_VF2PF_MSGTYPE_GET_MEDIUM_BLOCK_REQ 0x8 +#define ADF_VF2PF_MSGTYPE_GET_SMALL_BLOCK_REQ 0x9 +#define ADF_VF2PF_MSGTYPE_NOTIFY 0xa +#define ADF_VF2PF_MSGGENC_RESTARTING_COMPLETE 0x0 + +/* Block message types + * 0..15 - 32 byte message + * 16..23 - 64 byte message + * 24..27 - 128 byte message + * 2 - Get Capability Request message + */ +#define ADF_VF2PF_BLOCK_MSG_CAP_SUMMARY 2 +#define ADF_VF2PF_BLOCK_MSG_GET_RING_TO_SVC_REQ 0x3 + +/* VF->PF Compatible Version Request */ +#define ADF_VF2PF_COMPAT_VER_REQ_SHIFT 22 + +/* How long to wait for far side to acknowledge receipt */ +#define ADF_IOV_MSG_ACK_DELAY_US 5 +#define ADF_IOV_MSG_ACK_EXP_MAX_DELAY_US (5 * 1000) +#define ADF_IOV_MSG_ACK_DELAY_MS 5 +#define ADF_IOV_MSG_ACK_LIN_MAX_DELAY_US (2 * 1000 * 1000) +/* If CSR is busy, how long to delay before retrying */ +#define ADF_IOV_MSG_RETRY_DELAY 5 +#define ADF_IOV_MSG_MAX_RETRIES 10 +/* How long to wait for a response from the other side */ +#define ADF_IOV_MSG_RESP_TIMEOUT 100 +/* How often to retry when there is no response */ +#define ADF_IOV_MSG_RESP_RETRIES 5 + +#define ADF_IOV_RATELIMIT_INTERVAL 8 +#define ADF_IOV_RATELIMIT_BURST 130 + +/* CRC Calculation */ +#define ADF_CRC8_INIT_VALUE 0xFF +/* PF VF message byte shift */ +#define ADF_PFVF_DATA_SHIFT 8 +#define ADF_PFVF_DATA_MASK 0xFF +#endif /* ADF_IOV_MSG_H */ diff --git a/sys/dev/qat/include/adf_ver_dbg.h b/sys/dev/qat/include/adf_ver_dbg.h new file mode 100644 index 00000000000..be4ed24df75 --- /dev/null +++ b/sys/dev/qat/include/adf_ver_dbg.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_VER_DBG_H_ +#define ADF_VER_DBG_H_ + +struct adf_accel_dev; +int adf_ver_dbg_add(struct adf_accel_dev *accel_dev); +void adf_ver_dbg_del(struct adf_accel_dev *accel_dev); + +#endif /* ADF_VER_DBG_H_ */ diff --git a/sys/dev/qat/include/common/adf_accel_devices.h b/sys/dev/qat/include/common/adf_accel_devices.h new file mode 100644 index 00000000000..ad0e7433525 --- /dev/null +++ b/sys/dev/qat/include/common/adf_accel_devices.h @@ -0,0 +1,585 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_ACCEL_DEVICES_H_ +#define ADF_ACCEL_DEVICES_H_ + +#include "qat_freebsd.h" +#include "adf_cfg_common.h" + +#define ADF_CFG_NUM_SERVICES 4 + +#define ADF_DH895XCC_DEVICE_NAME "dh895xcc" +#define ADF_DH895XCCVF_DEVICE_NAME "dh895xccvf" +#define ADF_C62X_DEVICE_NAME "c6xx" +#define ADF_C62XVF_DEVICE_NAME "c6xxvf" +#define ADF_C3XXX_DEVICE_NAME "c3xxx" +#define ADF_C3XXXVF_DEVICE_NAME "c3xxxvf" +#define ADF_200XX_DEVICE_NAME "200xx" +#define ADF_200XXVF_DEVICE_NAME "200xxvf" +#define ADF_C4XXX_DEVICE_NAME "c4xxx" +#define ADF_C4XXXVF_DEVICE_NAME "c4xxxvf" +#define ADF_DH895XCC_PCI_DEVICE_ID 0x435 +#define ADF_DH895XCCIOV_PCI_DEVICE_ID 0x443 +#define ADF_C62X_PCI_DEVICE_ID 0x37c8 +#define ADF_C62XIOV_PCI_DEVICE_ID 0x37c9 +#define ADF_C3XXX_PCI_DEVICE_ID 0x19e2 +#define ADF_C3XXXIOV_PCI_DEVICE_ID 0x19e3 +#define ADF_200XX_PCI_DEVICE_ID 0x18ee +#define ADF_200XXIOV_PCI_DEVICE_ID 0x18ef +#define ADF_D15XX_PCI_DEVICE_ID 0x6f54 +#define ADF_D15XXIOV_PCI_DEVICE_ID 0x6f55 +#define ADF_C4XXX_PCI_DEVICE_ID 0x18a0 +#define ADF_C4XXXIOV_PCI_DEVICE_ID 0x18a1 + +#define IS_QAT_GEN3(ID) ({ (ID == ADF_C4XXX_PCI_DEVICE_ID); }) +#define ADF_VF2PF_SET_SIZE 32 +#define ADF_MAX_VF2PF_SET 4 +#define ADF_VF2PF_SET_OFFSET(set_nr) ((set_nr)*ADF_VF2PF_SET_SIZE) +#define ADF_VF2PF_VFNR_TO_SET(vf_nr) ((vf_nr) / ADF_VF2PF_SET_SIZE) +#define ADF_VF2PF_VFNR_TO_MASK(vf_nr) \ + ({ \ + u32 vf_nr_ = (vf_nr); \ + BIT((vf_nr_)-ADF_VF2PF_SET_SIZE *ADF_VF2PF_VFNR_TO_SET( \ + vf_nr_)); \ + }) + +#define ADF_DEVICE_FUSECTL_OFFSET 0x40 +#define ADF_DEVICE_LEGFUSE_OFFSET 0x4C +#define ADF_DEVICE_FUSECTL_MASK 0x80000000 +#define ADF_PCI_MAX_BARS 3 +#define ADF_DEVICE_NAME_LENGTH 32 +#define ADF_ETR_MAX_RINGS_PER_BANK 16 +#define ADF_MAX_MSIX_VECTOR_NAME 16 +#define ADF_DEVICE_NAME_PREFIX "qat_" +#define ADF_STOP_RETRY 50 +#define ADF_NUM_THREADS_PER_AE (8) +#define ADF_AE_ADMIN_THREAD (7) +#define ADF_NUM_PKE_STRAND (2) +#define ADF_AE_STRAND0_THREAD (8) +#define ADF_AE_STRAND1_THREAD (9) +#define ADF_NUM_HB_CNT_PER_AE (ADF_NUM_THREADS_PER_AE + ADF_NUM_PKE_STRAND) +#define ADF_CFG_NUM_SERVICES 4 +#define ADF_SRV_TYPE_BIT_LEN 3 +#define ADF_SRV_TYPE_MASK 0x7 +#define ADF_RINGS_PER_SRV_TYPE 2 +#define ADF_THRD_ABILITY_BIT_LEN 4 +#define ADF_THRD_ABILITY_MASK 0xf +#define ADF_VF_OFFSET 0x8 +#define ADF_MAX_FUNC_PER_DEV 0x7 +#define ADF_PCI_DEV_OFFSET 0x3 + +#define ADF_SRV_TYPE_BIT_LEN 3 +#define ADF_SRV_TYPE_MASK 0x7 + +#define GET_SRV_TYPE(ena_srv_mask, srv) \ + (((ena_srv_mask) >> (ADF_SRV_TYPE_BIT_LEN * (srv))) & ADF_SRV_TYPE_MASK) + +#define ADF_DEFAULT_RING_TO_SRV_MAP \ + (CRYPTO | CRYPTO << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + NA << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +enum adf_accel_capabilities { + ADF_ACCEL_CAPABILITIES_NULL = 0, + ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = 1, + ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = 2, + ADF_ACCEL_CAPABILITIES_CIPHER = 4, + ADF_ACCEL_CAPABILITIES_AUTHENTICATION = 8, + ADF_ACCEL_CAPABILITIES_COMPRESSION = 32, + ADF_ACCEL_CAPABILITIES_DEPRECATED = 64, + ADF_ACCEL_CAPABILITIES_RANDOM_NUMBER = 128 +}; + +struct adf_bar { + rman_res_t base_addr; + struct resource *virt_addr; + rman_res_t size; +} __packed; + +struct adf_accel_msix { + struct msix_entry *entries; + u32 num_entries; +} __packed; + +struct adf_accel_pci { + device_t pci_dev; + struct adf_accel_msix msix_entries; + struct adf_bar pci_bars[ADF_PCI_MAX_BARS]; + uint8_t revid; + uint8_t sku; + int node; +} __packed; + +enum dev_state { DEV_DOWN = 0, DEV_UP }; + +enum dev_sku_info { + DEV_SKU_1 = 0, + DEV_SKU_2, + DEV_SKU_3, + DEV_SKU_4, + DEV_SKU_VF, + DEV_SKU_1_CY, + DEV_SKU_2_CY, + DEV_SKU_3_CY, + DEV_SKU_UNKNOWN +}; + +static inline const char * +get_sku_info(enum dev_sku_info info) +{ + switch (info) { + case DEV_SKU_1: + return "SKU1"; + case DEV_SKU_1_CY: + return "SKU1CY"; + case DEV_SKU_2: + return "SKU2"; + case DEV_SKU_2_CY: + return "SKU2CY"; + case DEV_SKU_3: + return "SKU3"; + case DEV_SKU_3_CY: + return "SKU3CY"; + case DEV_SKU_4: + return "SKU4"; + case DEV_SKU_VF: + return "SKUVF"; + case DEV_SKU_UNKNOWN: + default: + break; + } + return "Unknown SKU"; +} + +enum adf_accel_unit_services { + ADF_ACCEL_SERVICE_NULL = 0, + ADF_ACCEL_INLINE_CRYPTO = 1, + ADF_ACCEL_CRYPTO = 2, + ADF_ACCEL_COMPRESSION = 4 +}; + +struct adf_ae_info { + u32 num_asym_thd; + u32 num_sym_thd; + u32 num_dc_thd; +} __packed; + +struct adf_accel_unit { + u8 au_mask; + u32 accel_mask; + u64 ae_mask; + u64 comp_ae_mask; + u32 num_ae; + enum adf_accel_unit_services services; +} __packed; + +struct adf_accel_unit_info { + u32 inline_ingress_msk; + u32 inline_egress_msk; + u32 sym_ae_msk; + u32 asym_ae_msk; + u32 dc_ae_msk; + u8 num_cy_au; + u8 num_dc_au; + u8 num_inline_au; + struct adf_accel_unit *au; + const struct adf_ae_info *ae_info; +} __packed; + +struct adf_hw_aram_info { + /* Inline Egress mask. "1" = AE is working with egress traffic */ + u32 inline_direction_egress_mask; + /* Inline congestion managmenet profiles set in config file */ + u32 inline_congest_mngt_profile; + /* Initialise CY AE mask, "1" = AE is used for CY operations */ + u32 cy_ae_mask; + /* Initialise DC AE mask, "1" = AE is used for DC operations */ + u32 dc_ae_mask; + /* Number of long words used to define the ARAM regions */ + u32 num_aram_lw_entries; + /* ARAM region definitions */ + u32 mmp_region_size; + u32 mmp_region_offset; + u32 skm_region_size; + u32 skm_region_offset; + /* + * Defines size and offset of compression intermediate buffers stored + * in ARAM (device's on-chip memory). + */ + u32 inter_buff_aram_region_size; + u32 inter_buff_aram_region_offset; + u32 sadb_region_size; + u32 sadb_region_offset; +} __packed; + +struct adf_hw_device_class { + const char *name; + const enum adf_device_type type; + uint32_t instances; +} __packed; + +struct arb_info { + u32 arbiter_offset; + u32 wrk_thd_2_srv_arb_map; + u32 wrk_cfg_offset; +} __packed; + +struct admin_info { + u32 admin_msg_ur; + u32 admin_msg_lr; + u32 mailbox_offset; +} __packed; + +struct adf_cfg_device_data; +struct adf_accel_dev; +struct adf_etr_data; +struct adf_etr_ring_data; + +struct adf_hw_device_data { + struct adf_hw_device_class *dev_class; + uint32_t (*get_accel_mask)(struct adf_accel_dev *accel_dev); + uint32_t (*get_ae_mask)(struct adf_accel_dev *accel_dev); + uint32_t (*get_sram_bar_id)(struct adf_hw_device_data *self); + uint32_t (*get_misc_bar_id)(struct adf_hw_device_data *self); + uint32_t (*get_etr_bar_id)(struct adf_hw_device_data *self); + uint32_t (*get_num_aes)(struct adf_hw_device_data *self); + uint32_t (*get_num_accels)(struct adf_hw_device_data *self); + void (*notify_and_wait_ethernet)(struct adf_accel_dev *accel_dev); + bool (*get_eth_doorbell_msg)(struct adf_accel_dev *accel_dev); + uint32_t (*get_pf2vf_offset)(uint32_t i); + uint32_t (*get_vintmsk_offset)(uint32_t i); + u32 (*get_vintsou_offset)(void); + void (*get_arb_info)(struct arb_info *arb_csrs_info); + void (*get_admin_info)(struct admin_info *admin_csrs_info); + void (*get_errsou_offset)(u32 *errsou3, u32 *errsou5); + uint32_t (*get_num_accel_units)(struct adf_hw_device_data *self); + int (*init_accel_units)(struct adf_accel_dev *accel_dev); + void (*exit_accel_units)(struct adf_accel_dev *accel_dev); + uint32_t (*get_clock_speed)(struct adf_hw_device_data *self); + enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self); + bool (*check_prod_sku)(struct adf_accel_dev *accel_dev); + int (*alloc_irq)(struct adf_accel_dev *accel_dev); + void (*free_irq)(struct adf_accel_dev *accel_dev); + void (*enable_error_correction)(struct adf_accel_dev *accel_dev); + int (*check_uncorrectable_error)(struct adf_accel_dev *accel_dev); + void (*print_err_registers)(struct adf_accel_dev *accel_dev); + void (*disable_error_interrupts)(struct adf_accel_dev *accel_dev); + int (*init_ras)(struct adf_accel_dev *accel_dev); + void (*exit_ras)(struct adf_accel_dev *accel_dev); + void (*disable_arb)(struct adf_accel_dev *accel_dev); + void (*update_ras_errors)(struct adf_accel_dev *accel_dev, int error); + bool (*ras_interrupts)(struct adf_accel_dev *accel_dev, + bool *reset_required); + int (*init_admin_comms)(struct adf_accel_dev *accel_dev); + void (*exit_admin_comms)(struct adf_accel_dev *accel_dev); + int (*send_admin_init)(struct adf_accel_dev *accel_dev); + void (*set_asym_rings_mask)(struct adf_accel_dev *accel_dev); + int (*get_ring_to_svc_map)(struct adf_accel_dev *accel_dev, + u16 *ring_to_svc_map); + uint32_t (*get_accel_cap)(struct adf_accel_dev *accel_dev); + int (*init_arb)(struct adf_accel_dev *accel_dev); + void (*exit_arb)(struct adf_accel_dev *accel_dev); + void (*get_arb_mapping)(struct adf_accel_dev *accel_dev, + const uint32_t **cfg); + int (*get_heartbeat_status)(struct adf_accel_dev *accel_dev); + uint32_t (*get_ae_clock)(struct adf_hw_device_data *self); + void (*disable_iov)(struct adf_accel_dev *accel_dev); + void (*configure_iov_threads)(struct adf_accel_dev *accel_dev, + bool enable); + void (*enable_ints)(struct adf_accel_dev *accel_dev); + bool (*check_slice_hang)(struct adf_accel_dev *accel_dev); + int (*set_ssm_wdtimer)(struct adf_accel_dev *accel_dev); + int (*enable_vf2pf_comms)(struct adf_accel_dev *accel_dev); + int (*disable_vf2pf_comms)(struct adf_accel_dev *accel_dev); + void (*reset_device)(struct adf_accel_dev *accel_dev); + void (*reset_hw_units)(struct adf_accel_dev *accel_dev); + int (*measure_clock)(struct adf_accel_dev *accel_dev); + void (*restore_device)(struct adf_accel_dev *accel_dev); + uint32_t (*get_obj_cfg_ae_mask)(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services); + int (*add_pke_stats)(struct adf_accel_dev *accel_dev); + void (*remove_pke_stats)(struct adf_accel_dev *accel_dev); + int (*add_misc_error)(struct adf_accel_dev *accel_dev); + int (*count_ras_event)(struct adf_accel_dev *accel_dev, + u32 *ras_event, + char *aeidstr); + void (*remove_misc_error)(struct adf_accel_dev *accel_dev); + int (*configure_accel_units)(struct adf_accel_dev *accel_dev); + uint32_t (*get_objs_num)(struct adf_accel_dev *accel_dev); + const char *(*get_obj_name)(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services); + void (*pre_reset)(struct adf_accel_dev *accel_dev); + void (*post_reset)(struct adf_accel_dev *accel_dev); + const char *fw_name; + const char *fw_mmp_name; + bool reset_ack; + uint32_t fuses; + uint32_t accel_capabilities_mask; + uint32_t instance_id; + uint16_t accel_mask; + u32 aerucm_mask; + u32 ae_mask; + u32 service_mask; + uint16_t tx_rings_mask; + uint8_t tx_rx_gap; + uint8_t num_banks; + u8 num_rings_per_bank; + uint8_t num_accel; + uint8_t num_logical_accel; + uint8_t num_engines; + uint8_t min_iov_compat_ver; + int (*get_storage_enabled)(struct adf_accel_dev *accel_dev, + uint32_t *storage_enabled); + u8 query_storage_cap; + u32 clock_frequency; + u8 storage_enable; + u32 extended_dc_capabilities; + int (*config_device)(struct adf_accel_dev *accel_dev); + u16 asym_rings_mask; + int (*get_fw_image_type)(struct adf_accel_dev *accel_dev, + enum adf_cfg_fw_image_type *fw_image_type); + u16 ring_to_svc_map; +} __packed; + +/* helper enum for performing CSR operations */ +enum operation { + AND, + OR, +}; + +/* 32-bit CSR write macro */ +#define ADF_CSR_WR(csr_base, csr_offset, val) \ + bus_write_4(csr_base, csr_offset, val) + +/* 64-bit CSR write macro */ +#ifdef __x86_64__ +#define ADF_CSR_WR64(csr_base, csr_offset, val) \ + bus_write_8(csr_base, csr_offset, val) +#else +static __inline void +adf_csr_wr64(struct resource *csr_base, bus_size_t offset, uint64_t value) +{ + bus_write_4(csr_base, offset, (uint32_t)value); + bus_write_4(csr_base, offset + 4, (uint32_t)(value >> 32)); +} +#define ADF_CSR_WR64(csr_base, csr_offset, val) \ + adf_csr_wr64(csr_base, csr_offset, val) +#endif + +/* 32-bit CSR read macro */ +#define ADF_CSR_RD(csr_base, csr_offset) bus_read_4(csr_base, csr_offset) + +/* 64-bit CSR read macro */ +#ifdef __x86_64__ +#define ADF_CSR_RD64(csr_base, csr_offset) bus_read_8(csr_base, csr_offset) +#else +static __inline uint64_t +adf_csr_rd64(struct resource *csr_base, bus_size_t offset) +{ + return (((uint64_t)bus_read_4(csr_base, offset)) | + (((uint64_t)bus_read_4(csr_base, offset + 4)) << 32)); +} +#define ADF_CSR_RD64(csr_base, csr_offset) adf_csr_rd64(csr_base, csr_offset) +#endif + +#define GET_DEV(accel_dev) ((accel_dev)->accel_pci_dev.pci_dev) +#define GET_BARS(accel_dev) ((accel_dev)->accel_pci_dev.pci_bars) +#define GET_HW_DATA(accel_dev) (accel_dev->hw_device) +#define GET_MAX_BANKS(accel_dev) (GET_HW_DATA(accel_dev)->num_banks) +#define GET_DEV_SKU(accel_dev) (accel_dev->accel_pci_dev.sku) +#define GET_NUM_RINGS_PER_BANK(accel_dev) \ + (GET_HW_DATA(accel_dev)->num_rings_per_bank) +#define GET_MAX_ACCELENGINES(accel_dev) (GET_HW_DATA(accel_dev)->num_engines) +#define accel_to_pci_dev(accel_ptr) accel_ptr->accel_pci_dev.pci_dev +#define GET_SRV_TYPE(ena_srv_mask, srv) \ + (((ena_srv_mask) >> (ADF_SRV_TYPE_BIT_LEN * (srv))) & ADF_SRV_TYPE_MASK) +#define SET_ASYM_MASK(asym_mask, srv) \ + ({ \ + typeof(srv) srv_ = (srv); \ + (asym_mask) |= ((1 << (srv_)*ADF_RINGS_PER_SRV_TYPE) | \ + (1 << ((srv_)*ADF_RINGS_PER_SRV_TYPE + 1))); \ + }) + +#define GET_NUM_RINGS_PER_BANK(accel_dev) \ + (GET_HW_DATA(accel_dev)->num_rings_per_bank) +#define GET_MAX_PROCESSES(accel_dev) \ + ({ \ + typeof(accel_dev) dev = (accel_dev); \ + (GET_MAX_BANKS(dev) * (GET_NUM_RINGS_PER_BANK(dev) / 2)); \ + }) +#define GET_DU_TABLE(accel_dev) (accel_dev->du_table) + +static inline void +adf_csr_fetch_and_and(struct resource *csr, size_t offs, unsigned long mask) +{ + unsigned int val = ADF_CSR_RD(csr, offs); + + val &= mask; + ADF_CSR_WR(csr, offs, val); +} + +static inline void +adf_csr_fetch_and_or(struct resource *csr, size_t offs, unsigned long mask) +{ + unsigned int val = ADF_CSR_RD(csr, offs); + + val |= mask; + ADF_CSR_WR(csr, offs, val); +} + +static inline void +adf_csr_fetch_and_update(enum operation op, + struct resource *csr, + size_t offs, + unsigned long mask) +{ + switch (op) { + case AND: + adf_csr_fetch_and_and(csr, offs, mask); + break; + case OR: + adf_csr_fetch_and_or(csr, offs, mask); + break; + } +} + +struct pfvf_stats { + struct dentry *stats_file; + /* Messages put in CSR */ + unsigned int tx; + /* Messages read from CSR */ + unsigned int rx; + /* Interrupt fired but int bit was clear */ + unsigned int spurious; + /* Block messages sent */ + unsigned int blk_tx; + /* Block messages received */ + unsigned int blk_rx; + /* Blocks received with CRC errors */ + unsigned int crc_err; + /* CSR in use by other side */ + unsigned int busy; + /* Receiver did not acknowledge */ + unsigned int no_ack; + /* Collision detected */ + unsigned int collision; + /* Couldn't send a response */ + unsigned int tx_timeout; + /* Didn't receive a response */ + unsigned int rx_timeout; + /* Responses received */ + unsigned int rx_rsp; + /* Messages re-transmitted */ + unsigned int retry; + /* Event put timeout */ + unsigned int event_timeout; +}; + +#define NUM_PFVF_COUNTERS 14 + +void adf_get_admin_info(struct admin_info *admin_csrs_info); +struct adf_admin_comms { + bus_addr_t phy_addr; + bus_addr_t const_tbl_addr; + bus_addr_t aram_map_phys_addr; + bus_addr_t phy_hb_addr; + bus_dmamap_t aram_map; + bus_dmamap_t const_tbl_map; + bus_dmamap_t hb_map; + char *virt_addr; + char *virt_hb_addr; + struct resource *mailbox_addr; + struct sx lock; + struct bus_dmamem dma_mem; + struct bus_dmamem dma_hb; +}; + +struct icp_qat_fw_loader_handle; +struct adf_fw_loader_data { + struct icp_qat_fw_loader_handle *fw_loader; + const struct firmware *uof_fw; + const struct firmware *mmp_fw; +}; + +struct adf_accel_vf_info { + struct adf_accel_dev *accel_dev; + struct mutex pf2vf_lock; /* protect CSR access for PF2VF messages */ + u32 vf_nr; + bool init; + u8 compat_ver; + struct pfvf_stats pfvf_counters; +}; + +struct adf_fw_versions { + u8 fw_version_major; + u8 fw_version_minor; + u8 fw_version_patch; + u8 mmp_version_major; + u8 mmp_version_minor; + u8 mmp_version_patch; +}; + +#define ADF_COMPAT_CHECKER_MAX 8 +typedef int (*adf_iov_compat_checker_t)(struct adf_accel_dev *accel_dev, + u8 vf_compat_ver); +struct adf_accel_compat_manager { + u8 num_chker; + adf_iov_compat_checker_t iov_compat_checkers[ADF_COMPAT_CHECKER_MAX]; +}; + +struct adf_heartbeat; +struct adf_accel_dev { + struct adf_hw_aram_info *aram_info; + struct adf_accel_unit_info *au_info; + struct adf_etr_data *transport; + struct adf_hw_device_data *hw_device; + struct adf_cfg_device_data *cfg; + struct adf_fw_loader_data *fw_loader; + struct adf_admin_comms *admin; + struct adf_heartbeat *heartbeat; + struct adf_fw_versions fw_versions; + unsigned int autoreset_on_error; + struct adf_fw_counters_data *fw_counters_data; + struct sysctl_oid *debugfs_ae_config; + struct list_head crypto_list; + atomic_t *ras_counters; + unsigned long status; + atomic_t ref_count; + bus_dma_tag_t dma_tag; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *ras_correctable; + struct sysctl_oid *ras_uncorrectable; + struct sysctl_oid *ras_fatal; + struct sysctl_oid *ras_reset; + struct sysctl_oid *pke_replay_dbgfile; + struct sysctl_oid *misc_error_dbgfile; + struct list_head list; + struct adf_accel_pci accel_pci_dev; + struct adf_accel_compat_manager *cm; + u8 compat_ver; + union { + struct { + /* vf_info is non-zero when SR-IOV is init'ed */ + struct adf_accel_vf_info *vf_info; + int num_vfs; + } pf; + struct { + struct resource *irq; + void *cookie; + char *irq_name; + struct task pf2vf_bh_tasklet; + struct mutex vf2pf_lock; /* protect CSR access */ + int iov_msg_completion; + uint8_t compatible; + uint8_t pf_version; + u8 pf2vf_block_byte; + u8 pf2vf_block_resp_type; + struct pfvf_stats pfvf_counters; + } vf; + } u1; + bool is_vf; + u32 accel_id; + void *lac_dev; +}; +#endif diff --git a/sys/dev/qat/include/common/adf_cfg.h b/sys/dev/qat/include/common/adf_cfg.h new file mode 100644 index 00000000000..edc4813cb69 --- /dev/null +++ b/sys/dev/qat/include/common/adf_cfg.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_H_ +#define ADF_CFG_H_ + +#include +#include "adf_accel_devices.h" +#include "adf_cfg_common.h" +#include "adf_cfg_strings.h" + +struct adf_cfg_key_val { + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + enum adf_cfg_val_type type; + struct list_head list; +}; + +struct adf_cfg_section { + char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; + bool processed; + bool is_derived; + struct list_head list; + struct list_head param_head; +}; + +struct adf_cfg_device_data { + struct adf_cfg_device *dev; + struct list_head sec_list; + struct sysctl_oid *debug; + struct sx lock; +}; + +struct adf_cfg_depot_list { + struct list_head sec_list; +}; + +int adf_cfg_dev_add(struct adf_accel_dev *accel_dev); +void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev); +int adf_cfg_depot_restore_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *dev_hp_cfg); +int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name); +void adf_cfg_del_all(struct adf_accel_dev *accel_dev); +void adf_cfg_depot_del_all(struct list_head *head); +int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const char *key, + const void *val, + enum adf_cfg_val_type type); +int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev, + const char *section, + const char *name, + char *value); +int adf_cfg_save_section(struct adf_accel_dev *accel_dev, + const char *name, + struct adf_cfg_section *section); +int adf_cfg_depot_save_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *dev_hp_cfg); +struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev, + const char *sec_name); +int adf_cfg_derived_section_add(struct adf_accel_dev *accel_dev, + const char *name); +int adf_cfg_remove_key_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const char *key); +int adf_cfg_setup_irq(struct adf_accel_dev *accel_dev); +void adf_cfg_set_asym_rings_mask(struct adf_accel_dev *accel_dev); +void adf_cfg_gen_dispatch_arbiter(struct adf_accel_dev *accel_dev, + const u32 *thrd_to_arb_map, + u32 *thrd_to_arb_map_gen, + u32 total_engines); +int adf_cfg_get_fw_image_type(struct adf_accel_dev *accel_dev, + enum adf_cfg_fw_image_type *fw_image_type); +int adf_cfg_get_services_enabled(struct adf_accel_dev *accel_dev, + u16 *ring_to_svc_map); +int adf_cfg_restore_section(struct adf_accel_dev *accel_dev, + struct adf_cfg_section *section); +void adf_cfg_keyval_del_all(struct list_head *head); +#endif diff --git a/sys/dev/qat/include/common/adf_cfg_common.h b/sys/dev/qat/include/common/adf_cfg_common.h new file mode 100644 index 00000000000..68fb5e8a98b --- /dev/null +++ b/sys/dev/qat/include/common/adf_cfg_common.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_COMMON_H_ +#define ADF_CFG_COMMON_H_ + +#include +#include +#include + +#define ADF_CFG_MAX_STR_LEN 128 +#define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN +/* + * Max value length increased to 128 to support more length of values. + * like Dc0CoreAffinity = 0, 1, 2,... config values to max cores + */ +#define ADF_CFG_MAX_VAL_LEN_IN_BYTES 128 +#define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN +#define ADF_CFG_NULL_TERM_SIZE 1 +#define ADF_CFG_BASE_DEC 10 +#define ADF_CFG_BASE_HEX 16 +#define ADF_CFG_ALL_DEVICES 0xFFFE +#define ADF_CFG_NO_DEVICE 0xFFFF +#define ADF_CFG_AFFINITY_WHATEVER 0xFF +#define MAX_DEVICE_NAME_SIZE 32 +#define ADF_MAX_DEVICES (32 * 32) +#define ADF_MAX_ACCELENGINES 12 +#define ADF_CFG_STORAGE_ENABLED 1 +#define ADF_DEVS_ARRAY_SIZE BITS_TO_LONGS(ADF_MAX_DEVICES) +#define ADF_SSM_WDT_PKE_DEFAULT_VALUE 0x3000000 +#define ADF_WDT_TIMER_SYM_COMP_MS 3 +#define ADF_MIN_HB_TIMER_MS 100 +#define ADF_CFG_MAX_NUM_OF_SECTIONS 16 +#define ADF_CFG_MAX_NUM_OF_TOKENS 16 +#define ADF_CFG_MAX_TOKENS_IN_CONFIG 8 +#define ADF_CFG_RESP_POLL 1 +#define ADF_CFG_RESP_EPOLL 2 +#define ADF_CFG_DEF_CY_RING_ASYM_SIZE 64 +#define ADF_CFG_DEF_CY_RING_SYM_SIZE 512 +#define ADF_CFG_DEF_DC_RING_SIZE 512 +#define ADF_CFG_MAX_CORE_NUM 256 +#define ADF_CFG_MAX_TOKENS ADF_CFG_MAX_CORE_NUM +#define ADF_CFG_MAX_TOKEN_LEN 10 +#define ADF_CFG_ACCEL_DEF_COALES 1 +#define ADF_CFG_ACCEL_DEF_COALES_TIMER 10000 +#define ADF_CFG_ACCEL_DEF_COALES_NUM_MSG 0 +#define ADF_CFG_ASYM_SRV_MASK 1 +#define ADF_CFG_SYM_SRV_MASK 2 +#define ADF_CFG_DC_SRV_MASK 8 +#define ADF_CFG_UNKNOWN_SRV_MASK 0 +#define ADF_CFG_DEF_ASYM_MASK 0x03 +#define ADF_CFG_MAX_SERVICES 4 +#define ADF_MAX_SERVICES 3 + +enum adf_svc_type { + ADF_SVC_ASYM = 0, + ADF_SVC_SYM = 1, + ADF_SVC_DC = 2, + ADF_SVC_NONE = 3 +}; + +struct adf_pci_address { + unsigned char bus; + unsigned char dev; + unsigned char func; +} __packed; + +#define ADF_CFG_SERV_RING_PAIR_0_SHIFT 0 +#define ADF_CFG_SERV_RING_PAIR_1_SHIFT 3 +#define ADF_CFG_SERV_RING_PAIR_2_SHIFT 6 +#define ADF_CFG_SERV_RING_PAIR_3_SHIFT 9 + +enum adf_cfg_service_type { NA = 0, CRYPTO, COMP, SYM, ASYM, USED }; + +enum adf_cfg_bundle_type { FREE, KERNEL, USER }; + +enum adf_cfg_val_type { ADF_DEC, ADF_HEX, ADF_STR }; + +enum adf_device_type { + DEV_UNKNOWN = 0, + DEV_DH895XCC, + DEV_DH895XCCVF, + DEV_C62X, + DEV_C62XVF, + DEV_C3XXX, + DEV_C3XXXVF, + DEV_200XX, + DEV_200XXVF, + DEV_C4XXX, + DEV_C4XXXVF +}; + +enum adf_cfg_fw_image_type { + ADF_FW_IMAGE_DEFAULT = 0, + ADF_FW_IMAGE_CRYPTO, + ADF_FW_IMAGE_COMPRESSION, + ADF_FW_IMAGE_CUSTOM1 +}; + +struct adf_dev_status_info { + enum adf_device_type type; + uint16_t accel_id; + uint16_t instance_id; + uint8_t num_ae; + uint8_t num_accel; + uint8_t num_logical_accel; + uint8_t banks_per_accel; + uint8_t state; + uint8_t bus; + uint8_t dev; + uint8_t fun; + int domain; + char name[MAX_DEVICE_NAME_SIZE]; + u8 sku; + u32 node_id; + u32 device_mem_available; + u32 pci_device_id; +}; + +struct adf_cfg_device { + /* contains all the bundles info */ + struct adf_cfg_bundle **bundles; + /* contains all the instances info */ + struct adf_cfg_instance **instances; + int bundle_num; + int instance_index; + char name[ADF_CFG_MAX_STR_LEN]; + int dev_id; + int max_kernel_bundle_nr; + u16 total_num_inst; +}; + +enum adf_accel_serv_type { + ADF_ACCEL_SERV_NA = 0x0, + ADF_ACCEL_SERV_ASYM, + ADF_ACCEL_SERV_SYM, + ADF_ACCEL_SERV_RND, + ADF_ACCEL_SERV_DC +}; + +struct adf_cfg_ring { + u8 mode : 1; + enum adf_accel_serv_type serv_type; + u8 number : 4; +}; + +struct adf_cfg_bundle { + /* Section(s) name this bundle is shared by */ + char **sections; + int max_section; + int section_index; + int number; + enum adf_cfg_bundle_type type; + cpuset_t affinity_mask; + int polling_mode; + int instance_num; + int num_of_rings; + /* contains all the info about rings */ + struct adf_cfg_ring **rings; + u16 in_use; +}; + +struct adf_cfg_instance { + enum adf_cfg_service_type stype; + char name[ADF_CFG_MAX_STR_LEN]; + int polling_mode; + cpuset_t affinity_mask; + /* rings within an instance for services */ + int asym_tx; + int asym_rx; + int sym_tx; + int sym_rx; + int dc_tx; + int dc_rx; + int bundle; +}; + +#define ADF_CFG_MAX_CORE_NUM 256 +#define ADF_CFG_MAX_TOKENS_IN_CONFIG 8 +#define ADF_CFG_MAX_TOKEN_LEN 10 +#define ADF_CFG_MAX_TOKENS ADF_CFG_MAX_CORE_NUM +#define ADF_CFG_ACCEL_DEF_COALES 1 +#define ADF_CFG_ACCEL_DEF_COALES_TIMER 10000 +#define ADF_CFG_ACCEL_DEF_COALES_NUM_MSG 0 +#define ADF_CFG_RESP_EPOLL 2 +#define ADF_CFG_SERV_RING_PAIR_1_SHIFT 3 +#define ADF_CFG_SERV_RING_PAIR_2_SHIFT 6 +#define ADF_CFG_SERV_RING_PAIR_3_SHIFT 9 +#define ADF_CFG_RESP_POLL 1 +#define ADF_CFG_ASYM_SRV_MASK 1 +#define ADF_CFG_SYM_SRV_MASK 2 +#define ADF_CFG_DC_SRV_MASK 8 +#define ADF_CFG_UNKNOWN_SRV_MASK 0 +#define ADF_CFG_DEF_ASYM_MASK 0x03 +#define ADF_CFG_MAX_SERVICES 4 + +#define ADF_CFG_HB_DEFAULT_VALUE 500 +#define ADF_CFG_HB_COUNT_THRESHOLD 3 +#define ADF_MIN_HB_TIMER_MS 100 + +enum adf_device_heartbeat_status { + DEV_HB_UNRESPONSIVE = 0, + DEV_HB_ALIVE, + DEV_HB_UNSUPPORTED +}; + +struct adf_dev_heartbeat_status_ctl { + uint16_t device_id; + enum adf_device_heartbeat_status status; +}; +#endif diff --git a/sys/dev/qat/include/common/adf_cfg_strings.h b/sys/dev/qat/include/common/adf_cfg_strings.h new file mode 100644 index 00000000000..2f05dadadc4 --- /dev/null +++ b/sys/dev/qat/include/common/adf_cfg_strings.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_STRINGS_H_ +#define ADF_CFG_STRINGS_H_ + +#define ADF_GENERAL_SEC "GENERAL" +#define ADF_KERNEL_SEC "KERNEL" +#define ADF_ACCEL_SEC "Accelerator" +#define ADF_NUM_CY "NumberCyInstances" +#define ADF_NUM_DC "NumberDcInstances" +#define ADF_RING_SYM_SIZE "NumConcurrentSymRequests" +#define ADF_RING_ASYM_SIZE "NumConcurrentAsymRequests" +#define ADF_RING_DC_SIZE "NumConcurrentRequests" +#define ADF_RING_ASYM_TX "RingAsymTx" +#define ADF_RING_SYM_TX "RingSymTx" +#define ADF_RING_RND_TX "RingNrbgTx" +#define ADF_RING_ASYM_RX "RingAsymRx" +#define ADF_RING_SYM_RX "RingSymRx" +#define ADF_RING_RND_RX "RingNrbgRx" +#define ADF_RING_DC_TX "RingTx" +#define ADF_RING_DC_RX "RingRx" +#define ADF_ETRMGR_BANK "Bank" +#define ADF_RING_BANK_NUM "BankNumber" +#define ADF_CY "Cy" +#define ADF_DC "Dc" +#define ADF_DC_EXTENDED_FEATURES "Device_DcExtendedFeatures" +#define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled" +#define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \ + ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_ENABLED +#define ADF_ETRMGR_COALESCE_TIMER "InterruptCoalescingTimerNs" +#define ADF_ETRMGR_COALESCE_TIMER_FORMAT \ + ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCE_TIMER +#define ADF_ETRMGR_COALESCING_MSG_ENABLED "InterruptCoalescingNumResponses" +#define ADF_ETRMGR_COALESCING_MSG_ENABLED_FORMAT \ + ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_MSG_ENABLED +#define ADF_ETRMGR_CORE_AFFINITY "CoreAffinity" +#define ADF_ETRMGR_CORE_AFFINITY_FORMAT \ + ADF_ETRMGR_BANK "%d" ADF_ETRMGR_CORE_AFFINITY +#define ADF_ACCEL_STR "Accelerator%d" +#define ADF_INLINE_SEC "INLINE" +#define ADF_NUM_CY_ACCEL_UNITS "NumCyAccelUnits" +#define ADF_NUM_DC_ACCEL_UNITS "NumDcAccelUnits" +#define ADF_NUM_INLINE_ACCEL_UNITS "NumInlineAccelUnits" +#define ADF_INLINE_INGRESS "InlineIngress" +#define ADF_INLINE_EGRESS "InlineEgress" +#define ADF_INLINE_CONGEST_MNGT_PROFILE "InlineCongestionManagmentProfile" +#define ADF_INLINE_IPSEC_ALGO_GROUP "InlineIPsecAlgoGroup" +#define ADF_SERVICE_CY "cy" +#define ADF_SERVICE_SYM "sym" +#define ADF_SERVICE_DC "dc" +#define ADF_CFG_CY "cy" +#define ADF_CFG_DC "dc" +#define ADF_CFG_ASYM "asym" +#define ADF_CFG_SYM "sym" +#define ADF_SERVICE_INLINE "inline" +#define ADF_SERVICES_ENABLED "ServicesEnabled" +#define ADF_SERVICES_SEPARATOR ";" + +#define ADF_DEV_SSM_WDT_BULK "CySymAndDcWatchDogTimer" +#define ADF_DEV_SSM_WDT_PKE "CyAsymWatchDogTimer" +#define ADF_DH895XCC_AE_FW_NAME "icp_qat_ae.uof" +#define ADF_CXXX_AE_FW_NAME "icp_qat_ae.suof" +#define ADF_HEARTBEAT_TIMER "HeartbeatTimer" +#define ADF_MMP_VER_KEY "Firmware_MmpVer" +#define ADF_UOF_VER_KEY "Firmware_UofVer" +#define ADF_HW_REV_ID_KEY "HW_RevId" +#define ADF_STORAGE_FIRMWARE_ENABLED "StorageEnabled" +#define ADF_DEV_MAX_BANKS "Device_Max_Banks" +#define ADF_DEV_CAPABILITIES_MASK "Device_Capabilities_Mask" +#define ADF_DEV_NODE_ID "Device_NodeId" +#define ADF_DEV_PKG_ID "Device_PkgId" +#define ADF_FIRST_USER_BUNDLE "FirstUserBundle" +#define ADF_INTERNAL_USERSPACE_SEC_SUFF "_INT_" +#define ADF_LIMIT_DEV_ACCESS "LimitDevAccess" +#define DEV_LIMIT_CFG_ACCESS_TMPL "_D_L_ACC" +#define ADF_DEV_MAX_RINGS_PER_BANK "Device_Max_Rings_Per_Bank" +#define ADF_NUM_PROCESSES "NumProcesses" +#define ADF_DH895XCC_AE_FW_NAME_COMPRESSION "compression.uof" +#define ADF_DH895XCC_AE_FW_NAME_CRYPTO "crypto.uof" +#define ADF_DH895XCC_AE_FW_NAME_CUSTOM1 "custom1.uof" +#define ADF_CXXX_AE_FW_NAME_COMPRESSION "compression.suof" +#define ADF_CXXX_AE_FW_NAME_CRYPTO "crypto.suof" +#define ADF_CXXX_AE_FW_NAME_CUSTOM1 "custom1.suof" +#define ADF_DC_EXTENDED_FEATURES "Device_DcExtendedFeatures" +#define ADF_PKE_DISABLED "PkeServiceDisabled" +#define ADF_INTER_BUF_SIZE "DcIntermediateBufferSizeInKB" +#define ADF_AUTO_RESET_ON_ERROR "AutoResetOnError" +#define ADF_KERNEL_SAL_SEC "KERNEL_QAT" +#define ADF_CFG_DEF_CY_RING_ASYM_SIZE 64 +#define ADF_CFG_DEF_CY_RING_SYM_SIZE 512 +#define ADF_CFG_DEF_DC_RING_SIZE 512 +#define ADF_NUM_PROCESSES "NumProcesses" +#define ADF_SERVICES_ENABLED "ServicesEnabled" +#define ADF_CFG_CY "cy" +#define ADF_CFG_SYM "sym" +#define ADF_CFG_ASYM "asym" +#define ADF_CFG_DC "dc" +#define ADF_POLL_MODE "IsPolled" +#define ADF_DEV_KPT_ENABLE "KptEnabled" +#define ADF_STORAGE_FIRMWARE_ENABLED "StorageEnabled" +#define ADF_RL_FIRMWARE_ENABLED "RateLimitingEnabled" +#define ADF_SERVICES_PROFILE "ServicesProfile" +#define ADF_SERVICES_DEFAULT "DEFAULT" +#define ADF_SERVICES_CRYPTO "CRYPTO" +#define ADF_SERVICES_COMPRESSION "COMPRESSION" +#define ADF_SERVICES_CUSTOM1 "CUSTOM1" + +#define ADF_DC_RING_SIZE (ADF_DC ADF_RING_DC_SIZE) +#define ADF_CY_RING_SYM_SIZE (ADF_CY ADF_RING_SYM_SIZE) +#define ADF_CY_RING_ASYM_SIZE (ADF_CY ADF_RING_ASYM_SIZE) +#define ADF_CY_CORE_AFFINITY_FORMAT ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY +#define ADF_DC_CORE_AFFINITY_FORMAT ADF_DC "%d" ADF_ETRMGR_CORE_AFFINITY +#define ADF_CY_BANK_NUM_FORMAT ADF_CY "%d" ADF_RING_BANK_NUM +#define ADF_DC_BANK_NUM_FORMAT ADF_DC "%d" ADF_RING_BANK_NUM +#define ADF_CY_ASYM_TX_FORMAT ADF_CY "%d" ADF_RING_ASYM_TX +#define ADF_CY_SYM_TX_FORMAT ADF_CY "%d" ADF_RING_SYM_TX +#define ADF_CY_ASYM_RX_FORMAT ADF_CY "%d" ADF_RING_ASYM_RX +#define ADF_CY_SYM_RX_FORMAT ADF_CY "%d" ADF_RING_SYM_RX +#define ADF_DC_TX_FORMAT ADF_DC "%d" ADF_RING_DC_TX +#define ADF_DC_RX_FORMAT ADF_DC "%d" ADF_RING_DC_RX +#define ADF_CY_RING_SYM_SIZE_FORMAT ADF_CY "%d" ADF_RING_SYM_SIZE +#define ADF_CY_RING_ASYM_SIZE_FORMAT ADF_CY "%d" ADF_RING_ASYM_SIZE +#define ADF_DC_RING_SIZE_FORMAT ADF_DC "%d" ADF_RING_DC_SIZE +#define ADF_CY_NAME_FORMAT ADF_CY "%dName" +#define ADF_DC_NAME_FORMAT ADF_DC "%dName" +#define ADF_CY_POLL_MODE_FORMAT ADF_CY "%d" ADF_POLL_MODE +#define ADF_DC_POLL_MODE_FORMAT ADF_DC "%d" ADF_POLL_MODE +#define ADF_USER_SECTION_NAME_FORMAT "%s_INT_%d" +#define ADF_LIMITED_USER_SECTION_NAME_FORMAT "%s_DEV%d_INT_%d" +#define ADF_CONFIG_VERSION "ConfigVersion" +#endif diff --git a/sys/dev/qat/include/common/adf_cfg_user.h b/sys/dev/qat/include/common/adf_cfg_user.h new file mode 100644 index 00000000000..910b0ea5146 --- /dev/null +++ b/sys/dev/qat/include/common/adf_cfg_user.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_USER_H_ +#define ADF_CFG_USER_H_ + +#include "adf_cfg_common.h" +#include "adf_cfg_strings.h" + +struct adf_user_cfg_key_val { + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + union { + struct adf_user_cfg_key_val *next; + uint64_t padding3; + }; + enum adf_cfg_val_type type; +}; + +struct adf_user_cfg_section { + char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; + union { + struct adf_user_cfg_key_val *params; + uint64_t padding1; + }; + union { + struct adf_user_cfg_section *next; + uint64_t padding3; + }; +}; + +struct adf_user_cfg_ctl_data { + union { + struct adf_user_cfg_section *config_section; + uint64_t padding; + }; + u32 device_id; +}; + +struct adf_user_reserve_ring { + u32 accel_id; + u32 bank_nr; + u32 ring_mask; +}; + +#endif diff --git a/sys/dev/qat/include/common/adf_common_drv.h b/sys/dev/qat/include/common/adf_common_drv.h new file mode 100644 index 00000000000..3bb35ed55da --- /dev/null +++ b/sys/dev/qat/include/common/adf_common_drv.h @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_DRV_H +#define ADF_DRV_H + +#include +#include "adf_accel_devices.h" +#include "icp_qat_fw_loader_handle.h" +#include "icp_qat_hal.h" +#include "adf_cfg_user.h" + +#define ADF_MAJOR_VERSION 0 +#define ADF_MINOR_VERSION 6 +#define ADF_BUILD_VERSION 0 +#define ADF_DRV_VERSION \ + __stringify(ADF_MAJOR_VERSION) "." __stringify( \ + ADF_MINOR_VERSION) "." __stringify(ADF_BUILD_VERSION) + +#define ADF_STATUS_RESTARTING 0 +#define ADF_STATUS_STARTING 1 +#define ADF_STATUS_CONFIGURED 2 +#define ADF_STATUS_STARTED 3 +#define ADF_STATUS_AE_INITIALISED 4 +#define ADF_STATUS_AE_UCODE_LOADED 5 +#define ADF_STATUS_AE_STARTED 6 +#define ADF_STATUS_PF_RUNNING 7 +#define ADF_STATUS_IRQ_ALLOCATED 8 +#define ADF_PCIE_FLR_ATTEMPT 10 +#define ADF_STATUS_SYSCTL_CTX_INITIALISED 9 + +#define PCI_EXP_AERUCS 0x104 + +/* PMISC BAR upper and lower offsets in PCIe config space */ +#define ADF_PMISC_L_OFFSET 0x18 +#define ADF_PMISC_U_OFFSET 0x1c + +enum adf_dev_reset_mode { ADF_DEV_RESET_ASYNC = 0, ADF_DEV_RESET_SYNC }; + +enum adf_event { + ADF_EVENT_INIT = 0, + ADF_EVENT_START, + ADF_EVENT_STOP, + ADF_EVENT_SHUTDOWN, + ADF_EVENT_RESTARTING, + ADF_EVENT_RESTARTED, + ADF_EVENT_ERROR, +}; + +struct adf_state { + enum adf_event dev_state; + int dev_id; +}; + +struct service_hndl { + int (*event_hld)(struct adf_accel_dev *accel_dev, enum adf_event event); + unsigned long init_status[ADF_DEVS_ARRAY_SIZE]; + unsigned long start_status[ADF_DEVS_ARRAY_SIZE]; + char *name; + struct list_head list; +}; + +static inline int +get_current_node(void) +{ + return PCPU_GET(domain); +} + +int adf_service_register(struct service_hndl *service); +int adf_service_unregister(struct service_hndl *service); + +int adf_dev_init(struct adf_accel_dev *accel_dev); +int adf_dev_start(struct adf_accel_dev *accel_dev); +int adf_dev_stop(struct adf_accel_dev *accel_dev); +void adf_dev_shutdown(struct adf_accel_dev *accel_dev); +int adf_dev_autoreset(struct adf_accel_dev *accel_dev); +int adf_dev_reset(struct adf_accel_dev *accel_dev, + enum adf_dev_reset_mode mode); +int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, + enum adf_dev_reset_mode mode); +void adf_error_notifier(uintptr_t arg); +int adf_init_fatal_error_wq(void); +void adf_exit_fatal_error_wq(void); +int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr); +int adf_iov_notify(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr); +void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev); +int adf_notify_fatal_error(struct adf_accel_dev *accel_dev); +void adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev); +void adf_pf2vf_notify_uncorrectable_error(struct adf_accel_dev *accel_dev); +void adf_pf2vf_notify_heartbeat_error(struct adf_accel_dev *accel_dev); +typedef int (*adf_iov_block_provider)(struct adf_accel_dev *accel_dev, + u8 **buffer, + u8 *length, + u8 *block_version, + u8 compatibility, + u8 byte_num); +int adf_iov_block_provider_register(u8 block_type, + const adf_iov_block_provider provider); +u8 adf_iov_is_block_provider_registered(u8 block_type); +int adf_iov_block_provider_unregister(u8 block_type, + const adf_iov_block_provider provider); +int adf_iov_block_get(struct adf_accel_dev *accel_dev, + u8 block_type, + u8 *block_version, + u8 *buffer, + u8 *length); +u8 adf_pfvf_crc(u8 start_crc, u8 *buf, u8 len); +int adf_iov_init_compat_manager(struct adf_accel_dev *accel_dev, + struct adf_accel_compat_manager **cm); +int adf_iov_shutdown_compat_manager(struct adf_accel_dev *accel_dev, + struct adf_accel_compat_manager **cm); +int adf_iov_register_compat_checker(struct adf_accel_dev *accel_dev, + const adf_iov_compat_checker_t cc); +int adf_iov_unregister_compat_checker(struct adf_accel_dev *accel_dev, + const adf_iov_compat_checker_t cc); +int adf_pf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev); +int adf_pf_disable_vf2pf_comms(struct adf_accel_dev *accel_dev); +int adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev); +int adf_disable_vf2pf_comms(struct adf_accel_dev *accel_dev); +void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info); +void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data); +void adf_clean_vf_map(bool); +int adf_sysctl_add_fw_versions(struct adf_accel_dev *accel_dev); +int adf_sysctl_remove_fw_versions(struct adf_accel_dev *accel_dev); + +int adf_ctl_dev_register(void); +void adf_ctl_dev_unregister(void); +int adf_pf_vf_capabilities_init(struct adf_accel_dev *accel_dev); +int adf_pf_ext_dc_cap_msg_provider(struct adf_accel_dev *accel_dev, + u8 **buffer, + u8 *length, + u8 *block_version, + u8 compatibility); +int adf_pf_vf_ring_to_svc_init(struct adf_accel_dev *accel_dev); +int adf_pf_ring_to_svc_msg_provider(struct adf_accel_dev *accel_dev, + u8 **buffer, + u8 *length, + u8 *block_version, + u8 compatibility, + u8 byte_num); +int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, + struct adf_accel_dev *pf); +void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, + struct adf_accel_dev *pf); +struct list_head *adf_devmgr_get_head(void); +struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id); +struct adf_accel_dev *adf_devmgr_get_first(void); +struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(device_t pci_dev); +int adf_devmgr_verify_id(uint32_t *id); +void adf_devmgr_get_num_dev(uint32_t *num); +int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev); +int adf_dev_started(struct adf_accel_dev *accel_dev); +int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev); +int adf_dev_restarting_notify_sync(struct adf_accel_dev *accel_dev); +int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev); +int adf_dev_stop_notify_sync(struct adf_accel_dev *accel_dev); +int adf_ae_init(struct adf_accel_dev *accel_dev); +int adf_ae_shutdown(struct adf_accel_dev *accel_dev); +int adf_ae_fw_load(struct adf_accel_dev *accel_dev); +void adf_ae_fw_release(struct adf_accel_dev *accel_dev); +int adf_ae_start(struct adf_accel_dev *accel_dev); +int adf_ae_stop(struct adf_accel_dev *accel_dev); + +int adf_aer_store_ppaerucm_reg(device_t pdev, + struct adf_hw_device_data *hw_data); + +int adf_enable_aer(struct adf_accel_dev *accel_dev, device_t *adf); +void adf_disable_aer(struct adf_accel_dev *accel_dev); +void adf_reset_sbr(struct adf_accel_dev *accel_dev); +void adf_reset_flr(struct adf_accel_dev *accel_dev); +void adf_dev_pre_reset(struct adf_accel_dev *accel_dev); +void adf_dev_post_reset(struct adf_accel_dev *accel_dev); +void adf_dev_restore(struct adf_accel_dev *accel_dev); +int adf_init_aer(void); +void adf_exit_aer(void); +int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev, + u32 ae, + void *in, + void *out); +struct icp_qat_fw_init_admin_req; +struct icp_qat_fw_init_admin_resp; +int adf_send_admin(struct adf_accel_dev *accel_dev, + struct icp_qat_fw_init_admin_req *req, + struct icp_qat_fw_init_admin_resp *resp, + u32 ae_mask); +int adf_config_device(struct adf_accel_dev *accel_dev); + +int adf_init_admin_comms(struct adf_accel_dev *accel_dev); +void adf_exit_admin_comms(struct adf_accel_dev *accel_dev); +int adf_send_admin_init(struct adf_accel_dev *accel_dev); +int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp); +int adf_get_fw_pke_stats(struct adf_accel_dev *accel_dev, + u64 *suc_count, + u64 *unsuc_count); +int adf_dev_measure_clock(struct adf_accel_dev *accel_dev, + u32 *frequency, + u32 min, + u32 max); +int adf_clock_debugfs_add(struct adf_accel_dev *accel_dev); +u64 adf_clock_get_current_time(void); +int adf_init_arb(struct adf_accel_dev *accel_dev); +int adf_init_gen2_arb(struct adf_accel_dev *accel_dev); +void adf_exit_arb(struct adf_accel_dev *accel_dev); +void adf_disable_arb(struct adf_accel_dev *accel_dev); +void adf_update_ring_arb(struct adf_etr_ring_data *ring); +void +adf_enable_ring_arb(void *csr_addr, unsigned int bank_nr, unsigned int mask); +void +adf_disable_ring_arb(void *csr_addr, unsigned int bank_nr, unsigned int mask); +int adf_set_ssm_wdtimer(struct adf_accel_dev *accel_dev); +struct adf_accel_dev *adf_devmgr_get_dev_by_bdf(struct adf_pci_address *addr); +struct adf_accel_dev *adf_devmgr_get_dev_by_pci_bus(u8 bus); +int adf_get_vf_nr(struct adf_pci_address *vf_pci_addr, int *vf_nr); +u32 adf_get_slices_for_svc(struct adf_accel_dev *accel_dev, + enum adf_svc_type svc); +bool adf_is_bdf_equal(struct adf_pci_address *bdf1, + struct adf_pci_address *bdf2); +int adf_is_vf_nr_valid(struct adf_accel_dev *accel_dev, int vf_nr); +void adf_dev_get(struct adf_accel_dev *accel_dev); +void adf_dev_put(struct adf_accel_dev *accel_dev); +int adf_dev_in_use(struct adf_accel_dev *accel_dev); +int adf_init_etr_data(struct adf_accel_dev *accel_dev); +void adf_cleanup_etr_data(struct adf_accel_dev *accel_dev); + +struct qat_crypto_instance *qat_crypto_get_instance_node(int node); +void qat_crypto_put_instance(struct qat_crypto_instance *inst); +void qat_alg_callback(void *resp); +void qat_alg_asym_callback(void *resp); +int qat_algs_register(void); +void qat_algs_unregister(void); +int qat_asym_algs_register(void); +void qat_asym_algs_unregister(void); + +int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev); +void adf_isr_resource_free(struct adf_accel_dev *accel_dev); +int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev); +void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev); + +int qat_hal_init(struct adf_accel_dev *accel_dev); +void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle); +void qat_hal_start(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask); +void qat_hal_stop(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask); +void qat_hal_reset(struct icp_qat_fw_loader_handle *handle); +int qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle); +void qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask); +int qat_hal_check_ae_active(struct icp_qat_fw_loader_handle *handle, + unsigned int ae); +int qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + enum icp_qat_uof_regtype lm_type, + unsigned char mode); +void qat_hal_set_ae_tindex_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode); +void qat_hal_set_ae_scs_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode); +int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode); +int qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode); +void qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask, + unsigned int upc); +void qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + const uint64_t *uword); +void qat_hal_wr_coalesce_uwords(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + uint64_t *uword); + +void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uword_addr, + unsigned int words_num, + unsigned int *data); +int qat_hal_get_ins_num(void); +int qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + struct icp_qat_uof_batch_init *lm_init_header); +int qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata); +int qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata); +int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata); +int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + unsigned short reg_num, + unsigned int regdata); +int qat_hal_wr_lm(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned short lm_addr, + unsigned int value); +int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle); +void qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle); +void qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle); +int qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + int mem_size); +int qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + u32 mem_size, + const char *obj_name); + +void qat_hal_get_scs_neigh_ae(unsigned char ae, unsigned char *ae_neigh); +int qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle, + unsigned int cfg_ae_mask); +void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); +void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); +int adf_init_vf_wq(void); +void adf_exit_vf_wq(void); +void adf_flush_vf_wq(void); +int adf_vf2pf_init(struct adf_accel_dev *accel_dev); +void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev); +static inline int +adf_sriov_configure(device_t *pdev, int numvfs) +{ + return 0; +} + +static inline void +adf_disable_sriov(struct adf_accel_dev *accel_dev) +{ +} + +static inline void +adf_vf2pf_handler(struct adf_accel_vf_info *vf_info) +{ +} + +static inline int +adf_init_pf_wq(void) +{ + return 0; +} + +static inline void +adf_exit_pf_wq(void) +{ +} +#endif diff --git a/sys/dev/qat/include/common/adf_transport.h b/sys/dev/qat/include/common/adf_transport.h new file mode 100644 index 00000000000..def448cc4ab --- /dev/null +++ b/sys/dev/qat/include/common/adf_transport.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_TRANSPORT_H +#define ADF_TRANSPORT_H + +#include "adf_accel_devices.h" + +struct adf_etr_ring_data; + +typedef void (*adf_callback_fn)(void *resp_msg); + +int adf_create_ring(struct adf_accel_dev *accel_dev, + const char *section, + u32 bank_num, + u32 num_mgs, + u32 msg_size, + const char *ring_name, + adf_callback_fn callback, + int poll_mode, + struct adf_etr_ring_data **ring_ptr); + +int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg); +void adf_remove_ring(struct adf_etr_ring_data *ring); +int adf_poll_bank(u32 accel_id, u32 bank_num, u32 quota); +int adf_poll_all_banks(u32 accel_id, u32 quota); +#endif /* ADF_TRANSPORT_H */ diff --git a/sys/dev/qat/include/common/adf_transport_access_macros.h b/sys/dev/qat/include/common/adf_transport_access_macros.h new file mode 100644 index 00000000000..ad9f0348b5a --- /dev/null +++ b/sys/dev/qat/include/common/adf_transport_access_macros.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_TRANSPORT_ACCESS_MACROS_H +#define ADF_TRANSPORT_ACCESS_MACROS_H + +#include "adf_accel_devices.h" +#define ADF_BANK_INT_SRC_SEL_MASK_0 0x4444444CUL +#define ADF_BANK_INT_SRC_SEL_MASK_X 0x44444444UL +#define ADF_BANK_INT_FLAG_CLEAR_MASK 0xFFFF +#define ADF_RING_CSR_RING_CONFIG 0x000 +#define ADF_RING_CSR_RING_LBASE 0x040 +#define ADF_RING_CSR_RING_UBASE 0x080 +#define ADF_RING_CSR_RING_HEAD 0x0C0 +#define ADF_RING_CSR_RING_TAIL 0x100 +#define ADF_RING_CSR_E_STAT 0x14C +#define ADF_RING_CSR_INT_FLAG 0x170 +#define ADF_RING_CSR_INT_SRCSEL 0x174 +#define ADF_RING_CSR_INT_SRCSEL_2 0x178 +#define ADF_RING_CSR_INT_COL_EN 0x17C +#define ADF_RING_CSR_INT_COL_CTL 0x180 +#define ADF_RING_CSR_INT_FLAG_AND_COL 0x184 +#define ADF_RING_CSR_INT_COL_CTL_ENABLE 0x80000000 +#define ADF_RING_BUNDLE_SIZE 0x1000 +#define ADF_RING_CONFIG_NEAR_FULL_WM 0x0A +#define ADF_RING_CONFIG_NEAR_EMPTY_WM 0x05 +#define ADF_COALESCING_MIN_TIME 0x1FF +#define ADF_COALESCING_MAX_TIME 0xFFFFF +#define ADF_COALESCING_DEF_TIME 0x27FF +#define ADF_RING_NEAR_WATERMARK_512 0x08 +#define ADF_RING_NEAR_WATERMARK_0 0x00 +#define ADF_RING_EMPTY_SIG 0x7F7F7F7F + +/* Valid internal ring size values */ +#define ADF_RING_SIZE_128 0x01 +#define ADF_RING_SIZE_256 0x02 +#define ADF_RING_SIZE_512 0x03 +#define ADF_RING_SIZE_4K 0x06 +#define ADF_RING_SIZE_16K 0x08 +#define ADF_RING_SIZE_4M 0x10 +#define ADF_MIN_RING_SIZE ADF_RING_SIZE_128 +#define ADF_MAX_RING_SIZE ADF_RING_SIZE_4M +#define ADF_DEFAULT_RING_SIZE ADF_RING_SIZE_16K + +/* Valid internal msg size values */ +#define ADF_MSG_SIZE_32 0x01 +#define ADF_MSG_SIZE_64 0x02 +#define ADF_MSG_SIZE_128 0x04 +#define ADF_MIN_MSG_SIZE ADF_MSG_SIZE_32 +#define ADF_MAX_MSG_SIZE ADF_MSG_SIZE_128 + +/* Size to bytes conversion macros for ring and msg size values */ +#define ADF_MSG_SIZE_TO_BYTES(SIZE) (SIZE << 5) +#define ADF_BYTES_TO_MSG_SIZE(SIZE) (SIZE >> 5) +#define ADF_SIZE_TO_RING_SIZE_IN_BYTES(SIZE) ((1 << (SIZE - 1)) << 7) +#define ADF_RING_SIZE_IN_BYTES_TO_SIZE(SIZE) ((1 << (SIZE - 1)) >> 7) + +/* Set the response quota to a high number */ +#define ADF_NO_RESPONSE_QUOTA 0xFFFFFFFF + +/* Minimum ring bufer size for memory allocation */ +#define ADF_RING_SIZE_BYTES_MIN(SIZE) \ + ((SIZE < ADF_SIZE_TO_RING_SIZE_IN_BYTES(ADF_RING_SIZE_4K)) ? \ + ADF_SIZE_TO_RING_SIZE_IN_BYTES(ADF_RING_SIZE_4K) : \ + SIZE) +#define ADF_RING_SIZE_MODULO(SIZE) (SIZE + 0x6) +#define ADF_SIZE_TO_POW(SIZE) \ + ((((SIZE & 0x4) >> 1) | ((SIZE & 0x4) >> 2) | SIZE) & ~0x4) +/* Max outstanding requests */ +#define ADF_MAX_INFLIGHTS(RING_SIZE, MSG_SIZE) \ + ((((1 << (RING_SIZE - 1)) << 3) >> ADF_SIZE_TO_POW(MSG_SIZE)) - 1) +#define BUILD_RING_CONFIG(size) \ + ((ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_FULL_WM) | \ + (ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_EMPTY_WM) | size) +#define BUILD_RESP_RING_CONFIG(size, watermark_nf, watermark_ne) \ + ((watermark_nf << ADF_RING_CONFIG_NEAR_FULL_WM) | \ + (watermark_ne << ADF_RING_CONFIG_NEAR_EMPTY_WM) | size) +#define BUILD_RING_BASE_ADDR(addr, size) \ + ((addr >> 6) & (0xFFFFFFFFFFFFFFFFULL << size)) +#define READ_CSR_RING_HEAD(csr_base_addr, bank, ring) \ + ADF_CSR_RD(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_RING_HEAD + \ + (ring << 2)) +#define READ_CSR_RING_TAIL(csr_base_addr, bank, ring) \ + ADF_CSR_RD(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_RING_TAIL + \ + (ring << 2)) +#define READ_CSR_E_STAT(csr_base_addr, bank) \ + ADF_CSR_RD(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_E_STAT) +#define WRITE_CSR_RING_CONFIG(csr_base_addr, bank, ring, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_RING_CONFIG + \ + (ring << 2), \ + value) +#define WRITE_CSR_RING_BASE(csr_base_addr, bank, ring, value) \ + do { \ + uint32_t l_base = 0, u_base = 0; \ + l_base = (uint32_t)(value & 0xFFFFFFFF); \ + u_base = (uint32_t)((value & 0xFFFFFFFF00000000ULL) >> 32); \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + \ + ADF_RING_CSR_RING_LBASE + (ring << 2), \ + l_base); \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + \ + ADF_RING_CSR_RING_UBASE + (ring << 2), \ + u_base); \ + } while (0) +static inline uint64_t +read_base(struct resource *csr_base_addr, uint32_t bank, uint32_t ring) +{ + uint32_t l_base, u_base; + uint64_t addr; + + l_base = ADF_CSR_RD(csr_base_addr, + (ADF_RING_BUNDLE_SIZE * bank) + + ADF_RING_CSR_RING_LBASE + (ring << 2)); + u_base = ADF_CSR_RD(csr_base_addr, + (ADF_RING_BUNDLE_SIZE * bank) + + ADF_RING_CSR_RING_UBASE + (ring << 2)); + + addr = (uint64_t)l_base & 0x00000000FFFFFFFFULL; + addr |= (uint64_t)u_base << 32 & 0xFFFFFFFF00000000ULL; + + return addr; +} + +#define READ_CSR_RING_BASE(csr_base_addr, bank, ring) \ + read_base(csr_base_addr, bank, ring) +#define WRITE_CSR_RING_HEAD(csr_base_addr, bank, ring, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_RING_HEAD + \ + (ring << 2), \ + value) +#define WRITE_CSR_RING_TAIL(csr_base_addr, bank, ring, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_RING_TAIL + \ + (ring << 2), \ + value) +#define WRITE_CSR_INT_FLAG(csr_base_addr, bank, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * (bank)) + ADF_RING_CSR_INT_FLAG, \ + value) +#define WRITE_CSR_INT_SRCSEL(csr_base_addr, bank) \ + do { \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + \ + ADF_RING_CSR_INT_SRCSEL, \ + ADF_BANK_INT_SRC_SEL_MASK_0); \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + \ + ADF_RING_CSR_INT_SRCSEL_2, \ + ADF_BANK_INT_SRC_SEL_MASK_X); \ + } while (0) +#define WRITE_CSR_INT_COL_EN(csr_base_addr, bank, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_INT_COL_EN, \ + value) +#define WRITE_CSR_INT_COL_CTL(csr_base_addr, bank, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + ADF_RING_CSR_INT_COL_CTL, \ + ADF_RING_CSR_INT_COL_CTL_ENABLE | value) +#define WRITE_CSR_INT_FLAG_AND_COL(csr_base_addr, bank, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_RING_BUNDLE_SIZE * bank) + \ + ADF_RING_CSR_INT_FLAG_AND_COL, \ + value) +#endif diff --git a/sys/dev/qat/include/common/adf_transport_internal.h b/sys/dev/qat/include/common/adf_transport_internal.h new file mode 100644 index 00000000000..88b99ea44cc --- /dev/null +++ b/sys/dev/qat/include/common/adf_transport_internal.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_TRANSPORT_INTRN_H +#define ADF_TRANSPORT_INTRN_H + +#include "adf_transport.h" + +struct adf_etr_ring_debug_entry { + char ring_name[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + struct sysctl_oid *debug; +}; + +struct adf_etr_ring_data { + void *base_addr; + atomic_t *inflights; + struct mtx lock; /* protects ring data struct */ + adf_callback_fn callback; + struct adf_etr_bank_data *bank; + bus_addr_t dma_addr; + uint16_t head; + uint16_t tail; + uint8_t ring_number; + uint8_t ring_size; + uint8_t msg_size; + uint8_t reserved; + struct adf_etr_ring_debug_entry *ring_debug; + struct bus_dmamem dma_mem; + u32 csr_tail_offset; + u32 max_inflights; +}; + +struct adf_etr_bank_data { + struct adf_etr_ring_data *rings; + struct task resp_handler; + struct resource *csr_addr; + struct adf_accel_dev *accel_dev; + uint32_t irq_coalesc_timer; + uint16_t ring_mask; + uint16_t irq_mask; + struct mtx lock; /* protects bank data struct */ + struct sysctl_oid *bank_debug_dir; + struct sysctl_oid *bank_debug_cfg; + uint32_t bank_number; +}; + +struct adf_etr_data { + struct adf_etr_bank_data *banks; + struct sysctl_oid *debug; +}; + +void adf_response_handler(uintptr_t bank_addr); +int adf_handle_response(struct adf_etr_ring_data *ring, u32 quota); +int adf_bank_debugfs_add(struct adf_etr_bank_data *bank); +void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank); +int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name); +void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring); +#endif diff --git a/sys/dev/qat/include/common/icp_qat_fw_loader_handle.h b/sys/dev/qat/include/common/icp_qat_fw_loader_handle.h new file mode 100644 index 00000000000..a8afb5a4b37 --- /dev/null +++ b/sys/dev/qat/include/common/icp_qat_fw_loader_handle.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef __ICP_QAT_FW_LOADER_HANDLE_H__ +#define __ICP_QAT_FW_LOADER_HANDLE_H__ +#include "icp_qat_uclo.h" + +struct icp_qat_fw_loader_ae_data { + unsigned int state; + unsigned int ustore_size; + unsigned int free_addr; + unsigned int free_size; + unsigned int live_ctx_mask; +}; + +struct icp_qat_fw_loader_hal_handle { + struct icp_qat_fw_loader_ae_data aes[ICP_QAT_UCLO_MAX_AE]; + unsigned int ae_mask; + unsigned int slice_mask; + unsigned int revision_id; + unsigned int ae_max_num; + unsigned int upc_mask; + unsigned int max_ustore; +}; + +struct icp_qat_fw_loader_handle { + struct icp_qat_fw_loader_hal_handle *hal_handle; + struct adf_accel_dev *accel_dev; + device_t pci_dev; + void *obj_handle; + void *sobj_handle; + void *mobj_handle; + bool fw_auth; + unsigned int cfg_ae_mask; + rman_res_t hal_sram_size; + struct resource *hal_sram_addr_v; + unsigned int hal_sram_offset; + struct resource *hal_misc_addr_v; + uintptr_t hal_cap_g_ctl_csr_addr_v; + uintptr_t hal_cap_ae_xfer_csr_addr_v; + uintptr_t hal_cap_ae_local_csr_addr_v; + uintptr_t hal_ep_csr_addr_v; +}; + +struct icp_firml_dram_desc { + struct bus_dmamem dram_mem; + + struct resource *dram_base_addr; + void *dram_base_addr_v; + bus_addr_t dram_bus_addr; + u64 dram_size; +}; +#endif diff --git a/sys/dev/qat/include/common/icp_qat_hal.h b/sys/dev/qat/include/common/icp_qat_hal.h new file mode 100644 index 00000000000..3a7475f2533 --- /dev/null +++ b/sys/dev/qat/include/common/icp_qat_hal.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef __ICP_QAT_HAL_H +#define __ICP_QAT_HAL_H +#include "adf_accel_devices.h" +#include "icp_qat_fw_loader_handle.h" + +enum hal_global_csr { + MISC_CONTROL = 0x04, + ICP_RESET = 0x0c, + ICP_GLOBAL_CLK_ENABLE = 0x50 +}; + +enum { MISC_CONTROL_C4XXX = 0xAA0, + ICP_RESET_CPP0 = 0x938, + ICP_RESET_CPP1 = 0x93c, + ICP_GLOBAL_CLK_ENABLE_CPP0 = 0x964, + ICP_GLOBAL_CLK_ENABLE_CPP1 = 0x968 }; + +enum hal_ae_csr { + USTORE_ADDRESS = 0x000, + USTORE_DATA_LOWER = 0x004, + USTORE_DATA_UPPER = 0x008, + ALU_OUT = 0x010, + CTX_ARB_CNTL = 0x014, + CTX_ENABLES = 0x018, + CC_ENABLE = 0x01c, + CSR_CTX_POINTER = 0x020, + CTX_STS_INDIRECT = 0x040, + ACTIVE_CTX_STATUS = 0x044, + CTX_SIG_EVENTS_INDIRECT = 0x048, + CTX_SIG_EVENTS_ACTIVE = 0x04c, + CTX_WAKEUP_EVENTS_INDIRECT = 0x050, + LM_ADDR_0_INDIRECT = 0x060, + LM_ADDR_1_INDIRECT = 0x068, + LM_ADDR_2_INDIRECT = 0x0cc, + LM_ADDR_3_INDIRECT = 0x0d4, + INDIRECT_LM_ADDR_0_BYTE_INDEX = 0x0e0, + INDIRECT_LM_ADDR_1_BYTE_INDEX = 0x0e8, + INDIRECT_LM_ADDR_2_BYTE_INDEX = 0x10c, + INDIRECT_LM_ADDR_3_BYTE_INDEX = 0x114, + INDIRECT_T_INDEX = 0x0f8, + INDIRECT_T_INDEX_BYTE_INDEX = 0x0fc, + FUTURE_COUNT_SIGNAL_INDIRECT = 0x078, + TIMESTAMP_LOW = 0x0c0, + TIMESTAMP_HIGH = 0x0c4, + PROFILE_COUNT = 0x144, + SIGNATURE_ENABLE = 0x150, + AE_MISC_CONTROL = 0x160, + LOCAL_CSR_STATUS = 0x180, +}; + +enum fcu_csr { + FCU_CONTROL = 0x0, + FCU_STATUS = 0x4, + FCU_DRAM_ADDR_LO = 0xc, + FCU_DRAM_ADDR_HI = 0x10, + FCU_RAMBASE_ADDR_HI = 0x14, + FCU_RAMBASE_ADDR_LO = 0x18 +}; + +enum fcu_csr_c4xxx { + FCU_CONTROL_C4XXX = 0x0, + FCU_STATUS_C4XXX = 0x4, + FCU_STATUS1_C4XXX = 0xc, + FCU_AE_LOADED_C4XXX = 0x10, + FCU_DRAM_ADDR_LO_C4XXX = 0x14, + FCU_DRAM_ADDR_HI_C4XXX = 0x18, +}; + +enum fcu_cmd { + FCU_CTRL_CMD_NOOP = 0, + FCU_CTRL_CMD_AUTH = 1, + FCU_CTRL_CMD_LOAD = 2, + FCU_CTRL_CMD_START = 3 +}; + +enum fcu_sts { + FCU_STS_NO_STS = 0, + FCU_STS_VERI_DONE = 1, + FCU_STS_LOAD_DONE = 2, + FCU_STS_VERI_FAIL = 3, + FCU_STS_LOAD_FAIL = 4, + FCU_STS_BUSY = 5 +}; +#define UA_ECS (0x1 << 31) +#define ACS_ABO_BITPOS 31 +#define ACS_ACNO 0x7 +#define CE_ENABLE_BITPOS 0x8 +#define CE_LMADDR_0_GLOBAL_BITPOS 16 +#define CE_LMADDR_1_GLOBAL_BITPOS 17 +#define CE_LMADDR_2_GLOBAL_BITPOS 22 +#define CE_LMADDR_3_GLOBAL_BITPOS 23 +#define CE_T_INDEX_GLOBAL_BITPOS 21 +#define CE_NN_MODE_BITPOS 20 +#define CE_REG_PAR_ERR_BITPOS 25 +#define CE_BREAKPOINT_BITPOS 27 +#define CE_CNTL_STORE_PARITY_ERROR_BITPOS 29 +#define CE_INUSE_CONTEXTS_BITPOS 31 +#define CE_NN_MODE (0x1 << CE_NN_MODE_BITPOS) +#define CE_INUSE_CONTEXTS (0x1 << CE_INUSE_CONTEXTS_BITPOS) +#define XCWE_VOLUNTARY (0x1) +#define LCS_STATUS (0x1) +#define MMC_SHARE_CS_BITPOS 2 +#define GLOBAL_CSR 0xA00 +#define FCU_CTRL_AE_POS 0x8 +#define FCU_AUTH_STS_MASK 0x7 +#define FCU_STS_DONE_POS 0x9 +#define FCU_STS_AUTHFWLD_POS 0X8 +#define FCU_LOADED_AE_POS 0x16 +#define FW_AUTH_WAIT_PERIOD 10 +#define FW_AUTH_MAX_RETRY 300 +#define FCU_OFFSET 0x8c0 +#define FCU_OFFSET_C4XXX 0x1000 +#define MAX_CPP_NUM 2 +#define AE_CPP_NUM 2 +#define AES_PER_CPP 16 +#define SLICES_PER_CPP 6 +#define ICP_QAT_AE_OFFSET 0x20000 +#define ICP_QAT_AE_OFFSET_C4XXX 0x40000 +#define ICP_QAT_CAP_OFFSET (ICP_QAT_AE_OFFSET + 0x10000) +#define ICP_QAT_CAP_OFFSET_C4XXX 0x70000 +#define LOCAL_TO_XFER_REG_OFFSET 0x800 +#define ICP_QAT_EP_OFFSET 0x3a000 +#define ICP_QAT_EP_OFFSET_C4XXX 0x60000 +#define MEM_CFG_ERR_BIT 0x20 + +#define CAP_CSR_ADDR(csr) (csr + handle->hal_cap_g_ctl_csr_addr_v) +#define SET_CAP_CSR(handle, csr, val) \ + ADF_CSR_WR(handle->hal_misc_addr_v, CAP_CSR_ADDR(csr), val) +#define GET_CAP_CSR(handle, csr) \ + ADF_CSR_RD(handle->hal_misc_addr_v, CAP_CSR_ADDR(csr)) +#define SET_GLB_CSR(handle, csr, val) \ + ({ \ + typeof(handle) handle_ = (handle); \ + typeof(csr) csr_ = (csr); \ + typeof(val) val_ = (val); \ + (IS_QAT_GEN3(pci_get_device(GET_DEV(handle_->accel_dev)))) ? \ + SET_CAP_CSR(handle_, (csr_), (val_)) : \ + SET_CAP_CSR(handle_, csr_ + GLOBAL_CSR, val_); \ + }) +#define GET_GLB_CSR(handle, csr) \ + ({ \ + typeof(handle) handle_ = (handle); \ + typeof(csr) csr_ = (csr); \ + (IS_QAT_GEN3(pci_get_device(GET_DEV(handle_->accel_dev)))) ? \ + (GET_CAP_CSR(handle_, (csr_))) : \ + (GET_CAP_CSR(handle_, (GLOBAL_CSR + (csr_)))); \ + }) +#define SET_FCU_CSR(handle, csr, val) \ + ({ \ + typeof(handle) handle_ = (handle); \ + typeof(csr) csr_ = (csr); \ + typeof(val) val_ = (val); \ + (IS_QAT_GEN3(pci_get_device(GET_DEV(handle_->accel_dev)))) ? \ + SET_CAP_CSR(handle_, \ + ((csr_) + FCU_OFFSET_C4XXX), \ + (val_)) : \ + SET_CAP_CSR(handle_, ((csr_) + FCU_OFFSET), (val_)); \ + }) +#define GET_FCU_CSR(handle, csr) \ + ({ \ + typeof(handle) handle_ = (handle); \ + typeof(csr) csr_ = (csr); \ + (IS_QAT_GEN3(pci_get_device(GET_DEV(handle_->accel_dev)))) ? \ + GET_CAP_CSR(handle_, (FCU_OFFSET_C4XXX + (csr_))) : \ + GET_CAP_CSR(handle_, (FCU_OFFSET + (csr_))); \ + }) +#define AE_CSR(handle, ae) \ + ((handle)->hal_cap_ae_local_csr_addr_v + ((ae) << 12)) +#define AE_CSR_ADDR(handle, ae, csr) (AE_CSR(handle, ae) + (0x3ff & (csr))) +#define SET_AE_CSR(handle, ae, csr, val) \ + ADF_CSR_WR(handle->hal_misc_addr_v, AE_CSR_ADDR(handle, ae, csr), val) +#define GET_AE_CSR(handle, ae, csr) \ + ADF_CSR_RD(handle->hal_misc_addr_v, AE_CSR_ADDR(handle, ae, csr)) +#define AE_XFER(handle, ae) \ + ((handle)->hal_cap_ae_xfer_csr_addr_v + ((ae) << 12)) +#define AE_XFER_ADDR(handle, ae, reg) \ + (AE_XFER(handle, ae) + (((reg)&0xff) << 2)) +#define SET_AE_XFER(handle, ae, reg, val) \ + ADF_CSR_WR(handle->hal_misc_addr_v, AE_XFER_ADDR(handle, ae, reg), val) +#define SRAM_WRITE(handle, addr, val) \ + ADF_CSR_WR((handle)->hal_sram_addr_v, addr, val) +#define GET_CSR_OFFSET(device_id, cap_offset_, ae_offset_, ep_offset_) \ + ({ \ + int gen3 = IS_QAT_GEN3(device_id); \ + cap_offset_ = \ + (gen3 ? ICP_QAT_CAP_OFFSET_C4XXX : ICP_QAT_CAP_OFFSET); \ + ae_offset_ = \ + (gen3 ? ICP_QAT_AE_OFFSET_C4XXX : ICP_QAT_AE_OFFSET); \ + ep_offset_ = \ + (gen3 ? ICP_QAT_EP_OFFSET_C4XXX : ICP_QAT_EP_OFFSET); \ + }) + +#endif diff --git a/sys/dev/qat/include/common/icp_qat_uclo.h b/sys/dev/qat/include/common/icp_qat_uclo.h new file mode 100644 index 00000000000..21a1c2fc8ac --- /dev/null +++ b/sys/dev/qat/include/common/icp_qat_uclo.h @@ -0,0 +1,558 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef __ICP_QAT_UCLO_H__ +#define __ICP_QAT_UCLO_H__ + +#define ICP_QAT_AC_895XCC_DEV_TYPE 0x00400000 +#define ICP_QAT_AC_C62X_DEV_TYPE 0x01000000 +#define ICP_QAT_AC_C3XXX_DEV_TYPE 0x02000000 +#define ICP_QAT_AC_200XX_DEV_TYPE 0x02000000 +#define ICP_QAT_AC_C4XXX_DEV_TYPE 0x04000000 +#define ICP_QAT_UCLO_MAX_AE 32 +#define ICP_QAT_UCLO_MAX_CTX 8 +#define ICP_QAT_UCLO_MAX_CPPNUM 2 +#define ICP_QAT_UCLO_MAX_UIMAGE (ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX) +#define ICP_QAT_UCLO_MAX_USTORE 0x4000 +#define ICP_QAT_UCLO_MAX_XFER_REG 128 +#define ICP_QAT_UCLO_MAX_GPR_REG 128 +#define ICP_QAT_UCLO_MAX_LMEM_REG 1024 +#define ICP_QAT_UCLO_AE_ALL_CTX 0xff +#define ICP_QAT_UOF_OBJID_LEN 8 +#define ICP_QAT_UOF_FID 0xc6c2 +#define ICP_QAT_UOF_MAJVER 0x4 +#define ICP_QAT_UOF_MINVER 0x11 +#define ICP_QAT_UOF_OBJS "UOF_OBJS" +#define ICP_QAT_UOF_STRT "UOF_STRT" +#define ICP_QAT_UOF_IMAG "UOF_IMAG" +#define ICP_QAT_UOF_IMEM "UOF_IMEM" +#define ICP_QAT_UOF_LOCAL_SCOPE 1 +#define ICP_QAT_UOF_INIT_EXPR 0 +#define ICP_QAT_UOF_INIT_REG 1 +#define ICP_QAT_UOF_INIT_REG_CTX 2 +#define ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP 3 +#define ICP_QAT_SUOF_OBJ_ID_LEN 8 +#define ICP_QAT_SUOF_FID 0x53554f46 +#define ICP_QAT_SUOF_MAJVER 0x0 +#define ICP_QAT_SUOF_MINVER 0x1 +#define ICP_QAT_SUOF_OBJ_NAME_LEN 128 +#define ICP_QAT_MOF_OBJ_ID_LEN 8 +#define ICP_QAT_MOF_OBJ_CHUNKID_LEN 8 +#define ICP_QAT_MOF_FID 0x00666f6d +#define ICP_QAT_MOF_MAJVER 0x0 +#define ICP_QAT_MOF_MINVER 0x1 +#define ICP_QAT_MOF_SYM_OBJS "SYM_OBJS" +#define ICP_QAT_SUOF_OBJS "SUF_OBJS" +#define ICP_QAT_SUOF_IMAG "SUF_IMAG" +#define ICP_QAT_SIMG_AE_INIT_SEQ_LEN (50 * sizeof(unsigned long long)) +#define ICP_QAT_SIMG_AE_INSTS_LEN (0x4000 * sizeof(unsigned long long)) +#define ICP_QAT_CSS_FWSK_MODULUS_LEN 256 +#define ICP_QAT_CSS_FWSK_EXPONENT_LEN 4 +#define ICP_QAT_CSS_FWSK_PAD_LEN 252 +#define ICP_QAT_CSS_FWSK_PUB_LEN \ + (ICP_QAT_CSS_FWSK_MODULUS_LEN + ICP_QAT_CSS_FWSK_EXPONENT_LEN + \ + ICP_QAT_CSS_FWSK_PAD_LEN) +#define ICP_QAT_CSS_SIGNATURE_LEN 256 +#define ICP_QAT_CSS_AE_IMG_LEN \ + (sizeof(struct icp_qat_simg_ae_mode) + ICP_QAT_SIMG_AE_INIT_SEQ_LEN + \ + ICP_QAT_SIMG_AE_INSTS_LEN) +#define ICP_QAT_CSS_AE_SIMG_LEN \ + (sizeof(struct icp_qat_css_hdr) + ICP_QAT_CSS_FWSK_PUB_LEN + \ + ICP_QAT_CSS_SIGNATURE_LEN + ICP_QAT_CSS_AE_IMG_LEN) +#define ICP_QAT_AE_IMG_OFFSET \ + (sizeof(struct icp_qat_css_hdr) + ICP_QAT_CSS_FWSK_MODULUS_LEN + \ + ICP_QAT_CSS_FWSK_EXPONENT_LEN + ICP_QAT_CSS_SIGNATURE_LEN) +#define ICP_QAT_CSS_MAX_IMAGE_LEN 0x40000 + +#define ICP_QAT_CTX_MODE(ae_mode) ((ae_mode)&0xf) +#define ICP_QAT_NN_MODE(ae_mode) (((ae_mode) >> 0x4) & 0xf) +#define ICP_QAT_SHARED_USTORE_MODE(ae_mode) (((ae_mode) >> 0xb) & 0x1) +#define RELOADABLE_CTX_SHARED_MODE(ae_mode) (((ae_mode) >> 0xc) & 0x1) + +#define ICP_QAT_LOC_MEM0_MODE(ae_mode) (((ae_mode) >> 0x8) & 0x1) +#define ICP_QAT_LOC_MEM1_MODE(ae_mode) (((ae_mode) >> 0x9) & 0x1) +#define ICP_QAT_LOC_MEM2_MODE(ae_mode) (((ae_mode) >> 0x6) & 0x1) +#define ICP_QAT_LOC_MEM3_MODE(ae_mode) (((ae_mode) >> 0x7) & 0x1) +#define ICP_QAT_LOC_TINDEX_MODE(ae_mode) (((ae_mode) >> 0xe) & 0x1) + +enum icp_qat_uof_mem_region { + ICP_QAT_UOF_SRAM_REGION = 0x0, + ICP_QAT_UOF_LMEM_REGION = 0x3, + ICP_QAT_UOF_UMEM_REGION = 0x5 +}; + +enum icp_qat_uof_regtype { + ICP_NO_DEST = 0, + ICP_GPA_REL = 1, + ICP_GPA_ABS = 2, + ICP_GPB_REL = 3, + ICP_GPB_ABS = 4, + ICP_SR_REL = 5, + ICP_SR_RD_REL = 6, + ICP_SR_WR_REL = 7, + ICP_SR_ABS = 8, + ICP_SR_RD_ABS = 9, + ICP_SR_WR_ABS = 10, + ICP_DR_REL = 19, + ICP_DR_RD_REL = 20, + ICP_DR_WR_REL = 21, + ICP_DR_ABS = 22, + ICP_DR_RD_ABS = 23, + ICP_DR_WR_ABS = 24, + ICP_LMEM = 26, + ICP_LMEM0 = 27, + ICP_LMEM1 = 28, + ICP_NEIGH_REL = 31, + ICP_LMEM2 = 61, + ICP_LMEM3 = 62, +}; + +enum icp_qat_css_fwtype { CSS_AE_FIRMWARE = 0, CSS_MMP_FIRMWARE = 1 }; + +struct icp_qat_uclo_page { + struct icp_qat_uclo_encap_page *encap_page; + struct icp_qat_uclo_region *region; + unsigned int flags; +}; + +struct icp_qat_uclo_region { + struct icp_qat_uclo_page *loaded; + struct icp_qat_uclo_page *page; +}; + +struct icp_qat_uclo_aeslice { + struct icp_qat_uclo_region *region; + struct icp_qat_uclo_page *page; + struct icp_qat_uclo_page *cur_page[ICP_QAT_UCLO_MAX_CTX]; + struct icp_qat_uclo_encapme *encap_image; + unsigned int ctx_mask_assigned; + unsigned int new_uaddr[ICP_QAT_UCLO_MAX_CTX]; +}; + +struct icp_qat_uclo_aedata { + unsigned int slice_num; + unsigned int eff_ustore_size; + struct icp_qat_uclo_aeslice ae_slices[ICP_QAT_UCLO_MAX_CTX]; + unsigned int shareable_ustore; +}; + +struct icp_qat_uof_encap_obj { + char *beg_uof; + struct icp_qat_uof_objhdr *obj_hdr; + struct icp_qat_uof_chunkhdr *chunk_hdr; + struct icp_qat_uof_varmem_seg *var_mem_seg; +}; + +struct icp_qat_uclo_encap_uwblock { + unsigned int start_addr; + unsigned int words_num; + uint64_t micro_words; +}; + +struct icp_qat_uclo_encap_page { + unsigned int def_page; + unsigned int page_region; + unsigned int beg_addr_v; + unsigned int beg_addr_p; + unsigned int micro_words_num; + unsigned int uwblock_num; + struct icp_qat_uclo_encap_uwblock *uwblock; +}; + +struct icp_qat_uclo_encapme { + struct icp_qat_uof_image *img_ptr; + struct icp_qat_uclo_encap_page *page; + unsigned int ae_reg_num; + struct icp_qat_uof_ae_reg *ae_reg; + unsigned int init_regsym_num; + struct icp_qat_uof_init_regsym *init_regsym; + unsigned int sbreak_num; + struct icp_qat_uof_sbreak *sbreak; + unsigned int uwords_num; +}; + +struct icp_qat_uclo_init_mem_table { + unsigned int entry_num; + struct icp_qat_uof_initmem *init_mem; +}; + +struct icp_qat_uclo_objhdr { + char *file_buff; + unsigned int checksum; + unsigned int size; +}; + +struct icp_qat_uof_strtable { + unsigned int table_len; + unsigned int reserved; + uint64_t strings; +}; + +struct icp_qat_uclo_objhandle { + unsigned int prod_type; + unsigned int prod_rev; + struct icp_qat_uclo_objhdr *obj_hdr; + struct icp_qat_uof_encap_obj encap_uof_obj; + struct icp_qat_uof_strtable str_table; + struct icp_qat_uclo_encapme ae_uimage[ICP_QAT_UCLO_MAX_UIMAGE]; + struct icp_qat_uclo_aedata ae_data[ICP_QAT_UCLO_MAX_AE]; + struct icp_qat_uclo_init_mem_table init_mem_tab; + struct icp_qat_uof_batch_init *lm_init_tab[ICP_QAT_UCLO_MAX_AE]; + struct icp_qat_uof_batch_init *umem_init_tab[ICP_QAT_UCLO_MAX_AE]; + int uimage_num; + int uword_in_bytes; + int global_inited; + unsigned int ae_num; + unsigned int ustore_phy_size; + void *obj_buf; + uint64_t *uword_buf; +}; + +struct icp_qat_uof_uword_block { + unsigned int start_addr; + unsigned int words_num; + unsigned int uword_offset; + unsigned int reserved; +}; + +struct icp_qat_uof_filehdr { + unsigned short file_id; + unsigned short reserved1; + char min_ver; + char maj_ver; + unsigned short reserved2; + unsigned short max_chunks; + unsigned short num_chunks; +}; + +struct icp_qat_uof_filechunkhdr { + char chunk_id[ICP_QAT_UOF_OBJID_LEN]; + unsigned int checksum; + unsigned int offset; + unsigned int size; +}; + +struct icp_qat_uof_objhdr { + unsigned int ac_dev_type; + unsigned short min_cpu_ver; + unsigned short max_cpu_ver; + short max_chunks; + short num_chunks; + unsigned int reserved1; + unsigned int reserved2; +}; + +struct icp_qat_uof_chunkhdr { + char chunk_id[ICP_QAT_UOF_OBJID_LEN]; + unsigned int offset; + unsigned int size; +}; + +struct icp_qat_uof_memvar_attr { + unsigned int offset_in_byte; + unsigned int value; +}; + +struct icp_qat_uof_initmem { + unsigned int sym_name; + char region; + char scope; + unsigned short reserved1; + unsigned int addr; + unsigned int num_in_bytes; + unsigned int val_attr_num; +}; + +struct icp_qat_uof_init_regsym { + unsigned int sym_name; + char init_type; + char value_type; + char reg_type; + unsigned char ctx; + unsigned int reg_addr; + unsigned int value; +}; + +struct icp_qat_uof_varmem_seg { + unsigned int sram_base; + unsigned int sram_size; + unsigned int sram_alignment; + unsigned int sdram_base; + unsigned int sdram_size; + unsigned int sdram_alignment; + unsigned int sdram1_base; + unsigned int sdram1_size; + unsigned int sdram1_alignment; + unsigned int scratch_base; + unsigned int scratch_size; + unsigned int scratch_alignment; +}; + +struct icp_qat_uof_gtid { + char tool_id[ICP_QAT_UOF_OBJID_LEN]; + int tool_ver; + unsigned int reserved1; + unsigned int reserved2; +}; + +struct icp_qat_uof_sbreak { + unsigned int page_num; + unsigned int virt_uaddr; + unsigned char sbreak_type; + unsigned char reg_type; + unsigned short reserved1; + unsigned int addr_offset; + unsigned int reg_addr; +}; + +struct icp_qat_uof_code_page { + unsigned int page_region; + unsigned int page_num; + unsigned char def_page; + unsigned char reserved2; + unsigned short reserved1; + unsigned int beg_addr_v; + unsigned int beg_addr_p; + unsigned int neigh_reg_tab_offset; + unsigned int uc_var_tab_offset; + unsigned int imp_var_tab_offset; + unsigned int imp_expr_tab_offset; + unsigned int code_area_offset; +}; + +struct icp_qat_uof_image { + unsigned int img_name; + unsigned int ae_assigned; + unsigned int ctx_assigned; + unsigned int ac_dev_type; + unsigned int entry_address; + unsigned int fill_pattern[2]; + unsigned int reloadable_size; + unsigned char sensitivity; + unsigned char reserved; + unsigned short ae_mode; + unsigned short max_ver; + unsigned short min_ver; + unsigned short image_attrib; + unsigned short reserved2; + unsigned short page_region_num; + unsigned short numpages; + unsigned int reg_tab_offset; + unsigned int init_reg_sym_tab; + unsigned int sbreak_tab; + unsigned int app_metadata; +}; + +struct icp_qat_uof_objtable { + unsigned int entry_num; +}; + +struct icp_qat_uof_ae_reg { + unsigned int name; + unsigned int vis_name; + unsigned short type; + unsigned short addr; + unsigned short access_mode; + unsigned char visible; + unsigned char reserved1; + unsigned short ref_count; + unsigned short reserved2; + unsigned int xo_id; +}; + +struct icp_qat_uof_code_area { + unsigned int micro_words_num; + unsigned int uword_block_tab; +}; + +struct icp_qat_uof_batch_init { + unsigned int ae; + unsigned int addr; + unsigned int *value; + unsigned int size; + struct icp_qat_uof_batch_init *next; +}; + +struct icp_qat_suof_img_hdr { + const char *simg_buf; + unsigned long simg_len; + const char *css_header; + const char *css_key; + const char *css_signature; + const char *css_simg; + unsigned long simg_size; + unsigned int ae_num; + unsigned int ae_mask; + unsigned int fw_type; + unsigned long simg_name; + unsigned long appmeta_data; +}; + +struct icp_qat_suof_img_tbl { + unsigned int num_simgs; + struct icp_qat_suof_img_hdr *simg_hdr; +}; + +struct icp_qat_suof_handle { + unsigned int file_id; + unsigned int check_sum; + char min_ver; + char maj_ver; + char fw_type; + const char *suof_buf; + unsigned int suof_size; + char *sym_str; + unsigned int sym_size; + struct icp_qat_suof_img_tbl img_table; +}; + +struct icp_qat_fw_auth_desc { + unsigned int img_len; + unsigned int ae_mask; + unsigned int css_hdr_high; + unsigned int css_hdr_low; + unsigned int img_high; + unsigned int img_low; + unsigned int signature_high; + unsigned int signature_low; + unsigned int fwsk_pub_high; + unsigned int fwsk_pub_low; + unsigned int img_ae_mode_data_high; + unsigned int img_ae_mode_data_low; + unsigned int img_ae_init_data_high; + unsigned int img_ae_init_data_low; + unsigned int img_ae_insts_high; + unsigned int img_ae_insts_low; +}; + +struct icp_qat_auth_chunk { + struct icp_qat_fw_auth_desc fw_auth_desc; + u64 chunk_size; + u64 chunk_bus_addr; +}; + +struct icp_qat_css_hdr { + unsigned int module_type; + unsigned int header_len; + unsigned int header_ver; + unsigned int module_id; + unsigned int module_vendor; + unsigned int date; + unsigned int size; + unsigned int key_size; + unsigned int module_size; + unsigned int exponent_size; + unsigned int fw_type; + unsigned int reserved[21]; +}; + +struct icp_qat_simg_ae_mode { + unsigned int file_id; + unsigned short maj_ver; + unsigned short min_ver; + unsigned int dev_type; + unsigned short devmax_ver; + unsigned short devmin_ver; + unsigned int ae_mask; + unsigned int ctx_enables; + char fw_type; + char ctx_mode; + char nn_mode; + char lm0_mode; + char lm1_mode; + char scs_mode; + char lm2_mode; + char lm3_mode; + char tindex_mode; + unsigned char reserved[7]; + char simg_name[256]; + char appmeta_data[256]; +}; + +struct icp_qat_suof_filehdr { + unsigned int file_id; + unsigned int check_sum; + char min_ver; + char maj_ver; + char fw_type; + char reserved; + unsigned short max_chunks; + unsigned short num_chunks; +}; + +struct icp_qat_suof_chunk_hdr { + char chunk_id[ICP_QAT_SUOF_OBJ_ID_LEN]; + u64 offset; + u64 size; +}; + +struct icp_qat_suof_strtable { + unsigned int tab_length; + unsigned int strings; +}; + +struct icp_qat_suof_objhdr { + unsigned int img_length; + unsigned int reserved; +}; + +struct icp_qat_mof_file_hdr { + unsigned int file_id; + unsigned int checksum; + char min_ver; + char maj_ver; + unsigned short reserved; + unsigned short max_chunks; + unsigned short num_chunks; +}; + +struct icp_qat_mof_chunkhdr { + char chunk_id[ICP_QAT_MOF_OBJ_ID_LEN]; + u64 offset; + u64 size; +}; + +struct icp_qat_mof_str_table { + unsigned int tab_len; + unsigned int strings; +}; + +struct icp_qat_mof_obj_hdr { + unsigned short max_chunks; + unsigned short num_chunks; + unsigned int reserved; +}; + +struct icp_qat_mof_obj_chunkhdr { + char chunk_id[ICP_QAT_MOF_OBJ_CHUNKID_LEN]; + u64 offset; + u64 size; + unsigned int name; + unsigned int reserved; +}; + +struct icp_qat_mof_objhdr { + char *obj_name; + const char *obj_buf; + unsigned int obj_size; +}; + +struct icp_qat_mof_table { + unsigned int num_objs; + struct icp_qat_mof_objhdr *obj_hdr; +}; + +struct icp_qat_mof_handle { + unsigned int file_id; + unsigned int checksum; + char min_ver; + char maj_ver; + const char *mof_buf; + u32 mof_size; + char *sym_str; + unsigned int sym_size; + const char *uobjs_hdr; + const char *sobjs_hdr; + struct icp_qat_mof_table obj_table; +}; +#endif diff --git a/sys/dev/qat/include/common/qat_freebsd.h b/sys/dev/qat/include/common/qat_freebsd.h new file mode 100644 index 00000000000..0a9cfc0188e --- /dev/null +++ b/sys/dev/qat/include/common/qat_freebsd.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef QAT_FREEBSD_H_ +#define QAT_FREEBSD_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_VENDOR_ID_INTEL 0x8086 + +#if !defined(__bool_true_false_are_defined) +#define __bool_true_false_are_defined 1 +#define false 0 +#define true 1 +#if __STDC_VERSION__ < 199901L && __GNUC__ < 3 && !defined(__INTEL_COMPILER) +typedef int _Bool; +#endif +typedef _Bool bool; +#endif /* !__bool_true_false_are_defined && !__cplusplus */ + +#if __STDC_VERSION__ < 199901L && __GNUC__ < 3 && !defined(__INTEL_COMPILER) +typedef int _Bool; +#endif + +#define pause_ms(wmesg, ms) pause_sbt(wmesg, (ms)*SBT_1MS, 0, C_HARDCLOCK) + +/* Function sets the MaxPayload size of a PCI device. */ +int pci_set_max_payload(device_t dev, int payload_size); + +device_t pci_find_pf(device_t vf); + +MALLOC_DECLARE(M_QAT); + +struct msix_entry { + struct resource *irq; + void *cookie; +}; + +struct pci_device_id { + uint16_t vendor; + uint16_t device; +}; + +struct bus_dmamem { + bus_dma_tag_t dma_tag; + bus_dmamap_t dma_map; + void *dma_vaddr; + bus_addr_t dma_baddr; +}; + +/* + * Allocate a mapping. On success, zero is returned and the 'dma_vaddr' + * and 'dma_baddr' fields are populated with the virtual and bus addresses, + * respectively, of the mapping. + */ +int bus_dma_mem_create(struct bus_dmamem *mem, + bus_dma_tag_t parent, + bus_size_t alignment, + bus_addr_t lowaddr, + bus_size_t len, + int flags); + +/* + * Release a mapping created by bus_dma_mem_create(). + */ +void bus_dma_mem_free(struct bus_dmamem *mem); + +#define list_for_each_prev_safe(p, n, h) \ + for (p = (h)->prev, n = (p)->prev; p != (h); p = n, n = (p)->prev) + +static inline int +compat_strtoul(const char *cp, unsigned int base, unsigned long *res) +{ + char *end; + + *res = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +compat_strtouint(const char *cp, unsigned int base, unsigned int *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (unsigned int)temp) + return (-ERANGE); + return (0); +} + +static inline int +compat_strtou8(const char *cp, unsigned int base, unsigned char *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return -EINVAL; + if (temp != (unsigned char)temp) + return -ERANGE; + return 0; +} + +#if __FreeBSD_version >= 1300500 +#undef dev_to_node +static inline int +dev_to_node(device_t dev) +{ + int numa_domain; + + if (!dev || bus_get_domain(dev, &numa_domain) != 0) + return (-1); + else + return (numa_domain); +} +#endif +#endif diff --git a/sys/dev/qat/include/common/sal_statistics_strings.h b/sys/dev/qat/include/common/sal_statistics_strings.h new file mode 100644 index 00000000000..aab88a0b374 --- /dev/null +++ b/sys/dev/qat/include/common/sal_statistics_strings.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef SAL_STATISTICS_STRINGS_H +#define SAL_STATISTICS_STRINGS_H + +/* + * Config values names for statistics + */ +#define SAL_STATS_CFG_ENABLED "statsGeneral" +/**< Config value name for enabling/disabling statistics */ +#define SAL_STATS_CFG_DC "statsDc" +/**< Config value name for enabling/disabling Compression statistics */ +#define SAL_STATS_CFG_DH "statsDh" +/**< Config value name for enabling/disabling Diffie-Helman statistics */ +#define SAL_STATS_CFG_DRBG "statsDrbg" +/**< Config value name for enabling/disabling DRBG statistics */ +#define SAL_STATS_CFG_DSA "statsDsa" +/**< Config value name for enabling/disabling DSA statistics */ +#define SAL_STATS_CFG_ECC "statsEcc" +/**< Config value name for enabling/disabling ECC statistics */ +#define SAL_STATS_CFG_KEYGEN "statsKeyGen" +/**< Config value name for enabling/disabling Key Gen statistics */ +#define SAL_STATS_CFG_LN "statsLn" +/**< Config value name for enabling/disabling Large Number statistics */ +#define SAL_STATS_CFG_PRIME "statsPrime" +/**< Config value name for enabling/disabling Prime statistics */ +#define SAL_STATS_CFG_RSA "statsRsa" +/**< Config value name for enabling/disabling RSA statistics */ +#define SAL_STATS_CFG_SYM "statsSym" +/**< Config value name for enabling/disabling Symmetric Crypto statistics */ + +#endif diff --git a/sys/dev/qat/include/icp_qat_fw.h b/sys/dev/qat/include/icp_qat_fw.h new file mode 100644 index 00000000000..fe470b45c28 --- /dev/null +++ b/sys/dev/qat/include/icp_qat_fw.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef _ICP_QAT_FW_H_ +#define _ICP_QAT_FW_H_ +#include +#include "icp_qat_hw.h" + +#define QAT_FIELD_SET(flags, val, bitpos, mask) \ + { \ + (flags) = (((flags) & (~((mask) << (bitpos)))) | \ + (((val) & (mask)) << (bitpos))); \ + } + +#define QAT_FIELD_GET(flags, bitpos, mask) (((flags) >> (bitpos)) & (mask)) + +#define ICP_QAT_FW_REQ_DEFAULT_SZ 128 +#define ICP_QAT_FW_RESP_DEFAULT_SZ 32 +#define ICP_QAT_FW_COMN_ONE_BYTE_SHIFT 8 +#define ICP_QAT_FW_COMN_SINGLE_BYTE_MASK 0xFF +#define ICP_QAT_FW_NUM_LONGWORDS_1 1 +#define ICP_QAT_FW_NUM_LONGWORDS_2 2 +#define ICP_QAT_FW_NUM_LONGWORDS_3 3 +#define ICP_QAT_FW_NUM_LONGWORDS_4 4 +#define ICP_QAT_FW_NUM_LONGWORDS_5 5 +#define ICP_QAT_FW_NUM_LONGWORDS_6 6 +#define ICP_QAT_FW_NUM_LONGWORDS_7 7 +#define ICP_QAT_FW_NUM_LONGWORDS_10 10 +#define ICP_QAT_FW_NUM_LONGWORDS_13 13 +#define ICP_QAT_FW_NULL_REQ_SERV_ID 1 + +enum icp_qat_fw_comn_resp_serv_id { + ICP_QAT_FW_COMN_RESP_SERV_NULL, + ICP_QAT_FW_COMN_RESP_SERV_CPM_FW, + ICP_QAT_FW_COMN_RESP_SERV_DELIMITER +}; + +enum icp_qat_fw_comn_request_id { + ICP_QAT_FW_COMN_REQ_NULL = 0, + ICP_QAT_FW_COMN_REQ_CPM_FW_PKE = 3, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA = 4, + ICP_QAT_FW_COMN_REQ_CPM_FW_DMA = 7, + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP = 9, + ICP_QAT_FW_COMN_REQ_DELIMITER +}; + +struct icp_qat_fw_comn_req_hdr_cd_pars { + union { + struct { + uint64_t content_desc_addr; + uint16_t content_desc_resrvd1; + uint8_t content_desc_params_sz; + uint8_t content_desc_hdr_resrvd2; + uint32_t content_desc_resrvd3; + } s; + struct { + uint32_t serv_specif_fields[4]; + } s1; + } u; +}; + +struct icp_qat_fw_comn_req_mid { + uint64_t opaque_data; + uint64_t src_data_addr; + uint64_t dest_data_addr; + uint32_t src_length; + uint32_t dst_length; +}; + +struct icp_qat_fw_comn_req_cd_ctrl { + uint32_t content_desc_ctrl_lw[ICP_QAT_FW_NUM_LONGWORDS_5]; +}; + +struct icp_qat_fw_comn_req_hdr { + uint8_t resrvd1; + uint8_t service_cmd_id; + uint8_t service_type; + uint8_t hdr_flags; + uint16_t serv_specif_flags; + uint16_t comn_req_flags; +}; + +struct icp_qat_fw_comn_req_rqpars { + uint32_t serv_specif_rqpars_lw[ICP_QAT_FW_NUM_LONGWORDS_13]; +}; + +struct icp_qat_fw_comn_req { + struct icp_qat_fw_comn_req_hdr comn_hdr; + struct icp_qat_fw_comn_req_hdr_cd_pars cd_pars; + struct icp_qat_fw_comn_req_mid comn_mid; + struct icp_qat_fw_comn_req_rqpars serv_specif_rqpars; + struct icp_qat_fw_comn_req_cd_ctrl cd_ctrl; +}; + +struct icp_qat_fw_comn_error { + uint8_t xlat_err_code; + uint8_t cmp_err_code; +}; + +struct icp_qat_fw_comn_resp_hdr { + uint8_t resrvd1; + uint8_t service_id; + uint8_t response_type; + uint8_t hdr_flags; + struct icp_qat_fw_comn_error comn_error; + uint8_t comn_status; + uint8_t cmd_id; +}; + +struct icp_qat_fw_comn_resp { + struct icp_qat_fw_comn_resp_hdr comn_hdr; + uint64_t opaque_data; + uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4]; +}; + +#define ICP_QAT_FW_COMN_REQ_FLAG_SET 1 +#define ICP_QAT_FW_COMN_REQ_FLAG_CLR 0 +#define ICP_QAT_FW_COMN_VALID_FLAG_BITPOS 7 +#define ICP_QAT_FW_COMN_VALID_FLAG_MASK 0x1 +#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK 0x7F + +#define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \ + icp_qat_fw_comn_req_hdr_t.service_type + +#define ICP_QAT_FW_COMN_OV_SRV_TYPE_SET(icp_qat_fw_comn_req_hdr_t, val) \ + icp_qat_fw_comn_req_hdr_t.service_type = val + +#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_GET(icp_qat_fw_comn_req_hdr_t) \ + icp_qat_fw_comn_req_hdr_t.service_cmd_id + +#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_SET(icp_qat_fw_comn_req_hdr_t, val) \ + icp_qat_fw_comn_req_hdr_t.service_cmd_id = val + +#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_GET(hdr_t) \ + ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_t.hdr_flags) + +#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_SET(hdr_t, val) \ + ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) + +#define ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_flags) \ + QAT_FIELD_GET(hdr_flags, \ + ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_VALID_FLAG_MASK) + +#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_GET(hdr_flags) \ + (hdr_flags & ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK) + +#define ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) \ + QAT_FIELD_SET((hdr_t.hdr_flags), \ + (val), \ + ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_VALID_FLAG_MASK) + +#define ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(valid) \ + (((valid)&ICP_QAT_FW_COMN_VALID_FLAG_MASK) \ + << ICP_QAT_FW_COMN_VALID_FLAG_BITPOS) + +#define QAT_COMN_PTR_TYPE_BITPOS 0 +#define QAT_COMN_PTR_TYPE_MASK 0x1 +#define QAT_COMN_CD_FLD_TYPE_BITPOS 1 +#define QAT_COMN_CD_FLD_TYPE_MASK 0x1 +#define QAT_COMN_PTR_TYPE_FLAT 0x0 +#define QAT_COMN_PTR_TYPE_SGL 0x1 +#define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0 +#define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1 + +#define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \ + ((((cdt)&QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) | \ + (((ptr)&QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS)) + +#define ICP_QAT_FW_COMN_PTR_TYPE_GET(flags) \ + QAT_FIELD_GET(flags, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK) + +#define ICP_QAT_FW_COMN_CD_FLD_TYPE_GET(flags) \ + QAT_FIELD_GET(flags, \ + QAT_COMN_CD_FLD_TYPE_BITPOS, \ + QAT_COMN_CD_FLD_TYPE_MASK) + +#define ICP_QAT_FW_COMN_PTR_TYPE_SET(flags, val) \ + QAT_FIELD_SET(flags, \ + val, \ + QAT_COMN_PTR_TYPE_BITPOS, \ + QAT_COMN_PTR_TYPE_MASK) + +#define ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(flags, val) \ + QAT_FIELD_SET(flags, \ + val, \ + QAT_COMN_CD_FLD_TYPE_BITPOS, \ + QAT_COMN_CD_FLD_TYPE_MASK) + +#define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4 +#define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0 +#define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0 +#define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F + +#define ICP_QAT_FW_COMN_NEXT_ID_GET(cd_ctrl_hdr_t) \ + ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ + (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) + +#define ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ + { \ + ((cd_ctrl_hdr_t)->next_curr_id) = \ + ((((cd_ctrl_hdr_t)->next_curr_id) & \ + ICP_QAT_FW_COMN_CURR_ID_MASK) | \ + ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK)); \ + } + +#define ICP_QAT_FW_COMN_CURR_ID_GET(cd_ctrl_hdr_t) \ + (((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK) + +#define ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl_hdr_t, val) \ + { \ + ((cd_ctrl_hdr_t)->next_curr_id) = \ + ((((cd_ctrl_hdr_t)->next_curr_id) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ + ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)); \ + } + +#define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7 +#define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1 +#define QAT_COMN_RESP_PKE_STATUS_BITPOS 6 +#define QAT_COMN_RESP_PKE_STATUS_MASK 0x1 +#define QAT_COMN_RESP_CMP_STATUS_BITPOS 5 +#define QAT_COMN_RESP_CMP_STATUS_MASK 0x1 +#define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4 +#define QAT_COMN_RESP_XLAT_STATUS_MASK 0x1 +#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS 3 +#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK 0x1 + +#define ICP_QAT_FW_COMN_RESP_STATUS_BUILD(crypto, comp, xlat, eolb) \ + ((((crypto)&QAT_COMN_RESP_CRYPTO_STATUS_MASK) \ + << QAT_COMN_RESP_CRYPTO_STATUS_BITPOS) | \ + (((comp)&QAT_COMN_RESP_CMP_STATUS_MASK) \ + << QAT_COMN_RESP_CMP_STATUS_BITPOS) | \ + (((xlat)&QAT_COMN_RESP_XLAT_STATUS_MASK) \ + << QAT_COMN_RESP_XLAT_STATUS_BITPOS) | \ + (((eolb)&QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) \ + << QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS)) + +#define ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CRYPTO_STATUS_BITPOS, \ + QAT_COMN_RESP_CRYPTO_STATUS_MASK) + +#define ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CMP_STATUS_BITPOS, \ + QAT_COMN_RESP_CMP_STATUS_MASK) + +#define ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_XLAT_STATUS_BITPOS, \ + QAT_COMN_RESP_XLAT_STATUS_MASK) + +#define ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS, \ + QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) + +#define ICP_QAT_FW_COMN_STATUS_FLAG_OK 0 +#define ICP_QAT_FW_COMN_STATUS_FLAG_ERROR 1 +#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_CLR 0 +#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET 1 +#define ERR_CODE_NO_ERROR 0 +#define ERR_CODE_INVALID_BLOCK_TYPE -1 +#define ERR_CODE_NO_MATCH_ONES_COMP -2 +#define ERR_CODE_TOO_MANY_LEN_OR_DIS -3 +#define ERR_CODE_INCOMPLETE_LEN -4 +#define ERR_CODE_RPT_LEN_NO_FIRST_LEN -5 +#define ERR_CODE_RPT_GT_SPEC_LEN -6 +#define ERR_CODE_INV_LIT_LEN_CODE_LEN -7 +#define ERR_CODE_INV_DIS_CODE_LEN -8 +#define ERR_CODE_INV_LIT_LEN_DIS_IN_BLK -9 +#define ERR_CODE_DIS_TOO_FAR_BACK -10 +#define ERR_CODE_OVERFLOW_ERROR -11 +#define ERR_CODE_SOFT_ERROR -12 +#define ERR_CODE_FATAL_ERROR -13 +#define ERR_CODE_SSM_ERROR -14 +#define ERR_CODE_ENDPOINT_ERROR -15 + +enum icp_qat_fw_slice { + ICP_QAT_FW_SLICE_NULL = 0, + ICP_QAT_FW_SLICE_CIPHER = 1, + ICP_QAT_FW_SLICE_AUTH = 2, + ICP_QAT_FW_SLICE_DRAM_RD = 3, + ICP_QAT_FW_SLICE_DRAM_WR = 4, + ICP_QAT_FW_SLICE_COMP = 5, + ICP_QAT_FW_SLICE_XLAT = 6, + ICP_QAT_FW_SLICE_DELIMITER +}; +#endif diff --git a/sys/dev/qat/include/icp_qat_fw_init_admin.h b/sys/dev/qat/include/icp_qat_fw_init_admin.h new file mode 100644 index 00000000000..6f88de14477 --- /dev/null +++ b/sys/dev/qat/include/icp_qat_fw_init_admin.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef _ICP_QAT_FW_INIT_ADMIN_H_ +#define _ICP_QAT_FW_INIT_ADMIN_H_ + +#include "icp_qat_fw.h" + +enum icp_qat_fw_init_admin_cmd_id { + ICP_QAT_FW_INIT_ME = 0, + ICP_QAT_FW_TRNG_ENABLE = 1, + ICP_QAT_FW_TRNG_DISABLE = 2, + ICP_QAT_FW_CONSTANTS_CFG = 3, + ICP_QAT_FW_STATUS_GET = 4, + ICP_QAT_FW_COUNTERS_GET = 5, + ICP_QAT_FW_LOOPBACK = 6, + ICP_QAT_FW_HEARTBEAT_SYNC = 7, + ICP_QAT_FW_HEARTBEAT_GET = 8, + ICP_QAT_FW_COMP_CAPABILITY_GET = 9, + ICP_QAT_FW_CRYPTO_CAPABILITY_GET = 10, + ICP_QAT_FW_HEARTBEAT_TIMER_SET = 13, + ICP_QAT_FW_RL_SLA_CONFIG = 14, + ICP_QAT_FW_RL_INIT = 15, + ICP_QAT_FW_RL_DU_START = 16, + ICP_QAT_FW_RL_DU_STOP = 17, + ICP_QAT_FW_TIMER_GET = 19, + ICP_QAT_FW_CNV_STATS_GET = 20, + ICP_QAT_FW_PKE_REPLAY_STATS_GET = 21 +}; + +enum icp_qat_fw_init_admin_resp_status { + ICP_QAT_FW_INIT_RESP_STATUS_SUCCESS = 0, + ICP_QAT_FW_INIT_RESP_STATUS_FAIL = 1, + ICP_QAT_FW_INIT_RESP_STATUS_UNSUPPORTED = 4 +}; + +enum icp_qat_fw_cnv_error_type { + CNV_ERR_TYPE_NO_ERROR = 0, + CNV_ERR_TYPE_CHECKSUM_ERROR, + CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH_ERROR, + CNV_ERR_TYPE_DECOMPRESSION_ERROR, + CNV_ERR_TYPE_TRANSLATION_ERROR, + CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH_ERROR, + CNV_ERR_TYPE_UNKNOWN_ERROR +}; + +#define CNV_ERROR_TYPE_GET(latest_error) \ + ({ \ + __typeof__(latest_error) _lerror = latest_error; \ + (_lerror >> 12) > CNV_ERR_TYPE_UNKNOWN_ERROR ? \ + CNV_ERR_TYPE_UNKNOWN_ERROR : \ + (enum icp_qat_fw_cnv_error_type)(_lerror >> 12); \ + }) +#define CNV_ERROR_LENGTH_DELTA_GET(latest_error) \ + ({ \ + __typeof__(latest_error) _lerror = latest_error; \ + ((s16)((_lerror & 0x0FFF) | (_lerror & 0x0800 ? 0xF000 : 0))); \ + }) +#define CNV_ERROR_DECOMP_STATUS_GET(latest_error) ((s8)(latest_error & 0xFF)) + +struct icp_qat_fw_init_admin_req { + u16 init_cfg_sz; + u8 resrvd1; + u8 cmd_id; + u32 max_req_duration; + u64 opaque_data; + + union { + /* ICP_QAT_FW_INIT_ME */ + struct { + u64 resrvd2; + u16 ibuf_size_in_kb; + u16 resrvd3; + u32 resrvd4; + }; + /* ICP_QAT_FW_CONSTANTS_CFG */ + struct { + u64 init_cfg_ptr; + u64 resrvd5; + }; + /* ICP_QAT_FW_HEARTBEAT_TIMER_SET */ + struct { + u64 hb_cfg_ptr; + u32 heartbeat_ticks; + u32 resrvd6; + }; + /* ICP_QAT_FW_RL_SLA_CONFIG */ + struct { + u32 credit_per_sla; + u8 service_id; + u8 vf_id; + u8 resrvd7; + u8 resrvd8; + u32 resrvd9; + u32 resrvd10; + }; + /* ICP_QAT_FW_RL_INIT */ + struct { + u32 rl_period; + u8 config; + u8 resrvd11; + u8 num_me; + u8 resrvd12; + u8 pke_svc_arb_map; + u8 bulk_crypto_svc_arb_map; + u8 compression_svc_arb_map; + u8 resrvd13; + u32 resrvd14; + }; + /* ICP_QAT_FW_RL_DU_STOP */ + struct { + u64 cfg_ptr; + u32 resrvd15; + u32 resrvd16; + }; + }; +} __packed; + +struct icp_qat_fw_init_admin_resp { + u8 flags; + u8 resrvd1; + u8 status; + u8 cmd_id; + union { + u32 resrvd2; + u32 ras_event_count; + /* ICP_QAT_FW_STATUS_GET */ + struct { + u16 version_minor_num; + u16 version_major_num; + }; + /* ICP_QAT_FW_COMP_CAPABILITY_GET */ + u32 extended_features; + /* ICP_QAT_FW_CNV_STATS_GET */ + struct { + u16 error_count; + u16 latest_error; + }; + }; + u64 opaque_data; + union { + u32 resrvd3[4]; + /* ICP_QAT_FW_STATUS_GET */ + struct { + u32 version_patch_num; + u8 context_id; + u8 ae_id; + u16 resrvd4; + u64 resrvd5; + }; + /* ICP_QAT_FW_COMP_CAPABILITY_GET */ + struct { + u16 compression_algos; + u16 checksum_algos; + u32 deflate_capabilities; + u32 resrvd6; + u32 deprecated; + }; + /* ICP_QAT_FW_CRYPTO_CAPABILITY_GET */ + struct { + u32 cipher_algos; + u32 hash_algos; + u16 keygen_algos; + u16 other; + u16 public_key_algos; + u16 prime_algos; + }; + /* ICP_QAT_FW_RL_DU_STOP */ + struct { + u32 resrvd7; + u8 granularity; + u8 resrvd8; + u16 resrvd9; + u32 total_du_time; + u32 resrvd10; + }; + /* ICP_QAT_FW_TIMER_GET */ + struct { + u64 timestamp; + u64 resrvd11; + }; + /* ICP_QAT_FW_COUNTERS_GET */ + struct { + u64 req_rec_count; + u64 resp_sent_count; + }; + /* ICP_QAT_FW_PKE_REPLAY_STATS_GET */ + struct { + u32 successful_count; + u32 unsuccessful_count; + u64 resrvd12; + }; + }; +} __packed; + +enum icp_qat_fw_init_admin_init_flag { ICP_QAT_FW_INIT_FLAG_PKE_DISABLED = 0 }; + +struct icp_qat_fw_init_admin_hb_cnt { + u16 resp_heartbeat_cnt; + u16 req_heartbeat_cnt; +}; + +struct icp_qat_fw_init_admin_hb_stats { + struct icp_qat_fw_init_admin_hb_cnt stats[ADF_NUM_HB_CNT_PER_AE]; +}; + +#define ICP_QAT_FW_COMN_HEARTBEAT_OK 0 +#define ICP_QAT_FW_COMN_HEARTBEAT_BLOCKED 1 +#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS 0 +#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK 0x1 +#define ICP_QAT_FW_COMN_STATUS_RESRVD_FLD_MASK 0xFE +#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_GET(hdr_t) \ + ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(hdr_t.flags) + +#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_SET(hdr_t, val) \ + ICP_QAT_FW_COMN_HEARTBEAT_FLAG_SET(hdr_t, val) + +#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK) +#endif diff --git a/sys/dev/qat/include/icp_qat_hw.h b/sys/dev/qat/include/icp_qat_hw.h new file mode 100644 index 00000000000..e98c8db06f6 --- /dev/null +++ b/sys/dev/qat/include/icp_qat_hw.h @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef _ICP_QAT_HW_H_ +#define _ICP_QAT_HW_H_ + +enum icp_qat_hw_ae_id { + ICP_QAT_HW_AE_0 = 0, + ICP_QAT_HW_AE_1 = 1, + ICP_QAT_HW_AE_2 = 2, + ICP_QAT_HW_AE_3 = 3, + ICP_QAT_HW_AE_4 = 4, + ICP_QAT_HW_AE_5 = 5, + ICP_QAT_HW_AE_6 = 6, + ICP_QAT_HW_AE_7 = 7, + ICP_QAT_HW_AE_8 = 8, + ICP_QAT_HW_AE_9 = 9, + ICP_QAT_HW_AE_10 = 10, + ICP_QAT_HW_AE_11 = 11, + ICP_QAT_HW_AE_DELIMITER = 12 +}; + +enum icp_qat_hw_qat_id { + ICP_QAT_HW_QAT_0 = 0, + ICP_QAT_HW_QAT_1 = 1, + ICP_QAT_HW_QAT_2 = 2, + ICP_QAT_HW_QAT_3 = 3, + ICP_QAT_HW_QAT_4 = 4, + ICP_QAT_HW_QAT_5 = 5, + ICP_QAT_HW_QAT_DELIMITER = 6 +}; + +enum icp_qat_hw_auth_algo { + ICP_QAT_HW_AUTH_ALGO_NULL = 0, + ICP_QAT_HW_AUTH_ALGO_SHA1 = 1, + ICP_QAT_HW_AUTH_ALGO_MD5 = 2, + ICP_QAT_HW_AUTH_ALGO_SHA224 = 3, + ICP_QAT_HW_AUTH_ALGO_SHA256 = 4, + ICP_QAT_HW_AUTH_ALGO_SHA384 = 5, + ICP_QAT_HW_AUTH_ALGO_SHA512 = 6, + ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC = 7, + ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC = 8, + ICP_QAT_HW_AUTH_ALGO_AES_F9 = 9, + ICP_QAT_HW_AUTH_ALGO_GALOIS_128 = 10, + ICP_QAT_HW_AUTH_ALGO_GALOIS_64 = 11, + ICP_QAT_HW_AUTH_ALGO_KASUMI_F9 = 12, + ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 = 13, + ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 = 14, + ICP_QAT_HW_AUTH_RESERVED_1 = 15, + ICP_QAT_HW_AUTH_RESERVED_2 = 16, + ICP_QAT_HW_AUTH_ALGO_SHA3_256 = 17, + ICP_QAT_HW_AUTH_RESERVED_3 = 18, + ICP_QAT_HW_AUTH_ALGO_SHA3_512 = 19, + ICP_QAT_HW_AUTH_ALGO_DELIMITER = 20 +}; + +enum icp_qat_hw_auth_mode { + ICP_QAT_HW_AUTH_MODE0 = 0, + ICP_QAT_HW_AUTH_MODE1 = 1, + ICP_QAT_HW_AUTH_MODE2 = 2, + ICP_QAT_HW_AUTH_MODE_DELIMITER = 3 +}; + +struct icp_qat_hw_auth_config { + uint32_t config; + uint32_t reserved; +}; +enum icp_qat_slice_mask { + ICP_ACCEL_MASK_CIPHER_SLICE = 0x01, + ICP_ACCEL_MASK_AUTH_SLICE = 0x02, + ICP_ACCEL_MASK_PKE_SLICE = 0x04, + ICP_ACCEL_MASK_COMPRESS_SLICE = 0x08, + ICP_ACCEL_MASK_DEPRECATED = 0x10, + ICP_ACCEL_MASK_EIA3_SLICE = 0x20, + ICP_ACCEL_MASK_SHA3_SLICE = 0x40, + ICP_ACCEL_MASK_CRYPTO0_SLICE = 0x80, + ICP_ACCEL_MASK_CRYPTO1_SLICE = 0x100, + ICP_ACCEL_MASK_CRYPTO2_SLICE = 0x200, + ICP_ACCEL_MASK_SM3_SLICE = 0x400, + ICP_ACCEL_MASK_SM4_SLICE = 0x800 +}; + +enum icp_qat_capabilities_mask { + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = BIT(0), + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = BIT(1), + ICP_ACCEL_CAPABILITIES_CIPHER = BIT(2), + ICP_ACCEL_CAPABILITIES_AUTHENTICATION = BIT(3), + ICP_ACCEL_CAPABILITIES_RESERVED_1 = BIT(4), + ICP_ACCEL_CAPABILITIES_COMPRESSION = BIT(5), + ICP_ACCEL_CAPABILITIES_DEPRECATED = BIT(6), + ICP_ACCEL_CAPABILITIES_RAND = BIT(7), + ICP_ACCEL_CAPABILITIES_ZUC = BIT(8), + ICP_ACCEL_CAPABILITIES_SHA3 = BIT(9), + ICP_ACCEL_CAPABILITIES_KPT = BIT(10), + ICP_ACCEL_CAPABILITIES_RL = BIT(11), + ICP_ACCEL_CAPABILITIES_HKDF = BIT(12), + ICP_ACCEL_CAPABILITIES_ECEDMONT = BIT(13), + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN = BIT(14), + ICP_ACCEL_CAPABILITIES_SHA3_EXT = BIT(15), + ICP_ACCEL_CAPABILITIES_AESGCM_SPC = BIT(16), + ICP_ACCEL_CAPABILITIES_CHACHA_POLY = BIT(17), + ICP_ACCEL_CAPABILITIES_SM2 = BIT(18), + ICP_ACCEL_CAPABILITIES_SM3 = BIT(19), + ICP_ACCEL_CAPABILITIES_SM4 = BIT(20), + ICP_ACCEL_CAPABILITIES_INLINE = BIT(21), + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY = BIT(22), + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64 = BIT(23), + ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = BIT(24), + ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION = BIT(25), + ICP_ACCEL_CAPABILITIES_AES_V2 = BIT(26), + ICP_ACCEL_CAPABILITIES_KPT2 = BIT(27), +}; + +enum icp_qat_extended_dc_capabilities_mask { + ICP_ACCEL_CAPABILITIES_ADVANCED_COMPRESSION = 0x101 +}; + +#define QAT_AUTH_MODE_BITPOS 4 +#define QAT_AUTH_MODE_MASK 0xF +#define QAT_AUTH_ALGO_BITPOS 0 +#define QAT_AUTH_ALGO_MASK 0xF +#define QAT_AUTH_CMP_BITPOS 8 +#define QAT_AUTH_HIGH_BIT 4 +#define QAT_AUTH_CMP_MASK 0x7F +#define QAT_AUTH_SHA3_PADDING_BITPOS 16 +#define QAT_AUTH_SHA3_PADDING_MASK 0x1 +#define QAT_AUTH_ALGO_SHA3_BITPOS 22 +#define QAT_AUTH_ALGO_SHA3_MASK 0x3 +#define ICP_QAT_HW_AUTH_CONFIG_BUILD(mode, algo, cmp_len) \ + (((mode & QAT_AUTH_MODE_MASK) << QAT_AUTH_MODE_BITPOS) | \ + ((algo & QAT_AUTH_ALGO_MASK) << QAT_AUTH_ALGO_BITPOS) | \ + (((algo >> 4) & QAT_AUTH_ALGO_SHA3_MASK) \ + << QAT_AUTH_ALGO_SHA3_BITPOS) | \ + (((((algo == ICP_QAT_HW_AUTH_ALGO_SHA3_256) || \ + (algo == ICP_QAT_HW_AUTH_ALGO_SHA3_512)) ? \ + 1 : \ + 0) & \ + QAT_AUTH_SHA3_PADDING_MASK) \ + << QAT_AUTH_SHA3_PADDING_BITPOS) | \ + ((cmp_len & QAT_AUTH_CMP_MASK) << QAT_AUTH_CMP_BITPOS)) + +struct icp_qat_hw_auth_counter { + __be32 counter; + uint32_t reserved; +}; + +#define QAT_AUTH_COUNT_MASK 0xFFFFFFFF +#define QAT_AUTH_COUNT_BITPOS 0 +#define ICP_QAT_HW_AUTH_COUNT_BUILD(val) \ + (((val)&QAT_AUTH_COUNT_MASK) << QAT_AUTH_COUNT_BITPOS) + +struct icp_qat_hw_auth_setup { + struct icp_qat_hw_auth_config auth_config; + struct icp_qat_hw_auth_counter auth_counter; +}; + +#define QAT_HW_DEFAULT_ALIGNMENT 8 +#define QAT_HW_ROUND_UP(val, n) (((val) + ((n)-1)) & (~(n - 1))) +#define ICP_QAT_HW_NULL_STATE1_SZ 32 +#define ICP_QAT_HW_MD5_STATE1_SZ 16 +#define ICP_QAT_HW_SHA1_STATE1_SZ 20 +#define ICP_QAT_HW_SHA224_STATE1_SZ 32 +#define ICP_QAT_HW_SHA256_STATE1_SZ 32 +#define ICP_QAT_HW_SHA3_256_STATE1_SZ 32 +#define ICP_QAT_HW_SHA384_STATE1_SZ 64 +#define ICP_QAT_HW_SHA512_STATE1_SZ 64 +#define ICP_QAT_HW_SHA3_512_STATE1_SZ 64 +#define ICP_QAT_HW_SHA3_224_STATE1_SZ 28 +#define ICP_QAT_HW_SHA3_384_STATE1_SZ 48 +#define ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ 16 +#define ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ 16 +#define ICP_QAT_HW_AES_F9_STATE1_SZ 32 +#define ICP_QAT_HW_KASUMI_F9_STATE1_SZ 16 +#define ICP_QAT_HW_GALOIS_128_STATE1_SZ 16 +#define ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ 8 +#define ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ 8 +#define ICP_QAT_HW_NULL_STATE2_SZ 32 +#define ICP_QAT_HW_MD5_STATE2_SZ 16 +#define ICP_QAT_HW_SHA1_STATE2_SZ 20 +#define ICP_QAT_HW_SHA224_STATE2_SZ 32 +#define ICP_QAT_HW_SHA256_STATE2_SZ 32 +#define ICP_QAT_HW_SHA3_256_STATE2_SZ 0 +#define ICP_QAT_HW_SHA384_STATE2_SZ 64 +#define ICP_QAT_HW_SHA512_STATE2_SZ 64 +#define ICP_QAT_HW_SHA3_512_STATE2_SZ 0 +#define ICP_QAT_HW_SHA3_224_STATE2_SZ 0 +#define ICP_QAT_HW_SHA3_384_STATE2_SZ 0 +#define ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ 16 +#define ICP_QAT_HW_AES_CBC_MAC_KEY_SZ 16 +#define ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ 16 +#define ICP_QAT_HW_F9_IK_SZ 16 +#define ICP_QAT_HW_F9_FK_SZ 16 +#define ICP_QAT_HW_KASUMI_F9_STATE2_SZ \ + (ICP_QAT_HW_F9_IK_SZ + ICP_QAT_HW_F9_FK_SZ) +#define ICP_QAT_HW_AES_F9_STATE2_SZ ICP_QAT_HW_KASUMI_F9_STATE2_SZ +#define ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ 24 +#define ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ 32 +#define ICP_QAT_HW_GALOIS_H_SZ 16 +#define ICP_QAT_HW_GALOIS_LEN_A_SZ 8 +#define ICP_QAT_HW_GALOIS_E_CTR0_SZ 16 + +struct icp_qat_hw_auth_sha512 { + struct icp_qat_hw_auth_setup inner_setup; + uint8_t state1[ICP_QAT_HW_SHA512_STATE1_SZ]; + struct icp_qat_hw_auth_setup outer_setup; + uint8_t state2[ICP_QAT_HW_SHA512_STATE2_SZ]; +}; + +struct icp_qat_hw_auth_algo_blk { + struct icp_qat_hw_auth_sha512 sha; +}; + +#define ICP_QAT_HW_GALOIS_LEN_A_BITPOS 0 +#define ICP_QAT_HW_GALOIS_LEN_A_MASK 0xFFFFFFFF + +enum icp_qat_hw_cipher_algo { + ICP_QAT_HW_CIPHER_ALGO_NULL = 0, + ICP_QAT_HW_CIPHER_ALGO_DES = 1, + ICP_QAT_HW_CIPHER_ALGO_3DES = 2, + ICP_QAT_HW_CIPHER_ALGO_AES128 = 3, + ICP_QAT_HW_CIPHER_ALGO_AES192 = 4, + ICP_QAT_HW_CIPHER_ALGO_AES256 = 5, + ICP_QAT_HW_CIPHER_ALGO_ARC4 = 6, + ICP_QAT_HW_CIPHER_ALGO_KASUMI = 7, + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 = 8, + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3 = 9, + ICP_QAT_HW_CIPHER_ALGO_SM4 = 10, + ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305 = 11, + ICP_QAT_HW_CIPHER_DELIMITER = 12 +}; + +enum icp_qat_hw_cipher_mode { + ICP_QAT_HW_CIPHER_ECB_MODE = 0, + ICP_QAT_HW_CIPHER_CBC_MODE = 1, + ICP_QAT_HW_CIPHER_CTR_MODE = 2, + ICP_QAT_HW_CIPHER_F8_MODE = 3, + ICP_QAT_HW_CIPHER_AEAD_MODE = 4, + ICP_QAT_HW_CIPHER_RESERVED_MODE = 5, + ICP_QAT_HW_CIPHER_XTS_MODE = 6, + ICP_QAT_HW_CIPHER_MODE_DELIMITER = 7 +}; + +struct icp_qat_hw_cipher_config { + uint32_t val; + uint32_t reserved; +}; + +enum icp_qat_hw_cipher_dir { + ICP_QAT_HW_CIPHER_ENCRYPT = 0, + ICP_QAT_HW_CIPHER_DECRYPT = 1, +}; + +enum icp_qat_hw_cipher_convert { + ICP_QAT_HW_CIPHER_NO_CONVERT = 0, + ICP_QAT_HW_CIPHER_KEY_CONVERT = 1, +}; + +#define QAT_CIPHER_MODE_BITPOS 4 +#define QAT_CIPHER_MODE_MASK 0xF +#define QAT_CIPHER_ALGO_BITPOS 0 +#define QAT_CIPHER_ALGO_MASK 0xF +#define QAT_CIPHER_CONVERT_BITPOS 9 +#define QAT_CIPHER_CONVERT_MASK 0x1 +#define QAT_CIPHER_DIR_BITPOS 8 +#define QAT_CIPHER_DIR_MASK 0x1 +#define QAT_CIPHER_AEAD_HASH_CMP_LEN_MASK 0x1F +#define QAT_CIPHER_AEAD_HASH_CMP_LEN_BITPOS 10 +#define QAT_CIPHER_AEAD_AAD_SIZE_LOWER_MASK 0xFF +#define QAT_CIPHER_AEAD_AAD_SIZE_UPPER_MASK 0x3F +#define QAT_CIPHER_AEAD_AAD_UPPER_SHIFT 8 +#define QAT_CIPHER_AEAD_AAD_LOWER_SHIFT 24 +#define QAT_CIPHER_AEAD_AAD_SIZE_BITPOS 16 +#define QAT_CIPHER_MODE_F8_KEY_SZ_MULT 2 +#define QAT_CIPHER_MODE_XTS_KEY_SZ_MULT 2 +#define ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, algo, convert, dir) \ + (((mode & QAT_CIPHER_MODE_MASK) << QAT_CIPHER_MODE_BITPOS) | \ + ((algo & QAT_CIPHER_ALGO_MASK) << QAT_CIPHER_ALGO_BITPOS) | \ + ((convert & QAT_CIPHER_CONVERT_MASK) << QAT_CIPHER_CONVERT_BITPOS) | \ + ((dir & QAT_CIPHER_DIR_MASK) << QAT_CIPHER_DIR_BITPOS)) +#define ICP_QAT_HW_DES_BLK_SZ 8 +#define ICP_QAT_HW_3DES_BLK_SZ 8 +#define ICP_QAT_HW_NULL_BLK_SZ 8 +#define ICP_QAT_HW_AES_BLK_SZ 16 +#define ICP_QAT_HW_KASUMI_BLK_SZ 8 +#define ICP_QAT_HW_SNOW_3G_BLK_SZ 8 +#define ICP_QAT_HW_ZUC_3G_BLK_SZ 8 +#define ICP_QAT_HW_NULL_KEY_SZ 256 +#define ICP_QAT_HW_DES_KEY_SZ 8 +#define ICP_QAT_HW_3DES_KEY_SZ 24 +#define ICP_QAT_HW_AES_128_KEY_SZ 16 +#define ICP_QAT_HW_AES_192_KEY_SZ 24 +#define ICP_QAT_HW_AES_256_KEY_SZ 32 +#define ICP_QAT_HW_AES_128_F8_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_192_F8_KEY_SZ \ + (ICP_QAT_HW_AES_192_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_256_F8_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_128_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_256_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +#define ICP_QAT_HW_KASUMI_KEY_SZ 16 +#define ICP_QAT_HW_KASUMI_F8_KEY_SZ \ + (ICP_QAT_HW_KASUMI_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_128_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +#define ICP_QAT_HW_AES_256_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +#define ICP_QAT_HW_ARC4_KEY_SZ 256 +#define ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ 16 +#define ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ 16 +#define ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ 16 +#define ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ 16 +#define ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR 2 +#define INIT_SHRAM_CONSTANTS_TABLE_SZ 1024 + +struct icp_qat_hw_cipher_aes256_f8 { + struct icp_qat_hw_cipher_config cipher_config; + uint8_t key[ICP_QAT_HW_AES_256_F8_KEY_SZ]; +}; + +struct icp_qat_hw_cipher_algo_blk { + struct icp_qat_hw_cipher_aes256_f8 aes; +} __aligned(64); +#endif diff --git a/sys/dev/qat/include/qat_ocf_mem_pool.h b/sys/dev/qat/include/qat_ocf_mem_pool.h new file mode 100644 index 00000000000..d1a59835f4f --- /dev/null +++ b/sys/dev/qat/include/qat_ocf_mem_pool.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef _QAT_OCF_MEM_POOL_H_ +#define _QAT_OCF_MEM_POOL_H_ + +/* System headers */ +#include + +/* QAT specific headers */ +#include "cpa.h" +#include "cpa_cy_sym_dp.h" +#include "icp_qat_fw_la.h" + +#define QAT_OCF_MAX_LEN (64 * 1024) +#define QAT_OCF_MAX_FLATS (32) +#define QAT_OCF_MAX_DIGEST SHA512_DIGEST_LENGTH +#define QAT_OCF_MAX_SYMREQ (256) +#define QAT_OCF_MEM_POOL_SIZE ((QAT_OCF_MAX_SYMREQ * 2 + 1) * 2) +#define QAT_OCF_MAXLEN 64 * 1024 + +/* Dedicated structure due to flexible arrays not allowed to be + * allocated on stack */ +struct qat_ocf_buffer_list { + Cpa64U reserved0; + Cpa32U numBuffers; + Cpa32U reserved1; + CpaPhysFlatBuffer flatBuffers[QAT_OCF_MAX_FLATS]; +}; + +struct qat_ocf_dma_mem { + bus_dma_tag_t dma_tag; + bus_dmamap_t dma_map; + bus_dma_segment_t dma_seg; + void *dma_vaddr; +} __aligned(64); + +struct qat_ocf_cookie { + /* Source SGLs */ + struct qat_ocf_buffer_list src_buffers; + /* Destination SGL */ + struct qat_ocf_buffer_list dst_buffers; + + /* Cache OP data */ + CpaCySymDpOpData pOpdata; + + /* IV max size taken from cryptdev */ + uint8_t qat_ocf_iv_buf[EALG_MAX_BLOCK_LEN]; + bus_addr_t qat_ocf_iv_buf_paddr; + uint8_t qat_ocf_digest[QAT_OCF_MAX_DIGEST]; + bus_addr_t qat_ocf_digest_paddr; + /* Used only in case of separated AAD and GCM, CCM and RC4 */ + uint8_t qat_ocf_gcm_aad[ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX]; + bus_addr_t qat_ocf_gcm_aad_paddr; + + /* Source SGLs */ + struct qat_ocf_dma_mem src_dma_mem; + bus_addr_t src_buffer_list_paddr; + + /* Destination SGL */ + struct qat_ocf_dma_mem dst_dma_mem; + bus_addr_t dst_buffer_list_paddr; + + /* AAD - used only if separated AAD is used by OCF and HW requires + * to have it at the beginning of source buffer */ + struct qat_ocf_dma_mem gcm_aad_dma_mem; + bus_addr_t gcm_aad_buffer_list_paddr; + CpaBoolean is_sep_aad_used; + + /* Cache OP data */ + bus_addr_t pOpData_paddr; + /* misc */ + struct cryptop *crp_op; + + /* This cookie tag and map */ + bus_dma_tag_t dma_tag; + bus_dmamap_t dma_map; +}; + +struct qat_ocf_session { + CpaCySymSessionCtx sessionCtx; + Cpa32U sessionCtxSize; + Cpa32U authLen; + Cpa32U aadLen; +}; + +struct qat_ocf_dsession { + struct qat_ocf_instance *qatInstance; + struct qat_ocf_session encSession; + struct qat_ocf_session decSession; +}; + +struct qat_ocf_load_cb_arg { + struct cryptop *crp_op; + struct qat_ocf_cookie *qat_cookie; + CpaCySymDpOpData *pOpData; + int error; +}; + +struct qat_ocf_instance { + CpaInstanceHandle cyInstHandle; + struct mtx cyInstMtx; + struct qat_ocf_dma_mem cookie_dmamem[QAT_OCF_MEM_POOL_SIZE]; + struct qat_ocf_cookie *cookie_pool[QAT_OCF_MEM_POOL_SIZE]; + struct qat_ocf_cookie *free_cookie[QAT_OCF_MEM_POOL_SIZE]; + int free_cookie_ptr; + struct mtx cookie_pool_mtx; + int32_t driver_id; +}; + +/* Init/deinit */ +CpaStatus qat_ocf_cookie_pool_init(struct qat_ocf_instance *instance, + device_t dev); +void qat_ocf_cookie_pool_deinit(struct qat_ocf_instance *instance); +/* Alloc/free */ +CpaStatus qat_ocf_cookie_alloc(struct qat_ocf_instance *instance, + struct qat_ocf_cookie **buffers_out); +void qat_ocf_cookie_free(struct qat_ocf_instance *instance, + struct qat_ocf_cookie *cookie); +/* Pre/post sync */ +CpaStatus qat_ocf_cookie_dma_pre_sync(struct cryptop *crp, + CpaCySymDpOpData *pOpData); +CpaStatus qat_ocf_cookie_dma_post_sync(struct cryptop *crp, + CpaCySymDpOpData *pOpData); +/* Bus DMA unload */ +CpaStatus qat_ocf_cookie_dma_unload(struct cryptop *crp, + CpaCySymDpOpData *pOpData); +/* Bus DMA load callbacks */ +void qat_ocf_crypto_load_buf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error); +void qat_ocf_crypto_load_obuf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error); +void qat_ocf_crypto_load_aadbuf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error); + +#endif /* _QAT_OCF_MEM_POOL_H_ */ diff --git a/sys/dev/qat/include/qat_ocf_utils.h b/sys/dev/qat/include/qat_ocf_utils.h new file mode 100644 index 00000000000..0cacd8f0a84 --- /dev/null +++ b/sys/dev/qat/include/qat_ocf_utils.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef _QAT_OCF_UTILS_H_ +#define _QAT_OCF_UTILS_H_ +/* System headers */ +#include +#include +#include + +/* Cryptodev headers */ +#include +#include + +/* QAT specific headers */ +#include "qat_ocf_mem_pool.h" +#include "cpa.h" +#include "cpa_cy_sym_dp.h" + +static inline CpaBoolean +is_gmac_exception(const struct crypto_session_params *csp) +{ + if (CSP_MODE_DIGEST == csp->csp_mode) + if (CRYPTO_AES_NIST_GMAC == csp->csp_auth_alg) + return CPA_TRUE; + + return CPA_FALSE; +} + +static inline CpaBoolean +is_sep_aad_supported(const struct crypto_session_params *csp) +{ + if (CPA_TRUE == is_gmac_exception(csp)) + return CPA_FALSE; + + if (CSP_MODE_AEAD == csp->csp_mode) + if (CRYPTO_AES_NIST_GCM_16 == csp->csp_cipher_alg || + CRYPTO_AES_NIST_GMAC == csp->csp_cipher_alg) + return CPA_TRUE; + + return CPA_FALSE; +} + +static inline CpaBoolean +is_use_sep_digest(const struct crypto_session_params *csp) +{ + /* Use separated digest for all digest/hash operations, + * including GMAC */ + if (CSP_MODE_DIGEST == csp->csp_mode || CSP_MODE_ETA == csp->csp_mode) + return CPA_TRUE; + + return CPA_FALSE; +} + +int qat_ocf_handle_session_update(struct qat_ocf_dsession *ocf_dsession, + struct cryptop *crp); + +CpaStatus qat_ocf_wait_for_session(CpaCySymSessionCtx sessionCtx, + Cpa32U timeoutMS); + +#endif /* _QAT_OCF_UTILS_H_ */ diff --git a/sys/dev/qat/qat/qat_ocf.c b/sys/dev/qat/qat/qat_ocf.c new file mode 100644 index 00000000000..2461f3134a7 --- /dev/null +++ b/sys/dev/qat/qat/qat_ocf.c @@ -0,0 +1,1228 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/* System headers */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Cryptodev headers */ +#include +#include "cryptodev_if.h" + +/* QAT specific headers */ +#include "cpa.h" +#include "cpa_cy_im.h" +#include "cpa_cy_sym_dp.h" +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_hash_defs_lookup.h" + +/* To get only IRQ instances */ +#include "icp_accel_devices.h" +#include "icp_adf_accel_mgr.h" +#include "lac_sal_types.h" + +/* QAT OCF specific headers */ +#include "qat_ocf_mem_pool.h" +#include "qat_ocf_utils.h" + +#define QAT_OCF_MAX_INSTANCES (256) +#define QAT_OCF_SESSION_WAIT_TIMEOUT_MS (1000) + +MALLOC_DEFINE(M_QAT_OCF, "qat_ocf", "qat_ocf(4) memory allocations"); + +/* QAT OCF internal structures */ +struct qat_ocf_softc { + device_t sc_dev; + int32_t cryptodev_id; + struct qat_ocf_instance cyInstHandles[QAT_OCF_MAX_INSTANCES]; + int32_t numCyInstances; +}; + +/* Function definitions */ +static void qat_ocf_freesession(device_t dev, crypto_session_t cses); +static int qat_ocf_probesession(device_t dev, + const struct crypto_session_params *csp); +static int qat_ocf_newsession(device_t dev, + crypto_session_t cses, + const struct crypto_session_params *csp); +static int qat_ocf_attach(device_t dev); +static int qat_ocf_detach(device_t dev); + +static void +symDpCallback(CpaCySymDpOpData *pOpData, + CpaStatus result, + CpaBoolean verifyResult) +{ + struct qat_ocf_cookie *qat_cookie; + struct cryptop *crp; + struct qat_ocf_dsession *qat_dsession = NULL; + struct qat_ocf_session *qat_session = NULL; + struct qat_ocf_instance *qat_instance = NULL; + CpaStatus status; + int rc = 0; + + qat_cookie = (struct qat_ocf_cookie *)pOpData->pCallbackTag; + if (!qat_cookie) + return; + + crp = qat_cookie->crp_op; + + qat_dsession = crypto_get_driver_session(crp->crp_session); + qat_instance = qat_dsession->qatInstance; + + status = qat_ocf_cookie_dma_post_sync(crp, pOpData); + if (CPA_STATUS_SUCCESS != status) { + rc = EIO; + goto exit; + } + + status = qat_ocf_cookie_dma_unload(crp, pOpData); + if (CPA_STATUS_SUCCESS != status) { + rc = EIO; + goto exit; + } + + /* Verify result */ + if (CPA_STATUS_SUCCESS != result) { + rc = EBADMSG; + goto exit; + } + + /* Verify digest by FW (GCM and CCM only) */ + if (CPA_TRUE != verifyResult) { + rc = EBADMSG; + goto exit; + } + + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) + qat_session = &qat_dsession->encSession; + else + qat_session = &qat_dsession->decSession; + + /* Copy back digest result if it's stored in separated buffer */ + if (pOpData->digestResult && qat_session->authLen > 0) { + if ((crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) != 0) { + char icv[QAT_OCF_MAX_DIGEST] = { 0 }; + crypto_copydata(crp, + crp->crp_digest_start, + qat_session->authLen, + icv); + if (timingsafe_bcmp(icv, + qat_cookie->qat_ocf_digest, + qat_session->authLen) != 0) { + rc = EBADMSG; + goto exit; + } + } else { + crypto_copyback(crp, + crp->crp_digest_start, + qat_session->authLen, + qat_cookie->qat_ocf_digest); + } + } + +exit: + qat_ocf_cookie_free(qat_instance, qat_cookie); + crp->crp_etype = rc; + crypto_done(crp); + + return; +} + +static inline CpaPhysicalAddr +qatVirtToPhys(void *virtAddr) +{ + return (CpaPhysicalAddr)vtophys(virtAddr); +} + +static int +qat_ocf_probesession(device_t dev, const struct crypto_session_params *csp) +{ + if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) != + 0) { + return EINVAL; + } + + switch (csp->csp_mode) { + case CSP_MODE_CIPHER: + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + case CRYPTO_AES_ICM: + if (csp->csp_ivlen != AES_BLOCK_LEN) + return EINVAL; + break; + case CRYPTO_AES_XTS: + if (csp->csp_ivlen != AES_XTS_IV_LEN) + return EINVAL; + break; + default: + return EINVAL; + } + break; + case CSP_MODE_DIGEST: + switch (csp->csp_auth_alg) { + case CRYPTO_SHA1: + case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_256_HMAC: + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_384_HMAC: + case CRYPTO_SHA2_512: + case CRYPTO_SHA2_512_HMAC: + break; + case CRYPTO_AES_NIST_GMAC: + if (csp->csp_ivlen != AES_GCM_IV_LEN) + return EINVAL; + break; + default: + return EINVAL; + } + break; + case CSP_MODE_AEAD: + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_NIST_GCM_16: + if (csp->csp_ivlen != AES_GCM_IV_LEN) + return EINVAL; + break; + default: + return EINVAL; + } + break; + case CSP_MODE_ETA: + switch (csp->csp_auth_alg) { + case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_256_HMAC: + case CRYPTO_SHA2_384_HMAC: + case CRYPTO_SHA2_512_HMAC: + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + case CRYPTO_AES_ICM: + if (csp->csp_ivlen != AES_BLOCK_LEN) + return EINVAL; + break; + case CRYPTO_AES_XTS: + if (csp->csp_ivlen != AES_XTS_IV_LEN) + return EINVAL; + break; + default: + return EINVAL; + } + break; + default: + return EINVAL; + } + break; + default: + return EINVAL; + } + + return CRYPTODEV_PROBE_HARDWARE; +} + +static CpaStatus +qat_ocf_session_init(device_t dev, + struct cryptop *crp, + struct qat_ocf_instance *qat_instance, + struct qat_ocf_session *qat_ssession) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + /* Crytpodev structures */ + crypto_session_t cses; + const struct crypto_session_params *csp; + /* DP API Session configuration */ + CpaCySymSessionSetupData sessionSetupData = { 0 }; + CpaCySymSessionCtx sessionCtx = NULL; + Cpa32U sessionCtxSize = 0; + + cses = crp->crp_session; + if (NULL == cses) { + device_printf(dev, "no crypto session in cryptodev request\n"); + return CPA_STATUS_FAIL; + } + + csp = crypto_get_params(cses); + if (NULL == csp) { + device_printf(dev, "no session in cryptodev session\n"); + return CPA_STATUS_FAIL; + } + + /* Common fields */ + sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; + /* Cipher key */ + if (crp->crp_cipher_key) + sessionSetupData.cipherSetupData.pCipherKey = + crp->crp_cipher_key; + else + sessionSetupData.cipherSetupData.pCipherKey = + csp->csp_cipher_key; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + csp->csp_cipher_klen; + + /* Auth key */ + if (crp->crp_auth_key) + sessionSetupData.hashSetupData.authModeSetupData.authKey = + crp->crp_auth_key; + else + sessionSetupData.hashSetupData.authModeSetupData.authKey = + csp->csp_auth_key; + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + csp->csp_auth_klen; + + qat_ssession->aadLen = crp->crp_aad_length; + if (CPA_TRUE == is_sep_aad_supported(csp)) + sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = + crp->crp_aad_length; + else + sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = + 0; + + /* Just setup algorithm - regardless of mode */ + if (csp->csp_cipher_alg) { + sessionSetupData.symOperation = CPA_CY_SYM_OP_CIPHER; + + switch (csp->csp_cipher_alg) { + case CRYPTO_AES_CBC: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_CBC; + break; + case CRYPTO_AES_ICM: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_CTR; + break; + case CRYPTO_AES_XTS: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_XTS; + break; + case CRYPTO_AES_NIST_GCM_16: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_GCM; + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_AES_GCM; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + default: + device_printf(dev, + "cipher_alg: %d not supported\n", + csp->csp_cipher_alg); + status = CPA_STATUS_UNSUPPORTED; + goto fail; + } + } + + if (csp->csp_auth_alg) { + switch (csp->csp_auth_alg) { + case CRYPTO_SHA1_HMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA1; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + case CRYPTO_SHA1: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA1; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_PLAIN; + break; + + case CRYPTO_SHA2_256_HMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA256; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + case CRYPTO_SHA2_256: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA256; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_PLAIN; + break; + + case CRYPTO_SHA2_224_HMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA224; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + case CRYPTO_SHA2_224: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA224; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_PLAIN; + break; + + case CRYPTO_SHA2_384_HMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA384; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + case CRYPTO_SHA2_384: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA384; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_PLAIN; + break; + + case CRYPTO_SHA2_512_HMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA512; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + break; + case CRYPTO_SHA2_512: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_SHA512; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_PLAIN; + break; + case CRYPTO_AES_NIST_GMAC: + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_AES_GMAC; + break; + default: + status = CPA_STATUS_UNSUPPORTED; + goto fail; + } + } /* csp->csp_auth_alg */ + + /* Setting digest-length if no cipher-only mode is set */ + if (csp->csp_mode != CSP_MODE_CIPHER) { + lac_sym_qat_hash_defs_t *pHashDefsInfo = NULL; + if (csp->csp_auth_mlen) { + sessionSetupData.hashSetupData.digestResultLenInBytes = + csp->csp_auth_mlen; + qat_ssession->authLen = csp->csp_auth_mlen; + } else { + LacSymQat_HashDefsLookupGet( + qat_instance->cyInstHandle, + sessionSetupData.hashSetupData.hashAlgorithm, + &pHashDefsInfo); + if (NULL == pHashDefsInfo) { + device_printf( + dev, + "unable to find corresponding hash data\n"); + status = CPA_STATUS_UNSUPPORTED; + goto fail; + } + sessionSetupData.hashSetupData.digestResultLenInBytes = + pHashDefsInfo->algInfo->digestLength; + qat_ssession->authLen = + pHashDefsInfo->algInfo->digestLength; + } + sessionSetupData.verifyDigest = CPA_FALSE; + } + + switch (csp->csp_mode) { + case CSP_MODE_AEAD: + sessionSetupData.symOperation = + CPA_CY_SYM_OP_ALGORITHM_CHAINING; + /* Place the digest result in a buffer unrelated to srcBuffer */ + sessionSetupData.digestIsAppended = CPA_TRUE; + /* For GCM and CCM driver forces to verify digest on HW */ + sessionSetupData.verifyDigest = CPA_TRUE; + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + } else { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + } + break; + case CSP_MODE_ETA: + sessionSetupData.symOperation = + CPA_CY_SYM_OP_ALGORITHM_CHAINING; + /* Place the digest result in a buffer unrelated to srcBuffer */ + sessionSetupData.digestIsAppended = CPA_FALSE; + /* Due to FW limitation to verify only appended MACs */ + sessionSetupData.verifyDigest = CPA_FALSE; + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + } else { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + } + break; + case CSP_MODE_CIPHER: + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; + } else { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; + } + sessionSetupData.symOperation = CPA_CY_SYM_OP_CIPHER; + break; + case CSP_MODE_DIGEST: + sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; + if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC) { + sessionSetupData.symOperation = + CPA_CY_SYM_OP_ALGORITHM_CHAINING; + /* GMAC is always encrypt */ + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_GCM; + sessionSetupData.hashSetupData.hashAlgorithm = + CPA_CY_SYM_HASH_AES_GMAC; + sessionSetupData.hashSetupData.hashMode = + CPA_CY_SYM_HASH_MODE_AUTH; + /* Same key for cipher and auth */ + sessionSetupData.cipherSetupData.pCipherKey = + csp->csp_auth_key; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + csp->csp_auth_klen; + /* Generated GMAC stored in separated buffer */ + sessionSetupData.digestIsAppended = CPA_FALSE; + /* Digest verification not allowed in GMAC case */ + sessionSetupData.verifyDigest = CPA_FALSE; + /* No AAD allowed */ + sessionSetupData.hashSetupData.authModeSetupData + .aadLenInBytes = 0; + } else { + sessionSetupData.cipherSetupData.cipherDirection = + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; + sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; + sessionSetupData.digestIsAppended = CPA_FALSE; + } + break; + default: + device_printf(dev, + "%s: unhandled crypto algorithm %d, %d\n", + __func__, + csp->csp_cipher_alg, + csp->csp_auth_alg); + status = CPA_STATUS_FAIL; + goto fail; + } + + /* Extracting session size */ + status = cpaCySymSessionCtxGetSize(qat_instance->cyInstHandle, + &sessionSetupData, + &sessionCtxSize); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, "unable to get session size\n"); + goto fail; + } + + /* Allocating contiguous memory for session */ + sessionCtx = contigmalloc(sessionCtxSize, + M_QAT_OCF, + M_NOWAIT, + 0, + ~1UL, + 1 << (bsrl(sessionCtxSize - 1) + 1), + 0); + if (NULL == sessionCtx) { + device_printf(dev, "unable to allocate memory for session\n"); + status = CPA_STATUS_RESOURCE; + goto fail; + } + + status = cpaCySymDpInitSession(qat_instance->cyInstHandle, + &sessionSetupData, + sessionCtx); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, "session initialization failed\n"); + goto fail; + } + + /* NOTE: lets keep double session (both directions) approach to overcome + * lack of direction update in FBSD QAT. + */ + qat_ssession->sessionCtx = sessionCtx; + qat_ssession->sessionCtxSize = sessionCtxSize; + + return CPA_STATUS_SUCCESS; + +fail: + /* Release resources if any */ + if (sessionCtx) + contigfree(sessionCtx, sessionCtxSize, M_QAT_OCF); + + return status; +} + +static int +qat_ocf_newsession(device_t dev, + crypto_session_t cses, + const struct crypto_session_params *csp) +{ + /* Cryptodev QAT structures */ + struct qat_ocf_softc *qat_softc; + struct qat_ocf_dsession *qat_dsession; + struct qat_ocf_instance *qat_instance; + u_int cpu_id = PCPU_GET(cpuid); + + /* Create cryptodev session */ + qat_softc = device_get_softc(dev); + qat_instance = + &qat_softc->cyInstHandles[cpu_id % qat_softc->numCyInstances]; + qat_dsession = crypto_get_driver_session(cses); + if (NULL == qat_dsession) { + device_printf(dev, "Unable to create new session\n"); + return (EINVAL); + } + + /* Add only instance at this point remaining operations moved to + * lazy session init */ + qat_dsession->qatInstance = qat_instance; + + return 0; +} + +static CpaStatus +qat_ocf_remove_session(device_t dev, + CpaInstanceHandle cyInstHandle, + struct qat_ocf_session *qat_session) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + if (NULL == qat_session->sessionCtx) + return CPA_STATUS_SUCCESS; + + /* User callback is executed right before decrementing pending + * callback atomic counter. To avoid removing session rejection + * we have to wait a very short while for counter update + * after call back execution. */ + status = qat_ocf_wait_for_session(qat_session->sessionCtx, + QAT_OCF_SESSION_WAIT_TIMEOUT_MS); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, "waiting for session un-busy failed\n"); + return CPA_STATUS_FAIL; + } + + status = cpaCySymDpRemoveSession(cyInstHandle, qat_session->sessionCtx); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, "error while removing session\n"); + return CPA_STATUS_FAIL; + } + + explicit_bzero(qat_session->sessionCtx, qat_session->sessionCtxSize); + contigfree(qat_session->sessionCtx, + qat_session->sessionCtxSize, + M_QAT_OCF); + qat_session->sessionCtx = NULL; + qat_session->sessionCtxSize = 0; + + return CPA_STATUS_SUCCESS; +} + +static void +qat_ocf_freesession(device_t dev, crypto_session_t cses) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + struct qat_ocf_dsession *qat_dsession = NULL; + struct qat_ocf_instance *qat_instance = NULL; + + qat_dsession = crypto_get_driver_session(cses); + qat_instance = qat_dsession->qatInstance; + mtx_lock(&qat_instance->cyInstMtx); + status = qat_ocf_remove_session(dev, + qat_dsession->qatInstance->cyInstHandle, + &qat_dsession->encSession); + if (CPA_STATUS_SUCCESS != status) + device_printf(dev, "unable to remove encrypt session\n"); + status = qat_ocf_remove_session(dev, + qat_dsession->qatInstance->cyInstHandle, + &qat_dsession->decSession); + if (CPA_STATUS_SUCCESS != status) + device_printf(dev, "unable to remove decrypt session\n"); + mtx_unlock(&qat_instance->cyInstMtx); +} + +/* QAT GCM/CCM FW API are only algorithms which support separated AAD. */ +static CpaStatus +qat_ocf_load_aad_gcm(struct cryptop *crp, struct qat_ocf_cookie *qat_cookie) +{ + CpaCySymDpOpData *pOpData; + + pOpData = &qat_cookie->pOpdata; + + if (NULL != crp->crp_aad) + memcpy(qat_cookie->qat_ocf_gcm_aad, + crp->crp_aad, + crp->crp_aad_length); + else + crypto_copydata(crp, + crp->crp_aad_start, + crp->crp_aad_length, + qat_cookie->qat_ocf_gcm_aad); + + pOpData->pAdditionalAuthData = qat_cookie->qat_ocf_gcm_aad; + pOpData->additionalAuthData = qat_cookie->qat_ocf_gcm_aad_paddr; + + return CPA_STATUS_SUCCESS; +} + +static CpaStatus +qat_ocf_load_aad(struct cryptop *crp, struct qat_ocf_cookie *qat_cookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + const struct crypto_session_params *csp; + CpaCySymDpOpData *pOpData; + struct qat_ocf_load_cb_arg args; + + pOpData = &qat_cookie->pOpdata; + pOpData->pAdditionalAuthData = NULL; + pOpData->additionalAuthData = 0UL; + + if (crp->crp_aad_length == 0) + return CPA_STATUS_SUCCESS; + + if (crp->crp_aad_length > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) + return CPA_STATUS_FAIL; + + csp = crypto_get_params(crp->crp_session); + + /* Handle GCM/CCM case */ + if (CPA_TRUE == is_sep_aad_supported(csp)) + return qat_ocf_load_aad_gcm(crp, qat_cookie); + + if (NULL == crp->crp_aad) { + /* AAD already embedded in source buffer */ + pOpData->messageLenToCipherInBytes = crp->crp_payload_length; + pOpData->cryptoStartSrcOffsetInBytes = crp->crp_payload_start; + + pOpData->messageLenToHashInBytes = + crp->crp_aad_length + crp->crp_payload_length; + pOpData->hashStartSrcOffsetInBytes = crp->crp_aad_start; + + return CPA_STATUS_SUCCESS; + } + + /* Separated AAD not supported by QAT - lets place the content + * of ADD buffer at the very beginning of source SGL */ + args.crp_op = crp; + args.qat_cookie = qat_cookie; + args.pOpData = pOpData; + args.error = 0; + status = bus_dmamap_load(qat_cookie->gcm_aad_dma_mem.dma_tag, + qat_cookie->gcm_aad_dma_mem.dma_map, + crp->crp_aad, + crp->crp_aad_length, + qat_ocf_crypto_load_aadbuf_cb, + &args, + BUS_DMA_NOWAIT); + qat_cookie->is_sep_aad_used = CPA_TRUE; + + /* Right after this step we have AAD placed in the first flat buffer + * in source SGL */ + pOpData->messageLenToCipherInBytes = crp->crp_payload_length; + pOpData->cryptoStartSrcOffsetInBytes = + crp->crp_aad_length + crp->crp_aad_start + crp->crp_payload_start; + + pOpData->messageLenToHashInBytes = + crp->crp_aad_length + crp->crp_payload_length; + pOpData->hashStartSrcOffsetInBytes = crp->crp_aad_start; + + return status; +} + +static CpaStatus +qat_ocf_load(struct cryptop *crp, struct qat_ocf_cookie *qat_cookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaCySymDpOpData *pOpData; + struct qat_ocf_load_cb_arg args; + /* cryptodev internals */ + const struct crypto_session_params *csp; + + pOpData = &qat_cookie->pOpdata; + + csp = crypto_get_params(crp->crp_session); + + /* Load IV buffer if present */ + if (csp->csp_ivlen > 0) { + memset(qat_cookie->qat_ocf_iv_buf, + 0, + sizeof(qat_cookie->qat_ocf_iv_buf)); + crypto_read_iv(crp, qat_cookie->qat_ocf_iv_buf); + pOpData->iv = qat_cookie->qat_ocf_iv_buf_paddr; + pOpData->pIv = qat_cookie->qat_ocf_iv_buf; + pOpData->ivLenInBytes = csp->csp_ivlen; + } + + /* GCM/CCM - load AAD to separated buffer + * AES+SHA - load AAD to first flat in SGL */ + status = qat_ocf_load_aad(crp, qat_cookie); + if (CPA_STATUS_SUCCESS != status) + goto fail; + + /* Load source buffer */ + args.crp_op = crp; + args.qat_cookie = qat_cookie; + args.pOpData = pOpData; + args.error = 0; + status = bus_dmamap_load_crp_buffer(qat_cookie->src_dma_mem.dma_tag, + qat_cookie->src_dma_mem.dma_map, + &crp->crp_buf, + qat_ocf_crypto_load_buf_cb, + &args, + BUS_DMA_NOWAIT); + if (CPA_STATUS_SUCCESS != status) + goto fail; + pOpData->srcBuffer = qat_cookie->src_buffer_list_paddr; + pOpData->srcBufferLen = CPA_DP_BUFLIST; + + /* Load destination buffer */ + if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { + status = + bus_dmamap_load_crp_buffer(qat_cookie->dst_dma_mem.dma_tag, + qat_cookie->dst_dma_mem.dma_map, + &crp->crp_obuf, + qat_ocf_crypto_load_obuf_cb, + &args, + BUS_DMA_NOWAIT); + if (CPA_STATUS_SUCCESS != status) + goto fail; + pOpData->dstBuffer = qat_cookie->dst_buffer_list_paddr; + pOpData->dstBufferLen = CPA_DP_BUFLIST; + } else { + pOpData->dstBuffer = pOpData->srcBuffer; + pOpData->dstBufferLen = pOpData->srcBufferLen; + } + + if (CPA_TRUE == is_use_sep_digest(csp)) + pOpData->digestResult = qat_cookie->qat_ocf_digest_paddr; + else + pOpData->digestResult = 0UL; + + /* GMAC - aka zero length buffer */ + if (CPA_TRUE == is_gmac_exception(csp)) + pOpData->messageLenToCipherInBytes = 0; + +fail: + return status; +} + +static int +qat_ocf_check_input(device_t dev, struct cryptop *crp) +{ + const struct crypto_session_params *csp; + csp = crypto_get_params(crp->crp_session); + + if (crypto_buffer_len(&crp->crp_buf) > QAT_OCF_MAX_LEN) + return E2BIG; + + if (CPA_TRUE == is_sep_aad_supported(csp) && + (crp->crp_aad_length > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX)) + return EBADMSG; + + return 0; +} + +static int +qat_ocf_process(device_t dev, struct cryptop *crp, int hint) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + int rc = 0; + struct qat_ocf_dsession *qat_dsession = NULL; + struct qat_ocf_session *qat_session = NULL; + struct qat_ocf_instance *qat_instance = NULL; + CpaCySymDpOpData *pOpData = NULL; + struct qat_ocf_cookie *qat_cookie = NULL; + CpaBoolean memLoaded = CPA_FALSE; + + rc = qat_ocf_check_input(dev, crp); + if (rc) + goto fail; + + qat_dsession = crypto_get_driver_session(crp->crp_session); + + if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) + qat_session = &qat_dsession->encSession; + else + qat_session = &qat_dsession->decSession; + qat_instance = qat_dsession->qatInstance; + + status = qat_ocf_cookie_alloc(qat_instance, &qat_cookie); + if (CPA_STATUS_SUCCESS != status) { + rc = EAGAIN; + goto fail; + } + + qat_cookie->crp_op = crp; + + /* Common request fields */ + pOpData = &qat_cookie->pOpdata; + pOpData->instanceHandle = qat_instance->cyInstHandle; + pOpData->sessionCtx = NULL; + + /* Cipher fields */ + pOpData->cryptoStartSrcOffsetInBytes = crp->crp_payload_start; + pOpData->messageLenToCipherInBytes = crp->crp_payload_length; + /* Digest fields - any exceptions from this basic rules are covered + * in qat_ocf_load */ + pOpData->hashStartSrcOffsetInBytes = crp->crp_payload_start; + pOpData->messageLenToHashInBytes = crp->crp_payload_length; + + status = qat_ocf_load(crp, qat_cookie); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, + "unable to load OCF buffers to QAT DMA " + "transaction\n"); + rc = EIO; + goto fail; + } + memLoaded = CPA_TRUE; + + status = qat_ocf_cookie_dma_pre_sync(crp, pOpData); + if (CPA_STATUS_SUCCESS != status) { + device_printf(dev, "unable to sync DMA buffers\n"); + rc = EIO; + goto fail; + } + + mtx_lock(&qat_instance->cyInstMtx); + /* Session initialization at the first request. It's done + * in such way to overcome missing QAT specific session data + * such like AAD length and limited possibility to update + * QAT session while handling traffic. + */ + if (NULL == qat_session->sessionCtx) { + status = + qat_ocf_session_init(dev, crp, qat_instance, qat_session); + if (CPA_STATUS_SUCCESS != status) { + mtx_unlock(&qat_instance->cyInstMtx); + device_printf(dev, "unable to init session\n"); + rc = EIO; + goto fail; + } + } else { + status = qat_ocf_handle_session_update(qat_dsession, crp); + if (CPA_STATUS_RESOURCE == status) { + mtx_unlock(&qat_instance->cyInstMtx); + rc = EAGAIN; + goto fail; + } else if (CPA_STATUS_SUCCESS != status) { + mtx_unlock(&qat_instance->cyInstMtx); + rc = EIO; + goto fail; + } + } + pOpData->sessionCtx = qat_session->sessionCtx; + status = cpaCySymDpEnqueueOp(pOpData, CPA_TRUE); + mtx_unlock(&qat_instance->cyInstMtx); + if (CPA_STATUS_SUCCESS != status) { + if (CPA_STATUS_RETRY == status) { + rc = EAGAIN; + goto fail; + } + device_printf(dev, + "unable to send request. Status: %d\n", + status); + rc = EIO; + goto fail; + } + + return 0; +fail: + if (qat_cookie) { + if (memLoaded) + qat_ocf_cookie_dma_unload(crp, pOpData); + qat_ocf_cookie_free(qat_instance, qat_cookie); + } + crp->crp_etype = rc; + crypto_done(crp); + + return 0; +} + +static void +qat_ocf_identify(driver_t *drv, device_t parent) +{ + if (device_find_child(parent, "qat_ocf", -1) == NULL && + BUS_ADD_CHILD(parent, 200, "qat_ocf", -1) == 0) + device_printf(parent, "qat_ocf: could not attach!"); +} + +static int +qat_ocf_probe(device_t dev) +{ + device_set_desc(dev, "QAT engine"); + return (BUS_PROBE_NOWILDCARD); +} + +static CpaStatus +qat_ocf_get_irq_instances(CpaInstanceHandle *cyInstHandles, + Cpa16U cyInstHandlesSize, + Cpa16U *foundInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *baseAddr = NULL; + sal_list_t *listTemp = NULL; + CpaInstanceHandle cyInstHandle; + CpaInstanceInfo2 info; + Cpa16U numDevices; + Cpa32U instCtr = 0; + Cpa32U i; + + /* Get the number of devices */ + status = icp_amgr_getNumInstances(&numDevices); + if (CPA_STATUS_SUCCESS != status) + return status; + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(numDevices * sizeof(icp_accel_dev_t *), M_QAT_OCF, M_WAITOK); + + /* Get ADF to return all accel_devs that support either + * symmetric or asymmetric crypto */ + status = icp_amgr_getAllAccelDevByCapabilities( + (ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC), pAdfInsts, &numDevices); + if (CPA_STATUS_SUCCESS != status) { + free(pAdfInsts, M_QAT_OCF); + return status; + } + + for (i = 0; i < numDevices; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + baseAddr = dev_addr->pSalHandle; + if (NULL == baseAddr) + continue; + listTemp = baseAddr->sym_services; + while (NULL != listTemp) { + cyInstHandle = SalList_getObject(listTemp); + status = cpaCyInstanceGetInfo2(cyInstHandle, &info); + if (CPA_STATUS_SUCCESS != status) + continue; + listTemp = SalList_next(listTemp); + if (CPA_TRUE == info.isPolled) + continue; + if (instCtr >= cyInstHandlesSize) + break; + cyInstHandles[instCtr++] = cyInstHandle; + } + } + free(pAdfInsts, M_QAT_OCF); + *foundInstances = instCtr; + + return CPA_STATUS_SUCCESS; +} + +static CpaStatus +qat_ocf_start_instances(struct qat_ocf_softc *qat_softc, device_t dev) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa16U numInstances = 0; + CpaInstanceHandle cyInstHandles[QAT_OCF_MAX_INSTANCES] = { 0 }; + CpaInstanceHandle cyInstHandle = NULL; + Cpa32U startedInstances = 0; + Cpa32U i; + + qat_softc->numCyInstances = 0; + status = qat_ocf_get_irq_instances(cyInstHandles, + QAT_OCF_MAX_INSTANCES, + &numInstances); + if (CPA_STATUS_SUCCESS != status) + return status; + if (0 == numInstances) + return CPA_STATUS_RESOURCE; + + for (i = 0; i < numInstances; i++) { + struct qat_ocf_instance *qat_ocf_instance; + + cyInstHandle = cyInstHandles[i]; + if (!cyInstHandle) + continue; + + /* Starting instance */ + status = cpaCyStartInstance(cyInstHandle); + if (CPA_STATUS_SUCCESS != status) { + device_printf(qat_softc->sc_dev, + "unable to get start instance\n"); + continue; + } + + status = + cpaCySetAddressTranslation(cyInstHandle, qatVirtToPhys); + if (CPA_STATUS_SUCCESS != status) { + device_printf(qat_softc->sc_dev, + "unable to add virt to phys callback"); + goto fail; + } + + status = cpaCySymDpRegCbFunc(cyInstHandle, symDpCallback); + if (CPA_STATUS_SUCCESS != status) { + device_printf(qat_softc->sc_dev, + "unable to add user callback\n"); + goto fail; + } + + qat_ocf_instance = &qat_softc->cyInstHandles[startedInstances]; + qat_ocf_instance->cyInstHandle = cyInstHandle; + mtx_init(&qat_ocf_instance->cyInstMtx, + "Instance MTX", + NULL, + MTX_DEF); + + /* Initialize cookie pool */ + status = qat_ocf_cookie_pool_init(qat_ocf_instance, dev); + if (CPA_STATUS_SUCCESS != status) { + device_printf(qat_softc->sc_dev, + "unable to create cookie pool\n"); + goto fail; + } + + qat_ocf_instance->driver_id = qat_softc->cryptodev_id; + + startedInstances++; + continue; + fail: + /* Stop instance */ + status = cpaCyStopInstance(cyInstHandle); + if (CPA_STATUS_SUCCESS != status) + device_printf(qat_softc->sc_dev, + "unable to stop the instance\n"); + continue; + } + qat_softc->numCyInstances = startedInstances; + + /* Success if at least one instance has been set */ + if (!qat_softc->numCyInstances) + return CPA_STATUS_FAIL; + + return CPA_STATUS_SUCCESS; +} + +static CpaStatus +qat_ocf_stop_instances(struct qat_ocf_softc *qat_softc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + int i; + + for (i = 0; i < qat_softc->numCyInstances; i++) { + struct qat_ocf_instance *qat_instance; + + qat_instance = &qat_softc->cyInstHandles[i]; + status = cpaCyStopInstance(qat_instance->cyInstHandle); + if (CPA_STATUS_SUCCESS != status) { + pr_err("QAT: stopping instance id: %d failed\n", i); + mtx_unlock(&qat_instance->cyInstMtx); + continue; + } + qat_ocf_cookie_pool_deinit(qat_instance); + mtx_destroy(&qat_instance->cyInstMtx); + } + + return status; +} + +static int +qat_ocf_attach(device_t dev) +{ + int status; + struct qat_ocf_softc *qat_softc; + int32_t cryptodev_id; + + qat_softc = device_get_softc(dev); + qat_softc->sc_dev = dev; + + cryptodev_id = crypto_get_driverid(dev, + sizeof(struct qat_ocf_dsession), + CRYPTOCAP_F_HARDWARE); + if (cryptodev_id < 0) { + device_printf(dev, "cannot initialize!\n"); + goto fail; + } + qat_softc->cryptodev_id = cryptodev_id; + + /* Starting instances for OCF */ + status = qat_ocf_start_instances(qat_softc, dev); + if (status) { + device_printf(dev, "no QAT IRQ instances available\n"); + goto fail; + } + + return 0; +fail: + qat_ocf_detach(dev); + + return (ENXIO); +} + +static int +qat_ocf_detach(device_t dev) +{ + struct qat_ocf_softc *qat_softc = NULL; + CpaStatus cpaStatus; + int status = 0; + + qat_softc = device_get_softc(dev); + + if (qat_softc->cryptodev_id >= 0) { + status = crypto_unregister_all(qat_softc->cryptodev_id); + if (status) + device_printf(dev, + "unable to unregister QAt backend\n"); + } + + /* Stop QAT instances */ + cpaStatus = qat_ocf_stop_instances(qat_softc); + if (CPA_STATUS_SUCCESS != cpaStatus) { + device_printf(dev, "unable to stop instances\n"); + status = EIO; + } + + return status; +} + +static device_method_t qat_ocf_methods[] = + { DEVMETHOD(device_identify, qat_ocf_identify), + DEVMETHOD(device_probe, qat_ocf_probe), + DEVMETHOD(device_attach, qat_ocf_attach), + DEVMETHOD(device_detach, qat_ocf_detach), + + /* Cryptodev interface */ + DEVMETHOD(cryptodev_probesession, qat_ocf_probesession), + DEVMETHOD(cryptodev_newsession, qat_ocf_newsession), + DEVMETHOD(cryptodev_freesession, qat_ocf_freesession), + DEVMETHOD(cryptodev_process, qat_ocf_process), + + DEVMETHOD_END }; + +static driver_t qat_ocf_driver = { + .name = "qat_ocf", + .methods = qat_ocf_methods, + .size = sizeof(struct qat_ocf_softc), +}; + + +DRIVER_MODULE_ORDERED(qat, + nexus, + qat_ocf_driver, + NULL, + NULL, + SI_ORDER_ANY); +MODULE_VERSION(qat, 1); +MODULE_DEPEND(qat, qat_c62x, 1, 1, 1); +MODULE_DEPEND(qat, qat_200xx, 1, 1, 1); +MODULE_DEPEND(qat, qat_c3xxx, 1, 1, 1); +MODULE_DEPEND(qat, qat_c4xxx, 1, 1, 1); +MODULE_DEPEND(qat, qat_dh895xcc, 1, 1, 1); +MODULE_DEPEND(qat, crypto, 1, 1, 1); +MODULE_DEPEND(qat, qat_common, 1, 1, 1); +MODULE_DEPEND(qat, qat_api, 1, 1, 1); +MODULE_DEPEND(qat, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat/qat_ocf_mem_pool.c b/sys/dev/qat/qat/qat_ocf_mem_pool.c new file mode 100644 index 00000000000..5548b57c047 --- /dev/null +++ b/sys/dev/qat/qat/qat_ocf_mem_pool.c @@ -0,0 +1,564 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/* System headers */ +#include +#include +#include +#include +#include +#include +#include + +/* Cryptodev headers */ +#include +#include + +/* QAT specific headers */ +#include "qat_ocf_mem_pool.h" +#include "qat_ocf_utils.h" +#include "cpa.h" + +/* Private functions */ +static void +qat_ocf_alloc_single_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + struct qat_ocf_dma_mem *dma_mem; + + if (error != 0) + return; + + dma_mem = arg; + dma_mem->dma_seg = segs[0]; +} + +static int +qat_ocf_populate_buf_list_cb(struct qat_ocf_buffer_list *buffers, + bus_dma_segment_t *segs, + int niseg, + int skip_seg, + int skip_bytes) +{ + CpaPhysFlatBuffer *flatBuffer; + bus_addr_t segment_addr; + bus_size_t segment_len; + int iseg, oseg; + + for (iseg = 0, oseg = skip_seg; + iseg < niseg && oseg < QAT_OCF_MAX_FLATS; + iseg++) { + segment_addr = segs[iseg].ds_addr; + segment_len = segs[iseg].ds_len; + + if (skip_bytes > 0) { + if (skip_bytes < segment_len) { + segment_addr += skip_bytes; + segment_len -= skip_bytes; + skip_bytes = 0; + } else { + skip_bytes -= segment_len; + continue; + } + } + flatBuffer = &buffers->flatBuffers[oseg++]; + flatBuffer->dataLenInBytes = (Cpa32U)segment_len; + flatBuffer->bufferPhysAddr = (CpaPhysicalAddr)segment_addr; + }; + buffers->numBuffers = oseg; + + return iseg < niseg ? E2BIG : 0; +} + +void +qat_ocf_crypto_load_aadbuf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error) +{ + struct qat_ocf_load_cb_arg *arg; + struct qat_ocf_cookie *qat_cookie; + + arg = _arg; + if (error != 0) { + arg->error = error; + return; + } + + qat_cookie = arg->qat_cookie; + arg->error = qat_ocf_populate_buf_list_cb( + &qat_cookie->src_buffers, segs, nseg, 0, 0); +} + +void +qat_ocf_crypto_load_buf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error) +{ + struct qat_ocf_cookie *qat_cookie; + struct qat_ocf_load_cb_arg *arg; + int start_segment = 0, skip_bytes = 0; + + arg = _arg; + if (error != 0) { + arg->error = error; + return; + } + + qat_cookie = arg->qat_cookie; + + skip_bytes = 0; + start_segment = qat_cookie->src_buffers.numBuffers; + + arg->error = qat_ocf_populate_buf_list_cb( + &qat_cookie->src_buffers, segs, nseg, start_segment, skip_bytes); +} + +void +qat_ocf_crypto_load_obuf_cb(void *_arg, + bus_dma_segment_t *segs, + int nseg, + int error) +{ + struct qat_ocf_load_cb_arg *arg; + struct cryptop *crp; + struct qat_ocf_cookie *qat_cookie; + const struct crypto_session_params *csp; + int osegs = 0, to_copy = 0; + + arg = _arg; + if (error != 0) { + arg->error = error; + return; + } + + crp = arg->crp_op; + qat_cookie = arg->qat_cookie; + csp = crypto_get_params(crp->crp_session); + + /* + * The payload must start at the same offset in the output SG list as in + * the input SG list. Copy over SG entries from the input corresponding + * to the AAD buffer. + */ + if (crp->crp_aad_length == 0 || + (CPA_TRUE == is_sep_aad_supported(csp) && crp->crp_aad)) { + arg->error = + qat_ocf_populate_buf_list_cb(&qat_cookie->dst_buffers, + segs, + nseg, + 0, + crp->crp_payload_output_start); + return; + } + + /* Copy AAD from source SGL to keep payload in the same position in + * destination buffers */ + if (NULL == crp->crp_aad) + to_copy = crp->crp_payload_start - crp->crp_aad_start; + else + to_copy = crp->crp_aad_length; + + for (; osegs < qat_cookie->src_buffers.numBuffers; osegs++) { + CpaPhysFlatBuffer *src_flat; + CpaPhysFlatBuffer *dst_flat; + int data_len; + + if (to_copy <= 0) + break; + + src_flat = &qat_cookie->src_buffers.flatBuffers[osegs]; + dst_flat = &qat_cookie->dst_buffers.flatBuffers[osegs]; + + dst_flat->bufferPhysAddr = src_flat->bufferPhysAddr; + data_len = imin(src_flat->dataLenInBytes, to_copy); + dst_flat->dataLenInBytes = data_len; + to_copy -= data_len; + } + + arg->error = + qat_ocf_populate_buf_list_cb(&qat_cookie->dst_buffers, + segs, + nseg, + osegs, + crp->crp_payload_output_start); +} + +static int +qat_ocf_alloc_dma_mem(device_t dev, + struct qat_ocf_dma_mem *dma_mem, + int nseg, + bus_size_t size, + bus_size_t alignment) +{ + int error; + + error = bus_dma_tag_create(bus_get_dma_tag(dev), + alignment, + 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, + NULL, /* filter, filterarg */ + size, /* maxsize */ + nseg, /* nsegments */ + size, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + NULL, + NULL, /* lockfunc, lockarg */ + &dma_mem->dma_tag); + if (error != 0) { + device_printf(dev, + "couldn't create DMA tag, error = %d\n", + error); + return error; + } + + error = + bus_dmamem_alloc(dma_mem->dma_tag, + &dma_mem->dma_vaddr, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &dma_mem->dma_map); + if (error != 0) { + device_printf(dev, + "couldn't allocate dmamem, error = %d\n", + error); + goto fail_0; + } + + error = bus_dmamap_load(dma_mem->dma_tag, + dma_mem->dma_map, + dma_mem->dma_vaddr, + size, + qat_ocf_alloc_single_cb, + dma_mem, + BUS_DMA_NOWAIT); + if (error) { + device_printf(dev, + "couldn't load dmamem map, error = %d\n", + error); + goto fail_1; + } + + return 0; +fail_1: + bus_dmamem_free(dma_mem->dma_tag, dma_mem->dma_vaddr, dma_mem->dma_map); +fail_0: + bus_dma_tag_destroy(dma_mem->dma_tag); + + return error; +} + +static void +qat_ocf_free_dma_mem(struct qat_ocf_dma_mem *qdm) +{ + if (qdm->dma_tag != NULL && qdm->dma_vaddr != NULL) { + bus_dmamap_unload(qdm->dma_tag, qdm->dma_map); + bus_dmamem_free(qdm->dma_tag, qdm->dma_vaddr, qdm->dma_map); + bus_dma_tag_destroy(qdm->dma_tag); + explicit_bzero(qdm, sizeof(*qdm)); + } +} + +static int +qat_ocf_dma_tag_and_map(device_t dev, + struct qat_ocf_dma_mem *dma_mem, + bus_size_t size, + bus_size_t segs) +{ + int error; + + error = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, + NULL, /* filter, filterarg */ + size, /* maxsize */ + segs, /* nsegments */ + size, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + NULL, + NULL, /* lockfunc, lockarg */ + &dma_mem->dma_tag); + if (error != 0) + return error; + + error = bus_dmamap_create(dma_mem->dma_tag, + BUS_DMA_COHERENT, + &dma_mem->dma_map); + if (error != 0) + return error; + + return 0; +} + +static void +qat_ocf_clear_cookie(struct qat_ocf_cookie *qat_cookie) +{ + qat_cookie->src_buffers.numBuffers = 0; + qat_cookie->dst_buffers.numBuffers = 0; + qat_cookie->is_sep_aad_used = CPA_FALSE; + explicit_bzero(qat_cookie->qat_ocf_iv_buf, + sizeof(qat_cookie->qat_ocf_iv_buf)); + explicit_bzero(qat_cookie->qat_ocf_digest, + sizeof(qat_cookie->qat_ocf_digest)); + explicit_bzero(qat_cookie->qat_ocf_gcm_aad, + sizeof(qat_cookie->qat_ocf_gcm_aad)); + qat_cookie->crp_op = NULL; +} + +/* Public functions */ +CpaStatus +qat_ocf_cookie_dma_pre_sync(struct cryptop *crp, CpaCySymDpOpData *pOpData) +{ + struct qat_ocf_cookie *qat_cookie; + + if (NULL == pOpData->pCallbackTag) + return CPA_STATUS_FAIL; + + qat_cookie = (struct qat_ocf_cookie *)pOpData->pCallbackTag; + + if (CPA_TRUE == qat_cookie->is_sep_aad_used) { + bus_dmamap_sync(qat_cookie->gcm_aad_dma_mem.dma_tag, + qat_cookie->gcm_aad_dma_mem.dma_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + } + + bus_dmamap_sync(qat_cookie->src_dma_mem.dma_tag, + qat_cookie->src_dma_mem.dma_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { + bus_dmamap_sync(qat_cookie->dst_dma_mem.dma_tag, + qat_cookie->dst_dma_mem.dma_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + } + bus_dmamap_sync(qat_cookie->dma_tag, + qat_cookie->dma_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qat_ocf_cookie_dma_post_sync(struct cryptop *crp, CpaCySymDpOpData *pOpData) +{ + struct qat_ocf_cookie *qat_cookie; + + if (NULL == pOpData->pCallbackTag) + return CPA_STATUS_FAIL; + + qat_cookie = (struct qat_ocf_cookie *)pOpData->pCallbackTag; + + bus_dmamap_sync(qat_cookie->src_dma_mem.dma_tag, + qat_cookie->src_dma_mem.dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) { + bus_dmamap_sync(qat_cookie->dst_dma_mem.dma_tag, + qat_cookie->dst_dma_mem.dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + } + bus_dmamap_sync(qat_cookie->dma_tag, + qat_cookie->dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + if (qat_cookie->is_sep_aad_used) + bus_dmamap_sync(qat_cookie->gcm_aad_dma_mem.dma_tag, + qat_cookie->gcm_aad_dma_mem.dma_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qat_ocf_cookie_dma_unload(struct cryptop *crp, CpaCySymDpOpData *pOpData) +{ + struct qat_ocf_cookie *qat_cookie; + + qat_cookie = pOpData->pCallbackTag; + + if (NULL == qat_cookie) + return CPA_STATUS_FAIL; + + bus_dmamap_unload(qat_cookie->src_dma_mem.dma_tag, + qat_cookie->src_dma_mem.dma_map); + if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) + bus_dmamap_unload(qat_cookie->dst_dma_mem.dma_tag, + qat_cookie->dst_dma_mem.dma_map); + if (qat_cookie->is_sep_aad_used) + bus_dmamap_unload(qat_cookie->gcm_aad_dma_mem.dma_tag, + qat_cookie->gcm_aad_dma_mem.dma_map); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qat_ocf_cookie_pool_init(struct qat_ocf_instance *instance, device_t dev) +{ + int i, error = 0; + + mtx_init(&instance->cookie_pool_mtx, + "QAT cookie pool MTX", + NULL, + MTX_DEF); + instance->free_cookie_ptr = 0; + for (i = 0; i < QAT_OCF_MEM_POOL_SIZE; i++) { + struct qat_ocf_cookie *qat_cookie; + struct qat_ocf_dma_mem *entry_dma_mem; + + entry_dma_mem = &instance->cookie_dmamem[i]; + + /* Allocate DMA segment for cache entry. + * Cache has to be stored in DMAable mem due to + * it contains i.a src and dst flat buffer + * lists. + */ + error = qat_ocf_alloc_dma_mem(dev, + entry_dma_mem, + 1, + sizeof(struct qat_ocf_cookie), + (1 << 6)); + if (error) + break; + + qat_cookie = entry_dma_mem->dma_vaddr; + instance->cookie_pool[i] = qat_cookie; + + qat_cookie->dma_map = entry_dma_mem->dma_map; + qat_cookie->dma_tag = entry_dma_mem->dma_tag; + + qat_ocf_clear_cookie(qat_cookie); + + /* Physical address of IV buffer */ + qat_cookie->qat_ocf_iv_buf_paddr = + entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, qat_ocf_iv_buf); + + /* Physical address of digest buffer */ + qat_cookie->qat_ocf_digest_paddr = + entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, qat_ocf_digest); + + /* Physical address of AAD buffer */ + qat_cookie->qat_ocf_gcm_aad_paddr = + entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, qat_ocf_gcm_aad); + + /* We already got physical address of src and dest SGL header */ + qat_cookie->src_buffer_list_paddr = + entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, src_buffers); + + qat_cookie->dst_buffer_list_paddr = + entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, dst_buffers); + + /* We already have physical address of pOpdata */ + qat_cookie->pOpData_paddr = entry_dma_mem->dma_seg.ds_addr + + offsetof(struct qat_ocf_cookie, pOpdata); + /* Init QAT DP API OP data with const values */ + qat_cookie->pOpdata.pCallbackTag = (void *)qat_cookie; + qat_cookie->pOpdata.thisPhys = + (CpaPhysicalAddr)qat_cookie->pOpData_paddr; + + error = qat_ocf_dma_tag_and_map(dev, + &qat_cookie->src_dma_mem, + QAT_OCF_MAXLEN, + QAT_OCF_MAX_FLATS); + if (error) + break; + + error = qat_ocf_dma_tag_and_map(dev, + &qat_cookie->dst_dma_mem, + QAT_OCF_MAXLEN, + QAT_OCF_MAX_FLATS); + if (error) + break; + + /* Max one flat buffer for embedded AAD if provided as separated + * by OCF and it's not supported by QAT */ + error = qat_ocf_dma_tag_and_map(dev, + &qat_cookie->gcm_aad_dma_mem, + QAT_OCF_MAXLEN, + 1); + if (error) + break; + + instance->free_cookie[i] = qat_cookie; + instance->free_cookie_ptr++; + } + + return error; +} + +CpaStatus +qat_ocf_cookie_alloc(struct qat_ocf_instance *qat_instance, + struct qat_ocf_cookie **cookie_out) +{ + mtx_lock(&qat_instance->cookie_pool_mtx); + if (qat_instance->free_cookie_ptr == 0) { + mtx_unlock(&qat_instance->cookie_pool_mtx); + return CPA_STATUS_FAIL; + } + *cookie_out = + qat_instance->free_cookie[--qat_instance->free_cookie_ptr]; + mtx_unlock(&qat_instance->cookie_pool_mtx); + + return CPA_STATUS_SUCCESS; +} + +void +qat_ocf_cookie_free(struct qat_ocf_instance *qat_instance, + struct qat_ocf_cookie *cookie) +{ + qat_ocf_clear_cookie(cookie); + mtx_lock(&qat_instance->cookie_pool_mtx); + qat_instance->free_cookie[qat_instance->free_cookie_ptr++] = cookie; + mtx_unlock(&qat_instance->cookie_pool_mtx); +} + +void +qat_ocf_cookie_pool_deinit(struct qat_ocf_instance *qat_instance) +{ + int i; + + for (i = 0; i < QAT_OCF_MEM_POOL_SIZE; i++) { + struct qat_ocf_cookie *cookie; + struct qat_ocf_dma_mem *cookie_dma; + + cookie = qat_instance->cookie_pool[i]; + if (NULL == cookie) + continue; + + /* Destroy tag and map for source SGL */ + if (cookie->src_dma_mem.dma_tag) { + bus_dmamap_destroy(cookie->src_dma_mem.dma_tag, + cookie->src_dma_mem.dma_map); + bus_dma_tag_destroy(cookie->src_dma_mem.dma_tag); + } + + /* Destroy tag and map for dest SGL */ + if (cookie->dst_dma_mem.dma_tag) { + bus_dmamap_destroy(cookie->dst_dma_mem.dma_tag, + cookie->dst_dma_mem.dma_map); + bus_dma_tag_destroy(cookie->dst_dma_mem.dma_tag); + } + + /* Destroy tag and map for separated AAD */ + if (cookie->gcm_aad_dma_mem.dma_tag) { + bus_dmamap_destroy(cookie->gcm_aad_dma_mem.dma_tag, + cookie->gcm_aad_dma_mem.dma_map); + bus_dma_tag_destroy(cookie->gcm_aad_dma_mem.dma_tag); + } + + /* Free DMA memory */ + cookie_dma = &qat_instance->cookie_dmamem[i]; + qat_ocf_free_dma_mem(cookie_dma); + qat_instance->cookie_pool[i] = NULL; + } + mtx_destroy(&qat_instance->cookie_pool_mtx); + + return; +} diff --git a/sys/dev/qat/qat/qat_ocf_utils.c b/sys/dev/qat/qat/qat_ocf_utils.c new file mode 100644 index 00000000000..64a10128b98 --- /dev/null +++ b/sys/dev/qat/qat/qat_ocf_utils.c @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/* System headers */ +#include +#include +#include +#include +#include +#include + +/* QAT specific headers */ +#include "qat_ocf_utils.h" +#include "cpa.h" +#include "lac_common.h" +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_sym.h" +#include "lac_sym_qat.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_session.h" +#include "lac_sym_cipher.h" +#include "lac_sym_hash.h" +#include "lac_sym_alg_chain.h" +#include "lac_sym_stats.h" +#include "lac_sym_partial.h" +#include "lac_sym_qat_hash_defs_lookup.h" + +#define QAT_OCF_AAD_NOCHANGE (-1) + +CpaStatus +qat_ocf_wait_for_session(CpaCySymSessionCtx sessionCtx, Cpa32U timeoutMS) +{ + CpaBoolean sessionInUse = CPA_TRUE; + CpaStatus status; + struct timespec start_ts; + struct timespec current_ts; + struct timespec delta; + u64 delta_ms; + + nanotime(&start_ts); + for (;;) { + status = cpaCySymSessionInUse(sessionCtx, &sessionInUse); + if (CPA_STATUS_SUCCESS != status) + return CPA_STATUS_FAIL; + if (CPA_FALSE == sessionInUse) + break; + nanotime(¤t_ts); + delta = timespec_sub(current_ts, start_ts); + delta_ms = (delta.tv_sec * 1000) + + (delta.tv_nsec / NSEC_PER_MSEC); + if (delta_ms > (timeoutMS)) + return CPA_STATUS_RESOURCE; + qatUtilsYield(); + } + + return CPA_STATUS_SUCCESS; +} + +static CpaStatus +qat_ocf_session_update(struct qat_ocf_session *ocf_session, + Cpa8U *newCipher, + Cpa8U *newAuth, + Cpa32U newAADLength) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean sessionInUse = CPA_TRUE; + + if (!ocf_session->sessionCtx) + return CPA_STATUS_SUCCESS; + + status = cpaCySymSessionInUse(ocf_session->sessionCtx, &sessionInUse); + if (CPA_TRUE == sessionInUse) + return CPA_STATUS_RESOURCE; + + pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(ocf_session->sessionCtx); + + if (newAADLength != QAT_OCF_AAD_NOCHANGE) { + ocf_session->aadLen = newAADLength; + status = + LacAlgChain_SessionAADUpdate(pSessionDesc, newAADLength); + if (CPA_STATUS_SUCCESS != status) + return status; + } + + if (newCipher) { + status = + LacAlgChain_SessionCipherKeyUpdate(pSessionDesc, newCipher); + if (CPA_STATUS_SUCCESS != status) + return status; + } + + if (newAuth) { + status = + LacAlgChain_SessionAuthKeyUpdate(pSessionDesc, newAuth); + if (CPA_STATUS_SUCCESS != status) + return status; + } + + return status; +} + +CpaStatus +qat_ocf_handle_session_update(struct qat_ocf_dsession *ocf_dsession, + struct cryptop *crp) +{ + Cpa32U newAADLength = QAT_OCF_AAD_NOCHANGE; + Cpa8U *cipherKey; + Cpa8U *authKey; + crypto_session_t cses; + const struct crypto_session_params *csp; + CpaStatus status = CPA_STATUS_SUCCESS; + + if (!ocf_dsession) + return CPA_STATUS_FAIL; + + cses = crp->crp_session; + if (!cses) + return CPA_STATUS_FAIL; + csp = crypto_get_params(cses); + if (!csp) + return CPA_STATUS_FAIL; + + cipherKey = crp->crp_cipher_key; + authKey = crp->crp_auth_key; + + if (is_sep_aad_supported(csp)) { + /* Determine if AAD has change */ + if ((ocf_dsession->encSession.sessionCtx && + ocf_dsession->encSession.aadLen != crp->crp_aad_length) || + (ocf_dsession->decSession.sessionCtx && + ocf_dsession->decSession.aadLen != crp->crp_aad_length)) { + newAADLength = crp->crp_aad_length; + + /* Get auth and cipher keys from session if not present + * in the request. Update keys is required to update + * AAD. + */ + if (!authKey) + authKey = csp->csp_auth_key; + if (!cipherKey) + cipherKey = csp->csp_cipher_key; + } + if (!authKey) + authKey = cipherKey; + } + + if (crp->crp_cipher_key || crp->crp_auth_key || + newAADLength != QAT_OCF_AAD_NOCHANGE) { + /* Update encryption session */ + status = qat_ocf_session_update(&ocf_dsession->encSession, + cipherKey, + authKey, + newAADLength); + if (CPA_STATUS_SUCCESS != status) + return status; + /* Update decryption session */ + status = qat_ocf_session_update(&ocf_dsession->decSession, + cipherKey, + authKey, + newAADLength); + if (CPA_STATUS_SUCCESS != status) + return status; + } + + return status; +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_buffers.c b/sys/dev/qat/qat_api/common/compression/dc_buffers.c new file mode 100644 index 00000000000..1a5d9bc8973 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_buffers.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_buffers.c + * + * @defgroup Dc_DataCompression DC Data Compression + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the buffer management operations for + * Data Compression service. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_bp.h" + +#include "sal_types_compression.h" +#include "icp_qat_fw_comp.h" + +#define CPA_DC_CEIL_DIV(x, y) (((x) + (y)-1) / (y)) +#define DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 (55) + +CpaStatus +cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes) +{ + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + LAC_CHECK_NULL_PARAM(pSizeInBytes); + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + if (0 == numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + *pSizeInBytes = (sizeof(icp_buffer_list_desc_t) + + (sizeof(icp_flat_buffer_desc_t) * (numBuffers + 1)) + + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcBnpBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numJobs, + Cpa32U *pSizeInBytes) +{ + return CPA_STATUS_UNSUPPORTED; +} + +static inline CpaStatus +dcDeflateBoundGen2(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize) +{ + /* Formula for GEN2 deflate: + * ceil(9 * Total input bytes / 8) + 55 bytes. + * 55 bytes is the skid pad value for GEN2 devices. + */ + *outputSize = + CPA_DC_CEIL_DIV(9 * inputSize, 8) + DC_DEST_BUFF_EXTRA_DEFLATE_GEN2; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDeflateCompressBound(const CpaInstanceHandle dcInstance, + CpaDcHuffType huffType, + Cpa32U inputSize, + Cpa32U *outputSize) +{ + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + LAC_CHECK_NULL_PARAM(outputSize); + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + if (!inputSize) { + QAT_UTILS_LOG( + "The input size needs to be greater than zero.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_DC_HT_STATIC != huffType) && + (CPA_DC_HT_FULL_DYNAMIC != huffType)) { + QAT_UTILS_LOG("Invalid huffType value.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + return dcDeflateBoundGen2(huffType, inputSize, outputSize); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_datapath.c b/sys/dev/qat/qat_api/common/compression/dc_datapath.c new file mode 100644 index 00000000000..0e2aa9f389e --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_datapath.c @@ -0,0 +1,1790 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_datapath.c + * + * @defgroup Dc_DataCompression DC Data Compression + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression datapath operations. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_dp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_session.h" +#include "dc_datapath.h" +#include "sal_statistics.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "dc_stats.h" +#include "lac_buffer_desc.h" +#include "lac_sal.h" +#include "lac_log.h" +#include "lac_sync.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" +#include "dc_error_counter.h" +#define DC_COMP_MAX_BUFF_SIZE (1024 * 64) + +static QatUtilsAtomic dcErrorCount[MAX_DC_ERROR_TYPE]; + +void +dcErrorLog(CpaDcReqStatus dcError) +{ + Cpa32U absError = 0; + + absError = abs(dcError); + if ((dcError < CPA_DC_OK) && (absError < MAX_DC_ERROR_TYPE)) { + qatUtilsAtomicInc(&(dcErrorCount[absError])); + } +} + +Cpa64U +getDcErrorCounter(CpaDcReqStatus dcError) +{ + Cpa32U absError = 0; + + absError = abs(dcError); + if (!(dcError >= CPA_DC_OK || dcError < CPA_DC_EMPTY_DYM_BLK)) { + return (Cpa64U)qatUtilsAtomicGet(&dcErrorCount[absError]); + } + + return 0; +} + +void +dcCompression_ProcessCallback(void *pRespMsg) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_qat_fw_comp_resp_t *pCompRespMsg = NULL; + void *callbackTag = NULL; + Cpa64U *pReqData = NULL; + CpaDcDpOpData *pResponse = NULL; + CpaDcRqResults *pResults = NULL; + CpaDcCallbackFn pCbFunc = NULL; + dc_session_desc_t *pSessionDesc = NULL; + sal_compression_service_t *pService = NULL; + dc_compression_cookie_t *pCookie = NULL; + CpaDcOpData *pOpData = NULL; + CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE; + CpaBoolean verifyHwIntegrityCrcs = CPA_FALSE; + Cpa8U cmpErr = ERR_CODE_NO_ERROR, xlatErr = ERR_CODE_NO_ERROR; + dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST; + Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; + Cpa8U hdrFlags = 0; + + /* Cast response message to compression response message type */ + pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg; + + /* Extract request data pointer from the opaque data */ + LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData); + + /* Extract fields from the request data structure */ + pCookie = (dc_compression_cookie_t *)pReqData; + if (!pCookie) + return; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + pResponse = (CpaDcDpOpData *)pReqData; + pResults = &(pResponse->results); + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + compDecomp = DC_DECOMPRESSION_REQUEST; + } + } else { + pSessionDesc = pCookie->pSessionDesc; + pResults = pCookie->pResults; + callbackTag = pCookie->callbackTag; + pCbFunc = pCookie->pSessionDesc->pCompressionCb; + compDecomp = pCookie->compDecomp; + pOpData = pCookie->pDcOpData; + } + + pService = (sal_compression_service_t *)(pCookie->dcInstance); + + opStatus = pCompRespMsg->comn_resp.comn_status; + + if (NULL != pOpData) { + verifyHwIntegrityCrcs = pOpData->verifyHwIntegrityCrcs; + } + + hdrFlags = pCompRespMsg->comn_resp.hdr_flags; + + /* Get the cmp error code */ + cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code; + if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) { + /* Compression not supported by firmware, set produced/consumed + to zero + and call the cb function with status CPA_STATUS_UNSUPPORTED + */ + QAT_UTILS_LOG("Compression feature not supported\n"); + status = CPA_STATUS_UNSUPPORTED; + pResults->status = (Cpa8S)cmpErr; + pResults->consumed = 0; + pResults->produced = 0; + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = + CPA_STATUS_UNSUPPORTED; + (pService->pDcDpCb)(pResponse); + } else { + /* Free the memory pool */ + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + if (NULL != pCbFunc) { + pCbFunc(callbackTag, status); + } + } + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompletedErrors, pService); + } else { + COMPRESSION_STAT_INC(numDecompCompletedErrors, + pService); + } + return; + } else { + /* Check compression response status */ + cmpPass = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus)); + } + + if (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) { + cmpPass = CPA_TRUE; + cmpErr = ERR_CODE_NO_ERROR; + } + /* log the slice hang and endpoint push/pull error inside the response + */ + if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) { + QAT_UTILS_LOG( + "Slice hang detected on the compression slice.\n"); + } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) { + QAT_UTILS_LOG( + "PCIe End Point Push/Pull or TI/RI Parity error detected.\n"); + } + + /* We return the compression error code for now. We would need to update + * the API if we decide to return both error codes */ + pResults->status = (Cpa8S)cmpErr; + + /* Check the translator status */ + if ((DC_COMPRESSION_REQUEST == compDecomp) && + (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { + /* Check translator response status */ + xlatPass = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus)); + + /* Get the translator error code */ + xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code; + + /* Return a fatal error or a potential error in the translator + * slice + * if the compression slice did not return any error */ + if ((CPA_DC_OK == pResults->status) || + (CPA_DC_FATALERR == (Cpa8S)xlatErr)) { + pResults->status = (Cpa8S)xlatErr; + } + } + /* Update dc error counter */ + dcErrorLog(pResults->status); + + if (CPA_FALSE == pSessionDesc->isDcDp) { + /* In case of any error for an end of packet request, we need to + * update + * the request type for the following request */ + if (CPA_DC_FLUSH_FINAL == pCookie->flushFlag && cmpPass && + xlatPass) { + pSessionDesc->requestType = DC_REQUEST_FIRST; + } else { + pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; + } + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) || + ((CPA_DC_STATELESS == pSessionDesc->sessState) && + (DC_COMPRESSION_REQUEST == compDecomp))) { + /* Overflow is a valid use case for Traditional API + * only. + * Stateful Overflow is supported in both compression + * and + * decompression direction. + * Stateless Overflow is supported only in compression + * direction. + */ + if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) + cmpPass = CPA_TRUE; + + if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { + xlatPass = CPA_TRUE; + } + } + } else { + if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) { + cmpPass = CPA_FALSE; + } + if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { + xlatPass = CPA_FALSE; + } + } + + if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { + /* Extract the response from the firmware */ + pResults->consumed = + pCompRespMsg->comp_resp_pars.input_byte_counter; + pResults->produced = + pCompRespMsg->comp_resp_pars.output_byte_counter; + pSessionDesc->cumulativeConsumedBytes += pResults->consumed; + + if (CPA_DC_OVERFLOW != (Cpa8S)xlatErr) { + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + pResults->checksum = + pCompRespMsg->comp_resp_pars.crc.legacy + .curr_crc32; + } else if (CPA_DC_ADLER32 == + pSessionDesc->checksumType) { + pResults->checksum = + pCompRespMsg->comp_resp_pars.crc.legacy + .curr_adler_32; + } + pSessionDesc->previousChecksum = pResults->checksum; + } + + if (DC_DECOMPRESSION_REQUEST == compDecomp) { + pResults->endOfLastBlock = + (ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET == + ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET( + opStatus)); + } + + /* Save the checksum for the next request */ + if ((CPA_DC_OVERFLOW != (Cpa8S)xlatErr) && + (CPA_TRUE == verifyHwIntegrityCrcs)) { + pSessionDesc->previousChecksum = + pSessionDesc->seedSwCrc.swCrcI; + } + + /* Check if a CNV recovery happened and + * increase stats counter + */ + if ((DC_COMPRESSION_REQUEST == compDecomp) && + ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) && + ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) { + COMPRESSION_STAT_INC(numCompCnvErrorsRecovered, + pService); + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = CPA_STATUS_SUCCESS; + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompleted, + pService); + } else { + COMPRESSION_STAT_INC(numDecompCompleted, + pService); + } + } + } else { + pResults->consumed = 0; + pResults->produced = 0; + if (CPA_DC_OVERFLOW == pResults->status && + CPA_DC_STATELESS == pSessionDesc->sessState) { + /* This error message will be returned by Data Plane API + * in both + * compression and decompression direction. With + * Traditional API + * this error message will be returned only in stateless + * decompression direction */ + QAT_UTILS_LOG( + "Unrecoverable error: stateless overflow. You may need to increase the size of your destination buffer.\n"); + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = CPA_STATUS_FAIL; + } else { + if (CPA_DC_OK != pResults->status && + CPA_DC_INCOMPLETE_FILE_ERR != pResults->status) { + status = CPA_STATUS_FAIL; + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompletedErrors, + pService); + } else { + COMPRESSION_STAT_INC(numDecompCompletedErrors, + pService); + } + } + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + /* Decrement number of stateless pending callbacks for session + */ + pSessionDesc->pendingDpStatelessCbCount--; + (pService->pDcDpCb)(pResponse); + } else { + /* Decrement number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicDec( + &(pCookie->pSessionDesc->pendingStatelessCbCount)); + } else if (0 != + qatUtilsAtomicGet(&pCookie->pSessionDesc + ->pendingStatefulCbCount)) { + qatUtilsAtomicDec( + &(pCookie->pSessionDesc->pendingStatefulCbCount)); + } + + /* Free the memory pool */ + if (NULL != pCookie) { + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + } + + if (NULL != pCbFunc) { + pCbFunc(callbackTag, status); + } + } +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check that all the parameters in the pOpData structure are valid + * + * @description + * Check that all the parameters in the pOpData structure are valid + * + * @param[in] pService Pointer to the compression service + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 and + * CpaDcDecompressData2 + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData) +{ + CpaDcSkipMode skipMode = 0; + + if ((pOpData->flushFlag < CPA_DC_FLUSH_NONE) || + (pOpData->flushFlag > CPA_DC_FLUSH_FULL)) { + LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); + return CPA_STATUS_INVALID_PARAM; + } + + skipMode = pOpData->inputSkipData.skipMode; + if ((skipMode < CPA_DC_SKIP_DISABLED) || + (skipMode > CPA_DC_SKIP_STRIDE)) { + LAC_INVALID_PARAM_LOG("Invalid input skip mode value"); + return CPA_STATUS_INVALID_PARAM; + } + + skipMode = pOpData->outputSkipData.skipMode; + if ((skipMode < CPA_DC_SKIP_DISABLED) || + (skipMode > CPA_DC_SKIP_STRIDE)) { + LAC_INVALID_PARAM_LOG("Invalid output skip mode value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->integrityCrcCheck == CPA_FALSE && + pOpData->verifyHwIntegrityCrcs == CPA_TRUE) { + LAC_INVALID_PARAM_LOG( + "integrityCrcCheck must be set to true" + "in order to enable verifyHwIntegrityCrcs"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->integrityCrcCheck != CPA_TRUE && + pOpData->integrityCrcCheck != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid integrityCrcCheck value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->verifyHwIntegrityCrcs != CPA_TRUE && + pOpData->verifyHwIntegrityCrcs != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid verifyHwIntegrityCrcs value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->compressAndVerify != CPA_TRUE && + pOpData->compressAndVerify != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid cnv decompress check value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_TRUE == pOpData->integrityCrcCheck && + CPA_FALSE == pService->generic_service_info.integrityCrcCheck) { + LAC_INVALID_PARAM_LOG("Integrity CRC check is not " + "supported on this device"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check the compression source buffer for Batch and Pack API. + * + * @description + * Check that all the parameters used for Pack compression + * request are valid. This function essentially checks the source buffer + * parameters and results structure parameters. + * + * @param[in] pSessionHandle Session handle + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space allocated for + * output data + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] srcBuffSize Size of the source buffer + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckSourceData(CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + Cpa64U srcBuffSize, + CpaDcSkipData *skipData) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSrcBuff); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pResults); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session handle not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((flushFlag < CPA_DC_FLUSH_NONE) || + (flushFlag > CPA_DC_FLUSH_FULL)) { + LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pSrcBuff == pDestBuff) { + LAC_INVALID_PARAM_LOG("In place operation not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Compressing zero bytes is not supported for stateless sessions + * for non Batch and Pack requests */ + if ((CPA_DC_STATELESS == pSessionDesc->sessState) && + (0 == srcBuffSize) && (NULL == skipData)) { + LAC_INVALID_PARAM_LOG( + "The source buffer size needs to be greater than " + "zero bytes for stateless sessions"); + return CPA_STATUS_INVALID_PARAM; + } + + if (srcBuffSize > DC_BUFFER_MAX_SIZE) { + LAC_INVALID_PARAM_LOG( + "The source buffer size needs to be less than or " + "equal to 2^32-1 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check the compression or decompression function parameters. + * + * @description + * Check that all the parameters used for a Batch and Pack compression + * request are valid. This function essentially checks the destination + * buffer parameters and intermediate buffer parameters. + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionHandle Session handle + * @param[in] pDestBuff Pointer to buffer space allocated for + * output data + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckDestinationData(sal_compression_service_t *pService, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pDestBuff, + dc_request_dir_t compDecomp) +{ + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U destBuffSize = 0; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session handle not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if (LacBuffDesc_BufferListVerify(pDestBuff, + &destBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG( + "Invalid destination buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + if (destBuffSize > DC_BUFFER_MAX_SIZE) { + LAC_INVALID_PARAM_LOG( + "The destination buffer size needs to be less " + "than or equal to 2^32-1 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + LAC_INVALID_PARAM_LOG( + "The session type should not be data plane"); + return CPA_STATUS_INVALID_PARAM; + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + + /* Check if intermediate buffers are supported */ + if ((0 == pService->pInterBuffPtrsArrayPhyAddr) || + (NULL == pService->pInterBuffPtrsArray)) { + LAC_LOG_ERROR( + "No intermediate buffer defined for this instance " + "- see cpaDcStartInstance"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the destination buffer size is greater or + * equal to 128B */ + if (destBuffSize < DC_DEST_BUFFER_DYN_MIN_SIZE) { + LAC_INVALID_PARAM_LOG( + "Destination buffer size should be " + "greater or equal to 128B"); + return CPA_STATUS_INVALID_PARAM; + } + } else + { + /* Ensure that the destination buffer size is greater or + * equal to devices min output buff size */ + if (destBuffSize < + pService->comp_device_data.minOutputBuffSize) { + LAC_INVALID_PARAM_LOG1( + "Destination buffer size should be " + "greater or equal to %d bytes", + pService->comp_device_data + .minOutputBuffSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } else { + /* Ensure that the destination buffer size is greater than + * 0 bytes */ + if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) { + LAC_INVALID_PARAM_LOG( + "Destination buffer size should be " + "greater than 0 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression request parameters + * + * @description + * This function will populate the compression request parameters + * + * @param[out] pCompReqParams Pointer to the compression request parameters + * @param[in] pCookie Pointer to the compression cookie + * + *****************************************************************************/ +static void +dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams, + dc_compression_cookie_t *pCookie) +{ + pCompReqParams->comp_len = pCookie->srcTotalDataLenInBytes; + pCompReqParams->out_buffer_sz = pCookie->dstTotalDataLenInBytes; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Create the requests for compression or decompression + * + * @description + * Create the requests for compression or decompression. This function + * will update the cookie will all required information. + * + * @param{out] pCookie Pointer to the compression cookie + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in pSessionHandle Session handle + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space for data after + * compression + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 + * and CpaDcDecompressData2 + * @param[in] callbackTag Pointer to the callback tag + * @param[in] compDecomp Direction of the operation + * @param[in] compressAndVerify Compress and Verify + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCreateRequest(dc_compression_cookie_t *pCookie, + sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + CpaDcOpData *pOpData, + void *callbackTag, + dc_request_dir_t compDecomp, + dc_cnv_mode_t cnvMode) +{ + icp_qat_fw_comp_req_t *pMsg = NULL; + icp_qat_fw_comp_req_params_t *pCompReqParams = NULL; + Cpa64U srcAddrPhys = 0, dstAddrPhys = 0; + Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0; + + Cpa32U rpCmdFlags = 0; + Cpa8U sop = ICP_QAT_FW_COMP_SOP; + Cpa8U eop = ICP_QAT_FW_COMP_EOP; + Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL; + Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; + Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + CpaBoolean integrityCrcCheck = CPA_FALSE; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaDcFlush flush = CPA_DC_FLUSH_NONE; + Cpa32U initial_adler = 1; + Cpa32U initial_crc32 = 0; + icp_qat_fw_comp_req_t *pReqCache = NULL; + + /* Write the buffer descriptors */ + status = LacBuffDesc_BufferListDescWriteAndGetSize( + pSrcBuff, + &srcAddrPhys, + CPA_FALSE, + &srcTotalDataLenInBytes, + &(pService->generic_service_info)); + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + status = LacBuffDesc_BufferListDescWriteAndGetSize( + pDestBuff, + &dstAddrPhys, + CPA_FALSE, + &dstTotalDataLenInBytes, + &(pService->generic_service_info)); + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + /* Populate the compression cookie */ + pCookie->dcInstance = pService; + pCookie->pSessionHandle = pSessionHandle; + pCookie->callbackTag = callbackTag; + pCookie->pSessionDesc = pSessionDesc; + pCookie->pDcOpData = pOpData; + pCookie->pResults = pResults; + pCookie->compDecomp = compDecomp; + pCookie->pUserSrcBuff = NULL; + pCookie->pUserDestBuff = NULL; + + /* Extract flush flag from either the opData or from the + * parameter. Opdata have been introduce with APIs + * cpaDcCompressData2 and cpaDcDecompressData2 */ + if (NULL != pOpData) { + flush = pOpData->flushFlag; + integrityCrcCheck = pOpData->integrityCrcCheck; + } else { + flush = flushFlag; + } + pCookie->flushFlag = flush; + + /* The firmware expects the length in bytes for source and destination + * to be Cpa32U parameters. However the total data length could be + * bigger as allocated by the user. We ensure that this is not the case + * in dcCheckSourceData and cast the values to Cpa32U here */ + pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes; + if ((DC_COMPRESSION_REQUEST == compDecomp) && + (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { + if (pService->minInterBuffSizeInBytes < + (Cpa32U)dstTotalDataLenInBytes) { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)(pService->minInterBuffSizeInBytes); + } else { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)dstTotalDataLenInBytes; + } + } else + { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)dstTotalDataLenInBytes; + } + + /* Device can not decompress an odd byte decompression request + * if bFinal is not set + */ + if (CPA_TRUE != pService->comp_device_data.oddByteDecompNobFinal) { + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_FLUSH_FINAL != flushFlag) && + (DC_DECOMPRESSION_REQUEST == compDecomp) && + (pCookie->srcTotalDataLenInBytes & 0x1)) { + pCookie->srcTotalDataLenInBytes--; + } + } + /* Device can not decompress odd byte interim requests */ + if (CPA_TRUE != pService->comp_device_data.oddByteDecompInterim) { + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_FLUSH_FINAL != flushFlag) && + (CPA_DC_FLUSH_FULL != flushFlag) && + (DC_DECOMPRESSION_REQUEST == compDecomp) && + (pCookie->srcTotalDataLenInBytes & 0x1)) { + pCookie->srcTotalDataLenInBytes--; + } + } + + pMsg = (icp_qat_fw_comp_req_t *)&pCookie->request; + + if (DC_COMPRESSION_REQUEST == compDecomp) { + pReqCache = &(pSessionDesc->reqCacheComp); + } else { + pReqCache = &(pSessionDesc->reqCacheDecomp); + } + + /* Fills the msg from the template cached in the session descriptor */ + memcpy((void *)pMsg, + (void *)(pReqCache), + LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES); + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + initial_adler = 1; + initial_crc32 = 0; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + } else if (CPA_DC_STATELESS == pSessionDesc->sessState) { + pSessionDesc->previousChecksum = pResults->checksum; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + initial_adler = pSessionDesc->previousChecksum; + } else { + initial_crc32 = pSessionDesc->previousChecksum; + } + } + + /* Backup source and destination buffer addresses, + * CRC calculations both for CNV and translator overflow + * will be performed on them in the callback function. + */ + pCookie->pUserSrcBuff = pSrcBuff; + pCookie->pUserDestBuff = pDestBuff; + + /* + * Due to implementation of CNV support and need for backwards + * compatibility certain fields in the request and response structs had + * been changed, moved or placed in unions cnvMode flag signifies fields + * to be selected from req/res + * + * Doing extended crc checks makes sense only when we want to do the + * actual CNV + */ + if (CPA_TRUE == pService->generic_service_info.integrityCrcCheck && + CPA_TRUE == integrityCrcCheck) { + pMsg->comp_pars.crc.crc_data_addr = + pSessionDesc->physDataIntegrityCrcs; + crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E; + } else { + /* Legacy request structure */ + pMsg->comp_pars.crc.legacy.initial_adler = initial_adler; + pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32; + crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; + } + + /* Populate the cmdFlags */ + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + pSessionDesc->previousRequestType = pSessionDesc->requestType; + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Update the request type for following requests */ + pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; + + /* Reinitialise the cumulative amount of consumed bytes + */ + pSessionDesc->cumulativeConsumedBytes = 0; + + if (DC_COMPRESSION_REQUEST == compDecomp) { + pSessionDesc->isSopForCompressionProcessed = + CPA_TRUE; + } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { + pSessionDesc->isSopForDecompressionProcessed = + CPA_TRUE; + } + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + if (CPA_TRUE == + pSessionDesc + ->isSopForCompressionProcessed) { + sop = ICP_QAT_FW_COMP_NOT_SOP; + } else { + pSessionDesc + ->isSopForCompressionProcessed = + CPA_TRUE; + } + } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { + if (CPA_TRUE == + pSessionDesc + ->isSopForDecompressionProcessed) { + sop = ICP_QAT_FW_COMP_NOT_SOP; + } else { + pSessionDesc + ->isSopForDecompressionProcessed = + CPA_TRUE; + } + } + } + + if ((CPA_DC_FLUSH_FINAL == flush) || + (CPA_DC_FLUSH_FULL == flush)) { + /* Update the request type for following requests */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + } else { + eop = ICP_QAT_FW_COMP_NOT_EOP; + } + } else { + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Reinitialise the cumulative amount of consumed bytes + */ + pSessionDesc->cumulativeConsumedBytes = 0; + } + } + + /* (LW 14 - 15) */ + pCompReqParams = &(pMsg->comp_pars); + dcCompRequestParamsPopulate(pCompReqParams, pCookie); + if (CPA_DC_FLUSH_FINAL == flush) { + bFinal = ICP_QAT_FW_COMP_BFINAL; + } + + switch (cnvMode) { + case DC_CNVNR: + cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY; + /* Fall through is intended here, because for CNVNR + * cnvDecompReq also needs to be set */ + case DC_CNV: + cnvDecompReq = ICP_QAT_FW_COMP_CNV; + break; + case DC_NO_CNV: + cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + break; + } + + /* LW 18 */ + rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + sop, eop, bFinal, cnvDecompReq, cnvRecovery, crcMode); + pMsg->comp_pars.req_par_flags = rpCmdFlags; + + /* Populates the QAT common request middle part of the message + * (LW 6 to 11) */ + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg, + pCookie, + DC_DEFAULT_QAT_PTR_TYPE, + srcAddrPhys, + dstAddrPhys, + 0, + 0); + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Send a compression request to QAT + * + * @description + * Send the requests for compression or decompression to QAT + * + * @param{in] pCookie Pointer to the compression cookie + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcSendRequest(dc_compression_cookie_t *pCookie, + sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + dc_request_dir_t compDecomp) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_compression_tx, + (void *)&(pCookie->request), + LAC_QAT_DC_REQ_SZ_LW); + + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_STATUS_RETRY == status)) { + /* reset requestType after receiving an retry on + * the stateful request */ + pSessionDesc->requestType = pSessionDesc->previousRequestType; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Process the synchronous and asynchronous case for compression or + * decompression + * + * @description + * Process the synchronous and asynchronous case for compression or + * decompression. This function will then create and send the request to + * the firmware. + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in] pSessionHandle Session handle + * @param[in] numRequests Number of operations in the batch request + * @param[in] pBatchOpData Address of the list of jobs to be processed + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space for data after + * compression + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 and + * CpaDcDecompressData2 + * @param[in] callbackTag Pointer to the callback tag + * @param[in] compDecomp Direction of the operation + * @param[in] isAsyncMode Used to know if synchronous or asynchronous + * mode + * @param[in] cnvMode CNV Mode + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_RETRY Retry operation + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_RESOURCE Resource error + * + *****************************************************************************/ +static CpaStatus +dcCompDecompData(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + CpaDcOpData *pOpData, + void *callbackTag, + dc_request_dir_t compDecomp, + CpaBoolean isAsyncMode, + dc_cnv_mode_t cnvMode) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + dc_compression_cookie_t *pCookie = NULL; + + if ((LacSync_GenWakeupSyncCaller == pSessionDesc->pCompressionCb) && + isAsyncMode == CPA_TRUE) { + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + pOpData, + pSyncCallbackData, + compDecomp, + CPA_FALSE, + cnvMode); + } else { + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + DC_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC( + numCompCompletedErrors, pService); + } else { + COMPRESSION_STAT_INC( + numDecompCompletedErrors, pService); + } + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + return status; + } + + /* Allocate the compression cookie + * The memory is freed in callback or in sendRequest if an error occurs + */ + pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( + pService->compression_mem_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry for compression"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } + + if (CPA_STATUS_SUCCESS == status) { + status = dcCreateRequest(pCookie, + pService, + pSessionDesc, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + pOpData, + callbackTag, + compDecomp, + cnvMode); + } + + if (CPA_STATUS_SUCCESS == status) { + /* Increment number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicInc( + &(pSessionDesc->pendingStatelessCbCount)); + } + status = + dcSendRequest(pCookie, pService, pSessionDesc, compDecomp); + } + + if (CPA_STATUS_SUCCESS == status) { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequests, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequests, pService); + } + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequestsErrors, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequestsErrors, pService); + } + + /* Decrement number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicDec( + &(pSessionDesc->pendingStatelessCbCount)); + } else { + qatUtilsAtomicDec( + &(pSessionDesc->pendingStatefulCbCount)); + } + + /* Free the memory pool */ + if (NULL != pCookie) { + if (status != CPA_STATUS_UNSUPPORTED) { + /* Free the memory pool */ + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + } + } + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Handle zero length compression or decompression requests + * + * @description + * Handle zero length compression or decompression requests + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated request + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_TRUE Zero length SOP or MOP processed + * @retval CPA_FALSE Zero length EOP + * + *****************************************************************************/ +static CpaStatus +dcZeroLengthRequests(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag, + dc_request_dir_t compDecomp) +{ + CpaBoolean status = CPA_FALSE; + CpaDcCallbackFn pCbFunc = pSessionDesc->pCompressionCb; + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Reinitialise the cumulative amount of consumed bytes */ + pSessionDesc->cumulativeConsumedBytes = 0; + + /* Zero length SOP */ + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pResults->checksum = 1; + } else { + pResults->checksum = 0; + } + + status = CPA_TRUE; + } else if ((CPA_DC_FLUSH_NONE == flushFlag) || + (CPA_DC_FLUSH_SYNC == flushFlag)) { + /* Zero length MOP */ + pResults->checksum = pSessionDesc->previousChecksum; + status = CPA_TRUE; + } + + if (CPA_TRUE == status) { + pResults->status = CPA_DC_OK; + pResults->produced = 0; + pResults->consumed = 0; + + /* Increment statistics */ + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequests, pService); + COMPRESSION_STAT_INC(numCompCompleted, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequests, pService); + COMPRESSION_STAT_INC(numDecompCompleted, pService); + } + + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + + if ((NULL != pCbFunc) && + (LacSync_GenWakeupSyncCaller != pCbFunc)) { + pCbFunc(callbackTag, CPA_STATUS_SUCCESS); + } + + return CPA_TRUE; + } + + return CPA_FALSE; +} + +static CpaStatus +dcParamCheck(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + sal_compression_service_t *pService, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + dc_session_desc_t *pSessionDesc, + CpaDcFlush flushFlag, + Cpa64U srcBuffSize) +{ + + if (dcCheckSourceData(pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + srcBuffSize, + NULL) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (dcCheckDestinationData( + pService, pSessionHandle, pDestBuff, DC_COMPRESSION_REQUEST) != + CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcCompressData(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionHandle); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (CPA_STATUS_SUCCESS != + dcParamCheck(insHandle, + pSessionHandle, + pService, + pSrcBuff, + pDestBuff, + pResults, + pSessionDesc, + flushFlag, + srcBuffSize)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG( + "Invalid session state, stateful sessions " + "are not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerify feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNVNR_EXTENDED_CAPABILITY)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerifyAndRecovery feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + NULL, + callbackTag, + DC_COMPRESSION_REQUEST, + CPA_TRUE, + DC_CNVNR); +} + +CpaStatus +cpaDcCompressData2(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + dc_cnv_mode_t cnvMode = DC_NO_CNV; + + LAC_CHECK_NULL_PARAM(pOpData); + + if (((CPA_TRUE != pOpData->compressAndVerify) && + (CPA_FALSE != pOpData->compressAndVerify)) || + ((CPA_FALSE != pOpData->compressAndVerifyAndRecover) && + (CPA_TRUE != pOpData->compressAndVerifyAndRecover))) { + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_FALSE == pOpData->compressAndVerify) && + (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { + return CPA_STATUS_INVALID_PARAM; + } + + + if ((CPA_TRUE == pOpData->compressAndVerify) && + (CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE == pOpData->integrityCrcCheck)) { + return cpaDcCompressData(dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + callbackTag); + } + + if (CPA_FALSE == pOpData->compressAndVerify) { + LAC_INVALID_PARAM_LOG( + "Data compression without verification not allowed"); + return CPA_STATUS_UNSUPPORTED; + } + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pOpData); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_TRUE == pOpData->compressAndVerify && + CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG( + "Invalid session state, stateful sessions " + "not supported with CNV"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY) && + (CPA_TRUE == pOpData->compressAndVerify)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerify feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (CPA_STATUS_SUCCESS != + dcParamCheck(insHandle, + pSessionHandle, + pService, + pSrcBuff, + pDestBuff, + pResults, + pSessionDesc, + pOpData->flushFlag, + srcBuffSize)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_TRUE != pOpData->compressAndVerify) { + if (srcBuffSize > DC_COMP_MAX_BUFF_SIZE) { + LAC_LOG_ERROR( + "Compression payload greater than 64KB is " + "unsupported, when CnV is disabled\n"); + return CPA_STATUS_UNSUPPORTED; + } + } + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + /* Lock the session to check if there are in-flight stateful + * requests */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + + /* Check if there is already one in-flight stateful request */ + if (0 != + qatUtilsAtomicGet( + &(pSessionDesc->pendingStatefulCbCount))) { + LAC_LOG_ERROR( + "Only one in-flight stateful request supported"); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + return CPA_STATUS_RETRY; + } + + if (0 == srcBuffSize) { + if (CPA_TRUE == + dcZeroLengthRequests(pService, + pSessionDesc, + pResults, + pOpData->flushFlag, + callbackTag, + DC_COMPRESSION_REQUEST)) { + return CPA_STATUS_SUCCESS; + } + } + + qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + } + + if (CPA_TRUE == pOpData->compressAndVerify) { + cnvMode = DC_CNV; + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + pOpData, + callbackTag, + DC_COMPRESSION_REQUEST, + CPA_TRUE, + cnvMode); +} + +static CpaStatus +dcDecompressDataCheck(CpaInstanceHandle insHandle, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + Cpa64U *srcBufferSize) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U srcBuffSize = 0; + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + if (dcCheckSourceData(pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + srcBuffSize, + NULL) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (dcCheckDestinationData(pService, + pSessionHandle, + pDestBuff, + DC_DECOMPRESSION_REQUEST) != + CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) { + LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); + return CPA_STATUS_INVALID_PARAM; + } + + + *srcBufferSize = srcBuffSize; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDecompressData(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + status = dcDecompressDataCheck(insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + &srcBuffSize); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + pService = (sal_compression_service_t *)insHandle; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + /* Lock the session to check if there are in-flight stateful + * requests */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot lock session lock"); + return CPA_STATUS_RESOURCE; + } + + /* Check if there is already one in-flight stateful request */ + if (0 != + qatUtilsAtomicGet( + &(pSessionDesc->pendingStatefulCbCount))) { + LAC_LOG_ERROR( + "Only one in-flight stateful request supported"); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + return CPA_STATUS_RETRY; + } + + if ((0 == srcBuffSize) || + ((1 == srcBuffSize) && (CPA_DC_FLUSH_FINAL != flushFlag) && + (CPA_DC_FLUSH_FULL != flushFlag))) { + if (CPA_TRUE == + dcZeroLengthRequests(pService, + pSessionDesc, + pResults, + flushFlag, + callbackTag, + DC_DECOMPRESSION_REQUEST)) { + return CPA_STATUS_SUCCESS; + } + } + + qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + NULL, + callbackTag, + DC_DECOMPRESSION_REQUEST, + CPA_TRUE, + DC_NO_CNV); +} + +CpaStatus +cpaDcDecompressData2(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa64U srcBuffSize = 0; + LAC_CHECK_NULL_PARAM(pOpData); + + if (CPA_FALSE == pOpData->integrityCrcCheck) { + + return cpaDcDecompressData(dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + callbackTag); + } + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + status = dcDecompressDataCheck(insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + &srcBuffSize); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + pService = (sal_compression_service_t *)insHandle; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG("Invalid session: Stateful session is " + "not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + return dcCompDecompData(pService, + pSessionDesc, + insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + pOpData, + callbackTag, + DC_DECOMPRESSION_REQUEST, + CPA_TRUE, + DC_NO_CNV); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_dp.c b/sys/dev/qat/qat_api/common/compression/dc_dp.c new file mode 100644 index 00000000000..4a24bf17dc3 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_dp.c @@ -0,0 +1,545 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_dp.c + * + * @defgroup cpaDcDp Data Compression Data Plane API + * + * @ingroup cpaDcDp + * + * @description + * Implementation of the Data Compression DP operations. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_dp.h" + +#include "icp_qat_fw_comp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "lac_sal.h" +#include "lac_sync.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" +#include "icp_sal_poll.h" + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * Check that pOpData is valid + * + * @description + * Check that all the parameters defined in the pOpData are valid + * + * @param[in] pOpData Pointer to a structure containing the + * request parameters + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcDataPlaneParamCheck(const CpaDcDpOpData *pOpData) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData->dcInstance); + LAC_CHECK_NULL_PARAM(pOpData->pSessionHandle); + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(pOpData->dcInstance, + SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)(pOpData->dcInstance); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_FALSE == pSessionDesc->isDcDp) { + QAT_UTILS_LOG("The session type should be data plane.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Compressing zero byte is not supported */ + if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) && + (0 == pOpData->bufferLenToCompress)) { + QAT_UTILS_LOG( + "The source buffer length to compress needs to be greater than zero byte.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->sessDirection > CPA_DC_DIR_DECOMPRESS) { + QAT_UTILS_LOG("Invalid direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (0 == pOpData->srcBuffer) { + QAT_UTILS_LOG("Invalid srcBuffer\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pOpData->destBuffer) { + QAT_UTILS_LOG("Invalid destBuffer\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (pOpData->srcBuffer == pOpData->destBuffer) { + QAT_UTILS_LOG("In place operation is not supported.\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pOpData->thisPhys) { + QAT_UTILS_LOG("Invalid thisPhys\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_TRUE != pOpData->compressAndVerify) && + (CPA_FALSE != pOpData->compressAndVerify)) { + QAT_UTILS_LOG("Invalid compressAndVerify\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerify) && + !(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY)) { + QAT_UTILS_LOG("Invalid compressAndVerify, no CNV capability\n"); + return CPA_STATUS_UNSUPPORTED; + } + if ((CPA_TRUE != pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE != pOpData->compressAndVerifyAndRecover)) { + QAT_UTILS_LOG("Invalid compressAndVerifyAndRecover\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE == pOpData->compressAndVerify)) { + QAT_UTILS_LOG("CnVnR option set without setting CnV\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + !(pService->generic_service_info.dcExtendedFeatures & + DC_CNVNR_EXTENDED_CAPABILITY)) { + QAT_UTILS_LOG( + "Invalid CnVnR option set and no CnVnR capability.\n"); + return CPA_STATUS_UNSUPPORTED; + } + + if ((CPA_DP_BUFLIST == pOpData->srcBufferLen) && + (CPA_DP_BUFLIST != pOpData->destBufferLen)) { + QAT_UTILS_LOG( + "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_DP_BUFLIST != pOpData->srcBufferLen) && + (CPA_DP_BUFLIST == pOpData->destBufferLen)) { + QAT_UTILS_LOG( + "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DP_BUFLIST != pOpData->srcBufferLen) { + if (pOpData->srcBufferLen < pOpData->bufferLenToCompress) { + QAT_UTILS_LOG( + "srcBufferLen is smaller than bufferLenToCompress.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->destBufferLen < pOpData->bufferLenForData) { + QAT_UTILS_LOG( + "destBufferLen is smaller than bufferLenForData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* We are assuming that there is enough memory in the source and + * destination buffer lists. We only receive physical addresses + * of the + * buffers so we are unable to test it here */ + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->srcBuffer); + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->destBuffer); + } + + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->thisPhys); + + if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) || + (CPA_DC_DIR_COMBINED == pSessionDesc->sessDirection)) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + /* Check if Intermediate Buffer Array pointer is NULL */ + if ((0 == pService->pInterBuffPtrsArrayPhyAddr) || + (NULL == pService->pInterBuffPtrsArray)) { + QAT_UTILS_LOG( + "No intermediate buffer defined for this instance - see cpaDcStartInstance.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the destination buffer length for data is + * greater + * or equal to 128B */ + if (pOpData->bufferLenForData < + DC_DEST_BUFFER_DYN_MIN_SIZE) { + QAT_UTILS_LOG( + "Destination buffer length for data should be greater or equal to 128B.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* Ensure that the destination buffer length for data is + * greater + * or equal to min output buffsize */ + if (pOpData->bufferLenForData < + pService->comp_device_data.minOutputBuffSize) { + QAT_UTILS_LOG( + "Destination buffer size should be greater or equal to %d bytes.\n", + pService->comp_device_data + .minOutputBuffSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDpGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize) +{ + return dcGetSessionSize(dcInstance, pSessionData, pSessionSize, NULL); +} + +CpaStatus +cpaDcDpInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + dc_session_desc_t *pSessionDesc = NULL; + sal_compression_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)dcInstance; + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + /* Stateful is not supported */ + if (CPA_DC_STATELESS != pSessionData->sessState) { + QAT_UTILS_LOG("Invalid sessState value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + status = + dcInitSession(dcInstance, pSessionHandle, pSessionData, NULL, NULL); + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + pSessionDesc->isDcDp = CPA_TRUE; + + ICP_QAT_FW_COMN_PTR_TYPE_SET( + pSessionDesc->reqCacheDecomp.comn_hdr.comn_req_flags, + DC_DP_QAT_PTR_TYPE); + ICP_QAT_FW_COMN_PTR_TYPE_SET( + pSessionDesc->reqCacheComp.comn_hdr.comn_req_flags, + DC_DP_QAT_PTR_TYPE); + } + + return status; +} + +CpaStatus +cpaDcDpRemoveSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + return cpaDcRemoveSession(dcInstance, pSessionHandle); +} + +CpaStatus +cpaDcDpRegCbFunc(const CpaInstanceHandle dcInstance, + const CpaDcDpCallbackFn pNewCb) +{ + sal_compression_service_t *pService = NULL; + + LAC_CHECK_NULL_PARAM(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pNewCb); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + pService = (sal_compression_service_t *)dcInstance; + pService->pDcDpCb = pNewCb; + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * + * @description + * Writes the message to the ring + * + * @param[in] pOpData Pointer to a structure containing the + * request parameters + * @param[in] pCurrentQatMsg Pointer to current QAT message on the ring + * + *****************************************************************************/ +static void +dcDpWriteRingMsg(CpaDcDpOpData *pOpData, icp_qat_fw_comp_req_t *pCurrentQatMsg) +{ + icp_qat_fw_comp_req_t *pReqCache = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa8U bufferFormat; + + Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + Cpa8U cnvnrCompReq = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + + if (CPA_DC_DIR_COMPRESS == pOpData->sessDirection) { + pReqCache = &(pSessionDesc->reqCacheComp); + /* CNV check */ + if (CPA_TRUE == pOpData->compressAndVerify) { + cnvDecompReq = ICP_QAT_FW_COMP_CNV; + /* CNVNR check */ + if (CPA_TRUE == pOpData->compressAndVerifyAndRecover) { + cnvnrCompReq = ICP_QAT_FW_COMP_CNV_RECOVERY; + } + } + } else { + pReqCache = &(pSessionDesc->reqCacheDecomp); + } + + /* Fills in the template DC ET ring message - cached from the + * session descriptor */ + memcpy((void *)pCurrentQatMsg, + (void *)(pReqCache), + (LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES)); + + if (CPA_DP_BUFLIST == pOpData->srcBufferLen) { + bufferFormat = QAT_COMN_PTR_TYPE_SGL; + } else { + bufferFormat = QAT_COMN_PTR_TYPE_FLAT; + } + + pCurrentQatMsg->comp_pars.req_par_flags |= + ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + 0, 0, 0, cnvDecompReq, cnvnrCompReq, 0); + + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pCurrentQatMsg, + pOpData, + bufferFormat, + pOpData->srcBuffer, + pOpData->destBuffer, + pOpData->srcBufferLen, + pOpData->destBufferLen); + + pCurrentQatMsg->comp_pars.comp_len = pOpData->bufferLenToCompress; + pCurrentQatMsg->comp_pars.out_buffer_sz = pOpData->bufferLenForData; +} + +CpaStatus +cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow) +{ + icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + status = dcDataPlaneParamCheck(pOpData); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + if ((CPA_FALSE == pOpData->compressAndVerify) && + (CPA_DC_DIR_COMPRESS == pOpData->sessDirection)) { + return CPA_STATUS_UNSUPPORTED; + } + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pOpData->dcInstance); + + trans_handle = ((sal_compression_service_t *)pOpData->dcInstance) + ->trans_handle_compression_tx; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + + if ((CPA_DC_DIR_COMPRESS == pOpData->sessDirection) && + (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_DC_DIR_DECOMPRESS == pOpData->sessDirection) && + (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + return CPA_STATUS_RETRY; + } + + dcDpWriteRingMsg(pOpData, pCurrentQatMsg); + pSessionDesc->pendingDpStatelessCbCount++; + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaDcDpOpData *pOpData[], + const CpaBoolean performOpNow) +{ + icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa32U i = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData[0]); + LAC_CHECK_NULL_PARAM(pOpData[0]->dcInstance); + + pService = (sal_compression_service_t *)(pOpData[0]->dcInstance); + if ((numberRequests == 0) || + (numberRequests > pService->maxNumCompConcurrentReq)) { + QAT_UTILS_LOG( + "The number of requests needs to be between 1 and %d.\n", + pService->maxNumCompConcurrentReq); + return CPA_STATUS_INVALID_PARAM; + } + + for (i = 0; i < numberRequests; i++) { + status = dcDataPlaneParamCheck(pOpData[i]); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + /* Check that all instance handles and session handles are the + * same */ + if (pOpData[i]->dcInstance != pOpData[0]->dcInstance) { + QAT_UTILS_LOG( + "All instance handles should be the same in the pOpData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData[i]->pSessionHandle != pOpData[0]->pSessionHandle) { + QAT_UTILS_LOG( + "All session handles should be the same in the pOpData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } + + for (i = 0; i < numberRequests; i++) { + if ((CPA_FALSE == pOpData[i]->compressAndVerify) && + (CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection)) { + return CPA_STATUS_UNSUPPORTED; + } + } + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pOpData[0]->dcInstance); + + trans_handle = ((sal_compression_service_t *)pOpData[0]->dcInstance) + ->trans_handle_compression_tx; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData[0]->pSessionHandle); + + for (i = 0; i < numberRequests; i++) { + if ((CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection) && + (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_DC_DIR_DECOMPRESS == + pOpData[i]->sessDirection) && + (CPA_DC_DIR_COMPRESS == + pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } + + icp_adf_getQueueMemory(trans_handle, + numberRequests, + (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + return CPA_STATUS_RETRY; + } + + for (i = 0; i < numberRequests; i++) { + dcDpWriteRingMsg(pOpData[i], pCurrentQatMsg); + icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); + } + + pSessionDesc->pendingDpStatelessCbCount += numberRequests; + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, Cpa32U responseQuota) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_INSTANCE_HANDLE(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_rx; + + return icp_adf_pollQueue(trans_handle, responseQuota); +} + +CpaStatus +cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_NULL_PARAM(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_header_footer.c b/sys/dev/qat/qat_api/common/compression/dc_header_footer.c new file mode 100644 index 00000000000..4a92e20ba0f --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_header_footer.c @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_header_footer.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression header and footer operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" +#include "icp_adf_init.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "dc_header_footer.h" +#include "dc_session.h" +#include "dc_datapath.h" + +CpaStatus +cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, + Cpa32U *count) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pDestBuff->pData); + LAC_CHECK_NULL_PARAM(count); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + QAT_UTILS_LOG("Invalid session direction\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + /* Adding a Gzip header */ + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + + if (pDestBuff->dataLenInBytes < DC_GZIP_HEADER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pDest[0] = DC_GZIP_ID1; /* ID1 */ + pDest[1] = DC_GZIP_ID2; /* ID2 */ + pDest[2] = + 0x08; /* CM = 8 denotes "deflate" compression */ + pDest[3] = 0x00; /* FLG = 0 denotes "No extra fields" */ + pDest[4] = 0x00; + pDest[5] = 0x00; + pDest[6] = 0x00; + pDest[7] = 0x00; /* MTIME = 0x00 means time stamp not + available */ + + /* XFL = 4 - compressor used fastest compression, */ + /* XFL = 2 - compressor used maximum compression. */ + pDest[8] = 0; + if (CPA_DC_L1 == pSessionDesc->compLevel) + pDest[8] = DC_GZIP_FAST_COMP; + else if (CPA_DC_L4 >= pSessionDesc->compLevel) + pDest[8] = DC_GZIP_MAX_COMP; + + pDest[9] = + DC_GZIP_FILESYSTYPE; /* OS = 0 means FAT filesystem + (MS-DOS, OS/2, NT/Win32), 3 - Unix */ + + /* Set to the number of bytes added to the buffer */ + *count = DC_GZIP_HEADER_SIZE; + } + + /* Adding a Zlib header */ + else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa16U header = 0, level = 0; + + if (pDestBuff->dataLenInBytes < DC_ZLIB_HEADER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* CMF = CM | CMINFO. + CM = 8 denotes "deflate" compression, + CMINFO = 7 indicates a 32K window size */ + /* Depending on the device, at compression levels above + L1, the + window size can be 8 or 16K bytes. + The file will decompress ok if a greater window size + is specified + in the header. */ + header = + (DC_ZLIB_CM_DEFLATE + + (DC_32K_WINDOW_SIZE << DC_ZLIB_WINDOWSIZE_OFFSET)) + << LAC_NUM_BITS_IN_BYTE; + + switch (pSessionDesc->compLevel) { + case CPA_DC_L1: + level = DC_ZLIB_LEVEL_0; + break; + case CPA_DC_L2: + level = DC_ZLIB_LEVEL_1; + break; + case CPA_DC_L3: + level = DC_ZLIB_LEVEL_2; + break; + default: + level = DC_ZLIB_LEVEL_3; + } + + /* Bits 6 - 7: FLEVEL, compression level */ + header |= level << DC_ZLIB_FLEVEL_OFFSET; + + /* The header has to be a multiple of 31 */ + header += DC_ZLIB_HEADER_OFFSET - + (header % DC_ZLIB_HEADER_OFFSET); + + pDest[0] = (Cpa8U)(header >> LAC_NUM_BITS_IN_BYTE); + pDest[1] = (Cpa8U)header; + + /* Set to the number of bytes added to the buffer */ + *count = DC_ZLIB_HEADER_SIZE; + } + + /* If deflate but no checksum required */ + else { + *count = 0; + } + } else { + /* There is no header for other compressed data */ + *count = 0; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, + CpaDcRqResults *pRes) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pDestBuff->pData); + LAC_CHECK_NULL_PARAM(pRes); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + QAT_UTILS_LOG("Invalid session direction\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa32U crc32 = pRes->checksum; + Cpa64U totalLenBeforeCompress = + pSessionDesc->cumulativeConsumedBytes; + + if (pDestBuff->dataLenInBytes < DC_GZIP_FOOTER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Crc32 of the uncompressed data */ + pDest[0] = (Cpa8U)crc32; + pDest[1] = (Cpa8U)(crc32 >> LAC_NUM_BITS_IN_BYTE); + pDest[2] = (Cpa8U)(crc32 >> 2 * LAC_NUM_BITS_IN_BYTE); + pDest[3] = (Cpa8U)(crc32 >> 3 * LAC_NUM_BITS_IN_BYTE); + + /* Length of the uncompressed data */ + pDest[4] = (Cpa8U)totalLenBeforeCompress; + pDest[5] = (Cpa8U)(totalLenBeforeCompress >> + LAC_NUM_BITS_IN_BYTE); + pDest[6] = (Cpa8U)(totalLenBeforeCompress >> + 2 * LAC_NUM_BITS_IN_BYTE); + pDest[7] = (Cpa8U)(totalLenBeforeCompress >> + 3 * LAC_NUM_BITS_IN_BYTE); + + /* Increment produced by the number of bytes added to + * the buffer */ + pRes->produced += DC_GZIP_FOOTER_SIZE; + } else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa32U adler32 = pRes->checksum; + + if (pDestBuff->dataLenInBytes < DC_ZLIB_FOOTER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Adler32 of the uncompressed data */ + pDest[0] = (Cpa8U)(adler32 >> 3 * LAC_NUM_BITS_IN_BYTE); + pDest[1] = (Cpa8U)(adler32 >> 2 * LAC_NUM_BITS_IN_BYTE); + pDest[2] = (Cpa8U)(adler32 >> LAC_NUM_BITS_IN_BYTE); + pDest[3] = (Cpa8U)adler32; + + /* Increment produced by the number of bytes added to + * the buffer */ + pRes->produced += DC_ZLIB_FOOTER_SIZE; + } + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_session.c b/sys/dev/qat/qat_api/common/compression/dc_session.c new file mode 100644 index 00000000000..1d742e227a1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_session.c @@ -0,0 +1,957 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_session.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression session operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" + +#include "icp_qat_fw.h" +#include "icp_qat_fw_comp.h" +#include "icp_qat_hw.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "lac_buffer_desc.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check that pSessionData is valid + * + * @description + * Check that all the parameters defined in the pSessionData are valid + * + * @param[in] pSessionData Pointer to a user instantiated structure + * containing session data + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed to find device + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature + * + *****************************************************************************/ +static CpaStatus +dcCheckSessionData(const CpaDcSessionSetupData *pSessionData, + CpaInstanceHandle dcInstance) +{ + CpaDcInstanceCapabilities instanceCapabilities = { 0 }; + + cpaDcQueryCapabilities(dcInstance, &instanceCapabilities); + + if ((pSessionData->compLevel < CPA_DC_L1) || + (pSessionData->compLevel > CPA_DC_L9)) { + QAT_UTILS_LOG("Invalid compLevel value\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) || + (pSessionData->autoSelectBestHuffmanTree > + CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS)) { + QAT_UTILS_LOG("Invalid autoSelectBestHuffmanTree value\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (pSessionData->compType != CPA_DC_DEFLATE) { + QAT_UTILS_LOG("Invalid compType value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->huffType < CPA_DC_HT_STATIC) || + (pSessionData->huffType > CPA_DC_HT_FULL_DYNAMIC) || + (CPA_DC_HT_PRECOMP == pSessionData->huffType)) { + QAT_UTILS_LOG("Invalid huffType value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->sessDirection < CPA_DC_DIR_COMPRESS) || + (pSessionData->sessDirection > CPA_DC_DIR_COMBINED)) { + QAT_UTILS_LOG("Invalid sessDirection value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->sessState < CPA_DC_STATEFUL) || + (pSessionData->sessState > CPA_DC_STATELESS)) { + QAT_UTILS_LOG("Invalid sessState value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->checksum < CPA_DC_NONE) || + (pSessionData->checksum > CPA_DC_ADLER32)) { + QAT_UTILS_LOG("Invalid checksum value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression hardware block + * + * @description + * This function will populate the compression hardware block and update + * the size in bytes of the block + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] pCompConfig Pointer to slice config word + * @param[in] compDecomp Direction of the operation + * @param[in] enableDmm Delayed Match Mode + * + *****************************************************************************/ +static void +dcCompHwBlockPopulate(dc_session_desc_t *pSessionDesc, + icp_qat_hw_compression_config_t *pCompConfig, + dc_request_dir_t compDecomp, + icp_qat_hw_compression_delayed_match_t enableDmm) +{ + icp_qat_hw_compression_direction_t dir = + ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; + icp_qat_hw_compression_algo_t algo = + ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; + icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + icp_qat_hw_compression_file_type_t filetype = + ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; + + /* Set the direction */ + if (DC_COMPRESSION_REQUEST == compDecomp) { + dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; + } else { + dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; + } else { + QAT_UTILS_LOG("Algorithm not supported for Compression\n"); + } + + /* Set the depth */ + if (DC_DECOMPRESSION_REQUEST == compDecomp) { + depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + } else { + switch (pSessionDesc->compLevel) { + case CPA_DC_L1: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + break; + case CPA_DC_L2: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_4; + break; + case CPA_DC_L3: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_8; + break; + default: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_16; + } + } + + /* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other + * modes will be used in the future for precompiled huffman trees */ + filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; + + pCompConfig->val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD( + dir, enableDmm, algo, depth, filetype); + + pCompConfig->reserved = 0; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression content descriptor + * + * @description + * This function will populate the compression content descriptor + * + * @param[in] pService Pointer to the service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] contextBufferAddrPhys Physical address of the context buffer + * @param[out] pMsg Pointer to the compression message + * @param[in] nextSlice Next slice + * @param[in] compDecomp Direction of the operation + * + *****************************************************************************/ +static void +dcCompContentDescPopulate(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaPhysicalAddr contextBufferAddrPhys, + icp_qat_fw_comp_req_t *pMsg, + icp_qat_fw_slice_t nextSlice, + dc_request_dir_t compDecomp) +{ + + icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL; + icp_qat_hw_compression_config_t *pCompConfig = NULL; + CpaBoolean bankEnabled = CPA_FALSE; + + pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pMsg->comp_cd_ctrl); + pCompConfig = + (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl + .comp_slice_cfg_word); + + ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); + + pCompControlBlock->comp_cfg_offset = 0; + + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_DEFLATE == pSessionDesc->compType) && + (DC_DECOMPRESSION_REQUEST == compDecomp)) { + /* Enable A, B, C, D, and E (CAMs). */ + pCompControlBlock->ram_bank_flags = + ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank E */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank D */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank C */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank B */ + ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */ + bankEnabled = CPA_TRUE; + } else { + /* Disable all banks */ + pCompControlBlock->ram_bank_flags = + ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank E */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank D */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank C */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank B */ + ICP_QAT_FW_COMP_BANK_DISABLED); /* Bank A */ + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + pService->generic_service_info, + pCompControlBlock->comp_state_addr, + pSessionDesc->stateRegistersComp); + } else { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + pService->generic_service_info, + pCompControlBlock->comp_state_addr, + pSessionDesc->stateRegistersDecomp); + } + + if (CPA_TRUE == bankEnabled) { + pCompControlBlock->ram_banks_addr = contextBufferAddrPhys; + } else { + pCompControlBlock->ram_banks_addr = 0; + } + + pCompControlBlock->resrvd = 0; + + /* Populate Compression Hardware Setup Block */ + dcCompHwBlockPopulate(pSessionDesc, + pCompConfig, + compDecomp, + pService->comp_device_data.enableDmm); +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the translator content descriptor + * + * @description + * This function will populate the translator content descriptor + * + * @param[out] pMsg Pointer to the compression message + * @param[in] nextSlice Next slice + * + *****************************************************************************/ +static void +dcTransContentDescPopulate(icp_qat_fw_comp_req_t *pMsg, + icp_qat_fw_slice_t nextSlice) +{ + + icp_qat_fw_xlt_cd_hdr_t *pTransControlBlock = NULL; + pTransControlBlock = (icp_qat_fw_xlt_cd_hdr_t *)&(pMsg->u2.xlt_cd_ctrl); + + ICP_QAT_FW_COMN_NEXT_ID_SET(pTransControlBlock, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(pTransControlBlock, ICP_QAT_FW_SLICE_XLAT); + + pTransControlBlock->resrvd1 = 0; + pTransControlBlock->resrvd2 = 0; + pTransControlBlock->resrvd3 = 0; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Get the context size and the history size + * + * @description + * This function will get the size of the context buffer and the history + * buffer. The history buffer is a subset of the context buffer and its + * size is needed for stateful compression. + + * @param[in] dcInstance DC Instance Handle + * + * @param[in] pSessionData Pointer to a user instantiated + * structure containing session data + * @param[out] pContextSize Pointer to the context size + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + * + *****************************************************************************/ +static CpaStatus +dcGetContextSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pContextSize) +{ + sal_compression_service_t *pCompService = NULL; + + pCompService = (sal_compression_service_t *)dcInstance; + + *pContextSize = 0; + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DEFLATE == pSessionData->compType) && + (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) { + *pContextSize = + pCompService->comp_device_data.inflateContextSize; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +dcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + icp_qat_fw_comp_req_t *pReqCache = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaPhysicalAddr contextAddrPhys = 0; + CpaPhysicalAddr physAddress = 0; + CpaPhysicalAddr physAddressAligned = 0; + Cpa32U minContextSize = 0, historySize = 0; + Cpa32U rpCmdFlags = 0; + icp_qat_fw_serv_specif_flags cmdFlags = 0; + Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION; + Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST; + Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST; + Cpa8U disableType0EnhancedAutoSelectBest = + ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; + icp_qat_fw_la_cmd_id_t dcCmdId = + (icp_qat_fw_la_cmd_id_t)ICP_QAT_FW_COMP_CMD_STATIC; + icp_qat_fw_comn_flags cmnRequestFlags = 0; + dc_integrity_crc_fw_t *pDataIntegrityCrcs = NULL; + + cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(DC_DEFAULT_QAT_PTR_TYPE, + QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); + + pService = (sal_compression_service_t *)dcInstance; + + secureRam = pService->comp_device_data.useDevRam; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionData); + + /* Check that the parameters defined in the pSessionData are valid for + * the + * device */ + if (CPA_STATUS_SUCCESS != + dcCheckSessionData(pSessionData, dcInstance)) { + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) { + QAT_UTILS_LOG("Stateful sessions are not supported.\n"); + return CPA_STATUS_UNSUPPORTED; + } + + if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { + /* Test if DRAM is available for the intermediate buffers */ + if ((NULL == pService->pInterBuffPtrsArray) && + (0 == pService->pInterBuffPtrsArrayPhyAddr)) { + if (CPA_DC_ASB_STATIC_DYNAMIC == + pSessionData->autoSelectBestHuffmanTree) { + /* Define the Huffman tree as static */ + pSessionData->huffType = CPA_DC_HT_STATIC; + } else { + QAT_UTILS_LOG( + "No buffer defined for this instance - see cpaDcStartInstance.\n"); + return CPA_STATUS_RESOURCE; + } + } + } + + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DEFLATE == pSessionData->compType)) { + /* Get the size of the context buffer */ + status = + dcGetContextSize(dcInstance, pSessionData, &minContextSize); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Unable to get the context size of the session.\n"); + return CPA_STATUS_FAIL; + } + + /* If the minContextSize is zero it means we will not save or + * restore + * any history */ + if (0 != minContextSize) { + Cpa64U contextBuffSize = 0; + + LAC_CHECK_NULL_PARAM(pContextBuffer); + + if (LacBuffDesc_BufferListVerify( + pContextBuffer, + &contextBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the context buffer size is greater or + * equal + * to minContextSize */ + if (contextBuffSize < minContextSize) { + QAT_UTILS_LOG( + "Context buffer size should be greater or equal to %d.\n", + minContextSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + /* Re-align the session structure to 64 byte alignment */ + physAddress = + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + (Cpa8U *)pSessionHandle + + sizeof(void *)); + + if (physAddress == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the session.\n"); + return CPA_STATUS_FAIL; + } + + physAddressAligned = + (CpaPhysicalAddr)LAC_ALIGN_POW2_ROUNDUP(physAddress, + LAC_64BYTE_ALIGNMENT); + + pSessionDesc = (dc_session_desc_t *) + /* Move the session pointer by the physical offset + between aligned and unaligned memory */ + ((Cpa8U *)pSessionHandle + sizeof(void *) + + (physAddressAligned - physAddress)); + + /* Save the aligned pointer in the first bytes (size of LAC_ARCH_UINT) + * of the session memory */ + *((LAC_ARCH_UINT *)pSessionHandle) = (LAC_ARCH_UINT)pSessionDesc; + + /* Zero the compression session */ + LAC_OS_BZERO(pSessionDesc, sizeof(dc_session_desc_t)); + + /* Write the buffer descriptor for context/history */ + if (0 != minContextSize) { + status = LacBuffDesc_BufferListDescWrite( + pContextBuffer, + &contextAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + pSessionDesc->pContextBuffer = pContextBuffer; + pSessionDesc->historyBuffSize = historySize; + } + + pSessionDesc->cumulativeConsumedBytes = 0; + + /* Initialise pSessionDesc */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + pSessionDesc->huffType = pSessionData->huffType; + pSessionDesc->compType = pSessionData->compType; + pSessionDesc->checksumType = pSessionData->checksum; + pSessionDesc->autoSelectBestHuffmanTree = + pSessionData->autoSelectBestHuffmanTree; + pSessionDesc->sessDirection = pSessionData->sessDirection; + pSessionDesc->sessState = pSessionData->sessState; + pSessionDesc->compLevel = pSessionData->compLevel; + pSessionDesc->isDcDp = CPA_FALSE; + pSessionDesc->minContextSize = minContextSize; + pSessionDesc->isSopForCompressionProcessed = CPA_FALSE; + pSessionDesc->isSopForDecompressionProcessed = CPA_FALSE; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + + if (CPA_DC_STATEFUL == pSessionData->sessState) { + /* Init the spinlock used to lock the access to the number of + * stateful + * in-flight requests */ + status = LAC_SPINLOCK_INIT(&(pSessionDesc->sessionLock)); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Spinlock init failed for sessionLock.\n"); + return CPA_STATUS_RESOURCE; + } + } + + /* For asynchronous - use the user supplied callback + * for synchronous - use the internal synchronous callback */ + pSessionDesc->pCompressionCb = ((void *)NULL != (void *)callbackFn) ? + callbackFn : + LacSync_GenWakeupSyncCaller; + + /* Reset the pending callback counters */ + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); + pSessionDesc->pendingDpStatelessCbCount = 0; + + if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { + /* Populate the compression section of the content + * descriptor */ + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_XLAT, + DC_COMPRESSION_REQUEST); + + /* Populate the translator section of the content + * descriptor */ + dcTransContentDescPopulate( + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_DRAM_WR); + + if (0 != pService->pInterBuffPtrsArrayPhyAddr) { + pReqCache = &(pSessionDesc->reqCacheComp); + + pReqCache->u1.xlt_pars.inter_buff_ptr = + pService->pInterBuffPtrsArrayPhyAddr; + } + } else { + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_DRAM_WR, + DC_COMPRESSION_REQUEST); + } + } + + /* Populate the compression section of the content descriptor for + * the decompression case or combined */ + if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheDecomp), + ICP_QAT_FW_SLICE_DRAM_WR, + DC_DECOMPRESSION_REQUEST); + } + + if (CPA_DC_STATEFUL == pSessionData->sessState) { + sessType = ICP_QAT_FW_COMP_STATEFUL_SESSION; + + LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, + sizeof(pSessionDesc->stateRegistersComp)); + + LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, + sizeof(pSessionDesc->stateRegistersDecomp)); + } + + /* Get physical address of E2E CRC buffer */ + pSessionDesc->physDataIntegrityCrcs = (icp_qat_addr_width_t) + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + &pSessionDesc->dataIntegrityCrcs); + if (0 == pSessionDesc->physDataIntegrityCrcs) { + QAT_UTILS_LOG( + "Unable to get the physical address of Data Integrity buffer.\n"); + return CPA_STATUS_FAIL; + } + /* Initialize default CRC parameters */ + pDataIntegrityCrcs = &pSessionDesc->dataIntegrityCrcs; + pDataIntegrityCrcs->crc32 = 0; + pDataIntegrityCrcs->adler32 = 1; + pDataIntegrityCrcs->oCrc32Cpr = DC_INVALID_CRC; + pDataIntegrityCrcs->iCrc32Cpr = DC_INVALID_CRC; + pDataIntegrityCrcs->oCrc32Xlt = DC_INVALID_CRC; + pDataIntegrityCrcs->iCrc32Xlt = DC_INVALID_CRC; + pDataIntegrityCrcs->xorFlags = DC_XOR_FLAGS_DEFAULT; + pDataIntegrityCrcs->crcPoly = DC_CRC_POLY_DEFAULT; + pDataIntegrityCrcs->xorOut = DC_XOR_OUT_DEFAULT; + + /* Initialise seed checksums */ + pSessionDesc->seedSwCrc.swCrcI = 0; + pSessionDesc->seedSwCrc.swCrcO = 0; + + /* Populate the cmdFlags */ + switch (pSessionDesc->autoSelectBestHuffmanTree) { + case CPA_DC_ASB_DISABLED: + break; + case CPA_DC_ASB_STATIC_DYNAMIC: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + break; + case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; + break; + case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; + disableType0EnhancedAutoSelectBest = + ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; + break; + default: + break; + } + + rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_SOP, + ICP_QAT_FW_COMP_EOP, + ICP_QAT_FW_COMP_BFINAL, + ICP_QAT_FW_COMP_NO_CNV, + ICP_QAT_FW_COMP_NO_CNV_RECOVERY, + ICP_QAT_FW_COMP_CRC_MODE_LEGACY); + + cmdFlags = + ICP_QAT_FW_COMP_FLAGS_BUILD(sessType, + autoSelectBest, + enhancedAutoSelectBest, + disableType0EnhancedAutoSelectBest, + secureRam); + + if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + dcCmdId = (icp_qat_fw_la_cmd_id_t)( + ICP_QAT_FW_COMP_CMD_DYNAMIC); + } + + pReqCache = &(pSessionDesc->reqCacheComp); + pReqCache->comp_pars.req_par_flags = rpCmdFlags; + pReqCache->comp_pars.crc.legacy.initial_adler = 1; + pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; + + /* Populate header of the common request message */ + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, + (uint8_t)dcCmdId, + cmnRequestFlags, + cmdFlags); + } + + if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { + dcCmdId = + (icp_qat_fw_la_cmd_id_t)(ICP_QAT_FW_COMP_CMD_DECOMPRESS); + pReqCache = &(pSessionDesc->reqCacheDecomp); + pReqCache->comp_pars.req_par_flags = rpCmdFlags; + pReqCache->comp_pars.crc.legacy.initial_adler = 1; + pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; + + /* Populate header of the common request message */ + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, + (uint8_t)dcCmdId, + cmnRequestFlags, + cmdFlags); + } + + return status; +} + +CpaStatus +cpaDcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)insHandle; + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + return dcInitSession(insHandle, + pSessionHandle, + pSessionData, + pContextBuffer, + callbackFn); +} + +CpaStatus +cpaDcResetSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U numPendingStateless = 0; + Cpa64U numPendingStateful = 0; + icp_comms_trans_handle trans_handle = NULL; + LAC_CHECK_NULL_PARAM(pSessionHandle); + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + insHandle = dcInstance; + } else { + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + } + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + /* Check if SAL is running otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + if (CPA_TRUE == pSessionDesc->isDcDp) { + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_tx; + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* Process the remaining messages on the ring */ + SalQatMsg_updateQueueTail(trans_handle); + QAT_UTILS_LOG( + "There are remaining messages on the ring\n"); + return CPA_STATUS_RETRY; + } + + /* Check if there are stateless pending requests */ + if (0 != pSessionDesc->pendingDpStatelessCbCount) { + QAT_UTILS_LOG( + "There are %llu stateless DP requests pending.\n", + (unsigned long long) + pSessionDesc->pendingDpStatelessCbCount); + return CPA_STATUS_RETRY; + } + } else { + numPendingStateless = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); + numPendingStateful = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); + /* Check if there are stateless pending requests */ + if (0 != numPendingStateless) { + QAT_UTILS_LOG( + "There are %llu stateless requests pending.\n", + (unsigned long long)numPendingStateless); + return CPA_STATUS_RETRY; + } + /* Check if there are stateful pending requests */ + if (0 != numPendingStateful) { + QAT_UTILS_LOG( + "There are %llu stateful requests pending.\n", + (unsigned long long)numPendingStateful); + return CPA_STATUS_RETRY; + } + + /* Reset pSessionDesc */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + pSessionDesc->cumulativeConsumedBytes = 0; + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + } + /* Reset the pending callback counters */ + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); + pSessionDesc->pendingDpStatelessCbCount = 0; + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, + sizeof(pSessionDesc->stateRegistersComp)); + LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, + sizeof(pSessionDesc->stateRegistersDecomp)); + } + return status; +} + +CpaStatus +cpaDcRemoveSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U numPendingStateless = 0; + Cpa64U numPendingStateful = 0; + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + insHandle = dcInstance; + } else { + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is running otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + trans_handle = ((sal_compression_service_t *)insHandle) + ->trans_handle_compression_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* Process the remaining messages on the ring */ + SalQatMsg_updateQueueTail(trans_handle); + QAT_UTILS_LOG( + "There are remaining messages on the ring.\n"); + return CPA_STATUS_RETRY; + } + + /* Check if there are stateless pending requests */ + if (0 != pSessionDesc->pendingDpStatelessCbCount) { + QAT_UTILS_LOG( + "There are %llu stateless DP requests pending.\n", + (unsigned long long) + pSessionDesc->pendingDpStatelessCbCount); + return CPA_STATUS_RETRY; + } + } else { + numPendingStateless = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); + numPendingStateful = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); + + /* Check if there are stateless pending requests */ + if (0 != numPendingStateless) { + QAT_UTILS_LOG( + "There are %llu stateless requests pending.\n", + (unsigned long long)numPendingStateless); + status = CPA_STATUS_RETRY; + } + + /* Check if there are stateful pending requests */ + if (0 != numPendingStateful) { + QAT_UTILS_LOG( + "There are %llu stateful requests pending.\n", + (unsigned long long)numPendingStateful); + status = CPA_STATUS_RETRY; + } + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_STATUS_SUCCESS == status)) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK_DESTROY( + &(pSessionDesc->sessionLock))) { + QAT_UTILS_LOG( + "Failed to destory session lock.\n"); + } + } + } + + return status; +} + +CpaStatus +dcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + /* Check parameters */ + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionData); + LAC_CHECK_NULL_PARAM(pSessionSize); + + if (dcCheckSessionData(pSessionData, insHandle) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + + /* Get session size for session data */ + *pSessionSize = sizeof(dc_session_desc_t) + LAC_64BYTE_ALIGNMENT + + sizeof(LAC_ARCH_UINT); + + if (NULL != pContextSize) { + status = + dcGetContextSize(insHandle, pSessionData, pContextSize); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Unable to get the context size of the session.\n"); + return CPA_STATUS_FAIL; + } + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize) +{ + + LAC_CHECK_NULL_PARAM(pContextSize); + + return dcGetSessionSize(dcInstance, + pSessionData, + pSessionSize, + pContextSize); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_stats.c b/sys/dev/qat/qat_api/common/compression/dc_stats.c new file mode 100644 index 00000000000..bcd3d61cb3c --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_stats.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_stats.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression stats operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_mem_pools.h" +#include "sal_service_state.h" +#include "sal_types_compression.h" +#include "dc_stats.h" + +CpaStatus +dcStatsInit(sal_compression_service_t *pService) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + pService->pCompStatsArr = + LAC_OS_MALLOC(COMPRESSION_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (pService->pCompStatsArr == NULL) { + status = CPA_STATUS_RESOURCE; + } + + if (CPA_STATUS_SUCCESS == status) { + COMPRESSION_STATS_RESET(pService); + } + + return status; +} + +void +dcStatsFree(sal_compression_service_t *pService) +{ + if (NULL != pService->pCompStatsArr) { + LAC_OS_FREE(pService->pCompStatsArr); + } +} + +CpaStatus +cpaDcGetStats(CpaInstanceHandle dcInstance, CpaDcStats *pStatistics) +{ + sal_compression_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pStatistics); + SAL_RUNNING_CHECK(insHandle); + + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + /* Retrieves the statistics for compression */ + COMPRESSION_STATS_GET(pStatistics, pService); + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c b/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c new file mode 100644 index 00000000000..6b3735b4051 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_sal_dc_err.c + * + * @defgroup SalCommon + * + * @ingroup SalCommon + * + *****************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ +#include "cpa.h" +#include "icp_sal.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_error_counter.h" + +Cpa64U +icp_sal_get_dc_error(Cpa8S dcError) +{ + return getDcErrorCounter(dcError); +} diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h b/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h new file mode 100644 index 00000000000..0a6ef719170 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_datapath.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression datapath parameters. + * + ******************* + * **********************************************************/ +#ifndef DC_DATAPATH_H_ +#define DC_DATAPATH_H_ + +#define LAC_QAT_DC_REQ_SZ_LW 32 +#define LAC_QAT_DC_RESP_SZ_LW 8 + +/* Restriction on the source buffer size for compression due to the firmware + * processing */ +#define DC_SRC_BUFFER_MIN_SIZE (15) + +/* Restriction on the destination buffer size for compression due to + * the management of skid buffers in the firmware */ +#define DC_DEST_BUFFER_DYN_MIN_SIZE (128) +#define DC_DEST_BUFFER_STA_MIN_SIZE (64) +/* C62x and C3xxx pcie rev0 devices require an additional 32bytes */ +#define DC_DEST_BUFFER_STA_ADDITIONAL_SIZE (32) + +/* C4xxx device only requires 47 bytes */ +#define DC_DEST_BUFFER_MIN_SIZE (47) + +/* Minimum destination buffer size for decompression */ +#define DC_DEST_BUFFER_DEC_MIN_SIZE (1) + +/* Restriction on the source and destination buffer sizes for compression due + * to the firmware taking 32 bits parameters. The max size is 2^32-1 */ +#define DC_BUFFER_MAX_SIZE (0xFFFFFFFF) + +/* DC Source & Destination buffer type (FLAT/SGL) */ +#define DC_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL +#define DC_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT + +/* Offset to first byte of Input Byte Counter (IBC) in state register */ +#define DC_STATE_IBC_OFFSET (8) +/* Size in bytes of input byte counter (IBC) in state register */ +#define DC_IBC_SIZE_IN_BYTES (4) + +/* Offset to first byte to CRC32 in state register */ +#define DC_STATE_CRC32_OFFSET (40) +/* Offset to first byte to output CRC32 in state register */ +#define DC_STATE_OUTPUT_CRC32_OFFSET (48) +/* Offset to first byte to input CRC32 in state register */ +#define DC_STATE_INPUT_CRC32_OFFSET (52) + +/* Offset to first byte of ADLER32 in state register */ +#define DC_STATE_ADLER32_OFFSET (48) + +/* 8 bit mask value */ +#define DC_8_BIT_MASK (0xff) + +/* 8 bit shift position */ +#define DC_8_BIT_SHIFT_POS (8) + +/* Size in bytes of checksum */ +#define DC_CHECKSUM_SIZE_IN_BYTES (4) + +/* Mask used to set the most significant bit to zero */ +#define DC_STATE_REGISTER_ZERO_MSB_MASK (0x7F) + +/* Mask used to keep only the most significant bit and set the others to zero */ +#define DC_STATE_REGISTER_KEEP_MSB_MASK (0x80) + +/* Compression state register word containing the parity bit */ +#define DC_STATE_REGISTER_PARITY_BIT_WORD (5) + +/* Location of the parity bit within the compression state register word */ +#define DC_STATE_REGISTER_PARITY_BIT (7) + +/* size which needs to be reserved before the results field to + * align the results field with the API struct */ +#define DC_API_ALIGNMENT_OFFSET (offsetof(CpaDcDpOpData, results)) + +/* Mask used to check the CompressAndVerify capability bit */ +#define DC_CNV_EXTENDED_CAPABILITY (0x01) + +/* Mask used to check the CompressAndVerifyAndRecover capability bit */ +#define DC_CNVNR_EXTENDED_CAPABILITY (0x100) + +/* Default values for CNV integrity checks, + * those are used to inform hardware of specifying CRC parameters to be used + * when calculating CRCs */ +#define DC_CRC_POLY_DEFAULT 0x04c11db7 +#define DC_XOR_FLAGS_DEFAULT 0xe0000 +#define DC_XOR_OUT_DEFAULT 0xffffffff +#define DC_INVALID_CRC 0x0 + +/** +******************************************************************************* +* @ingroup cpaDc Data Compression +* Compression cookie +* @description +* This cookie stores information for a particular compression perform op. +* This includes various user-supplied parameters for the operation which +* will be needed in our callback function. +* A pointer to this cookie is stored in the opaque data field of the QAT +* message so that it can be accessed in the asynchronous callback. +* @note +* The order of the parameters within this structure is important. It needs +* to match the order of the parameters in CpaDcDpOpData up to the +* pSessionHandle. This allows the correct processing of the callback. +*****************************************************************************/ +typedef struct dc_compression_cookie_s { + Cpa8U dcReqParamsBuffer[DC_API_ALIGNMENT_OFFSET]; + /**< Memory block - was previously reserved for request parameters. + * Now size maintained so following members align with API struct, + * but no longer used for request parameters */ + CpaDcRqResults reserved; + /**< This is reserved for results to correctly align the structure + * to match the one from the data plane API */ + CpaInstanceHandle dcInstance; + /**< Compression instance handle */ + CpaDcSessionHandle pSessionHandle; + /**< Pointer to the session handle */ + icp_qat_fw_comp_req_t request; + /**< Compression request */ + void *callbackTag; + /**< Opaque data supplied by the client */ + dc_session_desc_t *pSessionDesc; + /**< Pointer to the session descriptor */ + CpaDcFlush flushFlag; + /**< Flush flag */ + CpaDcOpData *pDcOpData; + /**< struct containing flags and CRC related data for this session */ + CpaDcRqResults *pResults; + /**< Pointer to result buffer holding consumed and produced data */ + Cpa32U srcTotalDataLenInBytes; + /**< Total length of the source data */ + Cpa32U dstTotalDataLenInBytes; + /**< Total length of the destination data */ + dc_request_dir_t compDecomp; + /**< Used to know whether the request is compression or decompression. + * Useful when defining the session as combined */ + CpaBufferList *pUserSrcBuff; + /**< virtual userspace ptr to source SGL */ + CpaBufferList *pUserDestBuff; + /**< virtual userspace ptr to destination SGL */ +} dc_compression_cookie_t; + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Callback function called for compression and decompression requests in + * asynchronous mode + * + * @description + * Called to process compression and decompression response messages. This + * callback will check for errors, update the statistics and will call the + * user callback + * + * @param[in] pRespMsg Response message + * + *****************************************************************************/ +void dcCompression_ProcessCallback(void *pRespMsg); + +/** +***************************************************************************** +* @ingroup Dc_DataCompression +* Describes CNV and CNVNR modes +* +* @description +* This enum is used to indicate the CNV modes. +* +*****************************************************************************/ +typedef enum dc_cnv_mode_s { + DC_NO_CNV = 0, + /* CNV = FALSE, CNVNR = FALSE */ + DC_CNV, + /* CNV = TRUE, CNVNR = FALSE */ + DC_CNVNR, + /* CNV = TRUE, CNVNR = TRUE */ +} dc_cnv_mode_t; + +#endif /* DC_DATAPATH_H_ */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h b/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h new file mode 100644 index 00000000000..dd1189fd970 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_error_counter.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression Error Counter parameters. + * + *****************************************************************************/ +#ifndef DC_ERROR_COUNTER_H +#define DC_ERROR_COUNTER_H + +#include "cpa_types.h" +#include "cpa_dc.h" + +#define MAX_DC_ERROR_TYPE 20 + +void dcErrorLog(CpaDcReqStatus dcError); +Cpa64U getDcErrorCounter(CpaDcReqStatus dcError); + +#endif /* DC_ERROR_COUNTER_H */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h b/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h new file mode 100644 index 00000000000..0ec2cc6f3f1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_header_footer.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression header and footer parameters. + * + *****************************************************************************/ +#ifndef DC_HEADER_FOOTER_H_ +#define DC_HEADER_FOOTER_H_ + +/* Header and footer sizes for Zlib and Gzip */ +#define DC_ZLIB_HEADER_SIZE (2) +#define DC_GZIP_HEADER_SIZE (10) +#define DC_ZLIB_FOOTER_SIZE (4) +#define DC_GZIP_FOOTER_SIZE (8) + +/* Values used to build the headers for Zlib and Gzip */ +#define DC_GZIP_ID1 (0x1f) +#define DC_GZIP_ID2 (0x8b) +#define DC_GZIP_FILESYSTYPE (0x03) +#define DC_ZLIB_WINDOWSIZE_OFFSET (4) +#define DC_ZLIB_FLEVEL_OFFSET (6) +#define DC_ZLIB_HEADER_OFFSET (31) + +/* Compression level for Zlib */ +#define DC_ZLIB_LEVEL_0 (0) +#define DC_ZLIB_LEVEL_1 (1) +#define DC_ZLIB_LEVEL_2 (2) +#define DC_ZLIB_LEVEL_3 (3) + +/* CM parameter for Zlib */ +#define DC_ZLIB_CM_DEFLATE (8) + +/* Type of Gzip compression */ +#define DC_GZIP_FAST_COMP (4) +#define DC_GZIP_MAX_COMP (2) + +#endif /* DC_HEADER_FOOTER_H_ */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_session.h b/sys/dev/qat/qat_api/common/compression/include/dc_session.h new file mode 100644 index 00000000000..5a4961fadd6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_session.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_session.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression session parameters. + * + *****************************************************************************/ +#ifndef DC_SESSION_H +#define DC_SESSION_H + +#include "cpa_dc_dp.h" +#include "icp_qat_fw_comp.h" +#include "sal_qat_cmn_msg.h" + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 6 compression slices */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES (12) + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 10 max compression slices */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_10COMP_SLICES (20) + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 24 max compression slices and 32 MEs */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_24COMP_SLICES (64) + +/* Maximum size of the state registers 64 bytes */ +#define DC_QAT_STATE_REGISTERS_MAX_SIZE (64) + +/* Size of the history window. + * Base 2 logarithm of maximum window size minus 8 */ +#define DC_8K_WINDOW_SIZE (5) +#define DC_16K_WINDOW_SIZE (6) +#define DC_32K_WINDOW_SIZE (7) + +/* Context size */ +#define DC_DEFLATE_MAX_CONTEXT_SIZE (49152) +#define DC_INFLATE_CONTEXT_SIZE (36864) + +#define DC_DEFLATE_EH_MAX_CONTEXT_SIZE (65536) +#define DC_DEFLATE_EH_MIN_CONTEXT_SIZE (49152) +#define DC_INFLATE_EH_CONTEXT_SIZE (34032) + +/* Retrieve the session descriptor pointer from the session context structure + * that the user allocates. The pointer to the internally realigned address + * is stored at the start of the session context that the user allocates */ +#define DC_SESSION_DESC_FROM_CTX_GET(pSession) \ + (dc_session_desc_t *)(*(LAC_ARCH_UINT *)pSession) + +/* Maximum size for the compression part of the content descriptor */ +#define DC_QAT_COMP_CONTENT_DESC_SIZE sizeof(icp_qat_fw_comp_cd_hdr_t) + +/* Maximum size for the translator part of the content descriptor */ +#define DC_QAT_TRANS_CONTENT_DESC_SIZE \ + (sizeof(icp_qat_fw_xlt_cd_hdr_t) + DC_QAT_MAX_TRANS_SETUP_BLK_SZ) + +/* Maximum size of the decompression content descriptor */ +#define DC_QAT_CONTENT_DESC_DECOMP_MAX_SIZE \ + LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE, \ + (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) + +/* Maximum size of the compression content descriptor */ +#define DC_QAT_CONTENT_DESC_COMP_MAX_SIZE \ + LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE + \ + DC_QAT_TRANS_CONTENT_DESC_SIZE, \ + (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) + +/* Direction of the request */ +typedef enum dc_request_dir_e { + DC_COMPRESSION_REQUEST = 1, + DC_DECOMPRESSION_REQUEST +} dc_request_dir_t; + +/* Type of the compression request */ +typedef enum dc_request_type_e { + DC_REQUEST_FIRST = 1, + DC_REQUEST_SUBSEQUENT +} dc_request_type_t; + +typedef enum dc_block_type_e { + DC_CLEARTEXT_TYPE = 0, + DC_STATIC_TYPE, + DC_DYNAMIC_TYPE +} dc_block_type_t; + +/* Internal data structure supporting end to end data integrity checks. */ +typedef struct dc_integrity_crc_fw_s { + Cpa32U crc32; + /* CRC32 checksum returned for compressed data */ + Cpa32U adler32; + /* ADLER32 checksum returned for compressed data */ + Cpa32U oCrc32Cpr; + /* CRC32 checksum returned for data output by compression accelerator */ + Cpa32U iCrc32Cpr; + /* CRC32 checksum returned for input data to compression accelerator */ + Cpa32U oCrc32Xlt; + /* CRC32 checksum returned for data output by translator accelerator */ + Cpa32U iCrc32Xlt; + /* CRC32 checksum returned for input data to translator accelerator */ + Cpa32U xorFlags; + /* Initialise transactor pCRC controls in state register */ + Cpa32U crcPoly; + /* CRC32 polynomial used by hardware */ + Cpa32U xorOut; + /* CRC32 from XOR stage (Input CRC is xor'ed with value in the state) */ + Cpa32U deflateBlockType; + /* Bit 1 - Bit 0 + * 0 0 -> RAW DATA + Deflate header. + * This will not produced any CRC check because + * the output will not come from the slices. + * It will be a simple copy from input to output + * buffers list. + * 0 1 -> Static deflate block type + * 1 0 -> Dynamic deflate block type + * 1 1 -> Invalid type */ +} dc_integrity_crc_fw_t; + +typedef struct dc_sw_checksums_s { + Cpa32U swCrcI; + Cpa32U swCrcO; +} dc_sw_checksums_t; + +/* Session descriptor structure for compression */ +typedef struct dc_session_desc_s { + Cpa8U stateRegistersComp[DC_QAT_STATE_REGISTERS_MAX_SIZE]; + /**< State registers for compression */ + Cpa8U stateRegistersDecomp[DC_QAT_STATE_REGISTERS_MAX_SIZE]; + /**< State registers for decompression */ + icp_qat_fw_comp_req_t reqCacheComp; + /**< Cache as much as possible of the compression request in a pre-built + * request */ + icp_qat_fw_comp_req_t reqCacheDecomp; + /**< Cache as much as possible of the decompression request in a + * pre-built + * request */ + dc_request_type_t requestType; + /**< Type of the compression request. As stateful mode do not support + * more + * than one in-flight request there is no need to use spinlocks */ + dc_request_type_t previousRequestType; + /**< Type of the previous compression request. Used in cases where there + * the + * stateful operation needs to be resubmitted */ + CpaDcHuffType huffType; + /**< Huffman tree type */ + CpaDcCompType compType; + /**< Compression type */ + CpaDcChecksum checksumType; + /**< Type of checksum */ + CpaDcAutoSelectBest autoSelectBestHuffmanTree; + /**< Indicates if the implementation selects the best Huffman encoding + */ + CpaDcSessionDir sessDirection; + /**< Session direction */ + CpaDcSessionState sessState; + /**< Session state */ + Cpa32U deflateWindowSize; + /**< Window size */ + CpaDcCompLvl compLevel; + /**< Compression level */ + CpaDcCallbackFn pCompressionCb; + /**< Callback function defined for the traditional compression session + */ + QatUtilsAtomic pendingStatelessCbCount; + /**< Keeps track of number of pending requests on stateless session */ + QatUtilsAtomic pendingStatefulCbCount; + /**< Keeps track of number of pending requests on stateful session */ + Cpa64U pendingDpStatelessCbCount; + /**< Keeps track of number of data plane pending requests on stateless + * session */ + struct mtx sessionLock; + /**< Lock used to provide exclusive access for number of stateful + * in-flight + * requests update */ + CpaBoolean isDcDp; + /**< Indicates if the data plane API is used */ + Cpa32U minContextSize; + /**< Indicates the minimum size required to allocate the context buffer + */ + CpaBufferList *pContextBuffer; + /**< Context buffer */ + Cpa32U historyBuffSize; + /**< Size of the history buffer */ + Cpa64U cumulativeConsumedBytes; + /**< Cumulative amount of consumed bytes. Used to build the footer in + * the + * stateful case */ + Cpa32U previousChecksum; + /**< Save the previous value of the checksum. Used to process zero byte + * stateful compression or decompression requests */ + CpaBoolean isSopForCompressionProcessed; + /**< Indicates whether a Compression Request is received in this session + */ + CpaBoolean isSopForDecompressionProcessed; + /**< Indicates whether a Decompression Request is received in this + * session + */ + /**< Data integrity table */ + dc_integrity_crc_fw_t dataIntegrityCrcs; + /**< Physical address of Data integrity buffer */ + CpaPhysicalAddr physDataIntegrityCrcs; + /* Seed checksums structure used to calculate software calculated + * checksums. + */ + dc_sw_checksums_t seedSwCrc; + /* Driver calculated integrity software CRC */ + dc_sw_checksums_t integritySwCrc; +} dc_session_desc_t; + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Initialise a compression session + * + * @description + * This function will initialise a compression session + * + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in,out] pSessionHandle Pointer to a session handle + * @param[in,out] pSessionData Pointer to a user instantiated structure + * containing session data + * @param[in] pContextBuffer Pointer to context buffer + * + * @param[in] callbackFn For synchronous operation this callback + * shall be a null pointer + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * @retval CPA_STATUS_RESOURCE Error related to system resources + *****************************************************************************/ +CpaStatus dcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn); + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Get the size of the memory required to hold the session information + * + * @description + * This function will get the size of the memory required to hold the + * session information + * + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in] pSessionData Pointer to a user instantiated structure + * containing session data + * @param[out] pSessionSize On return, this parameter will be the size + * of the memory that will be + * required by cpaDcInitSession() for session + * data. + * @param[out] pContextSize On return, this parameter will be the size + * of the memory that will be required + * for context data. Context data is + * save/restore data including history and + * any implementation specific data that is + * required for a save/restore operation. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + *****************************************************************************/ +CpaStatus dcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize); + +#endif /* DC_SESSION_H */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_stats.h b/sys/dev/qat/qat_api/common/compression/include/dc_stats.h new file mode 100644 index 00000000000..357be30107b --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_stats.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_stats.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression stats parameters. + * + *****************************************************************************/ +#ifndef DC_STATS_H_ +#define DC_STATS_H_ + +/* Number of Compression statistics */ +#define COMPRESSION_NUM_STATS (sizeof(CpaDcStats) / sizeof(Cpa64U)) + +#define COMPRESSION_STAT_INC(statistic, pService) \ + do { \ + if (CPA_TRUE == \ + pService->generic_service_info.stats->bDcStatsEnabled) { \ + qatUtilsAtomicInc( \ + &pService->pCompStatsArr[offsetof(CpaDcStats, \ + statistic) / \ + sizeof(Cpa64U)]); \ + } \ + } while (0) + +/* Macro to get all Compression stats (from internal array of atomics) */ +#define COMPRESSION_STATS_GET(compStats, pService) \ + do { \ + int i; \ + for (i = 0; i < COMPRESSION_NUM_STATS; i++) { \ + ((Cpa64U *)compStats)[i] = \ + qatUtilsAtomicGet(&pService->pCompStatsArr[i]); \ + } \ + } while (0) + +/* Macro to reset all Compression stats */ +#define COMPRESSION_STATS_RESET(pService) \ + do { \ + int i; \ + for (i = 0; i < COMPRESSION_NUM_STATS; i++) { \ + qatUtilsAtomicSet(0, &pService->pCompStatsArr[i]); \ + } \ + } while (0) + +/** +******************************************************************************* +* @ingroup Dc_DataCompression +* Initialises the compression stats +* +* @description +* This function allocates and initialises the stats array to 0 +* +* @param[in] pService Pointer to a compression service structure +* +* @retval CPA_STATUS_SUCCESS initialisation successful +* @retval CPA_STATUS_RESOURCE array allocation failed +* +*****************************************************************************/ +CpaStatus dcStatsInit(sal_compression_service_t *pService); + +/** +******************************************************************************* +* @ingroup Dc_DataCompression +* Frees the compression stats +* +* @description +* This function frees the stats array +* +* @param[in] pService Pointer to a compression service structure +* +* @retval None +* +*****************************************************************************/ +void dcStatsFree(sal_compression_service_t *pService); + +#endif /* DC_STATS_H_ */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h new file mode 100644 index 00000000000..6ae3c51e776 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h @@ -0,0 +1,622 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_session.h + * + * @defgroup LacSym_Session Session + * + * @ingroup LacSym + * + * Definition of symmetric session descriptor structure + * + * @lld_start + * + * @lld_overview + * A session is required for each symmetric operation. The session descriptor + * holds information about the session from when the session is initialised to + * when the session is removed. The session descriptor is used in the + * subsequent perform operations in the paths for both sending the request and + * receiving the response. The session descriptor and any other state + * information required for processing responses from the QAT are stored in an + * internal cookie. A pointer to this cookie is stored in the opaque data + * field of the QAT request. + * + * The user allocates the memory for the session using the size returned from + * \ref cpaCySymSessionCtxGetSize(). Internally this memory is re-aligned on a + * 64 byte boundary for use by the QAT engine. The aligned pointer is saved in + * the first bytes (size of void *) of the session memory. This address + * is then dereferenced in subsequent performs to get access to the session + * descriptor. + * + * LAC Session Init\n The session descriptor is re-aligned and + * populated. This includes populating the content descriptor which contains + * the hardware setup for the QAT engine. The content descriptor is a read + * only structure after session init and a pointer to it is sent to the QAT + * for each perform operation. + * + * LAC Perform \n + * The address for the session descriptor is got by dereferencing the first + * bytes of the session memory (size of void *). For each successful + * request put on the ring, the pendingCbCount for the session is incremented. + * + * LAC Callback \n + * For each successful response the pendingCbCount for the session is + * decremented. See \ref LacSymCb_ProcessCallbackInternal() + * + * LAC Session Remove \n + * The address for the session descriptor is got by dereferencing the first + * bytes of the session memory (size of void *). + * The pendingCbCount for the session is checked to see if it is 0. If it is + * non 0 then there are requests in flight. An error is returned to the user. + * + * Concurrency\n + * A reference count is used to prevent the descriptor being removed + * while there are requests in flight. + * + * Reference Count\n + * - The perform funcion increments the reference count for the session. + * - The callback function decrements the reference count for the session. + * - The Remove function checks the reference count to ensure that it is 0. + * + * @lld_dependencies + * - \ref LacMem "Memory" - Inline memory functions + * - QatUtils: logging, locking & virt to phys translations. + * + * @lld_initialisation + * + * @lld_module_algorithms + * + * @lld_process_context + * + * @lld_end + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_SESSION_H +#define LAC_SYM_SESSION_H + +/* + * Common alignment attributes to ensure + * hashStatePrefixBuffer is 64-byte aligned + */ +#define ALIGN_START(x) +#define ALIGN_END(x) __attribute__((__aligned__(x))) +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "icp_accel_devices.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "sal_qat_cmn_msg.h" +#include "lac_sym_cipher_defs.h" +#include "lac_sym.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_hash.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +/** +******************************************************************************* +* @ingroup LacSym_Session +* Symmetric session descriptor +* @description +* This structure stores information about a session +* Note: struct types lac_session_d1_s and lac_session_d2_s are subsets of +* this structure. Elements in all three should retain the same order +* Only this structure is used in the session init call. The other two are +* for determining the size of memory to allocate. +* The comments section of each of the other two structures below show +* the conditions that determine which session context memory size to use. +*****************************************************************************/ +typedef struct lac_session_desc_s { + Cpa8U contentDescriptor[LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE]; + /**< QAT Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U contentDescriptorOptimised[LAC_SYM_OPTIMISED_CD_SIZE]; + /**< QAT Optimised Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaCySymOp symOperation; + /**< type of command to be performed */ + sal_qat_content_desc_info_t contentDescInfo; + /**< info on the content descriptor */ + sal_qat_content_desc_info_t contentDescOptimisedInfo; + /**< info on the optimised content descriptor */ + icp_qat_fw_la_cmd_id_t laCmdId; + /** + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_alg_chain.h + * + * @defgroup LacAlgChain Algorithm Chaining + * + * @ingroup LacSym + * + * Interfaces exposed by the Algorithm Chaining Component + * + * @lld_start + * + * @lld_overview + * This is the LAC Algorithm-Chaining feature component. This component + * implements session registration and cleanup functions, and a perform + * function. Statistics are maintained to track requests issued and completed, + * errors incurred, and authentication verification failures. For each + * function the parameters supplied by the client are checked, and then the + * function proceeds if all the parameters are valid. This component also + * incorporates support for Authenticated-Encryption (CCM and GCM) which + * essentially comprises of a cipher operation and a hash operation combined. + * + * This component can combine a cipher operation with a hash operation or just + * simply create a hash only or cipher only operation and is called from the + * LAC Symmetric API component. In turn it calls the LAC Cipher, LAC Hash, and + * LAC Symmetric QAT components. The goal here is to duplicate as little code + * as possible from the Cipher and Hash components. + * + * The cipher and hash operations can be combined in either order, i.e. cipher + * first then hash or hash first then cipher. The client specifies this via + * the algChainOrder field in the session context. This ordering choice is + * stored as part of the session descriptor, so that it is known when a + * perform request is issued. In the case of Authenticated-Encryption, the + * ordering is an implicit part of the CCM or GCM protocol. + * + * When building a content descriptor, as part of session registration, this + * component asks the Cipher and Hash components to build their respective + * parts of the session descriptor. The key aspect here is to provide the + * correct offsets to the Cipher and Hash components for where in the content + * descriptor to write their Config and Hardware Setup blocks. Also the + * Config block in each case must specify the appropriate next slice. + * + * When building request parameters, as part of a perform operation, this + * component asks the Cipher and Hash components to build their respective + * parts of the request parameters block. Again the key aspect here is to + * provide the correct offsets to the Cipher and Hash components for where in + * the request parameters block to write their parameters. Also the request + * parameters block in each case must specify the appropriate next slice. + * + * Parameter checking for session registration and for operation perform is + * mostly delegated to the Cipher and Hash components. There are a few + * extra checks that this component must perform: check the algChainOrder + * parameter, ensure that CCM/GCM are specified for hash/cipher algorithms + * as appropriate, and ensure that requests are for full packets (partial + * packets are not supported for Algorithm-Chaining). + * + * The perform operation allocates a cookie to capture information required + * in the request callback. This cookie is then freed in the callback. + * + * @lld_dependencies + * - \ref LacCipher "Cipher" : For taking care of the cipher aspects of + * session registration and operation perform + * - \ref LacHash "Hash" : For taking care of the hash aspects of session + * registration and operation perform + * - \ref LacSymCommon "Symmetric Common" : statistics. + * - \ref LacSymQat "Symmetric QAT": To build the QAT request message, + * request param structure, and populate the content descriptor. Also + * for registering a callback function to process the QAT response. + * - \ref QatComms "QAT Comms" : For sending messages to the QAT, and for + * setting the response callback + * - \ref LacMem "Mem" : For memory allocation and freeing, virtual/physical + * address translation, and translating between scalar and pointer types + * - OSAL : For atomics and locking + * + * @lld_module_algorithms + * This component builds up a chain of slices at session init time + * and stores it in the session descriptor. This is used for building up the + * content descriptor at session init time and the request parameters structure + * in the perform operation. + * + * The offsets for the first slice are updated so that the second slice adds + * its configuration information after that of the first slice. The first + * slice also configures the next slice appropriately. + * + * This component is very much hard-coded to just support cipher+hash or + * hash+cipher. It should be quite possible to extend this idea to support + * an arbitrary chain of commands, by building up a command chain that can + * be traversed in order to build up the appropriate configuration for the + * QAT. This notion should be looked at in the future if other forms of + * Algorithm-Chaining are desired. + * + * @lld_process_context + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_ALG_CHAIN_H +#define LAC_SYM_ALG_CHAIN_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "lac_session.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +/* Macro for checking if zero length buffer are supported + * only for cipher is AES-GCM and hash are AES-GCM/AES-GMAC */ +#define IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipherAlgo, hashAlgo) \ + (CPA_CY_SYM_CIPHER_AES_GCM == cipherAlgo && \ + (CPA_CY_SYM_HASH_AES_GMAC == hashAlgo || \ + CPA_CY_SYM_HASH_AES_GCM == hashAlgo)) + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function registers a session for an Algorithm-Chaining operation. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* registered. +* +* @param[in] instanceHandle Instance Handle +* +* @param[in] pSessionCtx Pointer to session context which contains +* parameters which are static for a given +* cryptographic session such as operation type, +* mechanisms, and keys for cipher and/or digest +* operations. +* @param[out] pSessionDesc Pointer to session descriptor +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +* @see cpaCySymInitSession() +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionInit(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionCtx, + lac_session_desc_t *pSessionDesc); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* Data path function for the Algorithm-Chaining component +* +* @description +* This function gets called from cpaCySymPerformOp() which is the +* symmetric LAC API function. It is the data path function for the +* Algorithm-Chaining component. It does the parameter checking on the +* client supplied parameters and if the parameters are valid, the +* operation is performed and a request sent to the QAT, otherwise an +* error is returned to the client. +* +* @param[in] instanceHandle Instance Handle +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCallbackTag The application's context for this call +* @param[in] pOpData Pointer to a structure containing request +* parameters. The client code allocates the memory for +* this structure. This component takes ownership of +* the memory until it is returned in the callback. +* +* @param[in] pSrcBuffer Source Buffer List +* @param[out] pDstBuffer Destination Buffer List +* @param[out] pVerifyResult Verify Result +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resource. +* +* @see cpaCySymPerformOp() +* +*****************************************************************************/ +CpaStatus LacAlgChain_Perform(const CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + void *pCallbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update cipher key, as specified in provided +* input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCipherKey Pointer to new cipher key. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionCipherKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pCipherKey); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update authentication key, as specified in +* provided input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCipherKey Pointer to new authentication key. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionAuthKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pAuthKey); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update AAD length as specified in provided +* input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] newAADLength New AAD length. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionAADUpdate(lac_session_desc_t *pSessionDesc, + Cpa32U newAADLength); + +#endif /* LAC_SYM_ALG_CHAIN_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h new file mode 100644 index 00000000000..76e5e53c38a --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_auth_enc.h + * + * @defgroup LacAuthEnc Authenticated Encryption + * + * @ingroup LacSym + * + * @description + * Authenticated encryption specific functionality. + * For CCM related code NIST SP 800-38C is followed. + * For GCM related code NIST SP 800-38D is followed. + * + ***************************************************************************/ +#ifndef LAC_SYM_AUTH_ENC_H_ +#define LAC_SYM_AUTH_ENC_H_ + +/* This define for CCM describes constant sum of n and q */ +#define LAC_ALG_CHAIN_CCM_NQ_CONST 15 + +/* These defines for CCM describe maximum and minimum + * length of nonce in bytes*/ +#define LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX 13 +#define LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN 7 + +/** + * @ingroup LacAuthEnc + * This function applies any necessary padding to additional authentication data + * pointed by pAdditionalAuthData field of pOpData as described in + * NIST SP 800-38D + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in,out] pAdditionalAuthData Pointer to AAD + * + * @retval CPA_STATUS_SUCCESS Operation finished successfully + * + * @pre pAdditionalAuthData has been param checked + * + */ +void LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData); + +/** + * @ingroup LacAuthEnc + * This function prepares param checks iv and aad for CCM + * + * @param[in,out] pAdditionalAuthData Pointer to AAD + * @param[in,out] pIv Pointer to IV + * @param[in] messageLenToCipherInBytes Size of the message to cipher + * @param[in] ivLenInBytes Size of the IV + * + * @retval CPA_STATUS_SUCCESS Operation finished successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed + * + */ +CpaStatus LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes); + +/** + * @ingroup LacAuthEnc + * This function prepares Ctr0 and B0-Bn blocks for CCM algorithm as described + * in NIST SP 800-38C. Ctr0 block is placed in pIv field of pOpData and B0-BN + * blocks are placed in pAdditionalAuthData. + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in,out] pAdditionalAuthData Pointer to AAD + * @param[in,out] pIv Pointer to IV + * @param[in] messageLenToCipherInBytes Size of the message to cipher + * @param[in] ivLenInBytes Size of the IV + * + * @retval none + * + * @pre parameters have been checked using LacSymAlgChain_CheckCCMData() + */ +void LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes); + +#endif /* LAC_SYM_AUTH_ENC_H_ */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h new file mode 100644 index 00000000000..5332f8aab51 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cb.h + * + * @defgroup LacSymCb Symmetric callback functions + * + * @ingroup LacSym + * + * Functions to assist with callback processing for the symmetric component + ***************************************************************************/ + +#ifndef LAC_SYM_CB_H +#define LAC_SYM_CB_H + +/** + ***************************************************************************** + * @ingroup LacSym + * Dequeue pending requests + * @description + * This function is called by a callback function of a blocking + * operation (either a partial packet or a hash precompute operaion) + * in softIRQ context. It dequeues requests for the following reasons: + * 1. All pre-computes that happened when initialising a session + * have completed. Dequeue any requests that were queued on the + * session while waiting for the precompute operations to complete. + * 2. A partial packet request has completed. Dequeue any partials + * that were queued for this session while waiting for a previous + * partial to complete. + * + * @param[in] pSessionDesc Pointer to the session descriptor + * + * @return CpaStatus + * + ****************************************************************************/ +CpaStatus LacSymCb_PendingReqsDequeue(lac_session_desc_t *pSessionDesc); + +/** + ***************************************************************************** + * @ingroup LacSym + * Register symmetric callback funcion handlers + * + * @description + * This function registers the symmetric callback handler functions with + * the main symmetric callback handler function + * + * @return None + * + ****************************************************************************/ +void LacSymCb_CallbacksRegister(void); + +#endif /* LAC_SYM_CB_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h new file mode 100644 index 00000000000..822e9ce03f9 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h @@ -0,0 +1,312 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_cipher.h + * + * @defgroup LacCipher Cipher + * + * @ingroup LacSym + * + * API functions of the cipher component + * + * @lld_start + * @lld_overview + * There is a single \ref icp_LacSym "Symmetric LAC API" for hash, cipher, + * auth encryption and algorithm chaining. This API is implemented by the + * \ref LacSym "Symmetric" module. It demultiplexes calls to this API into + * their basic operation and does some common parameter checking and deals + * with accesses to the session table. + * + * The cipher component supports data encryption/decryption using the AES, DES, + * and Triple-DES cipher algorithms, in ECB, CBC and CTR modes. The ARC4 stream + * cipher algorithm is also supported. Data may be provided as a full packet, + * or as a sequence of partial packets. The result of the operation can be + * written back to the source buffer (in-place) or to a seperate output buffer + * (out-of-place). Data must be encapsulated in ICP buffers. + * + * The cipher component is responsible for implementing the cipher-specific + * functionality for registering and de-registering a session, for the perform + * operation and for processing the QAT responses to cipher requests. Statistics + * are maintained for cipher in the symmetric \ref CpaCySymStats64 "stats" + * structure. This module has been seperated out into two. The cipher QAT module + * deals entirely with QAT data structures. The cipher module itself has minimal + * exposure to the QAT data structures. + * + * @lld_dependencies + * - \ref LacCommon + * - \ref LacSymQat "Symmetric QAT": Hash uses the lookup table provided by + * this module to validate user input. Hash also uses this module to build + * the hash QAT request message, request param structure, populate the + * content descriptor, allocate and populate the hash state prefix buffer. + * Hash also registers its function to process the QAT response with this + * module. + * - OSAL : For memory functions, atomics and locking + * + * @lld_module_algorithms + * In general, all the cipher algorithms supported by this component are + * implemented entirely by the QAT. However, in the case of the ARC4 algorithm, + * it was deemed more efficient to carry out some processing on IA. During + * session registration, an initial state is derived from the base key provided + * by the user, using a simple ARC4 Key Scheduling Algorithm (KSA). Then the + * base key is discarded, but the state is maintained for the duration of the + * session. + * + * The ARC4 key scheduling algorithm (KSA) is specified as follows + * (taken from http://en.wikipedia.org/wiki/RC4_(cipher)): + * \code + * for i from 0 to 255 + * S[i] := i + * endfor + * j := 0 + * for i from 0 to 255 + * j := (j + S[i] + key[i mod keylength]) mod 256 + * swap(S[i],S[j]) + * endfor + * \endcode + * + * On registration of a new ARC4 session, the user provides a base key of any + * length from 1 to 256 bytes. This algorithm produces the initial ARC4 state + * (key matrix + i & j index values) from that base key. This ARC4 state is + * used as input for each ARC4 cipher operation in that session, and is updated + * by the QAT after each operation. The ARC4 state is stored in a session + * descriptor, and it's memory is freed when the session is deregistered. + * + * Block Vs. Stream Ciphers\n + * Block ciphers are treated slightly differently than Stream ciphers by this + * cipher component. Supported stream ciphers consist of AES and + * TripleDES algorithms in CTR mode, and ARC4. The 2 primary differences are: + * - Data buffers for block ciphers are required to be a multiple of the + * block size defined for the algorithm (e.g. 8 bytes for DES). For stream + * ciphers, there is no such restriction. + * - For stream ciphers, decryption is performed by setting the QAT hardware + * to encryption mode. + * + * Memory address alignment of data buffers \n + * The QAT requires that most data buffers are aligned on an 8-byte memory + * address boundary (64-byte boundary for optimum performance). For Cipher, + * this applies to the cipher key buffer passed in the Content Descriptor, + * and the IV/State buffer passed in the Request Parameters block in each + * request. Both of these buffers are provided by the user. It does not + * apply to the cipher source/destination data buffers. + * Alignment of the key buffer is ensured because the key is always copied + * from the user provided buffer into a new (aligned) buffer for the QAT + * (the hardware setup block, which configures the QAT slice). This is done + * once only during session registration, and the user's key buffer can be + * effectively discarded after that. + * The IV/State buffer is provided per-request by the user, so it is recommended + * to the user to provide aligned buffers for optimal performance. In the case + * where an unaligned buffer is provided, a new temporary buffer is allocated + * and the user's IV/State data is copied into this buffer. The aligned buffer + * is then passed to the QAT in the request. In the response callback, if the + * IV was updated by the QAT, the contents are copied back to the user's buffer + * and the temporary buffer is freed. + * + * @lld_process_context + * + * Session Register Sequence Diagram: For ARC4 cipher algorithm + * \msc + * APP [label="Application"], SYM [label="Symmetric LAC"], + * Achain [label="Alg chain"], Cipher, SQAT [label="Symmetric QAT"]; + * + * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", + * URL="\ref cpaCySymInitSession()"] ; + * SYM=>SYM [ label = "LacSymSession_ParamCheck()", + * URL="\ref LacSymSession_ParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_SessionInit()", + * URL="\ref LacAlgChain_SessionInit()"]; + * Achain=>Cipher [ label = "LacCipher_SessionSetupDataCheck()", + * URL="\ref LacCipher_SessionSetupDataCheck()"]; + * Achain<SQAT [ label = "LacSymQat_CipherContentDescPopulate()", + * URL="\ref LacSymQat_CipherContentDescPopulate()"]; + * Achain<SQAT [ label = "LacSymQat_CipherArc4StateInit()", + * URL="\ref LacSymQat_CipherArc4StateInit()"]; + * Achain<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<SYM [ label = "cpaCySymPerformOp()", + * URL="\ref cpaCySymPerformOp()"] ; + * SYM=>SYM [ label = "LacSym_Perform()", + * URL="\ref LacSym_Perform()"]; + * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", + * URL="\ref LacSymPerform_BufferParamCheck()"]; + * SYM<Achain [ label = "LacAlgChain_Perform()", + * URL="\ref LacCipher()"]; + * Achain=>Cipher [ label = "LacCipher_PerformParamCheck()", + * URL="\ref LacCipher_PerformParamCheck()"]; + * Achain<LMP [label="Lac_MemPoolEntryAlloc()", + * URL="\ref Lac_MemPoolEntryAlloc()"]; + * Achain<Cipher [ label = "LacCipher_PerformIvCheckAndAlign()", + * URL="\ref LacCipher_PerformIvCheckAndAlign()"]; + * Achain<SQAT [ label = "LacSymQat_CipherRequestParamsPopulate()", + * URL="\ref LacSymQat_CipherRequestParamsPopulate()"]; + * Achain<BUF [ label = "LacBuffDesc_BufferListDescWrite()", + * URL = "\ref LacBuffDesc_BufferListDescWrite()"]; + * Achain<SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", + * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; + * Achain<SYMQ [ label = "LacSymQueue_RequestSend()", + * URL="\ref LacSymQueue_RequestSend()"]; + * SYMQ=>QATCOMMS [ label = "QatComms_MsgSend()", + * URL="\ref QatComms_MsgSend()"]; + * SYMQ<SYM [ label = "LacSym_PartialPacketStateUpdate()", + * URL="\ref LacSym_PartialPacketStateUpdate()"]; + * SYM<SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYM<QATCOMMS [label ="QatComms_ResponseMsgHandler()", + * URL="\ref QatComms_ResponseMsgHandler()"]; + * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", + * URL="\ref LacSymQat_SymRespHandler()"]; + * SQAT=>SYMCB [label="LacSymCb_ProcessCallback()", + * URL="\ref LacSymCb_ProcessCallback()"]; + * SYMCB=>SYMCB [label="LacSymCb_ProcessCallbackInternal()", + * URL="\ref LacSymCb_ProcessCallbackInternal()"]; + * SYMCB=>LMP [label="Lac_MemPoolEntryFree()", + * URL="\ref Lac_MemPoolEntryFree()"]; + * SYMCB<SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYMCB<APP [label="cbFunc"]; + * SYMCB< + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_hash.h + * + * @defgroup LacHash Hash + * + * @ingroup LacSym + * + * API functions of the Hash component + * + * @lld_start + * @lld_overview + * There is a single \ref cpaCySym "Symmetric LAC API" for hash, cipher, + * auth encryption and algorithm chaining. This API is implemented by the + * \ref LacSym "Symmetric" module. It demultiplexes calls to this API into + * their basic operation and does some common parameter checking and deals + * with accesses to the session table. + * + * The hash component supports hashing in 3 modes. PLAIN, AUTH and NESTED. + * Plain mode is used to provide data integrity while auth mode is used to + * provide integrity as well as its authenticity. Nested mode is inteded + * for use by non standard HMAC like algorithms such as for the SSL master + * key secret. Partial packets is supported for both plain and auth modes. + * In-place and out-of-place processing is supported for all modes. The + * verify operation is supported for PLAIN and AUTH modes only. + * + * The hash component is responsible for implementing the hash specific + * functionality for initialising a session and for a perform operation. + * Statistics are maintained in the symmetric \ref CpaCySymStats64 "stats" + * structure. This module has been seperated out into two. The hash QAT module + * deals entirely with QAT data structures. The hash module itself has minimal + * exposure to the QAT data structures. + * + * @lld_dependencies + * - \ref LacCommon + * - \ref LacSymQat "Symmetric QAT": Hash uses the lookup table provided by + * this module to validate user input. Hash also uses this module to build + * the hash QAT request message, request param structure, populate the + * content descriptor, allocate and populate the hash state prefix buffer. + * Hash also registers its function to process the QAT response with this + * module. + * - OSAL : For memory functions, atomics and locking + * + * @lld_module_algorithms + * a. HMAC Precomputes\n + * HMAC algorithm is specified as follows: + * \f$ HMAC(msg) = hash((key \oplus opad) \parallel + * hash((key \oplus ipad) \parallel msg ))\f$. + * The key is fixed per session, and is padded up to the block size of the + * algorithm if necessary and xored with the ipad/opad. The following portion + * of the operation can be precomputed: \f$ hash(key \oplus ipad) \f$ as the + * output of this intermediate hash will be the same for every perform + * operation. This intermediate state is the intermediate state of a partial + * partial packet. It is used as the initialiser state to \f$ hash(msg) \f$. + * The same applies to \f$ hash(key \oplus ipad) \f$. There is a saving in + * the data path by the length of time it takes to do two hashes on a block + * size of data. Note: a partial packet operation generates an intermediate + * state. The final operation on a partial packet or when a full packet is + * used applies padding and gives the final hash result. Esentially for the + * inner hash, a partial packet final is issued on the data, using the + * precomputed intermediate state and returns the digest. + * + * For the HMAC precomputes, \ref LacSymHash_HmacPreCompute(), there are two + * hash operations done using a internal content descriptor to configure the + * QAT. A first partial packet is specified as the packet type for the + * pre-computes as we need the state that uses the initialiser constants + * specific to the algorithm. The resulting output is copied from the hash + * state prefix buffer into the QAT content descriptor for the session being + * initialised. The state is used each perform operation as the initialiser + * to the algorithm + * + * b. AES XCBC Precomputes\n + * A similar technique to HMAC will be used to generate the precomputes for + * AES XCBC. In this case a cipher operation will be used to generate the + * precomputed result. The Pre-compute operation involves deriving 3 128-bit + * keys (K1, K2 and K3) from the 128-bit secret key K. + * + * - K1 = 0x01010101010101010101010101010101 encrypted with Key K + * - K2 = 0x02020202020202020202020202020202 encrypted with Key K + * - K3 = 0x03030303030303030303030303030303 encrypted with Key K + * + * A content descriptor is created with the cipher algorithm set to AES + * in ECB mode and with the keysize set to 128 bits. The 3 constants, 16 bytes + * each, are copied into the src buffer and an in-place cipher operation is + * performed on the 48 bytes. ECB mode does not maintain the state, therefore + * the 3 keys can be encrypted in one perform. The encrypted result is used by + * the state2 field in the hash setup block of the content descriptor. + * + * The precompute operations use a different lac command ID and thus have a + * different route in the response path to the symmetric code. In this + * precompute callback function the output of the precompute operation is + * copied into the content descriptor for the session being registered. + * + * c. AES CCM Precomputes\n + * The precomputes for AES CCM are trivial, i.e. there is no need to perform + * a cipher or a digest operation. Instead, the key is stored directly in + * the state2 field. + * + * d. AES GCM Precomputes\n + * As with AES XCBC precomputes, a cipher operation will be used to generate + * the precomputed result for AES GCM. In this case the Galois Hash + * Multiplier (H) must be derived and stored in the state2 field. H is + * derived by encrypting a 16-byte block of zeroes with the + * cipher/authentication key, using AES in ECB mode. + * + * Key size for Auth algorithms\n + * Min Size\n + * RFC 2104 states "The key for HMAC can be of any length. However, less than + * L bytes is strongly discouraged as it would decrease the security strength + * of the function." + * + * FIPS 198a states "The size of the key, K, shall be equal to or greater than + * L/2, where L is the size of the hash function output." + * + * RFC 4434 states "If the key has fewer than 128 bits, lengthen it to exactly + * 128 bits by padding it on the right with zero bits. + * + * A key length of 0 upwards is accepted. It is up to the client to pass in a + * key that complies with the standard they wish to support. + * + * Max Size\n + * RFC 2104 section 2 states : "Applications that use keys longer than B bytes + * will first hash the key using H and then use the resultant L byte string + * as the actual key to HMAC + * + * RFC 4434 section 2 states: + * "If the key is 129 bits or longer, shorten it to exactly 128 bits + * by performing the steps in AES-XCBC-PRF-128 (that is, the + * algorithm described in this document). In that re-application of + * this algorithm, the key is 128 zero bits; the message is the + * too-long current key." + * + * We push this up to the client. They need to do the hash operation through + * the LAC API if the key is greater than the block size of the algorithm. This + * will reduce the key size to the digest size of the algorithm. + * + * RFC 3566 section 4 states: + * AES-XCBC-MAC-96 is a secret key algorithm. For use with either ESP or + * AH a fixed key length of 128-bits MUST be supported. Key lengths + * other than 128-bits MUST NOT be supported (i.e., only 128-bit keys are + * to be used by AES-XCBC-MAC-96). + * + * In this case it is up to the client to provide a key that complies with + * the standards. i.e. exactly 128 bits in size. + * + * + * HMAC-MD5-96 and HMAC-SHA1-96\n + * HMAC-MD5-96 and HMAC-SHA1-96 are defined as requirements by Look Aside + * IPsec. The differences between HMAC-SHA1 and HMAC-SHA1-96 are that the + * digest produced is truncated and there are strict requirements on the + * size of the key that is used. + * + * They are supported in LAC by HMAC-MD5 and HMAC-SHA1. The field + * \ref CpaCySymHashSetupData::digestResultLenInBytes in the LAC API in + * bytes needs to be set to 12 bytes. There are also requirements regarding + * the keysize. It is up to the client to ensure the key size meets the + * requirements of the standards they are using. + * + * RFC 2403: HMAC-MD5-96 Key lengths other than 128-bits MUST NOT be supported. + * HMAC-MD5-96 produces a 128-bit authenticator value. For use with either + * ESP or AH, a truncated value using the first 96 bits MUST be supported. + * + * RFC2404: HMAC-SHA1-96 Key lengths other than 160- bits MUST NOT be supported + * HMAC-SHA-1-96 produces a 160-bit authenticator value. For use with either + * ESP or AH, a truncated value using the first 96 bits MUST be supported. + * + * Out of place operations + * When verify is disabled, the digest will be written to the destination + * buffer. When verify is enabled, the digest calculated is compared to the + * digest stored in the source buffer. + * + * Partial Packets + * Partial packets are handled in the \ref LacSym "Symmetric" component for + * the request. The hash callback function handles the update of the state + * in the callback. + * + * + * @lld_process_context + * + * Session Register Sequence Diagram: For hash modes plain and nested. + * \msc + * APP [label="Application"], SYM [label="Symmetric LAC"], + * Achain [label="Alg chain"], Hash, SQAT [label="Symmetric QAT"]; + * + * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", + * URL="\ref cpaCySymInitSession()"] ; + * SYM=>SYM [ label = "LacSymSession_ParamCheck()", + * URL="\ref LacSymSession_ParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_SessionInit()", + * URL="\ref LacAlgChain_SessionInit()"]; + * Achain=>Hash [ label = "LacHash_HashContextCheck()", + * URL="\ref LacHash_HashContextCheck()"]; + * Achain<SQAT [ label = "LacSymQat_HashContentDescInit()", + * URL="\ref LacSymQat_HashContentDescInit()"]; + * Achain<Hash [ label = "LacHash_StatePrefixAadBufferInit()", + * URL="\ref LacHash_StatePrefixAadBufferInit()"]; + * Hash=>SQAT [ label = "LacSymQat_HashStatePrefixAadBufferSizeGet()", + * URL="\ref LacSymQat_HashStatePrefixAadBufferSizeGet()"]; + * Hash<SQAT [ label = "LacSymQat_HashStatePrefixAadBufferPopulate()", + * URL="\ref LacSymQat_HashStatePrefixAadBufferPopulate()"]; + * Hash<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<SYM [ label = "cpaCySymPerformOp()", + * URL="\ref cpaCySymPerformOp()"] ; + * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", + * URL="\ref LacSymPerform_BufferParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_Perform()", + * URL="\ref LacAlgChain_Perform()"]; + * Achain=>Achain [ label = "Lac_MemPoolEntryAlloc()", + * URL="\ref Lac_MemPoolEntryAlloc()"]; + * Achain=>SQAT [ label = "LacSymQat_packetTypeGet()", + * URL="\ref LacSymQat_packetTypeGet()"]; + * Achain<Achain [ label = "LacBuffDesc_BufferListTotalSizeGet()", + * URL="\ref LacBuffDesc_BufferListTotalSizeGet()"]; + * Achain=>Hash [ label = "LacHash_PerformParamCheck()", + * URL = "\ref LacHash_PerformParamCheck()"]; + * Achain<SQAT [ label = "LacSymQat_HashRequestParamsPopulate()", + * URL="\ref LacSymQat_HashRequestParamsPopulate()"]; + * Achain<Achain [ label = "LacBuffDesc_BufferListDescWrite()", + * URL="\ref LacBuffDesc_BufferListDescWrite()"]; + * Achain=>SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", + * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; + * Achain<SYM [ label = "LacSymQueue_RequestSend()", + * URL="\ref LacSymQueue_RequestSend()"]; + * SYM=>QATCOMMS [ label = "QatComms_MsgSend()", + * URL="\ref QatComms_MsgSend()"]; + * SYM<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<QATCOMMS [label ="QatComms_ResponseMsgHandler()", + * URL="\ref QatComms_ResponseMsgHandler()"]; + * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", + * URL="\ref LacSymQat_SymRespHandler()"]; + * SQAT=>SYM [label="LacSymCb_ProcessCallback()", + * URL="\ref LacSymCb_ProcessCallback()"]; + * SYM=>SYM [label = "LacSymCb_ProcessCallbackInternal()", + * URL="\ref LacSymCb_ProcessCallbackInternal()"]; + * SYM=>SYM [label = "Lac_MemPoolEntryFree()", + * URL="\ref Lac_MemPoolEntryFree()"]; + * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYM=>APP [label="cbFunc"]; + * APP>>SYM [label="return"]; + * SYM>>SQAT [label="return"]; + * SQAT>>QATCOMMS [label="return"]; + * \endmsc + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_HASH_H +#define LAC_SYM_HASH_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_session.h" +#include "lac_buffer_desc.h" + +/** + ***************************************************************************** + * @ingroup LacHash + * Definition of callback function. + * + * @description + * This is the callback function prototype. The callback function is + * invoked when a hash precompute operation completes. + * + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function call. + * + * @retval + * None + *****************************************************************************/ +typedef void (*lac_hash_precompute_done_cb_t)(void *pCallbackTag); + +/* + * WARNING: There are no checks done on the parameters of the functions in + * this file. The expected values of the parameters are documented and it is + * up to the caller to provide valid values. + */ + +/** +******************************************************************************* +* @ingroup LacHash +* validate the hash context +* +* @description +* The client populates the hash context in the session context structure +* This is passed as parameter to the session register API function and +* needs to be validated. +* +* @param[in] pHashSetupData pointer to hash context structure +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter +* +*****************************************************************************/ +CpaStatus LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData); + +/** + ****************************************************************************** + * @ingroup LacHash + * Populate the hash pre-compute data. + * + * @description + * This function populates the state1 and state2 fields with the hash + * pre-computes. This is only done for authentication. The state1 + * and state2 pointers must be set to point to the correct locations + * in the content descriptor where the precompute result(s) will be + * written, before this function is called. + * + * @param[in] instanceHandle Instance Handle + * @param[in] pSessionSetup pointer to session setup data + * @param[in] callbackFn Callback function which is invoked when + * the precompute operation is completed + * @param[in] pCallbackTag Opaque data which is passed back to the user + * as a parameter in the callback function + * @param[out] pWorkingBuffer Pointer to working buffer, sufficient memory + * must be allocated by the caller for this. + * Assumption that this is 8 byte aligned. + * @param[out] pState1 pointer to State 1 in content descriptor + * @param[out] pState2 pointer to State 2 in content descriptor + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_RETRY Retry the operation. + * @retval CPA_STATUS_RESOURCE Error Allocating memory + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, + CpaCySymSessionSetupData *pSessionSetup, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag, + Cpa8U *pWorkingBuffer, + Cpa8U *pState1, + Cpa8U *pState2); + +/** + ****************************************************************************** + * @ingroup LacHash + * populate the hash state prefix aad buffer. + * + * @description + * This function populates the hash state prefix aad buffer. This function + * is not called for CCM/GCM operations as the AAD data varies per request + * and is stored in the cookie as opposed to the session descriptor. + * + * @param[in] pHashSetupData pointer to hash setup structure + * @param[in] pHashControlBlock pointer to hash control block + * @param[in] qatHashMode QAT Mode for hash + * @param[in] pHashStateBuffer pointer to hash state prefix aad buffer + * @param[in] pHashStateBufferInfo Pointer to hash state prefix buffer info + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacHash_StatePrefixAadBufferInit( + sal_service_t *pService, + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_la_bulk_req_ftr_t *pHashControlBlock, + icp_qat_hw_auth_mode_t qatHashMode, + Cpa8U *pHashStateBuffer, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo); + +/** +******************************************************************************* +* @ingroup LacHash +* Check parameters for a hash perform operation +* +* @description +* This function checks the parameters for a hash perform operation. +* +* @param[in] pSessionDesc Pointer to session descriptor. +* @param[in] pOpData Pointer to request parameters. +* @param[in] srcPktSize Total size of the Buffer List +* @param[in] pVerifyResult Pointer to user flag +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_INVALID_PARAM Invalid Parameter +* +*****************************************************************************/ +CpaStatus LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + const CpaCySymOpData *pOpData, + Cpa64U srcPktSize, + const CpaBoolean *pVerifyResult); + +/** +******************************************************************************* +* @ingroup LacHash +* Perform hash precompute operation for HMAC +* +* @description +* This function sends 2 requests to the CPM for the hmac precompute +* operations. The results of the ipad and opad state calculation +* is copied into pState1 and pState2 (e.g. these may be the state1 and +* state2 buffers in a hash content desciptor) and when +* the final operation has completed the condition passed as a param to +* this function is set to true. +* +* This function performs the XORing of the IPAD and OPAD constants to +* the key (which was padded to the block size of the algorithm) +* +* @param[in] instanceHandle Instance Handle +* @param[in] hashAlgorithm Hash Algorithm +* @param[in] authKeyLenInBytes Length of Auth Key +* @param[in] pAuthKey Pointer to Auth Key +* @param[out] pWorkingMemory Pointer to working memory that is carved +* up and used in the pre-compute operations. +* Assumption that this is 8 byte aligned. +* @param[out] pState1 Pointer to State 1 in content descriptor +* @param[out] pState2 Pointer to State 2 in content descriptor +* @param[in] callbackFn Callback function which is invoked when +* the precompute operation is completed +* @param[in] pCallbackTag Opaque data which is passed back to the user +* as a parameter in the callback function +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_RETRY Retry the operation. +* @retval CPA_STATUS_FAIL Operation Failed +* +*****************************************************************************/ +CpaStatus LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState1, + Cpa8U *pState2, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag); + +/** +******************************************************************************* + * @ingroup LacHash + * Perform hash precompute operation for XCBC MAC and GCM + * + * @description + * This function sends 1 request to the CPM for the precompute operation + * based on an AES ECB cipher. The results of the calculation is copied + * into pState (this may be a pointer to the State 2 buffer in a Hash + * content descriptor) and when the operation has completed the condition + * passed as a param to this function is set to true. + * + * @param[in] instanceHandle Instance Handle + * @param[in] hashAlgorithm Hash Algorithm + * @param[in] authKeyLenInBytes Length of Auth Key + * @param[in] pAuthKey Auth Key + * @param[out] pWorkingMemory Pointer to working memory that is carved + * up and used in the pre-compute operations. + * Assumption that this is 8 byte aligned. + * @param[out] pState Pointer to output state + * @param[in] callbackFn Callback function which is invoked when + * the precompute operation is completed + * @param[in] pCallbackTag Opaque data which is passed back to the user + * as a parameter in the callback function + + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_RETRY Retry the operation. + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag); + +/** +******************************************************************************* +* @ingroup LacHash +* initialise data structures for the hash precompute operations +* +* @description +* This function registers the precompute callback handler function, which +* is different to the default one used by symmetric. Content desciptors +* are preallocted for the hmac precomputes as they are constant for these +* operations. +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_RESOURCE Error allocating memory +* +*****************************************************************************/ +CpaStatus LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacHash +* free resources allocated for the precompute operations +* +* @description +* free up the memory allocated on init time for the content descriptors +* that were allocated for the HMAC precompute operations. +* +* @return none +* +*****************************************************************************/ +void LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle); + +void LacSync_GenBufListVerifyCb(void *pCallbackTag, + CpaStatus status, + CpaCySymOp operationType, + void *pOpData, + CpaBufferList *pDstBuffer, + CpaBoolean opResult); + +#endif /* LAC_SYM_HASH_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h new file mode 100644 index 00000000000..e95b0efb5b0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_defs.h + * + * @defgroup LacHashDefs Hash Definitions + * + * @ingroup LacHash + * + * Constants for hash algorithms + * + ***************************************************************************/ + +#ifndef LAC_SYM_HASH_DEFS_H +#define LAC_SYM_HASH_DEFS_H + +/* Constant for MD5 algorithm */ +#define LAC_HASH_MD5_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * MD5 block size in bytes */ +#define LAC_HASH_MD5_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * MD5 digest length in bytes */ +#define LAC_HASH_MD5_STATE_SIZE 16 +/**< @ingroup LacHashDefs + * MD5 state size */ + +/* Constants for SHA1 algorithm */ +#define LAC_HASH_SHA1_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA1 Block size in bytes */ +#define LAC_HASH_SHA1_DIGEST_SIZE 20 +/**< @ingroup LacHashDefs + * SHA1 digest length in bytes */ +#define LAC_HASH_SHA1_STATE_SIZE 20 +/**< @ingroup LacHashDefs + * SHA1 state size */ + +/* Constants for SHA224 algorithm */ +#define LAC_HASH_SHA224_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA224 block size in bytes */ +#define LAC_HASH_SHA224_DIGEST_SIZE 28 +/**< @ingroup LacHashDefs + * SHA224 digest length in bytes */ +#define LAC_HASH_SHA224_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA224 state size */ + +/* Constants for SHA256 algorithm */ +#define LAC_HASH_SHA256_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA256 block size in bytes */ +#define LAC_HASH_SHA256_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SHA256 digest length */ +#define LAC_HASH_SHA256_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA256 state size */ + +/* Constants for SHA384 algorithm */ +#define LAC_HASH_SHA384_BLOCK_SIZE 128 +/**< @ingroup LacHashDefs + * SHA384 block size in bytes */ +#define LAC_HASH_SHA384_DIGEST_SIZE 48 +/**< @ingroup LacHashDefs + * SHA384 digest length in bytes */ +#define LAC_HASH_SHA384_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * SHA384 state size */ + +/* Constants for SHA512 algorithm */ +#define LAC_HASH_SHA512_BLOCK_SIZE 128 +/**< @ingroup LacHashDefs + * SHA512 block size in bytes */ +#define LAC_HASH_SHA512_DIGEST_SIZE 64 +/**< @ingroup LacHashDefs + * SHA512 digest length in bytes */ +#define LAC_HASH_SHA512_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * SHA512 state size */ + +/* Constants for SHA3_224 algorithm */ +#define LAC_HASH_SHA3_224_BLOCK_SIZE 144 +/**< @ingroup LacHashDefs + * SHA3_224 block size in bytes */ +#define LAC_HASH_SHA3_224_DIGEST_SIZE 28 +/**< @ingroup LacHashDefs + * SHA3_224 digest length in bytes */ +#define LAC_HASH_SHA3_224_STATE_SIZE 28 +/**< @ingroup LacHashDefs + * SHA3_224 state size */ + +/* Constants for SHA3_256 algorithm */ +#define LAC_HASH_SHA3_256_BLOCK_SIZE 136 +/**< @ingroup LacHashDefs + * SHA3_256 block size in bytes */ +#define LAC_HASH_SHA3_256_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SHA3_256 digest length in bytes */ +#define LAC_HASH_SHA3_256_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA3_256 state size */ + +/* Constants for SHA3_384 algorithm */ +#define LAC_HASH_SHA3_384_BLOCK_SIZE 104 +/**< @ingroup LacHashDefs + * * SHA3_384 block size in bytes */ +#define LAC_HASH_SHA3_384_DIGEST_SIZE 48 +/**< @ingroup LacHashDefs + * * SHA3_384 digest length in bytes */ +#define LAC_HASH_SHA3_384_STATE_SIZE 48 +/**< @ingroup LacHashDefs + * * SHA3_384 state size */ + +/* Constants for SHA3_512 algorithm */ +#define LAC_HASH_SHA3_512_BLOCK_SIZE 72 +/**< @ingroup LacHashDefs + * * * SHA3_512 block size in bytes */ +#define LAC_HASH_SHA3_512_DIGEST_SIZE 64 +/**< @ingroup LacHashDefs + * * * SHA3_512 digest length in bytes */ +#define LAC_HASH_SHA3_512_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * * * SHA3_512 state size */ + +/* Constants for SHAKE_128 algorithm */ +#define LAC_HASH_SHAKE_128_BLOCK_SIZE 168 +/**< @ingroup LacHashDefs + * * * SHAKE_128 block size in bytes */ +#define LAC_HASH_SHAKE_128_DIGEST_SIZE 0xFFFFFFFF +/**< @ingroup LacHashDefs + * * * SHAKE_128 digest length in bytes ((2^32)-1)*/ + +/* Constants for SHAKE_256 algorithm */ +#define LAC_HASH_SHAKE_256_BLOCK_SIZE 136 +/**< @ingroup LacHashDefs + * * * SHAKE_256 block size in bytes */ +#define LAC_HASH_SHAKE_256_DIGEST_SIZE 0xFFFFFFFF +/**< @ingroup LacHashDefs + * * * SHAKE_256 digest length in bytes ((2^ 32)-1)*/ + +/* Constants for POLY algorithm */ +#define LAC_HASH_POLY_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * POLY block size in bytes */ +#define LAC_HASH_POLY_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * POLY digest length */ +#define LAC_HASH_POLY_STATE_SIZE 0 +/**< @ingroup LacHashDefs + * POLY state size */ + +/* Constants for SM3 algorithm */ +#define LAC_HASH_SM3_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SM3 block size in bytes */ +#define LAC_HASH_SM3_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SM3 digest length */ +#define LAC_HASH_SM3_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SM3 state size */ + +/* Constants for XCBC precompute algorithm */ +#define LAC_HASH_XCBC_PRECOMP_KEY_NUM 3 +/**< @ingroup LacHashDefs + * The Pre-compute operation involves deriving 3 128-bit + * keys (K1, K2 and K3) */ + +/* Constants for XCBC MAC algorithm */ +#define LAC_HASH_XCBC_MAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * XCBC_MAC block size in bytes */ +#define LAC_HASH_XCBC_MAC_128_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * XCBC_MAC_PRF_128 digest length in bytes */ + +/* Constants for AES CMAC algorithm */ +#define LAC_HASH_CMAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * AES CMAC block size in bytes */ +#define LAC_HASH_CMAC_128_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * AES CMAC digest length in bytes */ + +/* constants for AES CCM */ +#define LAC_HASH_AES_CCM_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * block size for CBC-MAC part of CCM */ +#define LAC_HASH_AES_CCM_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * untruncated size of authentication field */ + +/* constants for AES GCM */ +#define LAC_HASH_AES_GCM_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * block size for Galois Hash 128 part of CCM */ +#define LAC_HASH_AES_GCM_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * untruncated size of authentication field */ + +/* constants for KASUMI F9 */ +#define LAC_HASH_KASUMI_F9_BLOCK_SIZE 8 +/**< @ingroup LacHashDefs + * KASUMI_F9 block size in bytes */ +#define LAC_HASH_KASUMI_F9_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * KASUMI_F9 digest size in bytes */ + +/* constants for SNOW3G UIA2 */ +#define LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE 8 +/**< @ingroup LacHashDefs + * SNOW3G UIA2 block size in bytes */ +#define LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * SNOW3G UIA2 digest size in bytes */ + +/* constants for AES CBC MAC */ +#define LAC_HASH_AES_CBC_MAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * AES CBC MAC block size in bytes */ +#define LAC_HASH_AES_CBC_MAC_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * AES CBC MAC digest size in bytes */ + +#define LAC_HASH_ZUC_EIA3_BLOCK_SIZE 4 +/**< @ingroup LacHashDefs + * ZUC EIA3 block size in bytes */ +#define LAC_HASH_ZUC_EIA3_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * ZUC EIA3 digest size in bytes */ + +/* constants for AES GCM ICV allowed sizes */ +#define LAC_HASH_AES_GCM_ICV_SIZE_8 8 +#define LAC_HASH_AES_GCM_ICV_SIZE_12 12 +#define LAC_HASH_AES_GCM_ICV_SIZE_16 16 + +/* constants for AES CCM ICV allowed sizes */ +#define LAC_HASH_AES_CCM_ICV_SIZE_MIN 4 +#define LAC_HASH_AES_CCM_ICV_SIZE_MAX 16 + +/* constants for authentication algorithms */ +#define LAC_HASH_IPAD_BYTE 0x36 +/**< @ingroup LacHashDefs + * Ipad Byte */ +#define LAC_HASH_OPAD_BYTE 0x5c +/**< @ingroup LacHashDefs + * Opad Byte */ + +#define LAC_HASH_IPAD_4_BYTES 0x36363636 +/**< @ingroup LacHashDefs + * Ipad for 4 Bytes */ +#define LAC_HASH_OPAD_4_BYTES 0x5c5c5c5c +/**< @ingroup LacHashDefs + * Opad for 4 Bytes */ + +/* Key Modifier (KM) value used in Kasumi algorithm in F9 mode to XOR + * Integrity Key (IK) */ +#define LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES 0xAAAAAAAA +/**< @ingroup LacHashDefs + * Kasumi F9 Key Modifier for 4 bytes */ + +#define LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW 2 +/**< @ingroup LacSymQatHash + * Maximum size of IV embedded in the request. + * This is set to 2, namely 4 LONGWORDS. */ + +#define LAC_SYM_QAT_HASH_STATE1_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE +/**< @ingroup LacSymQatHash + * Maximum size of state1 in the hash setup block of the content descriptor. + * This is set to the block size of SHA512. */ + +#define LAC_SYM_QAT_HASH_STATE2_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE +/**< @ingroup LacSymQatHash + * Maximum size of state2 in the hash setup block of the content descriptor. + * This is set to the block size of SHA512. */ + +#define LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES 255 +/**< Maximum size of the inner and outer prefix for nested hashing operations. + * This is got from the maximum size supported by the accelerator which stores + * the size in an 8bit field */ + +#define LAC_MAX_HASH_STATE_STORAGE_SIZE \ + (sizeof(icp_qat_hw_auth_counter_t) + LAC_HASH_SHA512_STATE_SIZE) +/**< Maximum size of the hash state storage section of the hash state prefix + * buffer */ + +#define LAC_MAX_HASH_STATE_BUFFER_SIZE_BYTES \ + LAC_MAX_HASH_STATE_STORAGE_SIZE + \ + (LAC_ALIGN_POW2_ROUNDUP(LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES, \ + LAC_QUAD_WORD_IN_BYTES) * \ + 2) +/**< Maximum size of the hash state prefix buffer will be for nested hash when + * there is the maximum sized inner prefix and outer prefix */ + +#define LAC_MAX_AAD_SIZE_BYTES 256 +/**< Maximum size of AAD in bytes */ + +#define IS_HMAC_ALG(algorithm) \ + ((algorithm == CPA_CY_SYM_HASH_MD5) || \ + (algorithm == CPA_CY_SYM_HASH_SHA1) || \ + (algorithm == CPA_CY_SYM_HASH_SHA224) || \ + (algorithm == CPA_CY_SYM_HASH_SHA256) || \ + (algorithm == CPA_CY_SYM_HASH_SHA384) || \ + (algorithm == CPA_CY_SYM_HASH_SHA512) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_224) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_256) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_384) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_512) || \ + (algorithm == CPA_CY_SYM_HASH_SM3)) +/**< @ingroup LacSymQatHash + * Macro to detect if the hash algorithm is a HMAC algorithm */ + +#define IS_HASH_MODE_1(qatHashMode) (ICP_QAT_HW_AUTH_MODE1 == qatHashMode) +/**< @ingroup LacSymQatHash + * Macro to detect is qat hash mode is set to 1 (precompute mode) + * only used with algorithms in hash mode CPA_CY_SYM_HASH_MODE_AUTH */ + +#define IS_HASH_MODE_2(qatHashMode) (ICP_QAT_HW_AUTH_MODE2 == qatHashMode) +/**< @ingroup LacSymQatHash + * Macro to detect is qat hash mode is set to 2. This is used for TLS and + * mode 2 HMAC (no preompute mode) */ + +#define IS_HASH_MODE_2_AUTH(qatHashMode, hashMode) \ + ((IS_HASH_MODE_2(qatHashMode)) && \ + (CPA_CY_SYM_HASH_MODE_AUTH == hashMode)) +/**< @ingroup LacSymQatHash + * Macro to check for qat hash mode is set to 2 and the hash mode is + * Auth. This applies to HMAC algorithms (no pre compute). This is used + * to differntiate between TLS and HMAC */ + +#define IS_HASH_MODE_2_NESTED(qatHashMode, hashMode) \ + ((IS_HASH_MODE_2(qatHashMode)) && \ + (CPA_CY_SYM_HASH_MODE_NESTED == hashMode)) +/**< @ingroup LacSymQatHash + * Macro to check for qat hash mode is set to 2 and the LAC hash mode is + * Nested. This applies to TLS. This is used to differentiate between + * TLS and HMAC */ + +#endif /* LAC_SYM_HASH_DEFS_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h new file mode 100644 index 00000000000..6fd93cc2817 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_precomputes.h + * + * @defgroup LacHashDefs Hash Definitions + * + * @ingroup LacHash + * + * Constants for hash algorithms + * + ***************************************************************************/ +#ifndef LAC_SYM_HASH_PRECOMPUTES_H +#define LAC_SYM_HASH_PRECOMPUTES_H + +#include "lac_sym_hash.h" + +#define LAC_SYM_AES_CMAC_RB_128 0x87 /* constant used for */ + /* CMAC calculation */ + +#define LAC_SYM_HASH_MSBIT_MASK 0x80 /* Mask to check MSB top bit */ + /* zero or one */ + +#define LAC_SINGLE_BUFFER_HW_META_SIZE \ + (sizeof(icp_buffer_list_desc_t) + sizeof(icp_flat_buffer_desc_t)) +/**< size of memory to allocate for the HW buffer list that is sent to the + * QAT */ + +#define LAC_SYM_HASH_PRECOMP_MAX_WORKING_BUFFER \ + ((sizeof(lac_sym_hash_precomp_op_data_t) * 2) + \ + sizeof(lac_sym_hash_precomp_op_t)) +/**< maximum size of the working data for the HMAC precompute operations + * + * Maximum size of lac_sym_hash_precomp_op_data_t is 264 bytes. For hash + * precomputes there are 2 of these structrues and a further + * lac_sym_hash_precomp_op_t structure required. This comes to a total of 536 + * bytes. + * For the asynchronous version of the precomputes, the memory for the hash + * state prefix buffer is used as the working memory. There are 584 bytes + * which are alloacted for the hash state prefix buffer which is enough to + * carve up for the precomputes. + */ + +#define LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA \ + ((ICP_QAT_HW_AES_128_KEY_SZ) * (3)) +/**< Maximum size for the data that an AES ECB precompute is generated on */ + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * Precompute type enum + * @description + * Enum used to distinguish between precompute types + * + *****************************************************************************/ +typedef enum { + LAC_SYM_HASH_PRECOMP_HMAC = 1, + /**< Hmac precompute operation. Copy state from hash state buffer */ + LAC_SYM_HASH_PRECOMP_AES_ECB, + /**< XCBC/CGM precompute, Copy state from data buffer */ +} lac_sym_hash_precomp_type_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * overall precompute management structure + * @description + * structure used to manage the precompute operations for a session + * + *****************************************************************************/ +typedef struct lac_sym_hash_precomp_op_s { + lac_hash_precompute_done_cb_t callbackFn; + /**< Callback function to be invoked when the final precompute completes + */ + + void *pCallbackTag; + /**< Opaque data to be passed back as a parameter in the callback */ + + QatUtilsAtomic opsPending; + /**< counter used to determine if the current precompute is the + * final one. */ + +} lac_sym_hash_precomp_op_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * hmac precompute structure as used by the QAT + * @description + * data used by the QAT for HMAC precomputes + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_hmac_precomp_qat_s { + Cpa8U data[LAC_HASH_SHA512_BLOCK_SIZE]; + /**< data to be hashed - block size of data for the algorithm */ + /* NOTE: to save space we could have got the QAT to overwrite + * this with the hash state storage */ + icp_qat_fw_la_auth_req_params_t hashReqParams; + /**< Request parameters as read in by the QAT */ + Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; + /**< Buffer descriptor structure */ + Cpa8U hashStateStorage[LAC_MAX_HASH_STATE_STORAGE_SIZE]; + /**< Internal buffer where QAT writes the intermediate partial + * state that is used in the precompute */ +} lac_sym_hash_hmac_precomp_qat_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * AES ECB precompute structure as used by the QAT + * @description + * data used by the QAT for AES ECB precomptes + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_aes_precomp_qat_s { + Cpa8U contentDesc[LAC_SYM_QAT_MAX_CIPHER_SETUP_BLK_SZ]; + /**< Content descriptor for a cipher operation */ + Cpa8U data[LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA]; + /**< The data to be ciphered is conatined here and the result is + * written in place back into this buffer */ + icp_qat_fw_la_cipher_req_params_t cipherReqParams; + /**< Request parameters as read in by the QAT */ + Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; + /**< Buffer descriptor structure */ +} lac_sym_hash_aes_precomp_qat_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * overall structure for managing a single precompute operation + * @description + * overall structure for managing a single precompute operation + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_precomp_op_data_s { + sal_crypto_service_t *pInstance; + /**< Instance handle for the operation */ + Cpa8U reserved[4]; + /**< padding to align later structures on minimum 8-Byte address */ + lac_sym_hash_precomp_type_t opType; + /**< operation type to determine the precompute type in the callback */ + lac_sym_hash_precomp_op_t *pOpStatus; + /**< structure containing the counter and the condition for the overall + * precompute operation. This is a pointer because the memory structure + * may be shared between precomputes when there are more than 1 as in + * the + * case of HMAC */ + union { + lac_sym_hash_hmac_precomp_qat_t hmacQatData; + /**< Data sent to the QAT for hmac precomputes */ + lac_sym_hash_aes_precomp_qat_t aesQatData; + /**< Data sent to the QAT for AES ECB precomputes */ + } u; + + /**< ASSUMPTION: The above structures are 8 byte aligned if the overall + * struct is 8 byte aligned, as there are two 4 byte fields before this + * union */ + Cpa32U stateSize; + /**< Size of the state to be copied into the state pointer in the + * content + * descriptor */ + Cpa8U *pState; + /**< pointer to the state in the content descriptor where the result of + * the precompute should be copied to */ +} lac_sym_hash_precomp_op_data_t; + +#endif /* LAC_SYM_HASH_PRECOMPUTES_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h new file mode 100644 index 00000000000..bae0d8faabc --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h @@ -0,0 +1,184 @@ +/*************************************************************************** + * + * + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_key.h + * + * @defgroup LacSymKey Key Generation + * + * @ingroup LacSym + * + * @lld_start + * + * @lld_overview + * + * Key generation component is reponsible for SSL, TLS & MGF operations. All + * memory required for the keygen operations is got from the keygen cookie + * structure which is carved up as required. + * + * For SSL the QAT accelerates the nested hash function with MD5 as the + * outer hash and SHA1 as the inner hash. + * + * Refer to sections in draft-freier-ssl-version3-02.txt: + * 6.1 Asymmetric cryptographic computations - This refers to coverting + * the pre master secret to the master secret. + * 6.2.2 Converting the master secret into keys and MAC secrets - Using + * the master secret to generate the key material. + * + * For TLS the QAT accelerates the PRF function as described in + * rfc4346 - TLS version 1.1 (this obsoletes rfc2246 - TLS version 1.0) + * 5. HMAC and the pseudorandom function - For the TLS PRF and getting + * S1 and S2 from the secret. + * 6.3. Key calculation - For how the key material is generated + * 7.4.9. Finished - How the finished message uses the TLS PRF + * 8.1. Computing the master secret + * + * + * @lld_dependencies + * \ref LacSymQatHash: for building up hash content descriptor + * \ref LacMem: for virt to phys coversions + * + * @lld_initialisation + * The reponse handler is registered with Symmetric. The Maximum SSL is + * allocated. A structure is allocated containing all the TLS lables that + * are supported. On shutdown the memory for these structures are freed. + * + * @lld_module_algorithms + * @lld_process_context + * + * @lld_end + * + * + *****************************************************************************/ +#ifndef LAC_SYM_KEY_H_ +#define LAC_SYM_KEY_H_ + +#include "icp_qat_fw_la.h" +#include "cpa_cy_key.h" + +/**< @ingroup LacSymKey + * Label for SSL. Size is 136 bytes for 16 iterations, which can theroretically + * generate up to 256 bytes of output data. QAT will generate a maximum of + * 255 bytes */ + +#define LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL ("master secret") +/**< @ingroup LacSymKey + * Label for TLS Master Secret Key Derivation, as defined in RFC4346 */ + +#define LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL ("key expansion") +/**< @ingroup LacSymKey + * Label for TLS Key Material Generation, as defined in RFC4346. */ + +#define LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL ("client finished") +/**< @ingroup LacSymKey + * Label for TLS Client finished Message, as defined in RFC4346. */ + +#define LAC_SYM_KEY_TLS_SERVER_FIN_LABEL ("server finished") +/**< @ingroup LacSymKey + * Label for TLS Server finished Message, as defined in RFC4346. */ + +/* +******************************************************************************* +* Define Constants and Macros for SSL, TLS and MGF +******************************************************************************* +*/ + +#define LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW 0 +/**< Used to indicate there is no hash block offset in the content descriptor + */ + +/* +******************************************************************************* +* Define Constant lengths for HKDF TLS v1.3 sublabels. +******************************************************************************* +*/ +#define HKDF_SUB_LABEL_KEY_LENGTH ((Cpa8U)13) +#define HKDF_SUB_LABEL_IV_LENGTH ((Cpa8U)12) +#define HKDF_SUB_LABEL_RESUMPTION_LENGTH ((Cpa8U)20) +#define HKDF_SUB_LABEL_FINISHED_LENGTH ((Cpa8U)18) +#define HKDF_SUB_LABELS_ALL \ + (CPA_CY_HKDF_SUBLABEL_KEY | CPA_CY_HKDF_SUBLABEL_IV | \ + CPA_CY_HKDF_SUBLABEL_RESUMPTION | CPA_CY_HKDF_SUBLABEL_FINISHED) +#define LAC_KEY_HKDF_SUBLABELS_NUM 4 +#define LAC_KEY_HKDF_DIGESTS 0 +#define LAC_KEY_HKDF_CIPHERS_MAX (CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256 + 1) +#define LAC_KEY_HKDF_SUBLABELS_MAX (LAC_KEY_HKDF_SUBLABELS_NUM + 1) + +/** + ****************************************************************************** + * @ingroup LacSymKey + * TLS label struct + * + * @description + * This structure is used to hold the various TLS labels. Each field is + * on an 8 byte boundary provided the structure itslef is 8 bytes aligned. + *****************************************************************************/ +typedef struct lac_sym_key_tls_labels_s { + Cpa8U masterSecret[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< Master secret label */ + Cpa8U keyMaterial[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< Key material label */ + Cpa8U clientFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< client finished label */ + Cpa8U serverFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< server finished label */ +} lac_sym_key_tls_labels_t; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * TLS HKDF sub label struct + * + * @description + * This structure is used to hold the various TLS HKDF sub labels. + * Each field is on an 8 byte boundary. + *****************************************************************************/ +typedef struct lac_sym_key_tls_hkdf_sub_labels_s { + CpaCyKeyGenHKDFExpandLabel keySublabel256; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + CpaCyKeyGenHKDFExpandLabel keySublabel384; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + CpaCyKeyGenHKDFExpandLabel keySublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + Cpa64U sublabelPhysAddr256; + /**< Physical address of the SHA-256 subLabels */ + Cpa64U sublabelPhysAddr384; + /**< Physical address of the SHA-384 subLabels */ + Cpa64U sublabelPhysAddrChaChaPoly; + /**< Physical address of the ChaChaPoly subLabels */ +} lac_sym_key_tls_hkdf_sub_labels_t; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function prints the stats to standard out. + * + * @retval CPA_STATUS_SUCCESS Status Success + * @retval CPA_STATUS_FAIL General failure + * + *****************************************************************************/ +void LacKeygen_StatsShow(CpaInstanceHandle instanceHandle); + +#endif diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h new file mode 100644 index 00000000000..b3088784a27 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_partial.h + * + * @defgroup LacSymPartial Partial Packets + * + * @ingroup LacSymCommon + * + * Partial packet handling code + * + * @lld_start + * + * Partials In Flight\n + * The API states that for partial packets the client should not submit + * the next partial request until the callback for the current partial has + * been called. We have chosen to enforce this rather than letting the user + * proceed where they would get an incorrect digest, cipher result. + * + * Maintain a SpinLock for partials in flight per session. Try and acquire this + * SpinLock. If it cant be acquired return an error straight away to the client + * as there is already a partial in flight. There is no blocking in the data + * path for this. + * + * By preventing any other partials from coming in while a partial is in flight + * we can check and change the state of the session without having to lock + * round it (dont want to have to lock and block in the data path). The state + * of the session indicates the previous packet type that a request was + * successfully completed for. The last packet type is only updated for partial + * packets. This state determines the packet types that can be accepted. + * e.g a last partial will not be accepted unless the previous packet was a + * partial. By only allowing one partial packet to be in flight, there is no + * need to lock around the update of the previous packet type for the session. + * + * The ECB Cipher mode, ciphers each block separately. No state is maintained + * between blocks. There is no need to wait for the callback for previous + * partial in ECB mode as the result of the previous partial has no impact on + * it. The API and our implementation only allows 1 partial packet to be in + * flight per session, therefore a partial packet request for ECB mode must + * be fully completed (ie. callback called) before the next partial request + * can be issued. + * + * Partial Ordering\n + * The ordering that the user submits partial packets will be checked. + * (we could have let the user proceed where they will get an incorrect + * digest/cipher result but chose against this). + * + * -# Maintain the last packet type of a partial operation for the session. If + * there have been no previous partials, we will accept only first partials + * -# The state must be set to partial before we will accept a final partial. + * i.e. a partial request must have already completed. + * + * The last packet type is updated in the callback for partial packets as this + * is the only place we can guarantee that a partial packet operation has been + * completed. When a partial completes the state can be updated from FULL to + * PARTIAL. The SpinLock for partial packets in flight for the session can be + * unlocked at this point. On a final Partial request the last packet type is + * reset back to FULL. NOTE: This is not done at the same time as the check in + * the perform as if an error occurs we would have to roll back the state + * + * For Hash mode it is possible to interleave full and a single partial + * packet stream in a session as the hash state buffer is updated for partial + * packets. It is not touched by full packets. For cipher mode, as the client + * manages the state, they can interleave full and a single partial packets. + * For ARC4, the state is managed internally and the packet type will always + * be set to partial internally. + * + * @lld_end + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_PARTIAL_H +#define LAC_SYM_PARTIAL_H + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/***************************************************************************/ + +/** +******************************************************************************* +* @ingroup LacSymPartial +* check if partial packet request is valid for a session +* +* @description +* This function checks to see if there is a partial packet request in +* flight and then if the partial state is correct +* +* @param[in] packetType Partial packet request +* @param[in] partialState Partial state of session +* +* @retval CPA_STATUS_SUCCESS Normal Operation +* @retval CPA_STATUS_INVALID_PARAM Invalid Parameter +* +*****************************************************************************/ +CpaStatus LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, + CpaCySymPacketType partialState); + +/** +******************************************************************************* +* @ingroup LacSymPartial +* update the state of the partial packet in a session +* +* @description +* This function is called in callback operation. It updates the state +* of a partial packet in a session and indicates that there is no +* longer a partial packet in flight for the session +* +* @param[in] packetType Partial packet request +* @param[out] pPartialState Pointer to partial state of session +* +*****************************************************************************/ +void LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, + CpaCySymPacketType *pPartialState); + +#endif /* LAC_SYM_PARTIAL_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h new file mode 100644 index 00000000000..af49764b649 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat.h + * + * @defgroup LacSymQat Symmetric QAT + * + * @ingroup LacSym + * + * Interfaces for populating the qat structures for a symmetric operation + * + * @lld_start + * + * @lld_overview + * This file documents the interfaces for populating the qat structures + * that are common for all symmetric operations. + * + * @lld_dependencies + * - \ref LacSymQatHash "Hash QAT Comms" Sym Qat commons for Hash + * - \ref LacSymQat_Cipher "Cipher QAT Comms" Sym Qat commons for Cipher + * - OSAL: logging + * - \ref LacMem "Memory" - Inline memory functions + * + * @lld_initialisation + * This component is initialied during the LAC initialisation sequence. It + * is called by the Symmetric Initialisation function. + * + * @lld_module_algorithms + * + * @lld_process_context + * Refer to \ref LacHash "Hash" and \ref LacCipher "Cipher" for sequence + * diagrams to see their interactions with this code. + * + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_H +#define LAC_SYM_QAT_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_accel_devices.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" +#include "lac_session.h" +#include "sal_qat_cmn_msg.h" +#include "lac_common.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#define LAC_SYM_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL +#define LAC_SYM_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT +#define LAC_SYM_KEY_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT +/**< @ingroup LacSymQat + * LAC SYM Source & Destination buffer type (FLAT/SGL) */ + +#define LAC_QAT_SYM_REQ_SZ_LW 32 +#define SYM_TX_MSG_SIZE (LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES) +#define NRBG_TX_MSG_SIZE (LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES) + +#define LAC_QAT_SYM_RESP_SZ_LW 8 +#define SYM_RX_MSG_SIZE (LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES) +#define NRBG_RX_MSG_SIZE (LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES) + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Symmetric crypto response handler + * + * @description + * This function handles the symmetric crypto response + * + * @param[in] trans_handle transport handle (if ICP_QAT_DBG set) + * @param[in] instanceHandle void* pRespMsg + * + * + *****************************************************************************/ +void LacSymQat_SymRespHandler(void *pRespMsg); + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Initialise the Symmetric QAT code + * + * @description + * This function initialises the symmetric QAT code + * + * @param[in] device Pointer to the acceleration device + * structure + * @param[in] instanceHandle Instance handle + * @param[in] numSymRequests Number of concurrent requests a pair + * (tx and rx) need to support + * + * @return CPA_STATUS_SUCCESS Operation successful + * @return CPA_STATUS_FAIL Initialisation Failed + * + *****************************************************************************/ +CpaStatus LacSymQat_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Register a response handler function for a symmetric command ID + * + * @description + * This function registers a response handler function for a symmetric + * operation. + * + * Note: This operation should only be performed once by the init function + * of a component. There is no corresponding deregister function, but + * registering a NULL function pointer will have the same effect. There + * MUST not be any requests in flight when calling this function. + * + * @param[in] lacCmdId Command Id of operation + * @param[in] pCbHandler callback handler function + * + * @return None + * + *****************************************************************************/ +void LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, + sal_qat_resp_handler_func_t pCbHandler); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * get the QAT packet type + * + * @description + * This function returns the QAT packet type for a LAC packet type. The + * LAC packet type does not indicate a first partial. therefore for a + * partial request, the previous packet type needs to be looked at to + * figure out if the current partial request is a first partial. + * + * + * @param[in] packetType LAC Packet type + * @param[in] packetState LAC Previous Packet state + * @param[out] pQatPacketType Packet type using the QAT macros + * + * @return none + * + *****************************************************************************/ +void LacSymQat_packetTypeGet(CpaCySymPacketType packetType, + CpaCySymPacketType packetState, + Cpa32U *pQatPacketType); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * Populate the command flags based on the packet type + * + * @description + * This function populates the following flags in the Symmetric Crypto + * service_specif_flags field of the common header of the request: + * - LA_PARTIAL + * - UPDATE_STATE + * - RET_AUTH_RES + * - CMP_AUTH_RES + * based on looking at the input params listed below. + * + * @param[in] qatPacketType Packet type + * @param[in] cmdId Command Id + * @param[in] cipherAlgorithm Cipher Algorithm + * @param[out] pLaCommandFlags Command Flags + * + * @return none + * + *****************************************************************************/ +void LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, + icp_qat_fw_la_cmd_id_t laCmdId, + CpaCySymCipherAlgorithm cipherAlgorithm, + Cpa16U *pLaCommandFlags, + Cpa32U ivLenInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * + * + * @description + * defaults the common request service specific flags + * + * @param[in] laCmdFlags Common request service specific flags + * @param[in] symOp Type of operation performed e.g hash or cipher + * + * @return none + * + *****************************************************************************/ + +void LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, + CpaCySymOp symOp); + +#endif /* LAC_SYM_QAT_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h new file mode 100644 index 00000000000..2360aa53633 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_cipher.h + * + * @defgroup LacSymQat_Cipher Cipher QAT + * + * @ingroup LacSymQat + * + * external interfaces for populating QAT structures for cipher operations. + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_CIPHER_H +#define LAC_SYM_QAT_CIPHER_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa_cy_sym.h" +#include "icp_qat_fw_la.h" +#include "lac_session.h" +#include "lac_sal_types_crypto.h" + +/* + ************************************************************************** + * @ingroup LacSymQat_Cipher + * + * @description + * Defines for building the cipher request params cache + * + ************************************************************************** */ + +#define LAC_SYM_QAT_CIPHER_NEXT_ID_BIT_OFFSET 24 +#define LAC_SYM_QAT_CIPHER_CURR_ID_BIT_OFFSET 16 +#define LAC_SYM_QAT_CIPHER_STATE_SIZE_BIT_OFFSET 8 +#define LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC 9 +#define LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC 2 +#define LAC_SYM_QAT_CIPHER_STATE_SIZE_SPC 48 +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Retrieve the cipher block size in bytes for a given algorithm + * + * @description + * This function returns a hard-coded block size for the specific cipher + * algorithm + * + * @param[in] cipherAlgorithm Cipher algorithm for the current session + * + * @retval The block size, in bytes, for the given cipher algorithm + * + *****************************************************************************/ +Cpa8U +LacSymQat_CipherBlockSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Retrieve the cipher IV/state size in bytes for a given algorithm + * + * @description + * This function returns a hard-coded IV/state size for the specific cipher + * algorithm + * + * @param[in] cipherAlgorithm Cipher algorithm for the current session + * + * @retval The IV/state size, in bytes, for the given cipher algorithm + * + *****************************************************************************/ +Cpa32U LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Populate the cipher request params structure + * + * @description + * This function is passed a pointer to the 128B request block. + * (This memory must be allocated prior to calling this function). It + * populates: + * - the cipher fields of the req_params block in the request. No + * need to zero this first, all fields will be populated. + * - the corresponding CIPH_IV_FLD flag in the serv_specif_flags field + * of the common header. + * To do this it uses the parameters described below and the following + *fields from the request block which must be populated prior to calling this + *function: + * - cd_ctrl.cipher_state_sz + * - UPDATE_STATE flag in comn_hdr.serv_specif_flags + * + * + * @param[in] pReq Pointer to request block. + * * + * @param[in] cipherOffsetInBytes Offset to cipher data in user data buffer + * + * @param[in] cipherLenInBytes Length of cipher data in buffer + * + * @param[in] ivBufferPhysAddr Physical address of aligned IV/state + * buffer + * @param[in] pIvBufferVirt Virtual address of aligned IV/state + * buffer + * @retval void + * + *****************************************************************************/ +CpaStatus LacSymQat_CipherRequestParamsPopulate(icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U cipherOffsetInBytes, + Cpa32U cipherLenInBytes, + Cpa64U ivBufferPhysAddr, + Cpa8U *pIvBufferVirt); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Derive initial ARC4 cipher state from a base key + * + * @description + * An initial state for an ARC4 cipher session is derived from the base + * key provided by the user, using the ARC4 Key Scheduling Algorithm (KSA) + * + * @param[in] pKey The base key provided by the user + * + * @param[in] keyLenInBytes The length of the base key provided. + * The range of valid values is 1-256 bytes + * + * @param[out] pArc4CipherState The initial state is written to this buffer, + * including i and j values, and 6 bytes of padding + * so 264 bytes must be allocated for this buffer + * by the caller + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, + Cpa32U keyLenInBytes, + Cpa8U *pArc4CipherState); + +/** + ****************************************************************************** + * @ingroup LacSymQat_CipherXTSModeUpdateKeyLen + * Update the initial XTS key after the first partial has been received. + * + * @description + * For XTS mode using partial packets, after the first partial response + * has been received, the the key length needs to be halved for subsequent + * partials. + * + * @param[in] pSessionDesc The session descriptor. + * + * @param[in] newKeySizeInBytes The new key size.. + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, + Cpa32U newKeySizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherCtrlBlockInitialize() + * + * @description + * intialize the cipher control block with all zeros + * + * @param[in] pMsg Pointer to the common request message + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherCtrlBlockInitialize(icp_qat_fw_la_bulk_req_t *pMsg); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherCtrlBlockWrite() + * + * @description + * This function populates the cipher control block of the common request + * message + * + * @param[in] pMsg Pointer to the common request message + * + * @param[in] cipherAlgorithm Cipher Algorithm to be used + * + * @param[in] targetKeyLenInBytes cipher key length in bytes of selected + * algorithm + * + * @param[out] nextSlice SliceID for next control block + * entry. This value is known only by + * the calling component + * + * @param[out] cipherCfgOffsetInQuadWord Offset into the config table in QW + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa32U cipherAlgorithm, + Cpa32U targetKeyLenInBytes, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherCfgOffsetInQuadWord); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherHwBlockPopulateCfgData() + * + * @description + * Populate the physical HW block with config data + * + * @param[in] pSession Pointer to the session data + * + * @param[in] pCipherHwBlock pointer to the hardware control block + * in the common message + * + * @param[in] pSizeInBytes + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherGetCfgData() + * + * @description + * setup the config data for cipher + * + * @param[in] pSession Pointer to the session data + * + * @param[in] pAlgorithm * + * @param[in] pMode + * @param[in] pDir + * @param[in] pKey_convert + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, + icp_qat_hw_cipher_algo_t *pAlgorithm, + icp_qat_hw_cipher_mode_t *pMode, + icp_qat_hw_cipher_dir_t *pDir, + icp_qat_hw_cipher_convert_t *pKey_convert); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherHwBlockPopulateKeySetup() + * + * @description + * populate the key setup data in the cipher hardware control block + * in the common request message + * + * param[in] pCipherSetupData Pointer to cipher setup data + * + * @param[in] targetKeyLenInBytes Target key length. If key length given + * in cipher setup data is less that this, + * the key will be "rounded up" to this + * target length by padding it with 0's. + * In normal no-padding case, the target + * key length MUST match the key length + * in the cipher setup data. + * + * @param[in] pCipherHwBlock Pointer to the cipher hardware block + * + * @param[out] pCipherHwBlockSizeBytes Size in bytes of cipher setup block + * + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherHwBlockPopulateKeySetup( + const CpaCySymCipherSetupData *pCipherSetupData, + Cpa32U targetKeyLenInBytes, + const void *pCipherHwBlock, + Cpa32U *pCipherHwBlockSizeBytes); + +#endif /* LAC_SYM_QAT_CIPHER_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h new file mode 100644 index 00000000000..147e10f573f --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_hash.h + * + * @defgroup LacSymQatHash Hash QAT + * + * @ingroup LacSymQat + * + * interfaces for populating qat structures for a hash operation + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_HASH_H +#define LAC_SYM_QAT_HASH_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_common.h" + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * hash precomputes + * + * @description + * This structure contains infomation on the hash precomputes + * + *****************************************************************************/ +typedef struct lac_sym_qat_hash_precompute_info_s { + Cpa8U *pState1; + /**< state1 pointer */ + Cpa32U state1Size; + /**< state1 size */ + Cpa8U *pState2; + /**< state2 pointer */ + Cpa32U state2Size; + /**< state2 size */ +} lac_sym_qat_hash_precompute_info_t; + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * hash state prefix buffer info + * + * @description + * This structure contains infomation on the hash state prefix aad buffer + * + *****************************************************************************/ +typedef struct lac_sym_qat_hash_state_buffer_info_s { + Cpa64U pDataPhys; + /**< Physical pointer to the hash state prefix buffer */ + Cpa8U *pData; + /**< Virtual pointer to the hash state prefix buffer */ + Cpa8U stateStorageSzQuadWords; + /**< hash state storage size in quad words */ + Cpa8U prefixAadSzQuadWords; + /**< inner prefix/aad and outer prefix size in quad words */ +} lac_sym_qat_hash_state_buffer_info_t; + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Init the hash specific part of the content descriptor. + * + * @description + * This function populates the hash specific fields of the control block + * and the hardware setup block for a digest session. This function sets + * the size param to hold the size of the hash setup block. + * + * In the case of hash only, the content descriptor will contain just a + * hash control block and hash setup block. In the case of chaining it + * will contain the hash control block and setup block along with the + * control block and setup blocks of additional services. + * + * Note: The memory for the content descriptor MUST be allocated prior to + * calling this function. The memory for the hash control block and hash + * setup block MUST be set to 0 prior to calling this function. + * + * @image html contentDescriptor.png "Content Descriptor" + * + * @param[in] pMsg Pointer to req Parameter Footer + * + * @param[in] pHashSetupData Pointer to the hash setup data as + * defined in the LAC API. + * + * @param[in] pHwBlockBase Pointer to the base of the hardware + * setup block + * + * @param[in] hashBlkOffsetInHwBlock Offset in quad-words from the base of + * the hardware setup block where the + * hash block will start. This offset + * is stored in the control block. It + * is used to figure out where to write + * that hash setup block. + * + * @param[in] nextSlice SliceID for next control block + * entry This value is known only by + * the calling component + * + * @param[in] qatHashMode QAT hash mode + * + * @param[in] useSymConstantsTable Indicate if Shared-SRAM constants table + * is used for this session. If TRUE, the + * h/w setup block is NOT populated + * + * @param[in] useOptimisedContentDesc Indicate if optimised content desc + * is used for this session. + * + * @param[in] pPrecompute For auth mode, this is the pointer + * to the precompute data. Otherwise this + * should be set to NULL + * + * @param[out] pHashBlkSizeInBytes size in bytes of hash setup block + * + * @return void + * + *****************************************************************************/ +void +LacSymQat_HashContentDescInit(icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + void *pHwBlockBase, + Cpa32U hashBlkOffsetInHwBlock, + icp_qat_fw_slice_t nextSlice, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean useSymConstantsTable, + CpaBoolean useOptimisedContentDesc, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + Cpa32U *pHashBlkSizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Calculate the size of the hash state prefix aad buffer + * + * @description + * This function inspects the hash control block and based on the values + * in the fields, it calculates the size of the hash state prefix aad + * buffer. + * + * A partial packet processing request is possible at any stage during a + * hash session. In this case, there will always be space for the hash + * state storage field of the hash state prefix buffer. When there is + * AAD data just the inner prefix AAD data field is used. + * + * @param[in] pMsg Pointer to the Request Message + * + * @param[out] pHashStateBuf Pointer to hash state prefix buffer info + * structure. + * + * @return None + * + *****************************************************************************/ +void LacSymQat_HashStatePrefixAadBufferSizeGet( + icp_qat_la_bulk_req_ftr_t *pMsg, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Populate the fields of the hash state prefix buffer + * + * @description + * This function populates the inner prefix/aad fields and/or the outer + * prefix field of the hash state prefix buffer. + * + * @param[in] pHashStateBuf Pointer to hash state prefix buffer info + * structure. + * + * @param[in] pMsg Pointer to the Request Message + * + * @param[in] pInnerPrefixAad Pointer to the Inner Prefix or Aad data + * This is NULL where if the data size is 0 + * + * @param[in] innerPrefixSize Size of inner prefix/aad data in bytes + * + * @param[in] pOuterPrefix Pointer to the Outer Prefix data. This is + * NULL where the data size is 0. + * + * @param[in] outerPrefixSize Size of the outer prefix data in bytes + * + * @return void + * + *****************************************************************************/ +void LacSymQat_HashStatePrefixAadBufferPopulate( + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa8U *pInnerPrefixAad, + Cpa8U innerPrefixSize, + Cpa8U *pOuterPrefix, + Cpa8U outerPrefixSize); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Populate the hash request params structure + * + * @description + * This function is passed a pointer to the 128B Request block. + * (This memory must be allocated prior to calling this function). It + * populates the fields of this block using the parameters as described + * below. It is also expected that this structure has been set to 0 + * prior to calling this function. + * + * + * @param[in] pReq Pointer to 128B request block. + * + * @param[in] authOffsetInBytes start offset of data that the digest is to + * be computed on. + * + * @param[in] authLenInBytes Length of data digest calculated on + * + * @param[in] pService Pointer to service data + * + * @param[in] pHashStateBuf Pointer to hash state buffer info. This + * structure contains the pointers and sizes. + * If there is no hash state prefix buffer + * required, this parameter can be set to NULL + * + * @param[in] qatPacketType Packet type using QAT macros. The hash + * state buffer pointer and state size will be + * different depending on the packet type + * + * @param[in] hashResultSize Size of the final hash result in bytes. + * + * @param[in] digestVerify Indicates if verify is enabled or not + * + * @param[in] pAuthResult Virtual pointer to digest + * + * @return CPA_STATUS_SUCCESS or CPA_STATUS_FAIL + * + *****************************************************************************/ +CpaStatus LacSymQat_HashRequestParamsPopulate( + icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U authOffsetInBytes, + Cpa32U authLenInBytes, + sal_service_t *pService, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + Cpa32U qatPacketType, + Cpa32U hashResultSize, + CpaBoolean digestVerify, + Cpa8U *pAuthResult, + CpaCySymHashAlgorithm alg, + void *data); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * + * + * @description + * This fn returns the QAT values for hash algorithm and nested fields + * + * + * @param[in] pInstance Pointer to service instance. + * + * @param[in] qatHashMode value for hash mode on the fw qat + *interface. + * + * @param[in] apiHashMode value for hash mode on the QA API. + * + * @param[in] apiHashAlgorithm value for hash algorithm on the QA API. + * + * @param[out] pQatAlgorithm Pointer to return fw qat value for + *algorithm. + * + * @param[out] pQatNested Pointer to return fw qat value for nested. + * + * + * @return + * none + * + *****************************************************************************/ +void LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, + icp_qat_hw_auth_mode_t qatHashMode, + CpaCySymHashMode apiHashMode, + CpaCySymHashAlgorithm apiHashAlgorithm, + icp_qat_hw_auth_algo_t *pQatAlgorithm, + CpaBoolean *pQatNested); + +void LacSymQat_HashSetupReqParamsMetaData( + icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + CpaBoolean hashStateBuffer, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean digestVerify); + +#endif /* LAC_SYM_QAT_HASH_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h new file mode 100644 index 00000000000..23db82a3b18 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_hash_defs_lookup.h + * + * @defgroup LacSymQatHashDefsLookup Hash Defs Lookup + * + * @ingroup LacSymQatHash + * + * API to be used for the hash defs lookup table. + * + *****************************************************************************/ + +#ifndef LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H +#define LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* Finishing Hash algorithm +* @description +* This define points to the last available hash algorithm +* @NOTE: If a new algorithm is added to the api, this #define +* MUST be updated to being the last hash algorithm in the struct +* CpaCySymHashAlgorithm in the file cpa_cy_sym.h +*****************************************************************************/ +#define CPA_CY_HASH_ALG_END CPA_CY_SYM_HASH_SM3 + +/***************************************************************************/ + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash algorithm specific structure +* @description +* This structure contain constants specific to an algorithm. +*****************************************************************************/ +typedef struct lac_sym_qat_hash_alg_info_s { + Cpa32U digestLength; /**< Digest length in bytes */ + Cpa32U blockLength; /**< Block length in bytes */ + Cpa8U *initState; /**< Initialiser state for hash algorithm */ + Cpa32U stateSize; /**< size of above state in bytes */ +} lac_sym_qat_hash_alg_info_t; + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash qat specific structure +* @description +* This structure contain constants as defined by the QAT for an +* algorithm. +*****************************************************************************/ +typedef struct lac_sym_qat_hash_qat_info_s { + Cpa32U algoEnc; /**< QAT Algorithm encoding */ + Cpa32U authCounter; /**< Counter value for Auth */ + Cpa32U state1Length; /**< QAT state1 length in bytes */ + Cpa32U state2Length; /**< QAT state2 length in bytes */ +} lac_sym_qat_hash_qat_info_t; + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash defs structure +* @description +* This type contains pointers to the hash algorithm structure and +* to the hash qat specific structure +*****************************************************************************/ +typedef struct lac_sym_qat_hash_defs_s { + lac_sym_qat_hash_alg_info_t *algInfo; + /**< pointer to hash info structure */ + lac_sym_qat_hash_qat_info_t *qatInfo; + /**< pointer to hash QAT info structure */ +} lac_sym_qat_hash_defs_t; + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* initialise the hash lookup table +* +* @description +* This function initialises the digest lookup table. +* +* @note +* This function does not have a corresponding shutdown function. +* +* @return CPA_STATUS_SUCCESS Operation successful +* @return CPA_STATUS_RESOURCE Allocating of hash lookup table failed +* +*****************************************************************************/ +CpaStatus LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* get hash algorithm specific structure from lookup table +* +* @description +* This function looks up the hash lookup array for a structure +* containing data specific to a hash algorithm. The hashAlgorithm enum +* value MUST be in the correct range prior to calling this function. +* +* @param[in] hashAlgorithm Hash Algorithm +* @param[out] ppHashAlgInfo Hash Alg Info structure +* +* @return None +* +*****************************************************************************/ +void LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t **ppHashAlgInfo); + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* get hash defintions from lookup table. +* +* @description +* This function looks up the hash lookup array for a structure +* containing data specific to a hash algorithm. This includes both +* algorithm specific info and qat specific infro. The hashAlgorithm enum +* value MUST be in the correct range prior to calling this function. +* +* @param[in] hashAlgorithm Hash Algorithm +* @param[out] ppHashDefsInfo Hash Defs structure +* +* @return void +* +*****************************************************************************/ +void LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_defs_t **ppHashDefsInfo); + +#endif /* LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h new file mode 100644 index 00000000000..a6a5d5169e1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_key.h + * + * @defgroup LacSymQatKey Key QAT + * + * @ingroup LacSymQat + * + * interfaces for populating qat structures for a key operation + * + *****************************************************************************/ + +#ifndef LAC_SYM_QAT_KEY_H +#define LAC_SYM_QAT_KEY_H + +#include "cpa.h" +#include "lac_sym.h" +#include "icp_qat_fw_la.h" + +/** +****************************************************************************** +* @ingroup LacSymQatKey +* Number of bytes generated per iteration +* @description +* This define is the number of bytes generated per iteration +*****************************************************************************/ +#define LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION (16) + +/** +****************************************************************************** +* @ingroup LacSymQatKey +* Shift to calculate the number of iterations +* @description +* This define is the shift to calculate the number of iterations +*****************************************************************************/ +#define LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT LAC_16BYTE_ALIGNMENT_SHIFT + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the SSL request +* +* @description +* Populate the SSL request +* +* @param[out] pKeyGenReqHdr Pointer to Key Generation request Header +* @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request +* @param[in] generatedKeyLenInBytes Length of Key generated +* @param[in] labelLenInBytes Length of Label +* @param[in] secretLenInBytes Length of Secret +* @param[in] iterations Number of iterations. This is related +* to the label length. +* +* @return None +* +*****************************************************************************/ +void +LacSymQat_KeySslRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa32U iterations); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS request +* +* @description +* Populate the TLS request +* +* @param[out] pKeyGenReq Pointer to Key Generation request +* @param[in] generatedKeyLenInBytes Length of Key generated +* @param[in] labelLenInBytes Length of Label +* @param[in] secretLenInBytes Length of Secret +* @param[in] seedLenInBytes Length of Seed +* @param[in] cmdId Command Id to differentiate TLS versions +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsRequestPopulate( + icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa8U seedLenInBytes, + icp_qat_fw_la_cmd_id_t cmdId); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate MGF request +* +* @description +* Populate MGF request +* +* @param[out] pKeyGenReqHdr Pointer to Key Generation request Header +* @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request +* @param[in] seedLenInBytes Length of Seed +* @param[in] maskLenInBytes Length of Mask +* @param[in] hashLenInBytes Length of hash +* +* @return None +* +*****************************************************************************/ +void +LacSymQat_KeyMgfRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa8U seedLenInBytes, + Cpa16U maskLenInBytes, + Cpa8U hashLenInBytes); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the SSL key material input +* +* @description +* Populate the SSL key material input +* +* @param[in] pService Pointer to service +* @param[out] pSslKeyMaterialInput Pointer to SSL key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* @param[in] pSecret Pointer to Secret +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeySslKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr, + void *pSecret); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS key material input +* +* @description +* Populate the TLS key material input +* +* @param[in] pService Pointer to service +* @param[out] pTlsKeyMaterialInput Pointer to TLS key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS HKDF key material input +* +* @description +* Populate the TLS HKDF key material input +* +* @param[in] pService Pointer to service +* @param[out] pTlsKeyMaterialInput Pointer to TLS key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* @param[in] cmdId Command ID +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_hkdf_key_material_input_t *pTlsKeyMaterialInput, + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + Cpa64U subLabelsPhysAddr, + icp_qat_fw_la_cmd_id_t cmdId); + +#endif /* LAC_SYM_QAT_KEY_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h new file mode 100644 index 00000000000..d7a5cd3c9e9 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ****************************************************************************** + * @file lac_sym_queue.h + * + * @defgroup LacSymQueue Symmetric request queueing functions + * + * @ingroup LacSym + * + * Function prototypes for sending/queuing symmetric requests + *****************************************************************************/ + +#ifndef LAC_SYM_QUEUE_H +#define LAC_SYM_QUEUE_H + +#include "cpa.h" +#include "lac_session.h" +#include "lac_sym.h" + +/** +******************************************************************************* +* @ingroup LacSymQueue +* Send a request message to the QAT, or queue it if necessary +* +* @description +* This function will send a request message to the QAT. However, if a +* blocking condition exists on the session (e.g. partial packet in flight, +* precompute in progress), then the message will instead be pushed on to +* the request queue for the session and will be sent later to the QAT +* once the blocking condition is cleared. +* +* @param[in] instanceHandle Handle for instance of QAT +* @param[in] pRequest Pointer to request cookie +* @param[out] pSessionDesc Pointer to session descriptor +* +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RESOURCE Problem Acquiring system resource +* @retval CPA_STATUS_RETRY Failed to send message to QAT due to queue +* full condition +* +*****************************************************************************/ +CpaStatus LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, + lac_sym_bulk_cookie_t *pRequest, + lac_session_desc_t *pSessionDesc); + +#endif /* LAC_SYM_QUEUE_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h new file mode 100644 index 00000000000..b5d82342016 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_stats.h + * + * @defgroup LacSymCommon Symmetric Common + * + * @ingroup LacSym + * + * Symetric Common consists of common statistics, buffer and partial packet + * functionality. + * + ***************************************************************************/ + +/** + *************************************************************************** + * @defgroup LacSymStats Statistics + * + * @ingroup LacSymCommon + * + * definitions and prototypes for LAC symmetric statistics. + * + * @lld_start + * In the LAC API the stats fields are defined as Cpa32U but + * QatUtilsAtomic is the type that the atomic API supports. Therefore we + * need to define a structure internally with the same fields as the API + * stats structure, but each field must be of type QatUtilsAtomic. + * + * - Incrementing Statistics:\n + * Atomically increment the statistic on the internal stats structure. + * + * - Providing a copy of the stats back to the user:\n + * Use atomicGet to read the atomic variable for each stat field in the + * local internal stat structure. These values are saved in structure + * (as defined by the LAC API) that the client will provide a pointer + * to as a parameter. + * + * - Stats Show:\n + * Use atomicGet to read the atomic variables for each field in the local + * internal stat structure and print to the screen + * + * - Stats Array:\n + * A macro is used to get the offset off the stat in the structure. This + * offset is passed to a function which uses it to increment the stat + * at that offset. + * + * @lld_end + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_STATS_H +#define LAC_SYM_STATS_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_common.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +/** +******************************************************************************* +* @ingroup LacSymStats +* increment a symmetric statistic +* +* @description +* Increment the statistics +* +* @param statistic IN The field in the symmetric statistics structure to be +* incremented +* @param instanceHandle IN engine Id Number +* +* @retval None +* +*****************************************************************************/ +#define LAC_SYM_STAT_INC(statistic, instanceHandle) \ + LacSym_StatsInc(offsetof(CpaCySymStats64, statistic), instanceHandle) + +/** +******************************************************************************* +* @ingroup LacSymStats +* initialises the symmetric stats +* +* @description +* This function allocates and initialises the stats array to 0 +* +* @param instanceHandle Instance Handle +* +* @retval CPA_STATUS_SUCCESS initialisation successful +* @retval CPA_STATUS_RESOURCE array allocation failed +* +*****************************************************************************/ +CpaStatus LacSym_StatsInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Frees the symmetric stats +* +* @description +* This function frees the stats array +* +* @param instanceHandle Instance Handle +* +* @retval None +* +*****************************************************************************/ +void LacSym_StatsFree(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Inrement a stat +* +* @description +* This function incrementes a stat for a specific engine. +* +* @param offset IN offset of stat field in structure +* @param instanceHandle IN qat Handle +* +* @retval None +* +*****************************************************************************/ +void LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Copy the contents of the statistics structure for an engine +* +* @description +* This function copies the 32bit symmetric statistics structure for +* a specific engine into an address supplied as a parameter. +* +* @param instanceHandle IN engine Id Number +* @param pSymStats OUT stats structure to copy the stats for the into +* +* @retval None +* +*****************************************************************************/ +void LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, + struct _CpaCySymStats *const pSymStats); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Copy the contents of the statistics structure for an engine +* +* @description +* This function copies the 64bit symmetric statistics structure for +* a specific engine into an address supplied as a parameter. +* +* @param instanceHandle IN engine Id Number +* @param pSymStats OUT stats structure to copy the stats for the into +* +* @retval None +* +*****************************************************************************/ +void LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, + CpaCySymStats64 *const pSymStats); + +/** +******************************************************************************* +* @ingroup LacSymStats +* print the symmetric stats to standard output +* +* @description +* The statistics for symmetric are printed to standard output. +* +* @retval None +* +* @see LacSym_StatsCopyGet() +* +*****************************************************************************/ +void LacSym_StatsShow(CpaInstanceHandle instanceHandle); + +#endif /*LAC_SYM_STATS_H_*/ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c b/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c new file mode 100644 index 00000000000..2f27a178187 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c @@ -0,0 +1,3021 @@ +/*************************************************************************** + * + * + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_key.c + * + * @ingroup LacSymKey + * + * This file contains the implementation of all keygen functionality + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_key.h" +#include "cpa_cy_im.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" + +#include "qat_utils.h" + +#include "lac_log.h" +#include "lac_hooks.h" +#include "lac_sym.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_qat.h" +#include "lac_sal.h" +#include "lac_sym_key.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" +#include "lac_sym_qat_key.h" +#include "lac_sym_hash_defs.h" +#include "sal_statistics.h" + +/* Number of statistics */ +#define LAC_KEY_NUM_STATS (sizeof(CpaCyKeyGenStats64) / sizeof(Cpa64U)) + +#define LAC_KEY_STAT_INC(statistic, instanceHandle) \ + do { \ + sal_crypto_service_t *pService = NULL; \ + pService = (sal_crypto_service_t *)instanceHandle; \ + if (CPA_TRUE == \ + pService->generic_service_info.stats \ + ->bKeyGenStatsEnabled) { \ + qatUtilsAtomicInc( \ + &pService \ + ->pLacKeyStats[offsetof(CpaCyKeyGenStats64, \ + statistic) / \ + sizeof(Cpa64U)]); \ + } \ + } while (0) +/**< Macro to increment a Key stat (derives offset into array of atomics) */ + +#define LAC_KEY_STATS32_GET(keyStats, instanceHandle) \ + do { \ + int i; \ + sal_crypto_service_t *pService = \ + (sal_crypto_service_t *)instanceHandle; \ + for (i = 0; i < LAC_KEY_NUM_STATS; i++) { \ + ((Cpa32U *)&(keyStats))[i] = \ + (Cpa32U)qatUtilsAtomicGet( \ + &pService->pLacKeyStats[i]); \ + } \ + } while (0) +/**< Macro to get all 32bit Key stats (from internal array of atomics) */ + +#define LAC_KEY_STATS64_GET(keyStats, instanceHandle) \ + do { \ + int i; \ + sal_crypto_service_t *pService = \ + (sal_crypto_service_t *)instanceHandle; \ + for (i = 0; i < LAC_KEY_NUM_STATS; i++) { \ + ((Cpa64U *)&(keyStats))[i] = \ + qatUtilsAtomicGet(&pService->pLacKeyStats[i]); \ + } \ + } while (0) +/**< Macro to get all 64bit Key stats (from internal array of atomics) */ + +#define IS_HKDF_UNSUPPORTED(cmdId, hkdfSupported) \ + ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= cmdId && \ + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= cmdId) && \ + !hkdfSupported) /**< macro to check whether the HKDF algorithm can be \ + supported on the device */ + +/* Sublabel for HKDF TLS Key Generation, as defined in RFC8446. */ +const static Cpa8U key256[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 16, 9, 't', + 'l', 's', '1', '3', + ' ', 'k', 'e', 'y', + 0 }; +const static Cpa8U key384[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 32, 9, 't', + 'l', 's', '1', '3', + ' ', 'k', 'e', 'y', + 0 }; +const static Cpa8U keyChaChaPoly[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 32, 9, + 't', 'l', 's', + '1', '3', ' ', + 'k', 'e', 'y', + 0 }; +/* Sublabel for HKDF TLS IV key Generation, as defined in RFC8446. */ +const static Cpa8U iv256[HKDF_SUB_LABEL_IV_LENGTH] = { 0, 12, 8, 't', + 'l', 's', '1', '3', + ' ', 'i', 'v', 0 }; +const static Cpa8U iv384[HKDF_SUB_LABEL_IV_LENGTH] = { 0, 12, 8, 't', + 'l', 's', '1', '3', + ' ', 'i', 'v', 0 }; +/* Sublabel for HKDF TLS RESUMPTION key Generation, as defined in RFC8446. */ +const static Cpa8U resumption256[HKDF_SUB_LABEL_RESUMPTION_LENGTH] = + { 0, 32, 16, 't', 'l', 's', '1', '3', ' ', 'r', + 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0 }; +const static Cpa8U resumption384[HKDF_SUB_LABEL_RESUMPTION_LENGTH] = + { 0, 48, 16, 't', 'l', 's', '1', '3', ' ', 'r', + 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0 }; +/* Sublabel for HKDF TLS FINISHED key Generation, as defined in RFC8446. */ +const static Cpa8U finished256[HKDF_SUB_LABEL_FINISHED_LENGTH] = + { 0, 32, 14, 't', 'l', 's', '1', '3', ' ', + 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; +const static Cpa8U finished384[HKDF_SUB_LABEL_FINISHED_LENGTH] = + { 0, 48, 14, 't', 'l', 's', '1', '3', ' ', + 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * SSL/TLS stat type + * + * @description + * This enum determines which stat should be incremented + *****************************************************************************/ +typedef enum { + LAC_KEY_REQUESTS = 0, + /**< Key requests sent */ + LAC_KEY_REQUEST_ERRORS, + /**< Key requests errors */ + LAC_KEY_COMPLETED, + /**< Key requests which received responses */ + LAC_KEY_COMPLETED_ERRORS + /**< Key requests which received responses with errors */ +} lac_key_stat_type_t; + +/*** Local functions prototypes ***/ +static void +LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +static CpaStatus +LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaBoolean bIsExtRequest); + +static void +LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +static CpaStatus +LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutpuData); + +/*** Implementation ***/ + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Get the instance handle. Support single handle. + * @param[in] instanceHandle_in user supplied handle. + * @retval CpaInstanceHandle the instance handle + */ +static CpaInstanceHandle +LacKey_GetHandle(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + return instanceHandle; +} + +/** +******************************************************************************* +* @ingroup LacSymKey +* Perform SSL/TLS key gen operation +* +* @description +* Perform SSL/TLS key gen operation +* +* @param[in] instanceHandle QAT device handle. +* @param[in] pKeyGenCb Pointer to callback function to be invoked +* when the operation is complete. +* @param[in] pCallbackTag Opaque User Data for this specific call. +* @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) +* @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to +* perform the SSL/TLS key generation +* operation. +* @param[in] hashAlgorithm Specifies the hash algorithm to use. +* According to RFC5246, this should be +* "SHA-256 or a stronger standard hash +* function." +* @param[out] pKeyGenOutputData pointer to where output result should be +* written +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Function should be retried. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +*****************************************************************************/ +static CpaStatus +LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutputData); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Increment stat for TLS or SSL operation + * + * @description + * This is a generic function to update the stats for either a TLS or SSL + * operation. + * + * @param[in] lacCmdId Indicate SSL or TLS operations + * @param[in] statType Statistics Type + * @param[in] instanceHandle Instance Handle + * + * @return None + * + *****************************************************************************/ +static void +LacKey_StatsInc(icp_qat_fw_la_cmd_id_t lacCmdId, + lac_key_stat_type_t statType, + CpaInstanceHandle instanceHandle) +{ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + switch (statType) { + case LAC_KEY_REQUESTS: + LAC_KEY_STAT_INC(numSslKeyGenRequests, instanceHandle); + break; + case LAC_KEY_REQUEST_ERRORS: + LAC_KEY_STAT_INC(numSslKeyGenRequestErrors, + instanceHandle); + break; + case LAC_KEY_COMPLETED: + LAC_KEY_STAT_INC(numSslKeyGenCompleted, instanceHandle); + break; + case LAC_KEY_COMPLETED_ERRORS: + LAC_KEY_STAT_INC(numSslKeyGenCompletedErrors, + instanceHandle); + break; + default: + QAT_UTILS_LOG("Invalid statistics type\n"); + break; + } + } else /* TLS v1.0/1.1 and 1.2 */ + { + switch (statType) { + case LAC_KEY_REQUESTS: + LAC_KEY_STAT_INC(numTlsKeyGenRequests, instanceHandle); + break; + case LAC_KEY_REQUEST_ERRORS: + LAC_KEY_STAT_INC(numTlsKeyGenRequestErrors, + instanceHandle); + break; + case LAC_KEY_COMPLETED: + LAC_KEY_STAT_INC(numTlsKeyGenCompleted, instanceHandle); + break; + case LAC_KEY_COMPLETED_ERRORS: + LAC_KEY_STAT_INC(numTlsKeyGenCompletedErrors, + instanceHandle); + break; + default: + QAT_UTILS_LOG("Invalid statistics type\n"); + break; + } + } +} + +void +LacKeygen_StatsShow(CpaInstanceHandle instanceHandle) +{ + CpaCyKeyGenStats64 keyStats = { 0 }; + + LAC_KEY_STATS64_GET(keyStats, instanceHandle); + + QAT_UTILS_LOG(SEPARATOR BORDER + " Key Stats: " BORDER + "\n" SEPARATOR); + + QAT_UTILS_LOG(BORDER " SSL Key Requests: %16llu " BORDER + "\n" BORDER + " SSL Key Request Errors: %16llu " BORDER + "\n" BORDER + " SSL Key Completed %16llu " BORDER + "\n" BORDER + " SSL Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numSslKeyGenRequests, + (unsigned long long)keyStats.numSslKeyGenRequestErrors, + (unsigned long long)keyStats.numSslKeyGenCompleted, + (unsigned long long)keyStats.numSslKeyGenCompletedErrors); + + QAT_UTILS_LOG(BORDER " TLS Key Requests: %16llu " BORDER + "\n" BORDER + " TLS Key Request Errors: %16llu " BORDER + "\n" BORDER + " TLS Key Completed %16llu " BORDER + "\n" BORDER + " TLS Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numTlsKeyGenRequests, + (unsigned long long)keyStats.numTlsKeyGenRequestErrors, + (unsigned long long)keyStats.numTlsKeyGenCompleted, + (unsigned long long)keyStats.numTlsKeyGenCompletedErrors); + + QAT_UTILS_LOG(BORDER " MGF Key Requests: %16llu " BORDER + "\n" BORDER + " MGF Key Request Errors: %16llu " BORDER + "\n" BORDER + " MGF Key Completed %16llu " BORDER + "\n" BORDER + " MGF Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numMgfKeyGenRequests, + (unsigned long long)keyStats.numMgfKeyGenRequestErrors, + (unsigned long long)keyStats.numMgfKeyGenCompleted, + (unsigned long long)keyStats.numMgfKeyGenCompletedErrors); +} + +/** @ingroup LacSymKey */ +CpaStatus +cpaCyKeyGenQueryStats(CpaInstanceHandle instanceHandle_in, + struct _CpaCyKeyGenStats *pSymKeyStats) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymKeyStats); + + SAL_RUNNING_CHECK(instanceHandle); + + LAC_KEY_STATS32_GET(*pSymKeyStats, instanceHandle); + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSymKey */ +CpaStatus +cpaCyKeyGenQueryStats64(CpaInstanceHandle instanceHandle_in, + CpaCyKeyGenStats64 *pSymKeyStats) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymKeyStats); + + SAL_RUNNING_CHECK(instanceHandle); + + LAC_KEY_STATS64_GET(*pSymKeyStats, instanceHandle); + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the size of the digest for a specific hash algorithm. + * @description + * Return the expected digest size based on the sha algorithm submitted. + * The only supported value are sha256, sha384 and sha512. + * + * @param[in] hashAlgorithm either sha256, sha384 or sha512. + * @return the expected size or 0 for an invalid hash. + * + *****************************************************************************/ +static Cpa32U +getDigestSizeFromHashAlgo(CpaCySymHashAlgorithm hashAlgorithm) +{ + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_SHA256: + return LAC_HASH_SHA256_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SHA384: + return LAC_HASH_SHA384_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SHA512: + return LAC_HASH_SHA512_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SM3: + return LAC_HASH_SM3_DIGEST_SIZE; + default: + return 0; + } +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the hash algorithm for a specific cipher. + * @description + * Return the hash algorithm related to the cipher suite. + * Supported hash's are SHA256, and SHA384. + * + * @param[in] cipherSuite AES_128_GCM, AES_256_GCM, AES_128_CCM, + * and CHACHA20_POLY1305. + * @return the expected hash algorithm or 0 for an invalid cipher. + * + *****************************************************************************/ +static CpaCySymHashAlgorithm +getHashAlgorithmFromCipherSuiteHKDF(CpaCyKeyHKDFCipherSuite cipherSuite) +{ + switch (cipherSuite) { + case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: /* Fall through */ + case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: + return CPA_CY_SYM_HASH_SHA256; + case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: + return CPA_CY_SYM_HASH_SHA384; + default: + return 0; + } +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the digest size of cipher. + * @description + * Return the output key size of specific cipher, for specified sub label + * + * @param[in] cipherSuite = AES_128_GCM, AES_256_GCM, AES_128_CCM, + * and CHACHA20_POLY1305. + * subLabels = KEY, IV, RESUMPTION, and FINISHED. + * @return the expected digest size of the cipher. + * + *****************************************************************************/ +static const Cpa32U cipherSuiteHKDFHashSizes + [LAC_KEY_HKDF_CIPHERS_MAX][LAC_KEY_HKDF_SUBLABELS_MAX] = { + {}, /* Not used */ + { 32, 16, 12, 32, 32 }, /* AES_128_GCM_SHA256 */ + { 48, 32, 12, 48, 48 }, /* AES_256_GCM_SHA384 */ + { 32, 32, 12, 32, 32 }, /* CHACHA20_POLY1305_SHA256 */ + { 32, 16, 12, 32, 32 }, /* AES_128_CCM_SHA256 */ + { 32, 16, 12, 32, 32 } /* AES_128_CCM_8_SHA256 */ + }; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Key Generation MGF response handler + * + * @description + * Handles Key Generation MGF response messages from the QAT. + * + * @param[in] lacCmdId Command id of the original request + * @param[in] pOpaqueData Pointer to opaque data that was in request + * @param[in] cmnRespFlags Indicates whether request succeeded + * + * @return void + * + *****************************************************************************/ +static void +LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + CpaCyKeyGenMgfOpData *pMgfOpData = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + CpaCyGenFlatBufCbFunc pKeyGenMgfCb = NULL; + void *pCallbackTag = NULL; + CpaFlatBuffer *pGeneratedKeyBuffer = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean respStatusOk = + (ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? + CPA_TRUE : + CPA_FALSE; + + pCookie = (lac_sym_key_cookie_t *)pOpaqueData; + + if (CPA_TRUE == respStatusOk) { + status = CPA_STATUS_SUCCESS; + LAC_KEY_STAT_INC(numMgfKeyGenCompleted, + pCookie->instanceHandle); + } else { + status = CPA_STATUS_FAIL; + LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, + pCookie->instanceHandle); + } + + pKeyGenMgfCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); + + pMgfOpData = pCookie->pKeyGenOpData; + pCallbackTag = pCookie->pCallbackTag; + pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; + + Lac_MemPoolEntryFree(pCookie); + + (*pKeyGenMgfCb)(pCallbackTag, status, pMgfOpData, pGeneratedKeyBuffer); +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Synchronous mode of operation wrapper function + * + * @description + * Wrapper function to implement synchronous mode of operation for + * cpaCyKeyGenMgf and cpaCyKeyGenMgfExt function. + * + * @param[in] instanceHandle Instance handle + * @param[in] pKeyGenCb Internal callback function pointer + * @param[in] pCallbackTag Callback tag + * @param[in] pKeyGenMgfOpData Pointer to user provided Op Data structure + * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask + * will be stored + * @param[in] bIsExtRequest Indicates origin of function call; + * if CPA_TRUE then the call comes from + * cpaCyKeyGenMgfExt function, otherwise + * from cpaCyKeyGenMgf + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Function should be retried. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + *****************************************************************************/ +static CpaStatus +LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaBoolean bIsExtRequest) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + if (CPA_TRUE == bIsExtRequest) { + status = cpaCyKeyGenMgfExt( + instanceHandle, + LacSync_GenFlatBufCb, + pSyncCallbackData, + (const CpaCyKeyGenMgfOpDataExt *)pKeyGenMgfOpData, + pGeneratedMaskBuffer); + } else { + status = cpaCyKeyGenMgf(instanceHandle, + LacSync_GenFlatBufCb, + pSyncCallbackData, + (const CpaCyKeyGenMgfOpData *) + pKeyGenMgfOpData, + pGeneratedMaskBuffer); + } + } else { + /* Failure allocating sync cookie */ + LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. + */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Perform MGF key gen operation + * + * @description + * This function performs MGF key gen operation. It is common for requests + * coming from both cpaCyKeyGenMgf and cpaCyKeyGenMgfExt QAT API + * functions. + * + * @param[in] instanceHandle Instance handle + * @param[in] pKeyGenCb Pointer to callback function to be invoked + * when the operation is complete. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * @param[in] pOpData Pointer to the Op Data structure provided by + * the user in API function call. For calls + * originating from cpaCyKeyGenMgfExt it will + * point to CpaCyKeyGenMgfOpDataExt type of + * structure while for calls originating from + * cpaCyKeyGenMgf it will point to + * CpaCyKeyGenMgfOpData type of structure. + * @param[in] pKeyGenMgfOpData Pointer to the user provided + * CpaCyKeyGenMgfOpData structure. For calls + * originating from cpaCyKeyGenMgf it will + * point to the same structure as pOpData + * parameter; for calls originating from + * cpaCyKeyGenMgfExt it will point to the + * baseOpData member of the + * CpaCyKeyGenMgfOpDataExt structure passed in + * as a parameter to the API function call. + * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask + * will be stored + * @param[in] hashAlgorithm Indicates which hash algorithm is to be used + * to perform MGF key gen operation. For calls + * originating from cpaCyKeyGenMgf it will + * always be CPA_CY_SYM_HASH_SHA1. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Function should be retried. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + *****************************************************************************/ +static CpaStatus +LacSymKey_MgfCommon(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pOpData, + const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaCySymHashAlgorithm hashAlgorithm) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + icp_qat_fw_la_bulk_req_t keyGenReq = { { 0 } }; + icp_qat_la_bulk_req_hdr_t keyGenReqHdr = { { 0 } }; + icp_qat_fw_la_key_gen_common_t keyGenReqMid = { { 0 } }; + icp_qat_la_bulk_req_ftr_t keyGenReqFtr = { { { 0 } } }; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyMid = NULL; + Cpa8U *pCacheDummyFtr = NULL; + sal_qat_content_desc_info_t contentDescInfo = { 0 }; + lac_sym_key_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + sal_crypto_service_t *pService = NULL; + Cpa64U inputPhysAddr = 0; + Cpa64U outputPhysAddr = 0; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compiler. + */ + CpaCySymHashSetupData hashSetupData = { 0 }; + Cpa32U hashBlkSizeInBytes = 0; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + icp_qat_fw_serv_specif_flags laCmdFlags = 0; + icp_qat_fw_comn_flags cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + pService = (sal_crypto_service_t *)instanceHandle; + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + SAL_RUNNING_CHECK(instanceHandle); + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData); + LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer); + LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer->pData); + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData->seedBuffer.pData); + + /* Maximum seed length for MGF1 request */ + if (pKeyGenMgfOpData->seedBuffer.dataLenInBytes > + ICP_QAT_FW_LA_MGF_SEED_LEN_MAX) { + LAC_INVALID_PARAM_LOG("seedBuffer.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum mask length for MGF1 request */ + if (pKeyGenMgfOpData->maskLenInBytes > ICP_QAT_FW_LA_MGF_MASK_LEN_MAX) { + LAC_INVALID_PARAM_LOG("maskLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* check for enough space in the flat buffer */ + if (pKeyGenMgfOpData->maskLenInBytes > + pGeneratedMaskBuffer->dataLenInBytes) { + LAC_INVALID_PARAM_LOG("pGeneratedMaskBuffer.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get hash alg info */ + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + + /* Allocate the cookie */ + pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pSymCookie = (lac_sym_cookie_t *)pCookie; + } + + if (CPA_STATUS_SUCCESS == status) { + /* populate the cookie */ + pCookie->instanceHandle = instanceHandle; + pCookie->pCallbackTag = pCallbackTag; + pCookie->pKeyGenOpData = (void *)LAC_CONST_PTR_CAST(pOpData); + pCookie->pKeyGenCb = pKeyGenCb; + pCookie->pKeyGenOutputData = pGeneratedMaskBuffer; + hashSetupData.hashAlgorithm = hashAlgorithm; + hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; + hashSetupData.digestResultLenInBytes = + pHashAlgInfo->digestLength; + + /* Populate the CD ctrl Block (LW 27 - LW 31) + * and the CD Hash HW setup block + */ + LacSymQat_HashContentDescInit( + &(keyGenReqFtr), + instanceHandle, + &hashSetupData, + /* point to base of hw setup block */ + (Cpa8U *)pCookie->contentDesc, + LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, + ICP_QAT_FW_SLICE_DRAM_WR, + ICP_QAT_HW_AUTH_MODE0, /* just a plain hash */ + CPA_FALSE, /* Not using sym Constants Table in Shared SRAM + */ + CPA_FALSE, /* not using the optimised Content Desc */ + NULL, + &hashBlkSizeInBytes); + + /* Populate the Req param LW 14-26 */ + LacSymQat_KeyMgfRequestPopulate( + &keyGenReqHdr, + &keyGenReqMid, + pKeyGenMgfOpData->seedBuffer.dataLenInBytes, + pKeyGenMgfOpData->maskLenInBytes, + (Cpa8U)pHashAlgInfo->digestLength); + + contentDescInfo.pData = pCookie->contentDesc; + contentDescInfo.hardwareSetupBlockPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyContentDescPhyAddr); + contentDescInfo.hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); + + /* Populate common request fields */ + inputPhysAddr = + LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pKeyGenMgfOpData->seedBuffer.pData)); + + if (inputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the seed buffer physical address"); + status = CPA_STATUS_FAIL; + } + outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + pGeneratedMaskBuffer->pData)); + if (outputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the mask"); + status = CPA_STATUS_FAIL; + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* Make up the full keyGenReq struct from its constituents */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&( + keyGenReq), + &(contentDescInfo)); + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + ICP_QAT_FW_LA_CMD_MGF1, + cmnRequestFlags, + laCmdFlags); + + /* + * MGF uses a flat buffer but we can use zero for source and + * dest length because the firmware will use the seed length, + * hash length and mask length to find source length. + */ + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), + pCookie, + LAC_SYM_KEY_QAT_PTR_TYPE, + inputPhysAddr, + outputPhysAddr, + 0, + 0); + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(keyGenReq), + LAC_QAT_SYM_REQ_SZ_LW); + } + if (CPA_STATUS_SUCCESS == status) { + /* Update stats */ + LAC_KEY_STAT_INC(numMgfKeyGenRequests, instanceHandle); + } else { + LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); + /* clean up memory */ + if (NULL != pCookie) { + Lac_MemPoolEntryFree(pCookie); + } + } + return status; +} + +/** + * cpaCyKeyGenMgf + */ +CpaStatus +cpaCyKeyGenMgf(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_MgfSync(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpData, + pGeneratedMaskBuffer, + CPA_FALSE); + } + /* Asynchronous Operation */ + return LacSymKey_MgfCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpData, + pKeyGenMgfOpData, + pGeneratedMaskBuffer, + CPA_CY_SYM_HASH_SHA1); +} + +/** + * cpaCyKeyGenMgfExt + */ +CpaStatus +cpaCyKeyGenMgfExt(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpDataExt *pKeyGenMgfOpDataExt, + CpaFlatBuffer *pGeneratedMaskBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_MgfSync(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpDataExt, + pGeneratedMaskBuffer, + CPA_TRUE); + } + + /* Param check specific for Ext function, rest of parameters validated + * in LacSymKey_MgfCommon + */ + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpDataExt); + if (CPA_CY_SYM_HASH_MD5 > pKeyGenMgfOpDataExt->hashAlgorithm || + CPA_CY_SYM_HASH_SHA512 < pKeyGenMgfOpDataExt->hashAlgorithm) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Asynchronous Operation */ + return LacSymKey_MgfCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpDataExt, + &pKeyGenMgfOpDataExt->baseOpData, + pGeneratedMaskBuffer, + pKeyGenMgfOpDataExt->hashAlgorithm); +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Key Generation SSL & TLS response handler + * + * @description + * Handles Key Generation SSL & TLS response messages from the QAT. + * + * @param[in] lacCmdId Command id of the original request + * @param[in] pOpaqueData Pointer to opaque data that was in request + * @param[in] cmnRespFlags LA response flags + * + * @return void + * + *****************************************************************************/ +static void +LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + void *pSslTlsOpData = NULL; + CpaCyGenFlatBufCbFunc pKeyGenSslTlsCb = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + void *pCallbackTag = NULL; + CpaFlatBuffer *pGeneratedKeyBuffer = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + CpaBoolean respStatusOk = + (ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? + CPA_TRUE : + CPA_FALSE; + + pCookie = (lac_sym_key_cookie_t *)pOpaqueData; + + pSslTlsOpData = pCookie->pKeyGenOpData; + + if (CPA_TRUE == respStatusOk) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED, + pCookie->instanceHandle); + } else { + status = CPA_STATUS_FAIL; + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED_ERRORS, + pCookie->instanceHandle); + } + + pKeyGenSslTlsCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); + + pCallbackTag = pCookie->pCallbackTag; + pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; + + Lac_MemPoolEntryFree(pCookie); + + (*pKeyGenSslTlsCb)(pCallbackTag, + status, + pSslTlsOpData, + pGeneratedKeyBuffer); +} + +/** +******************************************************************************* +* @ingroup LacSymKey +* Synchronous mode of operation function wrapper for performing SSL/TLS +* key gen operation +* +* @description +* Synchronous mode of operation function wrapper for performing SSL/TLS +* key gen operation +* +* @param[in] instanceHandle QAT device handle. +* @param[in] pKeyGenCb Pointer to callback function to be invoked +* when the operation is complete. +* @param[in] pCallbackTag Opaque User Data for this specific call. +* @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) +* @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to +* perform the SSL/TLS key generation +* operation. +* @param[in] hashAlgorithm Specifies the hash algorithm to use. +* According to RFC5246, this should be +* "SHA-256 or a stronger standard hash +* function." +* @param[out] pKeyGenOutputData pointer to where output result should be +* written +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Function should be retried. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +*****************************************************************************/ +static CpaStatus +LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutpuData) +{ + lac_sync_op_data_t *pSyncCallbackData = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + if (CPA_STATUS_SUCCESS == status) { + status = LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, + pKeyGenCb, + pSyncCallbackData, + lacCmdId, + pKeyGenSslTlsOpData, + hashAlgorithm, + pKeyGenOutpuData); + } else { + /* Failure allocating sync cookie */ + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUEST_ERRORS, + instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED_ERRORS, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. + */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; +} + +static CpaStatus +computeHashKey(CpaFlatBuffer *secret, + CpaFlatBuffer *hash, + CpaCySymHashAlgorithm *hashAlgorithm) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + switch (*hashAlgorithm) { + case CPA_CY_SYM_HASH_MD5: + status = qatUtilsHashMD5Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA1: + status = qatUtilsHashSHA1Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA256: + status = qatUtilsHashSHA256Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA384: + status = qatUtilsHashSHA384Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA512: + status = qatUtilsHashSHA512Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + default: + status = CPA_STATUS_FAIL; + } + return status; +} + +static CpaStatus +LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgCipher, + CpaFlatBuffer *pKeyGenOutputData) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean precompute = CPA_FALSE; + icp_qat_fw_la_bulk_req_t keyGenReq = { { 0 } }; + icp_qat_la_bulk_req_hdr_t keyGenReqHdr = { { 0 } }; + icp_qat_fw_la_key_gen_common_t keyGenReqMid = { { 0 } }; + icp_qat_la_bulk_req_ftr_t keyGenReqFtr = { { { 0 } } }; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyMid = NULL; + Cpa8U *pCacheDummyFtr = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + Cpa64U inputPhysAddr = 0; + Cpa64U outputPhysAddr = 0; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compiler. + */ + CpaCySymHashSetupData hashSetupData = { 0 }; + sal_qat_content_desc_info_t contentDescInfo = { 0 }; + Cpa32U hashBlkSizeInBytes = 0; + Cpa32U tlsPrefixLen = 0; + + CpaFlatBuffer inputSecret = { 0 }; + CpaFlatBuffer hashKeyOutput = { 0 }; + Cpa32U uSecretLen = 0; + CpaCySymHashNestedModeSetupData *pNestedModeSetupData = + &(hashSetupData.nestedModeSetupData); + icp_qat_fw_serv_specif_flags laCmdFlags = 0; + icp_qat_fw_comn_flags cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_SslTlsSync(instanceHandle, + LacSync_GenFlatBufCb, + pCallbackTag, + lacCmdId, + pKeyGenSslTlsOpData, + hashAlgCipher, + pKeyGenOutputData); + } + /* Allocate the cookie */ + pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pSymCookie = (lac_sym_cookie_t *)pCookie; + } + + if (CPA_STATUS_SUCCESS == status) { + icp_qat_hw_auth_mode_t qatHashMode = 0; + + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + qatHashMode = ICP_QAT_HW_AUTH_MODE0; + } else /* TLS v1.1, v1.2, v1.3 */ + { + qatHashMode = ICP_QAT_HW_AUTH_MODE2; + } + + pCookie->instanceHandle = pService; + pCookie->pCallbackTag = pCallbackTag; + pCookie->pKeyGenCb = pKeyGenCb; + pCookie->pKeyGenOpData = pKeyGenSslTlsOpData; + pCookie->pKeyGenOutputData = pKeyGenOutputData; + hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_NESTED; + + /* SSL3 */ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + hashSetupData.digestResultLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + pNestedModeSetupData->outerHashAlgorithm = + CPA_CY_SYM_HASH_MD5; + + pNestedModeSetupData->pInnerPrefixData = NULL; + pNestedModeSetupData->innerPrefixLenInBytes = 0; + pNestedModeSetupData->pOuterPrefixData = NULL; + pNestedModeSetupData->outerPrefixLenInBytes = 0; + } + /* TLS v1.1 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + + hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + hashSetupData.digestResultLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + pNestedModeSetupData->outerHashAlgorithm = + CPA_CY_SYM_HASH_MD5; + + uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; + + /* We want to handle pre_master_secret > 128 bytes + * therefore we + * only verify if the current operation is Master Secret + * Derive. + * The other operations remain unchanged. + */ + if ((uSecretLen > + ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX) && + (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp || + CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp)) { + CpaCySymHashAlgorithm hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgCipher; + /* secret = [s1 | s2 ] + * s1 = outer prefix, s2 = inner prefix + * length of s1 and s2 = ceil(secret_length / 2) + * (secret length + 1)/2 will always give the + * ceil as + * division by 2 + * (>>1) will give the smallest integral value + * not less than + * arg + */ + tlsPrefixLen = + (pKeyGenTlsOpData->secret.dataLenInBytes + + 1) >> + 1; + inputSecret.dataLenInBytes = tlsPrefixLen; + inputSecret.pData = + pKeyGenTlsOpData->secret.pData; + + /* Since the pre_master_secret is > 128, we + * split the input + * pre_master_secret in 2 halves and compute the + * MD5 of the + * first half and the SHA1 on the second half. + */ + hashAlgorithm = CPA_CY_SYM_HASH_MD5; + + /* Initialize pointer where MD5 key will go. */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer[0]; + hashKeyOutput.dataLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + computeHashKey(&inputSecret, + &hashKeyOutput, + &hashAlgorithm); + + pNestedModeSetupData->pOuterPrefixData = + &pCookie->hashKeyBuffer[0]; + pNestedModeSetupData->outerPrefixLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + + /* Point to the second half of the + * pre_master_secret */ + inputSecret.pData = + pKeyGenTlsOpData->secret.pData + + (pKeyGenTlsOpData->secret.dataLenInBytes - + tlsPrefixLen); + + /* Compute SHA1 on the second half of the + * pre_master_secret + */ + hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + /* Initialize pointer where SHA1 key will go. */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer + [LAC_HASH_MD5_DIGEST_SIZE]; + hashKeyOutput.dataLenInBytes = + LAC_HASH_SHA1_DIGEST_SIZE; + computeHashKey(&inputSecret, + &hashKeyOutput, + &hashAlgorithm); + + pNestedModeSetupData->pInnerPrefixData = + &pCookie->hashKeyBuffer + [LAC_HASH_MD5_DIGEST_SIZE]; + pNestedModeSetupData->innerPrefixLenInBytes = + LAC_HASH_SHA1_DIGEST_SIZE; + } else { + /* secret = [s1 | s2 ] + * s1 = outer prefix, s2 = inner prefix + * length of s1 and s2 = ceil(secret_length / 2) + * (secret length + 1)/2 will always give the + * ceil as + * division by 2 + * (>>1) will give the smallest integral value + * not less than + * arg + */ + tlsPrefixLen = + (pKeyGenTlsOpData->secret.dataLenInBytes + + 1) >> + 1; + /* last byte of s1 will be first byte of s2 if + * Length is odd + */ + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret.pData + + (pKeyGenTlsOpData->secret.dataLenInBytes - + tlsPrefixLen); + + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->innerPrefixLenInBytes = + pNestedModeSetupData + ->outerPrefixLenInBytes = tlsPrefixLen; + } + } + /* TLS v1.2 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + CpaCySymHashAlgorithm hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgCipher; + + uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; + + hashSetupData.hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgorithm; + hashSetupData.digestResultLenInBytes = + (Cpa32U)getDigestSizeFromHashAlgo(hashAlgorithm); + pNestedModeSetupData->outerHashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgorithm; + if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp || + CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp) { + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_SM3: + precompute = CPA_FALSE; + break; + case CPA_CY_SYM_HASH_SHA256: + if (uSecretLen > + ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX) { + precompute = CPA_TRUE; + } + break; + case CPA_CY_SYM_HASH_SHA384: + case CPA_CY_SYM_HASH_SHA512: + if (uSecretLen > + ICP_QAT_FW_LA_TLS_SECRET_LEN_MAX) { + precompute = CPA_TRUE; + } + break; + default: + break; + } + } + if (CPA_TRUE == precompute) { + /* Case when secret > algorithm block size + * RFC 4868: For SHA-256 Block size is 512 bits, + * for SHA-384 + * and SHA-512 Block size is 1024 bits + * Initialize pointer + * where SHAxxx key will go. + */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer[0]; + hashKeyOutput.dataLenInBytes = + hashSetupData.digestResultLenInBytes; + computeHashKey(&pKeyGenTlsOpData->secret, + &hashKeyOutput, + &hashSetupData.hashAlgorithm); + + /* Outer prefix = secret , inner prefix = secret + * secret < 64 bytes + */ + pNestedModeSetupData->pInnerPrefixData = + hashKeyOutput.pData; + pNestedModeSetupData->pOuterPrefixData = + hashKeyOutput.pData; + pNestedModeSetupData->innerPrefixLenInBytes = + hashKeyOutput.dataLenInBytes; + pNestedModeSetupData->outerPrefixLenInBytes = + hashKeyOutput.dataLenInBytes; + } else { + /* Outer prefix = secret , inner prefix = secret + * secret <= 64 bytes + */ + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->secret.dataLenInBytes; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->secret.dataLenInBytes; + } + } + /* TLS v1.3 */ + else if ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId) && + (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= + lacCmdId)) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + CpaCySymHashAlgorithm hashAlgorithm = + getHashAlgorithmFromCipherSuiteHKDF(hashAlgCipher); + + /* Set HASH data */ + hashSetupData.hashAlgorithm = hashAlgorithm; + /* Calculate digest length from the HASH type */ + hashSetupData.digestResultLenInBytes = + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS]; + /* Outer Hash type is the same as inner hash type */ + pNestedModeSetupData->outerHashAlgorithm = + hashAlgorithm; + + /* EXPAND (PRK): + * Outer prefix = secret, inner prefix = secret + * EXTRACT (SEED/SALT): + * Outer prefix = seed, inner prefix = seed + * Secret <= 64 Bytes + * We do not pre compute as secret can't be larger than + * 64 bytes + */ + + if ((ICP_QAT_FW_LA_CMD_HKDF_EXPAND == lacCmdId) || + (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId)) { + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret; + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret; + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->secretLen; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->secretLen; + } else { + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->seed; + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->seed; + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->seedLen; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->seedLen; + } + } + + /* Set the footer Data. + * Note that following function doesn't look at inner/outer + * prefix pointers in nested digest ctx + */ + LacSymQat_HashContentDescInit( + &keyGenReqFtr, + instanceHandle, + &hashSetupData, + pCookie + ->contentDesc, /* Pointer to base of hw setup block */ + LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, + ICP_QAT_FW_SLICE_DRAM_WR, + qatHashMode, + CPA_FALSE, /* Not using sym Constants Table in SRAM */ + CPA_FALSE, /* Not using the optimised content Desc */ + NULL, /* Precompute data */ + &hashBlkSizeInBytes); + + /* SSL3 */ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenSslOpData *pKeyGenSslOpData = + (CpaCyKeyGenSslOpData *)pKeyGenSslTlsOpData; + Cpa8U *pLabel = NULL; + Cpa32U labelLen = 0; + Cpa8U iterations = 0; + Cpa64U labelPhysAddr = 0; + + /* Iterations = ceiling of output required / output per + * iteration Ceiling of a / b = (a + (b-1)) / b + */ + iterations = + (pKeyGenSslOpData->generatedKeyLenInBytes + + (LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION - 1)) >> + LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT; + + if (CPA_CY_KEY_SSL_OP_USER_DEFINED == + pKeyGenSslOpData->sslOp) { + pLabel = pKeyGenSslOpData->userLabel.pData; + labelLen = + pKeyGenSslOpData->userLabel.dataLenInBytes; + labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, pLabel); + + if (labelPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " label"); + status = CPA_STATUS_FAIL; + } + } else { + pLabel = pService->pSslLabel; + + /* Calculate label length. + * eg. 3 iterations is ABBCCC so length is 6 + */ + labelLen = + ((iterations * iterations) + iterations) >> + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } + + LacSymQat_KeySslRequestPopulate( + &keyGenReqHdr, + &keyGenReqMid, + pKeyGenSslOpData->generatedKeyLenInBytes, + labelLen, + pKeyGenSslOpData->secret.dataLenInBytes, + iterations); + + LacSymQat_KeySslKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.sslKeyInput), + pKeyGenSslOpData->seed.pData, + labelPhysAddr, + pKeyGenSslOpData->secret.pData); + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keySslKeyInputPhyAddr); + } + /* TLS v1.1, v1.2 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == lacCmdId || + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + Cpa8U *pLabel = NULL; + Cpa32U labelLen = 0; + Cpa64U labelPhysAddr = 0; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + NULL); /* HKDF only */ + + /* Set up the labels and their length */ + if (CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp) { + pLabel = pKeyGenTlsOpData->userLabel.pData; + labelLen = + pKeyGenTlsOpData->userLabel.dataLenInBytes; + labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, pLabel); + + if (labelPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " label"); + status = CPA_STATUS_FAIL; + } + } else if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->masterSecret; + labelLen = + sizeof( + LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else if (CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->keyMaterial; + labelLen = + sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else if (CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->clientFinished; + labelLen = + sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else { + pLabel = pService->pTlsLabel->serverFinished; + labelLen = + sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + pKeyGenTlsOpData->generatedKeyLenInBytes, + labelLen, + pKeyGenTlsOpData->secret.dataLenInBytes, + pKeyGenTlsOpData->seed.dataLenInBytes, + lacCmdId); + + LacSymQat_KeyTlsKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsKeyInput), + pKeyGenTlsOpData->seed.pData, + labelPhysAddr); + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + /* TLS v1.3 */ + else if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId && + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND >= + lacCmdId) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pKeyGenTlsOpData->secret); /* IKM or PRK */ + + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS], + /* For EXTRACT, EXPAND, FW expects info to be passed + as label */ + pKeyGenTlsOpData->infoLen, + pKeyGenTlsOpData->secretLen, + pKeyGenTlsOpData->seedLen, + lacCmdId); + + LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsHKDFKeyInput), + pKeyGenTlsOpData, + 0, /* No subLabels used */ + lacCmdId); /* Pass op being performed */ + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + /* TLS v1.3 LABEL */ + else if (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId || + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL == + lacCmdId) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + Cpa64U subLabelsPhysAddr = 0; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pKeyGenTlsOpData->secret); /* IKM or PRK */ + + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS], + pKeyGenTlsOpData->numLabels, /* Number of Labels */ + pKeyGenTlsOpData->secretLen, + pKeyGenTlsOpData->seedLen, + lacCmdId); + + /* Get physical address of subLabels */ + switch (hashAlgCipher) { + case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: /* Fall Through + */ + case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: + subLabelsPhysAddr = pService->pTlsHKDFSubLabel + ->sublabelPhysAddr256; + break; + case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: + subLabelsPhysAddr = + pService->pTlsHKDFSubLabel + ->sublabelPhysAddrChaChaPoly; + break; + case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: + subLabelsPhysAddr = pService->pTlsHKDFSubLabel + ->sublabelPhysAddr384; + break; + default: + break; + } + + LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsHKDFKeyInput), + pKeyGenTlsOpData, + subLabelsPhysAddr, + lacCmdId); /* Pass op being performed */ + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + + outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + pKeyGenOutputData->pData)); + + if (outputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " output buffer"); + status = CPA_STATUS_FAIL; + } + } + if (CPA_STATUS_SUCCESS == status) { + Cpa8U lw26[4]; + char *tmp = NULL; + unsigned char a; + int n = 0; + /* Make up the full keyGenReq struct from its constituents + * before calling the SalQatMsg functions below. + * Note: The full cache struct has been reduced to a + * header, mid and footer for memory size reduction + */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(&lw26, + pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + LAC_LONG_WORD_IN_BYTES); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + tmp = (char *)(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW)); + + /* Copy LW26, or'd with what's already there, into the Msg, for + * TLS */ + for (n = 0; n < LAC_LONG_WORD_IN_BYTES; n++) { + a = (unsigned char)*(tmp + n); + lw26[n] = lw26[n] | a; + } + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + &lw26, + LAC_LONG_WORD_IN_BYTES); + + contentDescInfo.pData = pCookie->contentDesc; + contentDescInfo.hardwareSetupBlockPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyContentDescPhyAddr); + contentDescInfo.hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); + + /* Populate common request fields */ + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&( + keyGenReq), + &(contentDescInfo)); + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + lacCmdId, + cmnRequestFlags, + laCmdFlags); + + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), + pCookie, + LAC_SYM_KEY_QAT_PTR_TYPE, + inputPhysAddr, + outputPhysAddr, + 0, + 0); + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(keyGenReq), + LAC_QAT_SYM_REQ_SZ_LW); + } + if (CPA_STATUS_SUCCESS == status) { + /* Update stats */ + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUESTS, + pCookie->instanceHandle); + } else { + /* Clean up cookie memory */ + if (NULL != pCookie) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUEST_ERRORS, + pCookie->instanceHandle); + Lac_MemPoolEntryFree(pCookie); + } + } + return status; +} + +/** + * @ingroup LacSymKey + * Parameters check for TLS v1.0/1.1, v1.2, v1.3 and SSL3 + * @description + * Check user parameters against the firmware/spec requirements. + * + * @param[in] pKeyGenOpData Pointer to a structure containing all + * the data needed to perform the key + * generation operation. + * @param[in] hashAlgCipher Specifies the hash algorithm, + * or cipher we are using. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[in] pGeneratedKeyBuffer User output buffers. + * @param[in] cmdId Keygen operation to perform. + */ +static CpaStatus +LacSymKey_CheckParamSslTls(const void *pKeyGenOpData, + Cpa8U hashAlgCipher, + const CpaFlatBuffer *pGeneratedKeyBuffer, + icp_qat_fw_la_cmd_id_t cmdId) +{ + /* Api max value */ + Cpa32U maxSecretLen = 0; + Cpa32U maxSeedLen = 0; + Cpa32U maxOutputLen = 0; + Cpa32U maxInfoLen = 0; + Cpa32U maxLabelLen = 0; + + /* User info */ + Cpa32U uSecretLen = 0; + Cpa32U uSeedLen = 0; + Cpa32U uOutputLen = 0; + + LAC_CHECK_NULL_PARAM(pKeyGenOpData); + LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer); + LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer->pData); + + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == cmdId) { + CpaCyKeyGenSslOpData *opData = + (CpaCyKeyGenSslOpData *)pKeyGenOpData; + + /* User info */ + uSecretLen = opData->secret.dataLenInBytes; + uSeedLen = opData->seed.dataLenInBytes; + uOutputLen = opData->generatedKeyLenInBytes; + + /* Api max value */ + maxSecretLen = ICP_QAT_FW_LA_SSL_SECRET_LEN_MAX; + maxSeedLen = ICP_QAT_FW_LA_SSL_SEED_LEN_MAX; + maxOutputLen = ICP_QAT_FW_LA_SSL_OUTPUT_LEN_MAX; + + /* Check user buffers */ + LAC_CHECK_NULL_PARAM(opData->secret.pData); + LAC_CHECK_NULL_PARAM(opData->seed.pData); + + /* Check operation */ + if ((Cpa32U)opData->sslOp > CPA_CY_KEY_SSL_OP_USER_DEFINED) { + LAC_INVALID_PARAM_LOG("opData->sslOp"); + return CPA_STATUS_INVALID_PARAM; + } + if ((Cpa32U)opData->sslOp == CPA_CY_KEY_SSL_OP_USER_DEFINED) { + LAC_CHECK_NULL_PARAM(opData->userLabel.pData); + /* Maximum label length for SSL Key Gen request */ + if (opData->userLabel.dataLenInBytes > + ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX) { + LAC_INVALID_PARAM_LOG( + "userLabel.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Only seed length for SSL3 Key Gen request */ + if (maxSeedLen != uSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum output length for SSL3 Key Gen request */ + if (uOutputLen > maxOutputLen) { + LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* TLS v1.1 or TLS v.12 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId || + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == cmdId) { + CpaCyKeyGenTlsOpData *opData = + (CpaCyKeyGenTlsOpData *)pKeyGenOpData; + + /* User info */ + uSecretLen = opData->secret.dataLenInBytes; + uSeedLen = opData->seed.dataLenInBytes; + uOutputLen = opData->generatedKeyLenInBytes; + + if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId) { + /* Api max value */ + /* ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX needs to be + * multiplied + * by 4 in order to verifiy the 512 conditions. We did + * not change + * ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX as it + * represents + * the max value tha firmware can handle. + */ + maxSecretLen = + ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX * 4; + } else { + /* Api max value */ + /* ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX needs to be + * multiplied + * by 8 in order to verifiy the 512 conditions. We did + * not change + * ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX as it + * represents + * the max value tha firmware can handle. + */ + maxSecretLen = + ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX * 8; + + /* Check Hash algorithm */ + if (0 == getDigestSizeFromHashAlgo(hashAlgCipher)) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + maxSeedLen = ICP_QAT_FW_LA_TLS_SEED_LEN_MAX; + maxOutputLen = ICP_QAT_FW_LA_TLS_OUTPUT_LEN_MAX; + /* Check user buffers */ + LAC_CHECK_NULL_PARAM(opData->secret.pData); + LAC_CHECK_NULL_PARAM(opData->seed.pData); + + /* Check operation */ + if ((Cpa32U)opData->tlsOp > CPA_CY_KEY_TLS_OP_USER_DEFINED) { + LAC_INVALID_PARAM_LOG("opData->tlsOp"); + return CPA_STATUS_INVALID_PARAM; + } else if ((Cpa32U)opData->tlsOp == + CPA_CY_KEY_TLS_OP_USER_DEFINED) { + LAC_CHECK_NULL_PARAM(opData->userLabel.pData); + /* Maximum label length for TLS Key Gen request */ + if (opData->userLabel.dataLenInBytes > + ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX) { + LAC_INVALID_PARAM_LOG( + "userLabel.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Maximum/only seed length for TLS Key Gen request */ + if (((Cpa32U)opData->tlsOp != + CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE) && + ((Cpa32U)opData->tlsOp != + CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE)) { + if (uSeedLen > maxSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + if (maxSeedLen != uSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Maximum output length for TLS Key Gen request */ + if (uOutputLen > maxOutputLen) { + LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* TLS v1.3 */ + else if (cmdId >= ICP_QAT_FW_LA_CMD_HKDF_EXTRACT && + cmdId <= ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL) { + CpaCyKeyGenHKDFOpData *HKDF_Data = + (CpaCyKeyGenHKDFOpData *)pKeyGenOpData; + CpaCyKeyHKDFCipherSuite cipherSuite = hashAlgCipher; + CpaCySymHashAlgorithm hashAlgorithm = + getHashAlgorithmFromCipherSuiteHKDF(cipherSuite); + maxSeedLen = + cipherSuiteHKDFHashSizes[cipherSuite][LAC_KEY_HKDF_DIGESTS]; + maxSecretLen = CPA_CY_HKDF_KEY_MAX_SECRET_SZ; + maxInfoLen = CPA_CY_HKDF_KEY_MAX_INFO_SZ; + maxLabelLen = CPA_CY_HKDF_KEY_MAX_LABEL_SZ; + + uSecretLen = HKDF_Data->secretLen; + + /* Check using supported hash function */ + if (0 == + (uOutputLen = getDigestSizeFromHashAlgo(hashAlgorithm))) { + LAC_INVALID_PARAM_LOG("Hash function not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Number of labels does not exceed the MAX */ + if (HKDF_Data->numLabels > CPA_CY_HKDF_KEY_MAX_LABEL_COUNT) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.numLabels"); + return CPA_STATUS_INVALID_PARAM; + } + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + maxSecretLen = + cipherSuiteHKDFHashSizes[cipherSuite] + [LAC_KEY_HKDF_DIGESTS]; + + if (maxInfoLen < HKDF_Data->infoLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.infoLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + uOutputLen *= 2; + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + if (maxInfoLen < HKDF_Data->infoLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.infoLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: /* Fall through */ + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: { + Cpa8U subl_mask = 0, subl_number = 1; + Cpa8U i = 0; + + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + + /* If EXPAND set uOutputLen to zero */ + if (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == cmdId) { + uOutputLen = 0; + maxSecretLen = cipherSuiteHKDFHashSizes + [cipherSuite][LAC_KEY_HKDF_DIGESTS]; + } + + for (i = 0; i < HKDF_Data->numLabels; i++) { + /* Check that the labelLen does not overflow */ + if (maxLabelLen < + HKDF_Data->label[i].labelLen) { + LAC_INVALID_PARAM_LOG1( + "CpaCyKeyGenHKDFOpData.label[%d].labelLen", + i); + return CPA_STATUS_INVALID_PARAM; + } + + if (HKDF_Data->label[i].sublabelFlag & + ~HKDF_SUB_LABELS_ALL) { + LAC_INVALID_PARAM_LOG1( + "CpaCyKeyGenHKDFOpData.label[%d]." + "subLabelFlag", + i); + return CPA_STATUS_INVALID_PARAM; + } + + /* Calculate the appended subLabel output + * lengths and + * check that the output buffer that the user + * has + * supplied is the correct length. + */ + uOutputLen += cipherSuiteHKDFHashSizes + [cipherSuite][LAC_KEY_HKDF_DIGESTS]; + /* Get mask of subLabel */ + subl_mask = HKDF_Data->label[i].sublabelFlag; + + for (subl_number = 1; + subl_number <= LAC_KEY_HKDF_SUBLABELS_NUM; + subl_number++) { + /* Add the used subLabel key lengths */ + if (subl_mask & 1) { + uOutputLen += + cipherSuiteHKDFHashSizes + [cipherSuite] + [subl_number]; + } + subl_mask >>= 1; + } + } + } break; + default: + break; + } + } else { + LAC_INVALID_PARAM_LOG("TLS/SSL operation"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum secret length for TLS/SSL Key Gen request */ + if (uSecretLen > maxSecretLen) { + LAC_INVALID_PARAM_LOG("HKFD.secretLen/secret.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check for enough space in the flat buffer */ + if (uOutputLen > pGeneratedKeyBuffer->dataLenInBytes) { + LAC_INVALID_PARAM_LOG("pGeneratedKeyBuffer->dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +/** + * + */ +/** + * @ingroup LacSymKey + * Common Keygen Code for TLS v1.0/1.1, v1.2 and SSL3. + * @description + * Check user parameters and perform the required operation. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenOpData Pointer to a structure containing all + * the data needed to perform the key + * generation operation. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer User output buffer. + * @param[in] cmdId Keygen operation to perform. + */ +static CpaStatus +LacSymKey_KeyGenSslTls(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pGeneratedKeyBuffer, + icp_qat_fw_la_cmd_id_t cmdId) +{ + CpaStatus status = CPA_STATUS_FAIL; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + CpaCyCapabilitiesInfo cyCapInfo; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + SAL_RUNNING_CHECK(instanceHandle); + SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo); + + if (IS_HKDF_UNSUPPORTED(cmdId, cyCapInfo.hkdfSupported)) { + LAC_LOG_ERROR("The device does not support HKDF"); + return CPA_STATUS_UNSUPPORTED; + } + + status = LacSymKey_CheckParamSslTls(pKeyGenOpData, + hashAlgorithm, + pGeneratedKeyBuffer, + cmdId); + if (CPA_STATUS_SUCCESS != status) + return status; + return LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + cmdId, + LAC_CONST_PTR_CAST( + pKeyGenOpData), + hashAlgorithm, + pGeneratedKeyBuffer); +} + +/** + * @ingroup LacSymKey + * SSL Key Generation Function. + * @description + * This function is used for SSL key generation. It implements the key + * generation function defined in section 6.2.2 of the SSL 3.0 + * specification as described in + * http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt. + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenSslOpData Pointer to a structure containing all + * the data needed to perform the SSL key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenSsl(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenSslOpData *pKeyGenSslOpData, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenSslOpData), + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * TLS Key Generation Function. + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC2246 (TLS v1.0) + * and RFC4346 (TLS v1.1). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing all + * the data needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + */ +CpaStatus +cpaCyKeyGenTls(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC5246 (TLS v1.2). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing all + * the data needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenTls2(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaCySymHashAlgorithm hashAlgorithm, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + hashAlgorithm, + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * @description + * This function is used for TLS1.3 HKDF key generation. It implements + * the "extract-then-expand" paradigm as defined by RFC 5869. + * + * The input seed/secret/info is taken as a flat buffer and the generated + * key(s)/labels are returned to caller in a flat data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing + * the data needed to perform the HKDF key + * generation operation. + * The client code allocates the memory + * for this structure as contiguous + * pinned memory. + * This component takes ownership of the + * memory until it is returned in the + * callback. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenTls3(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + CpaCyKeyHKDFCipherSuite cipherSuite, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + + LAC_CHECK_NULL_PARAM(pKeyGenTlsOpData); + switch (pKeyGenTlsOpData->hkdfKeyOp) { + case CPA_CY_HKDF_KEY_EXTRACT: /* Fall through */ + case CPA_CY_HKDF_KEY_EXPAND: + case CPA_CY_HKDF_KEY_EXTRACT_EXPAND: + case CPA_CY_HKDF_KEY_EXPAND_LABEL: + case CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL: + break; + default: + LAC_INVALID_PARAM_LOG("HKDF operation not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + + return LacSymKey_KeyGenSslTls(instanceHandle_in, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + cipherSuite, + pGeneratedKeyBuffer, + (icp_qat_fw_la_cmd_id_t) + pKeyGenTlsOpData->hkdfKeyOp); +} + +/* + * LacSymKey_Init + */ +CpaStatus +LacSymKey_Init(CpaInstanceHandle instanceHandle_in) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + sal_crypto_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + pService->pLacKeyStats = + LAC_OS_MALLOC(LAC_KEY_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (NULL != pService->pLacKeyStats) { + LAC_OS_BZERO((void *)pService->pLacKeyStats, + LAC_KEY_NUM_STATS * sizeof(QatUtilsAtomic)); + + status = LAC_OS_CAMALLOC(&pService->pSslLabel, + ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX, + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } else { + status = CPA_STATUS_RESOURCE; + } + + if (CPA_STATUS_SUCCESS == status) { + Cpa32U i = 0; + Cpa32U offset = 0; + + /* Initialise SSL label ABBCCC..... */ + for (i = 0; i < ICP_QAT_FW_LA_SSL_ITERATES_LEN_MAX; i++) { + memset(pService->pSslLabel + offset, 'A' + i, i + 1); + offset += (i + 1); + } + + /* Allocate memory for TLS labels */ + status = LAC_OS_CAMALLOC(&pService->pTlsLabel, + sizeof(lac_sym_key_tls_labels_t), + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } + + if (CPA_STATUS_SUCCESS == status) { + /* Allocate memory for HKDF sub_labels */ + status = + LAC_OS_CAMALLOC(&pService->pTlsHKDFSubLabel, + sizeof(lac_sym_key_tls_hkdf_sub_labels_t), + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } + + if (CPA_STATUS_SUCCESS == status) { + LAC_OS_BZERO(pService->pTlsLabel, + sizeof(lac_sym_key_tls_labels_t)); + + /* Copy the TLS v1.2 labels into the dynamically allocated + * structure */ + memcpy(pService->pTlsLabel->masterSecret, + LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL, + sizeof(LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - 1); + + memcpy(pService->pTlsLabel->keyMaterial, + LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL, + sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - 1); + + memcpy(pService->pTlsLabel->clientFinished, + LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL, + sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - 1); + + memcpy(pService->pTlsLabel->serverFinished, + LAC_SYM_KEY_TLS_SERVER_FIN_LABEL, + sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - 1); + + LAC_OS_BZERO(pService->pTlsHKDFSubLabel, + sizeof(lac_sym_key_tls_hkdf_sub_labels_t)); + + /* Copy the TLS v1.3 subLabels into the dynamically allocated + * struct */ + /* KEY SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabel256, + &key256, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabel256.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabel256.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS; + /* KEY SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabel384, + &key384, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabel384.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabel384.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; + /* KEY CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabelChaChaPoly, + &keyChaChaPoly, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.sublabelFlag = + 1 << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; + /* IV SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabel256, + &iv256, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabel256.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabel256.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* IV SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabel384, + &iv384, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabel384.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabel384.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* IV CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly, + &iv256, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.sublabelFlag = + 1 << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* RESUMPTION SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel256, + &resumption256, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabel256.labelLen = + HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* RESUMPTION SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel384, + &resumption384, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabel384.labelLen = + HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* RESUMPTION CHACHAPOLY */ + memcpy( + &pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly, + &resumption256, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly + .labelLen = HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* FINISHED SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel256, + &finished256, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabel256.labelLen = + HKDF_SUB_LABEL_FINISHED_LENGTH; + /* FINISHED SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel384, + &finished384, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabel384.labelLen = + HKDF_SUB_LABEL_FINISHED_LENGTH; + /* FINISHED CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly, + &finished256, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly + .labelLen = HKDF_SUB_LABEL_FINISHED_LENGTH; + + /* Set physical address of sublabels */ + pService->pTlsHKDFSubLabel->sublabelPhysAddr256 = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabel256); + pService->pTlsHKDFSubLabel->sublabelPhysAddr384 = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabel384); + pService->pTlsHKDFSubLabel->sublabelPhysAddrChaChaPoly = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabelChaChaPoly); + + /* Register request handlers */ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXTRACT, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXPAND, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_MGF1, + LacSymKey_MgfHandleResponse); + } + + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(pService->pLacKeyStats); + LAC_OS_CAFREE(pService->pSslLabel); + LAC_OS_CAFREE(pService->pTlsLabel); + LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); + } + + return status; +} + +/* + * LacSymKey_Shutdown + */ +CpaStatus +LacSymKey_Shutdown(CpaInstanceHandle instanceHandle_in) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + sal_crypto_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + if (NULL != pService->pLacKeyStats) { + LAC_OS_FREE(pService->pLacKeyStats); + } + + LAC_OS_CAFREE(pService->pSslLabel); + LAC_OS_CAFREE(pService->pTlsLabel); + LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); + + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c new file mode 100644 index 00000000000..c2d30c77eea --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c @@ -0,0 +1,1860 @@ +/*************************************************************************** + * + * + * + ***************************************************************************/ + +/** + *************************************************************************** + * @file lac_sym_alg_chain.c Algorithm Chaining Perform + * + * @ingroup LacAlgChain + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_mem.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_list.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_sym_alg_chain.h" +#include "lac_sym_cipher.h" +#include "lac_sym_cipher_defs.h" +#include "lac_sym_hash.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_stats.h" +#include "lac_sym_queue.h" +#include "lac_sym_cb.h" +#include "sal_string_parse.h" +#include "lac_sym_auth_enc.h" +#include "lac_sym_qat.h" + +/** + * @ingroup LacAlgChain + * Function which checks for support of partial packets for symmetric + * crypto operations + * + * @param[in] pService Pointer to service descriptor + * @param[in/out] pSessionDesc Pointer to session descriptor + * + */ +static void +LacSymCheck_IsPartialSupported(Cpa32U capabilitiesMask, + lac_session_desc_t *pSessionDesc) +{ + CpaBoolean isHashPartialSupported = CPA_FALSE; + CpaBoolean isCipherPartialSupported = CPA_FALSE; + CpaBoolean isPartialSupported = CPA_FALSE; + + switch (pSessionDesc->cipherAlgorithm) { + /* Following ciphers don't support partial */ + case CPA_CY_SYM_CIPHER_KASUMI_F8: + case CPA_CY_SYM_CIPHER_AES_F8: + case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: + case CPA_CY_SYM_CIPHER_CHACHA: + case CPA_CY_SYM_CIPHER_ZUC_EEA3: + break; + /* All others support partial */ + default: + isCipherPartialSupported = CPA_TRUE; + } + switch (pSessionDesc->hashAlgorithm) { + /* Following hash don't support partial */ + case CPA_CY_SYM_HASH_KASUMI_F9: + case CPA_CY_SYM_HASH_SNOW3G_UIA2: + case CPA_CY_SYM_HASH_POLY: + case CPA_CY_SYM_HASH_ZUC_EIA3: + case CPA_CY_SYM_HASH_SHAKE_128: + case CPA_CY_SYM_HASH_SHAKE_256: + break; + /* Following hash may support partial based on device capabilities */ + case CPA_CY_SYM_HASH_SHA3_256: + if (ICP_ACCEL_CAPABILITIES_SHA3_EXT & capabilitiesMask) { + isHashPartialSupported = CPA_TRUE; + } + break; + /* All others support partial */ + default: + isHashPartialSupported = CPA_TRUE; + } + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: + isPartialSupported = isCipherPartialSupported; + break; + case CPA_CY_SYM_OP_HASH: + isPartialSupported = isHashPartialSupported; + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + if (isCipherPartialSupported && isHashPartialSupported) { + isPartialSupported = CPA_TRUE; + } + break; + case CPA_CY_SYM_OP_NONE: + break; + } + pSessionDesc->isPartialSupported = isPartialSupported; +} + +/** + * @ingroup LacAlgChain + * This callback function will be invoked whenever a hash precompute + * operation completes. It will dequeue and send any QAT requests + * which were queued up while the precompute was in progress. + * + * @param[in] callbackTag Opaque value provided by user. This will + * be a pointer to the session descriptor. + * + * @retval + * None + * + */ +static void +LacSymAlgChain_HashPrecomputeDoneCb(void *callbackTag) +{ + LacSymCb_PendingReqsDequeue((lac_session_desc_t *)callbackTag); +} + +/** + * @ingroup LacAlgChain + * Walk the buffer list and find the address for the given offset within + * a buffer. + * + * @param[in] pBufferList Buffer List + * @param[in] packetOffset Offset in the buffer list for which address + * is to be found. + * @param[out] ppDataPtr This is where the sought pointer will be put + * @param[out] pSpaceLeft Pointer to a variable in which information about + * available space from the given offset to the end + * of the flat buffer it is located in will be returned + * + * @retval CPA_STATUS_SUCCESS Address with a given offset is found in the list + * @retval CPA_STATUS_FAIL Address with a given offset not found in the list. + * + */ +static CpaStatus +LacSymAlgChain_PtrFromOffsetGet(const CpaBufferList *pBufferList, + const Cpa32U packetOffset, + Cpa8U **ppDataPtr) +{ + Cpa32U currentOffset = 0; + Cpa32U i = 0; + + for (i = 0; i < pBufferList->numBuffers; i++) { + Cpa8U *pCurrData = pBufferList->pBuffers[i].pData; + Cpa32U currDataSize = pBufferList->pBuffers[i].dataLenInBytes; + + /* If the offset is within the address space of the current + * buffer */ + if ((packetOffset >= currentOffset) && + (packetOffset < (currentOffset + currDataSize))) { + /* increment by offset of the address in the current + * buffer */ + *ppDataPtr = pCurrData + (packetOffset - currentOffset); + return CPA_STATUS_SUCCESS; + } + + /* Increment by the size of the buffer */ + currentOffset += currDataSize; + } + + return CPA_STATUS_FAIL; +} + +static void +LacAlgChain_CipherCDBuild(const CpaCySymCipherSetupData *pCipherData, + lac_session_desc_t *pSessionDesc, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherOffsetInConstantsTable, + icp_qat_fw_comn_flags *pCmnRequestFlags, + icp_qat_fw_serv_specif_flags *pLaCmdFlags, + Cpa8U *pHwBlockBaseInDRAM, + Cpa32U *pHwBlockOffsetInDRAM) +{ + Cpa8U *pCipherKeyField = NULL; + Cpa8U cipherOffsetInReqQW = 0; + Cpa32U sizeInBytes = 0; + + /* Construct the ContentDescriptor in DRAM */ + cipherOffsetInReqQW = (*pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES); + ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET( + *pLaCmdFlags, ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP); + + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + *pHwBlockOffsetInDRAM, + &sizeInBytes); + + *pHwBlockOffsetInDRAM += sizeInBytes; + + /* Cipher key will be in CD in DRAM. + * The Request contains a ptr to the CD. + * This ptr will be copied into the request later once the CD is + * fully constructed, but the flag is set here. */ + pCipherKeyField = pHwBlockBaseInDRAM + *pHwBlockOffsetInDRAM; + ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(*pCmnRequestFlags, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + LacSymQat_CipherHwBlockPopulateKeySetup( + pCipherData, + pCipherData->cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + /* update offset */ + *pHwBlockOffsetInDRAM += sizeInBytes; + + LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->reqCacheFtr), + pSessionDesc->cipherAlgorithm, + pSessionDesc->cipherKeyLenInBytes, + nextSlice, + cipherOffsetInReqQW); + if (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CHACHA(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherCtrlBlockWrite( + &(pSessionDesc->reqSpcCacheFtr), + pSessionDesc->cipherAlgorithm, + pSessionDesc->cipherKeyLenInBytes, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInReqQW); + } +} + +static void +LacAlgChain_HashCDBuild( + const CpaCySymHashSetupData *pHashData, + CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + icp_qat_fw_slice_t nextSlice, + Cpa8U hashOffsetInConstantsTable, + icp_qat_fw_comn_flags *pCmnRequestFlags, + icp_qat_fw_serv_specif_flags *pLaCmdFlags, + lac_sym_qat_hash_precompute_info_t *pPrecomputeData, + lac_sym_qat_hash_precompute_info_t *pPrecomputeDataOptimisedCd, + Cpa8U *pHwBlockBaseInDRAM, + Cpa32U *pHwBlockOffsetInDRAM, + Cpa8U *pOptimisedHwBlockBaseInDRAM, + Cpa32U *pOptimisedHwBlockOffsetInDRAM) +{ + Cpa32U sizeInBytes = 0; + Cpa32U hwBlockOffsetInQuadWords = + *pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES; + + /* build: + * - the hash part of the ContentDescriptor in DRAM */ + /* - the hash part of the CD control block in the Request template */ + LacSymQat_HashContentDescInit(&(pSessionDesc->reqCacheFtr), + instanceHandle, + pHashData, + pHwBlockBaseInDRAM, + hwBlockOffsetInQuadWords, + nextSlice, + pSessionDesc->qatHashMode, + CPA_FALSE, + CPA_FALSE, + pPrecomputeData, + &sizeInBytes); + + /* Using DRAM CD so update offset */ + *pHwBlockOffsetInDRAM += sizeInBytes; + + sizeInBytes = 0; +} + +CpaStatus +LacAlgChain_SessionAADUpdate(lac_session_desc_t *pSessionDesc, + Cpa32U newAADLength) +{ + icp_qat_la_bulk_req_ftr_t *req_ftr = &pSessionDesc->reqCacheFtr; + icp_qat_la_auth_req_params_t *req_params = &req_ftr->serv_specif_rqpars; + + if (!pSessionDesc) + return CPA_STATUS_FAIL; + + pSessionDesc->aadLenInBytes = newAADLength; + req_params->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(newAADLength, LAC_HASH_AES_GCM_BLOCK_SIZE); + + if (CPA_TRUE == pSessionDesc->isSinglePass) { + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U pSizeInBytes = 0; + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + + pHwBlockBaseInDRAM = + (Cpa8U *)pSessionDesc->contentDescInfo.pData; + if (pSessionDesc->cipherDirection == + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT) { + if (LAC_CIPHER_IS_GCM(cipher)) { + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + } else { + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + } + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &pSizeInBytes); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacAlgChain_SessionCipherKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pCipherKey) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + if (pSessionDesc == NULL || pCipherKey == NULL) + return CPA_STATUS_FAIL; + + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherArc4StateInit( + pCipherKey, + pSessionDesc->cipherKeyLenInBytes, + pSessionDesc->cipherARC4InitialState); + } else { + CpaCySymCipherSetupData cipherSetupData = { 0 }; + Cpa32U sizeInBytes; + Cpa8U *pCipherKeyField; + sal_qat_content_desc_info_t *pCdInfo = + &(pSessionDesc->contentDescInfo); + + cipherSetupData.cipherAlgorithm = pSessionDesc->cipherAlgorithm; + cipherSetupData.cipherKeyLenInBytes = + pSessionDesc->cipherKeyLenInBytes; + cipherSetupData.pCipherKey = pCipherKey; + + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: { + pCipherKeyField = (Cpa8U *)pCdInfo->pData + + sizeof(icp_qat_hw_cipher_config_t); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + + if (pSessionDesc->useSymConstantsTable) { + pCipherKeyField = (Cpa8U *)&( + pSessionDesc->shramReqCacheHdr.cd_pars.s1 + .serv_specif_fields); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + } + } break; + + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: { + icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t + *)&pSessionDesc->reqCacheFtr.cd_ctrl; + + pCipherKeyField = (Cpa8U *)pCdInfo->pData + + cd_ctrl->cipher_cfg_offset * + LAC_QUAD_WORD_IN_BYTES + + sizeof(icp_qat_hw_cipher_config_t); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + } break; + + default: + LAC_LOG_ERROR("Invalid sym operation\n"); + status = CPA_STATUS_INVALID_PARAM; + break; + } + } + return status; +} + +CpaStatus +LacAlgChain_SessionAuthKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pAuthKey) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa8U *pOutHashSetup = NULL; + Cpa8U *pInnerState1 = NULL; + Cpa8U *pInnerState2 = NULL; + CpaCySymSessionSetupData sessionSetup = { 0 }; + + if (pSessionDesc == NULL || pAuthKey == NULL) + return CPA_STATUS_FAIL; + + icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr + .cd_ctrl; + + pHwBlockBaseInDRAM = (Cpa8U *)pSessionDesc->contentDescInfo.pData; + + sessionSetup.hashSetupData.hashAlgorithm = pSessionDesc->hashAlgorithm; + sessionSetup.hashSetupData.hashMode = pSessionDesc->hashMode; + sessionSetup.hashSetupData.authModeSetupData.authKey = pAuthKey; + sessionSetup.hashSetupData.authModeSetupData.authKeyLenInBytes = + pSessionDesc->authKeyLenInBytes; + sessionSetup.hashSetupData.authModeSetupData.aadLenInBytes = + pSessionDesc->aadLenInBytes; + sessionSetup.hashSetupData.digestResultLenInBytes = + pSessionDesc->hashResultSize; + + sessionSetup.cipherSetupData.cipherAlgorithm = + pSessionDesc->cipherAlgorithm; + sessionSetup.cipherSetupData.cipherKeyLenInBytes = + pSessionDesc->cipherKeyLenInBytes; + + /* Calculate hash states offsets */ + pInnerState1 = pHwBlockBaseInDRAM + + cd_ctrl->hash_cfg_offset * LAC_QUAD_WORD_IN_BYTES + + sizeof(icp_qat_hw_auth_setup_t); + + pInnerState2 = pInnerState1 + cd_ctrl->inner_state1_sz; + + pOutHashSetup = pInnerState2 + cd_ctrl->inner_state2_sz; + + /* Calculate offset of cipher key */ + if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER_HASH) { + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } else if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_HASH_CIPHER) { + sessionSetup.cipherSetupData.pCipherKey = + pOutHashSetup + sizeof(icp_qat_hw_cipher_config_t); + } else if (CPA_TRUE == pSessionDesc->isSinglePass) { + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + Cpa32U hwBlockOffsetInDRAM = 0; + + if (pSessionDesc->cipherDirection == + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) { + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } else { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + hwBlockOffsetInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } + } + + if (!sessionSetup.cipherSetupData.pCipherKey) + return CPA_STATUS_FAIL; + + if (CPA_CY_SYM_HASH_SHA3_256 == pSessionDesc->hashAlgorithm) { + if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { + lac_sym_qat_hash_state_buffer_info_t + *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + + sal_crypto_service_t *pService = + (sal_crypto_service_t *)pSessionDesc->pInstance; + + status = LacHash_StatePrefixAadBufferInit( + &(pService->generic_service_info), + &(sessionSetup.hashSetupData), + &(pSessionDesc->reqCacheFtr), + pSessionDesc->qatHashMode, + pSessionDesc->hashStatePrefixBuffer, + pHashStateBufferInfo); + /* SHRAM Constants Table not used for Auth-Enc */ + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) { + Cpa8U *authKey = + (Cpa8U *)pOutHashSetup + sizeof(icp_qat_hw_cipher_config_t); + memcpy(authKey, pAuthKey, pSessionDesc->authKeyLenInBytes); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CBC_MAC == pSessionDesc->hashAlgorithm) { + memcpy(pInnerState2, pAuthKey, pSessionDesc->authKeyLenInBytes); + } else if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_KASUMI_F9 == pSessionDesc->hashAlgorithm || + IS_HASH_MODE_1(pSessionDesc->qatHashMode)) { + if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm) { + memset(pInnerState2, 0, cd_ctrl->inner_state2_sz); + } + + /* Block messages until precompute is completed */ + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + + status = LacHash_PrecomputeDataCreate( + pSessionDesc->pInstance, + (CpaCySymSessionSetupData *)&(sessionSetup), + LacSymAlgChain_HashPrecomputeDoneCb, + pSessionDesc, + pSessionDesc->hashStatePrefixBuffer, + pInnerState1, + pInnerState2); + } + + return status; +} + +/** @ingroup LacAlgChain */ +CpaStatus +LacAlgChain_SessionInit(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus stat, status = CPA_STATUS_SUCCESS; + sal_qat_content_desc_info_t *pCdInfo = NULL; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + Cpa32U capabilitiesMask = + pService->generic_service_info.capabilitiesMask; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa8U *pOptimisedHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U optimisedHwBlockOffsetInDRAM = 0; + Cpa8U cipherOffsetInConstantsTable = 0; + Cpa8U hashOffsetInConstantsTable = 0; + icp_qat_fw_comn_req_t *pMsg = NULL; + const CpaCySymCipherSetupData *pCipherData; + const CpaCySymHashSetupData *pHashData; + Cpa16U proto = ICP_QAT_FW_LA_NO_PROTO; /* no CCM/GCM/Snow3G */ + CpaCySymAlgChainOrder chainOrder = 0; + lac_sym_qat_hash_precompute_info_t precomputeData = { 0 }; + lac_sym_qat_hash_precompute_info_t precomputeDataOptimisedCd = { 0 }; + + pCipherData = &(pSessionSetupData->cipherSetupData); + pHashData = &(pSessionSetupData->hashSetupData); + + /*------------------------------------------------------------------------- + * Populate session data + *-----------------------------------------------------------------------*/ + + /* Initialise Request Queue */ + stat = LAC_SPINLOCK_INIT(&pSessionDesc->requestQueueLock); + if (CPA_STATUS_SUCCESS != stat) { + LAC_LOG_ERROR("Spinlock init failed for sessionLock"); + return CPA_STATUS_RESOURCE; + } + + pSessionDesc->pRequestQueueHead = NULL; + pSessionDesc->pRequestQueueTail = NULL; + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + pSessionDesc->pInstance = instanceHandle; + pSessionDesc->digestIsAppended = pSessionSetupData->digestIsAppended; + pSessionDesc->digestVerify = pSessionSetupData->verifyDigest; + + /* Reset the pending callback counter */ + qatUtilsAtomicSet(0, &pSessionDesc->u.pendingCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->u.pendingDpCbCount); + + /* Partial state must be set to full, to indicate that next packet + * expected on the session is a full packet or the start of a + * partial packet. */ + pSessionDesc->partialState = CPA_CY_SYM_PACKET_TYPE_FULL; + + pSessionDesc->symOperation = pSessionSetupData->symOperation; + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + pSessionDesc->isCipher = TRUE; + pSessionDesc->isAuth = FALSE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + + if (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == + pSessionSetupData->cipherSetupData.cipherAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pSessionSetupData->cipherSetupData.cipherAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + break; + case CPA_CY_SYM_OP_HASH: + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_AUTH; + pSessionDesc->isCipher = FALSE; + pSessionDesc->isAuth = TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionSetupData->hashSetupData.hashAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionSetupData->hashSetupData.hashAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + pSessionDesc->isCipher = TRUE; + pSessionDesc->isAuth = TRUE; + + { + /* set up some useful shortcuts */ + CpaCySymCipherAlgorithm cipherAlgorithm = + pSessionSetupData->cipherSetupData.cipherAlgorithm; + CpaCySymCipherDirection cipherDir = + pSessionSetupData->cipherSetupData.cipherDirection; + + if (LAC_CIPHER_IS_CCM(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + pSessionDesc->digestIsAppended = CPA_TRUE; + proto = ICP_QAT_FW_LA_CCM_PROTO; + + /* Derive chainOrder from direction for + * isAuthEncryptOp + * cases */ + /* For CCM & GCM modes: force digest verify flag + _TRUE + for decrypt and _FALSE for encrypt. For all + other cases + use user defined value */ + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + pSessionDesc->digestVerify = CPA_FALSE; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + pSessionDesc->digestVerify = CPA_TRUE; + } + } else if (LAC_CIPHER_IS_GCM(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + proto = ICP_QAT_FW_LA_GCM_PROTO; + + /* Derive chainOrder from direction for + * isAuthEncryptOp + * cases */ + /* For CCM & GCM modes: force digest verify flag + _TRUE + for decrypt and _FALSE for encrypt. For all + other cases + use user defined value */ + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + pSessionDesc->digestVerify = CPA_FALSE; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + pSessionDesc->digestVerify = CPA_TRUE; + } + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + proto = ICP_QAT_FW_LA_SINGLE_PASS_PROTO; + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + } + } else { + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + /* Use the chainOrder passed in */ + chainOrder = pSessionSetupData->algChainOrder; + if ((chainOrder != + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER) && + (chainOrder != + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH)) { + LAC_INVALID_PARAM_LOG("algChainOrder"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionSetupData->hashSetupData + .hashAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionSetupData->hashSetupData + .hashAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + } + + if (CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH == + chainOrder) { + pSessionDesc->laCmdId = + ICP_QAT_FW_LA_CMD_CIPHER_HASH; + } else if ( + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == + chainOrder) { + pSessionDesc->laCmdId = + ICP_QAT_FW_LA_CMD_HASH_CIPHER; + } + } + break; + default: + break; + } + + if (pSessionDesc->isCipher) { +/* Populate cipher specific session data */ + + status = LacCipher_SessionSetupDataCheck(pCipherData); + + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc->cipherAlgorithm = + pCipherData->cipherAlgorithm; + pSessionDesc->cipherKeyLenInBytes = + pCipherData->cipherKeyLenInBytes; + pSessionDesc->cipherDirection = + pCipherData->cipherDirection; + + /* ARC4 base key isn't added to the content descriptor, + * because + * we don't need to pass it directly to the QAT engine. + * Instead + * an initial cipher state & key matrix is derived from + * the + * base key and provided to the QAT through the state + * pointer + * in the request params. We'll store this initial state + * in + * the session descriptor. */ + + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherArc4StateInit( + pCipherData->pCipherKey, + pSessionDesc->cipherKeyLenInBytes, + pSessionDesc->cipherARC4InitialState); + + pSessionDesc->cipherARC4InitialStatePhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pSessionDesc->cipherARC4InitialState); + + if (0 == + pSessionDesc + ->cipherARC4InitialStatePhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address of " + "the initial state for ARC4\n"); + status = CPA_STATUS_FAIL; + } + } + } + } + + if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { + /* Populate auth-specific session data */ + const CpaCySymHashSetupData *pHashData = + &pSessionSetupData->hashSetupData; + + status = LacHash_HashContextCheck(instanceHandle, pHashData); + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc->hashResultSize = + pHashData->digestResultLenInBytes; + pSessionDesc->hashMode = pHashData->hashMode; + pSessionDesc->hashAlgorithm = pHashData->hashAlgorithm; + + /* Save the authentication key length for further update + */ + if (CPA_CY_SYM_HASH_MODE_AUTH == pHashData->hashMode) { + pSessionDesc->authKeyLenInBytes = + pHashData->authModeSetupData + .authKeyLenInBytes; + } + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp || + (pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_SNOW3G_UIA2 || + pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_ZUC_EIA3)) { + pSessionDesc->aadLenInBytes = + pHashData->authModeSetupData.aadLenInBytes; + } + + /* Set the QAT hash mode */ + if ((pHashData->hashMode == + CPA_CY_SYM_HASH_MODE_NESTED) || + (pHashData->hashMode == + CPA_CY_SYM_HASH_MODE_PLAIN) || + (pHashData->hashMode == CPA_CY_SYM_HASH_MODE_AUTH && + pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_AES_CBC_MAC)) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE0; + } else /* CPA_CY_SYM_HASH_MODE_AUTH + && anything except CPA_CY_SYM_HASH_AES_CBC_MAC + */ + { + if (IS_HMAC_ALG(pHashData->hashAlgorithm)) { + /* SHA3 and SM3 HMAC do not support + * precompute, force MODE2 + * for AUTH */ + if ((CPA_CY_SYM_HASH_SHA3_224 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_256 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_384 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_512 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SM3 == + pHashData->hashAlgorithm)) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE2; + } else { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE1; + } + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashData->hashAlgorithm) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE0; + } else { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE1; + } + } + } + } + + /*------------------------------------------------------------------------- + * build the message templates + * create two content descriptors in the case we can support using SHRAM + * constants and an optimised content descriptor. we have to do this in + *case + * of partials. + * 64 byte content desciptor is used in the SHRAM case for + *AES-128-HMAC-SHA1 + *-----------------------------------------------------------------------*/ + if (CPA_STATUS_SUCCESS == status) { + + LacSymCheck_IsPartialSupported(capabilitiesMask, pSessionDesc); + + /* setup some convenience pointers */ + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + hwBlockOffsetInDRAM = 0; + + /* + * Build the header flags with the default settings for this + * session. + */ + if (pSessionDesc->isDPSession == CPA_TRUE) { + pSessionDesc->cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD( + QAT_COMN_CD_FLD_TYPE_64BIT_ADR, + LAC_SYM_DP_QAT_PTR_TYPE); + } else { + pSessionDesc->cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD( + QAT_COMN_CD_FLD_TYPE_64BIT_ADR, + LAC_SYM_DEFAULT_QAT_PTR_TYPE); + } + + LacSymQat_LaSetDefaultFlags(&pSessionDesc->laCmdFlags, + pSessionDesc->symOperation); + + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: { + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + } break; + case CPA_CY_SYM_OP_HASH: + LacAlgChain_HashCDBuild(pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + NULL, + NULL); + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + /* For CCM/GCM, CPM firmware currently expects the + * cipher and + * hash h/w setup blocks to be arranged according to the + * chain + * order (Except for GCM/CCM, order doesn't actually + * matter as + * long as the config offsets are set correctly in CD + * control + * blocks + */ + if (CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == + chainOrder) { + LacAlgChain_HashCDBuild( + pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_CIPHER, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + pOptimisedHwBlockBaseInDRAM, + &optimisedHwBlockOffsetInDRAM); + + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + if (LAC_CIPHER_IS_SPC( + pCipherData->cipherAlgorithm, + pHashData->hashAlgorithm, + capabilitiesMask)) { + pCdInfo->hwBlkSzQuadWords = + (LAC_BYTES_TO_QUADWORDS( + hwBlockOffsetInDRAM)); + pMsg = (icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr); + SalQatMsg_ContentDescHdrWrite( + (icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + } + } else { + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_AUTH, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + + if (LAC_CIPHER_IS_SPC( + pCipherData->cipherAlgorithm, + pHashData->hashAlgorithm, + capabilitiesMask)) { + pCdInfo->hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + hwBlockOffsetInDRAM); + pMsg = (icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr); + SalQatMsg_ContentDescHdrWrite( + (icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + } + LacAlgChain_HashCDBuild( + pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + pOptimisedHwBlockBaseInDRAM, + &optimisedHwBlockOffsetInDRAM); + } + break; + default: + LAC_LOG_ERROR("Invalid sym operation\n"); + status = CPA_STATUS_INVALID_PARAM; + } + } + + if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + CpaBoolean hashStateBuffer = CPA_TRUE; + + /* set up fields in both the cd_ctrl and reqParams which + * describe + * the ReqParams block */ + LacSymQat_HashSetupReqParamsMetaData( + &(pSessionDesc->reqCacheFtr), + instanceHandle, + pHashData, + hashStateBuffer, + pSessionDesc->qatHashMode, + pSessionDesc->digestVerify); + + /* populate the hash state prefix buffer info structure + * (part of user allocated session memory & the + * buffer itself. For CCM/GCM the buffer is stored in the + * cookie and is not initialised here) */ + if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { + LAC_CHECK_64_BYTE_ALIGNMENT( + &(pSessionDesc->hashStatePrefixBuffer[0])); + status = LacHash_StatePrefixAadBufferInit( + &(pService->generic_service_info), + pHashData, + &(pSessionDesc->reqCacheFtr), + pSessionDesc->qatHashMode, + pSessionDesc->hashStatePrefixBuffer, + pHashStateBufferInfo); + /* SHRAM Constants Table not used for Auth-Enc */ + } + + if (CPA_STATUS_SUCCESS == status) { + if (IS_HASH_MODE_1(pSessionDesc->qatHashMode) || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashData->hashAlgorithm) { + LAC_CHECK_64_BYTE_ALIGNMENT( + &(pSessionDesc->hashStatePrefixBuffer[0])); + + /* Block messages until precompute is completed + */ + pSessionDesc->nonBlockingOpsInProgress = + CPA_FALSE; + status = LacHash_PrecomputeDataCreate( + instanceHandle, + (CpaCySymSessionSetupData *) + pSessionSetupData, + LacSymAlgChain_HashPrecomputeDoneCb, + pSessionDesc, + pSessionDesc->hashStatePrefixBuffer, + precomputeData.pState1, + precomputeData.pState2); + } else if (pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_AES_CBC_MAC) { + LAC_OS_BZERO(precomputeData.pState2, + precomputeData.state2Size); + memcpy(precomputeData.pState2, + pHashData->authModeSetupData.authKey, + pHashData->authModeSetupData + .authKeyLenInBytes); + } + } + if (CPA_STATUS_SUCCESS == status) { + + if (pSessionDesc->digestVerify) { + + ICP_QAT_FW_LA_CMP_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_CMP_AUTH_RES); + ICP_QAT_FW_LA_RET_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + } else { + + ICP_QAT_FW_LA_RET_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_RET_AUTH_RES); + ICP_QAT_FW_LA_CMP_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + } + + if (CPA_STATUS_SUCCESS == status) { + + pCdInfo->hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hwBlockOffsetInDRAM); + pMsg = (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr); + + /* Configure the ContentDescriptor field + * in the request if not done already */ + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + + if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pSessionSetupData->cipherSetupData.cipherAlgorithm || + pHashData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { + /* New bit position (12) for ZUC. The FW provides a + * specific macro + * to use to set the ZUC proto flag. With the new FW I/F + * this needs + * to be set for both Cipher and Auth */ + ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, proto); + } else { + /* Configure the common header */ + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, + proto); + } + + /* set Append flag, if digest is appended */ + if (pSessionDesc->digestIsAppended) { + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_DIGEST_IN_BUFFER); + } else { + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER); + } + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsg, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } + + return status; +} + +/** @ingroup LacAlgChain */ +CpaStatus +LacAlgChain_Perform(const CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + void *pCallbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + Cpa32U capabilitiesMask = + pService->generic_service_info.capabilitiesMask; + lac_sym_bulk_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + icp_qat_fw_la_bulk_req_t *pMsg = NULL; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + Cpa32U qatPacketType = 0; + CpaBufferList *pBufferList = NULL; + Cpa8U *pDigestResult = NULL; + Cpa64U srcAddrPhys = 0; + Cpa64U dstAddrPhys = 0; + icp_qat_fw_la_cmd_id_t laCmdId; + sal_qat_content_desc_info_t *pCdInfo = NULL; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U sizeInBytes = 0; + icp_qat_fw_cipher_cd_ctrl_hdr_t *pSpcCdCtrlHdr = NULL; + CpaCySymCipherAlgorithm cipher; + CpaCySymHashAlgorithm hash; + Cpa8U paddingLen = 0; + Cpa8U blockLen = 0; + Cpa64U srcPktSize = 0; + + /* Set the command id */ + laCmdId = pSessionDesc->laCmdId; + + cipher = pSessionDesc->cipherAlgorithm; + hash = pSessionDesc->hashAlgorithm; + + /* Convert Alg Chain Request to Cipher Request for CCP and + * AES_GCM single pass */ + if (!pSessionDesc->isSinglePass && + LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pOpData->ivLenInBytes)) { + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + laCmdId = pSessionDesc->laCmdId; + pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; + pSessionDesc->isSinglePass = CPA_TRUE; + pSessionDesc->isCipher = CPA_TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + pSessionDesc->isAuth = CPA_FALSE; + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = + pOpData->messageLenToHashInBytes; + if (ICP_QAT_FW_SPC_AAD_SZ_MAX < + pSessionDesc->aadLenInBytes) { + LAC_INVALID_PARAM_LOG( + "aadLenInBytes for AES_GMAC"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* New bit position (13) for SINGLE PASS. + * The FW provides a specific macro to use to set the proto flag + */ + ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, 0); + + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &sizeInBytes); + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr), + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = pOpData->messageLenToHashInBytes; + } + + if (LAC_CIPHER_IS_CHACHA(cipher) && + (LAC_CIPHER_SPC_IV_SIZE != pOpData->ivLenInBytes)) { + LAC_INVALID_PARAM_LOG("IV for CHACHA"); + return CPA_STATUS_INVALID_PARAM; + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + if (pOpData->messageLenToHashInBytes == 0 || + pOpData->pAdditionalAuthData != NULL) { + LAC_INVALID_PARAM_LOG( + "For AES_GMAC, AAD Length " + "(messageLenToHashInBytes) must " + "be non zero and pAdditionalAuthData " + "must be NULL"); + status = CPA_STATUS_INVALID_PARAM; + } + } + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) { + status = LacSymAlgChain_CheckCCMData( + pOpData->pAdditionalAuthData, + pOpData->pIv, + pOpData->messageLenToCipherInBytes, + pOpData->ivLenInBytes); + if (CPA_STATUS_SUCCESS == status) { + LacSymAlgChain_PrepareCCMData( + pSessionDesc, + pOpData->pAdditionalAuthData, + pOpData->pIv, + pOpData->messageLenToCipherInBytes, + pOpData->ivLenInBytes); + } + } else if (CPA_CY_SYM_HASH_AES_GCM == + pSessionDesc->hashAlgorithm) { + if (pSessionDesc->aadLenInBytes != 0 && + pOpData->pAdditionalAuthData == NULL) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData"); + status = CPA_STATUS_INVALID_PARAM; + } + if (CPA_STATUS_SUCCESS == status) { + LacSymAlgChain_PrepareGCMData( + pSessionDesc, pOpData->pAdditionalAuthData); + } + } + } + + /* allocate cookie (used by callback function) */ + if (CPA_STATUS_SUCCESS == status) { + pSymCookie = (lac_sym_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (pSymCookie == NULL) { + LAC_LOG_ERROR("Cannot allocate cookie - NULL"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pSymCookie) { + pSymCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pCookie = &(pSymCookie->u.bulkCookie); + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* write the buffer descriptors */ + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipher, hash)) { + status = + LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + (CpaBufferList *)pSrcBuffer, + &srcAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } else { + status = LacBuffDesc_BufferListDescWrite( + (CpaBufferList *)pSrcBuffer, + &srcAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Unable to write src buffer descriptors"); + } + + /* For out of place operations */ + if ((pSrcBuffer != pDstBuffer) && + (CPA_STATUS_SUCCESS == status)) { + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipher, hash)) { + status = + LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + pDstBuffer, + &dstAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } else { + status = LacBuffDesc_BufferListDescWrite( + pDstBuffer, + &dstAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR( + "Unable to write dest buffer descriptors"); + } + } + } + if (CPA_STATUS_SUCCESS == status) { + /* populate the cookie */ + pCookie->pCallbackTag = pCallbackTag; + pCookie->sessionCtx = pOpData->sessionCtx; + pCookie->pOpData = (const CpaCySymOpData *)pOpData; + pCookie->pDstBuffer = pDstBuffer; + pCookie->updateSessionIvOnSend = CPA_FALSE; + pCookie->updateUserIvOnRecieve = CPA_FALSE; + pCookie->updateKeySizeOnRecieve = CPA_FALSE; + pCookie->pNext = NULL; + pCookie->instanceHandle = pService; + + /* get the qat packet type for LAC packet type */ + LacSymQat_packetTypeGet(pOpData->packetType, + pSessionDesc->partialState, + &qatPacketType); + /* + * For XTS mode, the key size must be updated after + * the first partial has been sent. Set a flag here so the + * response knows to do this. + */ + if ((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && + (LAC_CIPHER_IS_XTS_MODE(pSessionDesc->cipherAlgorithm)) && + (qatPacketType == ICP_QAT_FW_LA_PARTIAL_START)) { + pCookie->updateKeySizeOnRecieve = CPA_TRUE; + } + + /* + * Now create the Request. + * Start by populating it from the cache in the session + * descriptor. + */ + pMsg = &(pCookie->qatMsg); + pMsgDummy = (Cpa8U *)pMsg; + + if (pSessionDesc->isSinglePass) { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); + } else { + /* Normally, we want to use the SHRAM Constants Table if + * possible + * for best performance (less DRAM accesses incurred by + * CPM). But + * we can't use it for partial-packet hash operations. + * This is why + * we build 2 versions of the message template at + * sessionInit, + * one for SHRAM Constants Table usage and the other + * (default) for + * Content Descriptor h/w setup data in DRAM. And we + * chose between + * them here on a per-request basis, when we know the + * packetType + */ + if ((!pSessionDesc->useSymConstantsTable) || + (pSessionDesc->isAuth && + (CPA_CY_SYM_PACKET_TYPE_FULL != + pOpData->packetType))) { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->reqCacheFtr); + } else { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); + } + } + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + /* + * Populate the comn_mid section + */ + SalQatMsg_CmnMidWrite(pMsg, + pCookie, + LAC_SYM_DEFAULT_QAT_PTR_TYPE, + srcAddrPhys, + dstAddrPhys, + 0, + 0); + + /* + * Populate the serv_specif_flags field of the Request header + * Some of the flags are set up here. + * Others are set up later when the RequestParams are set up. + */ + + LacSymQat_LaPacketCommandFlagSet( + qatPacketType, + laCmdId, + pSessionDesc->cipherAlgorithm, + &pMsg->comn_hdr.serv_specif_flags, + pOpData->ivLenInBytes); + + if (pSessionDesc->isSinglePass) { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); + + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == + pOpData->packetType) { + ICP_QAT_FW_LA_RET_AUTH_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + + ICP_QAT_FW_LA_CMP_AUTH_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + + LacBuffDesc_BufferListTotalSizeGet(pSrcBuffer, &srcPktSize); + + /* + * Populate the CipherRequestParams section of the Request + */ + if (laCmdId != ICP_QAT_FW_LA_CMD_AUTH) { + + Cpa8U *pIvBuffer = NULL; + + status = LacCipher_PerformParamCheck( + pSessionDesc->cipherAlgorithm, pOpData, srcPktSize); + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + Lac_MemPoolEntryFree(pCookie); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + /* align cipher IV */ + status = LacCipher_PerformIvCheck( + &(pService->generic_service_info), + pCookie, + qatPacketType, + &pIvBuffer); + } + if (pSessionDesc->isSinglePass && + ((ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType) || + (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType))) { + /* For SPC stateful cipher state size for mid + * and + * end partial packet is 48 bytes + */ + pSpcCdCtrlHdr = + (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&( + pMsg->cd_ctrl); + pSpcCdCtrlHdr->cipher_state_sz = + LAC_BYTES_TO_QUADWORDS( + LAC_SYM_QAT_CIPHER_STATE_SIZE_SPC); + } + /*populate the cipher request parameters */ + if (CPA_STATUS_SUCCESS == status) { + Cpa64U ivBufferPhysAddr = 0; + + if (pIvBuffer != NULL) { + /* User OpData memory being used for IV + * buffer */ + /* get the physical address */ + ivBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pIvBuffer); + if (0 == ivBufferPhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the IV\n"); + status = CPA_STATUS_FAIL; + } + } + + if (status == CPA_STATUS_SUCCESS) { + status = + LacSymQat_CipherRequestParamsPopulate( + pMsg, + pOpData + ->cryptoStartSrcOffsetInBytes, + pOpData + ->messageLenToCipherInBytes, + ivBufferPhysAddr, + pIvBuffer); + } + } + + if (CPA_STATUS_SUCCESS == status && + pSessionDesc->isSinglePass) { + Cpa64U aadBufferPhysAddr = 0; + + /* For CHACHA and AES-GCM there is an AAD buffer + * if + * aadLenInBytes is nonzero In case of AES-GMAC, + * AAD buffer + * passed in the src buffer. + */ + if (0 != pSessionDesc->aadLenInBytes && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + LAC_CHECK_NULL_PARAM( + pOpData->pAdditionalAuthData); + blockLen = + LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if ((pSessionDesc->aadLenInBytes % + blockLen) != 0) { + paddingLen = blockLen - + (pSessionDesc + ->aadLenInBytes % + blockLen); + memset( + &pOpData->pAdditionalAuthData + [pSessionDesc + ->aadLenInBytes], + 0, + paddingLen); + } + + /* User OpData memory being used for aad + * buffer */ + /* get the physical address */ + aadBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pOpData->pAdditionalAuthData); + if (0 == aadBufferPhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the aad\n"); + status = CPA_STATUS_FAIL; + } + } + + if (CPA_STATUS_SUCCESS == status) { + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams = + (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&( + pMsg->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + pCipherReqParams->spc_aad_addr = + aadBufferPhysAddr; + pCipherReqParams->spc_aad_sz = + pSessionDesc->aadLenInBytes; + + if (CPA_TRUE != + pSessionDesc->digestIsAppended) { + Cpa64U digestBufferPhysAddr = 0; + /* User OpData memory being used + * for digest buffer */ + /* get the physical address */ + digestBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService + ->generic_service_info, + pOpData->pDigestResult); + if (0 != digestBufferPhysAddr) { + pCipherReqParams + ->spc_auth_res_addr = + digestBufferPhysAddr; + pCipherReqParams + ->spc_auth_res_sz = + pSessionDesc + ->hashResultSize; + } else { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the digest\n"); + status = + CPA_STATUS_FAIL; + } + } + } + } + } + + /* + * Set up HashRequestParams part of Request + */ + if ((status == CPA_STATUS_SUCCESS) && + (laCmdId != ICP_QAT_FW_LA_CMD_CIPHER)) { + Cpa32U authOffsetInBytes = + pOpData->hashStartSrcOffsetInBytes; + Cpa32U authLenInBytes = + pOpData->messageLenToHashInBytes; + + status = LacHash_PerformParamCheck(instanceHandle, + pSessionDesc, + pOpData, + srcPktSize, + pVerifyResult); + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + Lac_MemPoolEntryFree(pCookie); + return status; + } + if (CPA_STATUS_SUCCESS == status) { + /* Info structure for CCM/GCM */ + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + lac_sym_qat_hash_state_buffer_info_t + *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + icp_qat_fw_la_auth_req_params_t *pHashReqParams = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&( + pMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + hashStateBufferInfo.pData = + pOpData->pAdditionalAuthData; + if (pOpData->pAdditionalAuthData == + NULL) { + hashStateBufferInfo.pDataPhys = + 0; + } else { + hashStateBufferInfo + .pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService + ->generic_service_info, + pOpData + ->pAdditionalAuthData)); + } + + hashStateBufferInfo + .stateStorageSzQuadWords = 0; + hashStateBufferInfo + .prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.aad_sz); + + /* Overwrite hash state buffer info + * structure pointer + * with the one created for CCM/GCM */ + pHashStateBufferInfo = + &hashStateBufferInfo; + + /* Aad buffer could be null in the GCM + * case */ + if (0 == + hashStateBufferInfo.pDataPhys && + CPA_CY_SYM_HASH_AES_GCM != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + LAC_LOG_ERROR( + "Unable to get the physical address" + "of the AAD\n"); + status = CPA_STATUS_FAIL; + } + + /* for CCM/GCM the hash and cipher data + * regions + * are equal */ + authOffsetInBytes = + pOpData + ->cryptoStartSrcOffsetInBytes; + + /* For authenticated encryption, + * authentication length is + * determined by + * messageLenToCipherInBytes for AES-GCM + * and + * AES-CCM, and by + * messageLenToHashInBytes for AES-GMAC. + * You don't see the latter here, as + * that is the initial + * value of authLenInBytes. */ + if (pSessionDesc->hashAlgorithm != + CPA_CY_SYM_HASH_AES_GMAC) + authLenInBytes = + pOpData + ->messageLenToCipherInBytes; + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + hashStateBufferInfo.pData = + pOpData->pAdditionalAuthData; + hashStateBufferInfo.pDataPhys = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + hashStateBufferInfo.pData); + hashStateBufferInfo + .stateStorageSzQuadWords = 0; + hashStateBufferInfo + .prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pSessionDesc->aadLenInBytes); + + pHashStateBufferInfo = + &hashStateBufferInfo; + + if (0 == + hashStateBufferInfo.pDataPhys) { + LAC_LOG_ERROR( + "Unable to get the physical address" + "of the AAD\n"); + status = CPA_STATUS_FAIL; + } + } + if (CPA_CY_SYM_HASH_AES_CCM == + pSessionDesc->hashAlgorithm) { + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + /* On a decrypt path pSrcBuffer + * is used as this is + * where encrypted digest is + * located. Firmware + * uses encrypted digest for + * compare/verification*/ + pBufferList = + (CpaBufferList *)pSrcBuffer; + } else { + /* On an encrypt path pDstBuffer + * is used as this is + * where encrypted digest will + * be written */ + pBufferList = + (CpaBufferList *)pDstBuffer; + } + status = LacSymAlgChain_PtrFromOffsetGet( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes + + pOpData + ->messageLenToCipherInBytes, + &pDigestResult); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR( + "Cannot set digest pointer within the" + " buffer list - offset out of bounds"); + } + } else { + pDigestResult = pOpData->pDigestResult; + } + + if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionDesc->symOperation) { + /* In alg chaining mode, packets are not + * seen as partials + * for hash operations. Override to + * NONE. + */ + qatPacketType = + ICP_QAT_FW_LA_PARTIAL_NONE; + } + if (CPA_TRUE == + pSessionDesc->digestIsAppended) { + /*Check if the destination buffer can + * handle the digest + * if digestIsAppend is true*/ + if (srcPktSize < + (authOffsetInBytes + + authLenInBytes + + pSessionDesc->hashResultSize)) { + status = + CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_STATUS_SUCCESS == status) { + /* populate the hash request parameters + */ + status = + LacSymQat_HashRequestParamsPopulate( + pMsg, + authOffsetInBytes, + authLenInBytes, + &(pService + ->generic_service_info), + pHashStateBufferInfo, + qatPacketType, + pSessionDesc->hashResultSize, + pSessionDesc->digestVerify, + pSessionDesc->digestIsAppended ? + NULL : + pDigestResult, + pSessionDesc->hashAlgorithm, + NULL); + } + } + } + } + + /* + * send the message to the QAT + */ + if (CPA_STATUS_SUCCESS == status) { + qatUtilsAtomicInc(&(pSessionDesc->u.pendingCbCount)); + + status = LacSymQueue_RequestSend(instanceHandle, + pCookie, + pSessionDesc); + + if (CPA_STATUS_SUCCESS != status) { + /* Decrease pending callback counter on send fail. */ + qatUtilsAtomicDec(&(pSessionDesc->u.pendingCbCount)); + } + } + /* Case that will catch all error status's for this function */ + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + if (NULL != pSymCookie) { + Lac_MemPoolEntryFree(pSymCookie); + } + } + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c new file mode 100644 index 00000000000..70446ef988b --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c @@ -0,0 +1,1130 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_api.c Implementation of the symmetric API + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_im.h" + +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_qat_fw_la.h" + +/* + ****************************************************************************** + * Include private header files + ****************************************************************************** + */ +#include "lac_common.h" +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_sym.h" +#include "lac_sym_qat.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_session.h" +#include "lac_sym_cipher.h" +#include "lac_sym_hash.h" +#include "lac_sym_alg_chain.h" +#include "lac_sym_stats.h" +#include "lac_sym_partial.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_cb.h" +#include "lac_buffer_desc.h" +#include "lac_sync.h" +#include "lac_hooks.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" + +#define IS_EXT_ALG_CHAIN_UNSUPPORTED( \ + cipherAlgorithm, hashAlgorithm, extAlgchainSupported) \ + ((((CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) || \ + ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) || \ + ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) && \ + !extAlgchainSupported) + +/*** Local functions definitions ***/ +static CpaStatus +LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, + const CpaBufferList *const pDstBuffer, + const lac_session_desc_t *const pSessionDesc, + const CpaCySymOpData *const pOpData); + +void getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup LacSym + * Generic bufferList callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] operationType Operation Type + * @param[in] pOpData Pointer to the Op Data + * @param[out] pDstBuffer Pointer to destination buffer list + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + * + *****************************************************************************/ +void +LacSync_GenBufListVerifyCb(void *pCallbackTag, + CpaStatus status, + CpaCySymOp operationType, + void *pOpData, + CpaBufferList *pDstBuffer, + CpaBoolean opResult) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/* +******************************************************************************* +* Define static function definitions +******************************************************************************* +*/ +/** + * @ingroup LacSym + * Function which perform parameter checks on session setup data + * + * @param[in] CpaInstanceHandle Instance Handle + * @param[in] pSessionSetupData Pointer to session setup data + * + * @retval CPA_STATUS_SUCCESS The operation succeeded + * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was found + */ +static CpaStatus +LacSymSession_ParamCheck(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData) +{ + /* initialize convenient pointers to cipher and hash contexts */ + const CpaCySymCipherSetupData *const pCipherSetupData = + (const CpaCySymCipherSetupData *)&pSessionSetupData + ->cipherSetupData; + const CpaCySymHashSetupData *const pHashSetupData = + &pSessionSetupData->hashSetupData; + + CpaCySymCapabilitiesInfo capInfo; + CpaCyCapabilitiesInfo cyCapInfo; + cpaCySymQueryCapabilities(instanceHandle, &capInfo); + SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo); + + /* Ensure cipher algorithm is correct and supported */ + if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) || + (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation)) { + /* Protect against value of cipher outside the bitmap + * and check if cipher algorithm is correct + */ + if ((pCipherSetupData->cipherAlgorithm >= + CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE) || + (!CPA_BITMAP_BIT_TEST(capInfo.ciphers, + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG("cipherAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Ensure hash algorithm is correct and supported */ + if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) || + (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation)) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + /* Protect against value of hash outside the bitmap + * and check if hash algorithm is correct + */ + if ((pHashSetupData->hashAlgorithm >= + CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) || + (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->hashAlgorithm))) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* ensure CCM, GCM, Kasumi, Snow3G and ZUC cipher and hash algorithms + * are + * selected together for Algorithm Chaining */ + if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) { + /* ensure both hash and cipher algorithms are POLY and CHACHA */ + if (((CPA_CY_SYM_CIPHER_CHACHA == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY != pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_CHACHA != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash " + "Algorithms for CHACHA/POLY"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are CCM */ + if (((CPA_CY_SYM_CIPHER_AES_CCM == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_AES_CCM != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_AES_CCM != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for CCM"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are GCM/GMAC */ + if ((CPA_CY_SYM_CIPHER_AES_GCM == + pCipherSetupData->cipherAlgorithm && + (CPA_CY_SYM_HASH_AES_GCM != + pHashSetupData->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) && + CPA_CY_SYM_CIPHER_AES_GCM != + pCipherSetupData->cipherAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for GCM"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are Kasumi */ + if (((CPA_CY_SYM_CIPHER_KASUMI_F8 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_KASUMI_F9 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_KASUMI_F8 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for Kasumi"); + return CPA_STATUS_INVALID_PARAM; + } + + if (IS_EXT_ALG_CHAIN_UNSUPPORTED( + pCipherSetupData->cipherAlgorithm, + pHashSetupData->hashAlgorithm, + cyCapInfo.extAlgchainSupported)) { + LAC_UNSUPPORTED_PARAM_LOG( + "ExtAlgChain feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + /* ensure both hash and cipher algorithms are Snow3G */ + if (((CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for Snow3G"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are ZUC */ + if (((CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_ZUC_EIA3 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_ZUC_EEA3 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for ZUC"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* not Algorithm Chaining so prevent CCM/GCM being selected */ + else if (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation) { + /* ensure cipher algorithm is not CCM or GCM */ + if ((CPA_CY_SYM_CIPHER_AES_CCM == + pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_AES_GCM == + pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_CHACHA == + pCipherSetupData->cipherAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid Cipher Algorithm for non-Algorithm " + "Chaining operation"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation) { + /* ensure hash algorithm is not CCM or GCM/GMAC */ + if ((CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid Hash Algorithm for non-Algorithm Chaining operation"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* Unsupported operation. Return error */ + else { + LAC_INVALID_PARAM_LOG("symOperation"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure that cipher direction param is + * valid for cipher and algchain ops */ + if (CPA_CY_SYM_OP_HASH != pSessionSetupData->symOperation) { + if ((pCipherSetupData->cipherDirection != + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) && + (pCipherSetupData->cipherDirection != + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT)) { + LAC_INVALID_PARAM_LOG("Invalid Cipher Direction"); + return CPA_STATUS_INVALID_PARAM; + } + } + + return CPA_STATUS_SUCCESS; +} + + +/** + * @ingroup LacSym + * Function which perform parameter checks on data buffers for symmetric + * crypto operations + * + * @param[in] pSrcBuffer Pointer to source buffer list + * @param[in] pDstBuffer Pointer to destination buffer list + * @param[in] pSessionDesc Pointer to session descriptor + * @param[in] pOpData Pointer to CryptoSymOpData. + * + * @retval CPA_STATUS_SUCCESS The operation succeeded + * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was found + */ + +static CpaStatus +LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, + const CpaBufferList *const pDstBuffer, + const lac_session_desc_t *const pSessionDesc, + const CpaCySymOpData *const pOpData) +{ + Cpa64U srcBufferLen = 0, dstBufferLen = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + /* verify packet type is in correct range */ + switch (pOpData->packetType) { + case CPA_CY_SYM_PACKET_TYPE_FULL: + case CPA_CY_SYM_PACKET_TYPE_PARTIAL: + case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL: + break; + default: { + LAC_INVALID_PARAM_LOG("packetType"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && + CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && + (0 == pOpData->messageLenToHashInBytes))) { + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED( + pSessionDesc->cipherAlgorithm, + pSessionDesc->hashAlgorithm)) { + status = LacBuffDesc_BufferListVerifyNull( + pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); + } else { + status = LacBuffDesc_BufferListVerify( + pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_INVALID_PARAM_LOG("Source buffer invalid"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* check MetaData !NULL */ + if (NULL == pSrcBuffer->pPrivateMetaData) { + LAC_INVALID_PARAM_LOG( + "Source buffer MetaData cannot be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* out of place checks */ + if (pSrcBuffer != pDstBuffer) { + /* exception for this check is zero length hash requests to + * allow */ + /* for srcBufflen=DstBufferLen=0 */ + if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && + CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && + (0 == pOpData->messageLenToHashInBytes))) { + /* Verify buffer(s) for dest packet & return packet + * length */ + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED( + pSessionDesc->cipherAlgorithm, + pSessionDesc->hashAlgorithm)) { + status = LacBuffDesc_BufferListVerifyNull( + pDstBuffer, + &dstBufferLen, + LAC_NO_ALIGNMENT_SHIFT); + } else { + status = LacBuffDesc_BufferListVerify( + pDstBuffer, + &dstBufferLen, + LAC_NO_ALIGNMENT_SHIFT); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_INVALID_PARAM_LOG( + "Destination buffer invalid"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* check MetaData !NULL */ + if (NULL == pDstBuffer->pPrivateMetaData) { + LAC_INVALID_PARAM_LOG( + "Dest buffer MetaData cannot be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* Check that src Buffer and dst Buffer Lengths are equal */ + if (srcBufferLen != dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Source and Dest buffer lengths need to be equal "); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* check for partial packet suport for the session operation */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { + if (CPA_FALSE == pSessionDesc->isPartialSupported) { + /* return out here to simplify cleanup */ + LAC_INVALID_PARAM_LOG( + "Partial packets not supported for operation"); + return CPA_STATUS_INVALID_PARAM; + } else { + /* This function checks to see if the partial packet + * sequence + * is correct */ + if (CPA_STATUS_SUCCESS != + LacSym_PartialPacketStateCheck( + pOpData->packetType, + pSessionDesc->partialState)) { + LAC_INVALID_PARAM_LOG("Partial packet Type"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymInitSession(const CpaInstanceHandle instanceHandle_in, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymSessionCtx pSessionCtx) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = NULL; + sal_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pService = (sal_service_t *)instanceHandle; + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + status = LacSym_InitSession(instanceHandle, + pSymCb, + pSessionSetupData, + CPA_FALSE, /* isDPSession */ + pSessionCtx); + + if (CPA_STATUS_SUCCESS == status) { + /* Increment the stats for a session registered successfully */ + LAC_SYM_STAT_INC(numSessionsInitialized, instanceHandle); + } else /* if there was an error */ + { + LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); + } + + return status; +} + +CpaStatus +cpaCySymSessionInUse(CpaCySymSessionCtx pSessionCtx, CpaBoolean *pSessionInUse) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionInUse); + LAC_CHECK_INSTANCE_HANDLE(pSessionCtx); + + *pSessionInUse = CPA_FALSE; + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); + + /* If there are pending requests */ + if (pSessionDesc->isDPSession) { + if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount))) + *pSessionInUse = CPA_TRUE; + } else { + if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount))) + *pSessionInUse = CPA_TRUE; + } + + return status; +} + +CpaStatus +LacSym_InitSession(const CpaInstanceHandle instanceHandle, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + const CpaBoolean isDPSession, + CpaCySymSessionCtx pSessionCtx) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_session_desc_t *pSessionDesc = NULL; + Cpa32U sessionCtxSizeInBytes = 0; + CpaPhysicalAddr physAddress = 0; + CpaPhysicalAddr physAddressAligned = 0; + sal_service_t *pService = NULL; + const CpaCySymCipherSetupData *pCipherSetupData = NULL; + const CpaCySymHashSetupData *pHashSetupData = NULL; + +/* Instance param checking done by calling function */ + + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtx); + status = LacSymSession_ParamCheck(instanceHandle, pSessionSetupData); + LAC_CHECK_STATUS(status); + + /* set the session priority for QAT AL*/ + if ((CPA_CY_PRIORITY_HIGH == pSessionSetupData->sessionPriority) || + (CPA_CY_PRIORITY_NORMAL == pSessionSetupData->sessionPriority)) { + // do nothing - clean up this code. use RANGE macro + } else { + LAC_INVALID_PARAM_LOG("sessionPriority"); + return CPA_STATUS_INVALID_PARAM; + } + + + pCipherSetupData = &pSessionSetupData->cipherSetupData; + pHashSetupData = &pSessionSetupData->hashSetupData; + + pService = (sal_service_t *)instanceHandle; + + /* Re-align the session structure to 64 byte alignment */ + physAddress = + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), + (Cpa8U *)pSessionCtx + sizeof(void *)); + + if (0 == physAddress) { + LAC_LOG_ERROR( + "Unable to get the physical address of the session"); + return CPA_STATUS_FAIL; + } + + physAddressAligned = + LAC_ALIGN_POW2_ROUNDUP(physAddress, LAC_64BYTE_ALIGNMENT); + + pSessionDesc = (lac_session_desc_t *) + /* Move the session pointer by the physical offset + between aligned and unaligned memory */ + ((Cpa8U *)pSessionCtx + sizeof(void *) + + (physAddressAligned - physAddress)); + + /* save the aligned pointer in the first bytes (size of unsigned long) + * of the session memory */ + *((LAC_ARCH_UINT *)pSessionCtx) = (LAC_ARCH_UINT)pSessionDesc; + + /* start off with a clean session */ + /* Choose Session Context size */ + getCtxSize(pSessionSetupData, &sessionCtxSizeInBytes); + switch (sessionCtxSizeInBytes) { + case LAC_SYM_SESSION_D1_SIZE: + memset(pSessionDesc, 0, sizeof(lac_session_desc_d1_t)); + break; + case LAC_SYM_SESSION_D2_SIZE: + memset(pSessionDesc, 0, sizeof(lac_session_desc_d2_t)); + break; + default: + memset(pSessionDesc, 0, sizeof(lac_session_desc_t)); + break; + } + + /* Setup content descriptor info structure + * assumption that content descriptor is the first field in + * in the session descriptor */ + pSessionDesc->contentDescInfo.pData = (Cpa8U *)pSessionDesc; + pSessionDesc->contentDescInfo.hardwareSetupBlockPhys = + physAddressAligned; + + pSessionDesc->contentDescOptimisedInfo.pData = + ((Cpa8U *)pSessionDesc + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); + pSessionDesc->contentDescOptimisedInfo.hardwareSetupBlockPhys = + (physAddressAligned + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); + + /* Set the Common Session Information */ + pSessionDesc->symOperation = pSessionSetupData->symOperation; + + if (CPA_FALSE == isDPSession) { + /* For asynchronous - use the user supplied callback + * for synchronous - use the internal synchronous callback */ + pSessionDesc->pSymCb = ((void *)NULL != (void *)pSymCb) ? + pSymCb : + LacSync_GenBufListVerifyCb; + } + + pSessionDesc->isDPSession = isDPSession; + if ((CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_ARC4 == pCipherSetupData->cipherAlgorithm)) { + pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgFull; + } else { + pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgOpt; + } + + if (CPA_STATUS_SUCCESS == status) { + /* Session set up via API call (not internal one) */ + /* Services such as DRBG call the crypto api as part of their + * service + * hence the need to for the flag, it is needed to distinguish + * between + * an internal and external session. + */ + pSessionDesc->internalSession = CPA_FALSE; + + status = LacAlgChain_SessionInit(instanceHandle, + pSessionSetupData, + pSessionDesc); + } + return status; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle_in, + CpaCySymSessionCtx pSessionCtx) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = NULL; + Cpa64U numPendingRequests = 0; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionCtx); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); + + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* + * Based on one instance, we can initialize multiple sessions. + * For example, we can initialize the session "X" and session + * "Y" with + * the same instance "A". If there is no operation pending for + * session + * "X", we can remove the session "X". + * + * Now we only check the @pSessionDesc->pendingDpCbCount, if it + * becomes + * zero, we can remove the session. + * + * Why? + * (1) We increase it in the cpaCySymDpEnqueueOp/ + * cpaCySymDpEnqueueOpBatch. + * (2) We decrease it in the LacSymCb_ProcessCallback. + * + * If the @pSessionDesc->pendingDpCbCount becomes zero, it means + * there is no operation pending for the session "X" anymore, so + * we can + * remove this session. Maybe there is still some requests left + * in the + * instance's ring (icp_adf_queueDataToSend() returns true), but + * the + * request does not belong to "X", it belongs to session "Y". + */ + numPendingRequests = + qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount)); + } else { + numPendingRequests = + qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount)); + } + + /* If there are pending requests */ + if (0 != numPendingRequests) { + QAT_UTILS_LOG("There are %llu requests pending\n", + (unsigned long long)numPendingRequests); + status = CPA_STATUS_RETRY; + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* Need to update tail if messages queue on tx hi ring + for + data plane api */ + icp_comms_trans_handle trans_handle = + ((sal_crypto_service_t *)instanceHandle) + ->trans_handle_sym_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* process the remaining messages in the ring */ + QAT_UTILS_LOG("Submitting enqueued requests\n"); + /* + * SalQatMsg_updateQueueTail + */ + SalQatMsg_updateQueueTail(trans_handle); + return status; + } + } + } + if (CPA_STATUS_SUCCESS == status) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK_DESTROY(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to destroy request queue lock"); + } + if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_SYM_STAT_INC(numSessionsRemoved, instanceHandle); + } + } else if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); + } + return status; +} + +/** @ingroup LacSym */ +static CpaStatus +LacSym_Perform(const CpaInstanceHandle instanceHandle, + void *callbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult, + CpaBoolean isAsyncMode) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData->sessionCtx); + LAC_CHECK_NULL_PARAM(pSrcBuffer); + LAC_CHECK_NULL_PARAM(pDstBuffer); + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + /*check whether Payload size is zero for CHACHA-POLY*/ + if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + if (!pOpData->messageLenToCipherInBytes) { + LAC_INVALID_PARAM_LOG( + "Invalid messageLenToCipherInBytes for CHACHA-POLY"); + return CPA_STATUS_INVALID_PARAM; + } + } + + + /* If synchronous Operation - Callback function stored in the session + * descriptor so a flag is set in the perform to indicate that + * the perform is being re-called for the synchronous operation */ + if ((LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb) && + isAsyncMode == CPA_TRUE) { + CpaBoolean opResult = CPA_FALSE; + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = LacSym_Perform(instanceHandle, + pSyncCallbackData, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult, + CPA_FALSE); + } else { + /* Failure allocating sync cookie */ + LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + syncStatus = LacSync_WaitForCallback( + pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + &opResult); + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + if (CPA_STATUS_SUCCESS == status) { + if (NULL != pVerifyResult) { + *pVerifyResult = opResult; + } + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + return status; + } + + status = + LacSymPerform_BufferParamCheck((const CpaBufferList *)pSrcBuffer, + pDstBuffer, + pSessionDesc, + pOpData); + LAC_CHECK_STATUS(status); + + if ((!pSessionDesc->digestIsAppended) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + /* Check that pDigestResult is not NULL */ + LAC_CHECK_NULL_PARAM(pOpData->pDigestResult); + } + + status = LacAlgChain_Perform(instanceHandle, + pSessionDesc, + callbackTag, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult); + + if (CPA_STATUS_SUCCESS == status) { + /* check for partial packet suport for the session operation */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { + LacSym_PartialPacketStateUpdate( + pOpData->packetType, &pSessionDesc->partialState); + } + /* increment #requests stat */ + LAC_SYM_STAT_INC(numSymOpRequests, instanceHandle); + } + /* Retry also results in the errors stat been incremented */ + else { + /* increment #errors stat */ + LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); + } + return status; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymPerformOp(const CpaInstanceHandle instanceHandle_in, + void *callbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSym_Perform(instanceHandle, + callbackTag, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult, + CPA_TRUE); +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymQueryStats(const CpaInstanceHandle instanceHandle_in, + struct _CpaCySymStats *pSymStats) +{ + + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymStats); + + /* check if crypto service is running + * otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + /* copy the fields from the internal structure into the api defined + * structure */ + LacSym_Stats32CopyGet(instanceHandle, pSymStats); + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle_in, + CpaCySymStats64 *pSymStats) +{ + + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymStats); + + /* check if crypto service is running + * otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + /* copy the fields from the internal structure into the api defined + * structure */ + LacSym_Stats64CopyGet(instanceHandle, pSymStats); + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymSessionCtxGetSize(const CpaInstanceHandle instanceHandle_in, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymSessionCtxGetDynamicSize( + const CpaInstanceHandle instanceHandle_in, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + /* Choose Session Context size */ + getCtxSize(pSessionSetupData, pSessionCtxSizeInBytes); + + + return CPA_STATUS_SUCCESS; +} + +void +getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + /* using lac_session_desc_d1_t */ + if ((pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_ARC4) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_SNOW3G_UEA2) && + (pSessionSetupData->hashSetupData.hashAlgorithm != + CPA_CY_SYM_HASH_SNOW3G_UIA2) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_AES_CCM) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_AES_GCM) && + (pSessionSetupData->hashSetupData.hashMode != + CPA_CY_SYM_HASH_MODE_AUTH) && + (pSessionSetupData->hashSetupData.hashMode != + CPA_CY_SYM_HASH_MODE_NESTED) && + (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D1_SIZE; + } + /* using lac_session_desc_d2_t */ + else if (((pSessionSetupData->cipherSetupData.cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_CCM) || + (pSessionSetupData->cipherSetupData.cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_GCM)) && + (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D2_SIZE; + } + /* using lac_session_desc_t */ + else { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; + } +} + +/** + ****************************************************************************** + * @ingroup LacSym + *****************************************************************************/ +CpaStatus +cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle_in, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes) +{ + + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSizeInBytes); + + /* In the case of zero buffers we still need to allocate one + * descriptor to pass to the firmware */ + if (0 == numBuffers) { + numBuffers = 1; + } + + /* Note: icp_buffer_list_desc_t is 8 bytes in size and + * icp_flat_buffer_desc_t is 16 bytes in size. Therefore if + * icp_buffer_list_desc_t is aligned + * so will each icp_flat_buffer_desc_t structure */ + + *pSizeInBytes = sizeof(icp_buffer_list_desc_t) + + (sizeof(icp_flat_buffer_desc_t) * numBuffers) + + ICP_DESCRIPTOR_ALIGNMENT_BYTES; + + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c new file mode 100644 index 00000000000..fe46b7eee3d --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_auth_enc.c + * + * @ingroup LacAuthEnc + * + * @description + * Authenticated encryption specific functionality. + * For CCM related code NIST SP 800-38C is followed. + * For GCM related code NIST SP 800-38D is followed. + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_log.h" +#include "lac_common.h" +#include "lac_session.h" +#include "lac_sym_auth_enc.h" + +/* These defines describe position of the flag fields + * in B0 block for CCM algorithm*/ +#define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6 +#define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3 + +/* This macro builds flags field to be put in B0 block for CCM algorithm */ +#define LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(Adata, t, q) \ + ((((Adata) > 0 ? 1 : 0) << LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT) | \ + ((((t)-2) >> 1) << LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT) | ((q)-1)) + +/** + * @ingroup LacAuthEnc + */ +CpaStatus +LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes) +{ + Cpa8U q = 0; + + LAC_CHECK_NULL_PARAM(pIv); + LAC_CHECK_NULL_PARAM(pAdditionalAuthData); + + /* check if n is within permitted range */ + if (ivLenInBytes < LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN || + ivLenInBytes > LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX) { + LAC_INVALID_PARAM_LOG2("ivLenInBytes for CCM algorithm " + "must be between %d and %d inclusive", + LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN, + LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX); + return CPA_STATUS_INVALID_PARAM; + } + + q = LAC_ALG_CHAIN_CCM_NQ_CONST - ivLenInBytes; + + /* Check if q is big enough to hold actual length of message to cipher + * if q = 8 -> maxlen = 2^64 always good as + * messageLenToCipherInBytes is 32 bits + * if q = 7 -> maxlen = 2^56 always good + * if q = 6 -> maxlen = 2^48 always good + * if q = 5 -> maxlen = 2^40 always good + * if q = 4 -> maxlen = 2^32 always good. + */ + if ((messageLenToCipherInBytes >= (1 << (q * LAC_NUM_BITS_IN_BYTE))) && + (q < sizeof(Cpa32U))) { + LAC_INVALID_PARAM_LOG( + "messageLenToCipherInBytes too long for the given" + " ivLenInBytes for CCM algorithm\n"); + return CPA_STATUS_INVALID_PARAM; + } + + return CPA_STATUS_SUCCESS; +} + + +/** + * @ingroup LacAuthEnc + */ +void +LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes) +{ + Cpa8U n = + ivLenInBytes; /* assumes ivLenInBytes has been param checked */ + Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n; + Cpa8U lenOfEncodedLen = 0; + Cpa16U lenAEncoded = 0; + Cpa32U bitStrQ = 0; + + /* populate Ctr0 block - stored in pIv */ + pIv[0] = (q - 1); + /* bytes 1 to n are already set with nonce by the user */ + /* set last q bytes with 0 */ + memset(pIv + n + 1, 0, q); + + /* Encode the length of associated data 'a'. As the API limits the + * length + * of an array pointed by pAdditionalAuthData to be 240 bytes max, the + * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding + * below is simplified. */ + if (pSessionDesc->aadLenInBytes > 0) { + lenOfEncodedLen = sizeof(Cpa16U); + lenAEncoded = QAT_UTILS_HOST_TO_NW_16( + (Cpa16U)pSessionDesc->aadLenInBytes); + } + + /* populate B0 block */ + /* first, set the flags field */ + pAdditionalAuthData[0] = + LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen, + pSessionDesc->hashResultSize, + q); + /* bytes 1 to n are already set with nonce by the user*/ + /* put Q in bytes 16-q...15 */ + bitStrQ = QAT_UTILS_HOST_TO_NW_32(messageLenToCipherInBytes); + + if (q > sizeof(bitStrQ)) { + memset(pAdditionalAuthData + n + 1, 0, q); + memcpy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)), + (Cpa8U *)&bitStrQ, + sizeof(bitStrQ)); + } else { + memcpy(pAdditionalAuthData + n + 1, + ((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q), + q); + } + + /* populate B1-Bn blocks */ + if (lenAEncoded > 0) { + *(Cpa16U + *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) = + lenAEncoded; + /* Next bytes are already set by the user with + * the associated data 'a' */ + + /* Check if padding is required */ + if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % + LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) { + Cpa8U paddingLen = 0; + Cpa8U paddingIndex = 0; + + paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE - + ((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % + LAC_HASH_AES_CCM_BLOCK_SIZE); + + paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST; + paddingIndex += + lenOfEncodedLen + pSessionDesc->aadLenInBytes; + + memset(&pAdditionalAuthData[paddingIndex], + 0, + paddingLen); + } + } +} + +/** + * @ingroup LacAuthEnc + */ +void +LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData) +{ + Cpa8U paddingLen = 0; + + if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) { + paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE - + (pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE); + + memset(&pAdditionalAuthData[pSessionDesc->aadLenInBytes], + 0, + paddingLen); + } +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c new file mode 100644 index 00000000000..8fa0a798304 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c @@ -0,0 +1,545 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cb.c Callback handler functions for symmetric components + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_qat_fw_la.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" + +#include "lac_sym.h" +#include "lac_sym_cipher.h" +#include "lac_common.h" +#include "lac_list.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_session.h" +#include "lac_sym_stats.h" +#include "lac_log.h" +#include "lac_sym_cb.h" +#include "lac_sym_hash.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat.h" + +#define DEQUEUE_MSGPUT_MAX_RETRIES 10000 + +/* +******************************************************************************* +* Define static function definitions +******************************************************************************* +*/ + +/** + ***************************************************************************** + * @ingroup LacSymCb + * Function to clean computed data. + * + * @description + * This function cleans GCM or CCM data in the case of a failure. + * + * @param[in] pSessionDesc pointer to the session descriptor + * @param[out] pBufferList pointer to the bufferlist to clean + * @param[in] pOpData pointer to operation data + * @param[in] isCCM is it a CCM operation boolean + * + * @return None + *****************************************************************************/ +static void +LacSymCb_CleanUserData(const lac_session_desc_t *pSessionDesc, + CpaBufferList *pBufferList, + const CpaCySymOpData *pOpData, + CpaBoolean isCCM) +{ + Cpa8U authTagLen = 0; + + /* Retrieve authTagLen */ + authTagLen = pSessionDesc->hashResultSize; + + /* Cleaning */ + if (isCCM) { + /* for CCM the digest is inside the buffer list */ + LacBuffDesc_BufferListZeroFromOffset( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes, + pOpData->messageLenToCipherInBytes + authTagLen); + } else { + /* clean buffer list */ + LacBuffDesc_BufferListZeroFromOffset( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes, + pOpData->messageLenToCipherInBytes); + } + if ((CPA_TRUE != pSessionDesc->digestIsAppended) && + (NULL != pOpData->pDigestResult)) { + /* clean digest */ + memset(pOpData->pDigestResult, 0, authTagLen); + } +} + +/** + ***************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric responses + * + * @description + * This callback is invoked to process symmetric response messages from + * the QAT. It will extract some details from the message and invoke + * the user's callback to complete a symmetric operation. + * + * @param[in] pCookie Pointer to cookie associated with this request + * @param[in] qatRespStatusOkFlag Boolean indicating ok/fail status from QAT + * @param[in] status Status variable indicating an error occurred + * in sending the message (e.g. when dequeueing) + * @param[in] pSessionDesc Session descriptor + * + * @return None + *****************************************************************************/ +static void +LacSymCb_ProcessCallbackInternal(lac_sym_bulk_cookie_t *pCookie, + CpaBoolean qatRespStatusOkFlag, + CpaStatus status, + lac_session_desc_t *pSessionDesc) +{ + CpaCySymCbFunc pSymCb = NULL; + void *pCallbackTag = NULL; + CpaCySymOpData *pOpData = NULL; + CpaBufferList *pDstBuffer = NULL; + CpaCySymOp operationType = CPA_CY_SYM_OP_NONE; + CpaStatus dequeueStatus = CPA_STATUS_SUCCESS; + + CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; + /* NOTE: cookie pointer validated in previous function */ + instanceHandle = pCookie->instanceHandle; + + pOpData = (CpaCySymOpData *)LAC_CONST_PTR_CAST(pCookie->pOpData); + operationType = pSessionDesc->symOperation; + + /* Set the destination pointer to the one supplied in the cookie. */ + pDstBuffer = pCookie->pDstBuffer; + + /* For a digest verify operation - for full packet and final partial + * only, perform a comparison with the digest generated and with the one + * supplied in the packet. */ + + if (((pSessionDesc->isSinglePass && + (CPA_CY_SYM_CIPHER_AES_GCM == pSessionDesc->cipherAlgorithm)) || + (CPA_CY_SYM_OP_CIPHER != operationType)) && + (CPA_TRUE == pSessionDesc->digestVerify) && + ((CPA_CY_SYM_PACKET_TYPE_FULL == pOpData->packetType) || + (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType))) { + if (CPA_FALSE == qatRespStatusOkFlag) { + LAC_SYM_STAT_INC(numSymOpVerifyFailures, + instanceHandle); + + /* The comparison has failed at this point (status is + * fail), + * need to clean any sensitive calculated data up to + * this point. + * The data calculated is no longer useful to the end + * result and + * does not need to be returned to the user so setting + * buffers to + * zero. + */ + if (pSessionDesc->cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_CCM) { + LacSymCb_CleanUserData(pSessionDesc, + pDstBuffer, + pOpData, + CPA_TRUE); + } else if (pSessionDesc->cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_GCM) { + LacSymCb_CleanUserData(pSessionDesc, + pDstBuffer, + pOpData, + CPA_FALSE); + } + } + } else { + /* Most commands have no point of failure and always return + * success. This is the default response from the QAT. + * If status is already set to an error value, don't overwrite + * it + */ + if ((CPA_STATUS_SUCCESS == status) && + (CPA_TRUE != qatRespStatusOkFlag)) { + LAC_LOG_ERROR("Response status value not as expected"); + status = CPA_STATUS_FAIL; + } + } + + pSymCb = pSessionDesc->pSymCb; + pCallbackTag = pCookie->pCallbackTag; + + /* State returned to the client for intermediate partials packets + * for hash only and cipher only partial packets. Cipher update + * allow next partial through */ + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) { + if ((CPA_CY_SYM_OP_CIPHER == operationType) || + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { + if (CPA_TRUE == pCookie->updateUserIvOnRecieve) { + /* Update the user's IV buffer + * Very important to do this BEFORE dequeuing + * subsequent partial requests, as the state + * buffer + * may get overwritten + */ + memcpy(pCookie->pOpData->pIv, + pSessionDesc->cipherPartialOpState, + pCookie->pOpData->ivLenInBytes); + } + if (CPA_TRUE == pCookie->updateKeySizeOnRecieve && + LAC_CIPHER_IS_XTS_MODE( + pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherXTSModeUpdateKeyLen( + pSessionDesc, + pSessionDesc->cipherKeyLenInBytes / 2); + } + } + } else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType) { + if ((CPA_CY_SYM_OP_CIPHER == operationType) || + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { + if (CPA_TRUE == LAC_CIPHER_IS_XTS_MODE( + pSessionDesc->cipherAlgorithm)) { + /* + * For XTS mode, we replace the updated key with + * the original key - for subsequent partial + * requests + * + */ + LacSymQat_CipherXTSModeUpdateKeyLen( + pSessionDesc, + pSessionDesc->cipherKeyLenInBytes); + } + } + } + + if ((CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) && + (qatRespStatusOkFlag != CPA_FALSE)) { + /* There may be requests blocked pending the completion of this + * operation + */ + + dequeueStatus = LacSymCb_PendingReqsDequeue(pSessionDesc); + if (CPA_STATUS_SUCCESS != dequeueStatus) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + qatRespStatusOkFlag = CPA_FALSE; + if (CPA_STATUS_SUCCESS == status) { + status = dequeueStatus; + } + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* update stats */ + if (pSessionDesc->internalSession == CPA_FALSE) { + LAC_SYM_STAT_INC(numSymOpCompleted, instanceHandle); + if (CPA_STATUS_SUCCESS != status) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + } + } + } + + qatUtilsAtomicDec(&(pSessionDesc->u.pendingCbCount)); + + /* deallocate the memory for the internal callback cookie */ + Lac_MemPoolEntryFree(pCookie); + + /* user callback function is the last thing to be called */ + pSymCb(pCallbackTag, + status, + operationType, + pOpData, + pDstBuffer, + qatRespStatusOkFlag); +} + +/** + ****************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric Data Plane + * responses + * + * @description + * This callback checks the status, decrements the number of operations + * pending and calls the user callback + * + * @param[in/out] pResponse pointer to the response structure + * @param[in] qatRespStatusOkFlag status + * @param[in] pSessionDesc pointer to the session descriptor + * + * @return None + ******************************************************************************/ +static void +LacSymCb_ProcessDpCallback(CpaCySymDpOpData *pResponse, + CpaBoolean qatRespStatusOkFlag, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* For CCM and GCM, if qatRespStatusOkFlag is false, the data has to be + * cleaned as stated in RFC 3610; in DP mode, it is the user + * responsability + * to do so */ + + if (CPA_FALSE == pSessionDesc->isSinglePass) { + if ((CPA_CY_SYM_OP_CIPHER == pSessionDesc->symOperation) || + (CPA_FALSE == pSessionDesc->digestVerify)) { + /* If not doing digest compare and qatRespStatusOkFlag + != + CPA_TRUE + then there is something very wrong */ + if (CPA_FALSE == qatRespStatusOkFlag) { + LAC_LOG_ERROR( + "Response status value not as expected"); + status = CPA_STATUS_FAIL; + } + } + } + + ((sal_crypto_service_t *)pResponse->instanceHandle) + ->pSymDpCb(pResponse, status, qatRespStatusOkFlag); + /* + * Decrement the number of pending CB. + * + * If the @pendingDpCbCount becomes zero, we may remove the session, + * please + * read more information in the cpaCySymRemoveSession(). + * + * But there is a field in the @pResponse to store the session, + * the "sessionCtx". In another word, in the above @->pSymDpCb() + * callback, + * it may use the session again. If we decrease the @pendingDpCbCount + * before + * the @->pSymDpCb(), there is a _risk_ the @->pSymDpCb() may reference + * to + * a deleted session. + * + * So in order to avoid the risk, we decrease the @pendingDpCbCount + * after + * the @->pSymDpCb() callback. + */ + qatUtilsAtomicDec(&pSessionDesc->u.pendingDpCbCount); +} + +/** + ****************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric responses + * + * @description + * This callback, which is registered with the common symmetric response + * message handler, is invoked to process symmetric response messages from + * the QAT. It will extract the response status from the cmnRespFlags set + * by the QAT, and then will pass it to @ref + * LacSymCb_ProcessCallbackInternal to complete the response processing. + * + * @param[in] lacCmdId ID of the symmetric QAT command of the request + * message + * @param[in] pOpaqueData pointer to opaque data in the request message + * @param[in] cmnRespFlags Flags set by QAT to indicate response status + * + * @return None + ******************************************************************************/ +static void +LacSymCb_ProcessCallback(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + CpaCySymDpOpData *pDpOpData = (CpaCySymDpOpData *)pOpaqueData; + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pDpOpData->sessionCtx); + CpaBoolean qatRespStatusOkFlag = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)); + + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* DP session */ + LacSymCb_ProcessDpCallback(pDpOpData, + qatRespStatusOkFlag, + pSessionDesc); + } else { + /* Trad session */ + LacSymCb_ProcessCallbackInternal((lac_sym_bulk_cookie_t *) + pOpaqueData, + qatRespStatusOkFlag, + CPA_STATUS_SUCCESS, + pSessionDesc); + } +} + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +/** + * @ingroup LacSymCb + * + * @return CpaStatus + * value returned will be the result of icp_adf_transPutMsg + */ +CpaStatus +LacSymCb_PendingReqsDequeue(lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + Cpa32U retries = 0; + + pService = (sal_crypto_service_t *)pSessionDesc->pInstance; + + /* Need to protect access to queue head and tail pointers, which may + * be accessed by multiple contexts simultaneously for enqueue and + * dequeue operations + */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to lock request queue"); + return CPA_STATUS_RESOURCE; + } + + /* Clear the blocking flag in the session descriptor */ + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + + while ((NULL != pSessionDesc->pRequestQueueHead) && + (CPA_TRUE == pSessionDesc->nonBlockingOpsInProgress)) { + + /* If we send a partial packet request, set the + * blockingOpsInProgress + * flag for the session to indicate that subsequent requests + * must be + * queued up until this request completes + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != + pSessionDesc->pRequestQueueHead->pOpData->packetType) { + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + } + + /* At this point, we're clear to send the request. For cipher + * requests, + * we need to check if the session IV needs to be updated. This + * can + * only be done when no other partials are in flight for this + * session, + * to ensure the cipherPartialOpState buffer in the session + * descriptor + * is not currently in use + */ + if (CPA_TRUE == + pSessionDesc->pRequestQueueHead->updateSessionIvOnSend) { + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->cipherARC4InitialState, + LAC_CIPHER_ARC4_STATE_LEN_BYTES); + } else { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->pRequestQueueHead->pOpData + ->pIv, + pSessionDesc->pRequestQueueHead->pOpData + ->ivLenInBytes); + } + } + + /* + * Now we'll attempt to send the message directly to QAT. We'll + * keep + * looing until it succeeds (or at least a very high number of + * retries), + * as the failure only happens when the ring is full, and this + * is only + * a temporary situation. After a few retries, space will become + * availble, allowing the putMsg to succeed. + */ + retries = 0; + do { + /* Send to QAT */ + status = icp_adf_transPutMsg( + pService->trans_handle_sym_tx, + (void *)&(pSessionDesc->pRequestQueueHead->qatMsg), + LAC_QAT_SYM_REQ_SZ_LW); + + retries++; + /* + * Yield to allow other threads that may be on this + * session to poll + * and make some space on the ring + */ + if (CPA_STATUS_SUCCESS != status) { + qatUtilsYield(); + } + } while ((CPA_STATUS_SUCCESS != status) && + (retries < DEQUEUE_MSGPUT_MAX_RETRIES)); + + if ((CPA_STATUS_SUCCESS != status) || + (retries >= DEQUEUE_MSGPUT_MAX_RETRIES)) { + LAC_LOG_ERROR( + "Failed to SalQatMsg_transPutMsg, maximum retries exceeded."); + goto cleanup; + } + + pSessionDesc->pRequestQueueHead = + pSessionDesc->pRequestQueueHead->pNext; + } + + /* If we've drained the queue, ensure the tail pointer is set to NULL */ + if (NULL == pSessionDesc->pRequestQueueHead) { + pSessionDesc->pRequestQueueTail = NULL; + } + +cleanup: + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to unlock request queue"); + } + return status; +} + +/** + * @ingroup LacSymCb + */ +void +LacSymCb_CallbacksRegister() +{ + /*** HASH ***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_AUTH, + LacSymCb_ProcessCallback); + + /*** ALGORITHM-CHAINING CIPHER_HASH***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER_HASH, + LacSymCb_ProcessCallback); + + /*** ALGORITHM-CHAINING HASH_CIPHER***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HASH_CIPHER, + LacSymCb_ProcessCallback); + + /*** CIPHER ***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER, + LacSymCb_ProcessCallback); + + /* Call compile time param check function to ensure it is included + in the build by the compiler - this compile time check + ensures callbacks run as expected */ + LacSym_CompileTimeAssertions(); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c new file mode 100644 index 00000000000..0039c1f6688 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cipher.c Cipher + * + * @ingroup LacCipher + * + * @description Functions specific to cipher + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +#include "icp_qat_fw_la.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_sym_cipher.h" +#include "lac_session.h" +#include "lac_mem.h" +#include "lac_common.h" +#include "lac_list.h" +#include "lac_sym.h" +#include "lac_sym_key.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_sym_cipher_defs.h" +#include "lac_sym_cipher.h" +#include "lac_sym_stats.h" +#include "lac_sym.h" +#include "lac_sym_qat_cipher.h" +#include "lac_log.h" +#include "lac_buffer_desc.h" + +/* +******************************************************************************* +* Static Variables +******************************************************************************* +*/ + +CpaStatus +LacCipher_PerformIvCheck(sal_service_t *pService, + lac_sym_bulk_cookie_t *pCbCookie, + Cpa32U qatPacketType, + Cpa8U **ppIvBuffer) +{ + const CpaCySymOpData *pOpData = pCbCookie->pOpData; + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); + CpaCySymCipherAlgorithm algorithm = pSessionDesc->cipherAlgorithm; + + /* Perform IV check. */ + if (LAC_CIPHER_IS_CTR_MODE(algorithm) || + LAC_CIPHER_IS_CBC_MODE(algorithm) || + LAC_CIPHER_IS_AES_F8(algorithm) || + LAC_CIPHER_IS_XTS_MODE(algorithm)) { + unsigned ivLenInBytes = + LacSymQat_CipherIvSizeBytesGet(algorithm); + LAC_CHECK_NULL_PARAM(pOpData->pIv); + if (pOpData->ivLenInBytes != ivLenInBytes) { + if (!(/* GCM with 12 byte IV is OK */ + (LAC_CIPHER_IS_GCM(algorithm) && + pOpData->ivLenInBytes == + LAC_CIPHER_IV_SIZE_GCM_12) || + /* IV len for CCM has been checked before */ + LAC_CIPHER_IS_CCM(algorithm))) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Always copy the user's IV into another cipher state buffer if + * the request is part of a partial packet sequence + * (ensures that pipelined partial requests use same + * buffer) + */ + if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { + /* Set the value of the ppIvBuffer to that supplied + * by the user. + * NOTE: There is no guarantee that this address is + * aligned on + * an 8 or 64 Byte address. */ + *ppIvBuffer = pOpData->pIv; + } else { + /* For partial packets, we use a per-session buffer to + * maintain + * the IV. This allows us to easily pass the updated IV + * forward + * to the next partial in the sequence. This makes + * internal + * buffering of partials easier to implement. + */ + *ppIvBuffer = pSessionDesc->cipherPartialOpState; + + /* Ensure that the user's IV buffer gets updated between + * partial + * requests so that they may also see the residue from + * the + * previous partial. Not needed for final partials + * though. + */ + if ((ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) || + (ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType)) { + pCbCookie->updateUserIvOnRecieve = CPA_TRUE; + + if (ICP_QAT_FW_LA_PARTIAL_START == + qatPacketType) { + /* if the previous partial state was + * full, then this is + * the first partial in the sequence so + * we need to copy + * in the user's IV. But, we have to be + * very careful + * here not to overwrite the + * cipherPartialOpState just + * yet in case there's a previous + * partial sequence in + * flight, so we defer the copy for now. + * This will be + * completed in the + * LacSymQueue_RequestSend() function. + */ + pCbCookie->updateSessionIvOnSend = + CPA_TRUE; + } + /* For subsequent partials in a sequence, we'll + * re-use the + * IV that was written back by the QAT, using + * internal + * request queueing if necessary to ensure that + * the next + * partial request isn't issued to the QAT until + * the + * previous one completes + */ + } + } + } else if (LAC_CIPHER_IS_KASUMI(algorithm)) { + LAC_CHECK_NULL_PARAM(pOpData->pIv); + + if (LAC_CIPHER_IS_KASUMI(algorithm) && + (pOpData->ivLenInBytes != LAC_CIPHER_KASUMI_F8_IV_LENGTH)) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + + + *ppIvBuffer = pOpData->pIv; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(algorithm)) { + LAC_CHECK_NULL_PARAM(pOpData->pIv); + if (LAC_CIPHER_IS_SNOW3G_UEA2(algorithm) && + (pOpData->ivLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ)) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + *ppIvBuffer = pOpData->pIv; + } else if (LAC_CIPHER_IS_ARC4(algorithm)) { + if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { + /* For full packets, the initial ARC4 state is stored in + * the + * session descriptor. Use it directly. + */ + *ppIvBuffer = pSessionDesc->cipherARC4InitialState; + } else { + /* For partial packets, we maintain the running ARC4 + * state in + * dedicated buffer in the session descriptor + */ + *ppIvBuffer = pSessionDesc->cipherPartialOpState; + + if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) { + /* if the previous partial state was full, then + * this is the + * first partial in the sequence so we need to + * (re-)initialise + * the contents of the state buffer using the + * initial state + * that is stored in the session descriptor. + * But, we have to be + * very careful here not to overwrite the + * cipherPartialOpState + * just yet in case there's a previous partial + * sequence in + * flight, so we defer the copy for now. This + * will be completed + * in the LacSymQueue_RequestSend() function + * when clear to send. + */ + pCbCookie->updateSessionIvOnSend = CPA_TRUE; + } + } + } else if (LAC_CIPHER_IS_ZUC_EEA3(algorithm)) { + LAC_CHECK_NULL_PARAM(pOpData->pIv); + if (pOpData->ivLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + *ppIvBuffer = pOpData->pIv; + } else { + *ppIvBuffer = NULL; + } + + return CPA_STATUS_SUCCESS; +} + + +CpaStatus +LacCipher_SessionSetupDataCheck(const CpaCySymCipherSetupData *pCipherSetupData) +{ + /* No key required for NULL algorithm */ + if (!LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm)) { + LAC_CHECK_NULL_PARAM(pCipherSetupData->pCipherKey); + + /* Check that algorithm and keys passed in are correct size */ + if (LAC_CIPHER_IS_ARC4(pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes > + ICP_QAT_HW_ARC4_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid ARC4 cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_CCM( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid AES CCM cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_XTS_MODE( + pCipherSetupData->cipherAlgorithm)) { + if ((pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_XTS_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_256_XTS_KEY_SZ)) { + LAC_INVALID_PARAM_LOG( + "Invalid AES XTS cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_AES( + pCipherSetupData->cipherAlgorithm)) { + if ((pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_192_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_256_KEY_SZ)) { + LAC_INVALID_PARAM_LOG( + "Invalid AES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_AES_F8( + pCipherSetupData->cipherAlgorithm)) { + if ((pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_F8_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_192_F8_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_256_F8_KEY_SZ)) { + LAC_INVALID_PARAM_LOG( + "Invalid AES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_DES( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_DES_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid DES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_TRIPLE_DES( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_3DES_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid Triple-DES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_KASUMI( + pCipherSetupData->cipherAlgorithm)) { + /* QAT-FW only supports 128 bits Cipher Key size for + * Kasumi F8 + * Ref: 3GPP TS 55.216 V6.2.0 */ + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_KASUMI_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid Kasumi cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pCipherSetupData->cipherAlgorithm)) { + /* QAT-FW only supports 256 bits Cipher Key size for + * Snow_3G */ + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid Snow_3G cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pCipherSetupData->cipherAlgorithm)) { + /* ZUC EEA3 */ + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid ZUC cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_CHACHA( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_CHACHAPOLY_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid CHACHAPOLY cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SM4( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_SM4_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid SM4 cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + LAC_INVALID_PARAM_LOG("Invalid cipher algorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm algorithm, + const CpaCySymOpData *pOpData, + const Cpa64U packetLen) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* The following check will cover the dstBuffer as well, since + * the dstBuffer cannot be smaller than the srcBuffer (checked in + * LacSymPerform_BufferParamCheck() called from LacSym_Perform()) + */ + if ((pOpData->messageLenToCipherInBytes + + pOpData->cryptoStartSrcOffsetInBytes) > packetLen) { + LAC_INVALID_PARAM_LOG("cipher len + offset greater than " + "srcBuffer packet len"); + status = CPA_STATUS_INVALID_PARAM; + } + + if (CPA_STATUS_SUCCESS == status) { + /* + * XTS Mode allow for ciphers which are not multiples of + * the block size. + */ + /* Perform algorithm-specific checks */ + if (LAC_CIPHER_IS_XTS_MODE(algorithm) && + ((pOpData->packetType == CPA_CY_SYM_PACKET_TYPE_FULL) || + (pOpData->packetType == + CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL))) { + /* + * If this is the last of a partial request + */ + if (pOpData->messageLenToCipherInBytes < + ICP_QAT_HW_AES_BLK_SZ) { + LAC_INVALID_PARAM_LOG( + "data size must be greater than block " + "size for last XTS partial or XTS " + "full packet"); + status = CPA_STATUS_INVALID_PARAM; + } + } else if (!(LAC_CIPHER_IS_ARC4(algorithm) || + LAC_CIPHER_IS_CTR_MODE(algorithm) || + LAC_CIPHER_IS_F8_MODE(algorithm) || + LAC_CIPHER_IS_SNOW3G_UEA2(algorithm) || + LAC_CIPHER_IS_XTS_MODE(algorithm) || + LAC_CIPHER_IS_CHACHA(algorithm) || + LAC_CIPHER_IS_ZUC_EEA3(algorithm))) { + /* Mask & check below is based on assumption that block + * size is + * a power of 2. If data size is not a multiple of the + * block size, + * the "remainder" bits selected by the mask be non-zero + */ + if (pOpData->messageLenToCipherInBytes & + (LacSymQat_CipherBlockSizeBytesGet(algorithm) - + 1)) { + LAC_INVALID_PARAM_LOG( + "data size must be block size multiple"); + status = CPA_STATUS_INVALID_PARAM; + } + } + } + + return status; +} + diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c new file mode 100644 index 00000000000..d732add29c7 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c @@ -0,0 +1,45 @@ +/*************************************************************************** + * + * + * + ***************************************************************************/ + +/** + *************************************************************************** + * @file lac_sym_compile_check.c + * + * @ingroup LacSym + * + * This file checks at compile time that some assumptions about the layout + * of key structures are as expected. + * + * + ***************************************************************************/ + +#include "cpa.h" + +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sym.h" +#include "cpa_cy_sym_dp.h" + +#define COMPILE_TIME_ASSERT(pred) \ + switch (0) { \ + case 0: \ + case pred:; \ + } + +void +LacSym_CompileTimeAssertions(void) +{ + /* ************************************************************* + * Check sessionCtx is at the same location in bulk cookie and + * CpaCySymDpOpData. + * This is required for the callbacks to work as expected - + * see LacSymCb_ProcessCallback + * ************************************************************* */ + + COMPILE_TIME_ASSERT(offsetof(lac_sym_bulk_cookie_t, sessionCtx) == + offsetof(CpaCySymDpOpData, sessionCtx)); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c new file mode 100644 index 00000000000..4ccf1f7f82d --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c @@ -0,0 +1,1080 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_dp.c + * Implementation of the symmetric data plane API + * + * @ingroup cpaCySymDp + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_sym_dp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" +#include "icp_adf_debug.h" +#include "icp_sal_poll.h" + +#include "qat_utils.h" + +#include "lac_mem.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_sym_qat_cipher.h" +#include "lac_list.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" +#include "lac_sym_auth_enc.h" + +typedef void (*write_ringMsgFunc_t)(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Check that the operation data is valid + * + * @description + * Check that all the parameters defined in the operation data are valid + * + * @param[in] pRequest Pointer to an operation data for crypto + * data plane API + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +LacDp_EnqueueParamCheck(const CpaCySymDpOpData *pRequest) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaCySymCipherAlgorithm cipher = 0; + CpaCySymHashAlgorithm hash = 0; + Cpa32U capabilitiesMask = 0; + + LAC_CHECK_NULL_PARAM(pRequest); + LAC_CHECK_NULL_PARAM(pRequest->instanceHandle); + LAC_CHECK_NULL_PARAM(pRequest->sessionCtx); + + /* Ensure this is a crypto instance */ + SAL_CHECK_INSTANCE_TYPE(pRequest->instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + if (NULL == pSessionDesc) { + do { + qatUtilsSleep(500); + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET( + pRequest->sessionCtx); + } while (NULL == pSessionDesc); + } + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session context not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_INVALID_PARAM_LOG( + "Session not initialised for data plane API"); + return CPA_STATUS_INVALID_PARAM; + } + + /*check whether Payload size is zero for CHACHA-POLY */ + if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + if (!pRequest->messageLenToCipherInBytes) { + LAC_INVALID_PARAM_LOG( + "Invalid messageLenToCipherInBytes for CHACHA-POLY"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (0 == pRequest->srcBuffer) { + LAC_INVALID_PARAM_LOG("Invalid srcBuffer"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->dstBuffer) { + LAC_INVALID_PARAM_LOG("Invalid destBuffer"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->thisPhys) { + LAC_INVALID_PARAM_LOG("Invalid thisPhys"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check that src buffer Len = dst buffer Len + Note this also checks that they are of the same type */ + if (pRequest->srcBufferLen != pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Source and Destination buffer lengths need to be equal"); + return CPA_STATUS_INVALID_PARAM; + } + + /* digestVerify and digestIsAppended on Hash-Only operation not + * supported */ + if (pSessionDesc->digestIsAppended && pSessionDesc->digestVerify && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LAC_INVALID_PARAM_LOG( + "digestVerify and digestIsAppended set " + "on Hash-Only operation is not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Cipher specific tests */ + if (CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) { + /* Perform IV check */ + if ((LAC_CIPHER_IS_CTR_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CBC_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_AES_F8(pSessionDesc->cipherAlgorithm)) && + (!(LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)))) { + Cpa32U ivLenInBytes = LacSymQat_CipherIvSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if (pRequest->ivLenInBytes != ivLenInBytes) { + if (!(/* GCM with 12 byte IV is OK */ + (LAC_CIPHER_IS_GCM( + pSessionDesc->cipherAlgorithm) && + pRequest->ivLenInBytes == + LAC_CIPHER_IV_SIZE_GCM_12))) { + LAC_INVALID_PARAM_LOG( + "invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + + /* pRequest->pIv is only used for CCM so is not checked + * here */ + } else if (LAC_CIPHER_IS_KASUMI( + pSessionDesc->cipherAlgorithm)) { + if (LAC_CIPHER_KASUMI_F8_IV_LENGTH != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pSessionDesc->cipherAlgorithm)) { + if (ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pSessionDesc->cipherAlgorithm)) { + if (ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { + if (CPA_STATUS_SUCCESS != + LacSymAlgChain_CheckCCMData( + pRequest->pAdditionalAuthData, + pRequest->pIv, + pRequest->messageLenToCipherInBytes, + pRequest->ivLenInBytes)) { + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Perform algorithm-specific checks */ + if (!(LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CTR_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_F8_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_SNOW3G_UEA2( + pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_ZUC_EEA3(pSessionDesc->cipherAlgorithm))) { + /* Mask & check below is based on assumption that block + * size is + * a power of 2. If data size is not a multiple of the + * block size, + * the "remainder" bits selected by the mask be non-zero + */ + if (pRequest->messageLenToCipherInBytes & + (LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm) - + 1)) { + LAC_INVALID_PARAM_LOG( + "Data size must be block size multiple"); + return CPA_STATUS_INVALID_PARAM; + } + } + + cipher = pSessionDesc->cipherAlgorithm; + hash = pSessionDesc->hashAlgorithm; + capabilitiesMask = + ((sal_crypto_service_t *)pRequest->instanceHandle) + ->generic_service_info.capabilitiesMask; + if (LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pRequest->ivLenInBytes)) { + /* For CHACHA and AES_GCM single pass there is an AAD + * buffer + * if aadLenInBytes is nonzero. AES_GMAC AAD is stored + * in + * source buffer, therefore there is no separate AAD + * buffer. */ + if ((0 != pSessionDesc->aadLenInBytes) && + (CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm)) { + LAC_CHECK_NULL_PARAM( + pRequest->pAdditionalAuthData); + } + + /* Ensure AAD length for AES_GMAC spc */ + if ((CPA_CY_SYM_HASH_AES_GMAC == hash) && + (ICP_QAT_FW_SPC_AAD_SZ_MAX < + pRequest->messageLenToHashInBytes)) { + LAC_INVALID_PARAM_LOG( + "aadLenInBytes for AES_GMAC"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + /* Hash specific tests */ + if (CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation) { + /* For CCM, snow3G and ZUC there is always an AAD buffer + For GCM there is an AAD buffer if aadLenInBytes is + nonzero */ + if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm && + (0 != pSessionDesc->aadLenInBytes))) { + LAC_CHECK_NULL_PARAM(pRequest->pAdditionalAuthData); + if (0 == pRequest->additionalAuthData) { + LAC_INVALID_PARAM_LOG( + "Invalid additionalAuthData"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + if (0 == pRequest->additionalAuthData) { + LAC_INVALID_PARAM_LOG( + "Invalid additionalAuthData"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if ((CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm) && + (!pSessionDesc->digestIsAppended) && + (0 == pRequest->digestResult)) { + LAC_INVALID_PARAM_LOG("Invalid digestResult"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) { + if ((pRequest->cryptoStartSrcOffsetInBytes + + pRequest->messageLenToCipherInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "CCM - Not enough room for" + " digest in destination buffer"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_TRUE == pSessionDesc->digestIsAppended) { + if (CPA_CY_SYM_HASH_AES_GMAC == + pSessionDesc->hashAlgorithm) { + if ((pRequest->hashStartSrcOffsetInBytes + + pRequest->messageLenToHashInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room for" + " digest in destination buffer for " + "AES GMAC algorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_CY_SYM_HASH_AES_GCM == + pSessionDesc->hashAlgorithm) { + if ((pRequest->cryptoStartSrcOffsetInBytes + + pRequest->messageLenToCipherInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room " + "for digest in destination buffer" + " for GCM algorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if ((pRequest->hashStartSrcOffsetInBytes + + pRequest->messageLenToHashInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room for" + " digest in destination buffer"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + if (pRequest->messageLenToHashInBytes == 0 || + pRequest->pAdditionalAuthData != NULL) { + LAC_INVALID_PARAM_LOG( + "For AES_GMAC, AAD Length " + "(messageLenToHashInBytes) must be " + "non zero and pAdditionalAuthData " + "must be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + if (CPA_DP_BUFLIST != pRequest->srcBufferLen) { + if ((CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) && + ((pRequest->messageLenToCipherInBytes + + pRequest->cryptoStartSrcOffsetInBytes) > + pRequest->srcBufferLen)) { + LAC_INVALID_PARAM_LOG( + "cipher len + offset greater than " + "srcBufferLen"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_CY_SYM_OP_CIPHER != + pSessionDesc->symOperation) && + (CPA_CY_SYM_HASH_AES_CCM != + pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_HASH_AES_GCM != + pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) && + ((pRequest->messageLenToHashInBytes + + pRequest->hashStartSrcOffsetInBytes) > + pRequest->srcBufferLen)) { + LAC_INVALID_PARAM_LOG( + "hash len + offset greater than srcBufferLen"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->srcBuffer); + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->dstBuffer); + } + + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->thisPhys); + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Write Message on the ring and write request params + * This is the optimized version, which should not be used for + * algorithm of CCM, GCM and RC4 + * + * @description + * Write Message on the ring and write request params + * + * @param[in/out] pRequest Pointer to operation data for crypto + * data plane API + * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will + * be written + * + * @retval none + * + *****************************************************************************/ + +void +LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) +{ + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + + pMsgDummy = (Cpa8U *)pCurrentQatMsg; + /* Write Request */ + /* + * Fill in the header and footer bytes of the ET ring message - cached + * from + * the session descriptor. + */ + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_CmnMidWrite(pCurrentQatMsg, + pRequest, + (CPA_DP_BUFLIST == pRequest->srcBufferLen ? + QAT_COMN_PTR_TYPE_SGL : + QAT_COMN_PTR_TYPE_FLAT), + pRequest->srcBuffer, + pRequest->dstBuffer, + pRequest->srcBufferLen, + pRequest->dstBufferLen); + + /* Write Request Params */ + if (pSessionDesc->isCipher) { + + LacSymQat_CipherRequestParamsPopulate( + pCurrentQatMsg, + pRequest->cryptoStartSrcOffsetInBytes, + pRequest->messageLenToCipherInBytes, + pRequest->iv, + pRequest->pIv); + } + + if (pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + icp_qat_fw_la_auth_req_params_t *pAuthReqPars = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && + (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { + /* prefixAadSzQuadWords > 0 when there is prefix data + - i.e. nested hash or HMAC no precompute cases + Note partials not supported on DP api so we do not need + dynamic hash state in this case */ + pRequest->additionalAuthData = + pHashStateBufferInfo->pDataPhys + + LAC_QUADWORDS_TO_BYTES( + pHashStateBufferInfo->stateStorageSzQuadWords); + } + + /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be + * copied directly from the op request data because they share a + * corresponding layout. The remaining 4 bytes are taken + * from the session message template and use values + * preconfigured at + * sessionInit (updated per request for some specific cases + * below) + */ + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + ((unsigned long)&(pAuthReqPars->u2.inner_prefix_sz) - + (unsigned long)pAuthReqPars)); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); + } + } + +} + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Write Message on the ring and write request params + * + * @description + * Write Message on the ring and write request params + * + * @param[in/out] pRequest Pointer to operation data for crypto + * data plane API + * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will + * be written + * + * @retval none + * + *****************************************************************************/ + +void +LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) +{ + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + sal_qat_content_desc_info_t *pCdInfo = NULL; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U sizeInBytes = 0; + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + CpaCySymHashAlgorithm hash = pSessionDesc->hashAlgorithm; + Cpa32U capabilitiesMask = + ((sal_crypto_service_t *)pRequest->instanceHandle) + ->generic_service_info.capabilitiesMask; + + Cpa8U paddingLen = 0; + Cpa8U blockLen = 0; + + pMsgDummy = (Cpa8U *)pCurrentQatMsg; + /* Write Request */ + /* + * Fill in the header and footer bytes of the ET ring message - cached + * from + * the session descriptor. + */ + + if (!pSessionDesc->isSinglePass && + LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pRequest->ivLenInBytes)) { + pSessionDesc->isSinglePass = CPA_TRUE; + pSessionDesc->isCipher = CPA_TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + pSessionDesc->isAuth = CPA_FALSE; + pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = + pRequest->messageLenToHashInBytes; + } + /* New bit position (13) for SINGLE PASS. + * The FW provides a specific macro to use to set the proto flag + */ + ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, 0); + + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &sizeInBytes); + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr), + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = pRequest->messageLenToHashInBytes; + } + if (pSessionDesc->isSinglePass) { + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); + } else { + if (!pSessionDesc->useSymConstantsTable) { + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); + } else { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); + } + } + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_CmnMidWrite(pCurrentQatMsg, + pRequest, + (CPA_DP_BUFLIST == pRequest->srcBufferLen ? + QAT_COMN_PTR_TYPE_SGL : + QAT_COMN_PTR_TYPE_FLAT), + pRequest->srcBuffer, + pRequest->dstBuffer, + pRequest->srcBufferLen, + pRequest->dstBufferLen); + + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm && + pSessionDesc->isAuth == CPA_TRUE) { + /* prepare IV and AAD for CCM */ + LacSymAlgChain_PrepareCCMData( + pSessionDesc, + pRequest->pAdditionalAuthData, + pRequest->pIv, + pRequest->messageLenToCipherInBytes, + pRequest->ivLenInBytes); + + /* According to the API, for CCM and GCM, + * messageLenToHashInBytes + * and hashStartSrcOffsetInBytes are not initialized by the + * user and must be set by the driver + */ + pRequest->hashStartSrcOffsetInBytes = + pRequest->cryptoStartSrcOffsetInBytes; + pRequest->messageLenToHashInBytes = + pRequest->messageLenToCipherInBytes; + } else if (!pSessionDesc->isSinglePass && + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm)) { + /* GCM case */ + if (CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm) { + /* According to the API, for CCM and GCM, + * messageLenToHashInBytes and hashStartSrcOffsetInBytes + * are not initialized by the user and must be set + * by the driver + */ + pRequest->hashStartSrcOffsetInBytes = + pRequest->cryptoStartSrcOffsetInBytes; + pRequest->messageLenToHashInBytes = + pRequest->messageLenToCipherInBytes; + + LacSymAlgChain_PrepareGCMData( + pSessionDesc, pRequest->pAdditionalAuthData); + } + + if (LAC_CIPHER_IV_SIZE_GCM_12 == pRequest->ivLenInBytes) { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + pCurrentQatMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); + } + } + + /* Write Request Params */ + if (pSessionDesc->isCipher) { + if (CPA_CY_SYM_CIPHER_ARC4 == pSessionDesc->cipherAlgorithm) { + /* ARC4 does not have an IV but the field is used to + * store the + * initial state */ + pRequest->iv = + pSessionDesc->cipherARC4InitialStatePhysAddr; + } + + LacSymQat_CipherRequestParamsPopulate( + pCurrentQatMsg, + pRequest->cryptoStartSrcOffsetInBytes, + pRequest->messageLenToCipherInBytes, + pRequest->iv, + pRequest->pIv); + if (pSessionDesc->isSinglePass) { + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams = + (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&( + pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + + pCipherReqParams->spc_aad_addr = + (uint64_t)pRequest->additionalAuthData; + pCipherReqParams->spc_aad_sz = + pSessionDesc->aadLenInBytes; + + pCipherReqParams->spc_auth_res_addr = + (uint64_t)pRequest->digestResult; + pCipherReqParams->spc_auth_res_sz = + pSessionDesc->hashResultSize; + + /* For CHACHA and AES_GCM single pass AAD buffer needs + * alignment + * if aadLenInBytes is nonzero. + * In case of AES-GMAC, AAD buffer passed in the src + * buffer. + */ + if (0 != pSessionDesc->aadLenInBytes && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + blockLen = LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if ((pSessionDesc->aadLenInBytes % blockLen) != + 0) { + paddingLen = blockLen - + (pSessionDesc->aadLenInBytes % + blockLen); + memset( + &pRequest->pAdditionalAuthData + [pSessionDesc->aadLenInBytes], + 0, + paddingLen); + } + } + } + } + + if (pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + icp_qat_fw_la_auth_req_params_t *pAuthReqPars = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && + (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { + /* prefixAadSzQuadWords > 0 when there is prefix data + - i.e. nested hash or HMAC no precompute cases + Note partials not supported on DP api so we do not need + dynamic hash state in this case */ + pRequest->additionalAuthData = + pHashStateBufferInfo->pDataPhys + + LAC_QUADWORDS_TO_BYTES( + pHashStateBufferInfo->stateStorageSzQuadWords); + } + + /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be + * copied directly from the op request data because they share a + * corresponding layout. The remaining 4 bytes are taken + * from the session message template and use values + * preconfigured at + * sessionInit (updated per request for some specific cases + * below) + */ + + /* We force a specific compiler optimisation here. The length + * to + * be copied turns out to be always 16, and by coding a memcpy + * with + * a literal value the compiler will compile inline code (in + * fact, + * only two vector instructions) to effect the copy. This gives + * us + * a huge performance increase. + */ + unsigned long cplen = + (unsigned long)&(pAuthReqPars->u2.inner_prefix_sz) - + (unsigned long)pAuthReqPars; + if (cplen == 16) + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + 16); + else + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + cplen); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); + } + } + +} + +CpaStatus +cpaCySymDpSessionCtxGetSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + /* All other param checks are common with trad api */ + /* Check for valid pointers */ + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + status = cpaCySymSessionCtxGetSize(instanceHandle, + pSessionSetupData, + pSessionCtxSizeInBytes); + + return status; +} + +CpaStatus +cpaCySymDpSessionCtxGetDynamicSize( + const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + /* All other param checks are common with trad api */ + /* Check for valid pointers */ + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + status = cpaCySymSessionCtxGetDynamicSize(instanceHandle, + pSessionSetupData, + pSessionCtxSizeInBytes); + + return status; +} + +/** @ingroup cpaCySymDp */ +CpaStatus +cpaCySymDpInitSession(CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymDpSessionCtx sessionCtx) +{ + CpaStatus status = CPA_STATUS_FAIL; + sal_service_t *pService = NULL; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + pService = (sal_service_t *)instanceHandle; + + /* Check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + status = LacSym_InitSession(instanceHandle, + NULL, /* Callback */ + pSessionSetupData, + CPA_TRUE, /* isDPSession */ + sessionCtx); + return status; +} + +CpaStatus +cpaCySymDpRemoveSession(const CpaInstanceHandle instanceHandle, + CpaCySymDpSessionCtx sessionCtx) +{ + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); +/* All other param checks are common with trad api */ + + return cpaCySymRemoveSession(instanceHandle, sessionCtx); +} + +CpaStatus +cpaCySymDpRegCbFunc(const CpaInstanceHandle instanceHandle, + const CpaCySymDpCbFunc pSymDpCb) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymDpCb); + SAL_RUNNING_CHECK(instanceHandle); + pService->pSymDpCb = pSymDpCb; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpEnqueueOp(CpaCySymDpOpData *pRequest, const CpaBoolean performOpNow) +{ + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + lac_session_desc_t *pSessionDesc = NULL; + write_ringMsgFunc_t callFunc; + + CpaStatus status = CPA_STATUS_SUCCESS; + + + LAC_CHECK_NULL_PARAM(pRequest); + status = LacDp_EnqueueParamCheck(pRequest); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + trans_handle = ((sal_crypto_service_t *)pRequest->instanceHandle) + ->trans_handle_sym_tx; + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + /* + * No space is available on the queue. + */ + return CPA_STATUS_RETRY; + } + + callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; + + LAC_CHECK_NULL_PARAM(callFunc); + + callFunc(pRequest, pCurrentQatMsg); + + qatUtilsAtomicInc(&(pSessionDesc->u.pendingDpCbCount)); + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpPerformOpNow(const CpaInstanceHandle instanceHandle) +{ + icp_comms_trans_handle trans_handle = NULL; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + trans_handle = + ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaCySymDpOpData *pRequests[], + const CpaBoolean performOpNow) +{ + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + lac_session_desc_t *pSessionDesc = NULL; + write_ringMsgFunc_t callFunc; + Cpa32U i = 0; + + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + LAC_CHECK_NULL_PARAM(pRequests); + LAC_CHECK_NULL_PARAM(pRequests[0]); + LAC_CHECK_NULL_PARAM(pRequests[0]->instanceHandle); + + pService = (sal_crypto_service_t *)(pRequests[0]->instanceHandle); + + if ((0 == numberRequests) || + (numberRequests > pService->maxNumSymReqBatch)) { + LAC_INVALID_PARAM_LOG1( + "The number of requests needs to be between 1 " + "and %d", + pService->maxNumSymReqBatch); + return CPA_STATUS_INVALID_PARAM; + } + + for (i = 0; i < numberRequests; i++) { + status = LacDp_EnqueueParamCheck(pRequests[i]); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + /* Check that all instance handles are the same */ + if (pRequests[i]->instanceHandle != + pRequests[0]->instanceHandle) { + LAC_INVALID_PARAM_LOG( + "All instance handles should be the same " + "in the requests"); + return CPA_STATUS_INVALID_PARAM; + } + } + + trans_handle = ((sal_crypto_service_t *)pRequests[0]->instanceHandle) + ->trans_handle_sym_tx; + pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequests[0]->sessionCtx); + icp_adf_getQueueMemory(trans_handle, + numberRequests, + (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + /* + * No space is available on the queue. + */ + return CPA_STATUS_RETRY; + } + + for (i = 0; i < numberRequests; i++) { + pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequests[i]->sessionCtx); + callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; + callFunc(pRequests[i], pCurrentQatMsg); + icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); + qatUtilsAtomicAdd(1, &(pSessionDesc->u.pendingDpCbCount)); + } + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_CyPollDpInstance(const CpaInstanceHandle instanceHandle, + const Cpa32U responseQuota) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + trans_handle = + ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_rx; + + return icp_adf_pollQueue(trans_handle, responseQuota); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c new file mode 100644 index 00000000000..e662d0d6d22 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c @@ -0,0 +1,783 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash.c + * + * @ingroup LacHash + * + * Hash specific functionality + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_session.h" +#include "lac_sym_hash.h" +#include "lac_log.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_cb.h" +#include "lac_sync.h" + +#define LAC_HASH_ALG_MODE_NOT_SUPPORTED(alg, mode) \ + ((((CPA_CY_SYM_HASH_KASUMI_F9 == (alg)) || \ + (CPA_CY_SYM_HASH_SNOW3G_UIA2 == (alg)) || \ + (CPA_CY_SYM_HASH_AES_XCBC == (alg)) || \ + (CPA_CY_SYM_HASH_AES_CCM == (alg)) || \ + (CPA_CY_SYM_HASH_AES_GCM == (alg)) || \ + (CPA_CY_SYM_HASH_AES_GMAC == (alg)) || \ + (CPA_CY_SYM_HASH_AES_CMAC == (alg)) || \ + (CPA_CY_SYM_HASH_ZUC_EIA3 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_AUTH != (mode))) || \ + (((CPA_CY_SYM_HASH_SHA3_224 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_256 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_384 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_512 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_NESTED == (mode))) || \ + (((CPA_CY_SYM_HASH_SHAKE_128 == (alg)) || \ + (CPA_CY_SYM_HASH_SHAKE_256 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_AUTH == (mode)))) + +/**< Macro to check for valid algorithm-mode combination */ + +/** + * @ingroup LacHash + * This callback function will be invoked whenever a synchronous + * hash precompute operation completes. It will set the wait + * queue flag for the synchronous operation. + * + * @param[in] pCallbackTag Opaque value provided by user. This will + * be a pointer to a wait queue flag. + * + * @retval + * None + * + */ +static void +LacHash_SyncPrecomputeDoneCb(void *pCallbackTag) +{ + LacSync_GenWakeupSyncCaller(pCallbackTag, CPA_STATUS_SUCCESS); +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_StatePrefixAadBufferInit( + sal_service_t *pService, + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_la_bulk_req_ftr_t *pReq, + icp_qat_hw_auth_mode_t qatHashMode, + Cpa8U *pHashStateBuffer, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo) +{ + /* set up the hash state prefix buffer info structure */ + pHashStateBufferInfo->pData = pHashStateBuffer; + + pHashStateBufferInfo->pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), pHashStateBuffer)); + + if (pHashStateBufferInfo->pDataPhys == 0) { + LAC_LOG_ERROR("Unable to get the physical address of " + "the hash state buffer"); + return CPA_STATUS_FAIL; + } + + LacSymQat_HashStatePrefixAadBufferSizeGet(pReq, pHashStateBufferInfo); + + /* Prefix data gets copied to the hash state buffer for nested mode */ + if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + LacSymQat_HashStatePrefixAadBufferPopulate( + pHashStateBufferInfo, + pReq, + pHashSetupData->nestedModeSetupData.pInnerPrefixData, + pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes, + pHashSetupData->nestedModeSetupData.pOuterPrefixData, + pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes); + } + /* For mode2 HMAC the key gets copied into both the inner and + * outer prefix fields */ + else if (IS_HASH_MODE_2_AUTH(qatHashMode, pHashSetupData->hashMode)) { + LacSymQat_HashStatePrefixAadBufferPopulate( + pHashStateBufferInfo, + pReq, + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes, + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + } + /* else do nothing for the other cases */ + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, + CpaCySymSessionSetupData *pSessionSetup, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag, + Cpa8U *pWorkingBuffer, + Cpa8U *pState1, + Cpa8U *pState2) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa8U *pAuthKey = NULL; + Cpa32U authKeyLenInBytes = 0; + CpaCySymHashAlgorithm hashAlgorithm = + pSessionSetup->hashSetupData.hashAlgorithm; + CpaCySymHashAuthModeSetupData *pAuthModeSetupData = + &pSessionSetup->hashSetupData.authModeSetupData; + + /* synchronous operation */ + if (NULL == callbackFn) { + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = LacHash_PrecomputeDataCreate( + instanceHandle, + pSessionSetup, + LacHash_SyncPrecomputeDoneCb, + /* wait queue condition from sync cookie */ + pSyncCallbackData, + pWorkingBuffer, + pState1, + pState2); + } else { + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = LacSync_WaitForCallback( + pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + QAT_UTILS_LOG( + "callback functions for precomputes did not return\n"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; + } + + /* set up convenience pointers */ + pAuthKey = pAuthModeSetupData->authKey; + authKeyLenInBytes = pAuthModeSetupData->authKeyLenInBytes; + + /* Pre-compute data state pointers must already be set up + * by LacSymQat_HashSetupBlockInit() + */ + + /* state1 is not allocated for AES XCBC/CCM/GCM/Kasumi/UIA2 + * so for these algorithms set state2 only */ + if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { + status = LacSymHash_AesECBPreCompute(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { + /* First, copy the original key to pState2 */ + memcpy(pState2, pAuthKey, authKeyLenInBytes); + /* Then precompute */ + status = LacSymHash_AesECBPreCompute(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) { + /* + * The Inner Hash Initial State2 block must contain K + * (the cipher key) and 16 zeroes which will be replaced with + * EK(Ctr0) by the QAT-ME. + */ + + /* write the auth key which for CCM is equivalent to cipher key + */ + memcpy(pState2, + pSessionSetup->cipherSetupData.pCipherKey, + pSessionSetup->cipherSetupData.cipherKeyLenInBytes); + + /* initialize remaining buffer space to all zeroes */ + LAC_OS_BZERO( + pState2 + + pSessionSetup->cipherSetupData.cipherKeyLenInBytes, + ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { + /* + * The Inner Hash Initial State2 block contains the following + * H (the Galois Hash Multiplier) + * len(A) (the length of A), (length before padding) + * 16 zeroes which will be replaced with EK(Ctr0) by the + * QAT. + */ + + /* Memset state2 to 0 */ + LAC_OS_BZERO(pState2, + ICP_QAT_HW_GALOIS_H_SZ + + ICP_QAT_HW_GALOIS_LEN_A_SZ + + ICP_QAT_HW_GALOIS_E_CTR0_SZ); + + /* write H (the Galois Hash Multiplier) where H = E(K, 0...0) + * This will only write bytes 0-15 of pState2 + */ + status = LacSymHash_AesECBPreCompute( + instanceHandle, + hashAlgorithm, + pSessionSetup->cipherSetupData.cipherKeyLenInBytes, + pSessionSetup->cipherSetupData.pCipherKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + + if (CPA_STATUS_SUCCESS == status) { + /* write len(A) (the length of A) into bytes 16-19 of + * pState2 + * in big-endian format. This field is 8 bytes */ + *(Cpa32U *)&pState2[ICP_QAT_HW_GALOIS_H_SZ] = + LAC_MEM_WR_32(pAuthModeSetupData->aadLenInBytes); + } + } else if (CPA_CY_SYM_HASH_KASUMI_F9 == hashAlgorithm) { + Cpa32U wordIndex = 0; + Cpa32U *pTempKey = (Cpa32U *)(pState2 + authKeyLenInBytes); + /* + * The Inner Hash Initial State2 block must contain IK + * (Initialisation Key), followed by IK XOR-ed with KM + * (Key Modifier): IK||(IK^KM). + */ + + /* write the auth key */ + memcpy(pState2, pAuthKey, authKeyLenInBytes); + /* initialise temp key with auth key */ + memcpy(pTempKey, pAuthKey, authKeyLenInBytes); + + /* XOR Key with KASUMI F9 key modifier at 4 bytes level */ + for (wordIndex = 0; + wordIndex < LAC_BYTES_TO_LONGWORDS(authKeyLenInBytes); + wordIndex++) { + pTempKey[wordIndex] ^= + LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES; + } + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) { + /* + * The Inner Hash Initial State2 should be all zeros + */ + LAC_OS_BZERO(pState2, ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm) { + /* + * The Inner Hash Initial State2 should contain the key + * and zero the rest of the state. + */ + LAC_OS_BZERO(pState2, ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ); + memcpy(pState2, pAuthKey, authKeyLenInBytes); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_POLY == hashAlgorithm) { + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else /* For Hmac Precomputes */ + { + status = LacSymHash_HmacPreComputes(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState1, + pState2, + callbackFn, + pCallbackTag); + } + + return status; +} + + +/** @ingroup LacHash */ +CpaStatus +LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData) +{ + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + lac_sym_qat_hash_alg_info_t *pOuterHashAlgInfo = NULL; + CpaCySymCapabilitiesInfo capInfo; + + /*Protect against value of hash outside the bitmap*/ + if ((pHashSetupData->hashAlgorithm) >= + CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + cpaCySymQueryCapabilities(instanceHandle, &capInfo); + if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->hashAlgorithm) && + pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_AES_CBC_MAC) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + switch (pHashSetupData->hashMode) { + case CPA_CY_SYM_HASH_MODE_PLAIN: + case CPA_CY_SYM_HASH_MODE_AUTH: + case CPA_CY_SYM_HASH_MODE_NESTED: + break; + + default: { + LAC_INVALID_PARAM_LOG("hashMode"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (LAC_HASH_ALG_MODE_NOT_SUPPORTED(pHashSetupData->hashAlgorithm, + pHashSetupData->hashMode)) { + LAC_INVALID_PARAM_LOG("hashAlgorithm and hashMode combination"); + return CPA_STATUS_INVALID_PARAM; + } + + LacSymQat_HashAlgLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashAlgInfo); + + /* note: nested hash mode checks digest length against outer algorithm + */ + if ((CPA_CY_SYM_HASH_MODE_PLAIN == pHashSetupData->hashMode) || + (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode)) { + /* Check Digest Length is permitted by the algorithm */ + if ((0 == pHashSetupData->digestResultLenInBytes) || + (pHashSetupData->digestResultLenInBytes > + pHashAlgInfo->digestLength)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode) { + if (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) { + Cpa32U aadDataSize = 0; + + /* RFC 4106: Implementations MUST support a full-length + * 16-octet + * ICV, and MAY support 8 or 12 octet ICVs, and MUST NOT + * support + * other ICV lengths. */ + if ((pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_8) && + (pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_12) && + (pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_16)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure aadLen is within maximum limit imposed by QAT + */ + aadDataSize = + pHashSetupData->authModeSetupData.aadLenInBytes; + + /* round the aad size to the multiple of GCM hash block + * size. */ + aadDataSize = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_GCM_BLOCK_SIZE); + + if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX && + CPA_CY_SYM_HASH_AES_GMAC != + pHashSetupData->hashAlgorithm) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) { + Cpa32U aadDataSize = 0; + + /* RFC 3610: Valid values are 4, 6, 8, 10, 12, 14, and + * 16 octets */ + if ((pHashSetupData->digestResultLenInBytes >= + LAC_HASH_AES_CCM_ICV_SIZE_MIN) && + (pHashSetupData->digestResultLenInBytes <= + LAC_HASH_AES_CCM_ICV_SIZE_MAX)) { + if ((pHashSetupData->digestResultLenInBytes & + 0x01) != 0) { + LAC_INVALID_PARAM_LOG( + "digestResultLenInBytes must be a multiple of 2"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure aadLen is within maximum limit imposed by QAT + */ + /* at the beginning of the buffer there is B0 block */ + aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; + + /* then, if there is some 'a' data, the buffer will + * store encoded + * length of 'a' and 'a' itself */ + if (pHashSetupData->authModeSetupData.aadLenInBytes > + 0) { + /* as the QAT API puts the requirement on the + * pAdditionalAuthData not to be bigger than 240 + * bytes then we + * just need 2 bytes to store encoded length of + * 'a' */ + aadDataSize += sizeof(Cpa16U); + aadDataSize += pHashSetupData->authModeSetupData + .aadLenInBytes; + } + + /* round the aad size to the multiple of CCM block + * size.*/ + aadDataSize = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_CCM_BLOCK_SIZE); + if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) { + /* QAT-FW only supports 128 bit Integrity Key size for + * Kasumi f9 + * Ref: 3GPP TS 35.201 version 7.0.0 Release 7 */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_KASUMI_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) { + + /* QAT-FW only supports 128 bits Integrity Key size for + * Snow3g */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + /* For Snow3g hash aad field contains IV - it needs to + * be 16 + * bytes long + */ + if (pHashSetupData->authModeSetupData.aadLenInBytes != + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_AES_XCBC == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CMAC == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CBC_MAC == + pHashSetupData->hashAlgorithm) { + /* ensure auth key len is valid (128-bit keys supported) + */ + if ((pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_AES_128_KEY_SZ)) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm) { + + /* QAT-FW only supports 128 bits Integrity Key size for + * ZUC */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + /* For ZUC EIA3 hash aad field contains IV - it needs to + * be 16 + * bytes long + */ + if (pHashSetupData->authModeSetupData.aadLenInBytes != + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_POLY == + pHashSetupData->hashAlgorithm) { + if (pHashSetupData->digestResultLenInBytes != + ICP_QAT_HW_SPC_CTR_SZ) { + LAC_INVALID_PARAM_LOG("Digest Length for CCP"); + return CPA_STATUS_INVALID_PARAM; + } + if (pHashSetupData->authModeSetupData.aadLenInBytes > + ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { + LAC_INVALID_PARAM_LOG("AAD Length for CCP"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* The key size must be less than or equal the block + * length */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes > + pHashAlgInfo->blockLength) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* when the key size is greater than 0 check pointer is not null + */ + if (CPA_CY_SYM_HASH_AES_CCM != pHashSetupData->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pHashSetupData->hashAlgorithm && + pHashSetupData->authModeSetupData.authKeyLenInBytes > 0) { + LAC_CHECK_NULL_PARAM( + pHashSetupData->authModeSetupData.authKey); + } + } else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm)) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + LAC_INVALID_PARAM_LOG("outerHashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + if (LAC_HASH_ALG_MODE_NOT_SUPPORTED( + pHashSetupData->nestedModeSetupData.outerHashAlgorithm, + pHashSetupData->hashMode)) { + LAC_INVALID_PARAM_LOG( + "outerHashAlgorithm and hashMode combination"); + return CPA_STATUS_INVALID_PARAM; + } + + LacSymQat_HashAlgLookupGet( + instanceHandle, + pHashSetupData->nestedModeSetupData.outerHashAlgorithm, + &pOuterHashAlgInfo); + + /* Check Digest Length is permitted by the algorithm */ + if ((0 == pHashSetupData->digestResultLenInBytes) || + (pHashSetupData->digestResultLenInBytes > + pOuterHashAlgInfo->digestLength)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > + LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { + LAC_INVALID_PARAM_LOG("innerPrefixLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > + 0) { + LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData + .pInnerPrefixData); + } + + if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > + LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { + LAC_INVALID_PARAM_LOG("outerPrefixLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > + 0) { + LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData + .pOuterPrefixData); + } + } + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + const CpaCySymOpData *pOpData, + Cpa64U srcPktSize, + const CpaBoolean *pVerifyResult) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + + /* digestVerify and digestIsAppended on Hash-Only operation not + * supported */ + if (pSessionDesc->digestIsAppended && pSessionDesc->digestVerify && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LAC_INVALID_PARAM_LOG( + "digestVerify and digestIsAppended set " + "on Hash-Only operation is not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* check the digest result pointer */ + if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && + !pSessionDesc->digestIsAppended && + (NULL == pOpData->pDigestResult)) { + LAC_INVALID_PARAM_LOG("pDigestResult is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + + /* + * Check if the pVerifyResult pointer is not null for hash operation + * when + * the packet is the last one and user has set verifyDigest flag + * Also, this is only needed for symchronous operation, so check if the + * callback pointer is the internal synchronous one rather than a user- + * supplied one. + */ + if ((CPA_TRUE == pSessionDesc->digestVerify) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && + (LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb)) { + if (NULL == pVerifyResult) { + LAC_INVALID_PARAM_LOG( + "Null pointer pVerifyResult for hash op"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* verify start offset + messageLenToDigest is inside the source packet. + * this also verifies that the start offset is inside the packet + * Note: digest is specified as a pointer therefore it can be + * written anywhere so we cannot check for this been inside a buffer + * CCM/GCM specify the auth region using just the cipher params as this + * region is the same for auth and cipher. It is not checked here */ + if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm)) { + /* ensure AAD data pointer is non-NULL if AAD len > 0 */ + if ((pSessionDesc->aadLenInBytes > 0) && + (NULL == pOpData->pAdditionalAuthData)) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + if ((pOpData->hashStartSrcOffsetInBytes + + pOpData->messageLenToHashInBytes) > srcPktSize) { + LAC_INVALID_PARAM_LOG( + "hashStartSrcOffsetInBytes + " + "messageLenToHashInBytes > Src Buffer Packet Length"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* For Snow3g & ZUC hash pAdditionalAuthData field + * of OpData should contain IV */ + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm)) { + if (NULL == pOpData->pAdditionalAuthData) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* partial packets need to be multiples of the algorithm block size in + * hash + * only mode (except for final partial packet) */ + if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LacSymQat_HashAlgLookupGet(instanceHandle, + pSessionDesc->hashAlgorithm, + &pHashAlgInfo); + + /* check if the message is a multiple of the block size. */ + if ((pOpData->messageLenToHashInBytes % + pHashAlgInfo->blockLength) != 0) { + LAC_INVALID_PARAM_LOG( + "messageLenToHashInBytes not block size"); + return CPA_STATUS_INVALID_PARAM; + } + } + + return status; +} + diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c new file mode 100644 index 00000000000..be3a39755b4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_sw_precomputes.c + * + * @ingroup LacHashDefs + * + * Hash Software + ***************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "qat_utils.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_log.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_session.h" +#include "lac_sym_hash_precomputes.h" + +static CpaStatus +LacSymHash_Compute(CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t *pHashAlgInfo, + Cpa8U *in, + Cpa8U *out) +{ + /* + * Note: from SHA hashes appropriate endian swapping is required. + * For sha1, sha224 and sha256 double words based swapping. + * For sha384 and sha512 quad words swapping. + * No endianes swapping for md5 is required. + */ + CpaStatus status = CPA_STATUS_FAIL; + Cpa32U i = 0; + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_MD5: + if (CPA_STATUS_SUCCESS != qatUtilsHashMD5(in, out)) { + LAC_LOG_ERROR("qatUtilsHashMD5 Failed\n"); + return status; + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA1: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA1(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA1 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA224: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA224(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA224 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA256: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA256(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA256 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA384: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA384(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA384 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa64U *)(out))[i] = + LAC_MEM_WR_64(((Cpa64U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA512: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA512(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA512 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa64U *)(out))[i] = + LAC_MEM_WR_64(((Cpa64U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + default: + return CPA_STATUS_INVALID_PARAM; + } + return status; +} + +CpaStatus +LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState1, + Cpa8U *pState2, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag) +{ + Cpa8U *pIpadData = NULL; + Cpa8U *pOpadData = NULL; + CpaStatus status = CPA_STATUS_FAIL; + lac_sym_hash_precomp_op_data_t *pHmacIpadOpData = + (lac_sym_hash_precomp_op_data_t *)pWorkingMemory; + lac_sym_hash_precomp_op_data_t *pHmacOpadOpData = pHmacIpadOpData + 1; + + /* Convenience pointers */ + lac_sym_hash_hmac_precomp_qat_t *pHmacIpadQatData = + &pHmacIpadOpData->u.hmacQatData; + lac_sym_hash_hmac_precomp_qat_t *pHmacOpadQatData = + &pHmacOpadOpData->u.hmacQatData; + + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + Cpa32U i = 0; + Cpa32U padLenBytes = 0; + + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + pHmacIpadOpData->stateSize = pHashAlgInfo->stateSize; + pHmacOpadOpData->stateSize = pHashAlgInfo->stateSize; + + /* Copy HMAC key into buffers */ + if (authKeyLenInBytes > 0) { + memcpy(pHmacIpadQatData->data, pAuthKey, authKeyLenInBytes); + memcpy(pHmacOpadQatData->data, pAuthKey, authKeyLenInBytes); + } + + padLenBytes = pHashAlgInfo->blockLength - authKeyLenInBytes; + + /* Clear the remaining buffer space */ + if (padLenBytes > 0) { + LAC_OS_BZERO(pHmacIpadQatData->data + authKeyLenInBytes, + padLenBytes); + LAC_OS_BZERO(pHmacOpadQatData->data + authKeyLenInBytes, + padLenBytes); + } + + /* XOR Key with IPAD at 4-byte level */ + for (i = 0; i < pHashAlgInfo->blockLength; i++) { + Cpa8U *ipad = pHmacIpadQatData->data + i; + Cpa8U *opad = pHmacOpadQatData->data + i; + + *ipad ^= LAC_HASH_IPAD_BYTE; + *opad ^= LAC_HASH_OPAD_BYTE; + } + pIpadData = (Cpa8U *)pHmacIpadQatData->data; + pOpadData = (Cpa8U *)pHmacOpadQatData->data; + + status = LacSymHash_Compute(hashAlgorithm, + pHashAlgInfo, + (Cpa8U *)pIpadData, + pState1); + + if (CPA_STATUS_SUCCESS == status) { + status = LacSymHash_Compute(hashAlgorithm, + pHashAlgInfo, + (Cpa8U *)pOpadData, + pState2); + } + + if (CPA_STATUS_SUCCESS == status) { + callbackFn(pCallbackTag); + } + return status; +} + +CpaStatus +LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_FAIL; + Cpa32U stateSize = 0, x = 0; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + + if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { + Cpa8U *in = pWorkingMemory; + Cpa8U *out = pState; + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + stateSize = pHashAlgInfo->stateSize; + memcpy(pWorkingMemory, pHashAlgInfo->initState, stateSize); + + for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM; x++) { + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt( + pAuthKey, authKeyLenInBytes, in, out)) { + return status; + } + in += LAC_HASH_XCBC_MAC_BLOCK_SIZE; + out += LAC_HASH_XCBC_MAC_BLOCK_SIZE; + } + status = CPA_STATUS_SUCCESS; + } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { + Cpa8U *out = pState; + Cpa8U k1[LAC_HASH_CMAC_BLOCK_SIZE], + k2[LAC_HASH_CMAC_BLOCK_SIZE]; + Cpa8U *ptr = NULL, i = 0; + stateSize = LAC_HASH_CMAC_BLOCK_SIZE; + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + /* Original state size includes K, K1 and K2 which are of equal + * length. + * For precompute state size is only of the length of K which is + * equal + * to the block size for CPA_CY_SYM_HASH_AES_CMAC. + * The algorithm is described in rfc4493 + * K is just copeid, K1 and K2 need to be single inplace encrypt + * with AES. + * */ + memcpy(out, pHashAlgInfo->initState, stateSize); + memcpy(out, pAuthKey, authKeyLenInBytes); + out += LAC_HASH_CMAC_BLOCK_SIZE; + + for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM - 1; x++) { + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt( + pAuthKey, authKeyLenInBytes, out, out)) { + return status; + } + out += LAC_HASH_CMAC_BLOCK_SIZE; + } + + ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; + + /* Derived keys (k1 and k2), copy them to + * pPrecompOpData->pState, + * but remember that at the beginning is original key (K0) + */ + /* Calculating K1 */ + for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++, ptr++) { + k1[i] = (*ptr) << 1; + if (i != 0) { + k1[i - 1] |= + (*ptr) >> (LAC_NUM_BITS_IN_BYTE - 1); + } + if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { + /* If msb of pState + LAC_HASH_CMAC_BLOCK_SIZE + is set xor + with RB. Because only the final byte of RB is + non-zero + this is all we need to xor */ + if ((*(pState + LAC_HASH_CMAC_BLOCK_SIZE)) & + LAC_SYM_HASH_MSBIT_MASK) { + k1[i] ^= LAC_SYM_AES_CMAC_RB_128; + } + } + } + + /* Calculating K2 */ + for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++) { + k2[i] = (k1[i]) << 1; + if (i != 0) { + k2[i - 1] |= + (k1[i]) >> (LAC_NUM_BITS_IN_BYTE - 1); + } + if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { + /* If msb of k1 is set xor last byte with RB */ + if (k1[0] & LAC_SYM_HASH_MSBIT_MASK) { + k2[i] ^= LAC_SYM_AES_CMAC_RB_128; + } + } + } + /* Now, when we have K1 & K2 lets copy them to the state2 */ + ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; + memcpy(ptr, k1, LAC_HASH_CMAC_BLOCK_SIZE); + ptr += LAC_HASH_CMAC_BLOCK_SIZE; + memcpy(ptr, k2, LAC_HASH_CMAC_BLOCK_SIZE); + status = CPA_STATUS_SUCCESS; + } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { + Cpa8U *in = pWorkingMemory; + Cpa8U *out = pState; + LAC_OS_BZERO(pWorkingMemory, ICP_QAT_HW_GALOIS_H_SZ); + + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt(pAuthKey, authKeyLenInBytes, in, out)) { + return status; + } + status = CPA_STATUS_SUCCESS; + } else { + return CPA_STATUS_INVALID_PARAM; + } + callbackFn(pCallbackTag); + return status; +} + +CpaStatus +LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + return status; +} + +void +LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle) +{ + return; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c new file mode 100644 index 00000000000..4a937c7d093 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_partial.c common partial packet functions + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" + +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +#include "lac_log.h" +#include "lac_sym.h" +#include "cpa_cy_sym.h" +#include "lac_common.h" + +#include "lac_sym_partial.h" + +CpaStatus +LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, + CpaCySymPacketType partialState) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* ASSUMPTION - partial requests on a given session must be issued + * sequentially to guarantee ordering + * (i.e. issuing partials on concurrent threads for a particular session + * just wouldn't work) + */ + + /* state is no partial - only a partial is allowed */ + if (((CPA_CY_SYM_PACKET_TYPE_FULL == partialState) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType)) || + + /* state is partial - only a partial or final partial is allowed */ + ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == partialState) && + ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType) || + (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType)))) { + status = CPA_STATUS_SUCCESS; + } else /* invalid sequence */ + { + LAC_INVALID_PARAM_LOG("invalid partial packet sequence"); + status = CPA_STATUS_INVALID_PARAM; + } + + return status; +} + +void +LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, + CpaCySymPacketType *pPartialState) +{ + /* if previous packet was either a full or ended a partial stream, + * update + * state to partial to indicate a new partial stream was created */ + if (CPA_CY_SYM_PACKET_TYPE_FULL == *pPartialState) { + *pPartialState = CPA_CY_SYM_PACKET_TYPE_PARTIAL; + } else { + /* if packet type is final - reset the partial state */ + if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType) { + *pPartialState = CPA_CY_SYM_PACKET_TYPE_FULL; + } + } +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c new file mode 100644 index 00000000000..977fb0b84d0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_queue.c Functions for sending/queuing symmetric requests + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_debug.h" +#include "icp_adf_transport.h" +#include "lac_sym_queue.h" +#include "lac_sym_qat.h" +#include "lac_session.h" +#include "lac_sym.h" +#include "lac_log.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types_crypto.h" + +#define GetSingleBitFromByte(byte, bit) ((byte) & (1 << (bit))) + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +CpaStatus +LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, + lac_sym_bulk_cookie_t *pRequest, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean enqueued = CPA_FALSE; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + /* Enqueue the message instead of sending directly if: + * (i) a blocking operation is in progress + * (ii) there are previous requests already in the queue + */ + if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || + (NULL != pSessionDesc->pRequestQueueTail)) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to lock request queue"); + return CPA_STATUS_RESOURCE; + } + + /* Re-check blockingOpsInProgress and pRequestQueueTail in case + * either + * changed before the lock was acquired. The lock is shared + * with + * the callback context which drains this queue + */ + if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || + (NULL != pSessionDesc->pRequestQueueTail)) { + /* Enqueue the message and exit */ + /* The FIFO queue is made up of a head and tail pointer. + * The head pointer points to the first/oldest, entry + * in the queue, and the tail pointer points to the + * last/newest + * entry in the queue + */ + + if (NULL != pSessionDesc->pRequestQueueTail) { + /* Queue is non-empty. Add this request to the + * list */ + pSessionDesc->pRequestQueueTail->pNext = + pRequest; + } else { + /* Queue is empty. Initialise the head pointer + * as well */ + pSessionDesc->pRequestQueueHead = pRequest; + } + + pSessionDesc->pRequestQueueTail = pRequest; + + /* request is queued, don't send to QAT here */ + enqueued = CPA_TRUE; + } + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to unlock request queue"); + } + } + + if (CPA_FALSE == enqueued) { + /* If we send a partial packet request, set the + * blockingOpsInProgress + * flag for the session to indicate that subsequent requests + * must be + * queued up until this request completes + * + * @assumption + * If we have got here it means that there were no previous + * blocking + * operations in progress and, since multiple partial packet + * requests + * on a given session cannot be issued concurrently, there + * should be + * no need for a critical section around the following code + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != + pRequest->pOpData->packetType) { + /* Select blocking operations which this reqest will + * complete */ + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + } + + /* At this point, we're clear to send the request. For cipher + * requests, + * we need to check if the session IV needs to be updated. This + * can + * only be done when no other partials are in flight for this + * session, + * to ensure the cipherPartialOpState buffer in the session + * descriptor + * is not currently in use + */ + if (CPA_TRUE == pRequest->updateSessionIvOnSend) { + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->cipherARC4InitialState, + LAC_CIPHER_ARC4_STATE_LEN_BYTES); + } else { + memcpy(pSessionDesc->cipherPartialOpState, + pRequest->pOpData->pIv, + pRequest->pOpData->ivLenInBytes); + } + } + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(pRequest->qatMsg), + LAC_QAT_SYM_REQ_SZ_LW); + + /* if fail to send request, we need to change + * nonBlockingOpsInProgress + * to CPA_TRUE + */ + if ((CPA_STATUS_SUCCESS != status) && + (CPA_CY_SYM_PACKET_TYPE_FULL != + pRequest->pOpData->packetType)) { + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + } + } + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c new file mode 100644 index 00000000000..ca1bbb99d3a --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_stats.c Implementation of symmetric stats + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_mem_pools.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_qat_fw_la.h" +#include "lac_sym_qat.h" +#include "lac_sym_stats.h" +#include "lac_sal_types_crypto.h" +#include "sal_statistics.h" + +/* Number of Symmetric Crypto statistics */ +#define LAC_SYM_NUM_STATS (sizeof(CpaCySymStats64) / sizeof(Cpa64U)) + +CpaStatus +LacSym_StatsInit(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + pService->pLacSymStatsArr = + LAC_OS_MALLOC(LAC_SYM_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (NULL != pService->pLacSymStatsArr) { + LAC_OS_BZERO((void *)LAC_CONST_VOLATILE_PTR_CAST( + pService->pLacSymStatsArr), + LAC_SYM_NUM_STATS * sizeof(QatUtilsAtomic)); + } else { + status = CPA_STATUS_RESOURCE; + } + return status; +} + +void +LacSym_StatsFree(CpaInstanceHandle instanceHandle) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + if (NULL != pService->pLacSymStatsArr) { + LAC_OS_FREE(pService->pLacSymStatsArr); + } +} + +void +LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + if (CPA_TRUE == + pService->generic_service_info.stats->bSymStatsEnabled) { + qatUtilsAtomicInc( + &pService->pLacSymStatsArr[offset / sizeof(Cpa64U)]); + } +} + +void +LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, + struct _CpaCySymStats *const pSymStats) +{ + int i = 0; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + for (i = 0; i < LAC_SYM_NUM_STATS; i++) { + ((Cpa32U *)pSymStats)[i] = + (Cpa32U)qatUtilsAtomicGet(&pService->pLacSymStatsArr[i]); + } +} + +void +LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, + CpaCySymStats64 *const pSymStats) +{ + int i = 0; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + for (i = 0; i < LAC_SYM_NUM_STATS; i++) { + ((Cpa64U *)pSymStats)[i] = + qatUtilsAtomicGet(&pService->pLacSymStatsArr[i]); + } +} + +void +LacSym_StatsShow(CpaInstanceHandle instanceHandle) +{ + CpaCySymStats64 symStats = { 0 }; + + LacSym_Stats64CopyGet(instanceHandle, &symStats); + + QAT_UTILS_LOG(SEPARATOR BORDER + " Symmetric Stats " BORDER + "\n" SEPARATOR); + + /* Session Info */ + QAT_UTILS_LOG(BORDER " Sessions Initialized: %16llu " BORDER + "\n" BORDER + " Sessions Removed: %16llu " BORDER + "\n" BORDER + " Session Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)symStats.numSessionsInitialized, + (unsigned long long)symStats.numSessionsRemoved, + (unsigned long long)symStats.numSessionErrors); + + /* Session info */ + QAT_UTILS_LOG( + BORDER " Symmetric Requests: %16llu " BORDER "\n" BORDER + " Symmetric Request Errors: %16llu " BORDER "\n" BORDER + " Symmetric Completed: %16llu " BORDER "\n" BORDER + " Symmetric Completed Errors: %16llu " BORDER "\n" BORDER + " Symmetric Verify Failures: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)symStats.numSymOpRequests, + (unsigned long long)symStats.numSymOpRequestErrors, + (unsigned long long)symStats.numSymOpCompleted, + (unsigned long long)symStats.numSymOpCompletedErrors, + (unsigned long long)symStats.numSymOpVerifyFailures); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c new file mode 100644 index 00000000000..c55da0a0d53 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat.c Interfaces for populating the symmetric qat structures + * + * @ingroup LacSymQat + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_sym_qat.h" +#include "lac_sal_types_crypto.h" +#include "sal_string_parse.h" +#include "lac_sym_key.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat_hash.h" + +#define EMBEDDED_CIPHER_KEY_MAX_SIZE 16 +static void +LacSymQat_SymLogSliceHangError(icp_qat_fw_la_cmd_id_t symCmdId) +{ + Cpa8U cmdId = symCmdId; + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_CIPHER: + case ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP: + LAC_LOG_ERROR("slice hang detected on CPM cipher slice."); + break; + + case ICP_QAT_FW_LA_CMD_AUTH: + case ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP: + LAC_LOG_ERROR("slice hang detected on CPM auth slice."); + break; + + case ICP_QAT_FW_LA_CMD_CIPHER_HASH: + case ICP_QAT_FW_LA_CMD_HASH_CIPHER: + case ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_MGF1: + default: + LAC_LOG_ERROR( + "slice hang detected on CPM cipher or auth slice."); + } + return; +} + +/* sym crypto response handlers */ +static sal_qat_resp_handler_func_t + respHandlerSymTbl[ICP_QAT_FW_LA_CMD_DELIMITER]; + +void +LacSymQat_SymRespHandler(void *pRespMsg) +{ + Cpa8U lacCmdId = 0; + void *pOpaqueData = NULL; + icp_qat_fw_la_resp_t *pRespMsgFn = NULL; + Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; + Cpa8U comnErr = ERR_CODE_NO_ERROR; + + pRespMsgFn = (icp_qat_fw_la_resp_t *)pRespMsg; + LAC_MEM_SHARED_READ_TO_PTR(pRespMsgFn->opaque_data, pOpaqueData); + + lacCmdId = pRespMsgFn->comn_resp.cmd_id; + opStatus = pRespMsgFn->comn_resp.comn_status; + comnErr = pRespMsgFn->comn_resp.comn_error.s.comn_err_code; + + /* log the slice hang and endpoint push/pull error inside the response + */ + if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) { + LacSymQat_SymLogSliceHangError(lacCmdId); + } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) { + LAC_LOG_ERROR("The PCIe End Point Push/Pull or" + " TI/RI Parity error detected."); + } + + /* call the response message handler registered for the command ID */ + respHandlerSymTbl[lacCmdId]((icp_qat_fw_la_cmd_id_t)lacCmdId, + pOpaqueData, + (icp_qat_fw_comn_flags)opStatus); +} + +CpaStatus +LacSymQat_Init(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Initialise the Hash lookup table */ + status = LacSymQat_HashLookupInit(instanceHandle); + + return status; +} + +void +LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, + sal_qat_resp_handler_func_t pCbHandler) +{ + if (lacCmdId >= ICP_QAT_FW_LA_CMD_DELIMITER) { + QAT_UTILS_LOG("Invalid Command ID\n"); + return; + } + + /* set the response handler for the command ID */ + respHandlerSymTbl[lacCmdId] = pCbHandler; +} + +void +LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, + icp_qat_fw_la_cmd_id_t laCmdId, + CpaCySymCipherAlgorithm cipherAlgorithm, + Cpa16U *pLaCommandFlags, + Cpa32U ivLenInBytes) +{ + /* For Chacha ciphers set command flag as partial none to proceed + * with stateless processing */ + if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm) || + LAC_CIPHER_IS_SM4(cipherAlgorithm)) { + ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_PARTIAL_NONE); + return; + } + ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, qatPacketType); + + /* For ECB-mode ciphers, IV is NULL so update-state flag + * must be disabled always. + * For all other ciphers and auth + * update state is disabled for full packets and final partials */ + if (((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && + LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm)) || + (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) || + (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType)) { + ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_NO_UPDATE_STATE); + } + /* For first or middle partials set the update state command flag */ + else { + ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_UPDATE_STATE); + + if (laCmdId == ICP_QAT_FW_LA_CMD_AUTH) { + /* For hash only partial - verify and return auth result + * are + * disabled */ + ICP_QAT_FW_LA_RET_AUTH_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); + + ICP_QAT_FW_LA_CMP_AUTH_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + + if ((LAC_CIPHER_IS_GCM(cipherAlgorithm)) && + (LAC_CIPHER_IV_SIZE_GCM_12 == ivLenInBytes)) + + { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); + } +} + +void +LacSymQat_packetTypeGet(CpaCySymPacketType packetType, + CpaCySymPacketType packetState, + Cpa32U *pQatPacketType) +{ + /* partial */ + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType) { + /* if the previous state was full, then this is the first packet + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL == packetState) { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_START; + } else { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_MID; + } + } + /* final partial */ + else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType) { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_END; + } + /* full packet - CPA_CY_SYM_PACKET_TYPE_FULL */ + else { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_NONE; + } +} + +void +LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, + CpaCySymOp symOp) +{ + + ICP_QAT_FW_LA_PARTIAL_SET(*laCmdFlags, ICP_QAT_FW_LA_PARTIAL_NONE); + + ICP_QAT_FW_LA_UPDATE_STATE_SET(*laCmdFlags, + ICP_QAT_FW_LA_NO_UPDATE_STATE); + + if (symOp != CPA_CY_SYM_OP_CIPHER) { + ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, + ICP_QAT_FW_LA_RET_AUTH_RES); + } else { + ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + } + + ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + *laCmdFlags, ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c new file mode 100644 index 00000000000..b958d372370 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c @@ -0,0 +1,889 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_cipher.c QAT-related support functions for Cipher + * + * @ingroup LacSymQat_Cipher + * + * @description Functions to support the QAT related operations for Cipher + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sym_qat.h" +#include "lac_sym_qat_cipher.h" +#include "lac_mem.h" +#include "lac_common.h" +#include "cpa_cy_sym.h" +#include "lac_sym_qat.h" +#include "lac_sym_cipher_defs.h" +#include "icp_qat_hw.h" +#include "icp_qat_fw_la.h" + +/***************************************************************************** + * Internal data + *****************************************************************************/ + +typedef enum _icp_qat_hw_key_depend { + IS_KEY_DEP_NO = 0, + IS_KEY_DEP_YES, +} icp_qat_hw_key_depend; + +/* LAC_CIPHER_IS_XTS_MODE */ +static const uint8_t key_size_xts[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_XTS_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_XTS_KEY_SZ +}; +/* LAC_CIPHER_IS_AES */ +static const uint8_t key_size_aes[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES192, // ICP_QAT_HW_AES_192_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_KEY_SZ +}; +/* LAC_CIPHER_IS_AES_F8 */ +static const uint8_t key_size_f8[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_F8_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES192, // ICP_QAT_HW_AES_192_F8_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_F8_KEY_SZ +}; +/* LAC_CIPHER_IS_SM4 */ +static const uint8_t key_size_sm4[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_SM4 // ICP_QAT_HW_SM4_KEY_SZ +}; + +typedef struct _icp_qat_hw_cipher_info { + icp_qat_hw_cipher_algo_t algorithm; + icp_qat_hw_cipher_mode_t mode; + icp_qat_hw_cipher_convert_t key_convert[2]; + icp_qat_hw_cipher_dir_t dir[2]; + icp_qat_hw_key_depend isKeyLenDepend; + const uint8_t *pAlgByKeySize; +} icp_qat_hw_cipher_info; + +static const icp_qat_hw_cipher_info icp_qat_alg_info[] = + { + /* CPA_CY_SYM_CIPHER_NULL */ + { + ICP_QAT_HW_CIPHER_ALGO_NULL, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_ARC4 */ + { + ICP_QAT_HW_CIPHER_ALGO_ARC4, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_AES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_ECB_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CBC_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CCM */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_GCM */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_DES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_DES, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_DES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_DES, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_KASUMI_F8 */ + { + ICP_QAT_HW_CIPHER_ALGO_KASUMI, + ICP_QAT_HW_CIPHER_F8_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_SNOW3G_UEA2 */ + { + /* The KEY_CONVERT bit has to be set for Snow_3G operation */ + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_AES_F8 */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_F8_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_f8, + }, + /* CPA_CY_SYM_CIPHER_AES_XTS */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_XTS_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_xts, + }, + /* CPA_CY_SYM_CIPHER_ZUC_EEA3 */ + { + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_CHACHA */ + { + ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_SM4_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + /* CPA_CY_SYM_CIPHER_SM4_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + /* CPA_CY_SYM_CIPHER_SM4_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + }; + +/***************************************************************************** + * Internal functions + *****************************************************************************/ + +void +LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa32U cipherAlgorithm, + Cpa32U targetKeyLenInBytes, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherCfgOffsetInQuadWord) +{ + icp_qat_fw_cipher_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + + /* state_padding_sz is nonzero for f8 mode only */ + cd_ctrl->cipher_padding_sz = 0; + + /* Base Key is not passed down to QAT in the case of ARC4 or NULL */ + if (LAC_CIPHER_IS_ARC4(cipherAlgorithm) || + LAC_CIPHER_IS_NULL(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = 0; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_KASUMI_F8_KEY_SZ); + cd_ctrl->cipher_padding_sz = + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + /* For Snow3G UEA2 content descriptor key size is + key size plus iv size */ + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ + + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + } else if (LAC_CIPHER_IS_AES_F8(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); + cd_ctrl->cipher_padding_sz = + 2 * ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + /* For ZUC EEA3 content descriptor key size is + key size plus iv size */ + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ + + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + } else { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); + } + + cd_ctrl->cipher_state_sz = LAC_BYTES_TO_QUADWORDS( + LacSymQat_CipherIvSizeBytesGet(cipherAlgorithm)); + + cd_ctrl->cipher_cfg_offset = cipherCfgOffsetInQuadWord; + + ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_CIPHER); +} + +void +LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, + icp_qat_hw_cipher_algo_t *pAlgorithm, + icp_qat_hw_cipher_mode_t *pMode, + icp_qat_hw_cipher_dir_t *pDir, + icp_qat_hw_cipher_convert_t *pKey_convert) +{ + + CpaCySymCipherAlgorithm cipherAlgorithm = 0; + icp_qat_hw_cipher_dir_t cipherDirection = 0; + + /* Set defaults */ + *pKey_convert = ICP_QAT_HW_CIPHER_NO_CONVERT; + *pAlgorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; + *pMode = ICP_QAT_HW_CIPHER_ECB_MODE; + *pDir = ICP_QAT_HW_CIPHER_ENCRYPT; + + /* decrease since it's numbered from 1 instead of 0 */ + cipherAlgorithm = pSession->cipherAlgorithm - 1; + cipherDirection = + pSession->cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT ? + ICP_QAT_HW_CIPHER_ENCRYPT : + ICP_QAT_HW_CIPHER_DECRYPT; + + *pAlgorithm = icp_qat_alg_info[cipherAlgorithm].algorithm; + *pMode = icp_qat_alg_info[cipherAlgorithm].mode; + *pDir = icp_qat_alg_info[cipherAlgorithm].dir[cipherDirection]; + *pKey_convert = + icp_qat_alg_info[cipherAlgorithm].key_convert[cipherDirection]; + + if (IS_KEY_DEP_NO != icp_qat_alg_info[cipherAlgorithm].isKeyLenDepend) { + *pAlgorithm = icp_qat_alg_info[cipherAlgorithm] + .pAlgByKeySize[pSession->cipherKeyLenInBytes]; + } + /* Set the mode */ + if (LAC_CIPHER_IS_CTR_MODE(pSession->cipherAlgorithm)) { + *pMode = ICP_QAT_HW_CIPHER_CTR_MODE; + *pKey_convert = ICP_QAT_HW_CIPHER_NO_CONVERT; + /* CCP and AES_GCM single pass, despite being limited to + * CTR/AEAD mode, + * support both Encrypt/Decrypt modes - this is because of the + * differences in the hash computation/verification paths in + * encrypt/decrypt modes respectively. + * By default CCP is set as CTR Mode.Set AEAD Mode for AES_GCM. + */ + if (pSession->isSinglePass) { + if (LAC_CIPHER_IS_GCM(pSession->cipherAlgorithm)) + *pMode = ICP_QAT_HW_CIPHER_AEAD_MODE; + if (cipherDirection == ICP_QAT_HW_CIPHER_DECRYPT) + *pDir = ICP_QAT_HW_CIPHER_DECRYPT; + } + } +} + +void +LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes) +{ + icp_qat_hw_cipher_algo_t algorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; + icp_qat_hw_cipher_mode_t mode = ICP_QAT_HW_CIPHER_ECB_MODE; + icp_qat_hw_cipher_dir_t dir = ICP_QAT_HW_CIPHER_ENCRYPT; + icp_qat_hw_cipher_convert_t key_convert; + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)pCipherHwBlock; + Cpa32U aed_hash_cmp_length = 0; + + *pSizeInBytes = 0; + + LacSymQat_CipherGetCfgData( + pSession, &algorithm, &mode, &dir, &key_convert); + + /* Build the cipher config into the hardware setup block */ + if (pSession->isSinglePass) { + aed_hash_cmp_length = pSession->hashResultSize; + pCipherConfig->reserved = ICP_QAT_HW_CIPHER_CONFIG_BUILD_UPPER( + pSession->aadLenInBytes); + } else { + pCipherConfig->reserved = 0; + } + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + mode, algorithm, key_convert, dir, aed_hash_cmp_length); + + *pSizeInBytes = sizeof(icp_qat_hw_cipher_config_t); +} + +void +LacSymQat_CipherHwBlockPopulateKeySetup( + const CpaCySymCipherSetupData *pCipherSetupData, + Cpa32U targetKeyLenInBytes, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes) +{ + Cpa8U *pCipherKey = (Cpa8U *)pCipherHwBlock; + Cpa32U actualKeyLenInBytes = pCipherSetupData->cipherKeyLenInBytes; + + *pSizeInBytes = 0; + + /* Key is copied into content descriptor for all cases except for + * Arc4 and Null cipher */ + if (!(LAC_CIPHER_IS_ARC4(pCipherSetupData->cipherAlgorithm) || + LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm))) { + /* Set the Cipher key field in the cipher block */ + memcpy(pCipherKey, + pCipherSetupData->pCipherKey, + actualKeyLenInBytes); + /* Pad the key with 0's if required */ + if (0 < (targetKeyLenInBytes - actualKeyLenInBytes)) { + LAC_OS_BZERO(pCipherKey + actualKeyLenInBytes, + targetKeyLenInBytes - actualKeyLenInBytes); + } + *pSizeInBytes += targetKeyLenInBytes; + + /* For Kasumi in F8 mode Cipher Key is concatenated with + * Cipher Key XOR-ed with Key Modifier (CK||CK^KM) */ + if (LAC_CIPHER_IS_KASUMI(pCipherSetupData->cipherAlgorithm)) { + Cpa32U wordIndex = 0; + Cpa32U *pu32CipherKey = + (Cpa32U *)pCipherSetupData->pCipherKey; + Cpa32U *pTempKey = + (Cpa32U *)(pCipherKey + targetKeyLenInBytes); + + /* XOR Key with KASUMI F8 key modifier at 4 bytes level + */ + for (wordIndex = 0; wordIndex < + LAC_BYTES_TO_LONGWORDS(targetKeyLenInBytes); + wordIndex++) { + pTempKey[wordIndex] = pu32CipherKey[wordIndex] ^ + LAC_CIPHER_KASUMI_F8_KEY_MODIFIER_4_BYTES; + } + + *pSizeInBytes += targetKeyLenInBytes; + + /* also add padding for F8 */ + *pSizeInBytes += LAC_QUADWORDS_TO_BYTES( + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR); + LAC_OS_BZERO((Cpa8U *)pTempKey + targetKeyLenInBytes, + LAC_QUADWORDS_TO_BYTES( + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR)); + } + /* For AES in F8 mode Cipher Key is concatenated with + * Cipher Key XOR-ed with Key Mask (CK||CK^KM) */ + else if (LAC_CIPHER_IS_AES_F8( + pCipherSetupData->cipherAlgorithm)) { + Cpa32U index = 0; + Cpa8U *pTempKey = + pCipherKey + (targetKeyLenInBytes / 2); + *pSizeInBytes += targetKeyLenInBytes; + /* XOR Key with key Mask */ + for (index = 0; index < targetKeyLenInBytes; index++) { + pTempKey[index] = + pCipherKey[index] ^ pTempKey[index]; + } + pTempKey = (pCipherKey + targetKeyLenInBytes); + /* also add padding for AES F8 */ + *pSizeInBytes += 2 * targetKeyLenInBytes; + LAC_OS_BZERO(pTempKey, 2 * targetKeyLenInBytes); + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pCipherSetupData->cipherAlgorithm)) { + /* For Snow3G zero area after the key for FW */ + LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + + *pSizeInBytes += ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pCipherSetupData->cipherAlgorithm)) { + /* For ZUC zero area after the key for FW */ + LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + + *pSizeInBytes += ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; + } + } +} + +/***************************************************************************** + * External functions + *****************************************************************************/ + +Cpa8U +LacSymQat_CipherBlockSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) +{ + if (LAC_CIPHER_IS_ARC4(cipherAlgorithm)) { + return LAC_CIPHER_ARC4_BLOCK_LEN_BYTES; + } else if (LAC_CIPHER_IS_AES(cipherAlgorithm) || + LAC_CIPHER_IS_AES_F8(cipherAlgorithm)) { + return ICP_QAT_HW_AES_BLK_SZ; + } else if (LAC_CIPHER_IS_DES(cipherAlgorithm)) { + return ICP_QAT_HW_DES_BLK_SZ; + } else if (LAC_CIPHER_IS_TRIPLE_DES(cipherAlgorithm)) { + return ICP_QAT_HW_3DES_BLK_SZ; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + return ICP_QAT_HW_KASUMI_BLK_SZ; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + return ICP_QAT_HW_SNOW_3G_BLK_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + return ICP_QAT_HW_ZUC_3G_BLK_SZ; + } else if (LAC_CIPHER_IS_NULL(cipherAlgorithm)) { + return LAC_CIPHER_NULL_BLOCK_LEN_BYTES; + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + return ICP_QAT_HW_CHACHAPOLY_BLK_SZ; + } else if (LAC_CIPHER_IS_SM4(cipherAlgorithm)) { + return ICP_QAT_HW_SM4_BLK_SZ; + } else { + QAT_UTILS_LOG("Algorithm not supported in Cipher\n"); + return 0; + } +} + +Cpa32U +LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) +{ + if (CPA_CY_SYM_CIPHER_ARC4 == cipherAlgorithm) { + return LAC_CIPHER_ARC4_STATE_LEN_BYTES; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + return ICP_QAT_HW_KASUMI_BLK_SZ; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + return ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + return ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + return ICP_QAT_HW_CHACHAPOLY_IV_SZ; + } else if (LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm)) { + return 0; + } else { + return (Cpa32U)LacSymQat_CipherBlockSizeBytesGet( + cipherAlgorithm); + } +} + +inline CpaStatus +LacSymQat_CipherRequestParamsPopulate(icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U cipherOffsetInBytes, + Cpa32U cipherLenInBytes, + Cpa64U ivBufferPhysAddr, + Cpa8U *pIvBufferVirt) +{ + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams; + icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherCdCtrlHdr; + icp_qat_fw_serv_specif_flags *pCipherSpecificFlags; + + pCipherReqParams = (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&(pReq->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + pCipherCdCtrlHdr = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pReq->cd_ctrl); + pCipherSpecificFlags = &(pReq->comn_hdr.serv_specif_flags); + + pCipherReqParams->cipher_offset = cipherOffsetInBytes; + pCipherReqParams->cipher_length = cipherLenInBytes; + + /* Don't copy the buffer into the Msg if + * it's too big for the cipher_IV_array + * OR if the FW needs to update it + * OR if there's no buffer supplied + * OR if last partial + */ + if ((pCipherCdCtrlHdr->cipher_state_sz > + LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW) || + (ICP_QAT_FW_LA_UPDATE_STATE_GET(*pCipherSpecificFlags) == + ICP_QAT_FW_LA_UPDATE_STATE) || + (pIvBufferVirt == NULL) || + (ICP_QAT_FW_LA_PARTIAL_GET(*pCipherSpecificFlags) == + ICP_QAT_FW_LA_PARTIAL_END)) { + /* Populate the field with a ptr to the flat buffer */ + pCipherReqParams->u.s.cipher_IV_ptr = ivBufferPhysAddr; + pCipherReqParams->u.s.resrvd1 = 0; + /* Set the flag indicating the field format */ + ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET( + *pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_64BIT_PTR); + } else { + /* Populate the field with the contents of the buffer, + * zero field first as data may be smaller than the field */ + memset(pCipherReqParams->u.cipher_IV_array, + 0, + LAC_LONGWORDS_TO_BYTES(ICP_QAT_FW_NUM_LONGWORDS_4)); + + /* We force a specific compiler optimisation here. The length + * to + * be copied turns out to be always 16, and by coding a memcpy + * with + * a literal value the compiler will compile inline code (in + * fact, + * only two vector instructions) to effect the copy. This gives + * us + * a huge performance increase. + */ + unsigned long cplen = + LAC_QUADWORDS_TO_BYTES(pCipherCdCtrlHdr->cipher_state_sz); + + if (cplen == 16) + memcpy(pCipherReqParams->u.cipher_IV_array, + pIvBufferVirt, + 16); + else + memcpy(pCipherReqParams->u.cipher_IV_array, + pIvBufferVirt, + cplen); + /* Set the flag indicating the field format */ + ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET( + *pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_16BYTE_DATA); + } + + return CPA_STATUS_SUCCESS; +} + +void +LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, + Cpa32U keyLenInBytes, + Cpa8U *pArc4CipherState) +{ + Cpa32U i = 0; + Cpa32U j = 0; + Cpa32U k = 0; + + for (i = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i) { + pArc4CipherState[i] = (Cpa8U)i; + } + + for (i = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i) { + Cpa8U swap = 0; + + if (k >= keyLenInBytes) + k -= keyLenInBytes; + + j = (j + pArc4CipherState[i] + pKey[k]); + if (j >= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES) + j %= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; + ++k; + + /* Swap state[i] & state[j] */ + swap = pArc4CipherState[i]; + pArc4CipherState[i] = pArc4CipherState[j]; + pArc4CipherState[j] = swap; + } + + /* Initialise i & j values for QAT */ + pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES] = 0; + pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES + 1] = 0; +} + +/* Update the cipher_key_sz in the Request cache prepared and stored + * in the session */ +void +LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, + Cpa32U newKeySizeInBytes) +{ + icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherControlBlock = NULL; + + pCipherControlBlock = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&( + pSessionDesc->reqCacheFtr.cd_ctrl); + + pCipherControlBlock->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(newKeySizeInBytes); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c new file mode 100644 index 00000000000..a39734ad16d --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_hash.c + * + * @ingroup LacSymQatHash + * + * Implementation for populating QAT data structures for hash operation + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_common.h" +#include "lac_sym_qat.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_qat_hash_defs_lookup.h" + +/** + * This structure contains pointers into the hash setup block of the + * security descriptor. As the hash setup block contains fields that + * are of variable length, pointers must be calculated to these fields + * and the hash setup block is populated using these pointers. */ +typedef struct lac_hash_blk_ptrs_s { + icp_qat_hw_auth_setup_t *pInHashSetup; + /**< inner hash setup */ + Cpa8U *pInHashInitState1; + /**< inner initial state 1 */ + Cpa8U *pInHashInitState2; + /**< inner initial state 2 */ + icp_qat_hw_auth_setup_t *pOutHashSetup; + /**< outer hash setup */ + Cpa8U *pOutHashInitState1; + /**< outer hash initial state */ +} lac_hash_blk_ptrs_t; + +typedef struct lac_hash_blk_ptrs_optimised_s { + Cpa8U *pInHashInitState1; + /**< inner initial state 1 */ + Cpa8U *pInHashInitState2; + /**< inner initial state 2 */ + +} lac_hash_blk_ptrs_optimised_t; + +/** + * This function calculates the pointers into the hash setup block + * based on the control block + * + * @param[in] pHashControlBlock Pointer to hash control block + * @param[in] pHwBlockBase pointer to base of hardware block + * @param[out] pHashBlkPtrs structure containing pointers to + * various fields in the hash setup block + * + * @return void + */ +static void +LacSymQat_HashHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + lac_hash_blk_ptrs_t *pHashBlkPtrs); + +static void +LacSymQat_HashSetupBlockOptimisedFormatInit( + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs); + +/** + * This function populates the hash setup block + * + * @param[in] pHashSetupData Pointer to the hash context + * @param[in] pHashControlBlock Pointer to hash control block + * @param[in] pHwBlockBase pointer to base of hardware block + * @param[in] qatHashMode QAT hash mode + * @param[in] pPrecompute For auth mode, this is the pointer + * to the precompute data. Otherwise this + * should be set to NULL + * @param[in] pHashDefs Pointer to Hash definitions + * @param[in] pOuterHashDefs Pointer to Outer Hash definitions. + * Required for nested hash mode only + * + * @return void + */ +static void +LacSymQat_HashSetupBlockInit(const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs); + +/** @ingroup LacSymQatHash */ +void +LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, + icp_qat_hw_auth_mode_t qatHashMode, + CpaCySymHashMode apiHashMode, + CpaCySymHashAlgorithm apiHashAlgorithm, + icp_qat_hw_auth_algo_t *pQatAlgorithm, + CpaBoolean *pQatNested) +{ + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + + LacSymQat_HashDefsLookupGet(pInstance, apiHashAlgorithm, &pHashDefs); + *pQatAlgorithm = pHashDefs->qatInfo->algoEnc; + + if (IS_HASH_MODE_2(qatHashMode)) { + /* set bit for nested hashing */ + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; + } + /* Nested hash in mode 0. */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == apiHashMode) { + /* set bit for nested hashing */ + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; + } + /* mode0 - plain or mode1 - auth */ + else { + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED; + } +} + +/** @ingroup LacSymQatHash */ +void +LacSymQat_HashContentDescInit(icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + void *pHwBlockBase, + Cpa32U hwBlockOffsetInQuadWords, + icp_qat_fw_slice_t nextSlice, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean useSymConstantsTable, + CpaBoolean useOptimisedContentDesc, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + Cpa32U *pHashBlkSizeInBytes) +{ + + icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + lac_sym_qat_hash_defs_t *pOuterHashDefs = NULL; + Cpa32U hashSetupBlkSize = 0; + + /* setup the offset in QuadWords into the hw blk */ + cd_ctrl->hash_cfg_offset = hwBlockOffsetInQuadWords; + + ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_AUTH); + + LacSymQat_HashDefsLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashDefs); + + /* Hmac in mode 2 TLS */ + if (IS_HASH_MODE_2(qatHashMode)) { + /* Set bit for nested hashing. + * Make sure not to overwrite other flags in hash_flags byte. + */ + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED); + } + /* Nested hash in mode 0 */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + /* Set bit for nested hashing. + * Make sure not to overwrite other flags in hash_flags byte. + */ + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED); + } + /* mode0 - plain or mode1 - auth */ + else { + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED); + } + + /* set the final digest size */ + cd_ctrl->final_sz = pHashSetupData->digestResultLenInBytes; + + /* set the state1 size */ + cd_ctrl->inner_state1_sz = + LAC_ALIGN_POW2_ROUNDUP(pHashDefs->qatInfo->state1Length, + LAC_QUAD_WORD_IN_BYTES); + + /* set the inner result size to the digest length */ + cd_ctrl->inner_res_sz = pHashDefs->algInfo->digestLength; + + /* set the state2 size - only for mode 1 Auth algos and AES CBC MAC */ + if (IS_HASH_MODE_1(qatHashMode) || + pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CBC_MAC || + pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { + cd_ctrl->inner_state2_sz = + LAC_ALIGN_POW2_ROUNDUP(pHashDefs->qatInfo->state2Length, + LAC_QUAD_WORD_IN_BYTES); + } else { + cd_ctrl->inner_state2_sz = 0; + } + + cd_ctrl->inner_state2_offset = cd_ctrl->hash_cfg_offset + + LAC_BYTES_TO_QUADWORDS(sizeof(icp_qat_hw_auth_setup_t) + + cd_ctrl->inner_state1_sz); + + /* size of inner part of hash setup block */ + hashSetupBlkSize = sizeof(icp_qat_hw_auth_setup_t) + + cd_ctrl->inner_state1_sz + cd_ctrl->inner_state2_sz; + + /* For nested hashing - Fill in the outer fields */ + if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || + IS_HASH_MODE_2(qatHashMode)) { + /* For nested - use the outer algorithm. This covers TLS and + * nested hash. For HMAC mode2 use inner algorithm again */ + CpaCySymHashAlgorithm outerAlg = + (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) ? + pHashSetupData->nestedModeSetupData.outerHashAlgorithm : + pHashSetupData->hashAlgorithm; + + LacSymQat_HashDefsLookupGet(instanceHandle, + outerAlg, + &pOuterHashDefs); + + /* outer config offset */ + cd_ctrl->outer_config_offset = cd_ctrl->inner_state2_offset + + LAC_BYTES_TO_QUADWORDS(cd_ctrl->inner_state2_sz); + + cd_ctrl->outer_state1_sz = + LAC_ALIGN_POW2_ROUNDUP(pOuterHashDefs->algInfo->stateSize, + LAC_QUAD_WORD_IN_BYTES); + + /* outer result size */ + cd_ctrl->outer_res_sz = pOuterHashDefs->algInfo->digestLength; + + /* outer_prefix_offset will be the size of the inner prefix data + * plus the hash state storage size. */ + /* The prefix buffer is part of the ReqParams, so this param + * will be + * setup where ReqParams are set up */ + + /* add on size of outer part of hash block */ + hashSetupBlkSize += + sizeof(icp_qat_hw_auth_setup_t) + cd_ctrl->outer_state1_sz; + } else { + cd_ctrl->outer_config_offset = 0; + cd_ctrl->outer_state1_sz = 0; + cd_ctrl->outer_res_sz = 0; + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { + /* add the size for the cipher config word, the key and the IV*/ + hashSetupBlkSize += sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes + + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } + + *pHashBlkSizeInBytes = hashSetupBlkSize; + + if (useOptimisedContentDesc) { + LacSymQat_HashSetupBlockOptimisedFormatInit(pHashSetupData, + cd_ctrl, + pHwBlockBase, + qatHashMode, + pPrecompute, + pHashDefs, + pOuterHashDefs); + } else if (!useSymConstantsTable) { + /***************************************************************************** + * Populate Hash Setup block * + *****************************************************************************/ + LacSymQat_HashSetupBlockInit(pHashSetupData, + cd_ctrl, + pHwBlockBase, + qatHashMode, + pPrecompute, + pHashDefs, + pOuterHashDefs); + } +} + +/* This fn populates fields in both the CD ctrl block and the ReqParams block + * which describe the Hash ReqParams: + * cd_ctrl.outer_prefix_offset + * cd_ctrl.outer_prefix_sz + * req_params.inner_prefix_sz/aad_sz + * req_params.hash_state_sz + * req_params.auth_res_sz + * + */ +void +LacSymQat_HashSetupReqParamsMetaData( + icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + CpaBoolean hashStateBuffer, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean digestVerify) +{ + icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = NULL; + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + + cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + LacSymQat_HashDefsLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashDefs); + + /* Hmac in mode 2 TLS */ + if (IS_HASH_MODE_2(qatHashMode)) { + /* Inner and outer prefixes are the block length */ + pHashReqParams->u2.inner_prefix_sz = + pHashDefs->algInfo->blockLength; + cd_ctrl->outer_prefix_sz = pHashDefs->algInfo->blockLength; + cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP((pHashReqParams->u2.inner_prefix_sz), + LAC_QUAD_WORD_IN_BYTES)); + } + /* Nested hash in mode 0 */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + + /* set inner and outer prefixes */ + pHashReqParams->u2.inner_prefix_sz = + pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes; + cd_ctrl->outer_prefix_sz = + pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes; + cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP((pHashReqParams->u2.inner_prefix_sz), + LAC_QUAD_WORD_IN_BYTES)); + } + /* mode0 - plain or mode1 - auth */ + else { + Cpa16U aadDataSize = 0; + + /* For Auth Encrypt set the aad size */ + if (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) { + /* at the beginning of the buffer there is B0 block */ + aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; + + /* then, if there is some 'a' data, the buffer will + * store encoded + * length of 'a' and 'a' itself */ + if (pHashSetupData->authModeSetupData.aadLenInBytes > + 0) { + /* as the QAT API puts the requirement on the + * pAdditionalAuthData not to be bigger than 240 + * bytes then we + * just need 2 bytes to store encoded length of + * 'a' */ + aadDataSize += sizeof(Cpa16U); + aadDataSize += pHashSetupData->authModeSetupData + .aadLenInBytes; + } + + /* round the aad size to the multiple of CCM block + * size.*/ + pHashReqParams->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_CCM_BLOCK_SIZE); + } else if (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) { + aadDataSize = + pHashSetupData->authModeSetupData.aadLenInBytes; + + /* round the aad size to the multiple of GCM hash block + * size. */ + pHashReqParams->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_GCM_BLOCK_SIZE); + } else { + pHashReqParams->u2.aad_sz = 0; + } + + cd_ctrl->outer_prefix_sz = 0; + cd_ctrl->outer_prefix_offset = 0; + } + + /* If there is a hash state prefix buffer */ + if (CPA_TRUE == hashStateBuffer) { + /* Note, this sets up size for both aad and non-aad cases */ + pHashReqParams->hash_state_sz = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP(pHashReqParams->u2.inner_prefix_sz, + LAC_QUAD_WORD_IN_BYTES) + + LAC_ALIGN_POW2_ROUNDUP(cd_ctrl->outer_prefix_sz, + LAC_QUAD_WORD_IN_BYTES)); + } else { + pHashReqParams->hash_state_sz = 0; + } + + if (CPA_TRUE == digestVerify) { + /* auth result size in bytes to be read in for a verify + * operation */ + pHashReqParams->auth_res_sz = + pHashSetupData->digestResultLenInBytes; + } else { + pHashReqParams->auth_res_sz = 0; + } + + pHashReqParams->resrvd1 = 0; +} + +void +LacSymQat_HashHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, + void *pHwBlockBase, + lac_hash_blk_ptrs_t *pHashBlkPtrs) +{ + /* encoded offset for inner config is converted to a byte offset. */ + pHashBlkPtrs->pInHashSetup = + (icp_qat_hw_auth_setup_t *)((Cpa8U *)pHwBlockBase + + (cd_ctrl->hash_cfg_offset * + LAC_QUAD_WORD_IN_BYTES)); + + pHashBlkPtrs->pInHashInitState1 = (Cpa8U *)pHashBlkPtrs->pInHashSetup + + sizeof(icp_qat_hw_auth_setup_t); + + pHashBlkPtrs->pInHashInitState2 = + (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + + cd_ctrl->inner_state1_sz; + + pHashBlkPtrs->pOutHashSetup = + (icp_qat_hw_auth_setup_t *)((Cpa8U *)(pHashBlkPtrs + ->pInHashInitState2) + + cd_ctrl->inner_state2_sz); + + pHashBlkPtrs->pOutHashInitState1 = + (Cpa8U *)(pHashBlkPtrs->pOutHashSetup) + + sizeof(icp_qat_hw_auth_setup_t); +} + +static void +LacSymQat_HashSetupBlockInit(const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs) +{ + Cpa32U innerConfig = 0; + lac_hash_blk_ptrs_t hashBlkPtrs = { 0 }; + Cpa32U aed_hash_cmp_length = 0; + + LacSymQat_HashHwBlockPtrsInit(pHashControlBlock, + pHwBlockBase, + &hashBlkPtrs); + + innerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD( + qatHashMode, + pHashDefs->qatInfo->algoEnc, + pHashSetupData->digestResultLenInBytes); + + /* Set the Inner hash configuration */ + hashBlkPtrs.pInHashSetup->auth_config.config = innerConfig; + hashBlkPtrs.pInHashSetup->auth_config.reserved = 0; + + /* For mode 1 pre-computes for auth algorithms */ + if (IS_HASH_MODE_1(qatHashMode) || + CPA_CY_SYM_HASH_AES_CBC_MAC == pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { + /* for HMAC in mode 1 authCounter is the block size + * else the authCounter is 0. The firmware expects the counter + * to be + * big endian */ + LAC_MEM_SHARED_WRITE_SWAP( + hashBlkPtrs.pInHashSetup->auth_counter.counter, + pHashDefs->qatInfo->authCounter); + + /* state 1 is set to 0 for the following algorithms */ + if ((CPA_CY_SYM_HASH_AES_XCBC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CBC_MAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm)) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1, + pHashDefs->qatInfo->state1Length); + } + + /* Pad remaining bytes of sha1 precomputes */ + if (CPA_CY_SYM_HASH_SHA1 == pHashSetupData->hashAlgorithm) { + Cpa32U state1PadLen = 0; + Cpa32U state2PadLen = 0; + + if (pHashControlBlock->inner_state1_sz > + pHashDefs->algInfo->stateSize) { + state1PadLen = + pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + } + + if (pHashControlBlock->inner_state2_sz > + pHashDefs->algInfo->stateSize) { + state2PadLen = + pHashControlBlock->inner_state2_sz - + pHashDefs->algInfo->stateSize; + } + + if (state1PadLen > 0) { + + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + state1PadLen); + } + + if (state2PadLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState2 + + pHashDefs->algInfo->stateSize, + state2PadLen); + } + } + + pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; + pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; + + /* Set the destination for pre-compute state1 data to be written + */ + pPrecompute->pState1 = hashBlkPtrs.pInHashInitState1; + + /* Set the destination for pre-compute state1 data to be written + */ + pPrecompute->pState2 = hashBlkPtrs.pInHashInitState2; + } + /* For digest and nested digest */ + else { + Cpa32U padLen = pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + + /* counter set to 0 */ + hashBlkPtrs.pInHashSetup->auth_counter.counter = 0; + + /* set the inner hash state 1 */ + memcpy(hashBlkPtrs.pInHashInitState1, + pHashDefs->algInfo->initState, + pHashDefs->algInfo->stateSize); + + if (padLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + padLen); + } + } + + hashBlkPtrs.pInHashSetup->auth_counter.reserved = 0; + + /* Fill in the outer part of the hash setup block */ + if ((CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || + IS_HASH_MODE_2(qatHashMode)) && + (NULL != pOuterHashDefs)) { + Cpa32U outerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD( + qatHashMode, + pOuterHashDefs->qatInfo->algoEnc, + pHashSetupData->digestResultLenInBytes); + + Cpa32U padLen = pHashControlBlock->outer_state1_sz - + pOuterHashDefs->algInfo->stateSize; + + /* populate the auth config */ + hashBlkPtrs.pOutHashSetup->auth_config.config = outerConfig; + hashBlkPtrs.pOutHashSetup->auth_config.reserved = 0; + + /* outer Counter set to 0 */ + hashBlkPtrs.pOutHashSetup->auth_counter.counter = 0; + hashBlkPtrs.pOutHashSetup->auth_counter.reserved = 0; + + /* set outer hash state 1 */ + memcpy(hashBlkPtrs.pOutHashInitState1, + pOuterHashDefs->algInfo->initState, + pOuterHashDefs->algInfo->stateSize); + + if (padLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pOutHashInitState1 + + pOuterHashDefs->algInfo->stateSize, + padLen); + } + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + ICP_QAT_HW_CIPHER_ECB_MODE, + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, + ICP_QAT_HW_CIPHER_KEY_CONVERT, + ICP_QAT_HW_CIPHER_ENCRYPT, + aed_hash_cmp_length); + + pCipherConfig->reserved = 0; + + memcpy((Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t), + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + + LAC_OS_BZERO( + (Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes, + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + ICP_QAT_HW_CIPHER_ECB_MODE, + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, + ICP_QAT_HW_CIPHER_KEY_CONVERT, + ICP_QAT_HW_CIPHER_ENCRYPT, + aed_hash_cmp_length); + + pCipherConfig->reserved = 0; + + memcpy((Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t), + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + + LAC_OS_BZERO( + (Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes, + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + } +} + +static void +LacSymQat_HashOpHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, + void *pHwBlockBase, + lac_hash_blk_ptrs_optimised_t *pHashBlkPtrs) +{ + pHashBlkPtrs->pInHashInitState1 = (((Cpa8U *)pHwBlockBase) + 16); + pHashBlkPtrs->pInHashInitState2 = + (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + + cd_ctrl->inner_state1_sz; +} + +static void +LacSymQat_HashSetupBlockOptimisedFormatInit( + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs) +{ + + Cpa32U state1PadLen = 0; + Cpa32U state2PadLen = 0; + + lac_hash_blk_ptrs_optimised_t pHashBlkPtrs = { 0 }; + + LacSymQat_HashOpHwBlockPtrsInit(pHashControlBlock, + pHwBlockBase, + &pHashBlkPtrs); + + if (pHashControlBlock->inner_state1_sz > + pHashDefs->algInfo->stateSize) { + state1PadLen = pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + } + + if (pHashControlBlock->inner_state2_sz > + pHashDefs->algInfo->stateSize) { + state2PadLen = pHashControlBlock->inner_state2_sz - + pHashDefs->algInfo->stateSize; + } + + if (state1PadLen > 0) { + + LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + state1PadLen); + } + + if (state2PadLen > 0) { + + LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState2 + + pHashDefs->algInfo->stateSize, + state2PadLen); + } + pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; + pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; + + /* Set the destination for pre-compute state1 data to be written */ + pPrecompute->pState1 = pHashBlkPtrs.pInHashInitState1; + + /* Set the destination for pre-compute state1 data to be written */ + pPrecompute->pState2 = pHashBlkPtrs.pInHashInitState2; +} + +void +LacSymQat_HashStatePrefixAadBufferSizeGet( + icp_qat_la_bulk_req_ftr_t *pMsg, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf) +{ + const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl; + icp_qat_la_auth_req_params_t *pHashReqParams; + + cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + /* hash state storage needed to support partial packets. Space reserved + * for this in all cases */ + pHashStateBuf->stateStorageSzQuadWords = LAC_BYTES_TO_QUADWORDS( + sizeof(icp_qat_hw_auth_counter_t) + cd_ctrl->inner_state1_sz); + + pHashStateBuf->prefixAadSzQuadWords = pHashReqParams->hash_state_sz; +} + +void +LacSymQat_HashStatePrefixAadBufferPopulate( + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa8U *pInnerPrefixAad, + Cpa8U innerPrefixSize, + Cpa8U *pOuterPrefix, + Cpa8U outerPrefixSize) +{ + const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + + icp_qat_la_auth_req_params_t *pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + /* + * Let S be the supplied secret + * S1 = S/2 if S is even and (S/2 + 1) if S is odd. + * Set length S2 (inner prefix) = S1 and the start address + * of S2 is S[S1/2] i.e. if S is odd then S2 starts at the last byte of + * S1 + * _____________________________________________________________ + * | outer prefix | padding | + * |________________| | + * | | + * |____________________________________________________________| + * | inner prefix | padding | + * |________________| | + * | | + * |____________________________________________________________| + * + */ + if (NULL != pInnerPrefixAad) { + Cpa8U *pLocalInnerPrefix = + (Cpa8U *)(pHashStateBuf->pData) + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->stateStorageSzQuadWords); + Cpa8U padding = + pHashReqParams->u2.inner_prefix_sz - innerPrefixSize; + /* copy the inner prefix or aad data */ + memcpy(pLocalInnerPrefix, pInnerPrefixAad, innerPrefixSize); + + /* Reset with zeroes any area reserved for padding in this block + */ + if (0 < padding) { + LAC_OS_BZERO(pLocalInnerPrefix + innerPrefixSize, + padding); + } + } + + if (NULL != pOuterPrefix) { + Cpa8U *pLocalOuterPrefix = + (Cpa8U *)pHashStateBuf->pData + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->stateStorageSzQuadWords + + cd_ctrl->outer_prefix_offset); + Cpa8U padding = LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->prefixAadSzQuadWords) - + pHashReqParams->u2.inner_prefix_sz - outerPrefixSize; + + /* copy the outer prefix */ + memcpy(pLocalOuterPrefix, pOuterPrefix, outerPrefixSize); + + /* Reset with zeroes any area reserved for padding in this block + */ + if (0 < padding) { + LAC_OS_BZERO(pLocalOuterPrefix + outerPrefixSize, + padding); + } + } +} + +inline CpaStatus +LacSymQat_HashRequestParamsPopulate( + icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U authOffsetInBytes, + Cpa32U authLenInBytes, + sal_service_t *pService, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + Cpa32U packetType, + Cpa32U hashResultSize, + CpaBoolean digestVerify, + Cpa8U *pAuthResult, + CpaCySymHashAlgorithm alg, + void *hkdf_secret) +{ + Cpa64U authResultPhys = 0; + icp_qat_fw_la_auth_req_params_t *pHashReqParams; + + pHashReqParams = (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pReq->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + pHashReqParams->auth_off = authOffsetInBytes; + pHashReqParams->auth_len = authLenInBytes; + + /* Set the physical location of secret for HKDF */ + if (NULL != hkdf_secret) { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pHashReqParams->u1.aad_adr, hkdf_secret); + + if (pHashReqParams->u1.aad_adr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " HKDF secret\n"); + return CPA_STATUS_FAIL; + } + } + + /* For a Full packet or last partial need to set the digest result + * pointer + * and the auth result field */ + if (NULL != pAuthResult) { + authResultPhys = + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), + (void *)pAuthResult); + + if (authResultPhys == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " auth result\n"); + return CPA_STATUS_FAIL; + } + + pHashReqParams->auth_res_addr = authResultPhys; + } else { + pHashReqParams->auth_res_addr = 0; + } + + if (CPA_TRUE == digestVerify) { + /* auth result size in bytes to be read in for a verify + * operation */ + pHashReqParams->auth_res_sz = hashResultSize; + } else { + pHashReqParams->auth_res_sz = 0; + } + + /* If there is a hash state prefix buffer */ + if (NULL != pHashStateBuf) { + /* Only write the pointer to the buffer if the size is greater + * than 0 + * this will be the case for plain and auth mode due to the + * state storage required for partial packets and for nested + * mode (when + * the prefix data is > 0) */ + if ((pHashStateBuf->stateStorageSzQuadWords + + pHashStateBuf->prefixAadSzQuadWords) > 0) { + /* For the first partial packet, the QAT expects the + * pointer to the + * inner prefix even if there is no memory allocated for + * this. The + * QAT will internally calculate where to write the + * state back. */ + if ((ICP_QAT_FW_LA_PARTIAL_START == packetType) || + (ICP_QAT_FW_LA_PARTIAL_NONE == packetType)) { + // prefix_addr changed to auth_partial_st_prefix + pHashReqParams->u1.auth_partial_st_prefix = + ((pHashStateBuf->pDataPhys) + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf + ->stateStorageSzQuadWords)); + } else { + pHashReqParams->u1.auth_partial_st_prefix = + pHashStateBuf->pDataPhys; + } + } + /* nested mode when the prefix data is 0 */ + else { + pHashReqParams->u1.auth_partial_st_prefix = 0; + } + + /* For middle & last partial, state size is the hash state + * storage + * if hash mode 2 this will include the prefix data */ + if ((ICP_QAT_FW_LA_PARTIAL_MID == packetType) || + (ICP_QAT_FW_LA_PARTIAL_END == packetType)) { + pHashReqParams->hash_state_sz = + (pHashStateBuf->stateStorageSzQuadWords + + pHashStateBuf->prefixAadSzQuadWords); + } + /* For full packets and first partials set the state size to + * that of + * the prefix/aad. prefix includes both the inner and outer + * prefix */ + else { + pHashReqParams->hash_state_sz = + pHashStateBuf->prefixAadSzQuadWords; + } + } else { + pHashReqParams->u1.auth_partial_st_prefix = 0; + pHashReqParams->hash_state_sz = 0; + } + + /* GMAC only */ + if (CPA_CY_SYM_HASH_AES_GMAC == alg) { + pHashReqParams->hash_state_sz = 0; + pHashReqParams->u1.aad_adr = 0; + } + + /* This field is only used by TLS requests */ + /* In TLS case this is set after this function is called */ + pHashReqParams->resrvd1 = 0; + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c new file mode 100644 index 00000000000..23a77f19cca --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c @@ -0,0 +1,491 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_hash_defs_lookup.c Hash Definitions Lookup + * + * @ingroup LacHashDefsLookup + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_transport.h" +#include "lac_sym.h" +#include "icp_qat_fw_la.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sal_types_crypto.h" +#include "lac_sym_hash_defs.h" + +/* state size for xcbc mac consists of 3 * 16 byte keys */ +#define LAC_SYM_QAT_XCBC_STATE_SIZE ((LAC_HASH_XCBC_MAC_BLOCK_SIZE)*3) + +#define LAC_SYM_QAT_CMAC_STATE_SIZE ((LAC_HASH_CMAC_BLOCK_SIZE)*3) + +/* This type is used for the mapping between the hash algorithm and + * the corresponding hash definitions structure */ +typedef struct lac_sym_qat_hash_def_map_s { + CpaCySymHashAlgorithm hashAlgorithm; + /* hash algorithm */ + lac_sym_qat_hash_defs_t hashDefs; + /* hash defintions pointers */ +} lac_sym_qat_hash_def_map_t; + +/* +******************************************************************************* +* Static Variables +******************************************************************************* +*/ + +/* initialisers as defined in FIPS and RFCS for digest operations */ + +/* md5 16 bytes - Initialiser state can be found in RFC 1321*/ +static Cpa8U md5InitialState[LAC_HASH_MD5_STATE_SIZE] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +/* SHA1 - 20 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha1InitialState[LAC_HASH_SHA1_STATE_SIZE] = { + 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, + 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0 +}; + +/* SHA 224 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha224InitialState[LAC_HASH_SHA224_STATE_SIZE] = { + 0xc1, 0x05, 0x9e, 0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd, + 0x17, 0xf7, 0x0e, 0x59, 0x39, 0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58, + 0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe, 0xfa, 0x4f, 0xa4 +}; + +/* SHA 256 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha256InitialState[LAC_HASH_SHA256_STATE_SIZE] = + { 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3, + 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, + 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19 }; + +/* SHA 384 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha384InitialState[LAC_HASH_SHA384_STATE_SIZE] = + { 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29, + 0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, + 0xdd, 0x17, 0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67, + 0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87, + 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f, + 0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4 }; + +/* SHA 512 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha512InitialState[LAC_HASH_SHA512_STATE_SIZE] = + { 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, + 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, + 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, + 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, + 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, + 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79 }; + +/* SHA3 224 - 28 bytes */ +static Cpa8U sha3_224InitialState[LAC_HASH_SHA3_224_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 256 - 32 bytes */ +static Cpa8U sha3_256InitialState[LAC_HASH_SHA3_256_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 384 - 48 bytes */ +static Cpa8U sha3_384InitialState[LAC_HASH_SHA3_384_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 512 - 64 bytes */ +static Cpa8U sha3_512InitialState[LAC_HASH_SHA3_512_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SM3 - 32 bytes */ +static Cpa8U sm3InitialState[LAC_HASH_SM3_STATE_SIZE] = + { 0x73, 0x80, 0x16, 0x6f, 0x49, 0x14, 0xb2, 0xb9, 0x17, 0x24, 0x42, + 0xd7, 0xda, 0x8a, 0x06, 0x00, 0xa9, 0x6f, 0x30, 0xbc, 0x16, 0x31, + 0x38, 0xaa, 0xe3, 0x8d, 0xee, 0x4d, 0xb0, 0xfb, 0x0e, 0x4e }; + +/* Constants used in generating K1, K2, K3 from a Key for AES_XCBC_MAC + * State defined in RFC 3566 */ +static Cpa8U aesXcbcKeySeed[LAC_SYM_QAT_XCBC_STATE_SIZE] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +}; + +static Cpa8U aesCmacKeySeed[LAC_HASH_CMAC_BLOCK_SIZE] = { 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00 }; + +/* Hash Algorithm specific structure */ + +static lac_sym_qat_hash_alg_info_t md5Info = { LAC_HASH_MD5_DIGEST_SIZE, + LAC_HASH_MD5_BLOCK_SIZE, + md5InitialState, + LAC_HASH_MD5_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha1Info = { LAC_HASH_SHA1_DIGEST_SIZE, + LAC_HASH_SHA1_BLOCK_SIZE, + sha1InitialState, + LAC_HASH_SHA1_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha224Info = { LAC_HASH_SHA224_DIGEST_SIZE, + LAC_HASH_SHA224_BLOCK_SIZE, + sha224InitialState, + LAC_HASH_SHA224_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha256Info = { LAC_HASH_SHA256_DIGEST_SIZE, + LAC_HASH_SHA256_BLOCK_SIZE, + sha256InitialState, + LAC_HASH_SHA256_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha384Info = { LAC_HASH_SHA384_DIGEST_SIZE, + LAC_HASH_SHA384_BLOCK_SIZE, + sha384InitialState, + LAC_HASH_SHA384_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha512Info = { LAC_HASH_SHA512_DIGEST_SIZE, + LAC_HASH_SHA512_BLOCK_SIZE, + sha512InitialState, + LAC_HASH_SHA512_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_224Info = + { LAC_HASH_SHA3_224_DIGEST_SIZE, + LAC_HASH_SHA3_224_BLOCK_SIZE, + sha3_224InitialState, + LAC_HASH_SHA3_224_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_256Info = + { LAC_HASH_SHA3_256_DIGEST_SIZE, + LAC_HASH_SHA3_256_BLOCK_SIZE, + sha3_256InitialState, + LAC_HASH_SHA3_256_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_384Info = + { LAC_HASH_SHA3_384_DIGEST_SIZE, + LAC_HASH_SHA3_384_BLOCK_SIZE, + sha3_384InitialState, + LAC_HASH_SHA3_384_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_512Info = + { LAC_HASH_SHA3_512_DIGEST_SIZE, + LAC_HASH_SHA3_512_BLOCK_SIZE, + sha3_512InitialState, + LAC_HASH_SHA3_512_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t polyInfo = { LAC_HASH_POLY_DIGEST_SIZE, + LAC_HASH_POLY_BLOCK_SIZE, + NULL, /* intial state */ + LAC_HASH_POLY_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t shake_128Info = + { LAC_HASH_SHAKE_128_DIGEST_SIZE, LAC_HASH_SHAKE_128_BLOCK_SIZE, NULL, 0 }; + +static lac_sym_qat_hash_alg_info_t shake_256Info = + { LAC_HASH_SHAKE_256_DIGEST_SIZE, LAC_HASH_SHAKE_256_BLOCK_SIZE, NULL, 0 }; + +static lac_sym_qat_hash_alg_info_t sm3Info = { LAC_HASH_SM3_DIGEST_SIZE, + LAC_HASH_SM3_BLOCK_SIZE, + sm3InitialState, + LAC_HASH_SM3_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t xcbcMacInfo = + { LAC_HASH_XCBC_MAC_128_DIGEST_SIZE, + LAC_HASH_XCBC_MAC_BLOCK_SIZE, + aesXcbcKeySeed, + LAC_SYM_QAT_XCBC_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t aesCmacInfo = + { LAC_HASH_CMAC_128_DIGEST_SIZE, + LAC_HASH_CMAC_BLOCK_SIZE, + aesCmacKeySeed, + LAC_SYM_QAT_CMAC_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t aesCcmInfo = { + LAC_HASH_AES_CCM_DIGEST_SIZE, + LAC_HASH_AES_CCM_BLOCK_SIZE, + NULL, /* intial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t aesGcmInfo = { + LAC_HASH_AES_GCM_DIGEST_SIZE, + LAC_HASH_AES_GCM_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t kasumiF9Info = { + LAC_HASH_KASUMI_F9_DIGEST_SIZE, + LAC_HASH_KASUMI_F9_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t snow3gUia2Info = { + LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE, + LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t aesCbcMacInfo = + { LAC_HASH_AES_CBC_MAC_DIGEST_SIZE, + LAC_HASH_AES_CBC_MAC_BLOCK_SIZE, + NULL, + 0 }; + +static lac_sym_qat_hash_alg_info_t zucEia3Info = { + LAC_HASH_ZUC_EIA3_DIGEST_SIZE, + LAC_HASH_ZUC_EIA3_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; +/* Hash QAT specific structures */ + +static lac_sym_qat_hash_qat_info_t md5Config = { ICP_QAT_HW_AUTH_ALGO_MD5, + LAC_HASH_MD5_BLOCK_SIZE, + ICP_QAT_HW_MD5_STATE1_SZ, + ICP_QAT_HW_MD5_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha1Config = { ICP_QAT_HW_AUTH_ALGO_SHA1, + LAC_HASH_SHA1_BLOCK_SIZE, + ICP_QAT_HW_SHA1_STATE1_SZ, + ICP_QAT_HW_SHA1_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha224Config = + { ICP_QAT_HW_AUTH_ALGO_SHA224, + LAC_HASH_SHA224_BLOCK_SIZE, + ICP_QAT_HW_SHA224_STATE1_SZ, + ICP_QAT_HW_SHA224_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha256Config = + { ICP_QAT_HW_AUTH_ALGO_SHA256, + LAC_HASH_SHA256_BLOCK_SIZE, + ICP_QAT_HW_SHA256_STATE1_SZ, + ICP_QAT_HW_SHA256_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha384Config = + { ICP_QAT_HW_AUTH_ALGO_SHA384, + LAC_HASH_SHA384_BLOCK_SIZE, + ICP_QAT_HW_SHA384_STATE1_SZ, + ICP_QAT_HW_SHA384_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha512Config = + { ICP_QAT_HW_AUTH_ALGO_SHA512, + LAC_HASH_SHA512_BLOCK_SIZE, + ICP_QAT_HW_SHA512_STATE1_SZ, + ICP_QAT_HW_SHA512_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_224Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_224, + LAC_HASH_SHA3_224_BLOCK_SIZE, + ICP_QAT_HW_SHA3_224_STATE1_SZ, + ICP_QAT_HW_SHA3_224_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_256Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_256, + LAC_HASH_SHA3_256_BLOCK_SIZE, + ICP_QAT_HW_SHA3_256_STATE1_SZ, + ICP_QAT_HW_SHA3_256_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_384Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_384, + LAC_HASH_SHA3_384_BLOCK_SIZE, + ICP_QAT_HW_SHA3_384_STATE1_SZ, + ICP_QAT_HW_SHA3_384_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_512Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_512, + LAC_HASH_SHA3_512_BLOCK_SIZE, + ICP_QAT_HW_SHA3_512_STATE1_SZ, + ICP_QAT_HW_SHA3_512_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t shake_128Config = + { ICP_QAT_HW_AUTH_ALGO_SHAKE_128, LAC_HASH_SHAKE_128_BLOCK_SIZE, 0, 0 }; + +static lac_sym_qat_hash_qat_info_t shake_256Config = + { ICP_QAT_HW_AUTH_ALGO_SHAKE_256, LAC_HASH_SHAKE_256_BLOCK_SIZE, 0, 0 }; + +static lac_sym_qat_hash_qat_info_t polyConfig = { ICP_QAT_HW_AUTH_ALGO_POLY, + LAC_HASH_POLY_BLOCK_SIZE, + 0, + 0 }; + +static lac_sym_qat_hash_qat_info_t sm3Config = { ICP_QAT_HW_AUTH_ALGO_SM3, + LAC_HASH_SM3_BLOCK_SIZE, + ICP_QAT_HW_SM3_STATE1_SZ, + ICP_QAT_HW_SM3_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t xcbcMacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, + 0, + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, + LAC_SYM_QAT_XCBC_STATE_SIZE }; + +static lac_sym_qat_hash_qat_info_t aesCmacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, + 0, + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, + LAC_SYM_QAT_CMAC_STATE_SIZE }; + +static lac_sym_qat_hash_qat_info_t aesCcmConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, + 0, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, + ICP_QAT_HW_AES_CBC_MAC_KEY_SZ + ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ }; + +static lac_sym_qat_hash_qat_info_t aesGcmConfig = + { ICP_QAT_HW_AUTH_ALGO_GALOIS_128, + 0, + ICP_QAT_HW_GALOIS_128_STATE1_SZ, + ICP_QAT_HW_GALOIS_H_SZ + ICP_QAT_HW_GALOIS_LEN_A_SZ + + ICP_QAT_HW_GALOIS_E_CTR0_SZ }; + +static lac_sym_qat_hash_qat_info_t kasumiF9Config = + { ICP_QAT_HW_AUTH_ALGO_KASUMI_F9, + 0, + ICP_QAT_HW_KASUMI_F9_STATE1_SZ, + ICP_QAT_HW_KASUMI_F9_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t snow3gUia2Config = + { ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2, + 0, + ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ, + ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t aesCbcMacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, + 0, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ }; + +static lac_sym_qat_hash_qat_info_t zucEia3Config = + { ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3, + 0, + ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ, + ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ }; + +/* Array of mappings between algorithm and info structure + * This array is used to populate the lookup table */ +static lac_sym_qat_hash_def_map_t lacHashDefsMapping[] = + { { CPA_CY_SYM_HASH_MD5, { &md5Info, &md5Config } }, + { CPA_CY_SYM_HASH_SHA1, { &sha1Info, &sha1Config } }, + { CPA_CY_SYM_HASH_SHA224, { &sha224Info, &sha224Config } }, + { CPA_CY_SYM_HASH_SHA256, { &sha256Info, &sha256Config } }, + { CPA_CY_SYM_HASH_SHA384, { &sha384Info, &sha384Config } }, + { CPA_CY_SYM_HASH_SHA512, { &sha512Info, &sha512Config } }, + { CPA_CY_SYM_HASH_SHA3_224, { &sha3_224Info, &sha3_224Config } }, + { CPA_CY_SYM_HASH_SHA3_256, { &sha3_256Info, &sha3_256Config } }, + { CPA_CY_SYM_HASH_SHA3_384, { &sha3_384Info, &sha3_384Config } }, + { CPA_CY_SYM_HASH_SHA3_512, { &sha3_512Info, &sha3_512Config } }, + { CPA_CY_SYM_HASH_SHAKE_128, { &shake_128Info, &shake_128Config } }, + { CPA_CY_SYM_HASH_SHAKE_256, { &shake_256Info, &shake_256Config } }, + { CPA_CY_SYM_HASH_POLY, { &polyInfo, &polyConfig } }, + { CPA_CY_SYM_HASH_SM3, { &sm3Info, &sm3Config } }, + { CPA_CY_SYM_HASH_AES_XCBC, { &xcbcMacInfo, &xcbcMacConfig } }, + { CPA_CY_SYM_HASH_AES_CMAC, { &aesCmacInfo, &aesCmacConfig } }, + { CPA_CY_SYM_HASH_AES_CCM, { &aesCcmInfo, &aesCcmConfig } }, + { CPA_CY_SYM_HASH_AES_GCM, { &aesGcmInfo, &aesGcmConfig } }, + { CPA_CY_SYM_HASH_KASUMI_F9, { &kasumiF9Info, &kasumiF9Config } }, + { CPA_CY_SYM_HASH_SNOW3G_UIA2, { &snow3gUia2Info, &snow3gUia2Config } }, + { CPA_CY_SYM_HASH_AES_GMAC, { &aesGcmInfo, &aesGcmConfig } }, + { CPA_CY_SYM_HASH_ZUC_EIA3, { &zucEia3Info, &zucEia3Config } }, + { CPA_CY_SYM_HASH_AES_CBC_MAC, { &aesCbcMacInfo, &aesCbcMacConfig } } }; + +/* + * LacSymQat_HashLookupInit + */ +CpaStatus +LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle) +{ + Cpa32U entry = 0; + Cpa32U numEntries = 0; + Cpa32U arraySize = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaCySymHashAlgorithm hashAlg = CPA_CY_SYM_HASH_NONE; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + arraySize = + (CPA_CY_HASH_ALG_END + 1) * sizeof(lac_sym_qat_hash_defs_t *); + /* Size round up for performance */ + arraySize = LAC_ALIGN_POW2_ROUNDUP(arraySize, LAC_64BYTE_ALIGNMENT); + + pService->pLacHashLookupDefs = LAC_OS_MALLOC(arraySize); + + if (NULL != pService->pLacHashLookupDefs) { + LAC_OS_BZERO(pService->pLacHashLookupDefs, arraySize); + + numEntries = sizeof(lacHashDefsMapping) / + sizeof(lac_sym_qat_hash_def_map_t); + + /* initialise the hash lookup definitions table so that the + * algorithm + * can be used to index into the table */ + for (entry = 0; entry < numEntries; entry++) { + hashAlg = lacHashDefsMapping[entry].hashAlgorithm; + + pService->pLacHashLookupDefs[hashAlg] = + &(lacHashDefsMapping[entry].hashDefs); + } + } else { + status = CPA_STATUS_RESOURCE; + } + return status; +} + +/* + * LacSymQat_HashAlgLookupGet + */ +void +LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t **ppHashAlgInfo) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + *ppHashAlgInfo = pService->pLacHashLookupDefs[hashAlgorithm]->algInfo; +} + +/* + * LacSymQat_HashDefsLookupGet + */ +void +LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_defs_t **ppHashDefsInfo) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + *ppHashDefsInfo = pService->pLacHashLookupDefs[hashAlgorithm]; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c new file mode 100644 index 00000000000..abc7710aa96 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_key.c Interfaces for populating the symmetric qat key + * structures + * + * @ingroup LacSymQatKey + * + *****************************************************************************/ + +#include "cpa.h" +#include "cpa_cy_key.h" +#include "lac_mem.h" +#include "icp_qat_fw_la.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_sym_qat_key.h" +#include "lac_sym_hash_defs.h" + +void +LacSymQat_KeySslRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa32U iterations) +{ + /* Rounded to nearest 8 byte boundary */ + Cpa8U outLenRounded = 0; + outLenRounded = LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, + LAC_QUAD_WORD_IN_BYTES); + + pKeyGenReqMid->u.secret_lgth_ssl = secretLenInBytes; + pKeyGenReqMid->u1.s1.output_lgth_ssl = outLenRounded; + pKeyGenReqMid->u1.s1.label_lgth_ssl = labelLenInBytes; + pKeyGenReqMid->u2.iter_count = iterations; + pKeyGenReqMid->u3.resrvd2 = 0; + pKeyGenReqMid->resrvd3 = 0; + + /* Set up the common LA flags */ + pKeyGenReqHdr->comn_hdr.service_cmd_id = + ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE; + pKeyGenReqHdr->comn_hdr.resrvd1 = 0; +} + +void +LacSymQat_KeyTlsRequestPopulate( + icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelInfo, /* Generic name, can be num of labels or label length */ + Cpa32U secretLenInBytes, + Cpa8U seedLenInBytes, + icp_qat_fw_la_cmd_id_t cmdId) +{ + pKeyGenReqParams->u1.s3.output_lgth_tls = + LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, + LAC_QUAD_WORD_IN_BYTES); + + /* For TLS u param of auth_req_params is set to secretLen */ + pKeyGenReqParams->u.secret_lgth_tls = secretLenInBytes; + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + pKeyGenReqParams->u3.resrvd2 = 0; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + pKeyGenReqParams->u1.hkdf.info_length = labelInfo; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + pKeyGenReqParams->u1.hkdf.info_length = labelInfo; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: + /* Num of Labels */ + pKeyGenReqParams->u1.hkdf_label.num_labels = labelInfo; + pKeyGenReqParams->u3.hkdf_num_sublabels = 4; /* 4 subLabels */ + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + /* Num of Labels */ + pKeyGenReqParams->u1.hkdf_label.num_labels = labelInfo; + pKeyGenReqParams->u3.hkdf_num_sublabels = 4; /* 4 subLabels */ + break; + default: + pKeyGenReqParams->u1.s3.label_lgth_tls = labelInfo; + pKeyGenReqParams->u2.tls_seed_length = seedLenInBytes; + pKeyGenReqParams->u3.resrvd2 = 0; + break; + } + pKeyGenReqParams->resrvd3 = 0; +} + +void +LacSymQat_KeyMgfRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa8U seedLenInBytes, + Cpa16U maskLenInBytes, + Cpa8U hashLenInBytes) +{ + pKeyGenReqHdr->comn_hdr.service_cmd_id = ICP_QAT_FW_LA_CMD_MGF1; + pKeyGenReqMid->u.mask_length = + LAC_ALIGN_POW2_ROUNDUP(maskLenInBytes, LAC_QUAD_WORD_IN_BYTES); + + pKeyGenReqMid->u1.s2.hash_length = hashLenInBytes; + pKeyGenReqMid->u1.s2.seed_length = seedLenInBytes; +} + +void +LacSymQat_KeySslKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr, + void *pSecret) +{ + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pSslKeyMaterialInput->seed_addr, pSeed); + + pSslKeyMaterialInput->label_addr = labelPhysAddr; + + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pSslKeyMaterialInput->secret_addr, pSecret); +} + +void +LacSymQat_KeyTlsKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr) +{ + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pTlsKeyMaterialInput->seed_addr, pSeed); + + pTlsKeyMaterialInput->label_addr = labelPhysAddr; +} + +void +LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_hkdf_key_material_input_t *pTlsKeyMaterialInput, + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + Cpa64U subLabelsPhysAddr, + icp_qat_fw_la_cmd_id_t cmdId) +{ + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->labels_addr, + pKeyGenTlsOpData->info); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + pTlsKeyMaterialInput->labels_addr = + pTlsKeyMaterialInput->ikm_addr + + ((uint64_t)&pKeyGenTlsOpData->info - + (uint64_t)&pKeyGenTlsOpData->secret); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: + pTlsKeyMaterialInput->sublabels_addr = subLabelsPhysAddr; + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->labels_addr, + pKeyGenTlsOpData->label); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: + pTlsKeyMaterialInput->sublabels_addr = subLabelsPhysAddr; + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + pTlsKeyMaterialInput->labels_addr = + pTlsKeyMaterialInput->ikm_addr + + ((uint64_t)&pKeyGenTlsOpData->label - + (uint64_t)&pKeyGenTlsOpData->secret); + break; + default: + break; + } +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_compression.c b/sys/dev/qat/qat_api/common/ctrl/sal_compression.c new file mode 100644 index 00000000000..d8523d23b0e --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_compression.c @@ -0,0 +1,1554 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_compression.c + * + * @ingroup SalCtrl + * + * @description + * This file contains the sal implementation for compression. + * + *****************************************************************************/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_dc.h" + +/* QAT utils includes */ +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_poll.h" +#include "icp_adf_debug.h" +#include "icp_adf_esram.h" +#include "icp_qat_hw.h" + +/* SAL includes */ +#include "lac_mem.h" +#include "lac_common.h" +#include "lac_mem_pools.h" +#include "sal_statistics.h" +#include "lac_list.h" +#include "icp_sal_poll.h" +#include "sal_types_compression.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "dc_stats.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "sal_string_parse.h" +#include "sal_service_state.h" +#include "lac_buffer_desc.h" +#include "icp_qat_fw_comp.h" +#include "icp_sal_versions.h" + +/* C string null terminator size */ +#define SAL_NULL_TERM_SIZE 1 + +/* Type to access extended features bit fields */ +typedef struct dc_extended_features_s { + unsigned is_cnv : 1; /* Bit<0> */ + unsigned padding : 7; + unsigned is_cnvnr : 1; /* Bit<8> */ + unsigned not_used : 23; +} dc_extd_ftrs_t; + +/* + * Prints statistics for a compression instance + */ +static int +SalCtrl_CompresionDebug(void *private_data, char *data, int size, int offset) +{ + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)private_data; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaDcStats dcStats = { 0 }; + Cpa32S len = 0; + + status = cpaDcGetStats(pCompressionService, &dcStats); + if (status != CPA_STATUS_SUCCESS) { + QAT_UTILS_LOG("cpaDcGetStats returned error.\n"); + return (-1); + } + + /* Engine Info */ + if (NULL != pCompressionService->debug_file) { + len += snprintf(data + len, + size - len, + SEPARATOR BORDER + " Statistics for Instance %24s | \n" SEPARATOR, + pCompressionService->debug_file->name); + } + + /* Perform Info */ + len += snprintf(data + len, + size - len, + BORDER " DC comp Requests: %16llu " BORDER + "\n" BORDER + " DC comp Request Errors: %16llu " BORDER + "\n" BORDER + " DC comp Completed: %16llu " BORDER + "\n" BORDER + " DC comp Completed Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)dcStats.numCompRequests, + (long long unsigned int)dcStats.numCompRequestsErrors, + (long long unsigned int)dcStats.numCompCompleted, + (long long unsigned int)dcStats.numCompCompletedErrors); + + /* Perform Info */ + len += snprintf( + data + len, + size - len, + BORDER " DC decomp Requests: %16llu " BORDER "\n" BORDER + " DC decomp Request Errors: %16llu " BORDER "\n" BORDER + " DC decomp Completed: %16llu " BORDER "\n" BORDER + " DC decomp Completed Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)dcStats.numDecompRequests, + (long long unsigned int)dcStats.numDecompRequestsErrors, + (long long unsigned int)dcStats.numDecompCompleted, + (long long unsigned int)dcStats.numDecompCompletedErrors); + return 0; +} + +/* Initialise device specific information needed by compression service */ +static CpaStatus +SalCtrl_CompressionInit_CompData(icp_accel_dev_t *device, + sal_compression_service_t *pCompService) +{ + switch (device->deviceType) { + case DEVICE_DH895XCC: + case DEVICE_DH895XCCVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES; + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.oddByteDecompNobFinal = CPA_TRUE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_FALSE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED; + + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_16; + + pCompService->comp_device_data.windowSizeMask = + (1 << DC_8K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.cnvnrSupported = CPA_FALSE; + break; + case DEVICE_C3XXX: + case DEVICE_C3XXXVF: + case DEVICE_200XX: + case DEVICE_200XXVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES; + pCompService->comp_device_data.oddByteDecompNobFinal = + CPA_FALSE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_16; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + case DEVICE_C62X: + case DEVICE_C62XVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_10COMP_SLICES; + pCompService->comp_device_data.oddByteDecompNobFinal = + CPA_FALSE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + case DEVICE_C4XXX: + case DEVICE_C4XXXVF: + pCompService->generic_service_info.integrityCrcCheck = CPA_TRUE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_24COMP_SLICES; + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_MIN_SIZE; + pCompService->comp_device_data.oddByteDecompNobFinal = CPA_TRUE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_TRUE; + if (pCompService->generic_service_info.capabilitiesMask & + ICP_ACCEL_CAPABILITIES_INLINE) { + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF; + } else { + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + } + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_128; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + default: + QAT_UTILS_LOG("Unknown device type! - %d.\n", + device->deviceType); + return CPA_STATUS_FAIL; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +SalCtrl_CompressionInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U numCompConcurrentReq = 0; + Cpa32U request_ring_id = 0; + Cpa32U response_ring_id = 0; + + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char compMemPool[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *instance_name = NULL; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + Cpa32U msgSize = 0; + char *section = DYN_SEC; + + SAL_SERVICE_GOOD_FOR_INIT(pCompressionService); + + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZING; + + if (CPA_FALSE == pCompressionService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + if (pStatsCollection == NULL) { + return CPA_STATUS_FAIL; + } + + /* Get Config Info: Accel Num, bank Num, packageID, + coreAffinity, nodeAffinity and response mode + */ + + pCompressionService->acceleratorNum = 0; + + /* Initialise device specific compression data */ + SalCtrl_CompressionInit_CompData(device, pCompressionService); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "BankNumber", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + + pCompressionService->bankNum = + Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "IsPolled", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + pCompressionService->isPolled = + (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* User instances only support poll and epoll mode */ + if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled) { + QAT_UTILS_LOG( + "IsPolled %u is not supported for user instance %s.\n", + pCompressionService->isPolled, + temp_string); + return CPA_STATUS_FAIL; + } + + if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { + rx_resp_type = ICP_RESP_TYPE_POLL; + } + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_PKG_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + ADF_DEV_PKG_ID); + return status; + } + pCompressionService->pkgID = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_NODE_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + ADF_DEV_NODE_ID); + return status; + } + pCompressionService->nodeAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* In case of interrupt instance, use the bank affinity set by adf_ctl + * Otherwise, use the instance affinity for backwards compatibility */ + if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled) { + /* Next need to read the [AcceleratorX] section of the config + * file */ + status = Sal_StringParsing("Accelerator", + pCompressionService->acceleratorNum, + "", + temp_string2); + LAC_CHECK_STATUS(status); + + status = Sal_StringParsing("Bank", + pCompressionService->bankNum, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } else { + strncpy(temp_string2, + section, + sizeof(temp_string2) - SAL_NULL_TERM_SIZE); + temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES - + SAL_NULL_TERM_SIZE] = '\0'; + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } + + status = icp_adf_cfgGetParamValue(device, + temp_string2, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + pCompressionService->coreAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "NumConcurrentRequests", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + + numCompConcurrentReq = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + if (validateConcurrRequest(numCompConcurrentReq)) { + QAT_UTILS_LOG( + "Invalid NumConcurrentRequests, valid values are: {64, 128, 256, ... 32768, 65536}.\n"); + return CPA_STATUS_FAIL; + } + + /* ADF does not allow us to completely fill the ring for batch requests + */ + pCompressionService->maxNumCompConcurrentReq = + (numCompConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); + + /* 1. Create transport handles */ + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "RingTx", + temp_string); + LAC_CHECK_STATUS(status); + + msgSize = LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCompressionService->acceleratorNum, + pCompressionService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_DC), + NULL, + ICP_RESP_TYPE_NONE, + numCompConcurrentReq, + msgSize, + (icp_comms_trans_handle *)&( + pCompressionService->trans_handle_compression_tx)); + LAC_CHECK_STATUS(status); + + if (icp_adf_transGetRingNum( + pCompressionService->trans_handle_compression_tx, + &request_ring_id) != CPA_STATUS_SUCCESS) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + QAT_UTILS_LOG("Failed to get DC TX ring number.\n"); + return CPA_STATUS_FAIL; + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "RingRx", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + return status; + } + + msgSize = LAC_QAT_DC_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCompressionService->acceleratorNum, + pCompressionService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_NONE), + (icp_trans_callback)dcCompression_ProcessCallback, + rx_resp_type, + numCompConcurrentReq, + msgSize, + (icp_comms_trans_handle *)&( + pCompressionService->trans_handle_compression_rx)); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + return status; + } + + if (icp_adf_transGetRingNum( + pCompressionService->trans_handle_compression_rx, + &response_ring_id) != CPA_STATUS_SUCCESS) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + QAT_UTILS_LOG("Failed to get DC RX ring number.\n"); + return CPA_STATUS_FAIL; + } + + /* 2. Allocates memory pools */ + + /* Valid initialisation value for a pool ID */ + pCompressionService->compression_mem_pool = LAC_MEM_POOL_INIT_POOL_ID; + + status = Sal_StringParsing( + "Comp", + pCompressionService->generic_service_info.instance, + "_MemPool", + compMemPool); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + + status = Lac_MemPoolCreate(&pCompressionService->compression_mem_pool, + compMemPool, + (numCompConcurrentReq + 1), + sizeof(dc_compression_cookie_t), + LAC_64BYTE_ALIGNMENT, + CPA_FALSE, + pCompressionService->nodeAffinity); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + + /* Init compression statistics */ + status = dcStatsInit(pCompressionService); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy(pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { + /* Get instance name for stats */ + instance_name = LAC_OS_MALLOC(ADF_CFG_MAX_VAL_LEN_IN_BYTES); + if (NULL == instance_name) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return CPA_STATUS_RESOURCE; + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "Name", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return status; + } + status = icp_adf_cfgGetParamValue(device, + section, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return status; + } + + snprintf(instance_name, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%s", + adfGetParam); + + pCompressionService->debug_file = + LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == pCompressionService->debug_file) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return CPA_STATUS_RESOURCE; + } + + memset(pCompressionService->debug_file, + 0, + sizeof(debug_file_info_t)); + pCompressionService->debug_file->name = instance_name; + pCompressionService->debug_file->seq_read = + SalCtrl_CompresionDebug; + pCompressionService->debug_file->private_data = + pCompressionService; + pCompressionService->debug_file->parent = + pCompressionService->generic_service_info.debug_parent_dir; + + status = icp_adf_debugAddFile(device, + pCompressionService->debug_file); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + LAC_OS_FREE(pCompressionService->debug_file); + return status; + } + } + pCompressionService->generic_service_info.stats = pStatsCollection; + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZED; + + return status; +} + +CpaStatus +SalCtrl_CompressionStart(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + + if (SAL_SERVICE_STATE_INITIALIZED != + pCompressionService->generic_service_info.state) { + QAT_UTILS_LOG("Not in the correct state to call start.\n"); + return CPA_STATUS_FAIL; + } + /**************************************************************/ + /* Obtain Extended Features. I.e. Compress And Verify */ + /**************************************************************/ + pCompressionService->generic_service_info.dcExtendedFeatures = + device->dcExtendedFeatures; + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RUNNING; + + return status; +} + +CpaStatus +SalCtrl_CompressionStop(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + + if (SAL_SERVICE_STATE_RUNNING != + pCompressionService->generic_service_info.state) { + QAT_UTILS_LOG("Not in the correct state to call stop.\n"); + return CPA_STATUS_FAIL; + } + + if (icp_adf_is_dev_in_reset(device)) { + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RESTARTING; + return CPA_STATUS_SUCCESS; + } + + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTTING_DOWN; + return CPA_STATUS_RETRY; +} + +CpaStatus +SalCtrl_CompressionShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + + if ((SAL_SERVICE_STATE_INITIALIZED != + pCompressionService->generic_service_info.state) && + (SAL_SERVICE_STATE_SHUTTING_DOWN != + pCompressionService->generic_service_info.state) && + (SAL_SERVICE_STATE_RESTARTING != + pCompressionService->generic_service_info.state)) { + QAT_UTILS_LOG("Not in the correct state to call shutdown.\n"); + return CPA_STATUS_FAIL; + } + + Lac_MemPoolDestroy(pCompressionService->compression_mem_pool); + + status = icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + LAC_CHECK_STATUS(status); + + status = icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_CHECK_STATUS(status); + + if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { + /* Clean stats */ + if (NULL != pCompressionService->debug_file) { + icp_adf_debugRemoveFile( + pCompressionService->debug_file); + LAC_OS_FREE(pCompressionService->debug_file->name); + LAC_OS_FREE(pCompressionService->debug_file); + pCompressionService->debug_file = NULL; + } + } + pCompressionService->generic_service_info.stats = NULL; + dcStatsFree(pCompressionService); + + if (icp_adf_is_dev_in_reset(device)) { + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RESTARTING; + return CPA_STATUS_SUCCESS; + } + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTDOWN; + return status; +} + +CpaStatus +cpaDcGetStatusText(const CpaInstanceHandle dcInstance, + const CpaStatus errStatus, + Cpa8S *pStatusText) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pStatusText); + + switch (errStatus) { + case CPA_STATUS_SUCCESS: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); + break; + case CPA_STATUS_FAIL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); + break; + case CPA_STATUS_RETRY: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); + break; + case CPA_STATUS_RESOURCE: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); + break; + case CPA_STATUS_INVALID_PARAM: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); + break; + case CPA_STATUS_FATAL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); + break; + case CPA_STATUS_UNSUPPORTED: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_UNSUPPORTED); + break; + default: + status = CPA_STATUS_INVALID_PARAM; + break; + } + + return status; +} + +CpaStatus +cpaDcGetNumIntermediateBuffers(CpaInstanceHandle dcInstance, + Cpa16U *pNumBuffers) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pNumBuffers); + + pService = (sal_compression_service_t *)insHandle; + *pNumBuffers = pService->numInterBuffs; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcStartInstance(CpaInstanceHandle instanceHandle, + Cpa16U numBuffers, + CpaBufferList **pIntermediateBufferPtrsArray) +{ + icp_qat_addr_width_t *pInterBuffPtrsArray = NULL; + icp_qat_addr_width_t pArrayBufferListDescPhyAddr = 0; + icp_qat_addr_width_t bufListDescPhyAddr; + icp_qat_addr_width_t bufListAlignedPhyAddr; + CpaFlatBuffer *pClientCurrFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa16U bufferIndex = 0; + Cpa32U numFlatBuffers = 0; + Cpa64U clientListSize = 0; + CpaBufferList *pClientCurrentIntermediateBuffer = NULL; + Cpa32U bufferIndex2 = 0; + CpaBufferList **pTempIntermediateBufferPtrsArray; + Cpa64U lastClientListSize = 0; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + LAC_CHECK_NULL_PARAM(insHandle); + + status = cpaDcInstanceGetInfo2(insHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get instance info.\n"); + return status; + } + + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + if (NULL == pIntermediateBufferPtrsArray) { + /* Increment dev ref counter and return - DRAM is not used */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; + } + + if (0 == numBuffers) { + /* Increment dev ref counter and return - DRAM is not used */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + + if ((numBuffers > 0) && (NULL == pIntermediateBufferPtrsArray)) { + QAT_UTILS_LOG("Invalid Intermediate Buffers Array pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check number of intermediate buffers allocated by user */ + if ((pService->numInterBuffs != numBuffers)) { + QAT_UTILS_LOG("Invalid number of buffers\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pTempIntermediateBufferPtrsArray = pIntermediateBufferPtrsArray; + for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { + if (NULL == *pTempIntermediateBufferPtrsArray) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Buffer List pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (NULL == (*pTempIntermediateBufferPtrsArray)->pBuffers) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Flat Buffer descriptor pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (NULL == + (*pTempIntermediateBufferPtrsArray)->pPrivateMetaData) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Private MetaData descriptor pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + clientListSize = 0; + for (bufferIndex2 = 0; bufferIndex2 < + (*pTempIntermediateBufferPtrsArray)->numBuffers; + bufferIndex2++) { + + if ((0 != + (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .dataLenInBytes) && + NULL == + (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .pData) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Flat Buffer pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + clientListSize += (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .dataLenInBytes; + } + + if (bufferIndex != 0) { + if (lastClientListSize != clientListSize) { + QAT_UTILS_LOG( + "SGLs have to be of the same size.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + lastClientListSize = clientListSize; + } + pTempIntermediateBufferPtrsArray++; + } + + /* Allocate array of physical pointers to icp_buffer_list_desc_t */ + status = LAC_OS_CAMALLOC(&pInterBuffPtrsArray, + (numBuffers * sizeof(icp_qat_addr_width_t)), + LAC_64BYTE_ALIGNMENT, + pService->nodeAffinity); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not allocate Intermediate Buffers array.\n"); + return status; + } + + /* Get physical address of the intermediate buffer pointers array */ + pArrayBufferListDescPhyAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_INTERNAL(pInterBuffPtrsArray)); + + pService->pInterBuffPtrsArray = pInterBuffPtrsArray; + pService->pInterBuffPtrsArrayPhyAddr = pArrayBufferListDescPhyAddr; + + /* Get the full size of the buffer list */ + /* Assumption: all the SGLs allocated by the user have the same size */ + clientListSize = 0; + for (bufferIndex = 0; + bufferIndex < (*pIntermediateBufferPtrsArray)->numBuffers; + bufferIndex++) { + clientListSize += ((*pIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex] + .dataLenInBytes); + } + pService->minInterBuffSizeInBytes = clientListSize; + + for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { + + /* Get pointer to the client Intermediate Buffer List + * (CpaBufferList) */ + pClientCurrentIntermediateBuffer = + *pIntermediateBufferPtrsArray; + + /* Get number of flat buffers in the buffer list */ + numFlatBuffers = pClientCurrentIntermediateBuffer->numBuffers; + + /* Get pointer to the client array of CpaFlatBuffers */ + pClientCurrFlatBuffer = + pClientCurrentIntermediateBuffer->pBuffers; + + /* Calculate Physical address of current private SGL */ + bufListDescPhyAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), + pClientCurrentIntermediateBuffer->pPrivateMetaData); + if (bufListDescPhyAddr == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + /* Align SGL physical address */ + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + /* Set physical address of the Intermediate Buffer SGL in the + * SGLs array + */ + *pInterBuffPtrsArray = + LAC_MEM_CAST_PTR_TO_UINT64(bufListAlignedPhyAddr); + + /* Calculate (virtual) offset to the buffer list descriptor */ + pBufferListDesc = + (icp_buffer_list_desc_t + *)((LAC_ARCH_UINT)pClientCurrentIntermediateBuffer + ->pPrivateMetaData + + (LAC_ARCH_UINT)(bufListAlignedPhyAddr - + bufListDescPhyAddr)); + + /* Set number of flat buffers in the physical Buffer List + * descriptor */ + pBufferListDesc->numBuffers = numFlatBuffers; + + /* Go past the Buffer List descriptor to the list of buffer + * descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + /* Loop for each flat buffer in the SGL */ + while (0 != numFlatBuffers) { + /* Set length of the current flat buffer */ + pCurrFlatBufDesc->dataLenInBytes = + pClientCurrFlatBuffer->dataLenInBytes; + + /* Set physical address of the flat buffer */ + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pClientCurrFlatBuffer->pData)); + + if (pCurrFlatBufDesc->phyBuffer == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the flat buffer.\n"); + return CPA_STATUS_FAIL; + } + + pCurrFlatBufDesc++; + pClientCurrFlatBuffer++; + numFlatBuffers--; + } + pIntermediateBufferPtrsArray++; + pInterBuffPtrsArray++; + } + + pService->generic_service_info.isInstanceStarted = CPA_TRUE; + + /* Increment dev ref counter */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcStopInstance(CpaInstanceHandle instanceHandle) +{ + CpaInstanceHandle insHandle = NULL; + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + pService = (sal_compression_service_t *)insHandle; + + /* Free Intermediate Buffer Pointers Array */ + if (pService->pInterBuffPtrsArray != NULL) { + LAC_OS_CAFREE(pService->pInterBuffPtrsArray); + pService->pInterBuffPtrsArray = 0; + } + + pService->pInterBuffPtrsArrayPhyAddr = 0; + + status = cpaDcInstanceGetInfo2(insHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get instance info.\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance.\n"); + return CPA_STATUS_FAIL; + } + + pService->generic_service_info.isInstanceStarted = CPA_FALSE; + + /* Decrement dev ref counter */ + icp_qa_dev_put(dev); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGetNumInstances(Cpa16U *pNumInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(pNumInstances); + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + num_accel_dev = 0; + + /* Get ADF to return accel_devs with dc enabled */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, pAdfInsts, &num_accel_dev); + if (CPA_STATUS_SUCCESS == status) { + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = + base_addr->compression_services; + while (NULL != list_temp) { + num++; + list_temp = + SalList_next(list_temp); + } + } + } + } + + *pNumInstances = num; + } + + free(pAdfInsts, M_QAT); + + return status; +} + +CpaStatus +cpaDcGetInstances(Cpa16U numInstances, CpaInstanceHandle *dcInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U index = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(dcInstances); + if (0 == numInstances) { + QAT_UTILS_LOG("numInstances is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + num_accel_dev = 0; + /* Get ADF to return accel_devs with dc enabled */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, pAdfInsts, &num_accel_dev); + + if (CPA_STATUS_SUCCESS == status) { + /* First check the number of instances in the system */ + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = + base_addr->compression_services; + while (NULL != list_temp) { + if (index > + (numInstances - 1)) { + break; + } + + dcInstances[index] = + SalList_getObject( + list_temp); + list_temp = + SalList_next(list_temp); + index++; + } + } + } + } + + if (numInstances > index) { + QAT_UTILS_LOG("Only %d dc instances available.\n", + index); + status = CPA_STATUS_RESOURCE; + } + } + + if (CPA_STATUS_SUCCESS == status) { + index = 0; + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + /* Note dev_addr cannot be NULL here as numInstances=0 + is not valid and if dev_addr=NULL then index=0 (which + is less than numInstances and status is set to + _RESOURCE + above */ + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = base_addr->compression_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + + dcInstances[index] = + SalList_getObject(list_temp); + list_temp = SalList_next(list_temp); + index++; + } + } + } + } + + free(pAdfInsts, M_QAT); + + return status; +} + +CpaStatus +cpaDcInstanceGetInfo2(const CpaInstanceHandle instanceHandle, + CpaInstanceInfo2 *pInstanceInfo2) +{ + sal_compression_service_t *pCompressionService = NULL; + CpaInstanceHandle insHandle = NULL; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 }; + char valStr[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *section = DYN_SEC; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pInstanceInfo2); + + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + pInstanceInfo2->accelerationServiceType = + CPA_ACC_SVC_TYPE_DATA_COMPRESSION; + + snprintf((char *)pInstanceInfo2->vendorName, + CPA_INST_VENDOR_NAME_SIZE, + "%s", + SAL_INFO2_VENDOR_NAME); + pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo2->swVersion, + CPA_INST_SW_VERSION_SIZE, + "Version %d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); + pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; + + /* Note we can safely read the contents of the compression service + instance + here because icp_amgr_getAccelDevByCapabilities() only returns devs + that have started */ + pCompressionService = (sal_compression_service_t *)insHandle; + pInstanceInfo2->physInstId.packageId = pCompressionService->pkgID; + pInstanceInfo2->physInstId.acceleratorId = + pCompressionService->acceleratorNum; + pInstanceInfo2->physInstId.executionEngineId = 0; + pInstanceInfo2->physInstId.busAddress = + icp_adf_get_busAddress(pInstanceInfo2->physInstId.packageId); + + /* set coreAffinity to zero before use */ + LAC_OS_BZERO(pInstanceInfo2->coreAffinity, + sizeof(pInstanceInfo2->coreAffinity)); + CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, + pCompressionService->coreAffinity); + + pInstanceInfo2->nodeAffinity = pCompressionService->nodeAffinity; + + if (CPA_TRUE == + pCompressionService->generic_service_info.isInstanceStarted) { + pInstanceInfo2->operState = CPA_OPER_STATE_UP; + } else { + pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; + } + + pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; + + if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { + pInstanceInfo2->isPolled = CPA_TRUE; + } else { + pInstanceInfo2->isPolled = CPA_FALSE; + } + + pInstanceInfo2->isOffloaded = CPA_TRUE; + /* Get the instance name and part name from the config file */ + dev = icp_adf_getAccelDevByAccelId(pCompressionService->pkgID); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance.\n"); + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + return CPA_STATUS_FAIL; + } + snprintf((char *)pInstanceInfo2->partName, + CPA_INST_PART_NAME_SIZE, + SAL_INFO2_PART_NAME, + dev->deviceName); + pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; + + if (CPA_FALSE == pCompressionService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "Name", + keyStr); + LAC_CHECK_STATUS(status); + status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); + LAC_CHECK_STATUS(status); + strncpy((char *)pInstanceInfo2->instName, + valStr, + sizeof(pInstanceInfo2->instName) - 1); + pInstanceInfo2->instName[CPA_INST_NAME_SIZE - 1] = '\0'; + +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation" +#endif + snprintf((char *)pInstanceInfo2->instID, + CPA_INST_ID_SIZE, + "%s_%s", + section, + valStr); +#if __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcQueryCapabilities(CpaInstanceHandle dcInstance, + CpaDcInstanceCapabilities *pInstanceCapabilities) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + Cpa32U capabilitiesMask = 0; + dc_extd_ftrs_t *pExtendedFtrs = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + if (NULL == insHandle) { + QAT_UTILS_LOG("Can not get the instance.\n"); + return CPA_STATUS_FAIL; + } + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pInstanceCapabilities); + + memset(pInstanceCapabilities, 0, sizeof(CpaDcInstanceCapabilities)); + + capabilitiesMask = pService->generic_service_info.capabilitiesMask; + + /* Set compression capabilities */ + if (capabilitiesMask & ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY) { + pInstanceCapabilities->integrityCrcs = CPA_TRUE; + } + + pInstanceCapabilities->endOfLastBlock = CPA_TRUE; + pInstanceCapabilities->statefulDeflateCompression = CPA_FALSE; + pInstanceCapabilities->statefulDeflateDecompression = CPA_TRUE; + pInstanceCapabilities->statelessDeflateCompression = CPA_TRUE; + pInstanceCapabilities->statelessDeflateDecompression = CPA_TRUE; + pInstanceCapabilities->checksumCRC32 = CPA_TRUE; + pInstanceCapabilities->checksumAdler32 = CPA_TRUE; + pInstanceCapabilities->dynamicHuffman = CPA_TRUE; + pInstanceCapabilities->precompiledHuffman = CPA_FALSE; + pInstanceCapabilities->dynamicHuffmanBufferReq = CPA_TRUE; + pInstanceCapabilities->autoSelectBestHuffmanTree = CPA_TRUE; + + pInstanceCapabilities->validWindowSizeMaskCompression = + pService->comp_device_data.windowSizeMask; + pInstanceCapabilities->validWindowSizeMaskDecompression = + pService->comp_device_data.windowSizeMask; + pExtendedFtrs = (dc_extd_ftrs_t *)&( + ((sal_service_t *)insHandle)->dcExtendedFeatures); + pInstanceCapabilities->batchAndPack = CPA_FALSE; + pInstanceCapabilities->compressAndVerify = + (CpaBoolean)pExtendedFtrs->is_cnv; + pInstanceCapabilities->compressAndVerifyStrict = CPA_TRUE; + pInstanceCapabilities->compressAndVerifyAndRecover = + (CpaBoolean)pExtendedFtrs->is_cnvnr; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcSetAddressTranslation(const CpaInstanceHandle instanceHandle, + CpaVirtualToPhysical virtual2Physical) +{ + sal_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(virtual2Physical); + + pService = (sal_service_t *)insHandle; + + pService->virt2PhysClient = virtual2Physical; + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaDcCommon + * Data compression specific polling function which polls a DC instance. + *****************************************************************************/ + +CpaStatus +icp_sal_DcPollInstance(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *dc_handle = NULL; + sal_service_t *gen_handle = NULL; + icp_comms_trans_handle trans_hndTable[DC_NUM_RX_RINGS]; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + dc_handle = (sal_compression_service_t *)dcGetFirstHandle(); + } else { + dc_handle = (sal_compression_service_t *)instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(dc_handle); + SAL_RUNNING_CHECK(dc_handle); + + gen_handle = &(dc_handle->generic_service_info); + if (SAL_SERVICE_TYPE_COMPRESSION != gen_handle->type) { + QAT_UTILS_LOG("Instance handle type is incorrect.\n"); + return CPA_STATUS_FAIL; + } + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + trans_hndTable[0] = dc_handle->trans_handle_compression_rx; + + /* Call adf to do the polling. */ + status = icp_adf_pollInstance(trans_hndTable, + DC_NUM_RX_RINGS, + response_quota); + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaDcCommon + *****************************************************************************/ +CpaStatus +cpaDcInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaDcInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *gen_handle = instanceHandle; + + LAC_CHECK_NULL_PARAM(gen_handle); + gen_handle->notification_cb = pInstanceNotificationCb; + gen_handle->cb_tag = pCallbackTag; + return status; +} + +CpaInstanceHandle +dcGetFirstHandle(void) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = { 0 }; + CpaInstanceHandle dcInst = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U i, num_dc = 0; + + /* Only need 1 dev with compression enabled - so check all devices */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, adfInsts, &num_dc); + if ((0 == num_dc) || (CPA_STATUS_SUCCESS != status)) { + QAT_UTILS_LOG( + "No compression devices enabled in the system.\n"); + return dcInst; + } + + for (i = 0; i < num_dc; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = base_addr->compression_services; + if (NULL != list_temp) { + dcInst = SalList_getObject(list_temp); + break; + } + } + } + } + return dcInst; +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c b/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c new file mode 100644 index 00000000000..d51cc1bcace --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_create_services.c + * + * @defgroup SalCtrl Service Access Layer Controller + * + * @ingroup SalCtrl + * + * @description + * This file contains the main function to create a specific service. + * + *****************************************************************************/ + +#include "cpa.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "qat_utils.h" +#include "lac_list.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +#include "icp_qat_fw_la.h" +#include "lac_sym_qat.h" +#include "sal_types_compression.h" +#include "lac_sal_types_crypto.h" + +#include "icp_adf_init.h" + +#include "lac_sal.h" +#include "lac_sal_ctrl.h" + +CpaStatus +SalCtrl_ServiceCreate(sal_service_type_t serviceType, + Cpa32U instance, + sal_service_t **ppInst) +{ + sal_crypto_service_t *pCrypto_service = NULL; + sal_compression_service_t *pCompression_service = NULL; + + switch ((sal_service_type_t)serviceType) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + case SAL_SERVICE_TYPE_CRYPTO_SYM: + case SAL_SERVICE_TYPE_CRYPTO: { + pCrypto_service = + malloc(sizeof(sal_crypto_service_t), M_QAT, M_WAITOK); + + /* Zero memory */ + memset(pCrypto_service, 0, sizeof(sal_crypto_service_t)); + + pCrypto_service->generic_service_info.type = + (sal_service_type_t)serviceType; + pCrypto_service->generic_service_info.state = + SAL_SERVICE_STATE_UNINITIALIZED; + pCrypto_service->generic_service_info.instance = instance; + + pCrypto_service->generic_service_info.init = SalCtrl_CryptoInit; + pCrypto_service->generic_service_info.start = + SalCtrl_CryptoStart; + pCrypto_service->generic_service_info.stop = SalCtrl_CryptoStop; + pCrypto_service->generic_service_info.shutdown = + SalCtrl_CryptoShutdown; + + *(ppInst) = &(pCrypto_service->generic_service_info); + + return CPA_STATUS_SUCCESS; + } + case SAL_SERVICE_TYPE_COMPRESSION: { + pCompression_service = + malloc(sizeof(sal_compression_service_t), M_QAT, M_WAITOK); + + /* Zero memory */ + memset(pCompression_service, + 0, + sizeof(sal_compression_service_t)); + + pCompression_service->generic_service_info.type = + (sal_service_type_t)serviceType; + pCompression_service->generic_service_info.state = + SAL_SERVICE_STATE_UNINITIALIZED; + pCompression_service->generic_service_info.instance = instance; + + pCompression_service->generic_service_info.init = + SalCtrl_CompressionInit; + pCompression_service->generic_service_info.start = + SalCtrl_CompressionStart; + pCompression_service->generic_service_info.stop = + SalCtrl_CompressionStop; + pCompression_service->generic_service_info.shutdown = + SalCtrl_CompressionShutdown; + + *(ppInst) = &(pCompression_service->generic_service_info); + return CPA_STATUS_SUCCESS; + } + + default: { + QAT_UTILS_LOG("Not a valid service type\n"); + (*ppInst) = NULL; + return CPA_STATUS_FAIL; + } + } +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c b/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c new file mode 100644 index 00000000000..c97d36103c2 --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c @@ -0,0 +1,1837 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file sal_crypto.c Instance handling functions for crypto + * + * @ingroup SalCtrl + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_types.h" +#include "cpa_cy_common.h" +#include "cpa_cy_im.h" +#include "cpa_cy_key.h" +#include "cpa_cy_sym.h" + +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_poll.h" +#include "icp_adf_debug.h" + +/* SAL includes */ +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_statistics.h" +#include "lac_common.h" +#include "lac_list.h" +#include "lac_hooks.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym.h" +#include "lac_sym_key.h" +#include "lac_sym_hash.h" +#include "lac_sym_cb.h" +#include "lac_sym_stats.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "sal_string_parse.h" +#include "sal_service_state.h" +#include "icp_sal_poll.h" +#include "lac_sync.h" +#include "lac_sym_qat.h" +#include "icp_sal_versions.h" +#include "icp_sal_user.h" + +#define TH_CY_RX_0 0 +#define TH_CY_RX_1 1 +#define MAX_CY_RX_RINGS 2 + +#define DOUBLE_INCR 2 + +#define TH_SINGLE_RX 0 +#define NUM_CRYPTO_SYM_RX_RINGS 1 +#define NUM_CRYPTO_ASYM_RX_RINGS 1 +#define NUM_CRYPTO_NRBG_RX_RINGS 1 + +static CpaInstanceHandle +Lac_CryptoGetFirstHandle(void) +{ + CpaInstanceHandle instHandle; + instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instHandle) { + instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + if (!instHandle) { + instHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); + } + } + return instHandle; +} + + +/* Function to release the sym handles. */ +static CpaStatus +SalCtrl_SymReleaseTransHandle(sal_service_t *service) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + + if (NULL != pCryptoService->trans_handle_sym_tx) { + status = icp_adf_transReleaseHandle( + pCryptoService->trans_handle_sym_tx); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + if (NULL != pCryptoService->trans_handle_sym_rx) { + status = icp_adf_transReleaseHandle( + pCryptoService->trans_handle_sym_rx); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + return ret_status; +} + + +/* + * @ingroup sal_crypto + * Frees resources (memory and transhandles) if allocated + * + * @param[in] pCryptoService Pointer to sym service instance + * @retval SUCCESS if transhandles released + * successfully. +*/ +static CpaStatus +SalCtrl_SymFreeResources(sal_crypto_service_t *pCryptoService) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Free memory pools if not NULL */ + Lac_MemPoolDestroy(pCryptoService->lac_sym_cookie_pool); + + /* Free misc memory if allocated */ + /* Frees memory allocated for Hmac precomputes */ + LacSymHash_HmacPrecompShutdown(pCryptoService); + /* Free memory allocated for key labels + Also clears key stats */ + LacSymKey_Shutdown(pCryptoService); + /* Free hash lookup table if allocated */ + if (NULL != pCryptoService->pLacHashLookupDefs) { + LAC_OS_FREE(pCryptoService->pLacHashLookupDefs); + } + + /* Free statistics */ + LacSym_StatsFree(pCryptoService); + + /* Free transport handles */ + status = SalCtrl_SymReleaseTransHandle((sal_service_t *)pCryptoService); + return status; +} + + +/** + *********************************************************************** + * @ingroup SalCtrl + * This macro verifies that the status is _SUCCESS + * If status is not _SUCCESS then Sym Instance resources are + * freed before the function returns the error + * + * @param[in] status status we are checking + * + * @return void status is ok (CPA_STATUS_SUCCESS) + * @return status The value in the status parameter is an error one + * + ****************************************************************************/ +#define LAC_CHECK_STATUS_SYM_INIT(status) \ + do { \ + if (CPA_STATUS_SUCCESS != status) { \ + SalCtrl_SymFreeResources(pCryptoService); \ + return status; \ + } \ + } while (0) + + +/* Function that creates the Sym Handles. */ +static CpaStatus +SalCtrl_SymCreateTransHandle(icp_accel_dev_t *device, + sal_service_t *service, + Cpa32U numSymRequests, + char *section) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; + Cpa32U msgSize = 0; + + if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { + rx_resp_type = ICP_RESP_TYPE_POLL; + } + + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + /* Parse Sym ring details */ + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "RingSymTx", + temp_string); + + /* Need to free resources in case not _SUCCESS from here */ + LAC_CHECK_STATUS_SYM_INIT(status); + + msgSize = LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = + icp_adf_transCreateHandle(device, + ICP_TRANS_TYPE_ETR, + section, + pCryptoService->acceleratorNum, + pCryptoService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_A_SYM_HI), + NULL, + ICP_RESP_TYPE_NONE, + numSymRequests, + msgSize, + (icp_comms_trans_handle *)&( + pCryptoService->trans_handle_sym_tx)); + LAC_CHECK_STATUS_SYM_INIT(status); + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "RingSymRx", + temp_string); + LAC_CHECK_STATUS_SYM_INIT(status); + + msgSize = LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCryptoService->acceleratorNum, + pCryptoService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_NONE), + (icp_trans_callback)LacSymQat_SymRespHandler, + rx_resp_type, + numSymRequests, + msgSize, + (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_rx)); + LAC_CHECK_STATUS_SYM_INIT(status); + + return status; +} + +static int +SalCtrl_CryptoDebug(void *private_data, char *data, int size, int offset) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U len = 0; + sal_crypto_service_t *pCryptoService = + (sal_crypto_service_t *)private_data; + + switch (offset) { + case SAL_STATS_SYM: { + CpaCySymStats64 symStats = { 0 }; + if (CPA_TRUE != + pCryptoService->generic_service_info.stats + ->bSymStatsEnabled) { + break; + } + status = cpaCySymQueryStats64(pCryptoService, &symStats); + if (status != CPA_STATUS_SUCCESS) { + LAC_LOG_ERROR("cpaCySymQueryStats64 returned error\n"); + return 0; + } + + /* Engine Info */ + len += snprintf( + data + len, + size - len, + SEPARATOR BORDER + " Statistics for Instance %24s |\n" BORDER + " Symmetric Stats " BORDER + "\n" SEPARATOR, + pCryptoService->debug_file->name); + + /* Session Info */ + len += snprintf( + data + len, + size - len, + BORDER " Sessions Initialized: %16llu " BORDER + "\n" BORDER + " Sessions Removed: %16llu " BORDER + "\n" BORDER + " Session Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)symStats.numSessionsInitialized, + (long long unsigned int)symStats.numSessionsRemoved, + (long long unsigned int)symStats.numSessionErrors); + + /* Session info */ + len += snprintf( + data + len, + size - len, + BORDER " Symmetric Requests: %16llu " BORDER + "\n" BORDER + " Symmetric Request Errors: %16llu " BORDER + "\n" BORDER + " Symmetric Completed: %16llu " BORDER + "\n" BORDER + " Symmetric Completed Errors: %16llu " BORDER + "\n" BORDER + " Symmetric Verify Failures: %16llu " BORDER + "\n", + (long long unsigned int)symStats.numSymOpRequests, + (long long unsigned int)symStats.numSymOpRequestErrors, + (long long unsigned int)symStats.numSymOpCompleted, + (long long unsigned int)symStats.numSymOpCompletedErrors, + (long long unsigned int)symStats.numSymOpVerifyFailures); + break; + } + default: { + len += snprintf(data + len, size - len, SEPARATOR); + return 0; + } + } + return ++offset; +} + + +static CpaStatus +SalCtrl_SymInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U numSymConcurrentReq = 0; + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + + /* Register callbacks for the symmetric services + * (Hash, Cipher, Algorithm-Chaining) (returns void)*/ + LacSymCb_CallbacksRegister(); + + /* Get num concurrent requests from config file */ + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "NumConcurrentSymRequests", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + + numSymConcurrentReq = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + if (CPA_STATUS_FAIL == validateConcurrRequest(numSymConcurrentReq)) { + LAC_LOG_ERROR("Invalid NumConcurrentSymRequests, valid " + "values {64, 128, 256, ... 32768, 65536}"); + return CPA_STATUS_FAIL; + } + + /* ADF does not allow us to completely fill the ring for batch requests + */ + pCryptoService->maxNumSymReqBatch = + (numSymConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); + + /* Create transport handles */ + status = SalCtrl_SymCreateTransHandle(device, + service, + numSymConcurrentReq, + section); + LAC_CHECK_STATUS(status); + + /* Allocates memory pools */ + + /* Create and initialise symmetric cookie memory pool */ + pCryptoService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "SymPool", + temp_string); + LAC_CHECK_STATUS_SYM_INIT(status); + /* Note we need twice (i.e. <<1) the number of sym cookies to + support sym ring pairs (and some, for partials) */ + status = + Lac_MemPoolCreate(&pCryptoService->lac_sym_cookie_pool, + temp_string, + ((numSymConcurrentReq + numSymConcurrentReq + 1) + << 1), + sizeof(lac_sym_cookie_t), + LAC_64BYTE_ALIGNMENT, + CPA_FALSE, + pCryptoService->nodeAffinity); + LAC_CHECK_STATUS_SYM_INIT(status); + /* For all sym cookies fill out the physical address of data that + will be set to QAT */ + Lac_MemPoolInitSymCookiesPhyAddr(pCryptoService->lac_sym_cookie_pool); + + /* Clear stats */ + /* Clears Key stats and allocate memory of SSL and TLS labels + These labels are initialised to standard values */ + status = LacSymKey_Init(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Initialises the hash lookup table*/ + status = LacSymQat_Init(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Fills out content descriptor for precomputes and registers the + hash precompute callback */ + status = LacSymHash_HmacPrecompInit(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Init the Sym stats */ + status = LacSym_StatsInit(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + return status; +} + +static void +SalCtrl_DebugShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + + if (CPA_TRUE == pStatsCollection->bStatsEnabled) { + /* Clean stats */ + if (NULL != pCryptoService->debug_file) { + icp_adf_debugRemoveFile(pCryptoService->debug_file); + LAC_OS_FREE(pCryptoService->debug_file->name); + LAC_OS_FREE(pCryptoService->debug_file); + pCryptoService->debug_file = NULL; + } + } + pCryptoService->generic_service_info.stats = NULL; +} + +static CpaStatus +SalCtrl_DebugInit(icp_accel_dev_t *device, sal_service_t *service) +{ + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *instance_name = NULL; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + CpaStatus status = CPA_STATUS_SUCCESS; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + if (CPA_TRUE == pStatsCollection->bStatsEnabled) { + /* Get instance name for stats */ + instance_name = LAC_OS_MALLOC(ADF_CFG_MAX_VAL_LEN_IN_BYTES); + if (NULL == instance_name) { + return CPA_STATUS_RESOURCE; + } + + status = Sal_StringParsing( + "Cy", + pCryptoService->generic_service_info.instance, + "Name", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(instance_name); + return status; + } + status = icp_adf_cfgGetParamValue(device, + section, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Failed to get %s from configuration file\n", + temp_string); + LAC_OS_FREE(instance_name); + return status; + } + snprintf(instance_name, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%s", + adfGetParam); + + pCryptoService->debug_file = + LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == pCryptoService->debug_file) { + LAC_OS_FREE(instance_name); + return CPA_STATUS_RESOURCE; + } + + memset(pCryptoService->debug_file, + 0, + sizeof(debug_file_info_t)); + pCryptoService->debug_file->name = instance_name; + pCryptoService->debug_file->seq_read = SalCtrl_CryptoDebug; + pCryptoService->debug_file->private_data = pCryptoService; + pCryptoService->debug_file->parent = + pCryptoService->generic_service_info.debug_parent_dir; + + status = + icp_adf_debugAddFile(device, pCryptoService->debug_file); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(instance_name); + LAC_OS_FREE(pCryptoService->debug_file); + return status; + } + } + pCryptoService->generic_service_info.stats = pStatsCollection; + + return status; +} + +static CpaStatus +SalCtr_InstInit(icp_accel_dev_t *device, sal_service_t *service) +{ + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + + /* Get Config Info: Accel Num, bank Num, packageID, + coreAffinity, nodeAffinity and response mode */ + + pCryptoService->acceleratorNum = 0; + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "BankNumber", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->bankNum = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "IsPolled", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->isPolled = + (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* Kernel instances do not support epoll mode */ + if (SAL_RESP_EPOLL_CFG_FILE == pCryptoService->isPolled) { + QAT_UTILS_LOG( + "IsPolled %u is not supported for kernel instance %s", + pCryptoService->isPolled, + temp_string); + return CPA_STATUS_FAIL; + } + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_PKG_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + ADF_DEV_PKG_ID); + return status; + } + pCryptoService->pkgID = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_NODE_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + ADF_DEV_NODE_ID); + return status; + } + pCryptoService->nodeAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + /* In case of interrupt instance, use the bank affinity set by adf_ctl + * Otherwise, use the instance affinity for backwards compatibility */ + if (SAL_RESP_POLL_CFG_FILE != pCryptoService->isPolled) { + /* Next need to read the [AcceleratorX] section of the config + * file */ + status = Sal_StringParsing("Accelerator", + pCryptoService->acceleratorNum, + "", + temp_string2); + LAC_CHECK_STATUS(status); + status = Sal_StringParsing("Bank", + pCryptoService->bankNum, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } else { + strncpy(temp_string2, section, (strlen(section) + 1)); + status = Sal_StringParsing( + "Cy", + pCryptoService->generic_service_info.instance, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } + + status = icp_adf_cfgGetParamValue(device, + temp_string2, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->coreAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /*No Execution Engine in DH895xcc, so make sure it is zero*/ + pCryptoService->executionEngine = 0; + + return status; +} + +/* This function: + * 1. Creates sym and asym transport handles + * 2. Allocates memory pools required by sym and asym services +.* 3. Clears the sym and asym stats counters + * 4. In case service asym or sym is enabled then this function + * only allocates resources for these services. i.e if the + * service asym is enabled then only asym transport handles + * are created and vice versa. + */ +CpaStatus +SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_service_type_t svc_type = service->type; + + SAL_SERVICE_GOOD_FOR_INIT(pCryptoService); + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZING; + + /* Set up the instance parameters such as bank number, + * coreAffinity, pkgId and node affinity etc + */ + status = SalCtr_InstInit(device, service); + LAC_CHECK_STATUS(status); + /* Create debug directory for service */ + status = SalCtrl_DebugInit(device, service); + LAC_CHECK_STATUS(status); + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + status = SalCtrl_SymInit(device, service); + if (CPA_STATUS_SUCCESS != status) { + SalCtrl_DebugShutdown(device, service); + return status; + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + status = SalCtrl_SymInit(device, service); + if (CPA_STATUS_SUCCESS != status) { + SalCtrl_DebugShutdown(device, service); + return status; + } + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + status = CPA_STATUS_FAIL; + break; + } + + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZED; + + return status; +} + +CpaStatus +SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + + if (pCryptoService->generic_service_info.state != + SAL_SERVICE_STATE_INITIALIZED) { + LAC_LOG_ERROR("Not in the correct state to call start\n"); + return CPA_STATUS_FAIL; + } + + pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; + return status; +} + +CpaStatus +SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + + if (SAL_SERVICE_STATE_RUNNING != + pCryptoService->generic_service_info.state) { + LAC_LOG_ERROR("Not in the correct state to call stop"); + } + + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTTING_DOWN; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +SalCtrl_CryptoShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_type_t svc_type = service->type; + + if ((SAL_SERVICE_STATE_INITIALIZED != + pCryptoService->generic_service_info.state) && + (SAL_SERVICE_STATE_SHUTTING_DOWN != + pCryptoService->generic_service_info.state)) { + LAC_LOG_ERROR("Not in the correct state to call shutdown \n"); + return CPA_STATUS_FAIL; + } + + + /* Free memory and transhandles */ + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + if (SalCtrl_SymFreeResources(pCryptoService)) { + status = CPA_STATUS_FAIL; + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + if (SalCtrl_SymFreeResources(pCryptoService)) { + status = CPA_STATUS_FAIL; + } + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + status = CPA_STATUS_FAIL; + break; + } + + SalCtrl_DebugShutdown(device, service); + + pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_SHUTDOWN; + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetStatusText(const CpaInstanceHandle instanceHandle, + CpaStatus errStatus, + Cpa8S *pStatusText) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + + LAC_CHECK_NULL_PARAM(pStatusText); + + switch (errStatus) { + case CPA_STATUS_SUCCESS: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); + break; + case CPA_STATUS_FAIL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); + break; + case CPA_STATUS_RETRY: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); + break; + case CPA_STATUS_RESOURCE: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); + break; + case CPA_STATUS_INVALID_PARAM: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); + break; + case CPA_STATUS_FATAL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); + break; + default: + status = CPA_STATUS_INVALID_PARAM; + break; + } + return status; +} + +void +SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, + CpaCyCapabilitiesInfo *pCapInfo) +{ + memset(pCapInfo, 0, sizeof(CpaCyCapabilitiesInfo)); + + if (SAL_SERVICE_TYPE_CRYPTO == pGenericService->type || + SAL_SERVICE_TYPE_CRYPTO_SYM == pGenericService->type) { + pCapInfo->symSupported = CPA_TRUE; + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN) { + pCapInfo->extAlgchainSupported = CPA_TRUE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_HKDF) { + pCapInfo->hkdfSupported = CPA_TRUE; + } + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_ECEDMONT) { + pCapInfo->ecEdMontSupported = CPA_TRUE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_RANDOM_NUMBER) { + pCapInfo->nrbgSupported = CPA_TRUE; + } + + pCapInfo->drbgSupported = CPA_FALSE; + pCapInfo->randSupported = CPA_FALSE; + pCapInfo->nrbgSupported = CPA_FALSE; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyStartInstance(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compilers. + */ + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instanceHandle) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + status = cpaCyInstanceGetInfo2(instanceHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Can not get instance info\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + pService->generic_service_info.isInstanceStarted = CPA_TRUE; + + /* Increment dev ref counter */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyStopInstance(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compilers. + */ + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(instanceHandle); + + status = cpaCyInstanceGetInfo2(instanceHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Can not get instance info\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + pService = (sal_crypto_service_t *)instanceHandle; + + pService->generic_service_info.isInstanceStarted = CPA_FALSE; + + /* Decrement dev ref counter */ + icp_qa_dev_put(dev); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *gen_handle = instanceHandle; + + + LAC_CHECK_NULL_PARAM(gen_handle); + gen_handle->notification_cb = pInstanceNotificationCb; + gen_handle->cb_tag = pCallbackTag; + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetNumInstances(Cpa16U *pNumInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle cyInstanceHandle; + CpaInstanceInfo2 info; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num_inst = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(pNumInstances); + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + num_accel_dev = 0; + /* Get ADF to return all accel_devs that support either + * symmetric or asymmetric crypto */ + status = icp_amgr_getAllAccelDevByCapabilities( + (ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC), + pAdfInsts, + &num_accel_dev); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("No support for crypto\n"); + *pNumInstances = 0; + free(pAdfInsts, M_QAT); + return status; + } + + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL == dev_addr || NULL == dev_addr->pSalHandle) { + continue; + } + + base_addr = dev_addr->pSalHandle; + list_temp = base_addr->crypto_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + list_temp = base_addr->asym_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + list_temp = base_addr->sym_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + } + *pNumInstances = num_inst; + free(pAdfInsts, M_QAT); + + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetInstances(Cpa16U numInstances, CpaInstanceHandle *pCyInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle cyInstanceHandle; + CpaInstanceInfo2 info; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num_allocated_instances = 0; + Cpa16U index = 0; + Cpa16U i = 0; + + + LAC_CHECK_NULL_PARAM(pCyInstances); + if (0 == numInstances) { + LAC_INVALID_PARAM_LOG("NumInstances is 0"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get the number of crypto instances */ + status = cpaCyGetNumInstances(&num_allocated_instances); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + if (numInstances > num_allocated_instances) { + QAT_UTILS_LOG("Only %d crypto instances available\n", + num_allocated_instances); + return CPA_STATUS_RESOURCE; + } + + /* Get the number of accel devices in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + num_accel_dev = 0; + /* Get ADF to return all accel_devs that support either + * symmetric or asymmetric crypto */ + status = icp_amgr_getAllAccelDevByCapabilities( + (ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC), + pAdfInsts, + &num_accel_dev); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("No support for crypto\n"); + free(pAdfInsts, M_QAT); + return status; + } + + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + /* Note dev_addr cannot be NULL here as numInstances = 0 + * is not valid and if dev_addr = NULL then index = 0 (which + * is less than numInstances and status is set to _RESOURCE + * above + */ + base_addr = dev_addr->pSalHandle; + if (NULL == base_addr) { + continue; + } + list_temp = base_addr->crypto_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + list_temp = base_addr->asym_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + list_temp = base_addr->sym_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + } + free(pAdfInsts, M_QAT); + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle_in, + struct _CpaInstanceInfo *pInstanceInfo) +{ + CpaInstanceHandle instanceHandle = NULL; + sal_crypto_service_t *pCryptoService = NULL; + sal_service_t *pGenericService = NULL; + + Cpa8U name[CPA_INST_NAME_SIZE] = + "Intel(R) DH89XXCC instance number: %02x, type: Crypto"; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + LAC_CHECK_NULL_PARAM(pInstanceInfo); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pCryptoService = (sal_crypto_service_t *)instanceHandle; + + pInstanceInfo->type = CPA_INSTANCE_TYPE_CRYPTO; + + /* According to cpa.h instance state is initialized and ready for use + * or shutdown. Therefore need to map our running state to initialised + * or shutdown */ + if (SAL_SERVICE_STATE_RUNNING == + pCryptoService->generic_service_info.state) { + pInstanceInfo->state = CPA_INSTANCE_STATE_INITIALISED; + } else { + pInstanceInfo->state = CPA_INSTANCE_STATE_SHUTDOWN; + } + + pGenericService = (sal_service_t *)instanceHandle; + snprintf((char *)pInstanceInfo->name, + CPA_INST_NAME_SIZE, + (char *)name, + pGenericService->instance); + + pInstanceInfo->name[CPA_INST_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo->version, + CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES, + "%d.%d", + CPA_CY_API_VERSION_NUM_MAJOR, + CPA_CY_API_VERSION_NUM_MINOR); + + pInstanceInfo->version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES - 1] = + '\0'; + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle_in, + CpaInstanceInfo2 *pInstanceInfo2) +{ + CpaInstanceHandle instanceHandle = NULL; + sal_crypto_service_t *pCryptoService = NULL; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 }; + char valStr[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *section = DYN_SEC; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + LAC_CHECK_NULL_PARAM(pInstanceInfo2); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_CRYPTO; + snprintf((char *)pInstanceInfo2->vendorName, + CPA_INST_VENDOR_NAME_SIZE, + "%s", + SAL_INFO2_VENDOR_NAME); + pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo2->swVersion, + CPA_INST_SW_VERSION_SIZE, + "Version %d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); + pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; + + /* Note we can safely read the contents of the crypto service instance + here because icp_amgr_getAllAccelDevByCapabilities() only returns + devs + that have started */ + pCryptoService = (sal_crypto_service_t *)instanceHandle; + pInstanceInfo2->physInstId.packageId = pCryptoService->pkgID; + pInstanceInfo2->physInstId.acceleratorId = + pCryptoService->acceleratorNum; + pInstanceInfo2->physInstId.executionEngineId = + pCryptoService->executionEngine; + pInstanceInfo2->physInstId.busAddress = + icp_adf_get_busAddress(pInstanceInfo2->physInstId.packageId); + + /*set coreAffinity to zero before use */ + LAC_OS_BZERO(pInstanceInfo2->coreAffinity, + sizeof(pInstanceInfo2->coreAffinity)); + CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, + pCryptoService->coreAffinity); + pInstanceInfo2->nodeAffinity = pCryptoService->nodeAffinity; + + if (SAL_SERVICE_STATE_RUNNING == + pCryptoService->generic_service_info.state) { + pInstanceInfo2->operState = CPA_OPER_STATE_UP; + } else { + pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; + } + + pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; + if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { + pInstanceInfo2->isPolled = CPA_TRUE; + } else { + pInstanceInfo2->isPolled = CPA_FALSE; + } + pInstanceInfo2->isOffloaded = CPA_TRUE; + + /* Get the instance name and part name*/ + dev = icp_adf_getAccelDevByAccelId(pCryptoService->pkgID); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + return CPA_STATUS_FAIL; + } + snprintf((char *)pInstanceInfo2->partName, + CPA_INST_PART_NAME_SIZE, + SAL_INFO2_PART_NAME, + dev->deviceName); + pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "Name", + keyStr); + LAC_CHECK_STATUS(status); + + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); + LAC_CHECK_STATUS(status); + + snprintf((char *)pInstanceInfo2->instName, + CPA_INST_NAME_SIZE, + "%s", + valStr); + snprintf((char *)pInstanceInfo2->instID, + CPA_INST_ID_SIZE, + "%s_%s", + section, + valStr); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ + +CpaStatus +cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle_in, + CpaCyCapabilitiesInfo *pCapInfo) +{ + /* Verify Instance exists */ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pCapInfo); + + SalCtrl_CyQueryCapabilities((sal_service_t *)instanceHandle, pCapInfo); + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCySym + *****************************************************************************/ +CpaStatus +cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle_in, + CpaCySymCapabilitiesInfo *pCapInfo) +{ + sal_crypto_service_t *pCryptoService = NULL; + sal_service_t *pGenericService = NULL; + CpaInstanceHandle instanceHandle = NULL; + + /* Verify Instance exists */ + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instanceHandle) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pCapInfo); + + pCryptoService = (sal_crypto_service_t *)instanceHandle; + pGenericService = &(pCryptoService->generic_service_info); + + memset(pCapInfo, '\0', sizeof(CpaCySymCapabilitiesInfo)); + /* An asym crypto instance does not support sym service */ + if (SAL_SERVICE_TYPE_CRYPTO_ASYM == pGenericService->type) { + return CPA_STATUS_SUCCESS; + } + + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_NULL); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_ARC4); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CTR); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CCM); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_GCM); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_DES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_DES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_CTR); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_KASUMI_F8); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SNOW3G_UEA2); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_F8); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_XTS); + + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_MD5); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA1); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA224); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA256); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA384); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA512); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_XCBC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CCM); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GCM); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_KASUMI_F9); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SNOW3G_UIA2); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CMAC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GMAC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CBC_MAC); + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC) { + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_ZUC_EEA3); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_ZUC_EIA3); + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CHACHA_POLY) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_POLY); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_CHACHA); + } + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM3) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SM3); + } + + pCapInfo->partialPacketSupported = CPA_TRUE; + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SHA3) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_SHA3_EXT) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_224); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_384); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_512); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM4) { + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_CTR); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle_in, + CpaVirtualToPhysical virtual2physical) +{ + + CpaInstanceHandle instanceHandle = NULL; + sal_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(virtual2physical); + + pService = (sal_service_t *)instanceHandle; + + pService->virt2PhysClient = virtual2physical; + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls a crypto instance. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *crypto_handle = NULL; + sal_service_t *gen_handle = NULL; + icp_comms_trans_handle trans_hndTable[MAX_CY_RX_RINGS] = { 0 }; + Cpa32U num_rx_rings = 0; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + crypto_handle = + (sal_crypto_service_t *)Lac_CryptoGetFirstHandle(); + } else { + crypto_handle = (sal_crypto_service_t *)instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(crypto_handle); + SAL_RUNNING_CHECK(crypto_handle); + SAL_CHECK_INSTANCE_TYPE(crypto_handle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + gen_handle = &(crypto_handle->generic_service_info); + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + + switch (gen_handle->type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + trans_hndTable[TH_CY_RX_0] = + crypto_handle->trans_handle_asym_rx; + num_rx_rings = 1; + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; + num_rx_rings = 1; + break; + case SAL_SERVICE_TYPE_CRYPTO: + trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; + trans_hndTable[TH_CY_RX_1] = + crypto_handle->trans_handle_asym_rx; + num_rx_rings = MAX_CY_RX_RINGS; + break; + default: + break; + } + + /* Call adf to do the polling. */ + status = + icp_adf_pollInstance(trans_hndTable, num_rx_rings, response_quota); + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls sym crypto ring. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *crypto_handle = NULL; + icp_comms_trans_handle trans_hndTable[NUM_CRYPTO_SYM_RX_RINGS] = { 0 }; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + crypto_handle = (sal_crypto_service_t *)Lac_GetFirstHandle( + SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + crypto_handle = (sal_crypto_service_t *)instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(crypto_handle); + SAL_CHECK_INSTANCE_TYPE(crypto_handle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + SAL_RUNNING_CHECK(crypto_handle); + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + trans_hndTable[TH_SINGLE_RX] = crypto_handle->trans_handle_sym_rx; + /* Call adf to do the polling. */ + status = icp_adf_pollInstance(trans_hndTable, + NUM_CRYPTO_SYM_RX_RINGS, + response_quota); + return status; +} + + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls an nrbg crypto ring. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollNRBGRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Returns the handle to the first asym crypto instance */ +static CpaInstanceHandle +Lac_GetFirstAsymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], + Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && (NULL != base_addr->asym_services)) { + list_temp = base_addr->asym_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + + return cyInst; +} + +/* Returns the handle to the first sym crypto instance */ +static CpaInstanceHandle +Lac_GetFirstSymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], + Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && (NULL != base_addr->sym_services)) { + list_temp = base_addr->sym_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + + return cyInst; +} + +/* Returns the handle to the first crypto instance + * Note that the crypto instance in this case supports + * both asym and sym services */ +static CpaInstanceHandle +Lac_GetFirstCyHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && + (NULL != base_addr->crypto_services)) { + list_temp = base_addr->crypto_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + return cyInst; +} + +CpaInstanceHandle +Lac_GetFirstHandle(sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = { 0 }; + CpaInstanceHandle cyInst = NULL; + Cpa16U num_cy_dev = 0; + Cpa32U capabilities = 0; + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + break; + case SAL_SERVICE_TYPE_CRYPTO: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + capabilities |= ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + return NULL; + break; + } + /* Only need 1 dev with crypto enabled - so check all devices*/ + status = icp_amgr_getAllAccelDevByEachCapability(capabilities, + adfInsts, + &num_cy_dev); + if ((0 == num_cy_dev) || (CPA_STATUS_SUCCESS != status)) { + LAC_LOG_ERROR("No crypto devices enabled in the system\n"); + return NULL; + } + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + /* Try to find an asym only instance first */ + cyInst = Lac_GetFirstAsymHandle(adfInsts, num_cy_dev); + /* Try to find a cy instance since it also supports asym */ + if (NULL == cyInst) { + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + } + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + /* Try to find a sym only instance first */ + cyInst = Lac_GetFirstSymHandle(adfInsts, num_cy_dev); + /* Try to find a cy instance since it also supports sym */ + if (NULL == cyInst) { + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + /* Try to find a cy instance */ + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + break; + default: + break; + } + if (NULL == cyInst) { + LAC_LOG_ERROR("No remaining crypto instances available\n"); + } + return cyInst; +} + +CpaStatus +icp_sal_NrbgGetInflightRequests(CpaInstanceHandle instanceHandle_in, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + sal_crypto_service_t *crypto_handle = NULL; + + crypto_handle = (sal_crypto_service_t *)instanceHandle; + + LAC_CHECK_NULL_PARAM(crypto_handle); + LAC_CHECK_NULL_PARAM(maxInflightRequests); + LAC_CHECK_NULL_PARAM(numInflightRequests); + SAL_RUNNING_CHECK(crypto_handle); + + return icp_adf_getInflightRequests(crypto_handle->trans_handle_sym_tx, + maxInflightRequests, + numInflightRequests); +} + + +CpaStatus +icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + sal_crypto_service_t *crypto_handle = NULL; + + crypto_handle = (sal_crypto_service_t *)instanceHandle; + + return icp_adf_dp_getInflightRequests( + crypto_handle->trans_handle_sym_tx, + maxInflightRequests, + numInflightRequests); +} + diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c b/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c new file mode 100644 index 00000000000..4a41340dfab --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c @@ -0,0 +1,1344 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_ctrl_services.c + * + * @ingroup SalCtrl + * + * @description + * This file contains the core of the service controller implementation. + * + *****************************************************************************/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_cy_key.h" +#include "cpa_cy_ln.h" +#include "cpa_cy_dh.h" +#include "cpa_cy_dsa.h" +#include "cpa_cy_rsa.h" +#include "cpa_cy_ec.h" +#include "cpa_cy_prime.h" +#include "cpa_cy_sym.h" +#include "cpa_dc.h" + +/* QAT utils includes */ +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_init.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_debug.h" + +/* FW includes */ +#include "icp_qat_fw_la.h" + +/* SAL includes */ +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_hooks.h" +#include "sal_string_parse.h" +#include "lac_common.h" +#include "lac_sal_types.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "icp_sal_versions.h" + +#define MAX_SUBSYSTEM_RETRY 64 + +static char *subsystem_name = "SAL"; +/**< Name used by ADF to identify this component. */ +static char *cy_dir_name = "cy"; +static char *asym_dir_name = "asym"; +static char *sym_dir_name = "sym"; +static char *dc_dir_name = "dc"; +/**< Stats dir names. */ +static char *ver_file_name = "version"; + +static subservice_registation_handle_t sal_service_reg_handle; +/**< Data structure used by ADF to keep a reference to this component. */ + +/* + * @ingroup SalCtrl + * @description + * This function is used to parse the results from ADF + * in response to ServiceEnabled query.The results are + * semi-colon separated. Internally, the bitmask represented + * by the enabled_service is used to track which features are enabled. + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device pointer to icp_accel_dev_t structure + * @param[in] pEnabledServices pointer to memory where enabled services will + * be written. + * @retval Status + */ +CpaStatus +SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *token = NULL; + char *running = NULL; + + *pEnabledServices = 0; + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + "ServicesEnabled", + param_value); + + if (CPA_STATUS_SUCCESS == status) { + running = param_value; + + token = strsep(&running, ";"); + + while (NULL != token) { + do { + if (strncmp(token, "asym", strlen("asym")) == + 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO_ASYM; + break; + } + if (strncmp(token, "sym", strlen("sym")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO_SYM; + break; + } + if (strncmp(token, "cy", strlen("cy")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO; + break; + } + if (strncmp(token, "dc", strlen("dc")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_COMPRESSION; + break; + } + + QAT_UTILS_LOG( + "Error parsing enabled services from ADF.\n"); + return CPA_STATUS_FAIL; + + } while (0); + token = strsep(&running, ";"); + } + } else { + QAT_UTILS_LOG("Failed to get enabled services from ADF.\n"); + } + return status; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to check whether a service is enabled + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] enabled_services It is the bitmask for the enabled services + * param[in] service It is the service we want to check for + */ +CpaBoolean +SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service) +{ + return (CpaBoolean)((enabled_services & (Cpa32U)(service)) != 0); +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to check whether enabled services has associated + * hardware capability support + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device A pointer to an icp_accel_dev_t + * param[in] enabled_services It is the bitmask for the enabled services + */ + +CpaStatus +SalCtrl_GetSupportedServices(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U capabilitiesMask = 0; + + status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask); + + if (CPA_STATUS_SUCCESS == status) { + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || + !(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Crypto service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Asym service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Sym service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_COMPRESSION)) { + QAT_UTILS_LOG( + "Device does not support Compression service.\n"); + status = CPA_STATUS_FAIL; + } + } + } + + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is supported + * on the device. The key difference between this and + * SalCtrl_GetSupportedServices() is that the latter treats it as + * an error if the service is unsupported. + * + * @context + * This can be called anywhere. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device + * param[in] service service or services to check + * + *************************************************************************/ +CpaBoolean +SalCtrl_IsServiceSupported(icp_accel_dev_t *device, + sal_service_type_t service_to_check) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U capabilitiesMask = 0; + CpaBoolean service_supported = CPA_TRUE; + + if (!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_SYM)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_COMPRESSION))) { + QAT_UTILS_LOG("Invalid service type\n"); + service_supported = CPA_FALSE; + } + + status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get device capabilities.\n"); + return CPA_FALSE; + } + + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || + !(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Crypto service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG("Device does not support Asym service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { + QAT_UTILS_LOG("Device does not support Sym service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_COMPRESSION)) { + if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) { + QAT_UTILS_LOG( + "Device does not support Compression service.\n"); + service_supported = CPA_FALSE; + } + } + + return service_supported; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to retrieve how many instances are + * to be configured for process specific service. + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device A pointer to an icp_accel_dev_t + * @param[in] key Represents the parameter's name we want to query + * @param[out] pCount Pointer to memory where num instances will be stored + * @retval status returned status from ADF or _FAIL if number of instances + * is out of range for the device. + */ +static CpaStatus +SalCtrl_GetInstanceCount(icp_accel_dev_t *device, char *key, Cpa32U *pCount) +{ + CpaStatus status = CPA_STATUS_FAIL; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + icpGetProcessName(), + key, + param_value); + if (CPA_STATUS_SUCCESS == status) { + *pCount = + (Cpa32U)(Sal_Strtoul(param_value, NULL, SAL_CFG_BASE_DEC)); + if (*pCount > SAL_MAX_NUM_INSTANCES_PER_DEV) { + QAT_UTILS_LOG("Number of instances is out of range.\n"); + status = CPA_STATUS_FAIL; + } + } + return status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the shutdown function on all the + * service instances. + * It also frees all service instance memory allocated at Init. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown + * function. + * + * @assumptions + * params[in] should not be NULL + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * @param[in] dbg_dir A pointer to the debug directory + * @param[in] svc_type The type of the service instance + * + ****************************************************************************/ +static CpaStatus +SalCtrl_ServiceShutdown(icp_accel_dev_t *device, + sal_list_t **services, + debug_dir_info_t **debug_dir, + sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_list_t *dyn_service = NULL; + sal_service_t *inst = NULL; + + /* Call Shutdown function for each service instance */ + SAL_FOR_EACH(*services, sal_service_t, device, shutdown, status); + + if (*debug_dir) { + icp_adf_debugRemoveDir(*debug_dir); + LAC_OS_FREE(*debug_dir); + *debug_dir = NULL; + } + + if (!icp_adf_is_dev_in_reset(device)) { + dyn_service = *services; + while (dyn_service) { + inst = (sal_service_t *)SalList_getObject(dyn_service); + if (CPA_TRUE == inst->is_dyn) { + icp_adf_putDynInstance(device, + (adf_service_type_t) + svc_type, + inst->instance); + } + dyn_service = SalList_next(dyn_service); + } + /* Free Sal services controller memory */ + SalList_free(services); + } else { + sal_list_t *curr_element = NULL; + sal_service_t *service = NULL; + curr_element = *services; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + service->state = SAL_SERVICE_STATE_RESTARTING; + curr_element = SalList_next(curr_element); + } + } + + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialise the service instances. + * It allocates memory for service instances and invokes the + * Init function on them. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * @param[in] dbg_dir A pointer to the debug directory + * @param[in] dbg_dir_name Name of the debug directory + * @param[in] tail_list SAL's list of services + * @param[in] instance_count Number of instances + * @param[in] svc_type The type of the service instance + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceInit(icp_accel_dev_t *device, + sal_list_t **services, + debug_dir_info_t **dbg_dir, + char *dbg_dir_name, + sal_list_t *tail_list, + Cpa32U instance_count, + sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *pInst = NULL; + Cpa32U i = 0; + debug_dir_info_t *debug_dir = NULL; + + debug_dir = LAC_OS_MALLOC(sizeof(debug_dir_info_t)); + if (NULL == debug_dir) { + QAT_UTILS_LOG("Failed to allocate memory for debug dir.\n"); + return CPA_STATUS_RESOURCE; + } + debug_dir->name = dbg_dir_name; + debug_dir->parent = NULL; + status = icp_adf_debugAddDir(device, debug_dir); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to add debug dir.\n"); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + return status; + } + + if (!icp_adf_is_dev_in_reset(device)) { + for (i = 0; i < instance_count; i++) { + status = SalCtrl_ServiceCreate(svc_type, i, &pInst); + if (CPA_STATUS_SUCCESS != status) { + break; + } + pInst->debug_parent_dir = debug_dir; + pInst->capabilitiesMask = device->accelCapabilitiesMask; + status = SalList_add(services, &tail_list, pInst); + if (CPA_STATUS_SUCCESS != status) { + free(pInst, M_QAT); + } + } + } else { + sal_list_t *curr_element = *services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + service->debug_parent_dir = debug_dir; + + if (CPA_TRUE == service->isInstanceStarted) { + icp_qa_dev_get(device); + } + + curr_element = SalList_next(curr_element); + } + } + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to allocate all instances.\n"); + icp_adf_debugRemoveDir(debug_dir); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + SalList_free(services); + return status; + } + + /* Call init function for each service instance */ + SAL_FOR_EACH(*services, sal_service_t, device, init, status); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to initialise all service instances.\n"); + /* shutdown all instances initialised before error */ + SAL_FOR_EACH_STATE(*services, + sal_service_t, + device, + shutdown, + SAL_SERVICE_STATE_INITIALIZED); + icp_adf_debugRemoveDir(debug_dir); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + SalList_free(services); + return status; + } + /* initialize the debug directory for relevant service */ + *dbg_dir = debug_dir; + + return status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the start function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * + **************************************************************************/ +static CpaStatus +SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Call Start function for each service instance */ + SAL_FOR_EACH(services, sal_service_t, device, start, status); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to start all instances.\n"); + /* stop all instances started before error */ + SAL_FOR_EACH_STATE(services, + sal_service_t, + device, + stop, + SAL_SERVICE_STATE_RUNNING); + return status; + } + + if (icp_adf_is_dev_in_reset(device)) { + sal_list_t *curr_element = services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + if (service->notification_cb) { + service->notification_cb( + service, + service->cb_tag, + CPA_INSTANCE_EVENT_RESTARTED); + } + curr_element = SalList_next(curr_element); + } + } + + return status; +} + +/**************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the stop function on all the + * service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Calling restarting functions */ + if (icp_adf_is_dev_in_reset(device)) { + sal_list_t *curr_element = services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + if (service->notification_cb) { + service->notification_cb( + service, + service->cb_tag, + CPA_INSTANCE_EVENT_RESTARTING); + } + curr_element = SalList_next(curr_element); + } + } + + /* Call Stop function for each service instance */ + SAL_FOR_EACH(services, sal_service_t, device, stop, status); + + return status; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to print hardware and software versions in proc + * filesystem entry via ADF Debug interface + * + * @context + * This functions is called from proc filesystem interface + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] private_data A pointer to a private data passed to the + * function while adding a debug file. + * @param[out] data Pointer to a buffer where version information + * needs to be printed to. + * @param[in] size Size of a buffer pointed by data. + * @param[in] offset Offset in a debug file + * + * @retval 0 This function always returns 0 + */ +static int +SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U len = 0; + icp_accel_dev_t *device = (icp_accel_dev_t *)private_data; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + + len += snprintf( + data + len, + size - len, + SEPARATOR BORDER + " Hardware and Software versions for device %d " BORDER + "\n" SEPARATOR, + device->accelId); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_HW_REV_ID_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Hardware Version: %s %s \n", + param_value, + get_sku_info(device->sku)); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_UOF_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Firmware Version: %s \n", + param_value); + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_MMP_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " MMP Version: %s \n", + param_value); + len += snprintf(data + len, + size - len, + " Driver Version: %d.%d.%d \n", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_LO_COMPATIBLE_DRV_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Lowest Compatible Driver: %s \n", + param_value); + + len += snprintf(data + len, + size - len, + " QuickAssist API CY Version: %d.%d \n", + CPA_CY_API_VERSION_NUM_MAJOR, + CPA_CY_API_VERSION_NUM_MINOR); + len += snprintf(data + len, + size - len, + " QuickAssist API DC Version: %d.%d \n", + CPA_DC_API_VERSION_NUM_MAJOR, + CPA_DC_API_VERSION_NUM_MINOR); + + len += snprintf(data + len, size - len, SEPARATOR); + return 0; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the shutdown function on all the service + * instances. It also frees all service instance memory + * allocated at Init. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Services enabled by user + * + ****************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_t *service_container = (sal_t *)device->pSalHandle; + + if (NULL == service_container) { + QAT_UTILS_LOG("Private data is NULL\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->crypto_services, + &service_container->cy_dir, + SAL_SERVICE_TYPE_CRYPTO); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->asym_services, + &service_container->asym_dir, + SAL_SERVICE_TYPE_CRYPTO_ASYM); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->sym_services, + &service_container->sym_dir, + SAL_SERVICE_TYPE_CRYPTO_SYM); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceShutdown( + device, + &service_container->compression_services, + &service_container->dc_dir, + SAL_SERVICE_TYPE_COMPRESSION); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (service_container->ver_file) { + icp_adf_debugRemoveFile(service_container->ver_file); + LAC_OS_FREE(service_container->ver_file); + service_container->ver_file = NULL; + } + + if (!icp_adf_is_dev_in_reset(device)) { + /* Free container also */ + free(service_container, M_QAT); + device->pSalHandle = NULL; + } + + return ret_status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize the service instances. + * It first checks (via ADF query) which services are enabled in the + * system and the number of each services. + * It then invokes the init function on them which creates the + * instances and allocates memory for them. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Services enabled by user + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + sal_t *service_container = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_list_t *tail_list = NULL; + Cpa32U instance_count = 0; + + status = SalCtrl_GetSupportedServices(device, enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get supported services.\n"); + return status; + } + + if (!icp_adf_is_dev_in_reset(device)) { + service_container = malloc(sizeof(sal_t), M_QAT, M_WAITOK); + device->pSalHandle = service_container; + service_container->asym_services = NULL; + service_container->sym_services = NULL; + service_container->crypto_services = NULL; + service_container->compression_services = NULL; + } else { + service_container = device->pSalHandle; + } + service_container->asym_dir = NULL; + service_container->sym_dir = NULL; + service_container->cy_dir = NULL; + service_container->dc_dir = NULL; + service_container->ver_file = NULL; + + service_container->ver_file = LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == service_container->ver_file) { + free(service_container, M_QAT); + return CPA_STATUS_RESOURCE; + } + + memset(service_container->ver_file, 0, sizeof(debug_file_info_t)); + service_container->ver_file->name = ver_file_name; + service_container->ver_file->seq_read = SalCtrl_VersionDebug; + service_container->ver_file->private_data = device; + service_container->ver_file->parent = NULL; + + status = icp_adf_debugAddFile(device, service_container->ver_file); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(service_container->ver_file); + free(service_container, M_QAT); + return status; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit(device, + &service_container->asym_services, + &service_container->asym_dir, + asym_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO_ASYM); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit(device, + &service_container->sym_services, + &service_container->sym_dir, + sym_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO_SYM); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = + SalCtrl_ServiceInit(device, + &service_container->crypto_services, + &service_container->cy_dir, + cy_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_GetInstanceCount(device, + "NumberDcInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit( + device, + &service_container->compression_services, + &service_container->dc_dir, + dc_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_COMPRESSION); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + return status; + +err_init: + SalCtrl_ServiceEventShutdown(device, enabled_services); + return status; +} + +/**************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the stop function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Enabled services by user + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_t *service_container = device->pSalHandle; + + if (service_container == NULL) { + QAT_UTILS_LOG("Private data is NULL.\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_ServiceStop(device, + service_container->asym_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_ServiceStop(device, + service_container->sym_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceStop(device, + service_container->crypto_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceStop( + device, service_container->compression_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + return ret_status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the start function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Enabled services by user + * + **************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_t *service_container = device->pSalHandle; + + if (service_container == NULL) { + QAT_UTILS_LOG("Private data is NULL.\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_ServiceStart(device, + service_container->asym_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_ServiceStart(device, + service_container->sym_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceStart(device, + service_container->crypto_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceStart( + device, service_container->compression_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + return status; +err_start: + SalCtrl_ServiceEventStop(device, enabled_services); + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is the events handler registered with ADF + * for the QA API services (cy, dc) - kernel and user + * + * @context + * This function is called from an ADF context. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] event Event from ADF + * @param[in] param Parameter used for back compatibility + * + ***********************************************************************/ +static CpaStatus +SalCtrl_ServiceEventHandler(icp_accel_dev_t *device, + icp_adf_subsystemEvent_t event, + void *param) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus stats_status = CPA_STATUS_SUCCESS; + Cpa32U enabled_services = 0; + + status = SalCtrl_GetEnabledServices(device, &enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get enabled services.\n"); + return status; + } + + switch (event) { + case ICP_ADF_EVENT_INIT: { + /* In case there is no QAT SAL needs to call InitStats */ + if (NULL == device->pQatStats) { + status = SalStatistics_InitStatisticsCollection(device); + } + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + status = SalCtrl_ServiceEventInit(device, enabled_services); + break; + } + case ICP_ADF_EVENT_START: { + status = SalCtrl_ServiceEventStart(device, enabled_services); + break; + } + case ICP_ADF_EVENT_STOP: { + status = SalCtrl_ServiceEventStop(device, enabled_services); + break; + } + case ICP_ADF_EVENT_SHUTDOWN: { + status = SalCtrl_ServiceEventShutdown(device, enabled_services); + stats_status = SalStatistics_CleanStatisticsCollection(device); + if (CPA_STATUS_SUCCESS != status || + CPA_STATUS_SUCCESS != stats_status) { + return CPA_STATUS_FAIL; + } + break; + } + default: + status = CPA_STATUS_SUCCESS; + break; + } + return status; +} + +CpaStatus +SalCtrl_AdfServicesRegister(void) +{ + /* Fill out the global sal_service_reg_handle structure */ + sal_service_reg_handle.subserviceEventHandler = + SalCtrl_ServiceEventHandler; + /* Set subsystem name to globally defined name */ + sal_service_reg_handle.subsystem_name = subsystem_name; + + return icp_adf_subsystemRegister(&sal_service_reg_handle); +} + +CpaStatus +SalCtrl_AdfServicesUnregister(void) +{ + return icp_adf_subsystemUnregister(&sal_service_reg_handle); +} + +CpaStatus +SalCtrl_AdfServicesStartedCheck(void) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U retry_num = 0; + CpaBoolean state = CPA_FALSE; + + do { + state = icp_adf_isSubsystemStarted(&sal_service_reg_handle); + retry_num++; + } while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY)); + + if (CPA_FALSE == state) { + QAT_UTILS_LOG("Sal Ctrl failed to start in given time.\n"); + status = CPA_STATUS_FAIL; + } + + return status; +} + +CpaStatus +validateConcurrRequest(Cpa32U numConcurrRequests) +{ + Cpa32U baseReq = SAL_64_CONCURR_REQUESTS; + + if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) { + QAT_UTILS_LOG( + "Invalid numConcurrRequests, it is less than min value.\n"); + return CPA_STATUS_FAIL; + } + + while (SAL_MAX_CONCURR_REQUESTS >= baseReq) { + if (baseReq != numConcurrRequests) { + baseReq = baseReq << 1; + } else { + break; + } + } + if (SAL_MAX_CONCURR_REQUESTS < baseReq) { + QAT_UTILS_LOG( + "Invalid baseReg, it is greater than max value.\n"); + return CPA_STATUS_FAIL; + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_list.c b/sys/dev/qat/qat_api/common/ctrl/sal_list.c new file mode 100644 index 00000000000..022e271c163 --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_list.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_list.c + * + * @ingroup SalCtrl + * + * List implementations for SAL + * + *****************************************************************************/ + +#include "lac_mem.h" +#include "lac_list.h" + +CpaStatus +SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj) +{ + sal_list_t *new_element = NULL; + + if (NULL == *list) { + /* First element in list */ + *list = malloc(sizeof(sal_list_t), M_QAT, M_WAITOK); + (*list)->next = NULL; + (*list)->pObj = pObj; + *tail = *list; + } else { + /* add to tail of the list */ + new_element = malloc(sizeof(sal_list_t), M_QAT, M_WAITOK); + new_element->pObj = pObj; + new_element->next = NULL; + + (*tail)->next = new_element; + + *tail = new_element; + } + + return CPA_STATUS_SUCCESS; +} + +void * +SalList_getObject(sal_list_t *list) +{ + if (list == NULL) { + return NULL; + } + + return list->pObj; +} + +void +SalList_delObject(sal_list_t **list) +{ + if (*list == NULL) { + return; + } + + (*list)->pObj = NULL; + return; +} + +void * +SalList_next(sal_list_t *list) +{ + return list->next; +} + +void +SalList_free(sal_list_t **list) +{ + sal_list_t *next_element = NULL; + void *pObj = NULL; + while (NULL != (*list)) { + next_element = SalList_next(*list); + pObj = SalList_getObject((*list)); + LAC_OS_FREE(pObj); + LAC_OS_FREE(*list); + *list = next_element; + } +} + +void +SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list) +{ + void *pObj = NULL; + if ((NULL == *head_list) || (NULL == *pre_list) || (NULL == list)) { + return; + } + if (*head_list == list) { /* delete the first node in list */ + *head_list = list->next; + } else { + (*pre_list)->next = list->next; + } + pObj = SalList_getObject(list); + LAC_OS_FREE(pObj); + LAC_OS_FREE(list); + return; +} diff --git a/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h b/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h new file mode 100644 index 00000000000..079d537d782 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_buffer_desc.h + * + * @defgroup LacBufferDesc Buffer Descriptors + * + * @ingroup LacCommon + * + * Functions which handle updating a user supplied buffer with the QAT + * descriptor representation. + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_BUFFER_DESC_H +#define LAC_BUFFER_DESC_H + +/*************************************************************************** + * Include header files + ***************************************************************************/ +#include "cpa.h" +#include "icp_buffer_desc.h" +#include "cpa_cy_sym.h" +#include "lac_common.h" + +/** +******************************************************************************* +* @ingroup LacBufferDesc +* Write the buffer descriptor in QAT friendly format. +* +* @description +* Updates the Meta Data associated with the pUserBufferList CpaBufferList +* This function will also return the (aligned) physical address +* associated with this CpaBufferList. +* +* @param[in] pUserBufferList A pointer to the buffer list to +* create the meta data for the QAT. +* @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical +* address. +* @param[in] isPhysicalAddress Type of address +* @param[in] pService Pointer to generic service +* +*****************************************************************************/ +CpaStatus LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufferListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService); + +/** +******************************************************************************* +* @ingroup LacBufferDesc +* Write the buffer descriptor in QAT friendly format. +* +* @description +* Updates the Meta Data associated with the pUserBufferList CpaBufferList +* This function will also return the (aligned) physical address +* associated with this CpaBufferList. Zero length buffers are allowed. +* Should be used for CHA-CHA-POLY and GCM algorithms. +* +* @param[in] pUserBufferList A pointer to the buffer list to +* create the meta data for the QAT. +* @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical +* address. +* @param[in] isPhysicalAddress Type of address +* @param[in] pService Pointer to generic service +* +*****************************************************************************/ +CpaStatus LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + const CpaBufferList *pUserBufferList, + Cpa64U *pBufferListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Write the buffer descriptor in QAT friendly format. + * + * @description + * Updates the Meta Data associated with the PClientList CpaBufferList + * This function will also return the (aligned) physical address + * associated with this CpaBufferList and the total data length of the + * buffer list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * create the meta data for the QAT. + * @param[out] pBufListAlignedPhyAddr The pointer to the aligned physical + * address. + * @param[in] isPhysicalAddress Type of address + * @param[out] totalDataLenInBytes The pointer to the total data length + * of the buffer list + * @param[in] pService Pointer to generic service + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListDescWriteAndGetSize(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaFlatBuffer is correctly formatted. + * + * @description + * Ensures the CpaFlatBuffer is correctly formatted + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserFlatBuffer A pointer to the flat buffer to + * validate. + * @param[out] pPktSize The total size of the packet. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_FlatBufferVerify(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaFlatBuffer is correctly formatted. + * This function will allow a size of zero bytes to any of the Flat + * buffers. + * + * @description + * Ensures the CpaFlatBuffer is correctly formatted + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserFlatBuffer A pointer to the flat buffer to + * validate. + * @param[out] pPktSize The total size of the packet. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_FlatBufferVerifyNull(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaBufferList is correctly formatted. + * + * @description + * Ensures the CpaBufferList pUserBufferList is correctly formatted + * including the user supplied metaData. + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * validate. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * list. + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListVerify(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaBufferList is correctly formatted. + * + * @description + * Ensures the CpaBufferList pUserBufferList is correctly formatted + * including the user supplied metaData. + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * validate. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * list. + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListVerifyNull(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Get the total size of a CpaBufferList. + * + * @description + * This function returns the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * calculate the total size for. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * + *****************************************************************************/ +void LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Zero some of the CpaBufferList. + * + * @description + * Zero a section of data within the CpaBufferList from an offset for + * a specific length. + * + * @param[in] pBuffList A pointer to the buffer list to + * zero an area of. + * @param[in] offset Number of bytes from start of buffer to where + * to start zeroing. + * + * @param[in] lenToZero Number of bytes that will be set to zero + * after the call to this function. + *****************************************************************************/ + +void LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, + Cpa32U offset, + Cpa32U lenToZero); + +#endif /* LAC_BUFFER_DESC_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_common.h b/sys/dev/qat/qat_api/common/include/lac_common.h new file mode 100644 index 00000000000..fb2fdd95300 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_common.h @@ -0,0 +1,847 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_common.h Common macros + * + * @defgroup Lac Look Aside Crypto LLD Doc + * + *****************************************************************************/ + +/** + ***************************************************************************** + * @defgroup LacCommon LAC Common + * Common code for Lac which includes init/shutdown, memory, logging and + * hooks. + * + * @ingroup Lac + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_COMMON_H +#define LAC_COMMON_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "qat_utils.h" +#include "cpa_cy_common.h" +#include "icp_adf_init.h" + +#define LAC_ARCH_UINT uintptr_t +#define LAC_ARCH_INT intptr_t + +/* +***************************************************************************** +* Max range values for some primitive param checking +***************************************************************************** +*/ + +/**< Maximum number of instances */ +#define SAL_MAX_NUM_INSTANCES_PER_DEV 512 + +#define SAL_DEFAULT_RING_SIZE 256 +/**< Default ring size */ + +#define SAL_64_CONCURR_REQUESTS 64 +#define SAL_128_CONCURR_REQUESTS 128 +#define SAL_256_CONCURR_REQUESTS 256 +#define SAL_512_CONCURR_REQUESTS 512 +#define SAL_1024_CONCURR_REQUESTS 1024 +#define SAL_2048_CONCURR_REQUESTS 2048 +#define SAL_4096_CONCURR_REQUESTS 4096 +#define SAL_MAX_CONCURR_REQUESTS 65536 +/**< Valid options for the num of concurrent requests per ring pair read + from the config file. These values are used to size the rings */ + +#define SAL_BATCH_SUBMIT_FREE_SPACE 2 +/**< For data plane batch submissions ADF leaves 2 spaces free on the ring */ + +/* +****************************************************************************** +* Some common settings for QA API queries +****************************************************************************** +*/ + +#define SAL_INFO2_VENDOR_NAME "Intel(R)" +/**< @ingroup LacCommon + * Name of vendor of this driver */ +#define SAL_INFO2_PART_NAME "%s with Intel(R) QuickAssist Technology" +/**< @ingroup LacCommon + */ + +/* +******************************************************************************** +* User process name defines and functions +******************************************************************************** +*/ + +#define LAC_USER_PROCESS_NAME_MAX_LEN 32 +/**< @ingroup LacCommon + * Max length of user process name */ + +#define LAC_KERNEL_PROCESS_NAME "KERNEL_QAT" +/**< @ingroup LacCommon + * Default name for kernel process */ + +/* +******************************************************************************** +* response mode indicator from Config file +******************************************************************************** +*/ + +#define SAL_RESP_POLL_CFG_FILE 1 +#define SAL_RESP_EPOLL_CFG_FILE 2 + +/* + * @ingroup LacCommon + * @description + * This function sets the process name + * + * @context + * This functions is called from module_init or from user space process + * initialization function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] processName Process name to be set +*/ +CpaStatus icpSetProcessName(const char *processName); + +/* + * @ingroup LacCommon + * @description + * This function gets the process name + * + * @context + * This functions is called from LAC context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +char *icpGetProcessName(void); + +/* Sections of the config file */ +#define LAC_CFG_SECTION_GENERAL "GENERAL" +#define LAC_CFG_SECTION_INTERNAL "INTERNAL" + +/* +******************************************************************************** +* Debug Macros and settings +******************************************************************************** +*/ + +#define SEPARATOR "+--------------------------------------------------+\n" +/**< @ingroup LacCommon + * separator used for printing stats to standard output*/ + +#define BORDER "|" +/**< @ingroup LacCommon + * separator used for printing stats to standard output*/ + +/** +***************************************************************************** + * @ingroup LacCommon + * Component state + * + * @description + * This enum is used to indicate the state that the component is in. Its + * purpose is to prevent components from being initialised or shutdown + * incorrectly. + * + *****************************************************************************/ +typedef enum { + LAC_COMP_SHUT_DOWN = 0, + /**< Component in the Shut Down state */ + LAC_COMP_SHUTTING_DOWN, + /**< Component in the Process of Shutting down */ + LAC_COMP_INITIALISING, + /**< Component in the Process of being initialised */ + LAC_COMP_INITIALISED, + /**< Component in the initialised state */ +} lac_comp_state_t; + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if a parameter is NULL + * + * @param[in] param Parameter + * + * @return CPA_STATUS_INVALID_PARAM Parameter is NULL + * @return void Parameter is not NULL + ******************************************************************************/ +#define LAC_CHECK_NULL_PARAM(param) \ + do { \ + if (NULL == (param)) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if a parameter is within a specified range + * + * @param[in] param Parameter + * @param[in] min Parameter must be greater than OR equal to + *min + * @param[in] max Parameter must be less than max + * + * @return CPA_STATUS_INVALID_PARAM Parameter is outside range + * @return void Parameter is within range + ******************************************************************************/ +#define LAC_CHECK_PARAM_RANGE(param, min, max) \ + do { \ + if (((param) < (min)) || ((param) >= (max))) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This checks if a param is 8 byte aligned. + * + ******************************************************************************/ +#define LAC_CHECK_8_BYTE_ALIGNMENT(param) \ + do { \ + if ((Cpa64U)param % 8 != 0) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This checks if a param is 64 byte aligned. + * + ******************************************************************************/ +#define LAC_CHECK_64_BYTE_ALIGNMENT(param) \ + do { \ + if ((LAC_ARCH_UINT)param % 64 != 0) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro returns the size of the buffer list structure given the + * number of elements in the buffer list - note: only the sizeof the + * buffer list structure is returned. + * + * @param[in] numBuffers The number of flatbuffers in a buffer list + * + * @return size of the buffer list structure + ******************************************************************************/ +#define LAC_BUFFER_LIST_SIZE_GET(numBuffers) \ + (sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer))) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks that a flatbuffer is valid i.e. that it is not + * null and the data it points to is not null + * + * @param[in] pFlatBuffer Pointer to flatbuffer + * + * @return CPA_STATUS_INVALID_PARAM Invalid flatbuffer pointer + * @return void flatbuffer is ok + ******************************************************************************/ +#define LAC_CHECK_FLAT_BUFFER(pFlatBuffer) \ + do { \ + LAC_CHECK_NULL_PARAM((pFlatBuffer)); \ + LAC_CHECK_NULL_PARAM((pFlatBuffer)->pData); \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro verifies that the status is ok i.e. equal to CPA_STATUS_SUCCESS + * + * @param[in] status status we are checking + * + * @return void status is ok (CPA_STATUS_SUCCESS) + * @return status The value in the status parameter is an error one + * + ******************************************************************************/ +#define LAC_CHECK_STATUS(status) \ + do { \ + if (CPA_STATUS_SUCCESS != (status)) { \ + return status; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro verifies that the Instance Handle is valid. + * + * @param[in] instanceHandle Instance Handle + * + * @return CPA_STATUS_INVALID_PARAM Parameter is NULL + * @return void Parameter is not NULL + * + ******************************************************************************/ +#define LAC_CHECK_INSTANCE_HANDLE(instanceHandle) \ + do { \ + if (NULL == (instanceHandle)) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro copies a string from one location to another + * + * @param[out] pDestinationBuffer Pointer to destination buffer + * @param[in] pSource Pointer to source buffer + * + ******************************************************************************/ +#define LAC_COPY_STRING(pDestinationBuffer, pSource) \ + do { \ + memcpy(pDestinationBuffer, pSource, (sizeof(pSource) - 1)); \ + pDestinationBuffer[(sizeof(pSource) - 1)] = '\0'; \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro fills a memory zone with ZEROES + * + * @param[in] pBuffer Pointer to buffer + * @param[in] count Buffer length + * + * @return void + * + ******************************************************************************/ +#define LAC_OS_BZERO(pBuffer, count) memset(pBuffer, 0, count); + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro calculates the position of the given member in a struct + * Only for use on a struct where all members are of equal size to map + * the struct member position to an array index + * + * @param[in] structType the struct + * @param[in] member the member of the given struct + * + ******************************************************************************/ +#define LAC_IDX_OF(structType, member) \ + (offsetof(structType, member) / sizeof(((structType *)0)->member)) + +/* +******************************************************************************** +* Alignment, Bid define and Bit Operation Macros +******************************************************************************** +*/ + +#define LAC_BIT31_SET 0x80000000 /**< bit 31 == 1 */ +#define LAC_BIT7_SET 0x80 /**< bit 7 == 1 */ +#define LAC_BIT6_SET 0x40 /**< bit 6 == 1 */ +#define LAC_BIT5_SET 0x20 /**< bit 5 == 1 */ +#define LAC_BIT4_SET 0x10 /**< bit 4 == 1 */ +#define LAC_BIT3_SET 0x08 /**< bit 3 == 1 */ +#define LAC_BIT2_SET 0x04 /**< bit 2 == 1 */ +#define LAC_BIT1_SET 0x02 /**< bit 1 == 1 */ +#define LAC_BIT0_SET 0x01 /**< bit 0 == 1 */ + +#define LAC_NUM_BITS_IN_BYTE (8) +/**< @ingroup LacCommon + * Number of bits in a byte */ + +#define LAC_LONG_WORD_IN_BYTES (4) +/**< @ingroup LacCommon + * Number of bytes in an IA word */ + +#define LAC_QUAD_WORD_IN_BYTES (8) +/**< @ingroup LacCommon + * Number of bytes in a QUAD word */ + +#define LAC_QAT_MAX_MSG_SZ_LW (32) +/**< @ingroup LacCommon + * Maximum size in Long Words for a QAT message */ + +/** +***************************************************************************** + * @ingroup LacCommon + * Alignment shift requirements of a buffer. + * + * @description + * This enum is used to indicate the alignment shift of a buffer. + * All alignments are to power of 2 + * + *****************************************************************************/ +typedef enum lac_aligment_shift_s { + LAC_NO_ALIGNMENT_SHIFT = 0, + /**< No alignment shift (to a power of 2)*/ + LAC_8BYTE_ALIGNMENT_SHIFT = 3, + /**< 8 byte alignment shift (to a power of 2)*/ + LAC_16BYTE_ALIGNMENT_SHIFT = 4, + /**< 16 byte alignment shift (to a power of 2)*/ + LAC_64BYTE_ALIGNMENT_SHIFT = 6, + /**< 64 byte alignment shift (to a power of 2)*/ + LAC_4KBYTE_ALIGNMENT_SHIFT = 12, + /**< 4k byte alignment shift (to a power of 2)*/ +} lac_aligment_shift_t; + +/** +***************************************************************************** + * @ingroup LacCommon + * Alignment of a buffer. + * + * @description + * This enum is used to indicate the alignment requirements of a buffer. + * + *****************************************************************************/ +typedef enum lac_aligment_s { + LAC_NO_ALIGNMENT = 0, + /**< No alignment */ + LAC_1BYTE_ALIGNMENT = 1, + /**< 1 byte alignment */ + LAC_8BYTE_ALIGNMENT = 8, + /**< 8 byte alignment*/ + LAC_64BYTE_ALIGNMENT = 64, + /**< 64 byte alignment*/ + LAC_4KBYTE_ALIGNMENT = 4096, + /**< 4k byte alignment */ +} lac_aligment_t; + +/** +***************************************************************************** + * @ingroup LacCommon + * Size of a buffer. + * + * @description + * This enum is used to indicate the required size. + * The buffer must be a multiple of the required size. + * + *****************************************************************************/ +typedef enum lac_expected_size_s { + LAC_NO_LENGTH_REQUIREMENTS = 0, + /**< No requirement for size */ + LAC_4KBYTE_MULTIPLE_REQUIRED = 4096, + /**< 4k multiple requirement for size */ +} lac_expected_size_t; + +#define LAC_OPTIMAL_ALIGNMENT_SHIFT LAC_64BYTE_ALIGNMENT_SHIFT +/**< @ingroup LacCommon + * optimal alignment to a power of 2 */ + +#define LAC_SHIFT_8 (1 << LAC_8BYTE_ALIGNMENT_SHIFT) +/**< shift by 8 bits */ +#define LAC_SHIFT_24 \ + ((1 << LAC_8BYTE_ALIGNMENT_SHIFT) + (1 << LAC_16BYTE_ALIGNMENT_SHIFT)) +/**< shift by 24 bits */ + +#define LAC_MAX_16_BIT_VALUE ((1 << 16) - 1) +/**< @ingroup LacCommon + * maximum value a 16 bit type can hold */ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro can be used to avoid an unused variable warning from the + * compiler + * + * @param[in] variable unused variable + * + ******************************************************************************/ +#define LAC_UNUSED_VARIABLE(x) (void)(x) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if an address is aligned to the specified power of 2 + * Returns 0 if alignment is ok, or non-zero otherwise + * + * @param[in] address the address we are checking + * + * @param[in] alignment the byte alignment to check (specified as power of 2) + * + ******************************************************************************/ +#define LAC_ADDRESS_ALIGNED(address, alignment) \ + (!((LAC_ARCH_UINT)(address) & ((1 << (alignment)) - 1))) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro rounds up a number to a be a multiple of the alignment when + * the alignment is a power of 2. + * + * @param[in] num Number + * @param[in] align Alignment (must be a power of 2) + * + ******************************************************************************/ +#define LAC_ALIGN_POW2_ROUNDUP(num, align) (((num) + (align)-1) & ~((align)-1)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro generates a bit mask to select a particular bit + * + * @param[in] bitPos Bit position to select + * + ******************************************************************************/ +#define LAC_BIT(bitPos) (0x1 << (bitPos)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bits to the equivalent size in bytes, + * using a bit shift to divide by 8 + * + * @param[in] x size in bits + * + ******************************************************************************/ +#define LAC_BITS_TO_BYTES(x) ((x) >> 3) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in bits, + * using a bit shift to multiply by 8 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_BITS(x) ((x) << 3) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in longwords, + * using a bit shift to divide by 4 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_LONGWORDS(x) ((x) >> 2) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in longwords to the equivalent size in bytes, + * using a bit shift to multiply by 4 + * + * @param[in] x size in long words + * + ******************************************************************************/ +#define LAC_LONGWORDS_TO_BYTES(x) ((x) << 2) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in quadwords, + * using a bit shift to divide by 8 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_QUADWORDS(x) (((x) >> 3) + (((x) % 8) ? 1 : 0)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in quadwords to the equivalent size in bytes, + * using a bit shift to multiply by 8 + * + * @param[in] x size in quad words + * + ******************************************************************************/ +#define LAC_QUADWORDS_TO_BYTES(x) ((x) << 3) + + +/******************************************************************************/ + +/* +******************************************************************************* +* Mutex Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro tries to acquire a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * @param[in] timeout Timeout + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_LOCK_MUTEX(pLock, timeout) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexLock((pLock), (timeout))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro unlocks a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_UNLOCK_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexUnlock((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro initialises a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_INIT_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexInit((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro destroys a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_DESTROY_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexDestroy((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro calls a trylock on a mutex + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_TRYLOCK_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != \ + qatUtilsMutexTryLock((pLock), QAT_UTILS_WAIT_NONE)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/* +******************************************************************************* +* Semaphore Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro waits on a semaphore and returns the status + * + * @param[in] sid The semaphore + * @param[in] timeout Timeout + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_WAIT_SEMAPHORE(sid, timeout) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreWait(&sid, (timeout))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_CHECK_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreTryWait(&sid)) ? \ + CPA_STATUS_RETRY : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro post a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_POST_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphorePost(&sid)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro initialises a semaphore and returns the status + * + * @param[in] sid The semaphore + * @param[in] semValue Initial semaphore value + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_INIT_SEMAPHORE(sid, semValue) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreInit(&sid, semValue)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro destroys a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_DESTROY_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreDestroy(&sid)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/* +******************************************************************************* +* Spinlock Macros +******************************************************************************* +*/ +typedef struct mtx *lac_lock_t; +#define LAC_SPINLOCK_INIT(lock) \ + ((CPA_STATUS_SUCCESS != qatUtilsLockInit(lock)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) +#define LAC_SPINLOCK(lock) \ + ({ \ + (void)qatUtilsLock(lock); \ + CPA_STATUS_SUCCESS; \ + }) +#define LAC_SPINUNLOCK(lock) \ + ({ \ + (void)qatUtilsUnlock(lock); \ + CPA_STATUS_SUCCESS; \ + }) +#define LAC_SPINLOCK_DESTROY(lock) \ + ({ \ + (void)qatUtilsLockDestroy(lock); \ + CPA_STATUS_SUCCESS; \ + }) + +#define LAC_CONST_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) +#define LAC_CONST_VOLATILE_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) + +/* Type of ring */ +#define SAL_RING_TYPE_NONE 0 +#define SAL_RING_TYPE_A_SYM_HI 1 +#define SAL_RING_TYPE_A_SYM_LO 2 +#define SAL_RING_TYPE_A_ASYM 3 +#define SAL_RING_TYPE_B_SYM_HI 4 +#define SAL_RING_TYPE_B_SYM_LO 5 +#define SAL_RING_TYPE_B_ASYM 6 +#define SAL_RING_TYPE_DC 7 +#define SAL_RING_TYPE_ADMIN 8 +#define SAL_RING_TYPE_TRNG 9 + +/* Maps Ring Service to generic service type */ +static inline icp_adf_ringInfoService_t +lac_getRingType(int type) +{ + switch (type) { + case SAL_RING_TYPE_NONE: + return ICP_ADF_RING_SERVICE_0; + case SAL_RING_TYPE_A_SYM_HI: + return ICP_ADF_RING_SERVICE_1; + case SAL_RING_TYPE_A_SYM_LO: + return ICP_ADF_RING_SERVICE_2; + case SAL_RING_TYPE_A_ASYM: + return ICP_ADF_RING_SERVICE_3; + case SAL_RING_TYPE_B_SYM_HI: + return ICP_ADF_RING_SERVICE_4; + case SAL_RING_TYPE_B_SYM_LO: + return ICP_ADF_RING_SERVICE_5; + case SAL_RING_TYPE_B_ASYM: + return ICP_ADF_RING_SERVICE_6; + case SAL_RING_TYPE_DC: + return ICP_ADF_RING_SERVICE_7; + case SAL_RING_TYPE_ADMIN: + return ICP_ADF_RING_SERVICE_8; + case SAL_RING_TYPE_TRNG: + return ICP_ADF_RING_SERVICE_9; + default: + return ICP_ADF_RING_SERVICE_0; + } + return ICP_ADF_RING_SERVICE_0; +} + +/* Maps generic service type to Ring Service type */ +static inline int +lac_getServiceType(icp_adf_ringInfoService_t type) +{ + switch (type) { + case ICP_ADF_RING_SERVICE_0: + return SAL_RING_TYPE_NONE; + case ICP_ADF_RING_SERVICE_1: + return SAL_RING_TYPE_A_SYM_HI; + case ICP_ADF_RING_SERVICE_2: + return SAL_RING_TYPE_A_SYM_LO; + case ICP_ADF_RING_SERVICE_3: + return SAL_RING_TYPE_A_ASYM; + case ICP_ADF_RING_SERVICE_4: + return SAL_RING_TYPE_B_SYM_HI; + case ICP_ADF_RING_SERVICE_5: + return SAL_RING_TYPE_B_SYM_LO; + case ICP_ADF_RING_SERVICE_6: + return SAL_RING_TYPE_B_ASYM; + case ICP_ADF_RING_SERVICE_7: + return SAL_RING_TYPE_DC; + case ICP_ADF_RING_SERVICE_8: + return SAL_RING_TYPE_ADMIN; + default: + return SAL_RING_TYPE_NONE; + } + return SAL_RING_TYPE_NONE; +} + +#endif /* LAC_COMMON_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_hooks.h b/sys/dev/qat/qat_api/common/include/lac_hooks.h new file mode 100644 index 00000000000..7018b77a480 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_hooks.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ******************************************************************************* + * @file lac_hooks.h + * + * @defgroup LacHooks Hooks + * + * @ingroup LacCommon + * + * Component Init/Shutdown functions. These are: + * - an init function which is called during the intialisation sequence, + * - a shutdown function which is called by the overall shutdown function, + * + ******************************************************************************/ + +#ifndef LAC_HOOKS_H +#define LAC_HOOKS_H + +/* +******************************************************************************** +* Include public/global header files +******************************************************************************** +*/ + +#include "cpa.h" + +/* +******************************************************************************** +* Include private header files +******************************************************************************** +*/ + +/******************************************************************************/ + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Large Number (ModExp and ModInv) module + * + * @description + * This function clears the Large Number statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacLn_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees statistics array for Large Number module + * + * @description + * This function frees statistics array for Large Number module + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacLn_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Prime module + * + * @description + * This function clears the Prime statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacPrime_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the Prime module statistics array + * + * @description + * This function frees the Prime module statistics array + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacPrime_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the DSA module + * + * @param[in] instanceHandle + * + * @description + * This function clears the DSA statistics + * + ******************************************************************************/ +CpaStatus LacDsa_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the DSA module statistics array + * + * @param[in] instanceHandle + * + * @description + * This function frees the DSA statistics array + * + ******************************************************************************/ +void LacDsa_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Diffie Hellmann module + * + * @description + * This function initialises the Diffie Hellman statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacDh_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the Diffie Hellmann module statistics + * + * @description + * This function frees the Diffie Hellmann module statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacDh_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function registers the callback handlers to SSL/TLS and MGF, + * allocates resources that are needed for the component and clears + * the stats. + * + * @param[in] instanceHandle + * + * @retval CPA_STATUS_SUCCESS Status Success + * @retval CPA_STATUS_FAIL General failure + * @retval CPA_STATUS_RESOURCE Resource allocation failure + * + *****************************************************************************/ +CpaStatus LacSymKey_Init(CpaInstanceHandle instanceHandle); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function frees up resources obtained by the key gen component + * and clears the stats + * + * @param[in] instanceHandle + * + * @retval CPA_STATUS_SUCCESS Status Success + * + *****************************************************************************/ +CpaStatus LacSymKey_Shutdown(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the RSA module + * + * @description + * This function clears the RSA statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacRsa_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the RSA module statistics + * + * @description + * This function frees the RSA module statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacRsa_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the EC module + * + * @description + * This function clears the EC statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacEc_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the EC module stats array + * + * @description + * This function frees the EC module stats array + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacEc_StatsFree(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* + * @ingroup LacSymNrbg + * Initialise the NRBG module + * + * @description + * This function registers NRBG callback handlers. + * + * + *****************************************************************************/ +void LacSymNrbg_Init(void); + +#endif /* LAC_HOOKS_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_list.h b/sys/dev/qat/qat_api/common/include/lac_list.h new file mode 100644 index 00000000000..2af91df155c --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_list.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_list.h + * + * @defgroup SalList + * + * @ingroup SalCtrl + * + * List structure and list functions. + * + ***************************************************************************/ + +#ifndef LAC_LIST_H +#define LAC_LIST_H + +/** + ***************************************************************************** + * @ingroup SalList + * + * @description + * List structure + * + *****************************************************************************/ +typedef struct sal_list_s { + + struct sal_list_s *next; + void *pObj; + +} sal_list_t; + +/** +******************************************************************************* + * @ingroup SalList + * Add a structure to tail of a list. + * + * @description + * Adds pObj to the tail of list (if it exists). Allocates and sets a + * new sal_list_t structure. + * + * @param[in] list Pointer to the head pointer of the list. + * Can be NULL if no elements yet in list. + * @param[in/out] tail Pointer to tail pointer of the list. + * Can be NULL if no elements yet in list. + * Is updated by the function to point to +*tail + * of list if pObj has been successfully +*added. + * @param[in] pObj Pointer to structure to add to tail of + * the list. + * @retval status + * + *****************************************************************************/ +CpaStatus SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj); + +/** +******************************************************************************* + * @ingroup SalList + * Delete an element from the list. + * + * @description + * Delete an element from the list. + * + * @param[in/out] head_list Pointer to the head pointer of the list. + * Can be NULL if no elements yet in list. + * Is updated by the function + * to point to list->next if head_list is +*list. + * @param[in/out] pre_list Pointer to the previous pointer of the +*list. + * Can be NULL if no elements yet in list. + * (*pre_list)->next is updated + * by the function to point to list->next + * @param[in] list Pointer to list. + * + *****************************************************************************/ +void +SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list); + +/** +******************************************************************************* + * @ingroup SalList + * Returns pObj element in list structure. + * + * @description + * Returns pObj associated with sal_list_t structure. + * + * @param[in] list Pointer to list element. + * @retval void* pObj member of list structure. + * + *****************************************************************************/ +void *SalList_getObject(sal_list_t *list); + +/** +******************************************************************************* + * @ingroup SalList + * Set pObj to be NULL in the list. + * + * @description + * Set pObj of a element in the list to be NULL. + * + * @param[in] list Pointer to list element. + * + *****************************************************************************/ +void SalList_delObject(sal_list_t **list); + +/** +******************************************************************************* + * @ingroup SalList + * Returns next element in list structure. + * + * @description + * Returns next associated with sal_list_t structure. + * + * @param[in] list Pointer to list element. + * @retval void* next member of list structure. + * + *****************************************************************************/ +void *SalList_next(sal_list_t *); + +/** +******************************************************************************* + * @ingroup SalList + * Frees memory associated with list structure. + * + * @description + * Frees memory associated with list structure and the Obj pointed to by + * the list. + * + * @param[in] list Pointer to list. + * + *****************************************************************************/ +void SalList_free(sal_list_t **); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_log.h b/sys/dev/qat/qat_api/common/include/lac_log.h new file mode 100644 index 00000000000..2593c7b5496 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_log.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_log.h + * + * @defgroup LacLog Log + * + * @ingroup LacCommon + * + * Logging Macros. These macros also log the function name they are called in. + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_LOG_H +#define LAC_LOG_H + +/*************************************************************************** + * Include public/global header files + ***************************************************************************/ +#include "cpa.h" +#include "lac_common.h" +#include "icp_accel_devices.h" + +#define LAC_INVALID_PARAM_LOG_(log, args...) \ + QAT_UTILS_LOG("[error] %s() - : Invalid API Param - " log "\n", \ + __func__, \ + ##args) + +#define LAC_INVALID_PARAM_LOG(log) LAC_INVALID_PARAM_LOG_(log) + +#define LAC_INVALID_PARAM_LOG1(log, param1) LAC_INVALID_PARAM_LOG_(log, param1) + +#define LAC_INVALID_PARAM_LOG2(log, param1, param2) \ + LAC_INVALID_PARAM_LOG_(log, param1, param2) + +#define LAC_UNSUPPORTED_PARAM_LOG(log) \ + QAT_UTILS_LOG("%s() - : UnSupported API Param - " log "\n", __func__) + +#define LAC_LOG_ERROR(log) QAT_UTILS_LOG("%s() - : " log "\n", __func__) + +#endif /* LAC_LOG_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_mem.h b/sys/dev/qat/qat_api/common/include/lac_mem.h new file mode 100644 index 00000000000..39be4d9ba65 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_mem.h @@ -0,0 +1,577 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem.h + * + * @defgroup LacMem Memory + * + * @ingroup LacCommon + * + * Memory re-sizing functions and memory accessor macros. + * + ***************************************************************************/ + +#ifndef LAC_MEM_H +#define LAC_MEM_H + +/*************************************************************************** + * Include header files + ***************************************************************************/ +#include "cpa.h" +#include "qat_utils.h" +#include "lac_common.h" + +/** + ******************************************************************************* + * @ingroup LacMem + * These macros are used to Endian swap variables from IA to QAT. + * + * @param[out] x The variable to be swapped. + * + * @retval none + ******************************************************************************/ +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define LAC_MEM_WR_64(x) QAT_UTILS_HOST_TO_NW_64(x) +#define LAC_MEM_WR_32(x) QAT_UTILS_HOST_TO_NW_32(x) +#define LAC_MEM_WR_16(x) QAT_UTILS_HOST_TO_NW_16(x) +#define LAC_MEM_RD_64(x) QAT_UTILS_NW_TO_HOST_64(x) +#define LAC_MEM_RD_32(x) QAT_UTILS_NW_TO_HOST_32(x) +#define LAC_MEM_RD_16(x) QAT_UTILS_NW_TO_HOST_16(x) +#else +#define LAC_MEM_WR_64(x) (x) +#define LAC_MEM_WR_32(x) (x) +#define LAC_MEM_WR_16(x) (x) +#define LAC_MEM_RD_64(x) (x) +#define LAC_MEM_RD_32(x) (x) +#define LAC_MEM_RD_16(x) (x) +#endif + +/* +******************************************************************************* +* Shared Memory Macros (memory accessible by Acceleration Engines, e.g. QAT) +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write to a variable that will be read by the + * QAT. The macro will automatically detect the size of the target variable and + * will select the correct method for performing the write. The data is cast to + * the type of the field that it will be written to. + * This macro swaps data if required. + * + * @param[out] var The variable to be written. Can be a field of a struct. + * + * @param[in] data The value to be written. Will be cast to the size of the + * target. + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_SWAP(var, data) \ + do { \ + switch (sizeof(var)) { \ + case 1: \ + (var) = (Cpa8U)(data); \ + break; \ + case 2: \ + (var) = (Cpa16U)(data); \ + (var) = LAC_MEM_WR_16(((Cpa16U)var)); \ + break; \ + case 4: \ + (var) = (Cpa32U)(data); \ + (var) = LAC_MEM_WR_32(((Cpa32U)var)); \ + break; \ + case 8: \ + (var) = (Cpa64U)(data); \ + (var) = LAC_MEM_WR_64(((Cpa64U)var)); \ + break; \ + default: \ + break; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to read a variable that was written by the QAT. + * The macro will automatically detect the size of the data to be read and will + * select the correct method for performing the read. The value read from the + * variable is cast to the size of the data type it will be stored in. + * This macro swaps data if required. + * + * @param[in] var The variable to be read. Can be a field of a struct. + * + * @param[out] data The variable to hold the result of the read. Data read + * will be cast to the size of this variable + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_READ_SWAP(var, data) \ + do { \ + switch (sizeof(var)) { \ + case 1: \ + (data) = (var); \ + break; \ + case 2: \ + (data) = LAC_MEM_RD_16(((Cpa16U)var)); \ + break; \ + case 4: \ + (data) = LAC_MEM_RD_32(((Cpa32U)var)); \ + break; \ + case 8: \ + (data) = LAC_MEM_RD_64(((Cpa64U)var)); \ + break; \ + default: \ + break; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write a pointer to a QAT request. The fields + * for pointers in the QAT request and response messages are always 64 bits + * + * @param[out] var The variable to be written to. Can be a field of a struct. + * + * @param[in] data The value to be written. Will be cast to size of target + * variable + * + * @retval none + ******************************************************************************/ +/* cast pointer to scalar of same size of the native pointer */ +#define LAC_MEM_SHARED_WRITE_FROM_PTR(var, data) \ + ((var) = (Cpa64U)(LAC_ARCH_UINT)(data)) + +/* Note: any changes to this macro implementation should also be made to the + * similar LAC_MEM_CAST_PTR_TO_UINT64 macro + */ + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to read a pointer from a QAT response. The fields + * for pointers in the QAT request and response messages are always 64 bits + * + * @param[in] var The variable to be read. Can be a field of a struct. + * + * @param[out] data The variable to hold the result of the read. Data read + * will be cast to the size of this variable + * + * @retval none + ******************************************************************************/ +/* Cast back to native pointer */ +#define LAC_MEM_SHARED_READ_TO_PTR(var, data) \ + ((data) = (void *)(LAC_ARCH_UINT)(var)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro safely casts a pointer to a Cpa64U type. + * + * @param[in] pPtr The pointer to be cast. + * + * @retval pointer cast to Cpa64U + ******************************************************************************/ +#define LAC_MEM_CAST_PTR_TO_UINT64(pPtr) ((Cpa64U)(pPtr)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro uses an QAT Utils macro to convert from a virtual address to + *a + * physical address for internally allocated memory. + * + * @param[in] pVirtAddr The address to be converted. + * + * @retval The converted physical address + ******************************************************************************/ +#define LAC_OS_VIRT_TO_PHYS_INTERNAL(pVirtAddr) \ + (QAT_UTILS_MMU_VIRT_TO_PHYS(pVirtAddr)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro should be called on all externally allocated memory it calls + * SalMem_virt2PhysExternal function which allows a user + * to set the virt2phys function used by an instance. + * Defaults to virt to phys for kernel. + * + * @param[in] genService Generic sal_service_t structure. + * @param[in] pVirtAddr The address to be converted. + * + * @retval The converted physical address + ******************************************************************************/ +#define LAC_OS_VIRT_TO_PHYS_EXTERNAL(genService, pVirtAddr) \ + ((SalMem_virt2PhysExternal(pVirtAddr, &(genService)))) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write an address variable that will be read by + * the QAT. The macro will perform the necessary virt2phys address translation + * This macro is only to be called on memory allocated internally by the driver. + * + * @param[out] var The address variable to write. Can be a field of a struct. + * + * @param[in] pPtr The pointer variable to containing the address to be + * written + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_INTERNAL(var, pPtr) \ + do { \ + Cpa64U physAddr = 0; \ + physAddr = LAC_MEM_CAST_PTR_TO_UINT64( \ + LAC_OS_VIRT_TO_PHYS_INTERNAL(pPtr)); \ + var = physAddr; \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write an address variable that will be read by + * the QAT. The macro will perform the necessary virt2phys address translation + * This macro is to be used on memory allocated externally by the user. It calls + * the user supplied virt2phys address translation. + * + * @param[in] pService The pointer to the service + * @param[out] var The address variable to write. Can be a field of a struct + * @param[in] pPtr The pointer variable to containing the address to be + * written + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(pService, var, pPtr) \ + do { \ + Cpa64U physAddr = 0; \ + physAddr = LAC_MEM_CAST_PTR_TO_UINT64( \ + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService, pPtr)); \ + var = physAddr; \ + } while (0) + +/* +******************************************************************************* +* OS Memory Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro allocates the memory for the given + * size and stores the address of the memory allocated in the pointer. + * + * @param[out] ppMemAddr address of pointer where address will be stored + * @param[in] sizeBytes the size of the memory to be allocated. + * + * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory + * @retval CPA_STATUS_SUCCESS Macro executed successfully + * + ******************************************************************************/ +static __inline CpaStatus +LacMem_OsMemAlloc(void **ppMemAddr, Cpa32U sizeBytes) +{ + *ppMemAddr = malloc(sizeBytes, M_QAT, M_WAITOK); + + return CPA_STATUS_SUCCESS; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro allocates the contiguous + * memory for the given + * size and stores the address of the memory allocated in the pointer. + * + * @param[out] ppMemAddr address of pointer where address will be stored + * @param[in] sizeBytes the size of the memory to be allocated. + * @param[in] alignmentBytes the alignment + * @param[in] node node to allocate from + * + * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory + * @retval CPA_STATUS_SUCCESS Macro executed successfully + * + ******************************************************************************/ +static __inline CpaStatus +LacMem_OsContigAlignMemAlloc(void **ppMemAddr, + Cpa32U sizeBytes, + Cpa32U alignmentBytes, + Cpa32U node) +{ + if ((alignmentBytes & (alignmentBytes - 1)) != + 0) /* if is not power of 2 */ + { + *ppMemAddr = NULL; + QAT_UTILS_LOG("alignmentBytes MUST be the power of 2\n"); + return CPA_STATUS_INVALID_PARAM; + } + + *ppMemAddr = + qatUtilsMemAllocContiguousNUMA(sizeBytes, node, alignmentBytes); + + if (NULL == *ppMemAddr) { + return CPA_STATUS_RESOURCE; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro from the malloc() function + * + ******************************************************************************/ +#define LAC_OS_MALLOC(sizeBytes) malloc(sizeBytes, M_QAT, M_WAITOK) + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro from the LacMem_OsContigAlignMemAlloc function + * + ******************************************************************************/ +#define LAC_OS_CAMALLOC(ppMemAddr, sizeBytes, alignmentBytes, node) \ + LacMem_OsContigAlignMemAlloc((void *)ppMemAddr, \ + sizeBytes, \ + alignmentBytes, \ + node) + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro for declaration static const unsigned int constant. One provides + * the compilation time computation with the highest bit set in the + * sizeof(TYPE) value. The constant is being put by the linker by default in + * .rodata section + * + * E.g. Statement LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t) + * results in following entry: + * static const unsigned int highest_bit_of_lac_mem_blk_t = 3 + * + * CAUTION!! + * Macro is prepared only for type names NOT-containing ANY + * special characters. Types as amongst others: + * - void * + * - unsigned long + * - unsigned int + * are strictly forbidden and will result in compilation error. + * Use typedef to provide one-word type name for MACRO's usage. + ******************************************************************************/ +#define LAC_DECLARE_HIGHEST_BIT_OF(TYPE) \ + static const unsigned int highest_bit_of_##TYPE = \ + (sizeof(TYPE) & 0x80000000 ? 31 : (sizeof(TYPE) & 0x40000000 ? 30 : (sizeof(TYPE) & 0x20000000 ? 29 : ( \ + sizeof(TYPE) & 0x10000000 ? 28 : ( \ + sizeof(TYPE) & 0x08000000 ? 27 : ( \ + sizeof(TYPE) & 0x04000000 ? 26 : ( \ + sizeof(TYPE) & 0x02000000 ? 25 : ( \ + sizeof(TYPE) & 0x01000000 ? 24 : ( \ + sizeof(TYPE) & 0x00800000 ? \ + 23 : \ + (sizeof(TYPE) & 0x00400000 ? 22 : ( \ + sizeof( \ + TYPE) & \ + 0x00200000 ? \ + 21 : \ + ( \ + sizeof(TYPE) & 0x00100000 ? 20 : (sizeof(TYPE) & 0x00080000 ? 19 : ( \ + sizeof( \ + TYPE) & \ + 0x00040000 ? \ + 18 : \ + ( \ + sizeof(TYPE) & 0x00020000 ? 17 : ( \ + sizeof(TYPE) & 0x00010000 ? 16 : (sizeof(TYPE) & \ + 0x00008000 ? \ + 15 : \ + (sizeof(TYPE) & 0x00004000 ? 14 : ( \ + sizeof(TYPE) & 0x00002000 ? 13 : \ + ( \ + sizeof(TYPE) & 0x00001000 ? 12 : ( \ + sizeof(TYPE) & 0x00000800 ? 11 : ( \ + sizeof(TYPE) & 0x00000400 ? 10 : \ + ( \ + sizeof(TYPE) & \ + 0x00000200 ? \ + 9 : \ + (sizeof( \ + TYPE) & \ + 0x00000100 ? \ + 8 : \ + (sizeof(TYPE) & 0x00000080 ? 7 : \ + ( \ + sizeof(TYPE) & 0x00000040 ? \ + 6 : \ + ( \ + sizeof(TYPE) & 0x00000020 ? 5 : \ + ( \ + sizeof(TYPE) & 0x00000010 ? 4 : \ + ( \ + sizeof(TYPE) & 0x00000008 ? 3 : \ + ( \ + sizeof(TYPE) & 0x00000004 ? 2 : \ + ( \ + sizeof(TYPE) & 0x00000002 ? 1 : ( \ + sizeof(TYPE) & 0x00000001 ? 0 : 32))))))))))))))))) /*16*/))))))))))))))) /* 31 */ + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro frees the memory at the given address + * and resets the pointer to NULL + * + * @param[out] ppMemAddr address of pointer where mem address is stored. + * If pointer is NULL, the function will exit silently + * + * @retval void + * + ******************************************************************************/ +static __inline void +LacMem_OsMemFree(void **ppMemAddr) +{ + free(*ppMemAddr, M_QAT); + *ppMemAddr = NULL; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro frees the contiguous memory at the + * given address and resets the pointer to NULL + * + * @param[out] ppMemAddr address of pointer where mem address is stored. + * If pointer is NULL, the function will exit silently + * + * @retval void + * + ******************************************************************************/ +static __inline void +LacMem_OsContigAlignMemFree(void **ppMemAddr) +{ + if (NULL != *ppMemAddr) { + qatUtilsMemFreeNUMA(*ppMemAddr); + *ppMemAddr = NULL; + } +} + +#define LAC_OS_FREE(pMemAddr) LacMem_OsMemFree((void *)&pMemAddr) + +#define LAC_OS_CAFREE(pMemAddr) LacMem_OsContigAlignMemFree((void *)&pMemAddr) + +/** +******************************************************************************* + * @ingroup LacMem + * Copies user data to a working buffer of the correct size (required by + * PKE services) + * + * @description + * This function produces a correctly sized working buffer from the input + * user buffer. If the original buffer is too small a new buffer shall + * be allocated and memory is copied (left padded with zeros to the +*required + * length). + * + * The returned working buffer is guaranteed to be of the desired size for + * QAT. + * + * When this function is called pInternalMem describes the user_buffer and + * when the function returns pInternalMem describes the working buffer. + * This is because pInternalMem describes the memory that will be sent to + * QAT. + * + * The caller must keep the original buffer pointer. The alllocated buffer +*is + * freed (as necessary) using icp_LacBufferRestore(). + * + * @param[in] instanceHandle Handle to crypto instance so pke_resize mem pool +*can + * be located + * @param[in] pUserBuffer Pointer on the user buffer + * @param[in] userLen length of the user buffer + * @param[in] workingLen length of the working (correctly sized) buffer + * @param[in/out] pInternalMem pointer to boolean if TRUE on input then + * user_buffer is internally allocated memory + * if false then it is externally allocated. + * This value gets updated by the function + * if the returned pointer references internally + * allocated memory. + * + * @return a pointer to the working (correctly sized) buffer or NULL if the + * allocation failed + * + * @note the working length cannot be smaller than the user buffer length + * + * @warning the working buffer may be the same or different from the original + * user buffer; the caller should make no assumptions in this regard + * + * @see icp_LacBufferRestore() + * + ******************************************************************************/ +Cpa8U *icp_LacBufferResize(CpaInstanceHandle instanceHandle, + Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa32U workingLen, + CpaBoolean *pInternalMemory); + +/** +******************************************************************************* + * @ingroup LacMem + * Restores a user buffer + * + * @description + * This function restores a user buffer and releases its + * corresponding working buffer. The working buffer, assumed to be + * previously obtained using icp_LacBufferResize(), is freed as necessary. + * + * The contents are copied in the process. + * + * @note the working length cannot be smaller than the user buffer length + * + * @param[out] pUserBuffer Pointer on the user buffer + * @param[in] userLen length of the user buffer + * @param[in] pWorkingBuffer Pointer on the working buffer + * @param[in] workingLen working buffer length + * @param[in] copyBuf if set _TRUE the data in the workingBuffer + * will be copied to the userBuffer before the + * workingBuffer is freed. + * + * @return the status of the operation + * + * @see icp_LacBufferResize() + * + ******************************************************************************/ +CpaStatus icp_LacBufferRestore(Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa8U *pWorkingBuffer, + Cpa32U workingLen, + CpaBoolean copyBuf); + +/** +******************************************************************************* + * @ingroup LacMem + * Uses an instance specific user supplied virt2phys function to convert a + * virtual address to a physical address. + * + * @description + * Uses an instance specific user supplied virt2phys function to convert a + * virtual address to a physical address. A client of QA API can set the + * virt2phys function for an instance by using the + * cpaXxSetAddressTranslation() function. If the client does not set the + * virt2phys function and the instance is in kernel space then OS specific + * virt2phys function will be used. In user space the virt2phys function + * MUST be set by the user. + * + * @param[in] pVirtAddr the virtual addr to be converted + * @param[in] pServiceGen Pointer on the sal_service_t structure + * so client supplied virt2phys function can be + * called. + * + * @return the physical address + * + ******************************************************************************/ +CpaPhysicalAddr SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen); + +#endif /* LAC_MEM_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_mem_pools.h b/sys/dev/qat/qat_api/common/include/lac_mem_pools.h new file mode 100644 index 00000000000..e66769e3a26 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_mem_pools.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem_pools.h + * + * @defgroup LacMemPool Memory Pool Mgmt + * + * @ingroup LacCommon + * + * Memory Pool creation and mgmt functions + * + * @lld_start + * @lld_overview + * This component is designed as a set of utility functions for the + * creation of pre-allocated memory pools. Each pool will be created using OS + * memory with a user specified number of elements, element size and element + * alignment(alignmnet is at byte granularity). + * @lld_dependencies + * These utilities rely on QAT Utils for locking mechanisms and memory + *allocation + * @lld_initialisation + * Pool creation needs to be done by each component. There is no specific + * initialisation required for this feature. + * @lld_module_algorithms + * The following is a diagram of how the memory is layed out for each block + * in a pool. Each element must be aligned on the boundary requested for in the + * create call. In order to hide the management of the pools from the user, + * the memory block data is hidden prior to the + * data pointer. This way it can be accessed easily on a free call with pointer + * arithmatic. The Padding at the start is simply there for alignment and is + * unused in the pools. + * + * ------------------------------------------------------- + * + * |Padding |lac_mem_blk_t | client memory | + * + * @lld_process_context + * @lld_end + ***************************************************************************/ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * + * + ******************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_MEM_POOLS_H +#define LAC_MEM_POOLS_H + +#include "cpa.h" +#include "lac_common.h" +struct lac_mem_pool_hdr_s; +/**< @ingroup LacMemPool + * This is a forward declaration of the structure type lac_mem_pool_hdr_s */ + +typedef LAC_ARCH_UINT lac_memory_pool_id_t; +/**< @ingroup LacMemPool + * Pool ID type to be used by all clients */ + +/**< @ingroup LacMemPool + * This structure is used to link each memory block in the created pool + * together and contain the necessary information for deletion of the block + */ +typedef struct lac_mem_blk_s { + CpaPhysicalAddr physDataPtr; + /**< physical address of data pointer for client */ + void *pMemAllocPtr; + /**< virtual address of the memory block actually allocated */ + CpaBoolean isInUse; + /**< indicates if the pool item is in use */ + struct lac_mem_blk_s *pNext; + /**< link to next blcok in the pool */ + struct lac_mem_pool_hdr_s *pPoolID; + /**< identifier of the pool that this block was allocated from */ +} lac_mem_blk_t; + +#define LAC_MEM_POOL_VIRT_TO_PHYS(pVirtAddr) \ + (((lac_mem_blk_t *)((LAC_ARCH_UINT)pVirtAddr - sizeof(lac_mem_blk_t))) \ + ->physDataPtr) +/**< @ingroup LacMemPool + * macro for retreiving the physical address of the memory block. */ + +#define LAC_MEM_POOL_INIT_POOL_ID 0 +/**< @ingroup LacMemPool + * macro which defines the valid initialisation value for a pool ID. This is + * used as a level of abstraction for the user of this interface */ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function creates a memory pool containing a specified number of + * elements of specific size and byte alignment. This function is not reentrant + * or thread safe and is only intended to be called during initialisation. + * + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * No + * @param[out] poolID on successful creation of a pool this will + * be the ID used for all subsequent accesses + * @param[in] poolName The name of the memory pool + * @param[in] numElementsInPool number of elements to provision in the pool + * @param[in] blkSizeInBytes size in bytes of each element in the pool + * @param[in] blkAlignmentInBytes byte alignment required for each element + * @param[in] trackMemory track the memory in use by this pool + * @param[in] node node to allocate from + * + * @retval CPA_STATUS_INVALID_PARAM invalid input parameter + * @retval CPA_STATUS_RESOURCE error in provisioning resources + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolCreate(lac_memory_pool_id_t *poolID, + char *poolName, + unsigned int numElementsInPool, + unsigned int blkSizeInBytes, + unsigned int blkAlignmentInBytes, + CpaBoolean trackMemory, + Cpa32U node); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function will destroy the memory pool in it's current state. All memory + * blocks which have been returned to the memory pool will be de-allocated and + * the pool indetifier will be freed and assigned to NULL. It is the + * responsibility of the pool creators to return all memory before a destroy or + * memory will be leaked. + * + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * No + + * @param[in] poolID Pointer to the memory pool to destroy + * + ******************************************************************************/ +void Lac_MemPoolDestroy(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function allocates a block from the pool which has been previously + * created. It does not check the validity of the pool Id prior to accessing the + * pool. It is up to the calling code to ensure the value is correct. + * + * @blocking + * Yes + * @reentrant + * Yes + * @threadSafe + * Yes + * @param[in] poolID ID of the pool to allocate memory from + * + * @retval pointer to the memory which has been allocated from the pool + * + ******************************************************************************/ +void *Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function de-allocates the memory passed in back to the pool from which + * it was allocated. + * + * @blocking + * Yes + * @reentrant + * Yes + * @threadSafe + * Yes + * @param[in] entry memory address of the block to be freed + * + ******************************************************************************/ +void Lac_MemPoolEntryFree(void *entry); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function returns the number of available entries in a particular pool + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval number of elements left for allocation from the pool + * + ******************************************************************************/ +unsigned int Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function displays the stats associated with the memory pools + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + ******************************************************************************/ +void Lac_MemPoolStatsShow(void); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function initialises the physical addresses of the symmetric cookie + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function populates all PKE requests with instance constant parameters + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * @param[in] instanceHandle instanceHandle + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitAsymCookies(lac_memory_pool_id_t poolID, + CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function initialises the physical addresses of the compression cookie + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitDcCookiePhyAddr(lac_memory_pool_id_t poolID); + +#endif /*LAC_MEM_POOLS_H*/ diff --git a/sys/dev/qat/qat_api/common/include/lac_module.h b/sys/dev/qat/qat_api/common/include/lac_module.h new file mode 100644 index 00000000000..8fe95c2e4cf --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_module.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef __LAC_MODULE_H__ +#define __LAC_MODULE_H__ + +#include "icp_qat_hw.h" + +/* Lac module getter/setter for TUNABLE_INT in lac_module.c */ +icp_qat_hw_auth_mode_t Lac_GetQatHmacMode(void); +void Lac_SetQatHmacMode(const icp_qat_hw_auth_mode_t); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal.h b/sys/dev/qat/qat_api/common/include/lac_sal.h new file mode 100644 index 00000000000..0c431dd688e --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal.h @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_sal.h + * + * @defgroup SalCtrl Service Access Layer Controller + * + * @ingroup SalCtrl + * + * @description + * These functions are the functions to be executed for each state + * of the state machine for each service. + * + *****************************************************************************/ + +#ifndef LAC_SAL_H +#define LAC_SAL_H + +#include "cpa_cy_im.h" + +/** +******************************************************************************* + * @ingroup SalCtrl + * @description + * This function allocates memory for a specific instance type. + * Zeros this memory and sets the generic service section of + * the instance memory. + * + * @context + * This function is called from the generic services init. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] service The type of the service to be created + * (e.g. CRYPTO) + * @param[in] instance_num The logical instance number which will + * run the service + * @param[out] pObj Pointer to specific service instance memory + * @retVal CPA_STATUS_SUCCESS Instance memory successfully allocated + * @retVal CPA_STATUS_RESOURCE Instance memory not successfully allocated + * @retVal CPA_STATUS_FAIL Unsupported service type + * + *****************************************************************************/ +CpaStatus SalCtrl_ServiceCreate(sal_service_type_t service, + Cpa32U instance_num, + sal_service_t **pObj); + +/** +******************************************************************************* + * @ingroup SalCtl + * @description + * This macro goes through the 'list' passed in as a parameter. For each + * element found in the list, it peforms a cast to the type of the element + * given by the 'type' parameter. Finally, it calls the function given by + * the 'function' parameter, passing itself and the device as parameters. + * + * In case of error (i.e. 'function' does not return _SUCCESS or _RETRY) + * processing of the 'list' elements will stop and the status_ret will be + * updated. + * + * In case of _RETRY status_ret will be updated but the 'list' + * will continue to be processed. _RETRY is only expected when + * 'function' is stop. + * + * @context + * This macro is used by both the service and qat event handlers. + * + * @assumptions + * None + * @sideEffects + * None + * + * @param[in] list The list of services or qats as a type of list_t + * @param[in] type It identifies the type of the object inside the + * list: service or qat + * @param[in] device The ADF accelerator handle for the device + * @param[in] function The function pointer to call + * @param[in/out] status_ret If an error occured (i.e. status returned from + * function is not _SUCCESS) then status_ret is + * overwritten with status returned from function. + * + *****************************************************************************/ +#define SAL_FOR_EACH(list, type, device, function, status_ret) \ + do { \ + sal_list_t *curr_element = list; \ + CpaStatus status_temp = CPA_STATUS_SUCCESS; \ + typeof(type) *process = NULL; \ + while (NULL != curr_element) { \ + process = \ + (typeof(type) *)SalList_getObject(curr_element); \ + status_temp = process->function(device, process); \ + if ((CPA_STATUS_SUCCESS != status_temp) && \ + (CPA_STATUS_RETRY != status_temp)) { \ + status_ret = status_temp; \ + break; \ + } else { \ + if (CPA_STATUS_RETRY == status_temp) { \ + status_ret = status_temp; \ + } \ + } \ + curr_element = SalList_next(curr_element); \ + } \ + } while (0) + +/** +******************************************************************************* + * @ingroup SalCtl + * @description + * This macro goes through the 'list' passed in as a parameter. For each + * element found in the list, it peforms a cast to the type of the element + * given by the 'type' parameter. Finally, it checks the state of the + * element and if it is in state 'state_check' then it calls the + * function given by the 'function' parameter, passing itself + * and the device as parameters. + * If the element is not in 'state_check' it returns from the macro. + * + * In case of error (i.e. 'function' does not return _SUCCESS) + * processing of the 'list' elements will continue. + * + * @context + * This macro is used by both the service and qat event handlers. + * + * @assumptions + * None + * @sideEffects + * None + * + * @param[in] list The list of services or qats as a type of list_t + * @param[in] type It identifies the type of the object + * inside the list: service or qat + * @param[in] device The ADF accelerator handle for the device + * @param[in] function The function pointer to call + * @param[in] state_check The state to check for + * + *****************************************************************************/ +#define SAL_FOR_EACH_STATE(list, type, device, function, state_check) \ + do { \ + sal_list_t *curr_element = list; \ + typeof(type) *process = NULL; \ + while (NULL != curr_element) { \ + process = \ + (typeof(type) *)SalList_getObject(curr_element); \ + if (process->state == state_check) { \ + process->function(device, process); \ + } else { \ + break; \ + } \ + curr_element = SalList_next(curr_element); \ + } \ + } while (0) + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize an instance of crypto service. + * It creates a crypto instance's memory pools. It calls ADF to create + * its required transport handles. It calls the sub crypto service init + * functions. Resets the stats. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to start an instance of crypto service. + * It sends the first messages to FW on its crypto instance transport + * handles. For asymmetric crypto it verifies the header on the downloaded + * MMP library. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to stop an instance of crypto service. + * It checks for inflight messages to the FW. If no messages are pending + * it returns success. If messages are pending it returns retry. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to shutdown an instance of crypto service. + * It frees resources allocated at initialisation - e.g. frees the + * memory pools and ADF transport handles. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoShutdown(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function sets the capability info of crypto instances. + * + * @context + * This function is called from the cpaCyQueryCapabilities and + * LacSymSession_ParamCheck function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] service A sal_service_t* type + * @param[in] cyCapabilityInfo A CpaCyCapabilitiesInfo* type + * + *************************************************************************/ +void SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, + CpaCyCapabilitiesInfo *pCapInfo); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize an instance of compression service. + * It creates a compression instance's memory pools. It calls ADF to create + * its required transport handles. It zeros an instances stats. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionInit(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to start an instance of compression service. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionStart(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to stop an instance of compression service. + * It checks for inflight messages to the FW. If no messages are pending + * it returns success. If messages are pending it returns retry. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionStop(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to shutdown an instance of compression service. + * It frees resources allocated at initialisation - e.g. frees the + * memory pools and ADF transport handles. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionShutdown(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to get the number of services enabled + * from the config table. + * + * @context + * This function is called from the SalCtrl_QatInit + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] device An icp_accel_dev_t* type + * param[in] pEnabledServices pointer to a variable used to store + * the enabled services + * + *************************************************************************/ + +CpaStatus SalCtrl_GetEnabledServices(icp_accel_dev_t *device, + Cpa32U *pEnabledServices); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is enabled + * + * @context + * This function is called from the SalCtrl_QatInit + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] enabled_services + * param[in] service + * + *************************************************************************/ + +CpaBoolean SalCtrl_IsServiceEnabled(Cpa32U enabled_services, + sal_service_type_t service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is supported on the device + * The key difference between this and SalCtrl_GetSupportedServices() is + * that the latter treats it as an error if the service is unsupported. + * + * @context + * This can be called anywhere. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device + * param[in] service service or services to check + * + *************************************************************************/ +CpaBoolean SalCtrl_IsServiceSupported(icp_accel_dev_t *device, + sal_service_type_t service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether enabled services has associated + * hardware capability support + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device A pointer to an icp_accel_dev_t + * param[in] enabled_services It is the bitmask for the enabled services + *************************************************************************/ + +CpaStatus SalCtrl_GetSupportedServices(icp_accel_dev_t *device, + Cpa32U enabled_services); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h b/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h new file mode 100644 index 00000000000..f6c53928edf --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sal_ctrl.h + * + * @ingroup SalCtrl + * + * Functions to register and deregister qat and service controllers with ADF. + * + ***************************************************************************/ + +#ifndef LAC_SAL_CTRL_H +#define LAC_SAL_CTRL_H + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether the service component + * has been successfully started. + * + * @context + * This function is called from the icp_sal_userStart() function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + ******************************************************************/ + +CpaStatus SalCtrl_AdfServicesStartedCheck(void); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether the user's parameter + * for concurrent request is valid. + * + * @context + * This function is called when crypto or compression is init + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus validateConcurrRequest(Cpa32U numConcurrRequests); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to register adf services + * + * @context + * This function is called from do_userStart() function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus SalCtrl_AdfServicesRegister(void); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to unregister adf services. + * + * @context + * This function is called from do_userStart() function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus SalCtrl_AdfServicesUnregister(void); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_types.h b/sys/dev/qat/qat_api/common/include/lac_sal_types.h new file mode 100644 index 00000000000..36e14666578 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_types.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sal_types.h + * + * @ingroup SalCtrl + * + * Generic instance type definitions of SAL controller + * + ***************************************************************************/ + +#ifndef LAC_SAL_TYPES_H +#define LAC_SAL_TYPES_H + +#include "lac_sync.h" +#include "lac_list.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" +#include "icp_adf_debug.h" + +#define SAL_CFG_BASE_DEC 10 +#define SAL_CFG_BASE_HEX 16 + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Instance States + * + * @description + * An enumeration containing the possible states for an instance. + * + *****************************************************************************/ +typedef enum sal_service_state_s { + SAL_SERVICE_STATE_UNINITIALIZED = 0, + SAL_SERVICE_STATE_INITIALIZING, + SAL_SERVICE_STATE_INITIALIZED, + SAL_SERVICE_STATE_RUNNING, + SAL_SERVICE_STATE_SHUTTING_DOWN, + SAL_SERVICE_STATE_SHUTDOWN, + SAL_SERVICE_STATE_RESTARTING, + SAL_SERVICE_STATE_END +} sal_service_state_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Service Instance Types + * + * @description + * An enumeration containing the possible types for a service. + * + *****************************************************************************/ +typedef enum { + SAL_SERVICE_TYPE_UNKNOWN = 0, + /* symmetric and asymmetric crypto service */ + SAL_SERVICE_TYPE_CRYPTO = 1, + /* compression service */ + SAL_SERVICE_TYPE_COMPRESSION = 2, + /* inline service */ + SAL_SERVICE_TYPE_INLINE = 4, + /* asymmetric crypto only service*/ + SAL_SERVICE_TYPE_CRYPTO_ASYM = 8, + /* symmetric crypto only service*/ + SAL_SERVICE_TYPE_CRYPTO_SYM = 16, + SAL_SERVICE_TYPE_QAT = 32 +} sal_service_type_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Generic Instance Container + * + * @description + * Contains all the common information across the different instances. + * + *****************************************************************************/ +typedef struct sal_service_s { + sal_service_type_t type; + /**< Service type (e.g. SAL_SERVICE_TYPE_CRYPTO)*/ + + Cpa8U state; + /**< Status of the service instance + (e.g. SAL_SERVICE_STATE_INITIALIZED) */ + + Cpa32U instance; + /**< Instance number */ + + CpaVirtualToPhysical virt2PhysClient; + /**< Function pointer to client supplied virt_to_phys */ + + CpaStatus (*init)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance INIT function */ + CpaStatus (*start)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance START function */ + CpaStatus (*stop)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance STOP function */ + CpaStatus (*shutdown)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance SHUTDOWN function */ + + CpaCyInstanceNotificationCbFunc notification_cb; + /**< Function pointer for instance restarting handler */ + + void *cb_tag; + /**< Restarting handler priv data */ + + sal_statistics_collection_t *stats; + /**< Pointer to device statistics configuration */ + + void *debug_parent_dir; + /**< Pointer to parent proc dir entry */ + + CpaBoolean is_dyn; + + Cpa32U capabilitiesMask; + /**< Capabilities mask of the device */ + + Cpa32U dcExtendedFeatures; + /**< Bit field of features. I.e. Compress And Verify */ + + CpaBoolean isInstanceStarted; + /**< True if user called StartInstance on this instance */ + + CpaBoolean integrityCrcCheck; + /** < True if the device supports end to end data integrity checks */ +} sal_service_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * SAL structure + * + * @description + * Contains lists to crypto and compression instances. + * + *****************************************************************************/ +typedef struct sal_s { + sal_list_t *crypto_services; + /**< Container of sal_crypto_service_t */ + sal_list_t *asym_services; + /**< Container of sal_asym_service_t */ + sal_list_t *sym_services; + /**< Container of sal_sym_service_t */ + sal_list_t *compression_services; + /**< Container of sal_compression_service_t */ + debug_dir_info_t *cy_dir; + /**< Container for crypto proc debug */ + debug_dir_info_t *asym_dir; + /**< Container for asym proc debug */ + debug_dir_info_t *sym_dir; + /**< Container for sym proc debug */ + debug_dir_info_t *dc_dir; + /**< Container for compression proc debug */ + debug_file_info_t *ver_file; + /**< Container for version debug file */ +} sal_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * SAL debug structure + * + * @description + * Service debug handler + * + *****************************************************************************/ +typedef struct sal_service_debug_s { + icp_accel_dev_t *accel_dev; + debug_file_info_t debug_file; +} sal_service_debug_t; + +/** + ******************************************************************************* + * @ingroup SalCtrl + * This macro verifies that the right service type has been passed in. + * + * @param[in] pService pointer to service instance + * @param[in] service_type service type to check againstx. + * + * @return CPA_STATUS_FAIL Parameter is incorrect type + * + ******************************************************************************/ +#define SAL_CHECK_INSTANCE_TYPE(pService, service_type) \ + do { \ + sal_service_t *pGenericService = NULL; \ + pGenericService = (sal_service_t *)pService; \ + if (!(service_type & pGenericService->type)) { \ + QAT_UTILS_LOG("Instance handle type is incorrect.\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h b/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h new file mode 100644 index 00000000000..c7db231260e --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sal_types_crypto.h + * + * @ingroup SalCtrl + * + * Generic crypto instance type definition + * + ***************************************************************************/ + +#ifndef LAC_SAL_TYPES_CRYPTO_H_ +#define LAC_SAL_TYPES_CRYPTO_H_ + +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_key.h" +#include "cpa_cy_sym_dp.h" + +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "icp_adf_transport.h" +#include "lac_mem_pools.h" + +#define LAC_PKE_FLOW_ID_TAG 0xFFFFFFFC +#define LAC_PKE_ACCEL_ID_BIT_POS 1 +#define LAC_PKE_SLICE_ID_BIT_POS 0 + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Crypto specific Service Container + * + * @description + * Contains information required per crypto service instance. + * + *****************************************************************************/ +typedef struct sal_crypto_service_s { + sal_service_t generic_service_info; + /**< An instance of the Generic Service Container */ + + lac_memory_pool_id_t lac_sym_cookie_pool; + /**< Memory pool ID used for symmetric operations */ + lac_memory_pool_id_t lac_ec_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_prime_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_pke_req_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_pke_align_pool; + /**< Memory pool ID used for asymmetric operations */ + + QatUtilsAtomic *pLacSymStatsArr; + /**< pointer to an array of atomic stats for symmetric */ + + QatUtilsAtomic *pLacKeyStats; + /**< pointer to an array of atomic stats for key */ + + QatUtilsAtomic *pLacDhStatsArr; + /**< pointer to an array of atomic stats for DH */ + + QatUtilsAtomic *pLacDsaStatsArr; + /**< pointer to an array of atomic stats for Dsa */ + + QatUtilsAtomic *pLacRsaStatsArr; + /**< pointer to an array of atomic stats for Rsa */ + + QatUtilsAtomic *pLacEcStatsArr; + /**< pointer to an array of atomic stats for Ecc */ + + QatUtilsAtomic *pLacEcdhStatsArr; + /**< pointer to an array of atomic stats for Ecc DH */ + + QatUtilsAtomic *pLacEcdsaStatsArr; + /**< pointer to an array of atomic stats for Ecc DSA */ + + QatUtilsAtomic *pLacPrimeStatsArr; + /**< pointer to an array of atomic stats for prime */ + + QatUtilsAtomic *pLacLnStatsArr; + /**< pointer to an array of atomic stats for large number */ + + QatUtilsAtomic *pLacDrbgStatsArr; + /**< pointer to an array of atomic stats for DRBG */ + + Cpa32U pkeFlowId; + /**< Flow ID for all pke requests from this instance - identifies + accelerator + and execution engine to use */ + + icp_comms_trans_handle trans_handle_sym_tx; + icp_comms_trans_handle trans_handle_sym_rx; + + icp_comms_trans_handle trans_handle_asym_tx; + icp_comms_trans_handle trans_handle_asym_rx; + + icp_comms_trans_handle trans_handle_nrbg_tx; + icp_comms_trans_handle trans_handle_nrbg_rx; + + Cpa32U maxNumSymReqBatch; + /**< Maximum number of requests that can be placed on the sym tx ring + for any one batch request (DP api) */ + + Cpa16U acceleratorNum; + Cpa16U bankNum; + Cpa16U pkgID; + Cpa8U isPolled; + Cpa8U executionEngine; + Cpa32U coreAffinity; + Cpa32U nodeAffinity; + /**< Config Info */ + + CpaCySymDpCbFunc pSymDpCb; + /**< Sym DP Callback */ + + lac_sym_qat_hash_defs_t **pLacHashLookupDefs; + /**< table of pointers to standard defined information for all hash + algorithms. We support an extra hash algo that is not exported by + cy api which is why we need the extra +1 */ + Cpa8U **ppHmacContentDesc; + /**< table of pointers to CD for Hmac precomputes - used at session init + */ + + Cpa8U *pSslLabel; + /**< pointer to memory holding the standard SSL label ABBCCC.. */ + + lac_sym_key_tls_labels_t *pTlsLabel; + /**< pointer to memory holding the 4 standard TLS labels */ + + QatUtilsAtomic drbgErrorState; + /**< DRBG related variables */ + + lac_sym_key_tls_hkdf_sub_labels_t *pTlsHKDFSubLabel; + /**< pointer to memory holding the 4 HKDFLabels sublabels */ + + debug_file_info_t *debug_file; +/**< Statistics handler */ +} sal_crypto_service_t; + +/************************************************************************* + * @ingroup cpaCyCommon + * @description + * This function returns a valid asym/sym/crypto instance handle for the + * system if it exists. When requesting an instance handle of type sym or + * asym, if either is not found then a crypto instance handle is returned + * if found, since a crypto handle supports both sym and asym services. + * Similarly when requesting a crypto instance handle, if it is not found + * then an asym or sym crypto instance handle is returned. + * + * @performance + * To avoid calling this function the user of the QA api should not use + * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. + * + * @context + * This function is called whenever instanceHandle = + *CPA_INSTANCE_HANDLE_SINGLE + * at the QA Cy api. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] svc_type Type of crypto service requested. + * + * @retval Pointer to first crypto instance handle or NULL if no crypto + * instances in the system. + * + *************************************************************************/ + +CpaInstanceHandle Lac_GetFirstHandle(sal_service_type_t svc_type); + +#endif /*LAC_SAL_TYPES_CRYPTO_H_*/ diff --git a/sys/dev/qat/qat_api/common/include/lac_sync.h b/sys/dev/qat/qat_api/common/include/lac_sync.h new file mode 100644 index 00000000000..b842cce30d8 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sync.h @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sync.h + * + * @defgroup LacSync LAC synchronous + * + * @ingroup LacCommon + * + * Function prototypes and defines for synchronous support + * + ***************************************************************************/ + +#ifndef LAC_SYNC_H +#define LAC_SYNC_H + +#include "cpa.h" +#include "qat_utils.h" +#include "lac_mem.h" + +/** + ***************************************************************************** + * @ingroup LacSync + * + * @description + * LAC cookie for synchronous support + * + *****************************************************************************/ +typedef struct lac_sync_op_data_s { + struct sema *sid; + /**< Semaphore to signal */ + CpaStatus status; + /**< Output - Status of the QAT response */ + CpaBoolean opResult; + /**< Output - Verification of the operation/protocol status */ + CpaBoolean complete; + /**< Output - Operation is complete */ + CpaBoolean canceled; + /**< Output - Operation canceled */ +} lac_sync_op_data_t; + +#define LAC_PKE_SYNC_CALLBACK_TIMEOUT (5000) +/**< @ingroup LacSync + * Timeout waiting for an async callbacks in msecs. + * This is derived from the max latency of a PKE request + 1 sec + */ + +#define LAC_SYM_DRBG_POLL_AND_WAIT_TIME_MS (10) +/**< @ingroup LacSyn + * Default interval DRBG polling in msecs */ + +#define LAC_SYM_SYNC_CALLBACK_TIMEOUT (300) +/**< @ingroup LacSyn + * Timeout for wait for symmetric response in msecs +*/ + +#define LAC_INIT_MSG_CALLBACK_TIMEOUT (1922) +/**< @ingroup LacSyn + * Timeout for wait for init messages response in msecs +*/ + +#define DC_SYNC_CALLBACK_TIMEOUT (1000) +/**< @ingroup LacSyn + * Timeout for wait for compression response in msecs */ + +#define LAC_SYN_INITIAL_SEM_VALUE (0) +/**< @ingroup LacSyn + * Initial value of the sync waiting semaphore */ + +/** + ******************************************************************************* + * @ingroup LacSync + * This function allocates a sync op data cookie + * and creates and initialises the QAT Utils semaphore + * + * @param[in] ppSyncCallbackCookie Pointer to synch op data + * + * @retval CPA_STATUS_RESOURCE Failed to allocate the memory for the cookie. + * @retval CPA_STATUS_SUCCESS Success + * + ******************************************************************************/ +static __inline CpaStatus +LacSync_CreateSyncCookie(lac_sync_op_data_t **ppSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + *ppSyncCallbackCookie = + malloc(sizeof(lac_sync_op_data_t), M_QAT, M_WAITOK); + + if (CPA_STATUS_SUCCESS == status) { + status = LAC_INIT_SEMAPHORE((*ppSyncCallbackCookie)->sid, + LAC_SYN_INITIAL_SEM_VALUE); + (*ppSyncCallbackCookie)->complete = CPA_FALSE; + (*ppSyncCallbackCookie)->canceled = CPA_FALSE; + } + + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(*ppSyncCallbackCookie); + } + + return status; +} + +/** + ******************************************************************************* + * @ingroup LacSync + * This macro frees a sync op data cookie and destroys the QAT Utils + *semaphore + * + * @param[in] ppSyncCallbackCookie Pointer to sync op data + * + * @return void + ******************************************************************************/ +static __inline CpaStatus +LacSync_DestroySyncCookie(lac_sync_op_data_t **ppSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* + * If the operation has not completed, cancel it instead of destroying + * the + * cookie. Otherwise, the callback might panic. In this case, the cookie + * will leak, but it's better than a panic. + */ + if (!(*ppSyncCallbackCookie)->complete) { + QAT_UTILS_LOG( + "Attempting to destroy an incomplete sync cookie\n"); + (*ppSyncCallbackCookie)->canceled = CPA_TRUE; + return CPA_STATUS_FAIL; + } + + status = LAC_DESTROY_SEMAPHORE((*ppSyncCallbackCookie)->sid); + LAC_OS_FREE(*ppSyncCallbackCookie); + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will wait for a sync callback on a given cookie. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * @param[in] timeOut Time to wait for callback (msec) + * @param[out] pStatus Status returned by the callback + * @param[out] pOpStatus Operation status returned by callback. + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_SUCCESS Fail waiting for a callback + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_WaitForCallback(lac_sync_op_data_t *pSyncCallbackCookie, + Cpa32S timeOut, + CpaStatus *pStatus, + CpaBoolean *pOpStatus) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LAC_WAIT_SEMAPHORE(pSyncCallbackCookie->sid, timeOut); + + if (CPA_STATUS_SUCCESS == status) { + *pStatus = pSyncCallbackCookie->status; + if (NULL != pOpStatus) { + *pOpStatus = pSyncCallbackCookie->opResult; + } + pSyncCallbackCookie->complete = CPA_TRUE; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will check for a sync callback on a given cookie. + * Returns whether the callback has happened or not, no timeout. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * @param[in] timeOut Time to wait for callback (msec) + * @param[out] pStatus Status returned by the callback + * @param[out] pOpStatus Operation status returned by callback. + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Fail waiting for a callback + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_CheckForCallback(lac_sync_op_data_t *pSyncCallbackCookie, + CpaStatus *pStatus, + CpaBoolean *pOpStatus) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LAC_CHECK_SEMAPHORE(pSyncCallbackCookie->sid); + + if (CPA_STATUS_SUCCESS == status) { + *pStatus = pSyncCallbackCookie->status; + if (NULL != pOpStatus) { + *pOpStatus = pSyncCallbackCookie->opResult; + } + pSyncCallbackCookie->complete = CPA_TRUE; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will mark a sync cookie as complete. + * If it's known that the callback will not happen it's necessary + * to call this, else the cookie can't be destroyed. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Failed to mark as complete + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_SetSyncCookieComplete(lac_sync_op_data_t *pSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_FAIL; + + if (NULL != pSyncCallbackCookie) { + pSyncCallbackCookie->complete = CPA_TRUE; + status = CPA_STATUS_SUCCESS; + } + return status; +} +/** + ***************************************************************************** + * @ingroup LacSync + * Generic verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status element of that cookie structure and kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[out] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + *****************************************************************************/ +void LacSync_GenVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic flatbuffer callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status element of that cookie structure and kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] pOut Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenFlatBufCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic flatbuffer verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * @param[out] pOut Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenFlatBufVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic dual flatbuffer verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * @param[out] pOut0 Pointer to the flat buffer + * @param[out] pOut1 Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenDualFlatBufVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut0, + CpaFlatBuffer *pOut1); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic wake up function. + * @description + * This function is used when the API is called in synchronous + * mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set + * the status element of that cookie structure and kick the + * sid. + * This function maybe called from an async callback. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * + * @return void + *****************************************************************************/ +void LacSync_GenWakeupSyncCaller(void *callbackTag, CpaStatus status); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic wake up verify function. + * @description + * This function is used when the API is called in synchronous + * mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set + * the status element and the opResult of that cookie structure + * and kick the sid. + * This function maybe called from an async callback. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + *****************************************************************************/ +void LacSync_GenVerifyWakeupSyncCaller(void *callbackTag, + CpaStatus status, + CpaBoolean opResult); + +#endif /*LAC_SYNC_H*/ diff --git a/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h b/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h new file mode 100644 index 00000000000..8cd7b08e84e --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_qat_cmn_msg.c + * + * @ingroup SalQatCmnMessage + * + * @description + * Implementation for populating the common (across services) QAT structures. + * + *****************************************************************************/ +#ifndef SAL_QAT_CMN_MSG_H +#define SAL_QAT_CMN_MSG_H +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "qat_utils.h" + +#include "cpa_cy_sym.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" + +#include "icp_qat_hw.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_la.h" + +/** + ****************************************************************************** + * @ingroup SalQatCmnMessage + * content descriptor info structure + * + * @description + * This structure contains generic information on the content descriptor + * + *****************************************************************************/ +typedef struct sal_qat_content_desc_info_s { + CpaPhysicalAddr hardwareSetupBlockPhys; + /**< Physical address of hardware setup block of the content descriptor + */ + void *pData; + /**< Virtual Pointer to the hardware setup block of the content + * descriptor */ + Cpa8U hwBlkSzQuadWords; + /**< Hardware Setup Block size in quad words */ +} sal_qat_content_desc_info_t; + +/** + ******************************************************************************* + * @ingroup SalQatCmnMessage + * Lookaside response handler function type + * + * @description + * This type definition specifies the function prototype for handling the + * response messages for a specific symmetric operation + * + * @param[in] lacCmdId Look Aside Command ID + * + * @param[in] pOpaqueData Pointer to Opaque Data + * + * @param[in] cmnRespFlags Common Response flags + * + * @return void + * + *****************************************************************************/ +typedef void (*sal_qat_resp_handler_func_t)(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +/******************************************************************** + * @ingroup SalQatMsg_CmnHdrWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t + * section of the Request Msg. Build LW0 + LW1 - + * service part of the request + * + * @param[in] pMsg Pointer to 128B Request Msg buffer + * @param[in] serviceType type of service request + * @param[in] serviceCmdId id for the type of service request + * @param[in] cmnFlags common request flags + * @param[in] serviceCmdFlags service command flahgs + * + * @return + * None + * + *****************************************/ +void SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, + icp_qat_fw_comn_request_id_t serviceType, + uint8_t serviceCmdId, + icp_qat_fw_comn_flags cmnFlags, + icp_qat_fw_serv_specif_flags serviceCmdFlags); + +/******************************************************************** + * @ingroup SalQatMsg_CmnMidWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_mid_t + * section of the Request Msg and the corresponding SGL/Flat flag + * in the Hdr. + * + * @param[in] pReq Pointer to 128B Request Msg buffer + * @param[in] pOpaqueData Pointer to opaque data used by callback + * @param[in] bufferFormat src and dst Buffers are either SGL or Flat + format + * @param[in] pSrcBuffer Address of source buffer + * @param[in] pDstBuffer Address of destination buffer + * @param[in] pSrcLength Length of source buffer + * @param[in] pDstLength Length of destination buffer + * + + * @assumptions + * All fields in mid section are zero before fn is called + + * @return + * None + * + *****************************************/ +void SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, + const void *pOpaqueData, + Cpa8U bufferFormat, + Cpa64U srcBuffer, + Cpa64U dstBuffer, + Cpa32U srcLength, + Cpa32U dstLength); + +/******************************************************************** + * @ingroup SalQatMsg_ContentDescHdrWrite + * + * @description + * This function fills in all fields in the + *icp_qat_fw_comn_req_hdr_cd_pars_t + * section of the Request Msg. + * + * @param[in] pMsg Pointer to 128B Request Msg buffer. + * @param[in] pContentDescInfo content descripter info. + * + * @return + * none + * + *****************************************/ +void SalQatMsg_ContentDescHdrWrite( + icp_qat_fw_comn_req_t *pMsg, + const sal_qat_content_desc_info_t *pContentDescInfo); + +/******************************************************************** + * @ingroup SalQatMsg_CtrlBlkSetToReserved + * + * @description + * This function set the whole contrle block to a reserved state. + * + * @param[in] _pMsg Pointer to 128B Request Msg buffer. + * + * @return + * none + * + *****************************************/ +void SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *_pMsg); + +/******************************************************************** + * @ingroup SalQatMsg_transPutMsg + * + * @description + * + * + * @param[in] trans_handle + * @param[in] pqat_msg + * @param[in] size_in_lws + * @param[in] service + * + * @return + * CpaStatus + * + *****************************************/ +CpaStatus SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, + void *pqat_msg, + Cpa32U size_in_lws, + Cpa8U service); + +/******************************************************************** + * @ingroup SalQatMsg_updateQueueTail + * + * @description + * + * + * @param[in] trans_handle + * + * + * @return + * CpaStatus + * + *****************************************/ +void SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_hnd); +#endif diff --git a/sys/dev/qat/qat_api/common/include/sal_service_state.h b/sys/dev/qat/qat_api/common/include/sal_service_state.h new file mode 100644 index 00000000000..3712d38cc3a --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_service_state.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_service_state.h + * + * @defgroup SalServiceState + * + * @ingroup SalCtrl + * + * Checks state for generic service instance + * + ***************************************************************************/ + +#ifndef SAL_SERVICE_STATE_H_ +#define SAL_SERVICE_STATE_H_ + +/** +******************************************************************************* + * @ingroup SalServiceState + * Check to see if the instance is in the running state + * + * @description + * This function checks the state of an instance to see if it is in the + * running state + * + * @param[in] instance Instance handle (assumes this is valid, i.e. checked + * before this function is called) + * @retval CPA_TRUE Instance in the RUNNING state + * @retval CPA_FALSE Instance not in RUNNING state + * + *****************************************************************************/ +CpaBoolean Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* + * @ingroup SalServiceState + * Check to see if the instance is beign restarted + * + * @description + * This function checks the state of an instance to see if the device it + * uses is being restarted because of hardware error. + * + * @param[in] instance Instance handle (assumes this is valid, i.e. checked + * before this function is called) + * @retval CPA_TRUE Device the instance is using is restarting. + * @retval CPA_FALSE Device the instance is running. + * + *****************************************************************************/ +CpaBoolean Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup SalServiceState + * This macro checks if an instance is running. An error message is logged + * if it is not in a running state. + * + * @return CPA_STATUS_FAIL Instance not in RUNNING state. + * @return void Instance is in RUNNING state. + ******************************************************************************/ +#define SAL_RUNNING_CHECK(instanceHandle) \ + do { \ + if (unlikely(CPA_TRUE != \ + Sal_ServiceIsRunning(instanceHandle))) { \ + if (CPA_TRUE == \ + Sal_ServiceIsRestarting(instanceHandle)) { \ + return CPA_STATUS_RESTARTING; \ + } \ + QAT_UTILS_LOG("Instance not in a Running state\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup SalServiceState + * This macro checks if an instance is in a state to get init event. + * + * @return CPA_STATUS_FAIL Instance not in good state. + * @return void Instance is in good state. + ******************************************************************************/ +#define SAL_SERVICE_GOOD_FOR_INIT(instanceHandle) \ + do { \ + sal_service_t *pService = (sal_service_t *)instanceHandle; \ + if ((SAL_SERVICE_STATE_UNINITIALIZED != pService->state) && \ + (SAL_SERVICE_STATE_RESTARTING != pService->state)) { \ + QAT_UTILS_LOG( \ + "Not in the correct state to call init\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +#endif /*SAL_SERVICE_STATE_H_*/ diff --git a/sys/dev/qat/qat_api/common/include/sal_statistics.h b/sys/dev/qat/qat_api/common/include/sal_statistics.h new file mode 100644 index 00000000000..47c08bc6eae --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_statistics.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_statistics.h + * + * @ingroup SalStats + * + * @description + * Statistics related defines, structures and functions + * + *****************************************************************************/ + +#ifndef SAL_STATISTICS_H +#define SAL_STATISTICS_H + +#include "sal_statistics_strings.h" + +#define SAL_STATS_SYM 0 +#define SAL_STATS_DSA 1 +#define SAL_STATS_DSA2 2 +#define SAL_STATS_RSA 3 +#define SAL_STATS_DH 4 +#define SAL_STATS_KEYGEN 5 +#define SAL_STATS_LN 6 +#define SAL_STATS_PRIME 7 +#define SAL_STATS_ECC 8 +#define SAL_STATS_ECDH 9 +#define SAL_STATS_ECDSA 10 +/**< Numeric values for crypto statistics */ + +#define SAL_STATISTICS_STRING_OFF "0" +/**< String representing the value for disabled statistics */ + +/** +***************************************************************************** + * @ingroup SalStats + * Structure describing stats enabled/disabled in the system + * + * @description + * Structure describing stats enabled/disabled in the system + * + *****************************************************************************/ +typedef struct sal_statistics_collection_s { + CpaBoolean bStatsEnabled; + /**< If CPA_TRUE then statistics functionality is enabled */ + CpaBoolean bDcStatsEnabled; + /**< If CPA_TRUE then Compression statistics are enabled */ + CpaBoolean bDhStatsEnabled; + /**< If CPA_TRUE then Diffie-Helman statistics are enabled */ + CpaBoolean bDsaStatsEnabled; + /**< If CPA_TRUE then DSA statistics are enabled */ + CpaBoolean bEccStatsEnabled; + /**< If CPA_TRUE then ECC statistics are enabled */ + CpaBoolean bKeyGenStatsEnabled; + /**< If CPA_TRUE then Key Gen statistics are enabled */ + CpaBoolean bLnStatsEnabled; + /**< If CPA_TRUE then Large Number statistics are enabled */ + CpaBoolean bPrimeStatsEnabled; + /**< If CPA_TRUE then Prime statistics are enabled */ + CpaBoolean bRsaStatsEnabled; + /**< If CPA_TRUE then RSA statistics are enabled */ + CpaBoolean bSymStatsEnabled; + /**< If CPA_TRUE then Symmetric Crypto statistics are enabled */ +} sal_statistics_collection_t; + +/** + ****************************************************************************** + * @ingroup SalStats + * + * @description + * Initializes structure describing which statistics + * are enabled for the acceleration device. + * + * @param[in] device Pointer to an acceleration device structure + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_RESOURCE Memory alloc failed + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +CpaStatus SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device); + +/** + ****************************************************************************** + * @ingroup SalStats + * + * @description + * Cleans structure describing which statistics + * are enabled for the acceleration device. + * + * @param[in] device Pointer to an acceleration device structure + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +CpaStatus SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device); +#endif diff --git a/sys/dev/qat/qat_api/common/include/sal_string_parse.h b/sys/dev/qat/qat_api/common/include/sal_string_parse.h new file mode 100644 index 00000000000..8654f2c0944 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_string_parse.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_string_parse.h + * + * @defgroup SalStringParse + * + * @ingroup SalStringParse + * + * @description + * This file contains string parsing functions + * + *****************************************************************************/ + +#ifndef SAL_STRING_PARSE_H +#define SAL_STRING_PARSE_H + +/* Maximum size of the strings used by SAL */ +#define SAL_CFG_MAX_VAL_LEN_IN_BYTES 64 + +/** +******************************************************************************* + * @ingroup SalStringParse + * Builds a string and store it in result + * + * @description + * The result string will be the concatenation of string1, instanceNumber + * and string2. The size of result has to be SAL_CFG_MAX_VAL_LEN_IN_BYTES. + * We can't check this in this function, this is the user responsibility + * + * @param[in] string1 First string to concatenate + * @param[in] instanceNumber Instance number + * @param[in] string2 Second string to concatenate + * @param[out] result Resulting string of concatenation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * + *****************************************************************************/ +CpaStatus Sal_StringParsing(char *string1, + Cpa32U instanceNumber, + char *string2, + char *result); + +/** +******************************************************************************* + * @ingroup SalStringParse + * Convert a string to an unsigned long + * + * @description + * Parses the string cp in the specified base, and returned it as an + * unsigned long value. + * + * @param[in] cp String to be converted + * @param[in] endp Pointer to the end of the string. This parameter + * can also be NULL and will not be used in this case + * @param[in] cfgBase Base to convert the string + * + * @retval The string converted to an unsigned long + * + *****************************************************************************/ +Cpa64U Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase); + +#endif /* SAL_STRING_PARSE_H */ diff --git a/sys/dev/qat/qat_api/common/include/sal_types_compression.h b/sys/dev/qat/qat_api/common/include/sal_types_compression.h new file mode 100644 index 00000000000..12f9f673ac4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_types_compression.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_types_compression.h + * + * @ingroup SalCtrl + * + * Generic compression instance type definition + * + ***************************************************************************/ +#ifndef SAL_TYPES_COMPRESSION_H_ +#define SAL_TYPES_COMPRESSION_H_ + +#include "cpa_dc.h" +#include "cpa_dc_dp.h" +#include "lac_sal_types.h" +#include "icp_qat_hw.h" +#include "icp_buffer_desc.h" + +#include "lac_mem_pools.h" +#include "icp_adf_transport.h" + +#define DC_NUM_RX_RINGS (1) + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Compression device specific data + * + * @description + * Contains device specific information for a compression service. + * + *****************************************************************************/ +typedef struct sal_compression_device_data { + /* Device specific minimum output buffer size for static compression */ + Cpa32U minOutputBuffSize; + + /* Enable/disable secureRam/acceleratorRam for intermediate buffers*/ + Cpa8U useDevRam; + + /* When set, implies device can decompress interim odd byte length + * stateful decompression requests. + */ + CpaBoolean oddByteDecompInterim; + + /* When set, implies device can decompress odd byte length + * stateful decompression requests when bFinal is absent + */ + CpaBoolean oddByteDecompNobFinal; + + /* Flag to indicate if translator slice overflow is supported */ + CpaBoolean translatorOverflow; + + /* Flag to enable/disable delayed match mode */ + icp_qat_hw_compression_delayed_match_t enableDmm; + + Cpa32U inflateContextSize; + Cpa8U highestHwCompressionDepth; + + /* Mask that reports supported window sizes for comp/decomp */ + Cpa8U windowSizeMask; + + /* Flag to indicate CompressAndVerifyAndRecover feature support */ + CpaBoolean cnvnrSupported; +} sal_compression_device_data_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Compression specific Service Container + * + * @description + * Contains information required per compression service instance. + * + *****************************************************************************/ +typedef struct sal_compression_service_s { + /* An instance of the Generic Service Container */ + sal_service_t generic_service_info; + + /* Memory pool ID used for compression */ + lac_memory_pool_id_t compression_mem_pool; + + /* Pointer to an array of atomic stats for compression */ + QatUtilsAtomic *pCompStatsArr; + + /* Size of the DRAM intermediate buffer in bytes */ + Cpa64U minInterBuffSizeInBytes; + + /* Number of DRAM intermediate buffers */ + Cpa16U numInterBuffs; + + /* Address of the array of DRAM intermediate buffers*/ + icp_qat_addr_width_t *pInterBuffPtrsArray; + CpaPhysicalAddr pInterBuffPtrsArrayPhyAddr; + + icp_comms_trans_handle trans_handle_compression_tx; + icp_comms_trans_handle trans_handle_compression_rx; + + /* Maximum number of in flight requests */ + Cpa32U maxNumCompConcurrentReq; + + /* Callback function defined for the DcDp API compression session */ + CpaDcDpCallbackFn pDcDpCb; + + /* Config info */ + Cpa16U acceleratorNum; + Cpa16U bankNum; + Cpa16U pkgID; + Cpa16U isPolled; + Cpa32U coreAffinity; + Cpa32U nodeAffinity; + + sal_compression_device_data_t comp_device_data; + + /* Statistics handler */ + debug_file_info_t *debug_file; +} sal_compression_service_t; + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function returns a valid compression instance handle for the system + * if it exists. + * + * @performance + * To avoid calling this function the user of the QA api should not use + * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. + * + * @context + * This function is called whenever instanceHandle = + * CPA_INSTANCE_HANDLE_SINGLE at the QA Dc api. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval Pointer to first compression instance handle or NULL if no + * compression instances in the system. + * + *************************************************************************/ +CpaInstanceHandle dcGetFirstHandle(void); + +#endif /*SAL_TYPES_COMPRESSION_H_*/ diff --git a/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c b/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c new file mode 100644 index 00000000000..4331f875aa6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_qat_cmn_msg.h + * + * @defgroup SalQatCmnMessage + * + * @ingroup SalQatCmnMessage + * + * Interfaces for populating the common QAT structures for a lookaside + * operation. + * + *****************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "sal_qat_cmn_msg.h" + +/******************************************************************** + * @ingroup SalQatMsg_CmnHdrWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t + * section of the Request Msg. Build LW0 + LW1 - + * service part of the request + * + * @param[in] pMsg Pointer to 128B Request Msg buffer + * @param[in] serviceType type of service request + * @param[in] serviceCmdId id for the type of service request + * @param[in] cmnFlags common request flags + * @param[in] serviceCmdFlags service command flahgs + * + * @return + * None + * + *****************************************/ +void +SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, + icp_qat_fw_comn_request_id_t serviceType, + uint8_t serviceCmdId, + icp_qat_fw_comn_flags cmnFlags, + icp_qat_fw_serv_specif_flags serviceCmdFlags) +{ + icp_qat_fw_comn_req_hdr_t *pHeader = &(pMsg->comn_hdr); + + /* LW0 */ + pHeader->hdr_flags = + ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET); + pHeader->service_type = (uint8_t)serviceType; + pHeader->service_cmd_id = serviceCmdId; + pHeader->resrvd1 = 0; + /* LW1 */ + pHeader->comn_req_flags = cmnFlags; + pHeader->serv_specif_flags = serviceCmdFlags; +} + +/******************************************************************** + * @ingroup SalQatCmnMessage + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_mid_t + * section of the Request Msg and the corresponding SGL/Flat flag + * in the Hdr. + * + * @param[in] pReq Pointer to 128B Request Msg buffer + * @param[in] pOpaqueData Pointer to opaque data used by callback + * @param[in] bufferFormat src and dst Buffers are either SGL or Flat + * format + * @param[in] pSrcBuffer Address of source buffer + * @param[in] pDstBuffer Address of destination buffer + * @param[in] pSrcLength Length of source buffer + * @param[in] pDstLength Length of destination buffer + * + + * @assumptions + * All fields in mid section are zero before fn is called + + * @return + * None + * + *****************************************/ +void inline SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, + const void *pOpaqueData, + Cpa8U bufferFormat, + Cpa64U srcBuffer, + Cpa64U dstBuffer, + Cpa32U srcLength, + Cpa32U dstLength) +{ + icp_qat_fw_comn_req_mid_t *pMid = &(pReq->comn_mid); + + LAC_MEM_SHARED_WRITE_FROM_PTR(pMid->opaque_data, pOpaqueData); + pMid->src_data_addr = srcBuffer; + + /* In place */ + if (0 == dstBuffer) { + pMid->dest_data_addr = srcBuffer; + } + /* Out of place */ + else { + pMid->dest_data_addr = dstBuffer; + } + + if (bufferFormat == QAT_COMN_PTR_TYPE_SGL) { + /* Using ScatterGatherLists so set flag in header */ + ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, + QAT_COMN_PTR_TYPE_SGL); + + /* Assumption: No need to set src and dest length in this case + * as not + * used */ + + } else { + /* Using Flat buffers so set flag in header */ + ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, + QAT_COMN_PTR_TYPE_FLAT); + + pMid->src_length = srcLength; + pMid->dst_length = dstLength; + } +} + +/******************************************************************** + * @ingroup SalQatMsg_ContentDescHdrWrite + * + * @description + * This function fills in all fields in the + * icp_qat_fw_comn_req_hdr_cd_pars_t section of the Request Msg. + * + * @param[in] pMsg Pointer to 128B Request Msg buffer. + * @param[in] pContentDescInfo content descripter info. + * + * @return + * none + * + *****************************************/ +void +SalQatMsg_ContentDescHdrWrite( + icp_qat_fw_comn_req_t *pMsg, + const sal_qat_content_desc_info_t *pContentDescInfo) +{ + icp_qat_fw_comn_req_hdr_cd_pars_t *pCd_pars = &(pMsg->cd_pars); + + pCd_pars->s.content_desc_addr = + pContentDescInfo->hardwareSetupBlockPhys; + pCd_pars->s.content_desc_params_sz = pContentDescInfo->hwBlkSzQuadWords; + pCd_pars->s.content_desc_resrvd1 = 0; + pCd_pars->s.content_desc_hdr_resrvd2 = 0; + pCd_pars->s.content_desc_resrvd3 = 0; +} + +/******************************************************************** + * @ingroup SalQatMsg_CtrlBlkSetToReserved + * + * @description + * This function sets the whole control block to a reserved state. + * + * @param[in] _pMsg Pointer to 128B Request Msg buffer. + * + * @return + * none + * + *****************************************/ +void +SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *pMsg) +{ + + icp_qat_fw_comn_req_cd_ctrl_t *pCd_ctrl = &(pMsg->cd_ctrl); + + memset(pCd_ctrl, 0, sizeof(icp_qat_fw_comn_req_cd_ctrl_t)); +} + +/******************************************************************** + * @ingroup SalQatMsg_transPutMsg + * + * @description + * + * + * @param[in] trans_handle + * @param[in] pqat_msg + * @param[in] size_in_lws + * @param[in] service + * + * @return + * CpaStatus + * + *****************************************/ +CpaStatus +SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, + void *pqat_msg, + Cpa32U size_in_lws, + Cpa8U service) +{ + return icp_adf_transPutMsg(trans_handle, pqat_msg, size_in_lws); +} + +void +SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_handle) +{ + icp_adf_updateQueueTail(trans_handle); +} diff --git a/sys/dev/qat/qat_api/common/stubs/lac_stubs.c b/sys/dev/qat/qat_api/common/stubs/lac_stubs.c new file mode 100644 index 00000000000..b9c0c3237a6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/stubs/lac_stubs.c @@ -0,0 +1,413 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * + * @file lac_stubs.c + * + * @defgroup kernel stubs + * + * All PKE and KPT API won't be supported in kernel API + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +/* API Includes */ +#include "cpa.h" +#include "cpa_cy_dh.h" +#include "cpa_cy_dsa.h" +#include "cpa_cy_ecdh.h" +#include "cpa_cy_ecdsa.h" +#include "cpa_cy_ec.h" +#include "cpa_cy_prime.h" +#include "cpa_cy_rsa.h" +#include "cpa_cy_ln.h" +#include "cpa_dc.h" +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_sal_poll.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_sym_dp.h" +#include "cpa_cy_key.h" +#include "cpa_cy_common.h" +#include "cpa_cy_im.h" +#include "icp_sal_user.h" + +/* Diffie Hellman */ +CpaStatus +cpaCyDhKeyGenPhase1(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase1Cb, + void *pCallbackTag, + const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, + CpaFlatBuffer *pLocalOctetStringPV) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhKeyGenPhase2Secret( + const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase2Cb, + void *pCallbackTag, + const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, + CpaFlatBuffer *pOctetStringSecretKey) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDhStats64 *pDhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyDhStats *pDhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* DSA */ +CpaStatus +cpaCyDsaGenPParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaPParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pP) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaGenGParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaGParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pG) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaGenYParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaYParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pY) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaRSSignCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyDsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyDsaStats *pDsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDsaStats64 *pDsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* ECDH */ +CpaStatus +cpaCyEcdhPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcdhPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdhPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdhStats64 *pEcdhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* ECDSA */ +CpaStatus +cpaCyEcdsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignROpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaSignRSCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignRSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdsaStats64 *pEcdsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* EC */ +CpaStatus +cpaCyEcPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcPointVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcStats64 *pEcStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcMontEdwdsPointMultiply( + const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Prime */ +CpaStatus +cpaCyPrimeTest(const CpaInstanceHandle instanceHandle, + const CpaCyPrimeTestCbFunc pCb, + void *pCallbackTag, + const CpaCyPrimeTestOpData *pOpData, + CpaBoolean *pTestPassed) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyPrimeQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyPrimeStats64 *pPrimeStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyPrimeQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyPrimeStats *pPrimeStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* RSA */ +CpaStatus +cpaCyRsaGenKey(const CpaInstanceHandle instanceHandle, + const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, + void *pCallbackTag, + const CpaCyRsaKeyGenOpData *pKeyGenOpData, + CpaCyRsaPrivateKey *pPrivateKey, + CpaCyRsaPublicKey *pPublicKey) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaEncrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaEncryptCb, + void *pCallbackTag, + const CpaCyRsaEncryptOpData *pEncryptOpData, + CpaFlatBuffer *pOutputData) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaDecrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaDecryptCb, + void *pCallbackTag, + const CpaCyRsaDecryptOpData *pDecryptOpData, + CpaFlatBuffer *pOutputData) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyRsaStats64 *pRsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyRsaStats *pRsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Large Number */ +CpaStatus +cpaCyLnModExp(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModExpCb, + void *pCallbackTag, + const CpaCyLnModExpOpData *pLnModExpOpData, + CpaFlatBuffer *pResult) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyLnModInv(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModInvCb, + void *pCallbackTag, + const CpaCyLnModInvOpData *pLnModInvOpData, + CpaFlatBuffer *pResult) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyLnStatsQuery64(const CpaInstanceHandle instanceHandle, + CpaCyLnStats64 *pLnStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Dynamic Instance */ +CpaStatus +icp_adf_putDynInstance(icp_accel_dev_t *accel_dev, + adf_service_type_t stype, + Cpa32U instance_id) +{ + return CPA_STATUS_FAIL; +} + +CpaStatus +icp_sal_CyPollAsymRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_AsymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_AsymPerformOpNow(CpaInstanceHandle instanceHandle) +{ + return CPA_STATUS_UNSUPPORTED; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c b/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c new file mode 100644 index 00000000000..06a6d9bd768 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_buffer_desc.c Utility functions for setting buffer descriptors + * + * @ingroup LacBufferDesc + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_buffer_desc.h" +#include "lac_mem.h" +#include "cpa_cy_common.h" + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ +/* Invalid physical address value */ +#define INVALID_PHYSICAL_ADDRESS 0 + +/* Indicates what type of buffer writes need to be perfomed */ +typedef enum lac_buff_write_op_e { + WRITE_NORMAL = 0, + WRITE_AND_GET_SIZE, + WRITE_AND_ALLOW_ZERO_BUFFER, +} lac_buff_write_op_t; + +/* This function implements the buffer description writes for the traditional + * APIs */ +static CpaStatus +LacBuffDesc_CommonBufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService, + lac_buff_write_op_t operationType) +{ + Cpa32U numBuffers = 0; + icp_qat_addr_width_t bufListDescPhyAddr = 0; + icp_qat_addr_width_t bufListAlignedPhyAddr = 0; + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + + if (WRITE_AND_GET_SIZE == operationType) { + *totalDataLenInBytes = 0; + } + + numBuffers = pUserBufferList->numBuffers; + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + /* + * Get the physical address of this descriptor - need to offset by the + * alignment restrictions on the buffer descriptors + */ + bufListDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pUserBufferList->pPrivateMetaData); + + if (bufListDescPhyAddr == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + pBufferListDesc = (icp_buffer_list_desc_t *)(LAC_ARCH_UINT)( + (LAC_ARCH_UINT)pUserBufferList->pPrivateMetaData + + ((LAC_ARCH_UINT)bufListAlignedPhyAddr - + (LAC_ARCH_UINT)bufListDescPhyAddr)); + + /* Go past the Buffer List descriptor to the list of buffer descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + pBufferListDesc->numBuffers = numBuffers; + + if (WRITE_AND_GET_SIZE != operationType) { + /* Defining zero buffers is useful for example if running zero + * length + * hash */ + if (0 == numBuffers) { + /* In the case where there are zero buffers within the + * BufList + * it is required by firmware that the number is set to + * 1 + * but the phyBuffer and dataLenInBytes are set to + * NULL.*/ + pBufferListDesc->numBuffers = 1; + pCurrFlatBufDesc->dataLenInBytes = 0; + pCurrFlatBufDesc->phyBuffer = 0; + } + } + + while (0 != numBuffers) { + pCurrFlatBufDesc->dataLenInBytes = + pCurrClientFlatBuffer->dataLenInBytes; + + if (WRITE_AND_GET_SIZE == operationType) { + /* Calculate the total data length in bytes */ + *totalDataLenInBytes += + pCurrClientFlatBuffer->dataLenInBytes; + } + + /* Check if providing a physical address in the function. If not + * we + * need to convert it to a physical one */ + if (CPA_TRUE == isPhysicalAddress) { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); + } else { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pCurrClientFlatBuffer->pData)); + + if (WRITE_AND_ALLOW_ZERO_BUFFER != operationType) { + if (INVALID_PHYSICAL_ADDRESS == + pCurrFlatBufDesc->phyBuffer) { + QAT_UTILS_LOG( + "Unable to get the physical address of the client buffer.\n"); + return CPA_STATUS_FAIL; + } + } + } + + pCurrFlatBufDesc++; + pCurrClientFlatBuffer++; + + numBuffers--; + } + + *pBufListAlignedPhyAddr = bufListAlignedPhyAddr; + return CPA_STATUS_SUCCESS; +} + +/* This function implements the buffer description writes for the traditional + * APIs Zero length buffers are allowed, should be used for CHA-CHA-POLY and + * GCM aglorithms */ +CpaStatus +LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService) +{ + return LacBuffDesc_CommonBufferListDescWrite( + pUserBufferList, + pBufListAlignedPhyAddr, + isPhysicalAddress, + NULL, + pService, + WRITE_AND_ALLOW_ZERO_BUFFER); +} + +/* This function implements the buffer description writes for the traditional + * APIs */ +CpaStatus +LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService) +{ + return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, + pBufListAlignedPhyAddr, + isPhysicalAddress, + NULL, + pService, + WRITE_NORMAL); +} + +/* This function does the same processing as LacBuffDesc_BufferListDescWrite + * but calculate as well the total length in bytes of the buffer list. */ +CpaStatus +LacBuffDesc_BufferListDescWriteAndGetSize(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService) +{ + Cpa32U numBuffers = 0; + icp_qat_addr_width_t bufListDescPhyAddr = 0; + icp_qat_addr_width_t bufListAlignedPhyAddr = 0; + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + *totalDataLenInBytes = 0; + + numBuffers = pUserBufferList->numBuffers; + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + /* + * Get the physical address of this descriptor - need to offset by the + * alignment restrictions on the buffer descriptors + */ + bufListDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pUserBufferList->pPrivateMetaData); + + if (INVALID_PHYSICAL_ADDRESS == bufListDescPhyAddr) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + pBufferListDesc = (icp_buffer_list_desc_t *)(LAC_ARCH_UINT)( + (LAC_ARCH_UINT)pUserBufferList->pPrivateMetaData + + ((LAC_ARCH_UINT)bufListAlignedPhyAddr - + (LAC_ARCH_UINT)bufListDescPhyAddr)); + + /* Go past the Buffer List descriptor to the list of buffer descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + pBufferListDesc->numBuffers = numBuffers; + + while (0 != numBuffers) { + pCurrFlatBufDesc->dataLenInBytes = + pCurrClientFlatBuffer->dataLenInBytes; + + /* Calculate the total data length in bytes */ + *totalDataLenInBytes += pCurrClientFlatBuffer->dataLenInBytes; + + if (isPhysicalAddress == CPA_TRUE) { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); + } else { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pCurrClientFlatBuffer->pData)); + + if (pCurrFlatBufDesc->phyBuffer == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the client buffer.\n"); + return CPA_STATUS_FAIL; + } + } + + pCurrFlatBufDesc++; + pCurrClientFlatBuffer++; + + numBuffers--; + } + + *pBufListAlignedPhyAddr = bufListAlignedPhyAddr; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_FlatBufferVerify(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + LAC_CHECK_NULL_PARAM(pUserFlatBuffer); + LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); + + if (0 == pUserFlatBuffer->dataLenInBytes) { + QAT_UTILS_LOG("FlatBuffer empty\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Expected alignment */ + if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { + if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, + alignmentShiftExpected)) { + QAT_UTILS_LOG( + "FlatBuffer not aligned correctly - expected alignment of %u bytes.\n", + 1 << alignmentShiftExpected); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Update the total size of the packet. This function being called in a + * loop + * for an entire buffer list we need to increment the value */ + *pPktSize += pUserFlatBuffer->dataLenInBytes; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_FlatBufferVerifyNull(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + LAC_CHECK_NULL_PARAM(pUserFlatBuffer); + + if (0 != pUserFlatBuffer->dataLenInBytes) { + LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); + } + + /* Expected alignment */ + if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { + if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, + alignmentShiftExpected)) { + QAT_UTILS_LOG( + "FlatBuffer not aligned correctly - expected alignment of %u bytes.\n", + 1 << alignmentShiftExpected); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Update the total size of the packet. This function being called in a + * loop + * for an entire buffer list we need to increment the value */ + *pPktSize += pUserFlatBuffer->dataLenInBytes; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_BufferListVerify(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pUserBufferList); + LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); + LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); + + numBuffers = pUserBufferList->numBuffers; + + if (0 == pUserBufferList->numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + *pPktSize = 0; + while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { + status = LacBuffDesc_FlatBufferVerify(pCurrClientFlatBuffer, + pPktSize, + alignmentShiftExpected); + + pCurrClientFlatBuffer++; + numBuffers--; + } + return status; +} + +CpaStatus +LacBuffDesc_BufferListVerifyNull(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pUserBufferList); + LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); + LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); + + numBuffers = pUserBufferList->numBuffers; + + if (0 == pUserBufferList->numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + *pPktSize = 0; + while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { + status = + LacBuffDesc_FlatBufferVerifyNull(pCurrClientFlatBuffer, + pPktSize, + alignmentShiftExpected); + + pCurrClientFlatBuffer++; + numBuffers--; + } + return status; +} + +/** + ****************************************************************************** + * @ingroup LacBufferDesc + *****************************************************************************/ +void +LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + numBuffers = pUserBufferList->numBuffers; + + *pPktSize = 0; + while (0 != numBuffers) { + *pPktSize += pCurrClientFlatBuffer->dataLenInBytes; + pCurrClientFlatBuffer++; + numBuffers--; + } +} + +void +LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, + Cpa32U offset, + Cpa32U lenToZero) +{ + Cpa32U zeroLen = 0, sizeLeftToZero = 0; + Cpa64U currentBufferSize = 0; + CpaFlatBuffer *pBuffer = NULL; + Cpa8U *pZero = NULL; + pBuffer = pBuffList->pBuffers; + + /* Take a copy of total length to zero. */ + sizeLeftToZero = lenToZero; + + while (sizeLeftToZero > 0) { + currentBufferSize = pBuffer->dataLenInBytes; + /* check where to start zeroing */ + if (offset >= currentBufferSize) { + /* Need to get to next buffer and reduce + * offset size by data len of buffer */ + offset = offset - pBuffer->dataLenInBytes; + pBuffer++; + } else { + /* Start to Zero from this position */ + pZero = (Cpa8U *)pBuffer->pData + offset; + + /* Need to calculate the correct number of bytes to zero + * for this iteration and for this location. + */ + if (sizeLeftToZero >= pBuffer->dataLenInBytes) { + /* The size to zero is spanning buffers, zeroLen + * in + * this case is from pZero (position) to end of + * buffer. + */ + zeroLen = pBuffer->dataLenInBytes - offset; + } else { + /* zeroLen is set to sizeLeftToZero, then check + * if zeroLen and + * the offset is greater or equal to the size of + * the buffer, if + * yes, adjust the zeroLen to zero out the + * remainder of this + * buffer. + */ + zeroLen = sizeLeftToZero; + if ((zeroLen + offset) >= + pBuffer->dataLenInBytes) { + zeroLen = + pBuffer->dataLenInBytes - offset; + } + } /* end inner else */ + memset((void *)pZero, 0, zeroLen); + sizeLeftToZero = sizeLeftToZero - zeroLen; + /* offset is no longer required as any data left to zero + * is now + * at the start of the next buffer. set offset to zero + * and move on + * the buffer pointer to the next buffer. + */ + offset = 0; + pBuffer++; + + } /* end outer else */ + + } /* end while */ +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h b/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h new file mode 100644 index 00000000000..fda9b0691e0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef LAC_LOCK_FREE_STACK_H_1 +#define LAC_LOCK_FREE_STACK_H_1 +#include "lac_mem_pools.h" + +typedef union { + struct { + uint64_t ctr : 16; + uint64_t ptr : 48; + }; + uint64_t atomic; +} pointer_t; + +typedef struct { + volatile pointer_t top; +} lock_free_stack_t; + +static inline void * +PTR(const uintptr_t addr48) +{ +#ifdef __x86_64__ + const int64_t addr64 = addr48 << 16; + + /* Do arithmetic shift to restore kernel canonical address (if not NULL) + */ + return (void *)(addr64 >> 16); +#else + return (void *)(addr48); +#endif +} + +static inline lac_mem_blk_t * +pop(lock_free_stack_t *stack) +{ + pointer_t old_top; + pointer_t new_top; + lac_mem_blk_t *next; + + do { + old_top.atomic = stack->top.atomic; + next = PTR(old_top.ptr); + if (NULL == next) + return next; + + new_top.ptr = (uintptr_t)next->pNext; + new_top.ctr = old_top.ctr + 1; + } while (!__sync_bool_compare_and_swap(&stack->top.atomic, + old_top.atomic, + new_top.atomic)); + + return next; +} + +static inline void +push(lock_free_stack_t *stack, lac_mem_blk_t *val) +{ + pointer_t new_top; + pointer_t old_top; + + do { + old_top.atomic = stack->top.atomic; + val->pNext = PTR(old_top.ptr); + new_top.ptr = (uintptr_t)val; + new_top.ctr = old_top.ctr + 1; + } while (!__sync_bool_compare_and_swap(&stack->top.atomic, + old_top.atomic, + new_top.atomic)); +} + +static inline lock_free_stack_t +_init_stack(void) +{ + lock_free_stack_t stack = { { { 0 } } }; + return stack; +} + +static inline lac_mem_blk_t * +top(lock_free_stack_t *stack) +{ + pointer_t old_top = stack->top; + lac_mem_blk_t *next = PTR(old_top.ptr); + return next; +} + +#endif diff --git a/sys/dev/qat/qat_api/common/utils/lac_mem.c b/sys/dev/qat/qat_api/common/utils/lac_mem.c new file mode 100644 index 00000000000..66bd59815e6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_mem.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_mem.c Implementation of Memory Functions + * + * @ingroup LacMem + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "cpa.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" +#include "icp_sal_iommu.h" + +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_common.h" +#include "lac_list.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types.h" + +/* +******************************************************************************** +* Static Variables +******************************************************************************** +*/ + +#define MAX_BUFFER_SIZE (LAC_BITS_TO_BYTES(4096)) +/**< @ingroup LacMem + * Maximum size of the buffers used in the resize function */ + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ +/** + * @ingroup LacMem + */ +CpaStatus +icp_LacBufferRestore(Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa8U *pWorkingBuffer, + Cpa32U workingLen, + CpaBoolean copyBuf) +{ + Cpa32U padSize = 0; + + /* NULL is a valid value for working buffer as this function may be + * called to clean up in an error case where all the resize operations + * were not completed */ + if (NULL == pWorkingBuffer) { + return CPA_STATUS_SUCCESS; + } + + if (workingLen < userLen) { + QAT_UTILS_LOG("Invalid buffer sizes\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pUserBuffer != pWorkingBuffer) { + + if (CPA_TRUE == copyBuf) { + /* Copy from internal buffer to user buffer */ + padSize = workingLen - userLen; + memcpy(pUserBuffer, pWorkingBuffer + padSize, userLen); + } + + Lac_MemPoolEntryFree(pWorkingBuffer); + } + return CPA_STATUS_SUCCESS; +} + +/** + * @ingroup LacMem + */ +CpaPhysicalAddr +SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen) +{ + sal_service_t *pService = (sal_service_t *)pServiceGen; + + if (NULL != pService->virt2PhysClient) { + return pService->virt2PhysClient(pVirtAddr); + } else { + /* Use internal QAT Utils virt to phys */ + /* Ok for kernel space probably should not use for user */ + return LAC_OS_VIRT_TO_PHYS_INTERNAL(pVirtAddr); + } +} + +size_t +icp_sal_iommu_get_remap_size(size_t size) +{ + return size; +} + +CpaStatus +icp_sal_iommu_map(Cpa64U phaddr, Cpa64U iova, size_t size) +{ + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_iommu_unmap(Cpa64U iova, size_t size) +{ + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c b/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c new file mode 100644 index 00000000000..7bd584bc775 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c @@ -0,0 +1,430 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem_pools.c + * + * @ingroup LacMemPool + * + * Memory Pool creation and mgmt function implementations + * + ***************************************************************************/ + +#include "cpa.h" +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" +#include "lac_lock_free_stack.h" +#include "lac_mem_pools.h" +#include "lac_mem.h" +#include "lac_common.h" +#include "cpa_dc.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "icp_qat_fw_comp.h" +#include "icp_buffer_desc.h" +#include "lac_sym.h" + +#define LAC_MEM_POOLS_NUM_SUPPORTED 32000 +/**< @ingroup LacMemPool + * Number of mem pools supported */ + +#define LAC_MEM_POOLS_NAME_SIZE 17 +/**< @ingroup LacMemPool + * 16 bytes plus '\\0' terminator */ + +/**< @ingroup LacMemPool + * This structure is used to manage each pool created using this utility + * feature. The client will maintain a pointer (identifier) to the created + * structure per pool. + */ +typedef struct lac_mem_pool_hdr_s { + lock_free_stack_t stack; + char poolName[LAC_MEM_POOLS_NAME_SIZE]; /*16 bytes of a pool name */ + /**< up to 16 bytes of a pool name */ + unsigned int numElementsInPool; + /**< number of elements in the Pool */ + unsigned int blkSizeInBytes; + /**< Block size in bytes */ + unsigned int blkAlignmentInBytes; + /**< block alignment in bytes */ + lac_mem_blk_t **trackBlks; + /* An array of mem block pointers to track the allocated entries in pool + */ + volatile size_t availBlks; + /* Number of blocks available for allocation in this pool */ +} lac_mem_pool_hdr_t; + +static lac_mem_pool_hdr_t *lac_mem_pools[LAC_MEM_POOLS_NUM_SUPPORTED] = { + NULL +}; +/**< @ingroup LacMemPool + * Array of pointers to the mem pool header structure + */ + +LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t); +/**< @ingroup LacMemPool + * local constant for quickening computation of additional space allocated + * for holding lac_mem_blk_t container-structure + */ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function cleans up a mem pool. + ******************************************************************************/ +void Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID); + +static inline Cpa32U +Lac_MemPoolGetElementRealSize(Cpa32U blkSizeInBytes, Cpa32U blkAlignmentInBytes) +{ + Cpa32U addSize = (blkAlignmentInBytes >= sizeof(lac_mem_blk_t) ? + blkAlignmentInBytes : + 1 << (highest_bit_of_lac_mem_blk_t + 1)); + return blkSizeInBytes + addSize; +} + +CpaStatus +Lac_MemPoolCreate(lac_memory_pool_id_t *pPoolID, + char *poolName, + unsigned int numElementsInPool, /*Number of elements*/ + unsigned int blkSizeInBytes, /*Block Size in bytes*/ + unsigned int blkAlignmentInBytes, /*Block alignment (bytes)*/ + CpaBoolean trackMemory, + Cpa32U node) +{ + unsigned int poolSearch = 0; + unsigned int counter = 0; + lac_mem_blk_t *pMemBlkCurrent = NULL; + + void *pMemBlk = NULL; + + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID param\n"); + return CPA_STATUS_INVALID_PARAM; /*Error*/ + } + + /* Find First available Pool return error otherwise */ + while (lac_mem_pools[poolSearch] != NULL) { + poolSearch++; + if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { + QAT_UTILS_LOG( + "No more memory pools available for allocation.\n"); + return CPA_STATUS_FAIL; + } + } + + /* Allocate a Pool header */ + lac_mem_pools[poolSearch] = LAC_OS_MALLOC(sizeof(lac_mem_pool_hdr_t)); + if (NULL == lac_mem_pools[poolSearch]) { + QAT_UTILS_LOG( + "Unable to allocate memory for creation of the pool.\n"); + return CPA_STATUS_RESOURCE; /*Error*/ + } + memset(lac_mem_pools[poolSearch], 0, sizeof(lac_mem_pool_hdr_t)); + + /* Copy in Pool Name */ + if (poolName != NULL) { + snprintf(lac_mem_pools[poolSearch]->poolName, + LAC_MEM_POOLS_NAME_SIZE, + "%s", + poolName); + } else { + LAC_OS_FREE(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG("Invalid Pool Name pointer\n"); + return CPA_STATUS_INVALID_PARAM; /*Error*/ + } + + /* Allocate table for tracking memory blocks */ + if (CPA_TRUE == trackMemory) { + lac_mem_pools[poolSearch]->trackBlks = LAC_OS_MALLOC( + (sizeof(lac_mem_blk_t *) * numElementsInPool)); + if (NULL == lac_mem_pools[poolSearch]->trackBlks) { + LAC_OS_FREE(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG( + "Unable to allocate memory for tracking memory blocks.\n"); + return CPA_STATUS_RESOURCE; /*Error*/ + } + } else { + lac_mem_pools[poolSearch]->trackBlks = NULL; + } + + lac_mem_pools[poolSearch]->availBlks = 0; + lac_mem_pools[poolSearch]->stack = _init_stack(); + + /* Calculate alignment needed for allocation */ + for (counter = 0; counter < numElementsInPool; counter++) { + CpaPhysicalAddr physAddr = 0; + /* realSize is computed for allocation of blkSize bytes + + additional + capacity for lac_mem_blk_t structure storage due to the some + OSes + (BSD) limitations for memory alignment to be power of 2; + sizeof(lac_mem_blk_t) is being round up to the closest power + of 2 - + optimised towards the least CPU overhead but at additional + memory + cost + */ + Cpa32U realSize = + Lac_MemPoolGetElementRealSize(blkSizeInBytes, + blkAlignmentInBytes); + Cpa32U addSize = realSize - blkSizeInBytes; + + if (CPA_STATUS_SUCCESS != LAC_OS_CAMALLOC(&pMemBlk, + realSize, + blkAlignmentInBytes, + node)) { + Lac_MemPoolCleanUpInternal(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG( + "Unable to allocate contiguous chunk of memory.\n"); + return CPA_STATUS_RESOURCE; + } + + /* Calcaulate various offsets */ + physAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + (void *)((LAC_ARCH_UINT)pMemBlk + addSize)); + + /* physAddr is now already aligned to the greater power of 2: + blkAlignmentInBytes or sizeof(lac_mem_blk_t) round up + We safely put the structure right before the blkSize + real data block + */ + pMemBlkCurrent = + (lac_mem_blk_t *)(((LAC_ARCH_UINT)(pMemBlk)) + addSize - + sizeof(lac_mem_blk_t)); + + pMemBlkCurrent->physDataPtr = physAddr; + pMemBlkCurrent->pMemAllocPtr = pMemBlk; + pMemBlkCurrent->pPoolID = lac_mem_pools[poolSearch]; + pMemBlkCurrent->isInUse = CPA_FALSE; + pMemBlkCurrent->pNext = NULL; + + push(&lac_mem_pools[poolSearch]->stack, pMemBlkCurrent); + + /* Store allocated memory pointer */ + if (lac_mem_pools[poolSearch]->trackBlks != NULL) { + (lac_mem_pools[poolSearch]->trackBlks[counter]) = + (lac_mem_blk_t *)pMemBlkCurrent; + } + __sync_add_and_fetch(&lac_mem_pools[poolSearch]->availBlks, 1); + (lac_mem_pools[poolSearch])->numElementsInPool = counter + 1; + } + + /* Set Pool details in the header */ + (lac_mem_pools[poolSearch])->blkSizeInBytes = blkSizeInBytes; + (lac_mem_pools[poolSearch])->blkAlignmentInBytes = blkAlignmentInBytes; + /* Set the Pool ID output parameter */ + *pPoolID = (LAC_ARCH_UINT)(lac_mem_pools[poolSearch]); + /* Success */ + return CPA_STATUS_SUCCESS; +} + +void * +Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_mem_blk_t *pMemBlkCurrent = NULL; + + /* Explicitly removing NULL PoolID check for speed */ + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID"); + return NULL; + } + + /* Remove block from pool */ + pMemBlkCurrent = pop(&pPoolID->stack); + if (NULL == pMemBlkCurrent) { + return (void *)CPA_STATUS_RETRY; + } + __sync_sub_and_fetch(&pPoolID->availBlks, 1); + pMemBlkCurrent->isInUse = CPA_TRUE; + return (void *)((LAC_ARCH_UINT)(pMemBlkCurrent) + + sizeof(lac_mem_blk_t)); +} + +void +Lac_MemPoolEntryFree(void *pEntry) +{ + lac_mem_blk_t *pMemBlk = NULL; + + /* Explicitly NULL pointer check */ + if (pEntry == NULL) { + QAT_UTILS_LOG("Memory Handle NULL"); + return; + } + + pMemBlk = + (lac_mem_blk_t *)((LAC_ARCH_UINT)pEntry - sizeof(lac_mem_blk_t)); + pMemBlk->isInUse = CPA_FALSE; + + push(&pMemBlk->pPoolID->stack, pMemBlk); + __sync_add_and_fetch(&pMemBlk->pPoolID->availBlks, 1); +} + +void +Lac_MemPoolDestroy(lac_memory_pool_id_t poolID) +{ + unsigned int poolSearch = 0; + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + + if (pPoolID != NULL) { + /*Remove entry from table*/ + while (lac_mem_pools[poolSearch] != pPoolID) { + poolSearch++; + + if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { + QAT_UTILS_LOG("Invalid Pool ID submitted.\n"); + return; + } + } + + lac_mem_pools[poolSearch] = NULL; /*Remove handle from pool*/ + + Lac_MemPoolCleanUpInternal(pPoolID); + } +} + +void +Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID) +{ + lac_mem_blk_t *pCurrentBlk = NULL; + void *pFreePtr = NULL; + Cpa32U count = 0; + + if (pPoolID->trackBlks == NULL) { + pCurrentBlk = pop(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + /* Free Data Blocks */ + pFreePtr = pCurrentBlk->pMemAllocPtr; + pCurrentBlk = pop(&pPoolID->stack); + LAC_OS_CAFREE(pFreePtr); + } + } else { + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pFreePtr = (pPoolID->trackBlks[count])->pMemAllocPtr; + LAC_OS_CAFREE(pFreePtr); + } + LAC_OS_FREE(pPoolID->trackBlks); + } + LAC_OS_FREE(pPoolID); +} + +unsigned int +Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return 0; + } + return pPoolID->availBlks; +} + +void +Lac_MemPoolStatsShow(void) +{ + unsigned int index = 0; + QAT_UTILS_LOG(SEPARATOR BORDER + " Memory Pools Stats\n" SEPARATOR); + + while (index < LAC_MEM_POOLS_NUM_SUPPORTED) { + if (lac_mem_pools[index] != NULL) { + QAT_UTILS_LOG( + BORDER " Pool Name: %s \n" BORDER + " No. Elements in Pool: %10u \n" BORDER + " Element Size in Bytes: %10u \n" BORDER + " Alignment in Bytes: %10u \n" BORDER + " No. Available Blocks: %10zu \n" SEPARATOR, + lac_mem_pools[index]->poolName, + lac_mem_pools[index]->numElementsInPool, + lac_mem_pools[index]->blkSizeInBytes, + lac_mem_pools[index]->blkAlignmentInBytes, + lac_mem_pools[index]->availBlks); + } + index++; + } +} + +static void +Lac_MemPoolInitSymCookies(lac_sym_cookie_t *pSymCookie) +{ + pSymCookie->keyContentDescPhyAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pSymCookie->u.keyCookie.contentDesc); + pSymCookie->keyHashStateBufferPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + pSymCookie->u.keyCookie.hashStateBuffer); + pSymCookie->keySslKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + &(pSymCookie->u.keyCookie.u.sslKeyInput)); + pSymCookie->keyTlsKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + &(pSymCookie->u.keyCookie.u.tlsKeyInput)); +} + +CpaStatus +Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_sym_cookie_t *pSymCookie = NULL; + lac_mem_blk_t *pCurrentBlk = NULL; + + if (NULL == pPoolID) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return CPA_STATUS_FAIL; + } + + if (pPoolID->trackBlks == NULL) { + pCurrentBlk = top(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + pSymCookie = + (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + + sizeof(lac_mem_blk_t)); + pCurrentBlk = pCurrentBlk->pNext; + Lac_MemPoolInitSymCookies(pSymCookie); + } + } else { + Cpa32U count = 0; + + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pCurrentBlk = pPoolID->trackBlks[count]; + pSymCookie = + (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + + sizeof(lac_mem_blk_t)); + Lac_MemPoolInitSymCookies(pSymCookie); + } + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +Lac_MemPoolInitDcCookiePhyAddr(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_mem_blk_t *pCurrentBlk = NULL; + + if (NULL == pPoolID) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return CPA_STATUS_FAIL; + } + + if (NULL == pPoolID->trackBlks) { + pCurrentBlk = top(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + pCurrentBlk = pCurrentBlk->pNext; + } + } else { + Cpa32U count = 0; + + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pCurrentBlk = pPoolID->trackBlks[count]; + } + } + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_sync.c b/sys/dev/qat/qat_api/common/utils/lac_sync.c new file mode 100644 index 00000000000..25a2f9764be --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_sync.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_sync.c Utility functions containing synchronous callback support + * functions + * + * @ingroup LacSync + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "lac_sync.h" +#include "lac_common.h" + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenWakeupSyncCaller(void *pCallbackTag, CpaStatus status) +{ + lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; + if (pSc != NULL) { + if (pSc->canceled) { + QAT_UTILS_LOG("Synchronous operation cancelled.\n"); + return; + } + pSc->status = status; + if (CPA_STATUS_SUCCESS != LAC_POST_SEMAPHORE(pSc->sid)) { + QAT_UTILS_LOG("Failed to post semaphore.\n"); + } + } +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenVerifyWakeupSyncCaller(void *pCallbackTag, + CpaStatus status, + CpaBoolean opResult) +{ + lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; + if (pSc != NULL) { + if (pSc->canceled) { + QAT_UTILS_LOG("Synchronous operation cancelled.\n"); + return; + } + pSc->status = status; + pSc->opResult = opResult; + if (CPA_STATUS_SUCCESS != LAC_POST_SEMAPHORE(pSc->sid)) { + QAT_UTILS_LOG("Failed to post semaphore.\n"); + } + } +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean opResult) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenFlatBufCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaFlatBuffer *pOut) +{ + LacSync_GenWakeupSyncCaller(pCallbackTag, status); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenFlatBufVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean opResult, + CpaFlatBuffer *pOut) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenDualFlatBufVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut0, + CpaFlatBuffer *pOut1) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_service_state.c b/sys/dev/qat/qat_api/common/utils/sal_service_state.c new file mode 100644 index 00000000000..c2fa491e7b7 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_service_state.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_service_state.c Service state checks + * + * @ingroup SalServiceState + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "qat_utils.h" +#include "lac_list.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "sal_service_state.h" + +CpaBoolean +Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle) +{ + sal_service_t *pService = (sal_service_t *)instanceHandle; + + if (SAL_SERVICE_STATE_RUNNING == pService->state) { + return CPA_TRUE; + } + return CPA_FALSE; +} + +CpaBoolean +Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle) +{ + sal_service_t *pService = (sal_service_t *)instanceHandle; + + if (SAL_SERVICE_STATE_RESTARTING == pService->state) { + return CPA_TRUE; + } + return CPA_FALSE; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_statistics.c b/sys/dev/qat/qat_api/common/utils/sal_statistics.c new file mode 100644 index 00000000000..e311f22283b --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_statistics.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_statistics.c + * + * @defgroup SalStats Sal Statistics + * + * @ingroup SalStats + * + * @description + * This file contains implementation of statistic related functions + * + *****************************************************************************/ + +#include "cpa.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "icp_adf_cfg.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" + +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "lac_sal.h" + +/** + ****************************************************************************** + * @ingroup SalStats + * Reads from the config file if the given statistic is enabled + * + * @description + * Reads from the config file if the given statistic is enabled + * + * @param[in] device Pointer to an acceleration device structure + * @param[in] statsName Name of the config value to read the value from + * @param[out] pIsEnabled Pointer to a variable where information if the + * given stat is enabled or disabled will be stored + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +static CpaStatus +SalStatistics_GetStatEnabled(icp_accel_dev_t *device, + const char *statsName, + CpaBoolean *pIsEnabled) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + + LAC_CHECK_NULL_PARAM(pIsEnabled); + LAC_CHECK_NULL_PARAM(statsName); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + statsName, + param_value); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + statsName); + return status; + } + + if (0 == strncmp(param_value, + SAL_STATISTICS_STRING_OFF, + strlen(SAL_STATISTICS_STRING_OFF))) { + *pIsEnabled = CPA_FALSE; + } else { + *pIsEnabled = CPA_TRUE; + } + + return status; +} + +/* @ingroup SalStats */ +CpaStatus +SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_statistics_collection_t *pStatsCollection = NULL; + Cpa32U enabled_services = 0; + + LAC_CHECK_NULL_PARAM(device); + + pStatsCollection = LAC_OS_MALLOC(sizeof(sal_statistics_collection_t)); + if (NULL == pStatsCollection) { + QAT_UTILS_LOG("Failed to allocate memory for statistic.\n"); + return CPA_STATUS_RESOURCE; + } + device->pQatStats = pStatsCollection; + + status = SalStatistics_GetStatEnabled(device, + SAL_STATS_CFG_ENABLED, + &pStatsCollection->bStatsEnabled); + LAC_CHECK_STATUS(status); + + if (CPA_FALSE == pStatsCollection->bStatsEnabled) { + pStatsCollection->bDcStatsEnabled = CPA_FALSE; + pStatsCollection->bDhStatsEnabled = CPA_FALSE; + pStatsCollection->bDsaStatsEnabled = CPA_FALSE; + pStatsCollection->bEccStatsEnabled = CPA_FALSE; + pStatsCollection->bKeyGenStatsEnabled = CPA_FALSE; + pStatsCollection->bLnStatsEnabled = CPA_FALSE; + pStatsCollection->bPrimeStatsEnabled = CPA_FALSE; + pStatsCollection->bRsaStatsEnabled = CPA_FALSE; + pStatsCollection->bSymStatsEnabled = CPA_FALSE; + + return status; + } + + /* What services are enabled */ + status = SalCtrl_GetEnabledServices(device, &enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get enabled services.\n"); + return CPA_STATUS_FAIL; + } + + /* Check if the compression service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DC, + &pStatsCollection->bDcStatsEnabled); + LAC_CHECK_STATUS(status); + } + /* Check if the asym service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM) || + SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DH, + &pStatsCollection->bDhStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DSA, + &pStatsCollection->bDsaStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_ECC, + &pStatsCollection->bEccStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_KEYGEN, + &pStatsCollection->bKeyGenStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_LN, + &pStatsCollection->bLnStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_PRIME, + &pStatsCollection->bPrimeStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_RSA, + &pStatsCollection->bRsaStatsEnabled); + LAC_CHECK_STATUS(status); + } + + /* Check if the sym service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM) || + SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_SYM, + &pStatsCollection->bSymStatsEnabled); + LAC_CHECK_STATUS(status); + } + return status; +}; + +/* @ingroup SalStats */ +CpaStatus +SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device) +{ + sal_statistics_collection_t *pStatsCollection = NULL; + LAC_CHECK_NULL_PARAM(device); + pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; + LAC_OS_FREE(pStatsCollection); + device->pQatStats = NULL; + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_string_parse.c b/sys/dev/qat/qat_api/common/utils/sal_string_parse.c new file mode 100644 index 00000000000..b6161aa8d88 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_string_parse.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_string_parse.c + * + * @ingroup SalStringParse + * + * @description + * This file contains string parsing functions for both user space and kernel + * space + * + *****************************************************************************/ +#include "cpa.h" +#include "lac_mem.h" +#include "sal_string_parse.h" + +CpaStatus +Sal_StringParsing(char *string1, + Cpa32U instanceNumber, + char *string2, + char *result) +{ + char instNumString[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + Cpa32U instNumStringLen = 0; + + snprintf(instNumString, + SAL_CFG_MAX_VAL_LEN_IN_BYTES, + "%d", + instanceNumber); + instNumStringLen = strnlen(instNumString, SAL_CFG_MAX_VAL_LEN_IN_BYTES); + if ((strnlen(string1, SAL_CFG_MAX_VAL_LEN_IN_BYTES) + instNumStringLen + + strnlen(string2, SAL_CFG_MAX_VAL_LEN_IN_BYTES)) > + SAL_CFG_MAX_VAL_LEN_IN_BYTES) { + QAT_UTILS_LOG("Size of result too small.\n"); + return CPA_STATUS_FAIL; + } + + LAC_OS_BZERO(result, SAL_CFG_MAX_VAL_LEN_IN_BYTES); + snprintf(result, + SAL_CFG_MAX_VAL_LEN_IN_BYTES, + "%s%d%s", + string1, + instanceNumber, + string2); + + return CPA_STATUS_SUCCESS; +} + +Cpa64U +Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase) +{ + Cpa64U ulResult = 0; + + ulResult = (Cpa64U)simple_strtoull(cp, endp, cfgBase); + + return ulResult; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_user_process.c b/sys/dev/qat/qat_api/common/utils/sal_user_process.c new file mode 100644 index 00000000000..09728f346c1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_user_process.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_user_process.c + * + * @ingroup SalUserProcess + * + * @description + * This file contains implementation of functions to set/get user process + * name + * + *****************************************************************************/ + +#include "qat_utils.h" +#include "lac_common.h" +static char lacProcessName[LAC_USER_PROCESS_NAME_MAX_LEN + 1] = + LAC_KERNEL_PROCESS_NAME; + +/**< Process name used to obtain values from correct section of config file. */ + +/* + * @ingroup LacCommon + * @description + * This function sets the process name + * + * @context + * This functions is called from module_init or from user space process + * initialisation function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] processName Process name to be set +*/ +CpaStatus +icpSetProcessName(const char *processName) +{ + LAC_CHECK_NULL_PARAM(processName); + + if (strnlen(processName, LAC_USER_PROCESS_NAME_MAX_LEN) == + LAC_USER_PROCESS_NAME_MAX_LEN) { + QAT_UTILS_LOG( + "Process name too long, maximum process name is %d>\n", + LAC_USER_PROCESS_NAME_MAX_LEN); + return CPA_STATUS_FAIL; + } + + strncpy(lacProcessName, processName, LAC_USER_PROCESS_NAME_MAX_LEN); + lacProcessName[LAC_USER_PROCESS_NAME_MAX_LEN] = '\0'; + + return CPA_STATUS_SUCCESS; +} + +/* + * @ingroup LacCommon + * @description + * This function gets the process name + * + * @context + * This functions is called from LAC context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * +*/ +char * +icpGetProcessName(void) +{ + return lacProcessName; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_versions.c b/sys/dev/qat/qat_api/common/utils/sal_versions.c new file mode 100644 index 00000000000..8e274eb8705 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_versions.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_versions.c + * + * @ingroup SalVersions + * + * @description + * This file contains implementation of functions used to obtain version + * information + * + *****************************************************************************/ + +#include "cpa.h" +#include "qat_utils.h" + +#include "icp_accel_devices.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_cfg.h" + +#include "lac_common.h" + +#include "icp_sal_versions.h" + +#define ICP_SAL_VERSIONS_ALL_CAP_MASK 0xFFFFFFFF +/**< Mask used to get all devices from ADF */ + +/** +******************************************************************************* + * @ingroup SalVersions + * Fills in the version info structure + * @description + * This function obtains hardware and software information associated with + * a given device and fills in the version info structure + * + * @param[in] device Pointer to the device for which version information + * is to be obtained. + * @param[out] pVerInfo Pointer to a structure that will hold version + * information + * + * @context + * This function might sleep. It cannot be executed in a context that + * does not permit sleeping. + * @assumptions + * The system has been started + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @return CPA_STATUS_SUCCESS Operation finished successfully + * @return CPA_STATUS_FAIL Operation failed + * + *****************************************************************************/ +static CpaStatus +SalVersions_FillVersionInfo(icp_accel_dev_t *device, + icp_sal_dev_version_info_t *pVerInfo) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + Cpa32S strSize = 0; + + memset(pVerInfo, 0, sizeof(icp_sal_dev_version_info_t)); + pVerInfo->devId = device->accelId; + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_HW_REV_ID_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->hardwareVersion, + ICP_SAL_VERSIONS_HW_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_HW_VERSION_SIZE); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_UOF_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->firmwareVersion, + ICP_SAL_VERSIONS_FW_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_FW_VERSION_SIZE); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_MMP_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->mmpVersion, + ICP_SAL_VERSIONS_MMP_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_MMP_VERSION_SIZE); + + snprintf((char *)pVerInfo->softwareVersion, + ICP_SAL_VERSIONS_SW_VERSION_SIZE, + "%d.%d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); + + return status; +} + +CpaStatus +icp_sal_getDevVersionInfo(Cpa32U devId, icp_sal_dev_version_info_t *pVerInfo) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa16U numInstances = 0; + icp_accel_dev_t **pAccel_dev = NULL; + Cpa16U num_accel_dev = 0, index = 0; + icp_accel_dev_t *pDevice = NULL; + + LAC_CHECK_NULL_PARAM(pVerInfo); + + status = icp_amgr_getNumInstances(&numInstances); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Error while getting number of devices.\n"); + return CPA_STATUS_FAIL; + } + + if (devId >= ADF_MAX_DEVICES) { + QAT_UTILS_LOG("Invalid devId\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pAccel_dev = + malloc(numInstances * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + /* Get ADF to return all accel_devs */ + status = + icp_amgr_getAllAccelDevByCapabilities(ICP_SAL_VERSIONS_ALL_CAP_MASK, + pAccel_dev, + &num_accel_dev); + + if (CPA_STATUS_SUCCESS == status) { + for (index = 0; index < num_accel_dev; index++) { + pDevice = (icp_accel_dev_t *)pAccel_dev[index]; + + if (pDevice->accelId == devId) { + status = SalVersions_FillVersionInfo(pDevice, + pVerInfo); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Error while filling in version info.\n"); + } + break; + } + } + + if (index == num_accel_dev) { + QAT_UTILS_LOG("Device %d not found or not started.\n", + devId); + status = CPA_STATUS_FAIL; + } + } else { + QAT_UTILS_LOG("Error while getting devices.\n"); + } + + free(pAccel_dev, M_QAT); + return status; +} diff --git a/sys/dev/qat/qat_api/device/dev_info.c b/sys/dev/qat/qat_api/device/dev_info.c new file mode 100644 index 00000000000..f8716b751a6 --- /dev/null +++ b/sys/dev/qat/qat_api/device/dev_info.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dev_info.c + * + * @defgroup Device + * + * @description + * This file contains implementation of functions for device level APIs + * + *****************************************************************************/ + +/* QAT-API includes */ +#include "cpa_dev.h" +#include "icp_accel_devices.h" +#include "lac_common.h" +#include "icp_adf_cfg.h" +#include "lac_sal_types.h" +#include "icp_adf_accel_mgr.h" +#include "sal_string_parse.h" +#include "lac_sal.h" + +CpaStatus +cpaGetNumDevices(Cpa16U *numDevices) +{ + LAC_CHECK_NULL_PARAM(numDevices); + + return icp_amgr_getNumInstances(numDevices); +} + +CpaStatus +cpaGetDeviceInfo(Cpa16U device, CpaDeviceInfo *deviceInfo) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t *pDevice = NULL; + Cpa16U numDevicesAvail = 0; + Cpa32U capabilitiesMask = 0; + Cpa32U enabledServices = 0; + + LAC_CHECK_NULL_PARAM(deviceInfo); + status = icp_amgr_getNumInstances(&numDevicesAvail); + /* Check if the application is not attempting to access a + * device that does not exist. + */ + if (0 == numDevicesAvail) { + QAT_UTILS_LOG("Failed to retrieve number of devices!\n"); + return CPA_STATUS_FAIL; + } + if (device >= numDevicesAvail) { + QAT_UTILS_LOG( + "Invalid device access! Number of devices available: %d.\n", + numDevicesAvail); + return CPA_STATUS_FAIL; + } + + /* Clear the entire capability structure before initialising it */ + memset(deviceInfo, 0x00, sizeof(CpaDeviceInfo)); + /* Bus/Device/Function should be 0xFF until initialised */ + deviceInfo->bdf = 0xffff; + + pDevice = icp_adf_getAccelDevByAccelId(device); + if (NULL == pDevice) { + QAT_UTILS_LOG("Failed to retrieve device.\n"); + return status; + } + + /* Device of interest is found, retrieve the information for it */ + deviceInfo->sku = pDevice->sku; + deviceInfo->deviceId = pDevice->pciDevId; + deviceInfo->bdf = icp_adf_get_busAddress(pDevice->accelId); + deviceInfo->numaNode = pDevice->pkg_id; + + if (DEVICE_DH895XCCVF == pDevice->deviceType || + DEVICE_C62XVF == pDevice->deviceType || + DEVICE_C3XXXVF == pDevice->deviceType || + DEVICE_C4XXXVF == pDevice->deviceType) { + deviceInfo->isVf = CPA_TRUE; + } + + status = SalCtrl_GetEnabledServices(pDevice, &enabledServices); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to retrieve enabled services!\n"); + return status; + } + + status = icp_amgr_getAccelDevCapabilities(pDevice, &capabilitiesMask); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to retrieve accel capabilities mask!\n"); + return status; + } + + /* Determine if Compression service is enabled */ + if (enabledServices & SAL_SERVICE_TYPE_COMPRESSION) { + deviceInfo->dcEnabled = + (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION) != + 0) ? + CPA_TRUE : + CPA_FALSE); + } + + /* Determine if Crypto service is enabled */ + if (enabledServices & SAL_SERVICE_TYPE_CRYPTO) { + deviceInfo->cySymEnabled = + (((capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) ? + CPA_TRUE : + CPA_FALSE); + deviceInfo->cyAsymEnabled = + (((capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) != 0) ? + CPA_TRUE : + CPA_FALSE); + } + /* Determine if Crypto Sym service is enabled */ + if (enabledServices & SAL_SERVICE_TYPE_CRYPTO_SYM) { + deviceInfo->cySymEnabled = + (((capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) ? + CPA_TRUE : + CPA_FALSE); + } + /* Determine if Crypto Asym service is enabled */ + if (enabledServices & SAL_SERVICE_TYPE_CRYPTO_ASYM) { + deviceInfo->cyAsymEnabled = + (((capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) != 0) ? + CPA_TRUE : + CPA_FALSE); + } + deviceInfo->deviceMemorySizeAvailable = pDevice->deviceMemAvail; + + return status; +} diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_fw.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw.h new file mode 100644 index 00000000000..7fe1bc3d105 --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw.h @@ -0,0 +1,1333 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_qat_fw.h + * @defgroup icp_qat_fw_comn ICP QAT FW Common Processing Definitions + * @ingroup icp_qat_fw + * + * @description + * This file documents the common interfaces that the QAT FW running on + * the QAT AE exports. This common layer is used by a number of services + * to export content processing services. + * + *****************************************************************************/ + +#ifndef _ICP_QAT_FW_H_ +#define _ICP_QAT_FW_H_ + +/* +* ============================== +* General Notes on the Interface +*/ + +/* +* +* ============================== +* +* Introduction +* +* Data movement and slice chaining +* +* Endianness +* - Unless otherwise stated, all structures are defined in LITTLE ENDIAN +* MODE +* +* Alignment +* - In general all data structures provided to a request should be aligned +* on the 64 byte boundary so as to allow optimal memory transfers. At the +* minimum they must be aligned to the 8 byte boundary +* +* Sizes +* Quad words = 8 bytes +* +* Terminology +* +* ============================== +*/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "icp_qat_hw.h" + +/* Big assumptions that both bitpos and mask are constants */ +#define QAT_FIELD_SET(flags, val, bitpos, mask) \ + (flags) = (((flags) & (~((mask) << (bitpos)))) | \ + (((val) & (mask)) << (bitpos))) + +#define QAT_FIELD_GET(flags, bitpos, mask) (((flags) >> (bitpos)) & (mask)) +#define QAT_FLAG_SET(flags, val, bitpos) \ + ((flags) = (((flags) & (~(1 << (bitpos)))) | (((val)&1) << (bitpos)))) + +#define QAT_FLAG_CLEAR(flags, bitpos) (flags) = ((flags) & (~(1 << (bitpos)))) + +#define QAT_FLAG_GET(flags, bitpos) (((flags) >> (bitpos)) & 1) + +/**< @ingroup icp_qat_fw_comn + * Default request and response ring size in bytes */ +#define ICP_QAT_FW_REQ_DEFAULT_SZ 128 +#define ICP_QAT_FW_RESP_DEFAULT_SZ 32 + +#define ICP_QAT_FW_COMN_ONE_BYTE_SHIFT 8 +#define ICP_QAT_FW_COMN_SINGLE_BYTE_MASK 0xFF + +/**< @ingroup icp_qat_fw_comn + * Common Request - Block sizes definitions in multiples of individual long + * words */ +#define ICP_QAT_FW_NUM_LONGWORDS_1 1 +#define ICP_QAT_FW_NUM_LONGWORDS_2 2 +#define ICP_QAT_FW_NUM_LONGWORDS_3 3 +#define ICP_QAT_FW_NUM_LONGWORDS_4 4 +#define ICP_QAT_FW_NUM_LONGWORDS_5 5 +#define ICP_QAT_FW_NUM_LONGWORDS_6 6 +#define ICP_QAT_FW_NUM_LONGWORDS_7 7 +#define ICP_QAT_FW_NUM_LONGWORDS_10 10 +#define ICP_QAT_FW_NUM_LONGWORDS_13 13 + +/**< @ingroup icp_qat_fw_comn + * Definition of the associated service Id for NULL service type. + * Note: the response is expected to use ICP_QAT_FW_COMN_RESP_SERV_CPM_FW */ +#define ICP_QAT_FW_NULL_REQ_SERV_ID 1 + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the firmware interface service users, for + * responses. + * @description + * Enumeration which is used to indicate the ids of the services + * for responses using the external firmware interfaces. + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_FW_COMN_RESP_SERV_NULL, /**< NULL service id type */ + ICP_QAT_FW_COMN_RESP_SERV_CPM_FW, /**< CPM FW Service ID */ + ICP_QAT_FW_COMN_RESP_SERV_DELIMITER /**< Delimiter service id type */ +} icp_qat_fw_comn_resp_serv_id_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the request types + * @description + * Enumeration which is used to indicate the ids of the request + * types used in each of the external firmware interfaces + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_FW_COMN_REQ_NULL = 0, /**< NULL request type */ + ICP_QAT_FW_COMN_REQ_CPM_FW_PKE = 3, /**< CPM FW PKE Request */ + ICP_QAT_FW_COMN_REQ_CPM_FW_LA = 4, /**< CPM FW Lookaside Request */ + ICP_QAT_FW_COMN_REQ_CPM_FW_DMA = 7, /**< CPM FW DMA Request */ + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP = 9, /**< CPM FW Compression Request */ + ICP_QAT_FW_COMN_REQ_DELIMITER /**< End delimiter */ + +} icp_qat_fw_comn_request_id_t; + +/* ========================================================================= */ +/* QAT FW REQUEST STRUCTURES */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Common request flags type + * + * @description + * Definition of the common request flags. + * + *****************************************************************************/ +typedef uint8_t icp_qat_fw_comn_flags; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Common request - Service specific flags type + * + * @description + * Definition of the common request service specific flags. + * + *****************************************************************************/ +typedef uint16_t icp_qat_fw_serv_specif_flags; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Common request - Extended service specific flags type + * + * @description + * Definition of the common request extended service specific flags. + * + *****************************************************************************/ +typedef uint8_t icp_qat_fw_ext_serv_specif_flags; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW request content descriptor field - + * points to the content descriptor parameters or itself contains service- + * specific data. Also specifies content descriptor parameter size. + * Contains reserved fields. + * @description + * Common section of the request used across all of the services exposed + * by the QAT FW. Each of the services inherit these common fields + * + *****************************************************************************/ +typedef union icp_qat_fw_comn_req_hdr_cd_pars_s { + /**< LWs 2-5 */ + struct { + uint64_t content_desc_addr; + /**< Address of the content descriptor */ + + uint16_t content_desc_resrvd1; + /**< Content descriptor reserved field */ + + uint8_t content_desc_params_sz; + /**< Size of the content descriptor parameters in quad words. + * These + * parameters describe the session setup configuration info for + * the + * slices that this request relies upon i.e. the configuration + * word and + * cipher key needed by the cipher slice if there is a request + * for + * cipher processing. */ + + uint8_t content_desc_hdr_resrvd2; + /**< Content descriptor reserved field */ + + uint32_t content_desc_resrvd3; + /**< Content descriptor reserved field */ + } s; + + struct { + uint32_t serv_specif_fields[ICP_QAT_FW_NUM_LONGWORDS_4]; + + } s1; + +} icp_qat_fw_comn_req_hdr_cd_pars_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW request middle block. + * @description + * Common section of the request used across all of the services exposed + * by the QAT FW. Each of the services inherit these common fields + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_req_mid_s { + /**< LWs 6-13 */ + uint64_t opaque_data; + /**< Opaque data passed unmodified from the request to response messages + * by + * firmware (fw) */ + + uint64_t src_data_addr; + /**< Generic definition of the source data supplied to the QAT AE. The + * common flags are used to further describe the attributes of this + * field */ + + uint64_t dest_data_addr; + /**< Generic definition of the destination data supplied to the QAT AE. + * The + * common flags are used to further describe the attributes of this + * field */ + + uint32_t src_length; + /** < Length of source flat buffer incase src buffer + * type is flat */ + + uint32_t dst_length; + /** < Length of source flat buffer incase dst buffer + * type is flat */ + +} icp_qat_fw_comn_req_mid_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW request content descriptor control + * block. + * + * @description + * Service specific section of the request used across all of the services + * exposed by the QAT FW. Each of the services populates this block + * uniquely. Refer to the service-specific header structures e.g. + * 'icp_qat_fw_cipher_hdr_s' (for Cipher) etc. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_req_cd_ctrl_s { + /**< LWs 27-31 */ + uint32_t content_desc_ctrl_lw[ICP_QAT_FW_NUM_LONGWORDS_5]; + +} icp_qat_fw_comn_req_cd_ctrl_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW request header. + * @description + * Common section of the request used across all of the services exposed + * by the QAT FW. Each of the services inherit these common fields. The + * reserved field of 7 bits and the service command Id field are all + * service-specific fields, along with the service specific flags. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_req_hdr_s { + /**< LW0 */ + uint8_t resrvd1; + /**< reserved field */ + + uint8_t service_cmd_id; + /**< Service Command Id - this field is service-specific + * Please use service-specific command Id here e.g.Crypto Command Id + * or Compression Command Id etc. */ + + uint8_t service_type; + /**< Service type */ + + uint8_t hdr_flags; + /**< This represents a flags field for the Service Request. + * The most significant bit is the 'valid' flag and the only + * one used. All remaining bit positions are unused and + * are therefore reserved and need to be set to 0. */ + + /**< LW1 */ + icp_qat_fw_serv_specif_flags serv_specif_flags; + /**< Common Request service-specific flags + * e.g. Symmetric Crypto Command Flags */ + + icp_qat_fw_comn_flags comn_req_flags; + /**< Common Request Flags consisting of + * - 6 reserved bits, + * - 1 Content Descriptor field type bit and + * - 1 Source/destination pointer type bit */ + + icp_qat_fw_ext_serv_specif_flags extended_serv_specif_flags; + /**< An extension of serv_specif_flags + */ +} icp_qat_fw_comn_req_hdr_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW request parameter field. + * + * @description + * Service specific section of the request used across all of the services + * exposed by the QAT FW. Each of the services populates this block + * uniquely. Refer to service-specific header structures e.g. + * 'icp_qat_fw_comn_req_cipher_rqpars_s' (for Cipher) etc. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_req_rqpars_s { + /**< LWs 14-26 */ + uint32_t serv_specif_rqpars_lw[ICP_QAT_FW_NUM_LONGWORDS_13]; + +} icp_qat_fw_comn_req_rqpars_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common request structure with service specific + * fields + * @description + * This is a definition of the full qat request structure used by all + * services. Each service is free to use the service fields in its own + * way. This struct is useful as a message passing argument before the + * service contained within the request is determined. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_req_s { + /**< LWs 0-1 */ + icp_qat_fw_comn_req_hdr_t comn_hdr; + /**< Common request header */ + + /**< LWs 2-5 */ + icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; + /**< Common Request content descriptor field which points either to a + * content descriptor + * parameter block or contains the service-specific data itself. */ + + /**< LWs 6-13 */ + icp_qat_fw_comn_req_mid_t comn_mid; + /**< Common request middle section */ + + /**< LWs 14-26 */ + icp_qat_fw_comn_req_rqpars_t serv_specif_rqpars; + /**< Common request service-specific parameter field */ + + /**< LWs 27-31 */ + icp_qat_fw_comn_req_cd_ctrl_t cd_ctrl; + /**< Common request content descriptor control block - + * this field is service-specific */ + +} icp_qat_fw_comn_req_t; + +/* ========================================================================= */ +/* QAT FW RESPONSE STRUCTURES */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Error code field + * + * @description + * Overloaded field with 8 bit common error field or two + * 8 bit compression error fields for compression and translator slices + * + *****************************************************************************/ +typedef union icp_qat_fw_comn_error_s { + struct { + uint8_t resrvd; + /**< 8 bit reserved field */ + + uint8_t comn_err_code; + /**< 8 bit common error code */ + + } s; + /**< Structure which is used for non-compression responses */ + + struct { + uint8_t xlat_err_code; + /**< 8 bit translator error field */ + + uint8_t cmp_err_code; + /**< 8 bit compression error field */ + + } s1; + /** Structure which is used for compression responses */ + +} icp_qat_fw_comn_error_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common QAT FW response header. + * @description + * This section of the response is common across all of the services + * that generate a firmware interface response + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_resp_hdr_s { + /**< LW0 */ + uint8_t resrvd1; + /**< Reserved field - this field is service-specific - + * Note: The Response Destination Id has been removed + * from first QWord */ + + uint8_t service_id; + /**< Service Id returned by service block */ + + uint8_t response_type; + /**< Response type - copied from the request to + * the response message */ + + uint8_t hdr_flags; + /**< This represents a flags field for the Response. + * Bit<7> = 'valid' flag + * Bit<6> = 'CNV' flag indicating that CNV was executed + * on the current request + * Bit<5> = 'CNVNR' flag indicating that a recovery happened + * on the current request following a CNV error + * All remaining bits are unused and are therefore reserved. + * They must to be set to 0. + */ + + /**< LW 1 */ + icp_qat_fw_comn_error_t comn_error; + /**< This field is overloaded to allow for one 8 bit common error field + * or two 8 bit error fields from compression and translator */ + + uint8_t comn_status; + /**< Status field which specifies which slice(s) report an error */ + + uint8_t cmd_id; + /**< Command Id - passed from the request to the response message */ + +} icp_qat_fw_comn_resp_hdr_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Definition of the common response structure with service specific + * fields + * @description + * This is a definition of the full qat response structure used by all + * services. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comn_resp_s { + /**< LWs 0-1 */ + icp_qat_fw_comn_resp_hdr_t comn_hdr; + /**< Common header fields */ + + /**< LWs 2-3 */ + uint64_t opaque_data; + /**< Opaque data passed from the request to the response message */ + + /**< LWs 4-7 */ + uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4]; + /**< Reserved */ + +} icp_qat_fw_comn_resp_t; + +/* ========================================================================= */ +/* MACRO DEFINITIONS */ +/* ========================================================================= */ + +/* Common QAT FW request header - structure of LW0 + * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + + * | Bit | 31 | 30 - 24 | 21 - 16 | 15 - 8 | 7 - 0 | + * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + + * | Flags | V | Reserved | Serv Type | Serv Cmd Id | Reserved | + * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + +*/ + +/**< @ingroup icp_qat_fw_comn + * Definition of the setting of the header's valid flag */ +#define ICP_QAT_FW_COMN_REQ_FLAG_SET 1 +/**< @ingroup icp_qat_fw_comn + * Definition of the setting of the header's valid flag */ +#define ICP_QAT_FW_COMN_REQ_FLAG_CLR 0 + +/**< @ingroup icp_qat_fw_comn + * Macros defining the bit position and mask of the 'valid' flag, within the + * hdr_flags field of LW0 (service request and response) */ +#define ICP_QAT_FW_COMN_VALID_FLAG_BITPOS 7 +#define ICP_QAT_FW_COMN_VALID_FLAG_MASK 0x1 +#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK 0x7F + +/* Common QAT FW response header - structure of LW0 + * + ===== + --- + --- + ----- + ----- + --------- + ----------- + ----- + + * | Bit | 31 | 30 | 29 | 28-24 | 21 - 16 | 15 - 8 | 7-0 | + * + ===== + --- + ----+ ----- + ----- + --------- + ----------- + ----- + + * | Flags | V | CNV | CNVNR | Rsvd | Serv Type | Serv Cmd Id | Rsvd | + * + ===== + --- + --- + ----- + ----- + --------- + ----------- + ----- + */ +/**< @ingroup icp_qat_fw_comn + * Macros defining the bit position and mask of 'CNV' flag + * within the hdr_flags field of LW0 (service response only) */ +#define ICP_QAT_FW_COMN_CNV_FLAG_BITPOS 6 +#define ICP_QAT_FW_COMN_CNV_FLAG_MASK 0x1 + +/**< @ingroup icp_qat_fw_comn + * Macros defining the bit position and mask of CNVNR flag + * within the hdr_flags field of LW0 (service response only) */ +#define ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS 5 +#define ICP_QAT_FW_COMN_CNVNR_FLAG_MASK 0x1 + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of Service Type Field + * + * @param icp_qat_fw_comn_req_hdr_t Structure 'icp_qat_fw_comn_req_hdr_t' + * to extract the Service Type Field + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \ + icp_qat_fw_comn_req_hdr_t.service_type + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for setting of Service Type Field + * + * @param 'icp_qat_fw_comn_req_hdr_t' structure to set the Service + * Type Field + * @param val Value of the Service Type Field + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_OV_SRV_TYPE_SET(icp_qat_fw_comn_req_hdr_t, val) \ + icp_qat_fw_comn_req_hdr_t.service_type = val + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of Service Command Id Field + * + * @param icp_qat_fw_comn_req_hdr_t Structure 'icp_qat_fw_comn_req_hdr_t' + * to extract the Service Command Id Field + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_GET(icp_qat_fw_comn_req_hdr_t) \ + icp_qat_fw_comn_req_hdr_t.service_cmd_id + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for setting of Service Command Id Field + * + * @param 'icp_qat_fw_comn_req_hdr_t' structure to set the + * Service Command Id Field + * @param val Value of the Service Command Id Field + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_SET(icp_qat_fw_comn_req_hdr_t, val) \ + icp_qat_fw_comn_req_hdr_t.service_cmd_id = val + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Extract the valid flag from the request or response's header flags. + * + * @param hdr_t Request or Response 'hdr_t' structure to extract the valid bit + * from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_GET(hdr_t) \ + ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_t.hdr_flags) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Extract the CNVNR flag from the header flags in the response only. + * + * @param hdr_t Response 'hdr_t' structure to extract the CNVNR bit + * from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdr_flags) \ + QAT_FIELD_GET(hdr_flags, \ + ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_CNVNR_FLAG_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Extract the CNV flag from the header flags in the response only. + * + * @param hdr_t Response 'hdr_t' structure to extract the CNV bit + * from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdr_flags) \ + QAT_FIELD_GET(hdr_flags, \ + ICP_QAT_FW_COMN_CNV_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_CNV_FLAG_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Set the valid bit in the request's header flags. + * + * @param hdr_t Request or Response 'hdr_t' structure to set the valid bit + * @param val Value of the valid bit flag. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_SET(hdr_t, val) \ + ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Common macro to extract the valid flag from the header flags field + * within the header structure (request or response). + * + * @param hdr_t Structure (request or response) to extract the + * valid bit from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_flags) \ + QAT_FIELD_GET(hdr_flags, \ + ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_VALID_FLAG_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Common macro to extract the remaining reserved flags from the header + flags field within the header structure (request or response). + * + * @param hdr_t Structure (request or response) to extract the + * remaining bits from the 'hdr_flags' field (excluding the + * valid flag). + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_GET(hdr_flags) \ + (hdr_flags & ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Common macro to set the valid bit in the header flags field within + * the header structure (request or response). + * + * @param hdr_t Structure (request or response) containing the header + * flags field, to allow the valid bit to be set. + * @param val Value of the valid bit flag. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) \ + QAT_FIELD_SET((hdr_t.hdr_flags), \ + (val), \ + ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_COMN_VALID_FLAG_MASK) + +/** +****************************************************************************** +* @ingroup icp_qat_fw_comn +* +* @description +* Macro that must be used when building the common header flags. +* Note that all bits reserved field bits 0-6 (LW0) need to be forced to 0. +* +* @param ptr Value of the valid flag +*****************************************************************************/ + +#define ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(valid) \ + (((valid)&ICP_QAT_FW_COMN_VALID_FLAG_MASK) \ + << ICP_QAT_FW_COMN_VALID_FLAG_BITPOS) + +/* + * < @ingroup icp_qat_fw_comn + * Common Request Flags Definition + * The bit offsets below are within the flags field. These are NOT relative to + * the memory word. Unused fields e.g. reserved bits, must be zeroed. + * + * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + + * | Bits [15:8] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | + * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + + * | Flags[15:8] | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | + * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + + * | Bits [7:0] | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + + * | Flags [7:0] | Rsv | Rsv | Rsv | Rsv | Rsv | BnP | Cdt | Ptr | + * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + + */ + +#define QAT_COMN_PTR_TYPE_BITPOS 0 +/**< @ingroup icp_qat_fw_comn + * Common Request Flags - Starting bit position indicating + * Src&Dst Buffer Pointer type */ + +#define QAT_COMN_PTR_TYPE_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * Common Request Flags - One bit mask used to determine + * Src&Dst Buffer Pointer type */ + +#define QAT_COMN_CD_FLD_TYPE_BITPOS 1 +/**< @ingroup icp_qat_fw_comn + * Common Request Flags - Starting bit position indicating + * CD Field type */ + +#define QAT_COMN_CD_FLD_TYPE_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * Common Request Flags - One bit mask used to determine + * CD Field type */ + +#define QAT_COMN_BNP_ENABLED_BITPOS 2 +/**< @ingroup icp_qat_fw_comn + * Common Request Flags - Starting bit position indicating + * the source buffer contains batch of requests. if this + * bit is set, source buffer is type of Batch And Pack OpData List + * and the Ptr Type Bit only applies to Destination buffer. */ + +#define QAT_COMN_BNP_ENABLED_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * Batch And Pack Enabled Flag Mask - One bit mask used to determine + * the source buffer is in Batch and Pack OpData Link List Mode. */ + +/* ========================================================================= */ +/* Pointer Type Flag definitions */ +/* ========================================================================= */ +#define QAT_COMN_PTR_TYPE_FLAT 0x0 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating Src&Dst Buffer Pointer type is flat + * If Batch and Pack mode is enabled, only applies to Destination buffer.*/ + +#define QAT_COMN_PTR_TYPE_SGL 0x1 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating Src&Dst Buffer Pointer type is SGL type + * If Batch and Pack mode is enabled, only applies to Destination buffer.*/ + +#define QAT_COMN_PTR_TYPE_BATCH 0x2 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating Src is a batch request + * and Dst Buffer Pointer type is SGL type */ + +/* ========================================================================= */ +/* CD Field Flag definitions */ +/* ========================================================================= */ +#define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating CD Field contains 64-bit address */ + +#define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating CD Field contains 16 bytes of setup data */ + +/* ========================================================================= */ +/* Batch And Pack Enable/Disable Definitions */ +/* ========================================================================= */ +#define QAT_COMN_BNP_ENABLED 0x1 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating Source buffer will point to Batch And Pack OpData + * List */ + +#define QAT_COMN_BNP_DISABLED 0x0 +/**< @ingroup icp_qat_fw_comn + * Constant value indicating Source buffer will point to Batch And Pack OpData + * List */ + +/** +****************************************************************************** +* @ingroup icp_qat_fw_comn +* +* @description +* Macro that must be used when building the common request flags (for all +* requests but comp BnP). +* Note that all bits reserved field bits 2-15 (LW1) need to be forced to 0. +* +* @param ptr Value of the pointer type flag +* @param cdt Value of the cd field type flag +*****************************************************************************/ +#define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \ + ((((cdt)&QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) | \ + (((ptr)&QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS)) + +/** +****************************************************************************** +* @ingroup icp_qat_fw_comn +* +* @description +* Macro that must be used when building the common request flags for comp +* BnP service. +* Note that all bits reserved field bits 3-15 (LW1) need to be forced to 0. +* +* @param ptr Value of the pointer type flag +* @param cdt Value of the cd field type flag +* @param bnp Value of the bnp enabled flag +*****************************************************************************/ +#define ICP_QAT_FW_COMN_FLAGS_BUILD_BNP(cdt, ptr, bnp) \ + ((((cdt)&QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) | \ + (((ptr)&QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS) | \ + (((bnp)&QAT_COMN_BNP_ENABLED_MASK) << QAT_COMN_BNP_ENABLED_BITPOS)) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the pointer type bit from the common flags + * + * @param flags Flags to extract the pointer type bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_PTR_TYPE_GET(flags) \ + QAT_FIELD_GET(flags, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the cd field type bit from the common flags + * + * @param flags Flags to extract the cd field type type bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_CD_FLD_TYPE_GET(flags) \ + QAT_FIELD_GET(flags, \ + QAT_COMN_CD_FLD_TYPE_BITPOS, \ + QAT_COMN_CD_FLD_TYPE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the bnp field type bit from the common flags + * + * @param flags Flags to extract the bnp field type type bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_BNP_ENABLED_GET(flags) \ + QAT_FIELD_GET(flags, \ + QAT_COMN_BNP_ENABLED_BITPOS, \ + QAT_COMN_BNP_ENABLED_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for setting the pointer type bit in the common flags + * + * @param flags Flags in which Pointer Type bit will be set + * @param val Value of the bit to be set in flags + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_PTR_TYPE_SET(flags, val) \ + QAT_FIELD_SET(flags, \ + val, \ + QAT_COMN_PTR_TYPE_BITPOS, \ + QAT_COMN_PTR_TYPE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for setting the cd field type bit in the common flags + * + * @param flags Flags in which Cd Field Type bit will be set + * @param val Value of the bit to be set in flags + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(flags, val) \ + QAT_FIELD_SET(flags, \ + val, \ + QAT_COMN_CD_FLD_TYPE_BITPOS, \ + QAT_COMN_CD_FLD_TYPE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for setting the bnp field type bit in the common flags + * + * @param flags Flags in which Bnp Field Type bit will be set + * @param val Value of the bit to be set in flags + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_BNP_ENABLE_SET(flags, val) \ + QAT_FIELD_SET(flags, \ + val, \ + QAT_COMN_BNP_ENABLED_BITPOS, \ + QAT_COMN_BNP_ENABLED_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macros using the bit position and mask to set/extract the next + * and current id nibbles within the next_curr_id field of the + * content descriptor header block. Note that these are defined + * in the common header file, as they are used by compression, cipher + * and authentication. + * + * @param cd_ctrl_hdr_t Content descriptor control block header pointer. + * @param val Value of the field being set. + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4 +#define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0 +#define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0 +#define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F + +#define ICP_QAT_FW_COMN_NEXT_ID_GET(cd_ctrl_hdr_t) \ + ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ + (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) + +#define ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ + ((cd_ctrl_hdr_t)->next_curr_id) = \ + ((((cd_ctrl_hdr_t)->next_curr_id) & \ + ICP_QAT_FW_COMN_CURR_ID_MASK) | \ + ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK)) + +#define ICP_QAT_FW_COMN_CURR_ID_GET(cd_ctrl_hdr_t) \ + (((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK) + +#define ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl_hdr_t, val) \ + ((cd_ctrl_hdr_t)->next_curr_id) = \ + ((((cd_ctrl_hdr_t)->next_curr_id) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ + ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) + +/* + * < @ingroup icp_qat_fw_comn + * Common Status Field Definition The bit offsets below are within the COMMON + * RESPONSE status field, assumed to be 8 bits wide. In the case of the PKE + * response (which follows the CPM 1.5 message format), the status field is 16 + * bits wide. + * The status flags are contained within the most significant byte and align + * with the diagram below. Please therefore refer to the service-specific PKE + * header file for the appropriate macro definition to extract the PKE status + * flag from the PKE response, which assumes that a word is passed to the + * macro. + * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + + * | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + + * | Flags | Crypto | Pke | Cmp | Xlat | EOLB | UnSupReq | Rsvd | XltWaApply | + * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + + * Note: + * For the service specific status bit definitions refer to service header files + * Eg. Crypto Status bit refers to Symmetric Crypto, Key Generation, and NRBG + * Requests' Status. Unused bits e.g. reserved bits need to have been forced to + * 0. + */ + +#define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating Response for Crypto service Flag */ + +#define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine Crypto status mask */ + +#define QAT_COMN_RESP_PKE_STATUS_BITPOS 6 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating Response for PKE service Flag */ + +#define QAT_COMN_RESP_PKE_STATUS_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine PKE status mask */ + +#define QAT_COMN_RESP_CMP_STATUS_BITPOS 5 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating Response for Compression service Flag */ + +#define QAT_COMN_RESP_CMP_STATUS_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine Compression status mask */ + +#define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating Response for Xlat service Flag */ + +#define QAT_COMN_RESP_XLAT_STATUS_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine Translator status mask */ + +#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS 3 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating the last block in a deflate stream for + the compression service Flag */ + +#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine the last block in a deflate stream + status mask */ + +#define QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS 2 +/**< @ingroup icp_qat_fw_comn + * Starting bit position indicating when an unsupported service request Flag */ + +#define QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask used to determine the unsupported service request status mask */ + +#define QAT_COMN_RESP_XLT_INV_APPLIED_BITPOS 0 +/**< @ingroup icp_qat_fw_comn + * Bit position indicating that firmware detected an invalid translation during + * dynamic compression and took measures to overcome this + * + */ + +#define QAT_COMN_RESP_XLT_INV_APPLIED_MASK 0x1 +/**< @ingroup icp_qat_fw_comn + * One bit mask */ + +/** + ****************************************************************************** + * @description + * Macro that must be used when building the status + * for the common response + * + * @param crypto Value of the Crypto Service status flag + * @param comp Value of the Compression Service Status flag + * @param xlat Value of the Xlator Status flag + * @param eolb Value of the Compression End of Last Block Status flag + * @param unsupp Value of the Unsupported Request flag + * @param xlt_inv Value of the Invalid Translation flag + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_STATUS_BUILD( \ + crypto, pke, comp, xlat, eolb, unsupp, xlt_inv) \ + ((((crypto)&QAT_COMN_RESP_CRYPTO_STATUS_MASK) \ + << QAT_COMN_RESP_CRYPTO_STATUS_BITPOS) | \ + (((pke)&QAT_COMN_RESP_PKE_STATUS_MASK) \ + << QAT_COMN_RESP_PKE_STATUS_BITPOS) | \ + (((xlt_inv)&QAT_COMN_RESP_XLT_INV_APPLIED_MASK) \ + << QAT_COMN_RESP_XLT_INV_APPLIED_BITPOS) | \ + (((comp)&QAT_COMN_RESP_CMP_STATUS_MASK) \ + << QAT_COMN_RESP_CMP_STATUS_BITPOS) | \ + (((xlat)&QAT_COMN_RESP_XLAT_STATUS_MASK) \ + << QAT_COMN_RESP_XLAT_STATUS_BITPOS) | \ + (((eolb)&QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) \ + << QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS) | \ + (((unsupp)&QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS) \ + << QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK)) + +/* ========================================================================= */ +/* GETTERS */ +/* ========================================================================= */ +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the Crypto bit from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CRYPTO_STATUS_BITPOS, \ + QAT_COMN_RESP_CRYPTO_STATUS_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the PKE bit from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_PKE_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_PKE_STATUS_BITPOS, \ + QAT_COMN_RESP_PKE_STATUS_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the Compression bit from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CMP_STATUS_BITPOS, \ + QAT_COMN_RESP_CMP_STATUS_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the Translator bit from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_XLAT_STATUS_BITPOS, \ + QAT_COMN_RESP_XLAT_STATUS_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the Translation Invalid bit + * from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_XLT_INV_APPLIED_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_XLT_INV_APPLIED_BITPOS, \ + QAT_COMN_RESP_XLT_INV_APPLIED_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the end of compression block bit from the + * status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS, \ + QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comn + * + * @description + * Macro for extraction of the Unsupported request from the status + * + * @param status + * Status to extract the status bit from + * + *****************************************************************************/ +#define ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(status) \ + QAT_FIELD_GET(status, \ + QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS, \ + QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK) + +/* ========================================================================= */ +/* Status Flag definitions */ +/* ========================================================================= */ + +#define ICP_QAT_FW_COMN_STATUS_FLAG_OK 0 +/**< @ingroup icp_qat_fw_comn + * Definition of successful processing of a request */ + +#define ICP_QAT_FW_COMN_STATUS_FLAG_ERROR 1 +/**< @ingroup icp_qat_fw_comn + * Definition of erroneous processing of a request */ + +#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_CLR 0 +/**< @ingroup icp_qat_fw_comn + * Final Deflate block of a compression request not completed */ + +#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET 1 +/**< @ingroup icp_qat_fw_comn + * Final Deflate block of a compression request completed */ + +#define ERR_CODE_NO_ERROR 0 +/**< Error Code constant value for no error */ + +#define ERR_CODE_INVALID_BLOCK_TYPE -1 +/* Invalid block type (type == 3)*/ + +#define ERR_CODE_NO_MATCH_ONES_COMP -2 +/* Stored block length does not match one's complement */ + +#define ERR_CODE_TOO_MANY_LEN_OR_DIS -3 +/* Too many length or distance codes */ + +#define ERR_CODE_INCOMPLETE_LEN -4 +/* Code lengths codes incomplete */ + +#define ERR_CODE_RPT_LEN_NO_FIRST_LEN -5 +/* Repeat lengths with no first length */ + +#define ERR_CODE_RPT_GT_SPEC_LEN -6 +/* Repeat more than specified lengths */ + +#define ERR_CODE_INV_LIT_LEN_CODE_LEN -7 +/* Invalid lit/len code lengths */ + +#define ERR_CODE_INV_DIS_CODE_LEN -8 +/* Invalid distance code lengths */ + +#define ERR_CODE_INV_LIT_LEN_DIS_IN_BLK -9 +/* Invalid lit/len or distance code in fixed/dynamic block */ + +#define ERR_CODE_DIS_TOO_FAR_BACK -10 +/* Distance too far back in fixed or dynamic block */ + +/* Common Error code definitions */ +#define ERR_CODE_OVERFLOW_ERROR -11 +/**< Error Code constant value for overflow error */ + +#define ERR_CODE_SOFT_ERROR -12 +/**< Error Code constant value for soft error */ + +#define ERR_CODE_FATAL_ERROR -13 +/**< Error Code constant value for hard/fatal error */ + +#define ERR_CODE_COMP_OUTPUT_CORRUPTION -14 +/**< Error Code constant for compression output corruption */ + +#define ERR_CODE_HW_INCOMPLETE_FILE -15 +/**< Error Code constant value for incomplete file hardware error */ + +#define ERR_CODE_SSM_ERROR -16 +/**< Error Code constant value for error detected by SSM e.g. slice hang */ + +#define ERR_CODE_ENDPOINT_ERROR -17 +/**< Error Code constant value for error detected by PCIe Endpoint, e.g. push + * data error */ + +#define ERR_CODE_CNV_ERROR -18 +/**< Error Code constant value for cnv failure */ + +#define ERR_CODE_EMPTY_DYM_BLOCK -19 +/**< Error Code constant value for submission of empty dynamic stored block to + * slice */ + +#define ERR_CODE_EXCEED_MAX_REQ_TIME -24 +/**< Error Code constant for exceeding max request time */ + +#define ERR_CODE_KPT_CRYPTO_SERVICE_FAIL_INVALID_HANDLE -20 +/**< Error Code constant for invalid handle in kpt crypto service */ + +#define ERR_CODE_KPT_CRYPTO_SERVICE_FAIL_HMAC_FAILED -21 +/**< Error Code constant for failed hmac in kpt crypto service */ + +#define ERR_CODE_KPT_CRYPTO_SERVICE_FAIL_INVALID_WRAPPING_ALGO -22 +/**< Error Code constant for invalid wrapping algo in kpt crypto service */ + +#define ERR_CODE_KPT_DRNG_SEED_NOT_LOAD -23 +/**< Error Code constant for no drng seed is not loaded in kpt ecdsa signrs +/service */ + +#define ERR_CODE_MISC_ERROR -50 +/**< Error Code constant for error detected but the source + * of error is not recognized */ + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Slice types for building of the processing chain within the content + * descriptor + * + * @description + * Enumeration used to indicate the ids of the slice types through which + * data will pass. + * + * A logical slice is not a hardware slice but is a software FSM + * performing the actions of a slice + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_FW_SLICE_NULL = 0, /**< NULL slice type */ + ICP_QAT_FW_SLICE_CIPHER = 1, /**< CIPHER slice type */ + ICP_QAT_FW_SLICE_AUTH = 2, /**< AUTH slice type */ + ICP_QAT_FW_SLICE_DRAM_RD = 3, /**< DRAM_RD Logical slice type */ + ICP_QAT_FW_SLICE_DRAM_WR = 4, /**< DRAM_WR Logical slice type */ + ICP_QAT_FW_SLICE_COMP = 5, /**< Compression slice type */ + ICP_QAT_FW_SLICE_XLAT = 6, /**< Translator slice type */ + ICP_QAT_FW_SLICE_DELIMITER /**< End delimiter */ + +} icp_qat_fw_slice_t; + +#endif /* _ICP_QAT_FW_H_ */ diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_comp.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_comp.h new file mode 100644 index 00000000000..1a9d7e727bd --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_comp.h @@ -0,0 +1,1029 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_qat_fw_comp.h + * @defgroup icp_qat_fw_comp ICP QAT FW Compression Service + * Interface Definitions + * @ingroup icp_qat_fw + * @description + * This file documents structs used to provide the interface to the + * Compression QAT FW service + * + *****************************************************************************/ + +#ifndef _ICP_QAT_FW_COMP_H_ +#define _ICP_QAT_FW_COMP_H_ + +/* +****************************************************************************** +* Include local header files +****************************************************************************** +*/ +#include "icp_qat_fw.h" + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the Compression command types + * @description + * Enumeration which is used to indicate the ids of functions + * that are exposed by the Compression QAT FW service + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_FW_COMP_CMD_STATIC = 0, + /*!< Static Compress Request */ + + ICP_QAT_FW_COMP_CMD_DYNAMIC = 1, + /*!< Dynamic Compress Request */ + + ICP_QAT_FW_COMP_CMD_DECOMPRESS = 2, + /*!< Decompress Request */ + + ICP_QAT_FW_COMP_CMD_DELIMITER + /**< Delimiter type */ + +} icp_qat_fw_comp_cmd_id_t; + +/* + * REQUEST FLAGS IN COMMON COMPRESSION + * In common message it is named as SERVICE SPECIFIC FLAGS. + * + * + ===== + ------ + ------ + --- + ----- + ----- + ----- + -- + ---- + --- + + * | Bit | 15 - 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * + ===== + ------ + ----- + --- + ----- + ----- + ----- + -- + ---- + --- + + * | Flags | Rsvd | Dis. |Resvd| Dis. | Enh. |Auto |Sess| Rsvd | Rsvd| + * | | Bits | secure | =0 | Type0 | ASB |Select |Type| = 0 | = 0 | + * | | = 0 |RAM use | | Header | |Best | | | | + * | | |as intmd| | | | | | | | + * | | | buf | | | | | | | | + * + ===== + ------ + ----- + --- + ------ + ----- + ----- + -- + ---- + --- + + */ + +/** Flag usage */ + +#define ICP_QAT_FW_COMP_STATELESS_SESSION 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that session is stateless */ + +#define ICP_QAT_FW_COMP_STATEFUL_SESSION 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that session is stateful */ + +#define ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that autoselectbest is NOT used */ + +#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that autoselectbest is used */ + +#define ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that enhanced autoselectbest is NOT used */ + +#define ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that enhanced autoselectbest is used */ + +#define ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that enhanced autoselectbest is NOT used */ + +#define ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that enhanced autoselectbest is used */ + +#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing secure RAM from being used as + * an intermediate buffer is DISABLED. */ + +#define ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing secure RAM from being used as + * an intermediate buffer is ENABLED. */ + +/** Flag mask & bit position */ + +#define ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS 2 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for the session type */ + +#define ICP_QAT_FW_COMP_SESSION_TYPE_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask used to determine the session type */ + +#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS 3 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for auto select best */ + +#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for auto select best */ + +#define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS 4 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for enhanced auto select best */ + +#define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for enhanced auto select best */ + +#define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS 5 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for disabling type zero header write back + when Enhanced autoselect best is enabled. If set firmware does + not return type0 store block header, only copies src to dest. + (if best output is Type0) */ + +#define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for auto select best */ + +#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS 7 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for flag used to disable secure ram from + * being used as an intermediate buffer. */ + +#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for disable secure ram for use as an intermediate + buffer. */ + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro used for the generation of the command flags for Compression Request. + * This should always be used for the generation of the flags. No direct sets or + * masks should be performed on the flags data + * + * @param sesstype Session Type + * @param autoselect AutoSelectBest + * @enhanced_asb Enhanced AutoSelectBest + * @ret_uncomp RetUnCompressed + * @secure_ram Secure Ram usage + * + *********************************************************************************/ +#define ICP_QAT_FW_COMP_FLAGS_BUILD( \ + sesstype, autoselect, enhanced_asb, ret_uncomp, secure_ram) \ + (((sesstype & ICP_QAT_FW_COMP_SESSION_TYPE_MASK) \ + << ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS) | \ + ((autoselect & ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK) \ + << ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS) | \ + ((enhanced_asb & ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK) \ + << ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS) | \ + ((ret_uncomp & ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK) \ + << ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS) | \ + ((secure_ram & ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK) \ + << ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS)) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the session type bit + * + * @param flags Flags to extract the session type bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_SESSION_TYPE_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS, \ + ICP_QAT_FW_COMP_SESSION_TYPE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the autoSelectBest bit + * + * @param flags Flags to extract the autoSelectBest bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS, \ + ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the enhanced asb bit + * + * @param flags Flags to extract the enhanced asb bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_EN_ASB_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS, \ + ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the RetUncomp bit + * + * @param flags Flags to extract the Ret Uncomp bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_RET_UNCOMP_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS, \ + ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the Secure Ram usage bit + * + * @param flags Flags to extract the Secure Ram usage from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_SECURE_RAM_USE_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS, \ + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the compression header cd pars block + * @description + * Definition of the compression processing cd pars block. + * The structure is a service-specific implementation of the common + * structure. + ******************************************************************************/ +typedef union icp_qat_fw_comp_req_hdr_cd_pars_s { + /**< LWs 2-5 */ + struct { + uint64_t content_desc_addr; + /**< Address of the content descriptor */ + + uint16_t content_desc_resrvd1; + /**< Content descriptor reserved field */ + + uint8_t content_desc_params_sz; + /**< Size of the content descriptor parameters in quad words. + * These + * parameters describe the session setup configuration info for + * the + * slices that this request relies upon i.e. the configuration + * word and + * cipher key needed by the cipher slice if there is a request + * for + * cipher + * processing. */ + + uint8_t content_desc_hdr_resrvd2; + /**< Content descriptor reserved field */ + + uint32_t content_desc_resrvd3; + /**< Content descriptor reserved field */ + } s; + + struct { + uint32_t comp_slice_cfg_word[ICP_QAT_FW_NUM_LONGWORDS_2]; + /* Compression Slice Config Word */ + + uint32_t content_desc_resrvd4; + /**< Content descriptor reserved field */ + } sl; + +} icp_qat_fw_comp_req_hdr_cd_pars_t; + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the compression request parameters block + * @description + * Definition of the compression processing request parameters block. + * The structure below forms part of the Compression + Translation + * Parameters block spanning LWs 14-21, thus differing from the common + * base Parameters block structure. Unused fields must be set to 0. + * + ******************************************************************************/ +typedef struct icp_qat_fw_comp_req_params_s { + /**< LW 14 */ + uint32_t comp_len; + /**< Size of input to process in bytes Note: Only EOP requests can be + * odd + * for decompression. IA must set LSB to zero for odd sized intermediate + * inputs */ + + /**< LW 15 */ + uint32_t out_buffer_sz; + /**< Size of output buffer in bytes */ + + /**< LW 16 */ + union { + struct { + /** LW 16 */ + uint32_t initial_crc32; + /**< CRC for processed bytes (input byte count) */ + + /** LW 17 */ + uint32_t initial_adler; + /**< Adler for processed bytes (input byte count) */ + } legacy; + + /** LW 16-17 */ + uint64_t crc_data_addr; + /**< CRC data structure pointer */ + } crc; + + /** LW 18 */ + uint32_t req_par_flags; + + /** LW 19 */ + uint32_t rsrvd; + +} icp_qat_fw_comp_req_params_t; + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro used for the generation of the request parameter flags. + * This should always be used for the generation of the flags. No direct sets or + * masks should be performed on the flags data + * + * @param sop SOP Flag, 0 restore, 1 don't restore + * @param eop EOP Flag, 0 restore, 1 don't restore + * @param bfinal Set bfinal in this block or not + * @param cnv Whether internal CNV check is to be performed + * * ICP_QAT_FW_COMP_NO_CNV + * * ICP_QAT_FW_COMP_CNV + * @param cnvnr Whether internal CNV recovery is to be performed + * * ICP_QAT_FW_COMP_NO_CNV_RECOVERY + * * ICP_QAT_FW_COMP_CNV_RECOVERY + * @param crc CRC Mode Flag - 0 legacy, 1 crc data struct + * + *****************************************************************************/ +#define ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( \ + sop, eop, bfinal, cnv, cnvnr, crc) \ + (((sop & ICP_QAT_FW_COMP_SOP_MASK) << ICP_QAT_FW_COMP_SOP_BITPOS) | \ + ((eop & ICP_QAT_FW_COMP_EOP_MASK) << ICP_QAT_FW_COMP_EOP_BITPOS) | \ + ((bfinal & ICP_QAT_FW_COMP_BFINAL_MASK) \ + << ICP_QAT_FW_COMP_BFINAL_BITPOS) | \ + ((cnv & ICP_QAT_FW_COMP_CNV_MASK) << ICP_QAT_FW_COMP_CNV_BITPOS) | \ + ((cnvnr & ICP_QAT_FW_COMP_CNV_RECOVERY_MASK) \ + << ICP_QAT_FW_COMP_CNV_RECOVERY_BITPOS) | \ + ((crc & ICP_QAT_FW_COMP_CRC_MODE_MASK) \ + << ICP_QAT_FW_COMP_CRC_MODE_BITPOS)) + +/* + * REQUEST FLAGS IN REQUEST PARAMETERS COMPRESSION + * + * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- + ---- + --- + + * --- + + * | Bit | 31-20 | 19 | 18 | 17 | 16 | 15 - 7 | 6 | 5-2 | 1 | 0 + * | + * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- | ---- + --- + + * --- + + * | Flags | Resvd | CRC |Resvd| CNVNR | CNV |Resvd Bits|BFin |Resvd | EOP | + * SOP | + * | | =0 | Mode| =0 | | | =0 | | =0 | | | + * | | | | | | | | | | | | + * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- | ---- + --- + + * --- + + */ + +#define ICP_QAT_FW_COMP_NOT_SOP 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that a request is NOT Start of Packet */ + +#define ICP_QAT_FW_COMP_SOP 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that a request IS Start of Packet */ + +#define ICP_QAT_FW_COMP_NOT_EOP 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing that a request is NOT Start of Packet */ + +#define ICP_QAT_FW_COMP_EOP 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing that a request IS End of Packet */ + +#define ICP_QAT_FW_COMP_NOT_BFINAL 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing to indicate firmware this is not the last block */ + +#define ICP_QAT_FW_COMP_BFINAL 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing to indicate firmware this is the last block */ + +#define ICP_QAT_FW_COMP_NO_CNV 0 +/**< @ingroup icp_qat_fw_comp + * Flag indicating that NO cnv check is to be performed on the request */ + +#define ICP_QAT_FW_COMP_CNV 1 +/**< @ingroup icp_qat_fw_comp + * Flag indicating that a cnv check IS to be performed on the request */ + +#define ICP_QAT_FW_COMP_NO_CNV_RECOVERY 0 +/**< @ingroup icp_qat_fw_comp + * Flag indicating that NO cnv recovery is to be performed on the request */ + +#define ICP_QAT_FW_COMP_CNV_RECOVERY 1 +/**< @ingroup icp_qat_fw_comp + * Flag indicating that a cnv recovery is to be performed on the request */ + +#define ICP_QAT_FW_COMP_CRC_MODE_LEGACY 0 +/**< @ingroup icp_qat_fw_comp + * Flag representing to use the legacy CRC mode */ + +#define ICP_QAT_FW_COMP_CRC_MODE_E2E 1 +/**< @ingroup icp_qat_fw_comp + * Flag representing to use the external CRC data struct */ + +#define ICP_QAT_FW_COMP_SOP_BITPOS 0 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for SOP */ + +#define ICP_QAT_FW_COMP_SOP_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask used to determine SOP */ + +#define ICP_QAT_FW_COMP_EOP_BITPOS 1 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for EOP */ + +#define ICP_QAT_FW_COMP_EOP_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask used to determine EOP */ + +#define ICP_QAT_FW_COMP_BFINAL_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for the bfinal bit */ + +#define ICP_QAT_FW_COMP_BFINAL_BITPOS 6 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for the bfinal bit */ + +#define ICP_QAT_FW_COMP_CNV_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for the CNV bit */ + +#define ICP_QAT_FW_COMP_CNV_BITPOS 16 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for the CNV bit */ + +#define ICP_QAT_FW_COMP_CNV_RECOVERY_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask for the CNV Recovery bit */ + +#define ICP_QAT_FW_COMP_CNV_RECOVERY_BITPOS 17 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for the CNV Recovery bit */ + +#define ICP_QAT_FW_COMP_CRC_MODE_BITPOS 19 +/**< @ingroup icp_qat_fw_comp + * Starting bit position for CRC mode */ + +#define ICP_QAT_FW_COMP_CRC_MODE_MASK 0x1 +/**< @ingroup icp_qat_fw_comp + * One bit mask used to determine CRC mode */ + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the SOP bit + * + * @param flags Flags to extract the SOP bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_SOP_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_SOP_BITPOS, \ + ICP_QAT_FW_COMP_SOP_MASK) + +/** +****************************************************************************** +* @ingroup icp_qat_fw_comp +* +* @description +* Macro for extraction of the EOP bit +* +* @param flags Flags to extract the EOP bit from +* +*****************************************************************************/ +#define ICP_QAT_FW_COMP_EOP_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_EOP_BITPOS, \ + ICP_QAT_FW_COMP_EOP_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the bfinal bit + * + * @param flags Flags to extract the bfinal bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_BFINAL_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_BFINAL_BITPOS, \ + ICP_QAT_FW_COMP_BFINAL_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the CNV bit + * + * @param flags Flag set containing the CNV flag + * + *****************************************************************************/ +#define ICP_QAT_FW_COMP_CNV_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_CNV_BITPOS, \ + ICP_QAT_FW_COMP_CNV_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * + * @description + * Macro for extraction of the crc mode bit + * + * @param flags Flags to extract the crc mode bit from + * + ******************************************************************************/ +#define ICP_QAT_FW_COMP_CRC_MODE_GET(flags) \ + QAT_FIELD_GET(flags, \ + ICP_QAT_FW_COMP_CRC_MODE_BITPOS, \ + ICP_QAT_FW_COMP_CRC_MODE_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the translator request parameters block + * @description + * Definition of the translator processing request parameters block + * The structure below forms part of the Compression + Translation + * Parameters block spanning LWs 20-21, thus differing from the common + * base Parameters block structure. Unused fields must be set to 0. + * + ******************************************************************************/ +typedef struct icp_qat_fw_xlt_req_params_s { + /**< LWs 20-21 */ + uint64_t inter_buff_ptr; + /**< This field specifies the physical address of an intermediate + * buffer SGL array. The array contains a pair of 64-bit + * intermediate buffer pointers to SGL buffer descriptors, one pair + * per CPM. Please refer to the CPM1.6 Firmware Interface HLD + * specification for more details. */ +} icp_qat_fw_xlt_req_params_t; + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Compression header of the content descriptor block + * @description + * Definition of the service-specific compression control block header + * structure. The compression parameters are defined per algorithm + * and are located in the icp_qat_hw.h file. This compression + * cd block spans LWs 24-29, forming part of the compression + translation + * cd block, thus differing from the common base content descriptor + * structure. + * + ******************************************************************************/ +typedef struct icp_qat_fw_comp_cd_hdr_s { + /**< LW 24 */ + uint16_t ram_bank_flags; + /**< Flags to show which ram banks to access */ + + uint8_t comp_cfg_offset; + /**< Quad word offset from the content descriptor parameters address to + * the + * parameters for the compression processing */ + + uint8_t next_curr_id; + /**< This field combines the next and current id (each four bits) - + * the next id is the most significant nibble. + * Next Id: Set to the next slice to pass the compressed data through. + * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through + * anymore slices after compression + * Current Id: Initialised with the compression slice type */ + + /**< LW 25 */ + uint32_t resrvd; + + /**< LWs 26-27 */ + uint64_t comp_state_addr; + /**< Pointer to compression state */ + + /**< LWs 28-29 */ + uint64_t ram_banks_addr; + /**< Pointer to banks */ + +} icp_qat_fw_comp_cd_hdr_t; + +#define COMP_CPR_INITIAL_CRC 0 +#define COMP_CPR_INITIAL_ADLER 1 + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Translator content descriptor header block + * @description + * Definition of the structure used to describe the translation processing + * to perform on data. The translator parameters are defined per algorithm + * and are located in the icp_qat_hw.h file. This translation cd block + * spans LWs 30-31, forming part of the compression + translation cd block, + * thus differing from the common base content descriptor structure. + * + ******************************************************************************/ +typedef struct icp_qat_fw_xlt_cd_hdr_s { + /**< LW 30 */ + uint16_t resrvd1; + /**< Reserved field and assumed set to 0 */ + + uint8_t resrvd2; + /**< Reserved field and assumed set to 0 */ + + uint8_t next_curr_id; + /**< This field combines the next and current id (each four bits) - + * the next id is the most significant nibble. + * Next Id: Set to the next slice to pass the translated data through. + * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through + * any more slices after compression + * Current Id: Initialised with the translation slice type */ + + /**< LW 31 */ + uint32_t resrvd3; + /**< Reserved and should be set to zero, needed for quadword alignment + */ +} icp_qat_fw_xlt_cd_hdr_t; + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the common Compression QAT FW request + * @description + * This is a definition of the full request structure for + * compression and translation. + * + ******************************************************************************/ +typedef struct icp_qat_fw_comp_req_s { + /**< LWs 0-1 */ + icp_qat_fw_comn_req_hdr_t comn_hdr; + /**< Common request header - for Service Command Id, + * use service-specific Compression Command Id. + * Service Specific Flags - use Compression Command Flags */ + + /**< LWs 2-5 */ + icp_qat_fw_comp_req_hdr_cd_pars_t cd_pars; + /**< Compression service-specific content descriptor field which points + * either to a content descriptor parameter block or contains the + * compression slice config word. */ + + /**< LWs 6-13 */ + icp_qat_fw_comn_req_mid_t comn_mid; + /**< Common request middle section */ + + /**< LWs 14-19 */ + icp_qat_fw_comp_req_params_t comp_pars; + /**< Compression request Parameters block */ + + /**< LWs 20-21 */ + union { + icp_qat_fw_xlt_req_params_t xlt_pars; + /**< Translation request Parameters block */ + + uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_2]; + /**< Reserved if not used for translation */ + } u1; + + /**< LWs 22-23 */ + union { + uint32_t resrvd2[ICP_QAT_FW_NUM_LONGWORDS_2]; + /**< Reserved - not used if Batch and Pack is disabled.*/ + + uint64_t bnp_res_table_addr; + /**< A generic pointer to the unbounded list of + * icp_qat_fw_resp_comp_pars_t members. This pointer is only + * used when the Batch and Pack is enabled. */ + } u3; + + /**< LWs 24-29 */ + icp_qat_fw_comp_cd_hdr_t comp_cd_ctrl; + /**< Compression request content descriptor control + * block header */ + + /**< LWs 30-31 */ + union { + icp_qat_fw_xlt_cd_hdr_t xlt_cd_ctrl; + /**< Translation request content descriptor + * control block header */ + + uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_2]; + /**< Reserved if not used for translation */ + } u2; + +} icp_qat_fw_comp_req_t; + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of the compression QAT FW response descriptor + * parameters + * @description + * This part of the response is specific to the compression response. + * + ******************************************************************************/ +typedef struct icp_qat_fw_resp_comp_pars_s { + /**< LW 4 */ + uint32_t input_byte_counter; + /**< Input byte counter */ + + /**< LW 5 */ + uint32_t output_byte_counter; + /**< Output byte counter */ + + /** LW 6-7 */ + union { + struct { + /** LW 6 */ + uint32_t curr_crc32; + /**< Current CRC32 */ + + /** LW 7 */ + uint32_t curr_adler_32; + /**< Current Adler32 */ + } legacy; + + uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_2]; + /**< Reserved if not in legacy mode */ + } crc; + +} icp_qat_fw_resp_comp_pars_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comp + * Definition of a single result metadata structure inside Batch and Pack + * results table array. It describes the output if single job in the + * batch and pack jobs. + * Total number of entries in BNP Out table shall be equal to total + * number of requests in the 'batch'. + * @description + * This structure is specific to the compression output. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comp_bnp_out_tbl_entry_s { + /**< LWs 0-3 */ + icp_qat_fw_resp_comp_pars_t comp_out_pars; + /**< Common output params (checksums and byte counts) */ + + /**< LW 4 */ + icp_qat_fw_comn_error_t comn_error; + /**< This field is overloaded to allow for one 8 bit common error field + * or two 8 bit error fields from compression and translator */ + + uint8_t comn_status; + /**< Status field which specifies which slice(s) report an error */ + + uint8_t reserved0; + /**< Reserved, shall be set to zero */ + + uint32_t reserved1; + /**< Reserved, shall be set to zero, + added for aligning entries to quadword boundary */ +} icp_qat_fw_comp_bnp_out_tbl_entry_t; + +/** +***************************************************************************** +* @ingroup icp_qat_fw_comp +* Supported modes for skipping regions of input or output buffers. +* +* @description +* This enumeration lists the supported modes for skipping regions of +* input or output buffers. +* +*****************************************************************************/ +typedef enum icp_qat_fw_comp_bnp_skip_mode_s { + ICP_QAT_FW_SKIP_DISABLED = 0, + /**< Skip mode is disabled */ + ICP_QAT_FW_SKIP_AT_START = 1, + /**< Skip region is at the start of the buffer. */ + ICP_QAT_FW_SKIP_AT_END = 2, + /**< Skip region is at the end of the buffer. */ + ICP_QAT_FW_SKIP_STRIDE = 3 + /**< Skip region occurs at regular intervals within the buffer. + specifies the number of bytes between each + skip region. */ +} icp_qat_fw_comp_bnp_skip_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Flags describing the skip and compression job bahaviour. refer to flag + * definitions on skip mode and reset/flush types. + * Note: compression behaviour flags are ignored for destination skip info. + * @description + * Definition of the common request flags. + * + *****************************************************************************/ +typedef uint8_t icp_qat_fw_comp_bnp_flags_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_comn + * Skip Region Data. + * @description + * This structure contains data relating to configuring skip region + * behaviour. A skip region is a region of an input buffer that + * should be omitted from processing or a region that should be inserted + * into the output buffer. + * + *****************************************************************************/ +typedef struct icp_qat_fw_comp_bnp_skip_info_s { + /**< LW 0 */ + uint16_t skip_length; + /**next_curr_id_cipher) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ + (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) + +#define ICP_QAT_FW_CIPHER_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ + (cd_ctrl_hdr_t)->next_curr_id_cipher = \ + ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \ + ICP_QAT_FW_COMN_CURR_ID_MASK) | \ + ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK)) + +#define ICP_QAT_FW_CIPHER_CURR_ID_GET(cd_ctrl_hdr_t) \ + (((cd_ctrl_hdr_t)->next_curr_id_cipher) & ICP_QAT_FW_COMN_CURR_ID_MASK) + +#define ICP_QAT_FW_CIPHER_CURR_ID_SET(cd_ctrl_hdr_t, val) \ + (cd_ctrl_hdr_t)->next_curr_id_cipher = \ + ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ + ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) + +/** Authentication fields within Cipher + Authentication structure */ +#define ICP_QAT_FW_AUTH_NEXT_ID_GET(cd_ctrl_hdr_t) \ + ((((cd_ctrl_hdr_t)->next_curr_id_auth) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ + (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) + +#define ICP_QAT_FW_AUTH_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ + (cd_ctrl_hdr_t)->next_curr_id_auth = \ + ((((cd_ctrl_hdr_t)->next_curr_id_auth) & \ + ICP_QAT_FW_COMN_CURR_ID_MASK) | \ + ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK)) + +#define ICP_QAT_FW_AUTH_CURR_ID_GET(cd_ctrl_hdr_t) \ + (((cd_ctrl_hdr_t)->next_curr_id_auth) & ICP_QAT_FW_COMN_CURR_ID_MASK) + +#define ICP_QAT_FW_AUTH_CURR_ID_SET(cd_ctrl_hdr_t, val) \ + (cd_ctrl_hdr_t)->next_curr_id_auth = \ + ((((cd_ctrl_hdr_t)->next_curr_id_auth) & \ + ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ + ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) + +/* Definitions of the bits in the test_status_info of the TRNG_TEST response. + * The values returned by the Lookaside service are given below + * The Test result and Test Fail Count values are only valid if the Test + * Results Valid (Tv) is set. + * + * TRNG Test Status Info + * + ===== + ------------------------------------------------ + --- + --- + + * | Bit | 31 - 2 | 1 | 0 | + * + ===== + ------------------------------------------------ + --- + --- + + * | Flags | RESERVED = 0 | Tv | Ts | + * + ===== + ------------------------------------------------------------ + + */ +/****************************************************************************** + * @ingroup icp_qat_fw_la + * Definition of the Lookaside TRNG Test Status Information received as + * a part of icp_qat_fw_la_trng_test_result_t + * + *****************************************************************************/ +#define QAT_FW_LA_TRNG_TEST_STATUS_TS_BITPOS 0 +/**< @ingroup icp_qat_fw_la + * TRNG Test Result t_status field bit pos definition.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TS_MASK 0x1 +/**< @ingroup icp_qat_fw_la + * TRNG Test Result t_status field mask definition.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TV_BITPOS 1 +/**< @ingroup icp_qat_fw_la + * TRNG Test Result test results valid field bit pos definition.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TV_MASK 0x1 +/**< @ingroup icp_qat_fw_la + * TRNG Test Result test results valid field mask definition.*/ + +/****************************************************************************** + * @ingroup icp_qat_fw_la + * Definition of the Lookaside TRNG test_status values. + * + * + *****************************************************************************/ +#define QAT_FW_LA_TRNG_TEST_STATUS_TV_VALID 1 +/**< @ingroup icp_qat_fw_la + * TRNG TEST Response Test Results Valid Value.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TV_NOT_VALID 0 +/**< @ingroup icp_qat_fw_la + * TRNG TEST Response Test Results are NOT Valid Value.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TS_NO_FAILS 1 +/**< @ingroup icp_qat_fw_la + * Value for TRNG Test status tests have NO FAILs Value.*/ + +#define QAT_FW_LA_TRNG_TEST_STATUS_TS_HAS_FAILS 0 +/**< @ingroup icp_qat_fw_la + * Value for TRNG Test status tests have one or more FAILS Value.*/ + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_la + * + * @description + * Macro for extraction of the Test Status Field returned in the response + * to TRNG TEST command. + * + * @param test_status 8 bit test_status value to extract the status bit + * + *****************************************************************************/ +#define ICP_QAT_FW_LA_TRNG_TEST_STATUS_TS_FLD_GET(test_status) \ + QAT_FIELD_GET(test_status, \ + QAT_FW_LA_TRNG_TEST_STATUS_TS_BITPOS, \ + QAT_FW_LA_TRNG_TEST_STATUS_TS_MASK) +/** + ****************************************************************************** + * @ingroup icp_qat_fw_la + * + * @description + * Macro for extraction of the Test Results Valid Field returned in the + * response to TRNG TEST command. + * + * @param test_status 8 bit test_status value to extract the Tests + * Results valid bit + * + *****************************************************************************/ +#define ICP_QAT_FW_LA_TRNG_TEST_STATUS_TV_FLD_GET(test_status) \ + QAT_FIELD_GET(test_status, \ + QAT_FW_LA_TRNG_TEST_STATUS_TV_BITPOS, \ + QAT_FW_LA_TRNG_TEST_STATUS_TV_MASK) + +/* + ****************************************************************************** + * MGF Max supported input parameters + ****************************************************************************** + */ +#define ICP_QAT_FW_LA_MGF_SEED_LEN_MAX 255 +/**< @ingroup icp_qat_fw_la + * Maximum seed length for MGF1 request in bytes + * Typical values may be 48, 64, 128 bytes (or any).*/ + +#define ICP_QAT_FW_LA_MGF_MASK_LEN_MAX 65528 +/**< @ingroup icp_qat_fw_la + * Maximum mask length for MGF1 request in bytes + * Typical values may be 8 (64-bit), 16 (128-bit). MUST be quad word multiple */ + +/* + ****************************************************************************** + * SSL Max supported input parameters + ****************************************************************************** + */ +#define ICP_QAT_FW_LA_SSL_SECRET_LEN_MAX 512 +/**< @ingroup icp_qat_fw_la + * Maximum secret length for SSL3 Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_SSL_ITERATES_LEN_MAX 16 +/**< @ingroup icp_qat_fw_la + * Maximum iterations for SSL3 Key Gen request (integer) */ + +#define ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX 136 +/**< @ingroup icp_qat_fw_la + * Maximum label length for SSL3 Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_SSL_SEED_LEN_MAX 64 +/**< @ingroup icp_qat_fw_la + * Maximum seed length for SSL3 Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_SSL_OUTPUT_LEN_MAX 248 +/**< @ingroup icp_qat_fw_la + * Maximum output length for SSL3 Key Gen request (bytes) */ + +/* + ****************************************************************************** + * TLS Max supported input parameters + ****************************************************************************** + */ +#define ICP_QAT_FW_LA_TLS_SECRET_LEN_MAX 128 +/**< @ingroup icp_qat_fw_la + * Maximum secret length for TLS Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX 128 +/**< @ingroup icp_qat_fw_la + * Maximum secret length for TLS Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX 64 +/**< @ingroup icp_qat_fw_la + * Maximum secret length for TLS Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX 255 +/**< @ingroup icp_qat_fw_la + * Maximum label length for TLS Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_TLS_SEED_LEN_MAX 64 +/**< @ingroup icp_qat_fw_la + * Maximum seed length for TLS Key Gen request (bytes) */ + +#define ICP_QAT_FW_LA_TLS_OUTPUT_LEN_MAX 248 +/**< @ingroup icp_qat_fw_la + * Maximum output length for TLS Key Gen request (bytes) */ + +/* + ****************************************************************************** + * HKDF input parameters + ****************************************************************************** + */ + +#define QAT_FW_HKDF_LABEL_BUFFER_SZ 78 +#define QAT_FW_HKDF_LABEL_LEN_SZ 1 +#define QAT_FW_HKDF_LABEL_FLAGS_SZ 1 + +#define QAT_FW_HKDF_LABEL_STRUCT_SZ \ + (QAT_FW_HKDF_LABEL_BUFFER_SZ + QAT_FW_HKDF_LABEL_LEN_SZ + \ + QAT_FW_HKDF_LABEL_FLAGS_SZ) + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_la + * + * @description + * Wraps an RFC 8446 HkdfLabel with metadata for use in HKDF Expand-Label + * operations. + * + *****************************************************************************/ +struct icp_qat_fw_hkdf_label { + uint8_t label[QAT_FW_HKDF_LABEL_BUFFER_SZ]; + /**< Buffer containing an HkdfLabel as specified in RFC 8446 */ + + uint8_t label_length; + /**< The size of the HkdfLabel */ + + union { + uint8_t label_flags; + /**< For first-level labels: each bit in [0..3] will trigger a + * child + * Expand-Label operation on the corresponding sublabel. Bits + * [4..7] + * are reserved. + */ + + uint8_t sublabel_flags; + /**< For sublabels the following flags are defined: + * - QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS + * - QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS + * - QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS + */ + } u; +}; + +#define ICP_QAT_FW_LA_HKDF_SECRET_LEN_MAX 64 +/**< Maximum secret length for HKDF request (bytes) */ + +#define ICP_QAT_FW_LA_HKDF_IKM_LEN_MAX 64 +/**< Maximum IKM length for HKDF request (bytes) */ + +#define QAT_FW_HKDF_MAX_LABELS 4 +/**< Maximum number of label structures allowed in the labels buffer */ + +#define QAT_FW_HKDF_MAX_SUBLABELS 4 +/**< Maximum number of label structures allowed in the sublabels buffer */ + +/* + ****************************************************************************** + * HKDF inner sublabel flags + ****************************************************************************** + */ + +#define QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS 0 +/**< Limit sublabel expand output to 12 bytes -- used with the "iv" sublabel */ + +#define QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS 1 +/**< Limit sublabel expand output to 16 bytes -- used with SHA-256 "key" */ + +#define QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS 2 +/**< Limit sublabel expand output to 32 bytes -- used with SHA-384 "key" */ + +#endif /* _ICP_QAT_FW_LA_H_ */ diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp.h new file mode 100644 index 00000000000..855e83905f5 --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp.h @@ -0,0 +1,5926 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + * @file icp_qat_fw_mmp.h + * @defgroup icp_qat_fw_mmp ICP QAT FW MMP Processing Definitions + * @ingroup icp_qat_fw + * $Revision: 0.1 $ + * @brief + * This file documents the external interfaces that the QAT FW running + * on the QAT Acceleration Engine provides to clients wanting to + * accelerate crypto assymetric applications + */ + +#ifndef __ICP_QAT_FW_MMP__ +#define __ICP_QAT_FW_MMP__ + +/************************************************************************** + * Include local header files + ************************************************************************** + */ + +#include "icp_qat_fw.h" + +/************************************************************************** + * Local constants + ************************************************************************** + */ +#define ICP_QAT_FW_PKE_INPUT_COUNT_MAX 7 +/**< @ingroup icp_qat_fw_pke + * Maximum number of input paramaters in all PKE request */ +#define ICP_QAT_FW_PKE_OUTPUT_COUNT_MAX 5 +/**< @ingroup icp_qat_fw_pke + * Maximum number of output paramaters in all PKE request */ + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Initialisation sequence , + * to be used when icp_qat_fw_pke_request_s::functionalityId is #PKE_INIT. + */ +typedef struct icp_qat_fw_mmp_init_input_s { + uint64_t z; /**< zeroed quadword (1 qwords)*/ +} icp_qat_fw_mmp_init_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 768-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_768. + */ +typedef struct icp_qat_fw_mmp_dh_g2_768_input_s { + uint64_t e; /**< exponent > 0 and < 2^768 (12 qwords)*/ + uint64_t m; /**< modulus ≥ 2^767 and < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_dh_g2_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for 768-bit + * numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_768. + */ +typedef struct icp_qat_fw_mmp_dh_768_input_s { + uint64_t g; /**< base ≥ 0 and < 2^768 (12 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^768 (12 qwords)*/ + uint64_t m; /**< modulus ≥ 2^767 and < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_dh_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 1024-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_1024. + */ +typedef struct icp_qat_fw_mmp_dh_g2_1024_input_s { + uint64_t e; /**< exponent > 0 and < 2^1024 (16 qwords)*/ + uint64_t m; /**< modulus ≥ 2^1023 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_dh_g2_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for + * 1024-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_1024. + */ +typedef struct icp_qat_fw_mmp_dh_1024_input_s { + uint64_t g; /**< base ≥ 0 and < 2^1024 (16 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^1024 (16 qwords)*/ + uint64_t m; /**< modulus ≥ 2^1023 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_dh_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 1536-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_1536. + */ +typedef struct icp_qat_fw_mmp_dh_g2_1536_input_s { + uint64_t e; /**< exponent > 0 and < 2^1536 (24 qwords)*/ + uint64_t m; /**< modulus ≥ 2^1535 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_dh_g2_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for + * 1536-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_1536. + */ +typedef struct icp_qat_fw_mmp_dh_1536_input_s { + uint64_t g; /**< base ≥ 0 and < 2^1536 (24 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^1536 (24 qwords)*/ + uint64_t m; /**< modulus ≥ 2^1535 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_dh_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 2048-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_2048. + */ +typedef struct icp_qat_fw_mmp_dh_g2_2048_input_s { + uint64_t e; /**< exponent > 0 and < 2^2048 (32 qwords)*/ + uint64_t m; /**< modulus ≥ 2^2047 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_dh_g2_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for + * 2048-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_2048. + */ +typedef struct icp_qat_fw_mmp_dh_2048_input_s { + uint64_t g; /**< base ≥ 0 and < 2^2048 (32 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^2048 (32 qwords)*/ + uint64_t m; /**< modulus ≥ 2^2047 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_dh_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 3072-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_3072. + */ +typedef struct icp_qat_fw_mmp_dh_g2_3072_input_s { + uint64_t e; /**< exponent > 0 and < 2^3072 (48 qwords)*/ + uint64_t m; /**< modulus ≥ 2^3071 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_dh_g2_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for + * 3072-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_3072. + */ +typedef struct icp_qat_fw_mmp_dh_3072_input_s { + uint64_t g; /**< base ≥ 0 and < 2^3072 (48 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^3072 (48 qwords)*/ + uint64_t m; /**< modulus ≥ 2^3071 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_dh_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 4096-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_G2_4096. + */ +typedef struct icp_qat_fw_mmp_dh_g2_4096_input_s { + uint64_t e; /**< exponent > 0 and < 2^4096 (64 qwords)*/ + uint64_t m; /**< modulus ≥ 2^4095 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_dh_g2_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Diffie-Hellman Modular exponentiation for + * 4096-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DH_4096. + */ +typedef struct icp_qat_fw_mmp_dh_4096_input_s { + uint64_t g; /**< base ≥ 0 and < 2^4096 (64 qwords)*/ + uint64_t e; /**< exponent > 0 and < 2^4096 (64 qwords)*/ + uint64_t m; /**< modulus ≥ 2^4095 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_dh_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 512 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_512. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_512_input_s { + uint64_t + p; /**< RSA parameter, prime,  2 < p < 2^256 (4 qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2 < q < 2^256 (4 qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (8 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 512 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_512. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_512_input_s { + uint64_t + p; /**< RSA parameter, prime,  2^255 < p < 2^256 (4 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^255 < q < 2^256 (4 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (8 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 512 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_512. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_512_input_s { + uint64_t m; /**< message representative, < n (8 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (8 qwords)*/ + uint64_t n; /**< RSA key, > 0 and < 2^256 (8 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 512 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_512. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_512_input_s { + uint64_t c; /**< cipher text representative, < n (8 qwords)*/ + uint64_t d; /**< RSA private key (RSADP first form) (8 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^256 (8 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_512. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_512_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (8 qwords)*/ + uint64_t + p; /**< RSA parameter, prime,  2^255 < p < 2^256 (4 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^255 < q < 2^256 (4 + qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (4 qwords)*/ + uint64_t dq; /**< RSA private key 0 < dq < q-1 (4 qwords)*/ + uint64_t qinv; /**< RSA private key 0 < qInv < p (4 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_1024_input_s { + uint64_t + p; /**< RSA parameter, prime,  2 < p < 2^512 (8 qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2 < q < 2^512 (8 qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (16 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_1024_input_s { + uint64_t + p; /**< RSA parameter, prime,  2^511 < p < 2^512 (8 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^511 < q < 2^512 (8 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (16 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_1024_input_s { + uint64_t m; /**< message representative, < n (16 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (16 qwords)*/ + uint64_t n; /**< RSA key, > 0 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_1024_input_s { + uint64_t c; /**< cipher text representative, < n (16 qwords)*/ + uint64_t d; /**< RSA private key (RSADP first form) (16 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1024 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_1024_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (16 qwords)*/ + uint64_t + p; /**< RSA parameter, prime,  2^511 < p < 2^512 (8 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^511 < q < 2^512 (8 + qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (8 qwords)*/ + uint64_t dq; /**< RSA private key 0 < dq < q-1 (8 qwords)*/ + uint64_t qinv; /**< RSA private key 0 < qInv < p (8 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1536 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_1536_input_s { + uint64_t p; /**< RSA parameter, prime,  2 < p < 2^768 (12 + qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2 < q < 2^768 (12 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (24 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1536 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_1536_input_s { + uint64_t + p; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^767 < q < 2^768 (12 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (24 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1536 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_1536_input_s { + uint64_t m; /**< message representative, < n (24 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ (p*q)-1 (24 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1536 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_1536_input_s { + uint64_t c; /**< cipher text representative, < n (24 qwords)*/ + uint64_t d; /**< RSA private key (24 qwords)*/ + uint64_t n; /**< RSA key, > 0 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 1536 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_1536_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (24 qwords)*/ + uint64_t + p; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 + qwords)*/ + uint64_t + q; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 + qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (12 qwords)*/ + uint64_t dq; /**< RSA private key, 0 < dq < q-1 (12 qwords)*/ + uint64_t qinv; /**< RSA private key, 0 < qInv < p (12 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 2048 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_2048_input_s { + uint64_t p; /**< RSA parameter, prime,  2 < p < 2^1024 (16 + qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2 < q < 2^1024 (16 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (32 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 2048 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_2048_input_s { + uint64_t p; /**< RSA parameter, prime,  2^1023 < p < 2^1024 + (16 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^1023 < q < 2^1024 + (16 qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (32 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 2048 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_2048_input_s { + uint64_t m; /**< message representative, < n (32 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (32 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 2048 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_2048_input_s { + uint64_t c; /**< cipher text representative, < n (32 qwords)*/ + uint64_t d; /**< RSA private key (32 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 2048 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_2048_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (32 qwords)*/ + uint64_t p; /**< RSA parameter, prime,  2^1023 < p < 2^1024 + (16 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^1023 < q < 2^1024 + (16 qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (16 qwords)*/ + uint64_t dq; /**< RSA private key, 0 < dq < q-1 (16 qwords)*/ + uint64_t qinv; /**< RSA private key, 0 < qInv < p (16 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 3072 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_3072_input_s { + uint64_t p; /**< RSA parameter, prime,  2 < p < 2^1536 (24 + qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2 < q < 2^1536 (24 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (48 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 3072 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_3072_input_s { + uint64_t p; /**< RSA parameter, prime,  2^1535 < p < 2^1536 + (24 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^1535 < q < 2^1536 + (24 qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (48 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 3072 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_3072_input_s { + uint64_t m; /**< message representative, < n (48 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (48 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 3072 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_3072_input_s { + uint64_t c; /**< cipher text representative, < n (48 qwords)*/ + uint64_t d; /**< RSA private key (48 qwords)*/ + uint64_t n; /**< RSA key > 0 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 3072 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_3072_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (48 qwords)*/ + uint64_t p; /**< RSA parameter, prime,  2^1535 < p < 2^1536 + (24 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^1535 < q < 2^1536 + (24 qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (24 qwords)*/ + uint64_t dq; /**< RSA private key, 0 < dq < q-1 (24 qwords)*/ + uint64_t qinv; /**< RSA private key, 0 < qInv < p (24 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 4096 key generation first form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP1_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_4096_input_s { + uint64_t p; /**< RSA parameter, prime,  2 < p < 2^2048 (32 + qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2 < q < 2^2048 (32 + qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (64 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 4096 key generation second form , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_KP2_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_4096_input_s { + uint64_t p; /**< RSA parameter, prime,  2^2047 < p < 2^2048 + (32 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^2047 < q < 2^2048 + (32 qwords)*/ + uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1, +  with GCD(e, p-1, q-1) = 1 (64 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 4096 Encryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_EP_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_4096_input_s { + uint64_t m; /**< message representative, < n (64 qwords)*/ + uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (64 qwords)*/ + uint64_t n; /**< RSA key, > 0 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 4096 Decryption , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP1_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_4096_input_s { + uint64_t c; /**< cipher text representative, < n (64 qwords)*/ + uint64_t d; /**< RSA private key (64 qwords)*/ + uint64_t n; /**< RSA key, > 0 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for RSA 4096 Decryption with CRT , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_RSA_DP2_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_4096_input_s { + uint64_t c; /**< cipher text representative, < (p*q) (64 qwords)*/ + uint64_t p; /**< RSA parameter, prime,  2^2047 < p < 2^2048 + (32 qwords)*/ + uint64_t q; /**< RSA parameter, prime,  2^2047 < q < 2^2048 + (32 qwords)*/ + uint64_t dp; /**< RSA private key, 0 < dp < p-1 (32 qwords)*/ + uint64_t dq; /**< RSA private key, 0 < dq < q-1 (32 qwords)*/ + uint64_t qinv; /**< RSA private key, 0 < qInv < p (32 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 192-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_192. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_192_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^192 (3 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_192_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 256-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_256. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_256_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^256 (4 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 384-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_384. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_384_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^384 (6 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_384_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_512. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_512_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_768. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_768_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_1024. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_1024_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_1536. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_1536_input_s { + uint64_t m; /**< (24 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_2048. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_2048_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_3072. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_3072_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for GCD primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_GCD_PT_4096. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_4096_input_s { + uint64_t m; /**< prime candidate > 1 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_gcd_pt_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 160-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_160. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_160_input_s { + uint64_t m; /**< prime candidate, 2^159 < m < 2^160 (3 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_512. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_512_input_s { + uint64_t m; /**< prime candidate, 2^511 < m < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for <e; 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_L512. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_l512_input_s { + uint64_t m; /**< prime candidate, 5 < m < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_768. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_768_input_s { + uint64_t m; /**< prime candidate, 2^767 < m < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_1024. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_1024_input_s { + uint64_t + m; /**< prime candidate, 2^1023 < m < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_1536. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_1536_input_s { + uint64_t + m; /**< prime candidate, 2^1535 < m < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_2048. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_2048_input_s { + uint64_t + m; /**< prime candidate, 2^2047 < m < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_3072. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_3072_input_s { + uint64_t + m; /**< prime candidate, 2^3071 < m < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Fermat primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_FERMAT_PT_4096. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_4096_input_s { + uint64_t + m; /**< prime candidate, 2^4095 < m < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_fermat_pt_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 160-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_160. + */ +typedef struct icp_qat_fw_mmp_mr_pt_160_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (3 qwords)*/ + uint64_t m; /**< prime candidate > 2^159 and < 2^160 (3 qwords)*/ +} icp_qat_fw_mmp_mr_pt_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_512. + */ +typedef struct icp_qat_fw_mmp_mr_pt_512_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (8 qwords)*/ + uint64_t m; /**< prime candidate > 2^511 and < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_mr_pt_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_768. + */ +typedef struct icp_qat_fw_mmp_mr_pt_768_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (12 qwords)*/ + uint64_t m; /**< prime candidate > 2^767 and < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_mr_pt_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 1024-bit numbers + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_1024. + */ +typedef struct icp_qat_fw_mmp_mr_pt_1024_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (16 qwords)*/ + uint64_t + m; /**< prime candidate > 2^1023 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_mmp_mr_pt_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 1536-bit numbers + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_1536. + */ +typedef struct icp_qat_fw_mmp_mr_pt_1536_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (24 qwords)*/ + uint64_t + m; /**< prime candidate > 2^1535 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_mmp_mr_pt_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 2048-bit numbers + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_2048. + */ +typedef struct icp_qat_fw_mmp_mr_pt_2048_input_s { + uint64_t x; /**< randomness > 1 and <m-1 (32 qwords)*/ + uint64_t + m; /**< prime candidate > 2^2047 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_mmp_mr_pt_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 3072-bit numbers + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_3072. + */ +typedef struct icp_qat_fw_mmp_mr_pt_3072_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (48 qwords)*/ + uint64_t + m; /**< prime candidate > 2^3071 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_mmp_mr_pt_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 4096-bit numbers + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_4096. + */ +typedef struct icp_qat_fw_mmp_mr_pt_4096_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (64 qwords)*/ + uint64_t + m; /**< prime candidate > 2^4095 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_mmp_mr_pt_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Miller-Rabin primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_MR_PT_L512. + */ +typedef struct icp_qat_fw_mmp_mr_pt_l512_input_s { + uint64_t x; /**< randomness > 1 and < m-1 (8 qwords)*/ + uint64_t m; /**< prime candidate > 1 and < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_mr_pt_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 160-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_160. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_160_input_s { + uint64_t + m; /**< odd prime candidate > 2^159 and < 2^160 (3 qwords)*/ +} icp_qat_fw_mmp_lucas_pt_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_512. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_512_input_s { + uint64_t + m; /**< odd prime candidate > 2^511 and < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_lucas_pt_512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_768. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_768_input_s { + uint64_t + m; /**< odd prime candidate > 2^767 and < 2^768 (12 qwords)*/ +} icp_qat_fw_mmp_lucas_pt_768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_1024. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_1024_input_s { + uint64_t m; /**< odd prime candidate > 2^1023 and < 2^1024 (16 + qwords)*/ +} icp_qat_fw_mmp_lucas_pt_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_1536. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_1536_input_s { + uint64_t m; /**< odd prime candidate > 2^1535 and < 2^1536 (24 + qwords)*/ +} icp_qat_fw_mmp_lucas_pt_1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_2048. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_2048_input_s { + uint64_t m; /**< odd prime candidate > 2^2047 and < 2^2048 (32 + qwords)*/ +} icp_qat_fw_mmp_lucas_pt_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_3072. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_3072_input_s { + uint64_t m; /**< odd prime candidate > 2^3071 and < 2^3072 (48 + qwords)*/ +} icp_qat_fw_mmp_lucas_pt_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_4096. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_4096_input_s { + uint64_t m; /**< odd prime candidate > 2^4096 and < 2^4096 (64 + qwords)*/ +} icp_qat_fw_mmp_lucas_pt_4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Lucas primality test for L512-bit numbers , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_LUCAS_PT_L512. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_l512_input_s { + uint64_t m; /**< odd prime candidate > 5 and < 2^512 (8 qwords)*/ +} icp_qat_fw_mmp_lucas_pt_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 512-bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L512. + */ +typedef struct icp_qat_fw_maths_modexp_l512_input_s { + uint64_t g; /**< base ≥ 0 and < 2^512 (8 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^512 (8 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^512 (8 qwords)*/ +} icp_qat_fw_maths_modexp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 1024-bit , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L1024. + */ +typedef struct icp_qat_fw_maths_modexp_l1024_input_s { + uint64_t g; /**< base ≥ 0 and < 2^1024 (16 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^1024 (16 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^1024 (16 qwords)*/ +} icp_qat_fw_maths_modexp_l1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 1536-bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L1536. + */ +typedef struct icp_qat_fw_maths_modexp_l1536_input_s { + uint64_t g; /**< base ≥ 0 and < 2^1536 (24 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^1536 (24 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^1536 (24 qwords)*/ +} icp_qat_fw_maths_modexp_l1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 2048-bit , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L2048. + */ +typedef struct icp_qat_fw_maths_modexp_l2048_input_s { + uint64_t g; /**< base ≥ 0 and < 2^2048 (32 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^2048 (32 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^2048 (32 qwords)*/ +} icp_qat_fw_maths_modexp_l2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 2560-bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L2560. + */ +typedef struct icp_qat_fw_maths_modexp_l2560_input_s { + uint64_t g; /**< base ≥ 0 and < 2^2560 (40 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^2560 (40 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^2560 (40 qwords)*/ +} icp_qat_fw_maths_modexp_l2560_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 3072-bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L3072. + */ +typedef struct icp_qat_fw_maths_modexp_l3072_input_s { + uint64_t g; /**< base ≥ 0 and < 2^3072 (48 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^3072 (48 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^3072 (48 qwords)*/ +} icp_qat_fw_maths_modexp_l3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 3584-bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L3584. + */ +typedef struct icp_qat_fw_maths_modexp_l3584_input_s { + uint64_t g; /**< base ≥ 0 and < 2^3584 (56 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^3584 (56 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^3584 (56 qwords)*/ +} icp_qat_fw_maths_modexp_l3584_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular exponentiation for numbers less than + * 4096-bit , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODEXP_L4096. + */ +typedef struct icp_qat_fw_maths_modexp_l4096_input_s { + uint64_t g; /**< base ≥ 0 and < 2^4096 (64 qwords)*/ + uint64_t e; /**< exponent ≥ 0 and < 2^4096 (64 qwords)*/ + uint64_t m; /**< modulus > 0 and < 2^4096 (64 qwords)*/ +} icp_qat_fw_maths_modexp_l4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 128 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L128. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l128_input_s { + uint64_t a; /**< number > 0 and < 2^128 (2 qwords)*/ + uint64_t + b; /**< odd modulus > 0 and < 2^128, coprime to a (2 qwords)*/ +} icp_qat_fw_maths_modinv_odd_l128_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 192 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L192. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l192_input_s { + uint64_t a; /**< number > 0 and < 2^192 (3 qwords)*/ + uint64_t + b; /**< odd modulus > 0 and < 2^192, coprime to a (3 qwords)*/ +} icp_qat_fw_maths_modinv_odd_l192_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 256 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L256. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l256_input_s { + uint64_t a; /**< number > 0 and < 2^256 (4 qwords)*/ + uint64_t + b; /**< odd modulus > 0 and < 2^256, coprime to a (4 qwords)*/ +} icp_qat_fw_maths_modinv_odd_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 384 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L384. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l384_input_s { + uint64_t a; /**< number > 0 and < 2^384 (6 qwords)*/ + uint64_t + b; /**< odd modulus > 0 and < 2^384, coprime to a (6 qwords)*/ +} icp_qat_fw_maths_modinv_odd_l384_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 512 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L512. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l512_input_s { + uint64_t a; /**< number > 0 and < 2^512 (8 qwords)*/ + uint64_t + b; /**< odd modulus > 0 and < 2^512, coprime to a (8 qwords)*/ +} icp_qat_fw_maths_modinv_odd_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 768 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L768. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l768_input_s { + uint64_t a; /**< number > 0 and < 2^768 (12 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^768 ,coprime to a (12 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 1024 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L1024. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l1024_input_s { + uint64_t a; /**< number > 0 and < 2^1024 (16 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^1024, coprime to a (16 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 1536 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L1536. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l1536_input_s { + uint64_t a; /**< number > 0 and < 2^1536 (24 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^1536, coprime to a (24 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 2048 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L2048. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l2048_input_s { + uint64_t a; /**< number > 0 and < 2^2048 (32 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^2048, coprime to a (32 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 3072 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L3072. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l3072_input_s { + uint64_t a; /**< number > 0 and < 2^3072 (48 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^3072, coprime to a (48 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 4096 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_ODD_L4096. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l4096_input_s { + uint64_t a; /**< number > 0 and < 2^4096 (64 qwords)*/ + uint64_t b; /**< odd modulus > 0 and < 2^4096, coprime to a (64 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 128 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L128. + */ +typedef struct icp_qat_fw_maths_modinv_even_l128_input_s { + uint64_t a; /**< odd number > 0 and < 2^128 (2 qwords)*/ + uint64_t + b; /**< even modulus > 0 and < 2^128, coprime with a (2 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l128_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 192 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L192. + */ +typedef struct icp_qat_fw_maths_modinv_even_l192_input_s { + uint64_t a; /**< odd number > 0 and < 2^192 (3 qwords)*/ + uint64_t + b; /**< even modulus > 0 and < 2^192, coprime with a (3 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l192_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 256 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L256. + */ +typedef struct icp_qat_fw_maths_modinv_even_l256_input_s { + uint64_t a; /**< odd number > 0 and < 2^256 (4 qwords)*/ + uint64_t + b; /**< even modulus > 0 and < 2^256, coprime with a (4 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 384 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L384. + */ +typedef struct icp_qat_fw_maths_modinv_even_l384_input_s { + uint64_t a; /**< odd number > 0 and < 2^384 (6 qwords)*/ + uint64_t + b; /**< even modulus > 0 and < 2^384, coprime with a (6 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l384_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 512 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L512. + */ +typedef struct icp_qat_fw_maths_modinv_even_l512_input_s { + uint64_t a; /**< odd number > 0 and < 2^512 (8 qwords)*/ + uint64_t + b; /**< even modulus > 0 and < 2^512, coprime with a (8 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 768 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L768. + */ +typedef struct icp_qat_fw_maths_modinv_even_l768_input_s { + uint64_t a; /**< odd number > 0 and < 2^768 (12 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^768, coprime with a + (12 qwords)*/ +} icp_qat_fw_maths_modinv_even_l768_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 1024 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L1024. + */ +typedef struct icp_qat_fw_maths_modinv_even_l1024_input_s { + uint64_t a; /**< odd number > 0 and < 2^1024 (16 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^1024, coprime with a + (16 qwords)*/ +} icp_qat_fw_maths_modinv_even_l1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 1536 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L1536. + */ +typedef struct icp_qat_fw_maths_modinv_even_l1536_input_s { + uint64_t a; /**< odd number > 0 and < 2^1536 (24 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^1536, coprime with a + (24 qwords)*/ +} icp_qat_fw_maths_modinv_even_l1536_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 2048 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L2048. + */ +typedef struct icp_qat_fw_maths_modinv_even_l2048_input_s { + uint64_t a; /**< odd number > 0 and < 2^2048 (32 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^2048, coprime with a + (32 qwords)*/ +} icp_qat_fw_maths_modinv_even_l2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 3072 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L3072. + */ +typedef struct icp_qat_fw_maths_modinv_even_l3072_input_s { + uint64_t a; /**< odd number > 0 and < 2^3072 (48 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^3072, coprime with a + (48 qwords)*/ +} icp_qat_fw_maths_modinv_even_l3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for Modular multiplicative inverse for numbers less + * than 4096 bits , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_MODINV_EVEN_L4096. + */ +typedef struct icp_qat_fw_maths_modinv_even_l4096_input_s { + uint64_t a; /**< odd number > 0 and < 2^4096 (64 qwords)*/ + uint64_t b; /**< even modulus > 0 and < 2^4096, coprime with a + (64 qwords)*/ +} icp_qat_fw_maths_modinv_even_l4096_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_P_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s { + uint64_t x; /**< DSA 1024-bit randomness (16 qwords)*/ + uint64_t q; /**< DSA 160-bit parameter (3 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_G_1024. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_1024_input_s { + uint64_t p; /**< DSA 1024-bit parameter (16 qwords)*/ + uint64_t q; /**< DSA 160-bit parameter (3 qwords)*/ + uint64_t h; /**< DSA 1024-bit parameter (16 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_Y_1024. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_1024_input_s { + uint64_t p; /**< DSA 1024-bit parameter (16 qwords)*/ + uint64_t g; /**< DSA parameter (16 qwords)*/ + uint64_t + x; /**< randomly generated DSA parameter (160 bits), (3 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_1024_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s { + uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ + uint64_t p; /**< DSA parameter, (16 qwords)*/ + uint64_t q; /**< DSA parameter (3 qwords)*/ + uint64_t g; /**< DSA parameter (16 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_S_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_160_input_s { + uint64_t m; /**< digest message to be signed (3 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ + uint64_t q; /**< DSA parameter (3 qwords)*/ + uint64_t r; /**< DSA parameter (3 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (3 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_S_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s { + uint64_t m; /**< digest of the message to be signed (3 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ + uint64_t p; /**< DSA parameter (16 qwords)*/ + uint64_t q; /**< DSA parameter (3 qwords)*/ + uint64_t g; /**< DSA parameter (16 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (3 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_VERIFY_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_1024_160_input_s { + uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ + uint64_t s; /**< DSA 160-bits signature (3 qwords)*/ + uint64_t m; /**< digest of the message (3 qwords)*/ + uint64_t p; /**< DSA parameter (16 qwords)*/ + uint64_t q; /**< DSA parameter (3 qwords)*/ + uint64_t g; /**< DSA parameter (16 qwords)*/ + uint64_t y; /**< DSA parameter (16 qwords)*/ +} icp_qat_fw_mmp_dsa_verify_1024_160_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_P_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s { + uint64_t x; /**< DSA 2048-bit randomness (32 qwords)*/ + uint64_t q; /**< DSA 224-bit parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_Y_2048. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_2048_input_s { + uint64_t p; /**< DSA 2048-bit parameter (32 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (224/256 bits), (4 + qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s { + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter, (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_S_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_224_input_s { + uint64_t m; /**< digest message to be signed (4 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t r; /**< DSA parameter (4 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_224_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_S_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s { + uint64_t m; /**< digest of the message to be signed (4 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_VERIFY_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_2048_224_input_s { + uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 224-bits signature (4 qwords)*/ + uint64_t m; /**< digest of the message (4 qwords)*/ + uint64_t p; /**< DSA parameter (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ + uint64_t y; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_verify_2048_224_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_P_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s { + uint64_t x; /**< DSA 2048-bit randomness (32 qwords)*/ + uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_G_2048. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_2048_input_s { + uint64_t p; /**< DSA 2048-bit parameter (32 qwords)*/ + uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ + uint64_t h; /**< DSA 2048-bit parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_2048_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s { + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter, (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_S_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_256_input_s { + uint64_t m; /**< digest message to be signed (4 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t r; /**< DSA parameter (4 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_S_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s { + uint64_t m; /**< digest of the message to be signed (4 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_VERIFY_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_2048_256_input_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t m; /**< digest of the message (4 qwords)*/ + uint64_t p; /**< DSA parameter (32 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (32 qwords)*/ + uint64_t y; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_verify_2048_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_P_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s { + uint64_t x; /**< DSA 3072-bit randomness (48 qwords)*/ + uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_G_3072. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_3072_input_s { + uint64_t p; /**< DSA 3072-bit parameter (48 qwords)*/ + uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ + uint64_t h; /**< DSA 3072-bit parameter (48 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_GEN_Y_3072. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_3072_input_s { + uint64_t p; /**< DSA 3072-bit parameter (48 qwords)*/ + uint64_t g; /**< DSA parameter (48 qwords)*/ + uint64_t + x; /**< randomly generated DSA parameter (3072 bits), (4 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_3072_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s { + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter, (48 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (48 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_SIGN_R_S_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s { + uint64_t m; /**< digest of the message to be signed (4 qwords)*/ + uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ + uint64_t p; /**< DSA parameter (48 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (48 qwords)*/ + uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_DSA_VERIFY_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_3072_256_input_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t m; /**< digest of the message (4 qwords)*/ + uint64_t p; /**< DSA parameter (48 qwords)*/ + uint64_t q; /**< DSA parameter (4 qwords)*/ + uint64_t g; /**< DSA parameter (48 qwords)*/ + uint64_t y; /**< DSA parameter (48 qwords)*/ +} icp_qat_fw_mmp_dsa_verify_3072_256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA Sign RS for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_s { + uint64_t in; /**< concatenated input parameters (G, n, q, a, b, k, e, d) + (36 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA Sign R for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s { + uint64_t + xg; /**< x coordinate of base point G of B/K-163 of B/K-233 (4 + qwords)*/ + uint64_t + yg; /**< y coordinate of base point G of B/K-163 or B/K-233 (4 + qwords)*/ + uint64_t + n; /**< order of the base point of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t q; /**< field polynomial of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t + a; /**< a equation coefficient of B/K-163 of B/K-233 (4 qwords)*/ + uint64_t + b; /**< b equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t k; /**< random value > 0 and < n (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA Sign S for curves with n < 2^256 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s { + uint64_t e; /**< hash of message (0 < e < 2^256) (4 qwords)*/ + uint64_t d; /**< private key (>0 and < n) (4 qwords)*/ + uint64_t + r; /**< ECDSA r signature value (>0 and < n) (4 qwords)*/ + uint64_t k; /**< random value > 0 and < n (4 qwords)*/ + uint64_t n; /**< order of the base point G (2 < n < 2^256) (4 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA Verify for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_s { + uint64_t + in; /**< concatenated curve parameter (e,s,r,n,G,Q,a,b,q) (44 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA Sign RS , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_s { + uint64_t in; /**< concatenated input parameters (G, n, q, a, b, k, e, d) + (72 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s { + uint64_t xg; /**< x coordinate of verified base point (> 0 and + degree(x(G)) < degree(q)) (8 qwords)*/ + uint64_t yg; /**< y coordinate of verified base point (> 0 and + degree(y(G)) < degree(q)) (8 qwords)*/ + uint64_t n; /**< order of the base point G, which must be prime and a + divisor of #E and < 2^512) (8 qwords)*/ + uint64_t + q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ + uint64_t a; /**< a equation coefficient (degree(a) < degree(q)) (8 + qwords)*/ + uint64_t b; /**< b equation coefficient (degree(b) < degree(q)) (8 + qwords)*/ + uint64_t k; /**< random value > 0 and < n (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s { + uint64_t e; /**< hash of message (0 < e < 2^512) (8 qwords)*/ + uint64_t d; /**< private key (>0 and < n) (8 qwords)*/ + uint64_t + r; /**< ECDSA r signature value (>0 and < n) (8 qwords)*/ + uint64_t k; /**< random value > 0 and < n (8 qwords)*/ + uint64_t n; /**< order of the base point G, which must be prime and a + divisor of #E and < 2^512) (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_s { + uint64_t + in; /**< concatenated curve parameters (e, s, r, n, xG, yG, xQ, yQ, + a, b, q) (88 qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Sign RS for curves B-571/K-571 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_s { + uint64_t + in; /**< concatenated input parameters (x(G), y(G), n, q, a, b, k, + e, d) (81 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Sign S for curves with deg(q) < 576 + * , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s { + uint64_t e; /**< hash of message < 2^576 (9 qwords)*/ + uint64_t d; /**< private key (> 0 and < n) (9 qwords)*/ + uint64_t + r; /**< ECDSA r signature value (> 0 and < n) (9 qwords)*/ + uint64_t k; /**< random value (> 0 and < n) (9 qwords)*/ + uint64_t + n; /**< order of the base point of the curve (n < 2^576) (9 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Sign R for degree 571 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s { + uint64_t xg; /**< x coordinate of verified base point belonging to + B/K-571 (9 qwords)*/ + uint64_t yg; /**< y coordinate of verified base point belonging to + B/K-571 (9 qwords)*/ + uint64_t n; /**< order of the base point G (9 qwords)*/ + uint64_t q; /**< irreducible field polynomial of B/K-571 (9 qwords)*/ + uint64_t a; /**< a coefficient of curve B/K-571 (degree(a) < + degree(q)) (9 qwords)*/ + uint64_t b; /**< b coefficient of curve B/K-571 (degree(b) < + degree(q)) (9 qwords)*/ + uint64_t k; /**< random value > 0 and < n (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GF2 Verify for degree 571 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_s { + uint64_t in; /**< concatenated input (e, s, r, n, G, Q, a, b, q) (99 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for MATHS GF2 Point Multiplication , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_L256. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_l256_input_s { + uint64_t k; /**< scalar multiplier > 0 and < 2^256 (4 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (degree(xG) < 256) (4 + qwords)*/ + uint64_t yg; /**< y coordinate of curve point (degree(yG) < 256) (4 + qwords)*/ + uint64_t + a; /**< a equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t + b; /**< b equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t q; /**< field polynomial of B/K-163 or B/K-233 (4 qwords)*/ + uint64_t h; /**< cofactor of B/K-163 or B/K-233 (4 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for MATHS GF2 Point Verification , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_L256. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_l256_input_s { + uint64_t xq; /**< x coordinate of input point (4 qwords)*/ + uint64_t yq; /**< y coordinate of input point (4 qwords)*/ + uint64_t + q; /**< field polynomial of curve, degree(q) < 256 (4 qwords)*/ + uint64_t + a; /**< a equation coefficient of curve, degree(a) < 256 (4 + qwords)*/ + uint64_t + b; /**< b equation coefficient of curve, degree(b) < 256 (4 + qwords)*/ +} icp_qat_fw_maths_point_verify_gf2_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for MATHS GF2 Point Multiplication , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_L512. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_l512_input_s { + uint64_t k; /**< scalar multiplier > 0 and < 2^512 (8 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (degree(xG) < 512) (8 + qwords)*/ + uint64_t yg; /**< y coordinate of curve point (degree(yG) < 512) (8 + qwords)*/ + uint64_t + a; /**< a equation coefficient (degree(a) < 512) (8 qwords)*/ + uint64_t + b; /**< b equation coefficient (degree(b) < 512) (8 qwords)*/ + uint64_t + q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ + uint64_t h; /**< cofactor (< 2^512) (8 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for MATHS GF2 Point Verification , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_L512. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_l512_input_s { + uint64_t xq; /**< x coordinate of input point (8 qwords)*/ + uint64_t yq; /**< y coordinate of input point (8 qwords)*/ + uint64_t + q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ + uint64_t + a; /**< a equation coefficient (degree(a) < 512) (8 qwords)*/ + uint64_t + b; /**< b equation coefficient (degree(a) < 512) (8 qwords)*/ +} icp_qat_fw_maths_point_verify_gf2_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GF2 Point Multiplication for curves + * B-571/K-571 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_571. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_571_input_s { + uint64_t k; /**< scalar value > 0 and < 2^576 (9 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (degree(xG) < + degree(q)) (9 qwords)*/ + uint64_t yg; /**< y coordinate of curve point (degree(xG) < + degree(q)) (9 qwords)*/ + uint64_t a; /**< a equation coefficient for B/K-571 (9 qwords)*/ + uint64_t b; /**< b equation coefficient for B/K-571 (9 qwords)*/ + uint64_t q; /**< field polynomial of B/K-571 (9 qwords)*/ + uint64_t h; /**< cofactor for B/K-571 (1 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GF2 Point Verification for degree 571 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_571. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_571_input_s { + uint64_t xq; /**< x coordinate of candidate public key (9 qwords)*/ + uint64_t yq; /**< y coordinate of candidate public key (9 qwords)*/ + uint64_t q; /**< field polynomial of B/K-571 (9 qwords)*/ + uint64_t a; /**< a equation coefficient of B/K-571 (9 qwords)*/ + uint64_t b; /**< b equation coefficient of B/K-571 (9 qwords)*/ +} icp_qat_fw_maths_point_verify_gf2_571_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s { + uint64_t xg; /**< x coordinate of base point G, (4 qwords)*/ + uint64_t yg; /**< y coordinate of base point G, (4 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (4 + qwords)*/ + uint64_t q; /**< modulus (4 qwords)*/ + uint64_t a; /**< a equation coefficient (4 qwords)*/ + uint64_t b; /**< b equation coefficient (4 qwords)*/ + uint64_t k; /**< random value (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s { + uint64_t e; /**< digest of the message to be signed (4 qwords)*/ + uint64_t d; /**< private key (4 qwords)*/ + uint64_t r; /**< DSA r signature value (4 qwords)*/ + uint64_t k; /**< random value (4 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (4 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_s { + uint64_t + in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (36 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_s { + uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b ,q} + concatenated (44 qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s { + uint64_t xg; /**< x coordinate of base point G, (8 qwords)*/ + uint64_t yg; /**< y coordinate of base point G, (8 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (8 + qwords)*/ + uint64_t q; /**< modulus (8 qwords)*/ + uint64_t a; /**< a equation coefficient (8 qwords)*/ + uint64_t b; /**< b equation coefficient (8 qwords)*/ + uint64_t k; /**< random value (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s { + uint64_t e; /**< digest of the message to be signed (8 qwords)*/ + uint64_t d; /**< private key (8 qwords)*/ + uint64_t r; /**< DSA r signature value (8 qwords)*/ + uint64_t k; /**< random value (8 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (8 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_s { + uint64_t + in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (72 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_s { + uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b ,q} + concatenated (88 qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s { + uint64_t xg; /**< x coordinate of base point G, (9 qwords)*/ + uint64_t yg; /**< y coordinate of base point G, (9 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (9 + qwords)*/ + uint64_t q; /**< modulus (9 qwords)*/ + uint64_t a; /**< a equation coefficient (9 qwords)*/ + uint64_t b; /**< b equation coefficient (9 qwords)*/ + uint64_t k; /**< random value (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s { + uint64_t e; /**< digest of the message to be signed (9 qwords)*/ + uint64_t d; /**< private key (9 qwords)*/ + uint64_t r; /**< DSA r signature value (9 qwords)*/ + uint64_t k; /**< random value (9 qwords)*/ + uint64_t n; /**< order of the base point G, which shall be prime (9 + qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_s { + uint64_t + in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (81 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_s { + uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b ,q} + concatenated (99 qwords)*/ +} icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_L256. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_l256_input_s { + uint64_t k; /**< scalar multiplier (4 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (4 qwords)*/ + uint64_t yg; /**< y coordinate of curve point (4 qwords)*/ + uint64_t a; /**< a equation coefficient (4 qwords)*/ + uint64_t b; /**< b equation coefficient (4 qwords)*/ + uint64_t q; /**< modulus (4 qwords)*/ + uint64_t h; /**< cofactor (4 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Partial Point Verification , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_L256. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_l256_input_s { + uint64_t xq; /**< x coordinate of candidate point (4 qwords)*/ + uint64_t yq; /**< y coordinate of candidate point (4 qwords)*/ + uint64_t q; /**< modulus (4 qwords)*/ + uint64_t a; /**< a equation coefficient (4 qwords)*/ + uint64_t b; /**< b equation coefficient (4 qwords)*/ +} icp_qat_fw_maths_point_verify_gfp_l256_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_L512. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_l512_input_s { + uint64_t k; /**< scalar multiplier (8 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (8 qwords)*/ + uint64_t yg; /**< y coordinate of curve point (8 qwords)*/ + uint64_t a; /**< a equation coefficient (8 qwords)*/ + uint64_t b; /**< b equation coefficient (8 qwords)*/ + uint64_t q; /**< modulus (8 qwords)*/ + uint64_t h; /**< cofactor (8 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Partial Point , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_L512. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_l512_input_s { + uint64_t xq; /**< x coordinate of candidate point (8 qwords)*/ + uint64_t yq; /**< y coordinate of candidate point (8 qwords)*/ + uint64_t q; /**< modulus (8 qwords)*/ + uint64_t a; /**< a equation coefficient (8 qwords)*/ + uint64_t b; /**< b equation coefficient (8 qwords)*/ +} icp_qat_fw_maths_point_verify_gfp_l512_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_521. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_521_input_s { + uint64_t k; /**< scalar multiplier (9 qwords)*/ + uint64_t xg; /**< x coordinate of curve point (9 qwords)*/ + uint64_t yg; /**< y coordinate of curve point (9 qwords)*/ + uint64_t a; /**< a equation coefficient (9 qwords)*/ + uint64_t b; /**< b equation coefficient (9 qwords)*/ + uint64_t q; /**< modulus (9 qwords)*/ + uint64_t h; /**< cofactor (1 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC GFP Partial Point Verification , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_521. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_521_input_s { + uint64_t xq; /**< x coordinate of candidate point (9 qwords)*/ + uint64_t yq; /**< y coordinate of candidate point (9 qwords)*/ + uint64_t q; /**< modulus (9 qwords)*/ + uint64_t a; /**< a equation coefficient (9 qwords)*/ + uint64_t b; /**< b equation coefficient (9 qwords)*/ +} icp_qat_fw_maths_point_verify_gfp_521_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC curve25519 Variable Point Multiplication + * [k]P(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #POINT_MULTIPLICATION_C25519. + */ +typedef struct icp_qat_fw_point_multiplication_c25519_input_s { + uint64_t xp; /**< xP = Montgomery affine coordinate X of point P (4 + qwords)*/ + uint64_t k; /**< k = scalar (4 qwords)*/ +} icp_qat_fw_point_multiplication_c25519_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC curve25519 Generator Point Multiplication + * [k]G(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #GENERATOR_MULTIPLICATION_C25519. + */ +typedef struct icp_qat_fw_generator_multiplication_c25519_input_s { + uint64_t k; /**< k = scalar (4 qwords)*/ +} icp_qat_fw_generator_multiplication_c25519_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC edwards25519 Variable Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #POINT_MULTIPLICATION_ED25519. + */ +typedef struct icp_qat_fw_point_multiplication_ed25519_input_s { + uint64_t xp; /**< xP = Twisted Edwards affine coordinate X of point P + (4 qwords)*/ + uint64_t yp; /**< yP = Twisted Edwards affine coordinate Y of point P + (4 qwords)*/ + uint64_t k; /**< k = scalar (4 qwords)*/ +} icp_qat_fw_point_multiplication_ed25519_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC edwards25519 Generator Point Multiplication + * [k]G, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #GENERATOR_MULTIPLICATION_ED25519. + */ +typedef struct icp_qat_fw_generator_multiplication_ed25519_input_s { + uint64_t k; /**< k = scalar (4 qwords)*/ +} icp_qat_fw_generator_multiplication_ed25519_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC curve448 Variable Point Multiplication + * [k]P(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #POINT_MULTIPLICATION_C448. + */ +typedef struct icp_qat_fw_point_multiplication_c448_input_s { + uint64_t xp; /**< xP = Montgomery affine coordinate X of point P (8 + qwords)*/ + uint64_t k; /**< k = scalar (8 qwords)*/ +} icp_qat_fw_point_multiplication_c448_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC curve448 Generator Point Multiplication + * [k]G(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #GENERATOR_MULTIPLICATION_C448. + */ +typedef struct icp_qat_fw_generator_multiplication_c448_input_s { + uint64_t k; /**< k = scalar (8 qwords)*/ +} icp_qat_fw_generator_multiplication_c448_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC edwards448 Variable Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #POINT_MULTIPLICATION_ED448. + */ +typedef struct icp_qat_fw_point_multiplication_ed448_input_s { + uint64_t + xp; /**< xP = Edwards affine coordinate X of point P (8 qwords)*/ + uint64_t + yp; /**< yP = Edwards affine coordinate Y of point P (8 qwords)*/ + uint64_t k; /**< k = scalar (8 qwords)*/ +} icp_qat_fw_point_multiplication_ed448_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Input parameter list for ECC edwards448 Generator Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_request_s::functionalityId is + * #GENERATOR_MULTIPLICATION_ED448. + */ +typedef struct icp_qat_fw_generator_multiplication_ed448_input_s { + uint64_t k; /**< k = scalar (8 qwords)*/ +} icp_qat_fw_generator_multiplication_ed448_input_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * MMP input parameters + */ +typedef union icp_qat_fw_mmp_input_param_u { + /** Generic parameter structure : All members of this wrapper structure + * are pointers to large integers. + */ + uint64_t flat_array[ICP_QAT_FW_PKE_INPUT_COUNT_MAX]; + + /** Initialisation sequence */ + icp_qat_fw_mmp_init_input_t mmp_init; + + /** Diffie-Hellman Modular exponentiation base 2 for 768-bit numbers */ + icp_qat_fw_mmp_dh_g2_768_input_t mmp_dh_g2_768; + + /** Diffie-Hellman Modular exponentiation for 768-bit numbers */ + icp_qat_fw_mmp_dh_768_input_t mmp_dh_768; + + /** Diffie-Hellman Modular exponentiation base 2 for 1024-bit numbers */ + icp_qat_fw_mmp_dh_g2_1024_input_t mmp_dh_g2_1024; + + /** Diffie-Hellman Modular exponentiation for 1024-bit numbers */ + icp_qat_fw_mmp_dh_1024_input_t mmp_dh_1024; + + /** Diffie-Hellman Modular exponentiation base 2 for 1536-bit numbers */ + icp_qat_fw_mmp_dh_g2_1536_input_t mmp_dh_g2_1536; + + /** Diffie-Hellman Modular exponentiation for 1536-bit numbers */ + icp_qat_fw_mmp_dh_1536_input_t mmp_dh_1536; + + /** Diffie-Hellman Modular exponentiation base 2 for 2048-bit numbers */ + icp_qat_fw_mmp_dh_g2_2048_input_t mmp_dh_g2_2048; + + /** Diffie-Hellman Modular exponentiation for 2048-bit numbers */ + icp_qat_fw_mmp_dh_2048_input_t mmp_dh_2048; + + /** Diffie-Hellman Modular exponentiation base 2 for 3072-bit numbers */ + icp_qat_fw_mmp_dh_g2_3072_input_t mmp_dh_g2_3072; + + /** Diffie-Hellman Modular exponentiation for 3072-bit numbers */ + icp_qat_fw_mmp_dh_3072_input_t mmp_dh_3072; + + /** Diffie-Hellman Modular exponentiation base 2 for 4096-bit numbers */ + icp_qat_fw_mmp_dh_g2_4096_input_t mmp_dh_g2_4096; + + /** Diffie-Hellman Modular exponentiation for 4096-bit numbers */ + icp_qat_fw_mmp_dh_4096_input_t mmp_dh_4096; + + /** RSA 512 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_512_input_t mmp_rsa_kp1_512; + + /** RSA 512 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_512_input_t mmp_rsa_kp2_512; + + /** RSA 512 Encryption */ + icp_qat_fw_mmp_rsa_ep_512_input_t mmp_rsa_ep_512; + + /** RSA 512 Decryption */ + icp_qat_fw_mmp_rsa_dp1_512_input_t mmp_rsa_dp1_512; + + /** RSA 1024 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_512_input_t mmp_rsa_dp2_512; + + /** RSA 1024 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_1024_input_t mmp_rsa_kp1_1024; + + /** RSA 1024 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_1024_input_t mmp_rsa_kp2_1024; + + /** RSA 1024 Encryption */ + icp_qat_fw_mmp_rsa_ep_1024_input_t mmp_rsa_ep_1024; + + /** RSA 1024 Decryption */ + icp_qat_fw_mmp_rsa_dp1_1024_input_t mmp_rsa_dp1_1024; + + /** RSA 1024 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_1024_input_t mmp_rsa_dp2_1024; + + /** RSA 1536 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_1536_input_t mmp_rsa_kp1_1536; + + /** RSA 1536 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_1536_input_t mmp_rsa_kp2_1536; + + /** RSA 1536 Encryption */ + icp_qat_fw_mmp_rsa_ep_1536_input_t mmp_rsa_ep_1536; + + /** RSA 1536 Decryption */ + icp_qat_fw_mmp_rsa_dp1_1536_input_t mmp_rsa_dp1_1536; + + /** RSA 1536 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_1536_input_t mmp_rsa_dp2_1536; + + /** RSA 2048 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_2048_input_t mmp_rsa_kp1_2048; + + /** RSA 2048 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_2048_input_t mmp_rsa_kp2_2048; + + /** RSA 2048 Encryption */ + icp_qat_fw_mmp_rsa_ep_2048_input_t mmp_rsa_ep_2048; + + /** RSA 2048 Decryption */ + icp_qat_fw_mmp_rsa_dp1_2048_input_t mmp_rsa_dp1_2048; + + /** RSA 2048 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_2048_input_t mmp_rsa_dp2_2048; + + /** RSA 3072 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_3072_input_t mmp_rsa_kp1_3072; + + /** RSA 3072 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_3072_input_t mmp_rsa_kp2_3072; + + /** RSA 3072 Encryption */ + icp_qat_fw_mmp_rsa_ep_3072_input_t mmp_rsa_ep_3072; + + /** RSA 3072 Decryption */ + icp_qat_fw_mmp_rsa_dp1_3072_input_t mmp_rsa_dp1_3072; + + /** RSA 3072 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_3072_input_t mmp_rsa_dp2_3072; + + /** RSA 4096 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_4096_input_t mmp_rsa_kp1_4096; + + /** RSA 4096 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_4096_input_t mmp_rsa_kp2_4096; + + /** RSA 4096 Encryption */ + icp_qat_fw_mmp_rsa_ep_4096_input_t mmp_rsa_ep_4096; + + /** RSA 4096 Decryption */ + icp_qat_fw_mmp_rsa_dp1_4096_input_t mmp_rsa_dp1_4096; + + /** RSA 4096 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_4096_input_t mmp_rsa_dp2_4096; + + /** GCD primality test for 192-bit numbers */ + icp_qat_fw_mmp_gcd_pt_192_input_t mmp_gcd_pt_192; + + /** GCD primality test for 256-bit numbers */ + icp_qat_fw_mmp_gcd_pt_256_input_t mmp_gcd_pt_256; + + /** GCD primality test for 384-bit numbers */ + icp_qat_fw_mmp_gcd_pt_384_input_t mmp_gcd_pt_384; + + /** GCD primality test for 512-bit numbers */ + icp_qat_fw_mmp_gcd_pt_512_input_t mmp_gcd_pt_512; + + /** GCD primality test for 768-bit numbers */ + icp_qat_fw_mmp_gcd_pt_768_input_t mmp_gcd_pt_768; + + /** GCD primality test for 1024-bit numbers */ + icp_qat_fw_mmp_gcd_pt_1024_input_t mmp_gcd_pt_1024; + + /** GCD primality test for 1536-bit numbers */ + icp_qat_fw_mmp_gcd_pt_1536_input_t mmp_gcd_pt_1536; + + /** GCD primality test for 2048-bit numbers */ + icp_qat_fw_mmp_gcd_pt_2048_input_t mmp_gcd_pt_2048; + + /** GCD primality test for 3072-bit numbers */ + icp_qat_fw_mmp_gcd_pt_3072_input_t mmp_gcd_pt_3072; + + /** GCD primality test for 4096-bit numbers */ + icp_qat_fw_mmp_gcd_pt_4096_input_t mmp_gcd_pt_4096; + + /** Fermat primality test for 160-bit numbers */ + icp_qat_fw_mmp_fermat_pt_160_input_t mmp_fermat_pt_160; + + /** Fermat primality test for 512-bit numbers */ + icp_qat_fw_mmp_fermat_pt_512_input_t mmp_fermat_pt_512; + + /** Fermat primality test for <e; 512-bit numbers */ + icp_qat_fw_mmp_fermat_pt_l512_input_t mmp_fermat_pt_l512; + + /** Fermat primality test for 768-bit numbers */ + icp_qat_fw_mmp_fermat_pt_768_input_t mmp_fermat_pt_768; + + /** Fermat primality test for 1024-bit numbers */ + icp_qat_fw_mmp_fermat_pt_1024_input_t mmp_fermat_pt_1024; + + /** Fermat primality test for 1536-bit numbers */ + icp_qat_fw_mmp_fermat_pt_1536_input_t mmp_fermat_pt_1536; + + /** Fermat primality test for 2048-bit numbers */ + icp_qat_fw_mmp_fermat_pt_2048_input_t mmp_fermat_pt_2048; + + /** Fermat primality test for 3072-bit numbers */ + icp_qat_fw_mmp_fermat_pt_3072_input_t mmp_fermat_pt_3072; + + /** Fermat primality test for 4096-bit numbers */ + icp_qat_fw_mmp_fermat_pt_4096_input_t mmp_fermat_pt_4096; + + /** Miller-Rabin primality test for 160-bit numbers */ + icp_qat_fw_mmp_mr_pt_160_input_t mmp_mr_pt_160; + + /** Miller-Rabin primality test for 512-bit numbers */ + icp_qat_fw_mmp_mr_pt_512_input_t mmp_mr_pt_512; + + /** Miller-Rabin primality test for 768-bit numbers */ + icp_qat_fw_mmp_mr_pt_768_input_t mmp_mr_pt_768; + + /** Miller-Rabin primality test for 1024-bit numbers */ + icp_qat_fw_mmp_mr_pt_1024_input_t mmp_mr_pt_1024; + + /** Miller-Rabin primality test for 1536-bit numbers */ + icp_qat_fw_mmp_mr_pt_1536_input_t mmp_mr_pt_1536; + + /** Miller-Rabin primality test for 2048-bit numbers */ + icp_qat_fw_mmp_mr_pt_2048_input_t mmp_mr_pt_2048; + + /** Miller-Rabin primality test for 3072-bit numbers */ + icp_qat_fw_mmp_mr_pt_3072_input_t mmp_mr_pt_3072; + + /** Miller-Rabin primality test for 4096-bit numbers */ + icp_qat_fw_mmp_mr_pt_4096_input_t mmp_mr_pt_4096; + + /** Miller-Rabin primality test for 512-bit numbers */ + icp_qat_fw_mmp_mr_pt_l512_input_t mmp_mr_pt_l512; + + /** Lucas primality test for 160-bit numbers */ + icp_qat_fw_mmp_lucas_pt_160_input_t mmp_lucas_pt_160; + + /** Lucas primality test for 512-bit numbers */ + icp_qat_fw_mmp_lucas_pt_512_input_t mmp_lucas_pt_512; + + /** Lucas primality test for 768-bit numbers */ + icp_qat_fw_mmp_lucas_pt_768_input_t mmp_lucas_pt_768; + + /** Lucas primality test for 1024-bit numbers */ + icp_qat_fw_mmp_lucas_pt_1024_input_t mmp_lucas_pt_1024; + + /** Lucas primality test for 1536-bit numbers */ + icp_qat_fw_mmp_lucas_pt_1536_input_t mmp_lucas_pt_1536; + + /** Lucas primality test for 2048-bit numbers */ + icp_qat_fw_mmp_lucas_pt_2048_input_t mmp_lucas_pt_2048; + + /** Lucas primality test for 3072-bit numbers */ + icp_qat_fw_mmp_lucas_pt_3072_input_t mmp_lucas_pt_3072; + + /** Lucas primality test for 4096-bit numbers */ + icp_qat_fw_mmp_lucas_pt_4096_input_t mmp_lucas_pt_4096; + + /** Lucas primality test for L512-bit numbers */ + icp_qat_fw_mmp_lucas_pt_l512_input_t mmp_lucas_pt_l512; + + /** Modular exponentiation for numbers less than 512-bits */ + icp_qat_fw_maths_modexp_l512_input_t maths_modexp_l512; + + /** Modular exponentiation for numbers less than 1024-bit */ + icp_qat_fw_maths_modexp_l1024_input_t maths_modexp_l1024; + + /** Modular exponentiation for numbers less than 1536-bits */ + icp_qat_fw_maths_modexp_l1536_input_t maths_modexp_l1536; + + /** Modular exponentiation for numbers less than 2048-bit */ + icp_qat_fw_maths_modexp_l2048_input_t maths_modexp_l2048; + + /** Modular exponentiation for numbers less than 2560-bits */ + icp_qat_fw_maths_modexp_l2560_input_t maths_modexp_l2560; + + /** Modular exponentiation for numbers less than 3072-bits */ + icp_qat_fw_maths_modexp_l3072_input_t maths_modexp_l3072; + + /** Modular exponentiation for numbers less than 3584-bits */ + icp_qat_fw_maths_modexp_l3584_input_t maths_modexp_l3584; + + /** Modular exponentiation for numbers less than 4096-bit */ + icp_qat_fw_maths_modexp_l4096_input_t maths_modexp_l4096; + + /** Modular multiplicative inverse for numbers less than 128 bits */ + icp_qat_fw_maths_modinv_odd_l128_input_t maths_modinv_odd_l128; + + /** Modular multiplicative inverse for numbers less than 192 bits */ + icp_qat_fw_maths_modinv_odd_l192_input_t maths_modinv_odd_l192; + + /** Modular multiplicative inverse for numbers less than 256 bits */ + icp_qat_fw_maths_modinv_odd_l256_input_t maths_modinv_odd_l256; + + /** Modular multiplicative inverse for numbers less than 384 bits */ + icp_qat_fw_maths_modinv_odd_l384_input_t maths_modinv_odd_l384; + + /** Modular multiplicative inverse for numbers less than 512 bits */ + icp_qat_fw_maths_modinv_odd_l512_input_t maths_modinv_odd_l512; + + /** Modular multiplicative inverse for numbers less than 768 bits */ + icp_qat_fw_maths_modinv_odd_l768_input_t maths_modinv_odd_l768; + + /** Modular multiplicative inverse for numbers less than 1024 bits */ + icp_qat_fw_maths_modinv_odd_l1024_input_t maths_modinv_odd_l1024; + + /** Modular multiplicative inverse for numbers less than 1536 bits */ + icp_qat_fw_maths_modinv_odd_l1536_input_t maths_modinv_odd_l1536; + + /** Modular multiplicative inverse for numbers less than 2048 bits */ + icp_qat_fw_maths_modinv_odd_l2048_input_t maths_modinv_odd_l2048; + + /** Modular multiplicative inverse for numbers less than 3072 bits */ + icp_qat_fw_maths_modinv_odd_l3072_input_t maths_modinv_odd_l3072; + + /** Modular multiplicative inverse for numbers less than 4096 bits */ + icp_qat_fw_maths_modinv_odd_l4096_input_t maths_modinv_odd_l4096; + + /** Modular multiplicative inverse for numbers less than 128 bits */ + icp_qat_fw_maths_modinv_even_l128_input_t maths_modinv_even_l128; + + /** Modular multiplicative inverse for numbers less than 192 bits */ + icp_qat_fw_maths_modinv_even_l192_input_t maths_modinv_even_l192; + + /** Modular multiplicative inverse for numbers less than 256 bits */ + icp_qat_fw_maths_modinv_even_l256_input_t maths_modinv_even_l256; + + /** Modular multiplicative inverse for numbers less than 384 bits */ + icp_qat_fw_maths_modinv_even_l384_input_t maths_modinv_even_l384; + + /** Modular multiplicative inverse for numbers less than 512 bits */ + icp_qat_fw_maths_modinv_even_l512_input_t maths_modinv_even_l512; + + /** Modular multiplicative inverse for numbers less than 768 bits */ + icp_qat_fw_maths_modinv_even_l768_input_t maths_modinv_even_l768; + + /** Modular multiplicative inverse for numbers less than 1024 bits */ + icp_qat_fw_maths_modinv_even_l1024_input_t maths_modinv_even_l1024; + + /** Modular multiplicative inverse for numbers less than 1536 bits */ + icp_qat_fw_maths_modinv_even_l1536_input_t maths_modinv_even_l1536; + + /** Modular multiplicative inverse for numbers less than 2048 bits */ + icp_qat_fw_maths_modinv_even_l2048_input_t maths_modinv_even_l2048; + + /** Modular multiplicative inverse for numbers less than 3072 bits */ + icp_qat_fw_maths_modinv_even_l3072_input_t maths_modinv_even_l3072; + + /** Modular multiplicative inverse for numbers less than 4096 bits */ + icp_qat_fw_maths_modinv_even_l4096_input_t maths_modinv_even_l4096; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t mmp_dsa_gen_p_1024_160; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_1024_input_t mmp_dsa_gen_g_1024; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_1024_input_t mmp_dsa_gen_y_1024; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t mmp_dsa_sign_r_1024_160; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_160_input_t mmp_dsa_sign_s_160; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t mmp_dsa_sign_r_s_1024_160; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_1024_160_input_t mmp_dsa_verify_1024_160; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t mmp_dsa_gen_p_2048_224; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_2048_input_t mmp_dsa_gen_y_2048; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t mmp_dsa_sign_r_2048_224; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_224_input_t mmp_dsa_sign_s_224; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t mmp_dsa_sign_r_s_2048_224; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_2048_224_input_t mmp_dsa_verify_2048_224; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t mmp_dsa_gen_p_2048_256; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_2048_input_t mmp_dsa_gen_g_2048; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t mmp_dsa_sign_r_2048_256; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_256_input_t mmp_dsa_sign_s_256; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t mmp_dsa_sign_r_s_2048_256; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_2048_256_input_t mmp_dsa_verify_2048_256; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t mmp_dsa_gen_p_3072_256; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_3072_input_t mmp_dsa_gen_g_3072; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_3072_input_t mmp_dsa_gen_y_3072; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t mmp_dsa_sign_r_3072_256; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t mmp_dsa_sign_r_s_3072_256; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_3072_256_input_t mmp_dsa_verify_3072_256; + + /** ECDSA Sign RS for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_t + mmp_ecdsa_sign_rs_gf2_l256; + + /** ECDSA Sign R for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_t mmp_ecdsa_sign_r_gf2_l256; + + /** ECDSA Sign S for curves with n < 2^256 */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_t mmp_ecdsa_sign_s_gf2_l256; + + /** ECDSA Verify for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_t mmp_ecdsa_verify_gf2_l256; + + /** ECDSA Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_t + mmp_ecdsa_sign_rs_gf2_l512; + + /** ECDSA GF2 Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_t mmp_ecdsa_sign_r_gf2_l512; + + /** ECDSA GF2 Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_t mmp_ecdsa_sign_s_gf2_l512; + + /** ECDSA GF2 Verify */ + icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_t mmp_ecdsa_verify_gf2_l512; + + /** ECDSA GF2 Sign RS for curves B-571/K-571 */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_t mmp_ecdsa_sign_rs_gf2_571; + + /** ECDSA GF2 Sign S for curves with deg(q) < 576 */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_t mmp_ecdsa_sign_s_gf2_571; + + /** ECDSA GF2 Sign R for degree 571 */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_t mmp_ecdsa_sign_r_gf2_571; + + /** ECDSA GF2 Verify for degree 571 */ + icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_t mmp_ecdsa_verify_gf2_571; + + /** MATHS GF2 Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gf2_l256_input_t + maths_point_multiplication_gf2_l256; + + /** MATHS GF2 Point Verification */ + icp_qat_fw_maths_point_verify_gf2_l256_input_t + maths_point_verify_gf2_l256; + + /** MATHS GF2 Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gf2_l512_input_t + maths_point_multiplication_gf2_l512; + + /** MATHS GF2 Point Verification */ + icp_qat_fw_maths_point_verify_gf2_l512_input_t + maths_point_verify_gf2_l512; + + /** ECC GF2 Point Multiplication for curves B-571/K-571 */ + icp_qat_fw_maths_point_multiplication_gf2_571_input_t + maths_point_multiplication_gf2_571; + + /** ECC GF2 Point Verification for degree 571 */ + icp_qat_fw_maths_point_verify_gf2_571_input_t + maths_point_verify_gf2_571; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_t mmp_ecdsa_sign_r_gfp_l256; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_t mmp_ecdsa_sign_s_gfp_l256; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_t + mmp_ecdsa_sign_rs_gfp_l256; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_t mmp_ecdsa_verify_gfp_l256; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_t mmp_ecdsa_sign_r_gfp_l512; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_t mmp_ecdsa_sign_s_gfp_l512; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_t + mmp_ecdsa_sign_rs_gfp_l512; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_t mmp_ecdsa_verify_gfp_l512; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_t mmp_ecdsa_sign_r_gfp_521; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_t mmp_ecdsa_sign_s_gfp_521; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_t mmp_ecdsa_sign_rs_gfp_521; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_t mmp_ecdsa_verify_gfp_521; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_l256_input_t + maths_point_multiplication_gfp_l256; + + /** ECC GFP Partial Point Verification */ + icp_qat_fw_maths_point_verify_gfp_l256_input_t + maths_point_verify_gfp_l256; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_l512_input_t + maths_point_multiplication_gfp_l512; + + /** ECC GFP Partial Point */ + icp_qat_fw_maths_point_verify_gfp_l512_input_t + maths_point_verify_gfp_l512; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_521_input_t + maths_point_multiplication_gfp_521; + + /** ECC GFP Partial Point Verification */ + icp_qat_fw_maths_point_verify_gfp_521_input_t + maths_point_verify_gfp_521; + + /** ECC curve25519 Variable Point Multiplication [k]P(x), as specified + * in RFC7748 */ + icp_qat_fw_point_multiplication_c25519_input_t + point_multiplication_c25519; + + /** ECC curve25519 Generator Point Multiplication [k]G(x), as specified + * in RFC7748 */ + icp_qat_fw_generator_multiplication_c25519_input_t + generator_multiplication_c25519; + + /** ECC edwards25519 Variable Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_point_multiplication_ed25519_input_t + point_multiplication_ed25519; + + /** ECC edwards25519 Generator Point Multiplication [k]G, as specified + * in RFC8032 */ + icp_qat_fw_generator_multiplication_ed25519_input_t + generator_multiplication_ed25519; + + /** ECC curve448 Variable Point Multiplication [k]P(x), as specified in + * RFC7748 */ + icp_qat_fw_point_multiplication_c448_input_t point_multiplication_c448; + + /** ECC curve448 Generator Point Multiplication [k]G(x), as specified in + * RFC7748 */ + icp_qat_fw_generator_multiplication_c448_input_t + generator_multiplication_c448; + + /** ECC edwards448 Variable Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_point_multiplication_ed448_input_t + point_multiplication_ed448; + + /** ECC edwards448 Generator Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_generator_multiplication_ed448_input_t + generator_multiplication_ed448; +} icp_qat_fw_mmp_input_param_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Initialisation sequence , + * to be used when icp_qat_fw_pke_response_s::functionalityId is #PKE_INIT. + */ +typedef struct icp_qat_fw_mmp_init_output_s { + uint64_t zz; /**< 1'd quadword (1 qwords)*/ +} icp_qat_fw_mmp_init_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 768-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_768. + */ +typedef struct icp_qat_fw_mmp_dh_g2_768_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (12 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 768-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_768. + */ +typedef struct icp_qat_fw_mmp_dh_768_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (12 + qwords)*/ +} icp_qat_fw_mmp_dh_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 1024-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_1024. + */ +typedef struct icp_qat_fw_mmp_dh_g2_1024_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 1024-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_1024. + */ +typedef struct icp_qat_fw_mmp_dh_1024_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 + qwords)*/ +} icp_qat_fw_mmp_dh_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 1536-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_1536. + */ +typedef struct icp_qat_fw_mmp_dh_g2_1536_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 1536-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_1536. + */ +typedef struct icp_qat_fw_mmp_dh_1536_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 + qwords)*/ +} icp_qat_fw_mmp_dh_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 2048-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_2048. + */ +typedef struct icp_qat_fw_mmp_dh_g2_2048_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 2048-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_2048. + */ +typedef struct icp_qat_fw_mmp_dh_2048_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 + qwords)*/ +} icp_qat_fw_mmp_dh_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 3072-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_3072. + */ +typedef struct icp_qat_fw_mmp_dh_g2_3072_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 3072-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_3072. + */ +typedef struct icp_qat_fw_mmp_dh_3072_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 + qwords)*/ +} icp_qat_fw_mmp_dh_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for + * 4096-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_G2_4096. + */ +typedef struct icp_qat_fw_mmp_dh_g2_4096_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 + qwords)*/ +} icp_qat_fw_mmp_dh_g2_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Diffie-Hellman Modular exponentiation for + * 4096-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DH_4096. + */ +typedef struct icp_qat_fw_mmp_dh_4096_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 + qwords)*/ +} icp_qat_fw_mmp_dh_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 512 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_512. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_512_output_s { + uint64_t n; /**< RSA key (8 qwords)*/ + uint64_t d; /**< RSA private key (first form) (8 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 512 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_512. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_512_output_s { + uint64_t n; /**< RSA key (8 qwords)*/ + uint64_t d; /**< RSA private key (second form) (8 qwords)*/ + uint64_t dp; /**< RSA private key (second form) (4 qwords)*/ + uint64_t dq; /**< RSA private key (second form) (4 qwords)*/ + uint64_t qinv; /**< RSA private key (second form) (4 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 512 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_512. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_512_output_s { + uint64_t c; /**< cipher text representative, < n (8 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 512 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_512. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_512_output_s { + uint64_t m; /**< message representative, < n (8 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_512. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_512_output_s { + uint64_t m; /**< message representative, < (p*q) (8 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_1024_output_s { + uint64_t n; /**< RSA key (16 qwords)*/ + uint64_t d; /**< RSA private key (first form) (16 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_1024_output_s { + uint64_t n; /**< RSA key (16 qwords)*/ + uint64_t d; /**< RSA private key (second form) (16 qwords)*/ + uint64_t dp; /**< RSA private key (second form) (8 qwords)*/ + uint64_t dq; /**< RSA private key (second form) (8 qwords)*/ + uint64_t qinv; /**< RSA private key (second form) (8 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_1024_output_s { + uint64_t c; /**< cipher text representative, < n (16 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_1024_output_s { + uint64_t m; /**< message representative, < n (16 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1024 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_1024. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_1024_output_s { + uint64_t m; /**< message representative, < (p*q) (16 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1536 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_1536_output_s { + uint64_t n; /**< RSA key (24 qwords)*/ + uint64_t d; /**< RSA private key (24 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1536 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_1536_output_s { + uint64_t n; /**< RSA key (24 qwords)*/ + uint64_t d; /**< RSA private key (24 qwords)*/ + uint64_t dp; /**< RSA private key (12 qwords)*/ + uint64_t dq; /**< RSA private key (12 qwords)*/ + uint64_t qinv; /**< RSA private key (12 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1536 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_1536_output_s { + uint64_t c; /**< cipher text representative, < n (24 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1536 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_1536_output_s { + uint64_t m; /**< message representative, < n (24 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 1536 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_1536. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_1536_output_s { + uint64_t m; /**< message representative, < (p*q) (24 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 2048 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_2048_output_s { + uint64_t n; /**< RSA key (32 qwords)*/ + uint64_t d; /**< RSA private key (32 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 2048 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_2048_output_s { + uint64_t n; /**< RSA key (32 qwords)*/ + uint64_t d; /**< RSA private key (32 qwords)*/ + uint64_t dp; /**< RSA private key (16 qwords)*/ + uint64_t dq; /**< RSA private key (16 qwords)*/ + uint64_t qinv; /**< RSA private key (16 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 2048 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_2048_output_s { + uint64_t c; /**< cipher text representative, < n (32 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 2048 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_2048_output_s { + uint64_t m; /**< message representative, < n (32 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 2048 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_2048. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_2048_output_s { + uint64_t m; /**< message representative, < (p*q) (32 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 3072 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_3072_output_s { + uint64_t n; /**< RSA key (48 qwords)*/ + uint64_t d; /**< RSA private key (48 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 3072 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_3072_output_s { + uint64_t n; /**< RSA key (48 qwords)*/ + uint64_t d; /**< RSA private key (48 qwords)*/ + uint64_t dp; /**< RSA private key (24 qwords)*/ + uint64_t dq; /**< RSA private key (24 qwords)*/ + uint64_t qinv; /**< RSA private key (24 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 3072 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_3072_output_s { + uint64_t c; /**< cipher text representative, < n (48 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 3072 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_3072_output_s { + uint64_t m; /**< message representative, < n (48 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 3072 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_3072. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_3072_output_s { + uint64_t m; /**< message representative, < (p*q) (48 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 4096 key generation first form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP1_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_kp1_4096_output_s { + uint64_t n; /**< RSA key (64 qwords)*/ + uint64_t d; /**< RSA private key (64 qwords)*/ +} icp_qat_fw_mmp_rsa_kp1_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 4096 key generation second form , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_KP2_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_kp2_4096_output_s { + uint64_t n; /**< RSA key (64 qwords)*/ + uint64_t d; /**< RSA private key (64 qwords)*/ + uint64_t dp; /**< RSA private key (32 qwords)*/ + uint64_t dq; /**< RSA private key (32 qwords)*/ + uint64_t qinv; /**< RSA private key (32 qwords)*/ +} icp_qat_fw_mmp_rsa_kp2_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 4096 Encryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_EP_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_ep_4096_output_s { + uint64_t c; /**< cipher text representative, < n (64 qwords)*/ +} icp_qat_fw_mmp_rsa_ep_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 4096 Decryption , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP1_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_dp1_4096_output_s { + uint64_t m; /**< message representative, < n (64 qwords)*/ +} icp_qat_fw_mmp_rsa_dp1_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for RSA 4096 Decryption with CRT , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_RSA_DP2_4096. + */ +typedef struct icp_qat_fw_mmp_rsa_dp2_4096_output_s { + uint64_t m; /**< message representative, < (p*q) (64 qwords)*/ +} icp_qat_fw_mmp_rsa_dp2_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 192-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_192. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_192_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_192_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 256-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_256. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_256_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 384-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_384. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_384_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_384_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_512. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_768. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_768_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_1024. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_1024_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_1536. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_1536_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_2048. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_2048_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_3072. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_3072_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for GCD primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_GCD_PT_4096. + */ +typedef struct icp_qat_fw_mmp_gcd_pt_4096_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_gcd_pt_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 160-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_160. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_160_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_512. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for <e; 512-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_L512. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_l512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_768. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_768_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_1024. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_1024_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_1536. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_1536_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_2048. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_2048_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_3072. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_3072_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Fermat primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_FERMAT_PT_4096. + */ +typedef struct icp_qat_fw_mmp_fermat_pt_4096_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_fermat_pt_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 160-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_160. + */ +typedef struct icp_qat_fw_mmp_mr_pt_160_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 512-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_512. + */ +typedef struct icp_qat_fw_mmp_mr_pt_512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 768-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_768. + */ +typedef struct icp_qat_fw_mmp_mr_pt_768_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 1024-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_1024. + */ +typedef struct icp_qat_fw_mmp_mr_pt_1024_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 1536-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_1536. + */ +typedef struct icp_qat_fw_mmp_mr_pt_1536_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 2048-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_2048. + */ +typedef struct icp_qat_fw_mmp_mr_pt_2048_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 3072-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_3072. + */ +typedef struct icp_qat_fw_mmp_mr_pt_3072_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 4096-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_4096. + */ +typedef struct icp_qat_fw_mmp_mr_pt_4096_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Miller-Rabin primality test for 512-bit numbers + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_MR_PT_L512. + */ +typedef struct icp_qat_fw_mmp_mr_pt_l512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_mr_pt_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 160-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_160. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_160_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 512-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_512. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 768-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_768. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_768_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 1024-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_1024. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_1024_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 1536-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_1536. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_1536_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 2048-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_2048. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_2048_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 3072-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_3072. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_3072_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for 4096-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_4096. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_4096_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Lucas primality test for L512-bit numbers , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_LUCAS_PT_L512. + */ +typedef struct icp_qat_fw_mmp_lucas_pt_l512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_lucas_pt_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 512-bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L512. + */ +typedef struct icp_qat_fw_maths_modexp_l512_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (8 + qwords)*/ +} icp_qat_fw_maths_modexp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 1024-bit , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L1024. + */ +typedef struct icp_qat_fw_maths_modexp_l1024_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 + qwords)*/ +} icp_qat_fw_maths_modexp_l1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 1536-bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L1536. + */ +typedef struct icp_qat_fw_maths_modexp_l1536_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 + qwords)*/ +} icp_qat_fw_maths_modexp_l1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 2048-bit , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L2048. + */ +typedef struct icp_qat_fw_maths_modexp_l2048_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 + qwords)*/ +} icp_qat_fw_maths_modexp_l2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 2560-bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L2560. + */ +typedef struct icp_qat_fw_maths_modexp_l2560_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (40 + qwords)*/ +} icp_qat_fw_maths_modexp_l2560_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 3072-bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L3072. + */ +typedef struct icp_qat_fw_maths_modexp_l3072_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 + qwords)*/ +} icp_qat_fw_maths_modexp_l3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 3584-bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L3584. + */ +typedef struct icp_qat_fw_maths_modexp_l3584_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (56 + qwords)*/ +} icp_qat_fw_maths_modexp_l3584_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular exponentiation for numbers less than + * 4096-bit , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODEXP_L4096. + */ +typedef struct icp_qat_fw_maths_modexp_l4096_output_s { + uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 + qwords)*/ +} icp_qat_fw_maths_modexp_l4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 128 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L128. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l128_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (2 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l128_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 192 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L192. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l192_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (3 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l192_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 256 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L256. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l256_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (4 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 384 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L384. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l384_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (6 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l384_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 512 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L512. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l512_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (8 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 768 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L768. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l768_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (12 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 1024 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L1024. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l1024_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (16 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 1536 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L1536. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l1536_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (24 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 2048 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L2048. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l2048_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (32 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 3072 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L3072. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l3072_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (48 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 4096 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_ODD_L4096. + */ +typedef struct icp_qat_fw_maths_modinv_odd_l4096_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (64 + qwords)*/ +} icp_qat_fw_maths_modinv_odd_l4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 128 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L128. + */ +typedef struct icp_qat_fw_maths_modinv_even_l128_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (2 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l128_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 192 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L192. + */ +typedef struct icp_qat_fw_maths_modinv_even_l192_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (3 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l192_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 256 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L256. + */ +typedef struct icp_qat_fw_maths_modinv_even_l256_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (4 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 384 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L384. + */ +typedef struct icp_qat_fw_maths_modinv_even_l384_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (6 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l384_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 512 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L512. + */ +typedef struct icp_qat_fw_maths_modinv_even_l512_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (8 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 768 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L768. + */ +typedef struct icp_qat_fw_maths_modinv_even_l768_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (12 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l768_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 1024 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L1024. + */ +typedef struct icp_qat_fw_maths_modinv_even_l1024_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (16 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 1536 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L1536. + */ +typedef struct icp_qat_fw_maths_modinv_even_l1536_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (24 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l1536_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 2048 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L2048. + */ +typedef struct icp_qat_fw_maths_modinv_even_l2048_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (32 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 3072 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L3072. + */ +typedef struct icp_qat_fw_maths_modinv_even_l3072_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (48 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for Modular multiplicative inverse for numbers less + * than 4096 bits , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_MODINV_EVEN_L4096. + */ +typedef struct icp_qat_fw_maths_modinv_even_l4096_output_s { + uint64_t + c; /**< modular multiplicative inverse of a, > 0 and < b (64 + qwords)*/ +} icp_qat_fw_maths_modinv_even_l4096_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_P_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_1024_160_output_s { + uint64_t p; /**< candidate for DSA parameter p (16 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_1024_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_G_1024. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_1024_output_s { + uint64_t g; /**< DSA parameter (16 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_Y_1024. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_1024_output_s { + uint64_t y; /**< DSA parameter (16 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_1024_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_1024_160_output_s { + uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_1024_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_S_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_160_output_s { + uint64_t s; /**< s DSA 160-bits signature (3 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_S_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s { + uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ + uint64_t s; /**< DSA 160-bits signature (3 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_VERIFY_1024_160. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_1024_160_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_dsa_verify_1024_160_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_P_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_224_output_s { + uint64_t p; /**< candidate for DSA parameter p (32 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_2048_224_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_Y_2048. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_2048_output_s { + uint64_t y; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_224_output_s { + uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_2048_224_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_S_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_224_output_s { + uint64_t s; /**< s DSA 224-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_224_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_S_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s { + uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 224-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_VERIFY_2048_224. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_2048_224_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_dsa_verify_2048_224_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_P_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_256_output_s { + uint64_t p; /**< candidate for DSA parameter p (32 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_2048_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_G_2048. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_2048_output_s { + uint64_t g; /**< DSA parameter (32 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_2048_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_256_output_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_2048_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_S_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_s_256_output_s { + uint64_t s; /**< s DSA 256-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_s_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_S_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_VERIFY_2048_256. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_2048_256_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_dsa_verify_2048_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA parameter generation P , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_P_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_p_3072_256_output_s { + uint64_t p; /**< candidate for DSA parameter p (48 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_p_3072_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation G , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_G_3072. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_g_3072_output_s { + uint64_t g; /**< DSA parameter (48 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_g_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA key generation Y , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_GEN_Y_3072. + */ +typedef struct icp_qat_fw_mmp_dsa_gen_y_3072_output_s { + uint64_t y; /**< DSA parameter (48 qwords)*/ +} icp_qat_fw_mmp_dsa_gen_y_3072_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_3072_256_output_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_3072_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Sign R S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_SIGN_R_S_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s { + uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ + uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ +} icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for DSA Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_DSA_VERIFY_3072_256. + */ +typedef struct icp_qat_fw_mmp_dsa_verify_3072_256_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_dsa_verify_3072_256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA Sign RS for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s { + uint64_t r; /**< ECDSA signature r > 0 and < n (4 qwords)*/ + uint64_t s; /**< ECDSA signature s > 0 and < n (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA Sign R for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_s { + uint64_t r; /**< ECDSA signature r > 0 and < n (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA Sign S for curves with n < 2^256 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_s { + uint64_t s; /**< ECDSA signature s > 0 and < n (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA Verify for curves B/K-163 and B/K-233 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA Sign RS , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s { + uint64_t r; /**< (8 qwords)*/ + uint64_t s; /**< ECDSA signature r > 0 and < n ECDSA signature s + > 0 and < n (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_s { + uint64_t r; /**< ECDSA signature r > 0 and < n (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_s { + uint64_t s; /**< ECDSA signature s > 0 and < n (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Sign RS for curves B-571/K-571 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s { + uint64_t r; /**< (9 qwords)*/ + uint64_t s; /**< ECDSA signature r > 0 and < n ECDSA signature s + > 0 and < n (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Sign S for curves with deg(q) < 576 + * , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_s { + uint64_t s; /**< ECDSA signature s > 0 and < n (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Sign R for degree 571 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_s { + uint64_t r; /**< ECDSA signature r > 0 and < n (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GF2 Verify for degree 571 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GF2_571. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for MATHS GF2 Point Multiplication , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_L256. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_l256_output_s { + uint64_t xk; /**< x coordinate of resultant point (< degree(q)) (4 + qwords)*/ + uint64_t yk; /**< y coordinate of resultant point (< degree(q)) (4 + qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for MATHS GF2 Point Verification , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_L256. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_l256_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gf2_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for MATHS GF2 Point Multiplication , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_L512. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_l512_output_s { + uint64_t xk; /**< x coordinate of resultant point (< q) (8 qwords)*/ + uint64_t yk; /**< y coordinate of resultant point (< q) (8 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for MATHS GF2 Point Verification , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_L512. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_l512_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gf2_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GF2 Point Multiplication for curves + * B-571/K-571 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GF2_571. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gf2_571_output_s { + uint64_t xk; /**< x coordinate of resultant point (degree < + degree(q)) (9 qwords)*/ + uint64_t yk; /**< y coordinate of resultant point (degree < + degree(q)) (9 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GF2 Point Verification for degree 571 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GF2_571. + */ +typedef struct icp_qat_fw_maths_point_verify_gf2_571_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gf2_571_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_s { + uint64_t r; /**< ECDSA signature (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_s { + uint64_t s; /**< ECDSA signature s (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s { + uint64_t r; /**< ECDSA signature r (4 qwords)*/ + uint64_t s; /**< ECDSA signature s (4 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_L256. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_s { + uint64_t r; /**< ECDSA signature (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_s { + uint64_t s; /**< ECDSA signature s (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s { + uint64_t r; /**< ECDSA signature r (8 qwords)*/ + uint64_t s; /**< ECDSA signature s (8 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_L512. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign R , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_R_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_s { + uint64_t r; /**< ECDSA signature (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign S , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_S_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_s { + uint64_t s; /**< ECDSA signature s (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Sign RS , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_SIGN_RS_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s { + uint64_t r; /**< ECDSA signature r (9 qwords)*/ + uint64_t s; /**< ECDSA signature s (9 qwords)*/ +} icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECDSA GFP Verify , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #PKE_ECDSA_VERIFY_GFP_521. + */ +typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_s { + /* no output parameters */ +} icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_L256. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_l256_output_s { + uint64_t xk; /**< x coordinate of resultant EC point (4 qwords)*/ + uint64_t yk; /**< y coordinate of resultant EC point (4 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Partial Point Verification , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_L256. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_l256_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gfp_l256_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_L512. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_l512_output_s { + uint64_t xk; /**< x coordinate of resultant EC point (8 qwords)*/ + uint64_t yk; /**< y coordinate of resultant EC point (8 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Partial Point , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_L512. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_l512_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gfp_l512_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Point Multiplication , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_MULTIPLICATION_GFP_521. + */ +typedef struct icp_qat_fw_maths_point_multiplication_gfp_521_output_s { + uint64_t xk; /**< x coordinate of resultant EC point (9 qwords)*/ + uint64_t yk; /**< y coordinate of resultant EC point (9 qwords)*/ +} icp_qat_fw_maths_point_multiplication_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC GFP Partial Point Verification , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #MATHS_POINT_VERIFY_GFP_521. + */ +typedef struct icp_qat_fw_maths_point_verify_gfp_521_output_s { + /* no output parameters */ +} icp_qat_fw_maths_point_verify_gfp_521_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC curve25519 Variable Point Multiplication + * [k]P(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #POINT_MULTIPLICATION_C25519. + */ +typedef struct icp_qat_fw_point_multiplication_c25519_output_s { + uint64_t + xr; /**< xR = Montgomery affine coordinate X of point [k]P (4 + qwords)*/ +} icp_qat_fw_point_multiplication_c25519_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC curve25519 Generator Point Multiplication + * [k]G(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #GENERATOR_MULTIPLICATION_C25519. + */ +typedef struct icp_qat_fw_generator_multiplication_c25519_output_s { + uint64_t + xr; /**< xR = Montgomery affine coordinate X of point [k]G (4 + qwords)*/ +} icp_qat_fw_generator_multiplication_c25519_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC edwards25519 Variable Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #POINT_MULTIPLICATION_ED25519. + */ +typedef struct icp_qat_fw_point_multiplication_ed25519_output_s { + uint64_t + xr; /**< xR = Twisted Edwards affine coordinate X of point [k]P (4 + qwords)*/ + uint64_t + yr; /**< yR = Twisted Edwards affine coordinate Y of point [k]P (4 + qwords)*/ +} icp_qat_fw_point_multiplication_ed25519_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC edwards25519 Generator Point Multiplication + * [k]G, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #GENERATOR_MULTIPLICATION_ED25519. + */ +typedef struct icp_qat_fw_generator_multiplication_ed25519_output_s { + uint64_t + xr; /**< xR = Twisted Edwards affine coordinate X of point [k]G (4 + qwords)*/ + uint64_t + yr; /**< yR = Twisted Edwards affine coordinate Y of point [k]G (4 + qwords)*/ +} icp_qat_fw_generator_multiplication_ed25519_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC curve448 Variable Point Multiplication + * [k]P(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #POINT_MULTIPLICATION_C448. + */ +typedef struct icp_qat_fw_point_multiplication_c448_output_s { + uint64_t + xr; /**< xR = Montgomery affine coordinate X of point [k]P (8 + qwords)*/ +} icp_qat_fw_point_multiplication_c448_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC curve448 Generator Point Multiplication + * [k]G(x), as specified in RFC7748 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #GENERATOR_MULTIPLICATION_C448. + */ +typedef struct icp_qat_fw_generator_multiplication_c448_output_s { + uint64_t + xr; /**< xR = Montgomery affine coordinate X of point [k]G (8 + qwords)*/ +} icp_qat_fw_generator_multiplication_c448_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC edwards448 Variable Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #POINT_MULTIPLICATION_ED448. + */ +typedef struct icp_qat_fw_point_multiplication_ed448_output_s { + uint64_t xr; /**< xR = Edwards affine coordinate X of point [k]P (8 + qwords)*/ + uint64_t yr; /**< yR = Edwards affine coordinate Y of point [k]P (8 + qwords)*/ +} icp_qat_fw_point_multiplication_ed448_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * Output parameter list for ECC edwards448 Generator Point Multiplication + * [k]P, as specified in RFC8032 , + * to be used when icp_qat_fw_pke_response_s::functionalityId is + * #GENERATOR_MULTIPLICATION_ED448. + */ +typedef struct icp_qat_fw_generator_multiplication_ed448_output_s { + uint64_t xr; /**< xR = Edwards affine coordinate X of point [k]G (8 + qwords)*/ + uint64_t yr; /**< yR = Edwards affine coordinate Y of point [k]G (8 + qwords)*/ +} icp_qat_fw_generator_multiplication_ed448_output_t; + +/** + * @ingroup icp_qat_fw_mmp + * @brief + * MMP output parameters + */ +typedef union icp_qat_fw_mmp_output_param_u { + /** Generic parameter structure : All members of this wrapper structure + * are pointers to large integers. + */ + uint64_t flat_array[ICP_QAT_FW_PKE_OUTPUT_COUNT_MAX]; + + /** Initialisation sequence */ + icp_qat_fw_mmp_init_output_t mmp_init; + + /** Diffie-Hellman Modular exponentiation base 2 for 768-bit numbers */ + icp_qat_fw_mmp_dh_g2_768_output_t mmp_dh_g2_768; + + /** Diffie-Hellman Modular exponentiation for 768-bit numbers */ + icp_qat_fw_mmp_dh_768_output_t mmp_dh_768; + + /** Diffie-Hellman Modular exponentiation base 2 for 1024-bit numbers */ + icp_qat_fw_mmp_dh_g2_1024_output_t mmp_dh_g2_1024; + + /** Diffie-Hellman Modular exponentiation for 1024-bit numbers */ + icp_qat_fw_mmp_dh_1024_output_t mmp_dh_1024; + + /** Diffie-Hellman Modular exponentiation base 2 for 1536-bit numbers */ + icp_qat_fw_mmp_dh_g2_1536_output_t mmp_dh_g2_1536; + + /** Diffie-Hellman Modular exponentiation for 1536-bit numbers */ + icp_qat_fw_mmp_dh_1536_output_t mmp_dh_1536; + + /** Diffie-Hellman Modular exponentiation base 2 for 2048-bit numbers */ + icp_qat_fw_mmp_dh_g2_2048_output_t mmp_dh_g2_2048; + + /** Diffie-Hellman Modular exponentiation for 2048-bit numbers */ + icp_qat_fw_mmp_dh_2048_output_t mmp_dh_2048; + + /** Diffie-Hellman Modular exponentiation base 2 for 3072-bit numbers */ + icp_qat_fw_mmp_dh_g2_3072_output_t mmp_dh_g2_3072; + + /** Diffie-Hellman Modular exponentiation for 3072-bit numbers */ + icp_qat_fw_mmp_dh_3072_output_t mmp_dh_3072; + + /** Diffie-Hellman Modular exponentiation base 2 for 4096-bit numbers */ + icp_qat_fw_mmp_dh_g2_4096_output_t mmp_dh_g2_4096; + + /** Diffie-Hellman Modular exponentiation for 4096-bit numbers */ + icp_qat_fw_mmp_dh_4096_output_t mmp_dh_4096; + + /** RSA 512 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_512_output_t mmp_rsa_kp1_512; + + /** RSA 512 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_512_output_t mmp_rsa_kp2_512; + + /** RSA 512 Encryption */ + icp_qat_fw_mmp_rsa_ep_512_output_t mmp_rsa_ep_512; + + /** RSA 512 Decryption */ + icp_qat_fw_mmp_rsa_dp1_512_output_t mmp_rsa_dp1_512; + + /** RSA 1024 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_512_output_t mmp_rsa_dp2_512; + + /** RSA 1024 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_1024_output_t mmp_rsa_kp1_1024; + + /** RSA 1024 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_1024_output_t mmp_rsa_kp2_1024; + + /** RSA 1024 Encryption */ + icp_qat_fw_mmp_rsa_ep_1024_output_t mmp_rsa_ep_1024; + + /** RSA 1024 Decryption */ + icp_qat_fw_mmp_rsa_dp1_1024_output_t mmp_rsa_dp1_1024; + + /** RSA 1024 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_1024_output_t mmp_rsa_dp2_1024; + + /** RSA 1536 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_1536_output_t mmp_rsa_kp1_1536; + + /** RSA 1536 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_1536_output_t mmp_rsa_kp2_1536; + + /** RSA 1536 Encryption */ + icp_qat_fw_mmp_rsa_ep_1536_output_t mmp_rsa_ep_1536; + + /** RSA 1536 Decryption */ + icp_qat_fw_mmp_rsa_dp1_1536_output_t mmp_rsa_dp1_1536; + + /** RSA 1536 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_1536_output_t mmp_rsa_dp2_1536; + + /** RSA 2048 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_2048_output_t mmp_rsa_kp1_2048; + + /** RSA 2048 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_2048_output_t mmp_rsa_kp2_2048; + + /** RSA 2048 Encryption */ + icp_qat_fw_mmp_rsa_ep_2048_output_t mmp_rsa_ep_2048; + + /** RSA 2048 Decryption */ + icp_qat_fw_mmp_rsa_dp1_2048_output_t mmp_rsa_dp1_2048; + + /** RSA 2048 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_2048_output_t mmp_rsa_dp2_2048; + + /** RSA 3072 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_3072_output_t mmp_rsa_kp1_3072; + + /** RSA 3072 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_3072_output_t mmp_rsa_kp2_3072; + + /** RSA 3072 Encryption */ + icp_qat_fw_mmp_rsa_ep_3072_output_t mmp_rsa_ep_3072; + + /** RSA 3072 Decryption */ + icp_qat_fw_mmp_rsa_dp1_3072_output_t mmp_rsa_dp1_3072; + + /** RSA 3072 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_3072_output_t mmp_rsa_dp2_3072; + + /** RSA 4096 key generation first form */ + icp_qat_fw_mmp_rsa_kp1_4096_output_t mmp_rsa_kp1_4096; + + /** RSA 4096 key generation second form */ + icp_qat_fw_mmp_rsa_kp2_4096_output_t mmp_rsa_kp2_4096; + + /** RSA 4096 Encryption */ + icp_qat_fw_mmp_rsa_ep_4096_output_t mmp_rsa_ep_4096; + + /** RSA 4096 Decryption */ + icp_qat_fw_mmp_rsa_dp1_4096_output_t mmp_rsa_dp1_4096; + + /** RSA 4096 Decryption with CRT */ + icp_qat_fw_mmp_rsa_dp2_4096_output_t mmp_rsa_dp2_4096; + + /** GCD primality test for 192-bit numbers */ + icp_qat_fw_mmp_gcd_pt_192_output_t mmp_gcd_pt_192; + + /** GCD primality test for 256-bit numbers */ + icp_qat_fw_mmp_gcd_pt_256_output_t mmp_gcd_pt_256; + + /** GCD primality test for 384-bit numbers */ + icp_qat_fw_mmp_gcd_pt_384_output_t mmp_gcd_pt_384; + + /** GCD primality test for 512-bit numbers */ + icp_qat_fw_mmp_gcd_pt_512_output_t mmp_gcd_pt_512; + + /** GCD primality test for 768-bit numbers */ + icp_qat_fw_mmp_gcd_pt_768_output_t mmp_gcd_pt_768; + + /** GCD primality test for 1024-bit numbers */ + icp_qat_fw_mmp_gcd_pt_1024_output_t mmp_gcd_pt_1024; + + /** GCD primality test for 1536-bit numbers */ + icp_qat_fw_mmp_gcd_pt_1536_output_t mmp_gcd_pt_1536; + + /** GCD primality test for 2048-bit numbers */ + icp_qat_fw_mmp_gcd_pt_2048_output_t mmp_gcd_pt_2048; + + /** GCD primality test for 3072-bit numbers */ + icp_qat_fw_mmp_gcd_pt_3072_output_t mmp_gcd_pt_3072; + + /** GCD primality test for 4096-bit numbers */ + icp_qat_fw_mmp_gcd_pt_4096_output_t mmp_gcd_pt_4096; + + /** Fermat primality test for 160-bit numbers */ + icp_qat_fw_mmp_fermat_pt_160_output_t mmp_fermat_pt_160; + + /** Fermat primality test for 512-bit numbers */ + icp_qat_fw_mmp_fermat_pt_512_output_t mmp_fermat_pt_512; + + /** Fermat primality test for <e; 512-bit numbers */ + icp_qat_fw_mmp_fermat_pt_l512_output_t mmp_fermat_pt_l512; + + /** Fermat primality test for 768-bit numbers */ + icp_qat_fw_mmp_fermat_pt_768_output_t mmp_fermat_pt_768; + + /** Fermat primality test for 1024-bit numbers */ + icp_qat_fw_mmp_fermat_pt_1024_output_t mmp_fermat_pt_1024; + + /** Fermat primality test for 1536-bit numbers */ + icp_qat_fw_mmp_fermat_pt_1536_output_t mmp_fermat_pt_1536; + + /** Fermat primality test for 2048-bit numbers */ + icp_qat_fw_mmp_fermat_pt_2048_output_t mmp_fermat_pt_2048; + + /** Fermat primality test for 3072-bit numbers */ + icp_qat_fw_mmp_fermat_pt_3072_output_t mmp_fermat_pt_3072; + + /** Fermat primality test for 4096-bit numbers */ + icp_qat_fw_mmp_fermat_pt_4096_output_t mmp_fermat_pt_4096; + + /** Miller-Rabin primality test for 160-bit numbers */ + icp_qat_fw_mmp_mr_pt_160_output_t mmp_mr_pt_160; + + /** Miller-Rabin primality test for 512-bit numbers */ + icp_qat_fw_mmp_mr_pt_512_output_t mmp_mr_pt_512; + + /** Miller-Rabin primality test for 768-bit numbers */ + icp_qat_fw_mmp_mr_pt_768_output_t mmp_mr_pt_768; + + /** Miller-Rabin primality test for 1024-bit numbers */ + icp_qat_fw_mmp_mr_pt_1024_output_t mmp_mr_pt_1024; + + /** Miller-Rabin primality test for 1536-bit numbers */ + icp_qat_fw_mmp_mr_pt_1536_output_t mmp_mr_pt_1536; + + /** Miller-Rabin primality test for 2048-bit numbers */ + icp_qat_fw_mmp_mr_pt_2048_output_t mmp_mr_pt_2048; + + /** Miller-Rabin primality test for 3072-bit numbers */ + icp_qat_fw_mmp_mr_pt_3072_output_t mmp_mr_pt_3072; + + /** Miller-Rabin primality test for 4096-bit numbers */ + icp_qat_fw_mmp_mr_pt_4096_output_t mmp_mr_pt_4096; + + /** Miller-Rabin primality test for 512-bit numbers */ + icp_qat_fw_mmp_mr_pt_l512_output_t mmp_mr_pt_l512; + + /** Lucas primality test for 160-bit numbers */ + icp_qat_fw_mmp_lucas_pt_160_output_t mmp_lucas_pt_160; + + /** Lucas primality test for 512-bit numbers */ + icp_qat_fw_mmp_lucas_pt_512_output_t mmp_lucas_pt_512; + + /** Lucas primality test for 768-bit numbers */ + icp_qat_fw_mmp_lucas_pt_768_output_t mmp_lucas_pt_768; + + /** Lucas primality test for 1024-bit numbers */ + icp_qat_fw_mmp_lucas_pt_1024_output_t mmp_lucas_pt_1024; + + /** Lucas primality test for 1536-bit numbers */ + icp_qat_fw_mmp_lucas_pt_1536_output_t mmp_lucas_pt_1536; + + /** Lucas primality test for 2048-bit numbers */ + icp_qat_fw_mmp_lucas_pt_2048_output_t mmp_lucas_pt_2048; + + /** Lucas primality test for 3072-bit numbers */ + icp_qat_fw_mmp_lucas_pt_3072_output_t mmp_lucas_pt_3072; + + /** Lucas primality test for 4096-bit numbers */ + icp_qat_fw_mmp_lucas_pt_4096_output_t mmp_lucas_pt_4096; + + /** Lucas primality test for L512-bit numbers */ + icp_qat_fw_mmp_lucas_pt_l512_output_t mmp_lucas_pt_l512; + + /** Modular exponentiation for numbers less than 512-bits */ + icp_qat_fw_maths_modexp_l512_output_t maths_modexp_l512; + + /** Modular exponentiation for numbers less than 1024-bit */ + icp_qat_fw_maths_modexp_l1024_output_t maths_modexp_l1024; + + /** Modular exponentiation for numbers less than 1536-bits */ + icp_qat_fw_maths_modexp_l1536_output_t maths_modexp_l1536; + + /** Modular exponentiation for numbers less than 2048-bit */ + icp_qat_fw_maths_modexp_l2048_output_t maths_modexp_l2048; + + /** Modular exponentiation for numbers less than 2560-bits */ + icp_qat_fw_maths_modexp_l2560_output_t maths_modexp_l2560; + + /** Modular exponentiation for numbers less than 3072-bits */ + icp_qat_fw_maths_modexp_l3072_output_t maths_modexp_l3072; + + /** Modular exponentiation for numbers less than 3584-bits */ + icp_qat_fw_maths_modexp_l3584_output_t maths_modexp_l3584; + + /** Modular exponentiation for numbers less than 4096-bit */ + icp_qat_fw_maths_modexp_l4096_output_t maths_modexp_l4096; + + /** Modular multiplicative inverse for numbers less than 128 bits */ + icp_qat_fw_maths_modinv_odd_l128_output_t maths_modinv_odd_l128; + + /** Modular multiplicative inverse for numbers less than 192 bits */ + icp_qat_fw_maths_modinv_odd_l192_output_t maths_modinv_odd_l192; + + /** Modular multiplicative inverse for numbers less than 256 bits */ + icp_qat_fw_maths_modinv_odd_l256_output_t maths_modinv_odd_l256; + + /** Modular multiplicative inverse for numbers less than 384 bits */ + icp_qat_fw_maths_modinv_odd_l384_output_t maths_modinv_odd_l384; + + /** Modular multiplicative inverse for numbers less than 512 bits */ + icp_qat_fw_maths_modinv_odd_l512_output_t maths_modinv_odd_l512; + + /** Modular multiplicative inverse for numbers less than 768 bits */ + icp_qat_fw_maths_modinv_odd_l768_output_t maths_modinv_odd_l768; + + /** Modular multiplicative inverse for numbers less than 1024 bits */ + icp_qat_fw_maths_modinv_odd_l1024_output_t maths_modinv_odd_l1024; + + /** Modular multiplicative inverse for numbers less than 1536 bits */ + icp_qat_fw_maths_modinv_odd_l1536_output_t maths_modinv_odd_l1536; + + /** Modular multiplicative inverse for numbers less than 2048 bits */ + icp_qat_fw_maths_modinv_odd_l2048_output_t maths_modinv_odd_l2048; + + /** Modular multiplicative inverse for numbers less than 3072 bits */ + icp_qat_fw_maths_modinv_odd_l3072_output_t maths_modinv_odd_l3072; + + /** Modular multiplicative inverse for numbers less than 4096 bits */ + icp_qat_fw_maths_modinv_odd_l4096_output_t maths_modinv_odd_l4096; + + /** Modular multiplicative inverse for numbers less than 128 bits */ + icp_qat_fw_maths_modinv_even_l128_output_t maths_modinv_even_l128; + + /** Modular multiplicative inverse for numbers less than 192 bits */ + icp_qat_fw_maths_modinv_even_l192_output_t maths_modinv_even_l192; + + /** Modular multiplicative inverse for numbers less than 256 bits */ + icp_qat_fw_maths_modinv_even_l256_output_t maths_modinv_even_l256; + + /** Modular multiplicative inverse for numbers less than 384 bits */ + icp_qat_fw_maths_modinv_even_l384_output_t maths_modinv_even_l384; + + /** Modular multiplicative inverse for numbers less than 512 bits */ + icp_qat_fw_maths_modinv_even_l512_output_t maths_modinv_even_l512; + + /** Modular multiplicative inverse for numbers less than 768 bits */ + icp_qat_fw_maths_modinv_even_l768_output_t maths_modinv_even_l768; + + /** Modular multiplicative inverse for numbers less than 1024 bits */ + icp_qat_fw_maths_modinv_even_l1024_output_t maths_modinv_even_l1024; + + /** Modular multiplicative inverse for numbers less than 1536 bits */ + icp_qat_fw_maths_modinv_even_l1536_output_t maths_modinv_even_l1536; + + /** Modular multiplicative inverse for numbers less than 2048 bits */ + icp_qat_fw_maths_modinv_even_l2048_output_t maths_modinv_even_l2048; + + /** Modular multiplicative inverse for numbers less than 3072 bits */ + icp_qat_fw_maths_modinv_even_l3072_output_t maths_modinv_even_l3072; + + /** Modular multiplicative inverse for numbers less than 4096 bits */ + icp_qat_fw_maths_modinv_even_l4096_output_t maths_modinv_even_l4096; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_1024_160_output_t mmp_dsa_gen_p_1024_160; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_1024_output_t mmp_dsa_gen_g_1024; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_1024_output_t mmp_dsa_gen_y_1024; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_1024_160_output_t mmp_dsa_sign_r_1024_160; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_160_output_t mmp_dsa_sign_s_160; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t mmp_dsa_sign_r_s_1024_160; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_1024_160_output_t mmp_dsa_verify_1024_160; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_2048_224_output_t mmp_dsa_gen_p_2048_224; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_2048_output_t mmp_dsa_gen_y_2048; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_2048_224_output_t mmp_dsa_sign_r_2048_224; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_224_output_t mmp_dsa_sign_s_224; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t mmp_dsa_sign_r_s_2048_224; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_2048_224_output_t mmp_dsa_verify_2048_224; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_2048_256_output_t mmp_dsa_gen_p_2048_256; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_2048_output_t mmp_dsa_gen_g_2048; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_2048_256_output_t mmp_dsa_sign_r_2048_256; + + /** DSA Sign S */ + icp_qat_fw_mmp_dsa_sign_s_256_output_t mmp_dsa_sign_s_256; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t mmp_dsa_sign_r_s_2048_256; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_2048_256_output_t mmp_dsa_verify_2048_256; + + /** DSA parameter generation P */ + icp_qat_fw_mmp_dsa_gen_p_3072_256_output_t mmp_dsa_gen_p_3072_256; + + /** DSA key generation G */ + icp_qat_fw_mmp_dsa_gen_g_3072_output_t mmp_dsa_gen_g_3072; + + /** DSA key generation Y */ + icp_qat_fw_mmp_dsa_gen_y_3072_output_t mmp_dsa_gen_y_3072; + + /** DSA Sign R */ + icp_qat_fw_mmp_dsa_sign_r_3072_256_output_t mmp_dsa_sign_r_3072_256; + + /** DSA Sign R S */ + icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t mmp_dsa_sign_r_s_3072_256; + + /** DSA Verify */ + icp_qat_fw_mmp_dsa_verify_3072_256_output_t mmp_dsa_verify_3072_256; + + /** ECDSA Sign RS for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_t + mmp_ecdsa_sign_rs_gf2_l256; + + /** ECDSA Sign R for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_t mmp_ecdsa_sign_r_gf2_l256; + + /** ECDSA Sign S for curves with n < 2^256 */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_t mmp_ecdsa_sign_s_gf2_l256; + + /** ECDSA Verify for curves B/K-163 and B/K-233 */ + icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_t mmp_ecdsa_verify_gf2_l256; + + /** ECDSA Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_t + mmp_ecdsa_sign_rs_gf2_l512; + + /** ECDSA GF2 Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_t mmp_ecdsa_sign_r_gf2_l512; + + /** ECDSA GF2 Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_t mmp_ecdsa_sign_s_gf2_l512; + + /** ECDSA GF2 Verify */ + icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_t mmp_ecdsa_verify_gf2_l512; + + /** ECDSA GF2 Sign RS for curves B-571/K-571 */ + icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_t mmp_ecdsa_sign_rs_gf2_571; + + /** ECDSA GF2 Sign S for curves with deg(q) < 576 */ + icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_t mmp_ecdsa_sign_s_gf2_571; + + /** ECDSA GF2 Sign R for degree 571 */ + icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_t mmp_ecdsa_sign_r_gf2_571; + + /** ECDSA GF2 Verify for degree 571 */ + icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_t mmp_ecdsa_verify_gf2_571; + + /** MATHS GF2 Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gf2_l256_output_t + maths_point_multiplication_gf2_l256; + + /** MATHS GF2 Point Verification */ + icp_qat_fw_maths_point_verify_gf2_l256_output_t + maths_point_verify_gf2_l256; + + /** MATHS GF2 Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gf2_l512_output_t + maths_point_multiplication_gf2_l512; + + /** MATHS GF2 Point Verification */ + icp_qat_fw_maths_point_verify_gf2_l512_output_t + maths_point_verify_gf2_l512; + + /** ECC GF2 Point Multiplication for curves B-571/K-571 */ + icp_qat_fw_maths_point_multiplication_gf2_571_output_t + maths_point_multiplication_gf2_571; + + /** ECC GF2 Point Verification for degree 571 */ + icp_qat_fw_maths_point_verify_gf2_571_output_t + maths_point_verify_gf2_571; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_t mmp_ecdsa_sign_r_gfp_l256; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_t mmp_ecdsa_sign_s_gfp_l256; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_t + mmp_ecdsa_sign_rs_gfp_l256; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_t mmp_ecdsa_verify_gfp_l256; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_t mmp_ecdsa_sign_r_gfp_l512; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_t mmp_ecdsa_sign_s_gfp_l512; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_t + mmp_ecdsa_sign_rs_gfp_l512; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_t mmp_ecdsa_verify_gfp_l512; + + /** ECDSA GFP Sign R */ + icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_t mmp_ecdsa_sign_r_gfp_521; + + /** ECDSA GFP Sign S */ + icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_t mmp_ecdsa_sign_s_gfp_521; + + /** ECDSA GFP Sign RS */ + icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_t mmp_ecdsa_sign_rs_gfp_521; + + /** ECDSA GFP Verify */ + icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_t mmp_ecdsa_verify_gfp_521; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_l256_output_t + maths_point_multiplication_gfp_l256; + + /** ECC GFP Partial Point Verification */ + icp_qat_fw_maths_point_verify_gfp_l256_output_t + maths_point_verify_gfp_l256; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_l512_output_t + maths_point_multiplication_gfp_l512; + + /** ECC GFP Partial Point */ + icp_qat_fw_maths_point_verify_gfp_l512_output_t + maths_point_verify_gfp_l512; + + /** ECC GFP Point Multiplication */ + icp_qat_fw_maths_point_multiplication_gfp_521_output_t + maths_point_multiplication_gfp_521; + + /** ECC GFP Partial Point Verification */ + icp_qat_fw_maths_point_verify_gfp_521_output_t + maths_point_verify_gfp_521; + + /** ECC curve25519 Variable Point Multiplication [k]P(x), as specified + * in RFC7748 */ + icp_qat_fw_point_multiplication_c25519_output_t + point_multiplication_c25519; + + /** ECC curve25519 Generator Point Multiplication [k]G(x), as specified + * in RFC7748 */ + icp_qat_fw_generator_multiplication_c25519_output_t + generator_multiplication_c25519; + + /** ECC edwards25519 Variable Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_point_multiplication_ed25519_output_t + point_multiplication_ed25519; + + /** ECC edwards25519 Generator Point Multiplication [k]G, as specified + * in RFC8032 */ + icp_qat_fw_generator_multiplication_ed25519_output_t + generator_multiplication_ed25519; + + /** ECC curve448 Variable Point Multiplication [k]P(x), as specified in + * RFC7748 */ + icp_qat_fw_point_multiplication_c448_output_t point_multiplication_c448; + + /** ECC curve448 Generator Point Multiplication [k]G(x), as specified in + * RFC7748 */ + icp_qat_fw_generator_multiplication_c448_output_t + generator_multiplication_c448; + + /** ECC edwards448 Variable Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_point_multiplication_ed448_output_t + point_multiplication_ed448; + + /** ECC edwards448 Generator Point Multiplication [k]P, as specified in + * RFC8032 */ + icp_qat_fw_generator_multiplication_ed448_output_t + generator_multiplication_ed448; +} icp_qat_fw_mmp_output_param_t; + +#endif /* __ICP_QAT_FW_MMP__ */ + +/* --- (Automatically generated (build v. 2.7), do not modify manually) --- */ + +/* --- end of file --- */ diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp_ids.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp_ids.h new file mode 100644 index 00000000000..9ccccc22145 --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_mmp_ids.h @@ -0,0 +1,1555 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + * @file icp_qat_fw_mmp_ids.h + * @ingroup icp_qat_fw_mmp + * $Revision: 0.1 $ + * @brief + * This file documents the external interfaces that the QAT FW running + * on the QAT Acceleration Engine provides to clients wanting to + * accelerate crypto assymetric applications + */ + +#ifndef __ICP_QAT_FW_MMP_IDS__ +#define __ICP_QAT_FW_MMP_IDS__ + +#define PKE_INIT 0x09061798 +/**< Functionality ID for Initialisation sequence + * @li 1 input parameters : @link icp_qat_fw_mmp_init_input_s::z z @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_init_output_s::zz zz @endlink + */ +#define PKE_DH_G2_768 0x1c0b1a10 +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 768-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_768_input_s::e e @endlink + * @link icp_qat_fw_mmp_dh_g2_768_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_768_output_s::r r + * @endlink + */ +#define PKE_DH_768 0x210c1a1b +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 768-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_768_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_768_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_768_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_768_output_s::r r @endlink + */ +#define PKE_DH_G2_1024 0x220b1a27 +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 1024-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_1024_input_s::e e + * @endlink @link icp_qat_fw_mmp_dh_g2_1024_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_1024_output_s::r r + * @endlink + */ +#define PKE_DH_1024 0x290c1a32 +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 1024-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_1024_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_1024_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_1024_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_1024_output_s::r r @endlink + */ +#define PKE_DH_G2_1536 0x2e0b1a3e +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 1536-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_1536_input_s::e e + * @endlink @link icp_qat_fw_mmp_dh_g2_1536_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_1536_output_s::r r + * @endlink + */ +#define PKE_DH_1536 0x390c1a49 +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 1536-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_1536_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_1536_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_1536_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_1536_output_s::r r @endlink + */ +#define PKE_DH_G2_2048 0x3e0b1a55 +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 2048-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_2048_input_s::e e + * @endlink @link icp_qat_fw_mmp_dh_g2_2048_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_2048_output_s::r r + * @endlink + */ +#define PKE_DH_2048 0x4d0c1a60 +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 2048-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_2048_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_2048_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_2048_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_2048_output_s::r r @endlink + */ +#define PKE_DH_G2_3072 0x3a0b1a6c +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 3072-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_3072_input_s::e e + * @endlink @link icp_qat_fw_mmp_dh_g2_3072_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_3072_output_s::r r + * @endlink + */ +#define PKE_DH_3072 0x510c1a77 +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 3072-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_3072_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_3072_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_3072_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_3072_output_s::r r @endlink + */ +#define PKE_DH_G2_4096 0x4a0b1a83 +/**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for + * 4096-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_4096_input_s::e e + * @endlink @link icp_qat_fw_mmp_dh_g2_4096_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_4096_output_s::r r + * @endlink + */ +#define PKE_DH_4096 0x690c1a8e +/**< Functionality ID for Diffie-Hellman Modular exponentiation for 4096-bit + * numbers + * @li 3 input parameters : @link icp_qat_fw_mmp_dh_4096_input_s::g g @endlink + * @link icp_qat_fw_mmp_dh_4096_input_s::e e @endlink @link + * icp_qat_fw_mmp_dh_4096_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dh_4096_output_s::r r @endlink + */ +#define PKE_RSA_KP1_512 0x191d1a9a +/**< Functionality ID for RSA 512 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_512_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_512_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_512_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_512_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_512_output_s::d d @endlink + */ +#define PKE_RSA_KP2_512 0x19401acc +/**< Functionality ID for RSA 512 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_512_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_512_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_512_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_512_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_512_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_512_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_512_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_512_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_512 0x1c161b21 +/**< Functionality ID for RSA 512 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_512_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_512_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_512_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_512_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_512 0x1c161b3c +/**< Functionality ID for RSA 512 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_512_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_512_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_512_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_512_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_512 0x1c131b57 +/**< Functionality ID for RSA 1024 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_512_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_512_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_512_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_512_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_512_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_512_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_512_output_s::m m + * @endlink + */ +#define PKE_RSA_KP1_1024 0x36181b71 +/**< Functionality ID for RSA 1024 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_1024_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_1024_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_1024_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_1024_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_1024_output_s::d d @endlink + */ +#define PKE_RSA_KP2_1024 0x40451b9e +/**< Functionality ID for RSA 1024 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_1024_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_1024_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1024_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1024_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1024_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1024_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_1024 0x35111bf7 +/**< Functionality ID for RSA 1024 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_1024_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_1024_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_1024_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_1024_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_1024 0x35111c12 +/**< Functionality ID for RSA 1024 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_1024_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_1024_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_1024_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_1024_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_1024 0x26131c2d +/**< Functionality ID for RSA 1024 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1024_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1024_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1024_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1024_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_1024_output_s::m m + * @endlink + */ +#define PKE_RSA_KP1_1536 0x531d1c46 +/**< Functionality ID for RSA 1536 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_1536_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_1536_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_1536_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_1536_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_1536_output_s::d d @endlink + */ +#define PKE_RSA_KP2_1536 0x32391c78 +/**< Functionality ID for RSA 1536 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_1536_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_1536_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1536_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1536_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1536_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_1536_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_1536 0x4d111cdc +/**< Functionality ID for RSA 1536 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_1536_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_1536_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_1536_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_1536_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_1536 0x4d111cf7 +/**< Functionality ID for RSA 1536 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_1536_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_1536_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_1536_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_1536_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_1536 0x45111d12 +/**< Functionality ID for RSA 1536 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1536_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1536_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1536_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_1536_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_1536_output_s::m m + * @endlink + */ +#define PKE_RSA_KP1_2048 0x72181d2e +/**< Functionality ID for RSA 2048 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_2048_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_2048_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_2048_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_2048_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_2048_output_s::d d @endlink + */ +#define PKE_RSA_KP2_2048 0x42341d5b +/**< Functionality ID for RSA 2048 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_2048_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_2048_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_2048_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_2048_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_2048_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_2048_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_2048 0x6e111dba +/**< Functionality ID for RSA 2048 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_2048_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_2048_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_2048_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_2048_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_2048 0x6e111dda +/**< Functionality ID for RSA 2048 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_2048_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_2048_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_2048_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_2048_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_2048 0x59121dfa +/**< Functionality ID for RSA 2048 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_2048_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_2048_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_2048_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_2048_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_2048_output_s::m m + * @endlink + */ +#define PKE_RSA_KP1_3072 0x60191e16 +/**< Functionality ID for RSA 3072 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_3072_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_3072_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_3072_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_3072_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_3072_output_s::d d @endlink + */ +#define PKE_RSA_KP2_3072 0x68331e45 +/**< Functionality ID for RSA 3072 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_3072_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_3072_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_3072_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_3072_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_3072_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_3072_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_3072 0x7d111ea3 +/**< Functionality ID for RSA 3072 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_3072_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_3072_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_3072_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_3072_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_3072 0x7d111ebe +/**< Functionality ID for RSA 3072 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_3072_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_3072_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_3072_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_3072_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_3072 0x81121ed9 +/**< Functionality ID for RSA 3072 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_3072_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_3072_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_3072_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_3072_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_3072_output_s::m m + * @endlink + */ +#define PKE_RSA_KP1_4096 0x7d1f1ef6 +/**< Functionality ID for RSA 4096 key generation first form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp1_4096_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp1_4096_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp1_4096_input_s::e e @endlink + * @li 2 output parameters : @link icp_qat_fw_mmp_rsa_kp1_4096_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp1_4096_output_s::d d @endlink + */ +#define PKE_RSA_KP2_4096 0x91251f27 +/**< Functionality ID for RSA 4096 key generation second form + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_kp2_4096_input_s::p p + * @endlink @link icp_qat_fw_mmp_rsa_kp2_4096_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_kp2_4096_input_s::e e @endlink + * @li 5 output parameters : @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::n n + * @endlink @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_kp2_4096_output_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_kp2_4096_output_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_kp2_4096_output_s::qinv qinv @endlink + */ +#define PKE_RSA_EP_4096 0xa5101f7e +/**< Functionality ID for RSA 4096 Encryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_4096_input_s::m m + * @endlink @link icp_qat_fw_mmp_rsa_ep_4096_input_s::e e @endlink @link + * icp_qat_fw_mmp_rsa_ep_4096_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_4096_output_s::c c + * @endlink + */ +#define PKE_RSA_DP1_4096 0xa5101f98 +/**< Functionality ID for RSA 4096 Decryption + * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_4096_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp1_4096_input_s::d d @endlink @link + * icp_qat_fw_mmp_rsa_dp1_4096_input_s::n n @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_4096_output_s::m m + * @endlink + */ +#define PKE_RSA_DP2_4096 0xb1111fb2 +/**< Functionality ID for RSA 4096 Decryption with CRT + * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::c c + * @endlink @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::p p @endlink @link + * icp_qat_fw_mmp_rsa_dp2_4096_input_s::q q @endlink @link + * icp_qat_fw_mmp_rsa_dp2_4096_input_s::dp dp @endlink @link + * icp_qat_fw_mmp_rsa_dp2_4096_input_s::dq dq @endlink @link + * icp_qat_fw_mmp_rsa_dp2_4096_input_s::qinv qinv @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_4096_output_s::m m + * @endlink + */ +#define PKE_GCD_PT_192 0x19201fcd +/**< Functionality ID for GCD primality test for 192-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_192_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_256 0x19201ff7 +/**< Functionality ID for GCD primality test for 256-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_256_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_384 0x19202021 +/**< Functionality ID for GCD primality test for 384-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_384_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_512 0x1b1b204b +/**< Functionality ID for GCD primality test for 512-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_512_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_768 0x170c2070 +/**< Functionality ID for GCD primality test for 768-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_768_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_1024 0x130f2085 +/**< Functionality ID for GCD primality test for 1024-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_1024_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_1536 0x1d0c2094 +/**< Functionality ID for GCD primality test for 1536-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_1536_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_2048 0x210c20a5 +/**< Functionality ID for GCD primality test for 2048-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_2048_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_3072 0x290c20b6 +/**< Functionality ID for GCD primality test for 3072-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_3072_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_GCD_PT_4096 0x310c20c7 +/**< Functionality ID for GCD primality test for 4096-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_gcd_pt_4096_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_160 0x0e1120d8 +/**< Functionality ID for Fermat primality test for 160-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_160_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_512 0x121120ee +/**< Functionality ID for Fermat primality test for 512-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_512_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_L512 0x19162104 +/**< Functionality ID for Fermat primality test for <e; 512-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_l512_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_768 0x19112124 +/**< Functionality ID for Fermat primality test for 768-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_768_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_1024 0x1f11213a +/**< Functionality ID for Fermat primality test for 1024-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_1024_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_1536 0x2b112150 +/**< Functionality ID for Fermat primality test for 1536-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_1536_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_2048 0x3b112166 +/**< Functionality ID for Fermat primality test for 2048-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_2048_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_3072 0x3a11217c +/**< Functionality ID for Fermat primality test for 3072-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_3072_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_FERMAT_PT_4096 0x4a112192 +/**< Functionality ID for Fermat primality test for 4096-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_fermat_pt_4096_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_MR_PT_160 0x0e1221a8 +/**< Functionality ID for Miller-Rabin primality test for 160-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_160_input_s::x x @endlink + * @link icp_qat_fw_mmp_mr_pt_160_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_512 0x111221bf +/**< Functionality ID for Miller-Rabin primality test for 512-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_512_input_s::x x @endlink + * @link icp_qat_fw_mmp_mr_pt_512_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_768 0x1d0d21d6 +/**< Functionality ID for Miller-Rabin primality test for 768-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_768_input_s::x x @endlink + * @link icp_qat_fw_mmp_mr_pt_768_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_1024 0x250d21ed +/**< Functionality ID for Miller-Rabin primality test for 1024-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_1024_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_1024_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_1536 0x350d2204 +/**< Functionality ID for Miller-Rabin primality test for 1536-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_1536_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_1536_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_2048 0x490d221b +/**< Functionality ID for Miller-Rabin primality test for 2048-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_2048_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_2048_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_3072 0x4d0d2232 +/**< Functionality ID for Miller-Rabin primality test for 3072-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_3072_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_3072_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_4096 0x650d2249 +/**< Functionality ID for Miller-Rabin primality test for 4096-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_4096_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_4096_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_MR_PT_L512 0x18182260 +/**< Functionality ID for Miller-Rabin primality test for 512-bit numbers + * @li 2 input parameters : @link icp_qat_fw_mmp_mr_pt_l512_input_s::x x + * @endlink @link icp_qat_fw_mmp_mr_pt_l512_input_s::m m @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_160 0x0e0c227e +/**< Functionality ID for Lucas primality test for 160-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_160_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_512 0x110c228f +/**< Functionality ID for Lucas primality test for 512-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_512_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_768 0x130c22a0 +/**< Functionality ID for Lucas primality test for 768-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_768_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_1024 0x150c22b1 +/**< Functionality ID for Lucas primality test for 1024-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_1024_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_1536 0x190c22c2 +/**< Functionality ID for Lucas primality test for 1536-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_1536_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_2048 0x1d0c22d3 +/**< Functionality ID for Lucas primality test for 2048-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_2048_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_3072 0x250c22e4 +/**< Functionality ID for Lucas primality test for 3072-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_3072_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_4096 0x661522f5 +/**< Functionality ID for Lucas primality test for 4096-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_4096_input_s::m m + * @endlink + * @li no output parameters + */ +#define PKE_LUCAS_PT_L512 0x1617230a +/**< Functionality ID for Lucas primality test for L512-bit numbers + * @li 1 input parameters : @link icp_qat_fw_mmp_lucas_pt_l512_input_s::m m + * @endlink + * @li no output parameters + */ +#define MATHS_MODEXP_L512 0x150c2327 +/**< Functionality ID for Modular exponentiation for numbers less than 512-bits + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l512_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l512_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l512_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l512_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L1024 0x2d0c233e +/**< Functionality ID for Modular exponentiation for numbers less than 1024-bit + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l1024_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l1024_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l1024_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l1024_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L1536 0x410c2355 +/**< Functionality ID for Modular exponentiation for numbers less than 1536-bits + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l1536_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l1536_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l1536_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l1536_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L2048 0x5e12236c +/**< Functionality ID for Modular exponentiation for numbers less than 2048-bit + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l2048_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l2048_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l2048_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l2048_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L2560 0x60162388 +/**< Functionality ID for Modular exponentiation for numbers less than 2560-bits + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l2560_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l2560_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l2560_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l2560_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L3072 0x650c23a9 +/**< Functionality ID for Modular exponentiation for numbers less than 3072-bits + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l3072_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l3072_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l3072_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l3072_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L3584 0x801623c0 +/**< Functionality ID for Modular exponentiation for numbers less than 3584-bits + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l3584_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l3584_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l3584_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l3584_output_s::r r + * @endlink + */ +#define MATHS_MODEXP_L4096 0x850c23e1 +/**< Functionality ID for Modular exponentiation for numbers less than 4096-bit + * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l4096_input_s::g g + * @endlink @link icp_qat_fw_maths_modexp_l4096_input_s::e e @endlink @link + * icp_qat_fw_maths_modexp_l4096_input_s::m m @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l4096_output_s::r r + * @endlink + */ +#define MATHS_MODINV_ODD_L128 0x090623f8 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 128 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l128_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l128_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l128_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L192 0x0a0623fe +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 192 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l192_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l192_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l192_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L256 0x0a062404 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 256 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l256_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l256_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l256_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L384 0x0b06240a +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 384 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l384_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l384_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l384_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L512 0x0c062410 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 512 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l512_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l512_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l512_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L768 0x0e062416 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 768 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l768_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l768_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l768_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L1024 0x1006241c +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 1024 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l1024_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l1024_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l1024_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L1536 0x18062422 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 1536 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l1536_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l1536_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l1536_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L2048 0x20062428 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 2048 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l2048_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l2048_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l2048_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L3072 0x3006242e +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 3072 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l3072_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l3072_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l3072_output_s::c + * c @endlink + */ +#define MATHS_MODINV_ODD_L4096 0x40062434 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 4096 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l4096_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_odd_l4096_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l4096_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L128 0x0906243a +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 128 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l128_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l128_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l128_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L192 0x0a062440 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 192 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l192_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l192_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l192_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L256 0x0a062446 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 256 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l256_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l256_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l256_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L384 0x0e0b244c +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 384 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l384_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l384_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l384_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L512 0x110b2457 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 512 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l512_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l512_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l512_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L768 0x170b2462 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 768 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l768_input_s::a a + * @endlink @link icp_qat_fw_maths_modinv_even_l768_input_s::b b @endlink + * @li 1 output parameters : @link icp_qat_fw_maths_modinv_even_l768_output_s::c + * c @endlink + */ +#define MATHS_MODINV_EVEN_L1024 0x1d0b246d +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 1024 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l1024_input_s::a + * a @endlink @link icp_qat_fw_maths_modinv_even_l1024_input_s::b b @endlink + * @li 1 output parameters : @link + * icp_qat_fw_maths_modinv_even_l1024_output_s::c c @endlink + */ +#define MATHS_MODINV_EVEN_L1536 0x290b2478 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 1536 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l1536_input_s::a + * a @endlink @link icp_qat_fw_maths_modinv_even_l1536_input_s::b b @endlink + * @li 1 output parameters : @link + * icp_qat_fw_maths_modinv_even_l1536_output_s::c c @endlink + */ +#define MATHS_MODINV_EVEN_L2048 0x350b2483 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 2048 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l2048_input_s::a + * a @endlink @link icp_qat_fw_maths_modinv_even_l2048_input_s::b b @endlink + * @li 1 output parameters : @link + * icp_qat_fw_maths_modinv_even_l2048_output_s::c c @endlink + */ +#define MATHS_MODINV_EVEN_L3072 0x4d0b248e +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 3072 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l3072_input_s::a + * a @endlink @link icp_qat_fw_maths_modinv_even_l3072_input_s::b b @endlink + * @li 1 output parameters : @link + * icp_qat_fw_maths_modinv_even_l3072_output_s::c c @endlink + */ +#define MATHS_MODINV_EVEN_L4096 0x650b2499 +/**< Functionality ID for Modular multiplicative inverse for numbers less than + * 4096 bits + * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l4096_input_s::a + * a @endlink @link icp_qat_fw_maths_modinv_even_l4096_input_s::b b @endlink + * @li 1 output parameters : @link + * icp_qat_fw_maths_modinv_even_l4096_output_s::c c @endlink + */ +#define PKE_DSA_GEN_P_1024_160 0x381824a4 +/**< Functionality ID for DSA parameter generation P + * @li 2 input parameters : @link icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s::x x + * @endlink @link icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s::q q @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_p_1024_160_output_s::p + * p @endlink + */ +#define PKE_DSA_GEN_G_1024 0x261424d4 +/**< Functionality ID for DSA key generation G + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_g_1024_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_g_1024_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_gen_g_1024_input_s::h h @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_g_1024_output_s::g g + * @endlink + */ +#define PKE_DSA_GEN_Y_1024 0x291224ed +/**< Functionality ID for DSA key generation Y + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_y_1024_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_y_1024_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_gen_y_1024_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_y_1024_output_s::y y + * @endlink + */ +#define PKE_DSA_SIGN_R_1024_160 0x2c1c2504 +/**< Functionality ID for DSA Sign R + * @li 4 input parameters : @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::k + * k @endlink @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::p p @endlink + * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::g g @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_1024_160_output_s::r r @endlink + */ +#define PKE_DSA_SIGN_S_160 0x12142526 +/**< Functionality ID for DSA Sign S + * @li 5 input parameters : @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::m m + * @endlink @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_160_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_160_input_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_160_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_sign_s_160_output_s::s s + * @endlink + */ +#define PKE_DSA_SIGN_R_S_1024_160 0x301e2540 +/**< Functionality ID for DSA Sign R S + * @li 6 input parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::x x @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s::s s @endlink + */ +#define PKE_DSA_VERIFY_1024_160 0x323a2570 +/**< Functionality ID for DSA Verify + * @li 7 input parameters : @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::r + * r @endlink @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::s s @endlink + * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_verify_1024_160_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_verify_1024_160_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_verify_1024_160_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_verify_1024_160_input_s::y y @endlink + * @li no output parameters + */ +#define PKE_DSA_GEN_P_2048_224 0x341d25be +/**< Functionality ID for DSA parameter generation P + * @li 2 input parameters : @link icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s::x x + * @endlink @link icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s::q q @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_p_2048_224_output_s::p + * p @endlink + */ +#define PKE_DSA_GEN_Y_2048 0x4d1225ea +/**< Functionality ID for DSA key generation Y + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_y_2048_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_y_2048_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_gen_y_2048_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_y_2048_output_s::y y + * @endlink + */ +#define PKE_DSA_SIGN_R_2048_224 0x511c2601 +/**< Functionality ID for DSA Sign R + * @li 4 input parameters : @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::k + * k @endlink @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::p p @endlink + * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::g g @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_2048_224_output_s::r r @endlink + */ +#define PKE_DSA_SIGN_S_224 0x15142623 +/**< Functionality ID for DSA Sign S + * @li 5 input parameters : @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::m m + * @endlink @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_224_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_224_input_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_224_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_sign_s_224_output_s::s s + * @endlink + */ +#define PKE_DSA_SIGN_R_S_2048_224 0x571e263d +/**< Functionality ID for DSA Sign R S + * @li 6 input parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::x x @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s::s s @endlink + */ +#define PKE_DSA_VERIFY_2048_224 0x6930266d +/**< Functionality ID for DSA Verify + * @li 7 input parameters : @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::r + * r @endlink @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::s s @endlink + * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_224_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_224_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_224_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_224_input_s::y y @endlink + * @li no output parameters + */ +#define PKE_DSA_GEN_P_2048_256 0x431126b7 +/**< Functionality ID for DSA parameter generation P + * @li 2 input parameters : @link icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s::x x + * @endlink @link icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s::q q @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_p_2048_256_output_s::p + * p @endlink + */ +#define PKE_DSA_GEN_G_2048 0x4b1426ed +/**< Functionality ID for DSA key generation G + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_g_2048_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_g_2048_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_gen_g_2048_input_s::h h @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_g_2048_output_s::g g + * @endlink + */ +#define PKE_DSA_SIGN_R_2048_256 0x5b182706 +/**< Functionality ID for DSA Sign R + * @li 4 input parameters : @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::k + * k @endlink @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::p p @endlink + * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::g g @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_2048_256_output_s::r r @endlink + */ +#define PKE_DSA_SIGN_S_256 0x15142733 +/**< Functionality ID for DSA Sign S + * @li 5 input parameters : @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::m m + * @endlink @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_256_input_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_s_256_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_sign_s_256_output_s::s s + * @endlink + */ +#define PKE_DSA_SIGN_R_S_2048_256 0x5a2a274d +/**< Functionality ID for DSA Sign R S + * @li 6 input parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::x x @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s::s s @endlink + */ +#define PKE_DSA_VERIFY_2048_256 0x723a2789 +/**< Functionality ID for DSA Verify + * @li 7 input parameters : @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::r + * r @endlink @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::s s @endlink + * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_256_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_256_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_verify_2048_256_input_s::y y @endlink + * @li no output parameters + */ +#define PKE_DSA_GEN_P_3072_256 0x4b1127e0 +/**< Functionality ID for DSA parameter generation P + * @li 2 input parameters : @link icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s::x x + * @endlink @link icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s::q q @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_p_3072_256_output_s::p + * p @endlink + */ +#define PKE_DSA_GEN_G_3072 0x4f142816 +/**< Functionality ID for DSA key generation G + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_g_3072_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_g_3072_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_gen_g_3072_input_s::h h @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_g_3072_output_s::g g + * @endlink + */ +#define PKE_DSA_GEN_Y_3072 0x5112282f +/**< Functionality ID for DSA key generation Y + * @li 3 input parameters : @link icp_qat_fw_mmp_dsa_gen_y_3072_input_s::p p + * @endlink @link icp_qat_fw_mmp_dsa_gen_y_3072_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_gen_y_3072_input_s::x x @endlink + * @li 1 output parameters : @link icp_qat_fw_mmp_dsa_gen_y_3072_output_s::y y + * @endlink + */ +#define PKE_DSA_SIGN_R_3072_256 0x59282846 +/**< Functionality ID for DSA Sign R + * @li 4 input parameters : @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::k + * k @endlink @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::p p @endlink + * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::g g @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_3072_256_output_s::r r @endlink + */ +#define PKE_DSA_SIGN_R_S_3072_256 0x61292874 +/**< Functionality ID for DSA Sign R S + * @li 6 input parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::k k @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::x x @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s::r r @endlink @link + * icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s::s s @endlink + */ +#define PKE_DSA_VERIFY_3072_256 0x7f4328ae +/**< Functionality ID for DSA Verify + * @li 7 input parameters : @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::r + * r @endlink @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::s s @endlink + * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::m m @endlink @link + * icp_qat_fw_mmp_dsa_verify_3072_256_input_s::p p @endlink @link + * icp_qat_fw_mmp_dsa_verify_3072_256_input_s::q q @endlink @link + * icp_qat_fw_mmp_dsa_verify_3072_256_input_s::g g @endlink @link + * icp_qat_fw_mmp_dsa_verify_3072_256_input_s::y y @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_RS_GF2_L256 0x46512907 +/**< Functionality ID for ECDSA Sign RS for curves B/K-163 and B/K-233 + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_R_GF2_L256 0x323a298f +/**< Functionality ID for ECDSA Sign R for curves B/K-163 and B/K-233 + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_s::r r @endlink + */ +#define PKE_ECDSA_SIGN_S_GF2_L256 0x2b2229e6 +/**< Functionality ID for ECDSA Sign S for curves with n < 2^256 + * @li 5 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::e e @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::d d @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_s::s s @endlink + */ +#define PKE_ECDSA_VERIFY_GF2_L256 0x337e2a27 +/**< Functionality ID for ECDSA Verify for curves B/K-163 and B/K-233 + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_s::in in @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_RS_GF2_L512 0x5e5f2ad7 +/**< Functionality ID for ECDSA Sign RS + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_R_GF2_L512 0x84312b6a +/**< Functionality ID for ECDSA GF2 Sign R + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_s::r r @endlink + */ +#define PKE_ECDSA_SIGN_S_GF2_L512 0x26182bbe +/**< Functionality ID for ECDSA GF2 Sign S + * @li 5 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::e e @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::d d @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_s::s s @endlink + */ +#define PKE_ECDSA_VERIFY_GF2_L512 0x58892bea +/**< Functionality ID for ECDSA GF2 Verify + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_s::in in @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_RS_GF2_571 0x554a2c93 +/**< Functionality ID for ECDSA GF2 Sign RS for curves B-571/K-571 + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_S_GF2_571 0x52332d09 +/**< Functionality ID for ECDSA GF2 Sign S for curves with deg(q) < 576 + * @li 5 input parameters : @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::e + * e @endlink @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::d d @endlink + * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_R_GF2_571 0x731a2d51 +/**< Functionality ID for ECDSA GF2 Sign R for degree 571 + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_s::r r @endlink + */ +#define PKE_ECDSA_VERIFY_GF2_571 0x4f6c2d91 +/**< Functionality ID for ECDSA GF2 Verify for degree 571 + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_s::in in @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GF2_L256 0x3b242e38 +/**< Functionality ID for MATHS GF2 Point Multiplication + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l256_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GF2_L256 0x231a2e7c +/**< Functionality ID for MATHS GF2 Point Verification + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gf2_l256_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l256_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l256_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l256_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l256_input_s::b b @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GF2_L512 0x722c2e96 +/**< Functionality ID for MATHS GF2 Point Multiplication + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_l512_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GF2_L512 0x25132ee2 +/**< Functionality ID for MATHS GF2 Point Verification + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gf2_l512_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l512_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l512_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l512_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gf2_l512_input_s::b b @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GF2_571 0x44152ef5 +/**< Functionality ID for ECC GF2 Point Multiplication for curves B-571/K-571 + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gf2_571_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gf2_571_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GF2_571 0x12072f1b +/**< Functionality ID for ECC GF2 Point Verification for degree 571 + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gf2_571_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_571_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gf2_571_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gf2_571_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gf2_571_input_s::b b @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_R_GFP_L256 0x431b2f22 +/**< Functionality ID for ECDSA GFP Sign R + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_s::r r @endlink + */ +#define PKE_ECDSA_SIGN_S_GFP_L256 0x2b252f6d +/**< Functionality ID for ECDSA GFP Sign S + * @li 5 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::e e @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::d d @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_RS_GFP_L256 0x6a3c2fa6 +/**< Functionality ID for ECDSA GFP Sign RS + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s::s s @endlink + */ +#define PKE_ECDSA_VERIFY_GFP_L256 0x325b3023 +/**< Functionality ID for ECDSA GFP Verify + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_s::in in @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_R_GFP_L512 0x4e2530b3 +/**< Functionality ID for ECDSA GFP Sign R + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_s::r r @endlink + */ +#define PKE_ECDSA_SIGN_S_GFP_L512 0x251830fa +/**< Functionality ID for ECDSA GFP Sign S + * @li 5 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::e e @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::d d @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_RS_GFP_L512 0x5a2b3127 +/**< Functionality ID for ECDSA GFP Sign RS + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s::s s @endlink + */ +#define PKE_ECDSA_VERIFY_GFP_L512 0x3553318a +/**< Functionality ID for ECDSA GFP Verify + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_s::in in @endlink + * @li no output parameters + */ +#define PKE_ECDSA_SIGN_R_GFP_521 0x772c31fe +/**< Functionality ID for ECDSA GFP Sign R + * @li 7 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::xg xg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::yg yg @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::n n @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::q q @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::a a @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::b b @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_s::r r @endlink + */ +#define PKE_ECDSA_SIGN_S_GFP_521 0x52343251 +/**< Functionality ID for ECDSA GFP Sign S + * @li 5 input parameters : @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::e + * e @endlink @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::d d @endlink + * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::k k @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::n n @endlink + * @li 1 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_s::s s @endlink + */ +#define PKE_ECDSA_SIGN_RS_GFP_521 0x494a329b +/**< Functionality ID for ECDSA GFP Sign RS + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_s::in in @endlink + * @li 2 output parameters : @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s::r r @endlink @link + * icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s::s s @endlink + */ +#define PKE_ECDSA_VERIFY_GFP_521 0x554c331f +/**< Functionality ID for ECDSA GFP Verify + * @li 1 input parameters : @link + * icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_s::in in @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GFP_L256 0x432033a6 +/**< Functionality ID for ECC GFP Point Multiplication + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l256_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GFP_L256 0x1f0c33fc +/**< Functionality ID for ECC GFP Partial Point Verification + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gfp_l256_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l256_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l256_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l256_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l256_input_s::b b @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GFP_L512 0x41253419 +/**< Functionality ID for ECC GFP Point Multiplication + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_l512_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GFP_L512 0x2612345c +/**< Functionality ID for ECC GFP Partial Point + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gfp_l512_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l512_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l512_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l512_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gfp_l512_input_s::b b @endlink + * @li no output parameters + */ +#define MATHS_POINT_MULTIPLICATION_GFP_521 0x5511346e +/**< Functionality ID for ECC GFP Point Multiplication + * @li 7 input parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::k k @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::xg xg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::yg yg @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::a a @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::b b @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::q q @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_input_s::h h @endlink + * @li 2 output parameters : @link + * icp_qat_fw_maths_point_multiplication_gfp_521_output_s::xk xk @endlink @link + * icp_qat_fw_maths_point_multiplication_gfp_521_output_s::yk yk @endlink + */ +#define MATHS_POINT_VERIFY_GFP_521 0x0e0734be +/**< Functionality ID for ECC GFP Partial Point Verification + * @li 5 input parameters : @link + * icp_qat_fw_maths_point_verify_gfp_521_input_s::xq xq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_521_input_s::yq yq @endlink @link + * icp_qat_fw_maths_point_verify_gfp_521_input_s::q q @endlink @link + * icp_qat_fw_maths_point_verify_gfp_521_input_s::a a @endlink @link + * icp_qat_fw_maths_point_verify_gfp_521_input_s::b b @endlink + * @li no output parameters + */ +#define POINT_MULTIPLICATION_C25519 0x0a0634c6 +/**< Functionality ID for ECC curve25519 Variable Point Multiplication [k]P(x), + * as specified in RFC7748 + * @li 2 input parameters : @link + * icp_qat_fw_point_multiplication_c25519_input_s::xp xp @endlink @link + * icp_qat_fw_point_multiplication_c25519_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_point_multiplication_c25519_output_s::xr xr @endlink + */ +#define GENERATOR_MULTIPLICATION_C25519 0x0a0634d6 +/**< Functionality ID for ECC curve25519 Generator Point Multiplication [k]G(x), + * as specified in RFC7748 + * @li 1 input parameters : @link + * icp_qat_fw_generator_multiplication_c25519_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_generator_multiplication_c25519_output_s::xr xr @endlink + */ +#define POINT_MULTIPLICATION_ED25519 0x100b34e6 +/**< Functionality ID for ECC edwards25519 Variable Point Multiplication [k]P, + * as specified in RFC8032 + * @li 3 input parameters : @link + * icp_qat_fw_point_multiplication_ed25519_input_s::xp xp @endlink @link + * icp_qat_fw_point_multiplication_ed25519_input_s::yp yp @endlink @link + * icp_qat_fw_point_multiplication_ed25519_input_s::k k @endlink + * @li 2 output parameters : @link + * icp_qat_fw_point_multiplication_ed25519_output_s::xr xr @endlink @link + * icp_qat_fw_point_multiplication_ed25519_output_s::yr yr @endlink + */ +#define GENERATOR_MULTIPLICATION_ED25519 0x100a34f6 +/**< Functionality ID for ECC edwards25519 Generator Point Multiplication [k]G, + * as specified in RFC8032 + * @li 1 input parameters : @link + * icp_qat_fw_generator_multiplication_ed25519_input_s::k k @endlink + * @li 2 output parameters : @link + * icp_qat_fw_generator_multiplication_ed25519_output_s::xr xr @endlink @link + * icp_qat_fw_generator_multiplication_ed25519_output_s::yr yr @endlink + */ +#define POINT_MULTIPLICATION_C448 0x0c063506 +/**< Functionality ID for ECC curve448 Variable Point Multiplication [k]P(x), as + * specified in RFC7748 + * @li 2 input parameters : @link + * icp_qat_fw_point_multiplication_c448_input_s::xp xp @endlink @link + * icp_qat_fw_point_multiplication_c448_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_point_multiplication_c448_output_s::xr xr @endlink + */ +#define GENERATOR_MULTIPLICATION_C448 0x0c063516 +/**< Functionality ID for ECC curve448 Generator Point Multiplication [k]G(x), + * as specified in RFC7748 + * @li 1 input parameters : @link + * icp_qat_fw_generator_multiplication_c448_input_s::k k @endlink + * @li 1 output parameters : @link + * icp_qat_fw_generator_multiplication_c448_output_s::xr xr @endlink + */ +#define POINT_MULTIPLICATION_ED448 0x1a0b3526 +/**< Functionality ID for ECC edwards448 Variable Point Multiplication [k]P, as + * specified in RFC8032 + * @li 3 input parameters : @link + * icp_qat_fw_point_multiplication_ed448_input_s::xp xp @endlink @link + * icp_qat_fw_point_multiplication_ed448_input_s::yp yp @endlink @link + * icp_qat_fw_point_multiplication_ed448_input_s::k k @endlink + * @li 2 output parameters : @link + * icp_qat_fw_point_multiplication_ed448_output_s::xr xr @endlink @link + * icp_qat_fw_point_multiplication_ed448_output_s::yr yr @endlink + */ +#define GENERATOR_MULTIPLICATION_ED448 0x1a0a3536 +/**< Functionality ID for ECC edwards448 Generator Point Multiplication [k]P, as + * specified in RFC8032 + * @li 1 input parameters : @link + * icp_qat_fw_generator_multiplication_ed448_input_s::k k @endlink + * @li 2 output parameters : @link + * icp_qat_fw_generator_multiplication_ed448_output_s::xr xr @endlink @link + * icp_qat_fw_generator_multiplication_ed448_output_s::yr yr @endlink + */ + +#define PKE_LIVENESS 0x00000001 +/**< Functionality ID for PKE_LIVENESS + * @li 0 input parameter(s) + * @li 1 output parameter(s) (8 qwords) + */ +#define PKE_INTERFACE_SIGNATURE 0x972ded54 +/**< Encoded signature of the interface specifications + */ + +#define PKE_INVALID_FUNC_ID 0xffffffff + +#endif /* __ICP_QAT_FW_MMP_IDS__ */ + +/* --- (Automatically generated (relocation v. 1.3), do not modify manually) --- + */ + +/* --- end of file --- */ diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_pke.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_pke.h new file mode 100644 index 00000000000..0f71bd15439 --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_fw_pke.h @@ -0,0 +1,418 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + * @file icp_qat_fw_pke.h + * @defgroup icp_qat_fw_pke ICP QAT FW PKE Processing Definitions + * @ingroup icp_qat_fw + * $Revision: 0.1 $ + * @brief + * This file documents the external interfaces that the QAT FW running + * on the QAT Acceleration Engine provides to clients wanting to + * accelerate crypto assymetric applications + */ + +#ifndef _ICP_QAT_FW_PKE_ +#define _ICP_QAT_FW_PKE_ + +/* +**************************************************************************** +* Include local header files +**************************************************************************** +*/ +#include "icp_qat_fw.h" + +/** + ***************************************************************************** + * + * @ingroup icp_qat_fw_pke + * + * @brief + * PKE response status field structure contained + * within LW1, comprising the common error codes and + * the response flags. + * + *****************************************************************************/ +typedef struct icp_qat_fw_pke_resp_status_s { + uint8_t comn_err_code; + /**< 8 bit common error code */ + + uint8_t pke_resp_flags; + /**< 8-bit PKE response flags */ + +} icp_qat_fw_pke_resp_status_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_pke + * Definition of the QAT FW PKE request header pars field. + * Structure differs from the DH895xxCC common base header structure, hence + * redefined here. + * @description + * PKE request message header pars structure + * + *****************************************************************************/ +typedef struct icp_qat_fw_req_hdr_pke_cd_pars_s { + /**< LWs 2-3 */ + uint64_t content_desc_addr; + /**< Content descriptor pointer */ + + /**< LW 4 */ + uint32_t content_desc_resrvd; + /**< Content descriptor reserved field */ + + /**< LW 5 */ + uint32_t func_id; + /**< MMP functionality Id */ + +} icp_qat_fw_req_hdr_pke_cd_pars_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_pke + * Definition of the QAT FW PKE request header mid section. + * Structure differs from the DH895xxCC common base header structure, + * instead following the DH89xxCC format, hence redefined here. + * @description + * PKE request message header middle structure + * + *****************************************************************************/ +typedef struct icp_qat_fw_req_pke_mid_s { + /**< LWs 6-11 */ + uint64_t opaque_data; + /**< Opaque data passed unmodified from the request to response messages + * by + * firmware (fw) */ + + uint64_t src_data_addr; + /**< Generic definition of the source data supplied to the QAT AE. The + * common flags are used to further describe the attributes of this + * field */ + + uint64_t dest_data_addr; + /**< Generic definition of the destination data supplied to the QAT AE. + * The + * common flags are used to further describe the attributes of this + * field */ + + /**< Following DH89xxCC structure format - footer is excluded */ + +} icp_qat_fw_req_pke_mid_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_fw_pke + * Definition of the QAT FW PKE request header. + * Structure differs from the DH895xxCC common base header structure, + * instead following the DH89xxCC format, hence redefined here. + * @description + * PKE request message header structure + * + *****************************************************************************/ +typedef struct icp_qat_fw_req_pke_hdr_s { + /**< LW0 */ + uint8_t resrvd1; + /**< reserved field */ + + uint8_t resrvd2; + /**< reserved field */ + + uint8_t service_type; + /**< Service type */ + + uint8_t hdr_flags; + /**< This represents a flags field for the Service Request. + * The most significant bit is the 'valid' flag and the only + * one used. All remaining bit positions are unused and + * are therefore reserved and need to be set to 0. */ + + /**< LW1 */ + icp_qat_fw_comn_flags comn_req_flags; + /**< Common Request flags must indicate flat buffer (as per DH89xxCC) + * Common Request flags - PKE slice flags no longer used - slice + * allocated to a threadstrand.*/ + + uint16_t resrvd4; + /**< (DH89xxCC) CD Header Size and CD Params Size unused. Set to zero. + */ + + /**< LWs 2-5 */ + icp_qat_fw_req_hdr_pke_cd_pars_t cd_pars; + /**< PKE request message header pars structure - this differs + * from the DH895xxCC common base structure */ + +} icp_qat_fw_req_pke_hdr_t; + +/** + *************************************************************************** + * + * @ingroup icp_qat_fw_pke + * + * @brief + * PKE request message structure (64 bytes) + * + *****************************************************************************/ +typedef struct icp_qat_fw_pke_request_s { + /**< LWs 0-5 */ + icp_qat_fw_req_pke_hdr_t pke_hdr; + /**< Request header for PKE - CD Header/Param size + * must be zero */ + + /**< LWs 6-11 (same as DH89xxCC) */ + icp_qat_fw_req_pke_mid_t pke_mid; + /**< Request middle section for PKE */ + + /**< LW 12 */ + uint8_t output_param_count; + /**< Number of output large integers + * for request */ + + uint8_t input_param_count; + /**< Number of input large integers + * for request */ + + uint16_t resrvd1; + /** Reserved **/ + + /**< LW 13 */ + uint32_t resrvd2; + /**< Reserved */ + + /**< LWs 14-15 */ + uint64_t next_req_adr; + /** < PKE - next request address */ + +} icp_qat_fw_pke_request_t; + +/** + ***************************************************************************** + * + * @ingroup icp_qat_fw_pke + * + * @brief + * PKE response message header structure + * + *****************************************************************************/ +typedef struct icp_qat_fw_resp_pke_hdr_s { + /**< LW0 */ + uint8_t resrvd1; + /**< The Response Destination Id has been removed + * from first QWord */ + + uint8_t resrvd2; + /**< Response Pipe Id field is unused (reserved) + * - Functionality within DH895xxCC uses arbiter instead */ + + uint8_t response_type; + /**< Response type - copied from the request to + * the response message */ + + uint8_t hdr_flags; + /**< This represents a flags field for the Response. + * The most significant bit is the 'valid' flag and the only + * one used. All remaining bit positions are unused and + * are therefore reserved */ + + /**< LW1 */ + icp_qat_fw_pke_resp_status_t resp_status; + + uint16_t resrvd4; + /**< (DH89xxCC) CD Header Size and CD Params Size fields unused. + * Set to zero. */ + +} icp_qat_fw_resp_pke_hdr_t; + +/** + ***************************************************************************** + * + * @ingroup icp_qat_fw_pke + * + * @brief + * PKE response message structure (32 bytes) + * + *****************************************************************************/ +typedef struct icp_qat_fw_pke_resp_s { + /**< LWs 0-1 */ + icp_qat_fw_resp_pke_hdr_t pke_resp_hdr; + /**< Response header for PKE */ + + /**< LWs 2-3 */ + uint64_t opaque_data; + /**< Opaque data passed from the request to the response message */ + + /**< LWs 4-5 */ + uint64_t src_data_addr; + /**< Generic definition of the source data supplied to the QAT AE. The + * common flags are used to further describe the attributes of this + * field */ + + /**< LWs 6-7 */ + uint64_t dest_data_addr; + /**< Generic definition of the destination data supplied to the QAT AE. + * The + * common flags are used to further describe the attributes of this + * field */ + +} icp_qat_fw_pke_resp_t; + +/* ========================================================================= */ +/* MACRO DEFINITIONS */ +/* ========================================================================= */ + +/**< @ingroup icp_qat_fw_pke + * Macro defining the bit position and mask of the 'valid' flag, within the + * hdr_flags field of LW0 (service request and response) of the PKE request */ +#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS 7 +#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK 0x1 + +/**< @ingroup icp_qat_fw_pke + * Macro defining the bit position and mask of the PKE status flag, within the + * status field LW1 of a PKE response message */ +#define QAT_COMN_RESP_PKE_STATUS_BITPOS 6 +/**< @ingroup icp_qat_fw_pke + * Starting bit position indicating the PKE status flag within the PKE response + * pke_resp_flags byte. */ + +#define QAT_COMN_RESP_PKE_STATUS_MASK 0x1 +/**< @ingroup icp_qat_fw_pke + * One bit mask used to determine PKE status mask */ + +/* + * < @ingroup icp_qat_fw_pke + * *** PKE Response Status Field Definition *** + * The PKE response follows the CPM 1.5 message format. The status field is 16 bits + * wide, where the status flags are contained within the most significant byte of the + * icp_qat_fw_pke_resp_status_t structure. The lower 8 bits of this word now contain + * the common error codes, which are defined in the common header file(*). + */ +/* + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + + * | Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | [7....0] | + * + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + + * | Flags | Rsrvd | Pke | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Common error codes(*) | + * + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + + */ + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Macro for extraction of the PKE bit from the 16-bit status field + * particular to a PKE response. The status flags are contained within + * the most significant byte of the word. The lower 8 bits of this status + * word now contain the common error codes, which are defined in the common + * header file. The appropriate macro definition to extract the PKE status + * flag from the PKE response assumes that a single byte i.e. + *pke_resp_flags + * is passed to the macro. + * + * @param status + * Status to extract the PKE status bit + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(flags) \ + QAT_FIELD_GET((flags), \ + QAT_COMN_RESP_PKE_STATUS_BITPOS, \ + QAT_COMN_RESP_PKE_STATUS_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Extract the valid flag from the PKE Request's header flags. Note that + * this invokes the common macro which may be used by either the request + * or the response. + * + * @param icp_qat_fw_req_pke_hdr_t Structure passed to extract the valid bit + * from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_RQ_VALID_FLAG_GET(icp_qat_fw_req_pke_hdr_t) \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(icp_qat_fw_req_pke_hdr_t) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Set the valid bit in the PKE Request's header flags. Note that + * this invokes the common macro which may be used by either the request + * or the response. + * + * @param icp_qat_fw_req_pke_hdr_t Structure passed to set the valid bit. + * @param val Value of the valid bit flag. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_RQ_VALID_FLAG_SET(icp_qat_fw_req_pke_hdr_t, val) \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(icp_qat_fw_req_pke_hdr_t, val) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Extract the valid flag from the PKE Response's header flags. Note that + * invokes the common macro which may be used by either the request + * or the response. + * + * @param icp_qat_fw_resp_pke_hdr_t Structure to extract the valid bit + * from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_RESP_VALID_FLAG_GET(icp_qat_fw_resp_pke_hdr_t) \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(icp_qat_fw_resp_pke_hdr_t) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Set the valid bit in the PKE Response's header flags. Note that + * this invokes the common macro which may be used by either the + * request or the response. + * + * @param icp_qat_fw_resp_pke_hdr_t Structure to set the valid bit + * @param val Value of the valid bit flag. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_RESP_VALID_FLAG_SET(icp_qat_fw_resp_pke_hdr_t, val) \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(icp_qat_fw_resp_pke_hdr_t, val) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Common macro to extract the valid flag from the header flags field + * within the header structure (request or response). + * + * @param hdr_t Structure (request or response) to extract the + * valid bit from the 'hdr_flags' field. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(hdr_t) \ + QAT_FIELD_GET(hdr_t.hdr_flags, \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_fw_pke + * + * @description + * Common macro to set the valid bit in the header flags field within + * the header structure (request or response). + * + * @param hdr_t Structure (request or response) containing the header + * flags field, to allow the valid bit to be set. + * @param val Value of the valid bit flag. + * + *****************************************************************************/ +#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(hdr_t, val) \ + QAT_FIELD_SET((hdr_t.hdr_flags), \ + (val), \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS, \ + ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK) + +#endif /* _ICP_QAT_FW_PKE_ */ diff --git a/sys/dev/qat/qat_api/firmware/include/icp_qat_hw.h b/sys/dev/qat/qat_api/firmware/include/icp_qat_hw.h new file mode 100644 index 00000000000..5ed607aa3c3 --- /dev/null +++ b/sys/dev/qat/qat_api/firmware/include/icp_qat_hw.h @@ -0,0 +1,1552 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_qat_hw.h + * @defgroup icp_qat_hw_defs ICP QAT HW definitions + * @ingroup icp_qat_hw + * @description + * This file documents definitions for the QAT HW + * + *****************************************************************************/ + +#ifndef _ICP_QAT_HW_H_ +#define _ICP_QAT_HW_H_ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +/* ========================================================================= */ +/* AccelerationEngine */ +/* ========================================================================= */ + +typedef enum { + ICP_QAT_HW_AE_0 = 0, /*!< ID of AE0 */ + ICP_QAT_HW_AE_1 = 1, /*!< ID of AE1 */ + ICP_QAT_HW_AE_2 = 2, /*!< ID of AE2 */ + ICP_QAT_HW_AE_3 = 3, /*!< ID of AE3 */ + ICP_QAT_HW_AE_4 = 4, /*!< ID of AE4 */ + ICP_QAT_HW_AE_5 = 5, /*!< ID of AE5 */ + ICP_QAT_HW_AE_6 = 6, /*!< ID of AE6 */ + ICP_QAT_HW_AE_7 = 7, /*!< ID of AE7 */ + ICP_QAT_HW_AE_8 = 8, /*!< ID of AE8 */ + ICP_QAT_HW_AE_9 = 9, /*!< ID of AE9 */ + ICP_QAT_HW_AE_10 = 10, /*!< ID of AE10 */ + ICP_QAT_HW_AE_11 = 11, /*!< ID of AE11 */ + ICP_QAT_HW_AE_12 = 12, /*!< ID of AE12 */ + ICP_QAT_HW_AE_13 = 13, /*!< ID of AE13 */ + ICP_QAT_HW_AE_14 = 14, /*!< ID of AE14 */ + ICP_QAT_HW_AE_15 = 15, /*!< ID of AE15 */ + ICP_QAT_HW_AE_DELIMITER = 16 /**< Delimiter type */ +} icp_qat_hw_ae_id_t; + +/* ========================================================================= */ +/* QAT */ +/* ========================================================================= */ + +typedef enum { + ICP_QAT_HW_QAT_0 = 0, /*!< ID of QAT0 */ + ICP_QAT_HW_QAT_1 = 1, /*!< ID of QAT1 */ + ICP_QAT_HW_QAT_2 = 2, /*!< ID of QAT2 */ + ICP_QAT_HW_QAT_3 = 3, /*!< ID of QAT3 */ + ICP_QAT_HW_QAT_4 = 4, /*!< ID of QAT4 */ + ICP_QAT_HW_QAT_5 = 5, /*!< ID of QAT5 */ + ICP_QAT_HW_QAT_DELIMITER = 6 /**< Delimiter type */ +} icp_qat_hw_qat_id_t; + +/* ========================================================================= */ +/* AUTH SLICE */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Supported Authentication Algorithm types + * @description + * Enumeration which is used to define the authenticate algorithms + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_AUTH_ALGO_NULL = 0, /*!< Null hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA1 = 1, /*!< SHA1 hashing */ + ICP_QAT_HW_AUTH_ALGO_MD5 = 2, /*!< MD5 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA224 = 3, /*!< SHA-224 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA256 = 4, /*!< SHA-256 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA384 = 5, /*!< SHA-384 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA512 = 6, /*!< SHA-512 hashing */ + ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC = 7, /*!< AES-XCBC-MAC hashing */ + ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC = 8, /*!< AES-CBC-MAC hashing */ + ICP_QAT_HW_AUTH_ALGO_AES_F9 = 9, /*!< AES F9 hashing */ + ICP_QAT_HW_AUTH_ALGO_GALOIS_128 = 10, /*!< Galois 128 bit hashing */ + ICP_QAT_HW_AUTH_ALGO_GALOIS_64 = 11, /*!< Galois 64 hashing */ + ICP_QAT_HW_AUTH_ALGO_KASUMI_F9 = 12, /*!< Kasumi F9 hashing */ + ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 = 13, /*!< UIA2/SNOW_3G F9 hashing */ + ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 = + 14, /*!< 128_EIA3/ZUC_3G hashing */ + ICP_QAT_HW_AUTH_ALGO_SM3 = 15, /*!< SM3 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA3_224 = 16, /*!< SHA3-224 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA3_256 = 17, /*!< SHA3-256 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA3_384 = 18, /*!< SHA3-384 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHA3_512 = 19, /*!< SHA3-512 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHAKE_128 = 20, /*!< SHAKE-128 hashing */ + ICP_QAT_HW_AUTH_ALGO_SHAKE_256 = 21, /*!< SHAKE-256 hashing */ + ICP_QAT_HW_AUTH_ALGO_POLY = 22, /*!< POLY hashing */ + ICP_QAT_HW_AUTH_ALGO_DELIMITER = 23 /**< Delimiter type */ +} icp_qat_hw_auth_algo_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported Authentication modes + * @description + * Enumeration which is used to define the authentication slice modes. + * The concept of modes is very specific to the QAT implementation. Its + * main use is differentiate how the algorithms are used i.e. mode0 SHA1 + * will configure the QAT Auth Slice to do plain SHA1 hashing while mode1 + * configures it to do SHA1 HMAC with precomputes and mode2 sets up the + * slice to do SHA1 HMAC with no precomputes (uses key directly) + * + * @Note + * Only some algorithms are valid in some of the modes. If you dont know + * what you are doing then refer back to the HW documentation + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_AUTH_MODE0 = 0, /*!< QAT Auth Mode0 configuration */ + ICP_QAT_HW_AUTH_MODE1 = 1, /*!< QAT Auth Mode1 configuration */ + ICP_QAT_HW_AUTH_MODE2 = 2, /*!< QAT AuthMode2 configuration */ + ICP_QAT_HW_AUTH_MODE_DELIMITER = 3 /**< Delimiter type */ +} icp_qat_hw_auth_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Auth configuration structure + * + * @description + * Definition of the format of the authentication slice configuration + * + *****************************************************************************/ +typedef struct icp_qat_hw_auth_config_s { + uint32_t config; + /**< Configuration used for setting up the slice */ + + uint32_t reserved; + /**< Reserved */ +} icp_qat_hw_auth_config_t; + +/* Private defines */ + +/* Note: Bit positions have been defined for little endian ordering */ +/* +* AUTH CONFIG WORD BITMAP +* + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ----- + ----- + +* | Bit | 63:56 | 55:52 | 51:48 | 47:32 | 31:24 | 23:22 | 21:18 | 17 | 16 | 15 | 14:8 | 7:4 | 3:0 | +* + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ------+ ----- + +* | Usage | Prog | Resvd | Prog | Resvd | Resvd | Algo | Rsvrd | SHA3 | SHA3 |Rsvrd | Cmp | Mode | Algo | +* | |padding | Bits=0 | padding | Bits=0 | Bits=0 | SHA3 | |Padding |Padding | | | | | +* | | SHA3 | | SHA3 | | | | |Override|Disable | | | | | +* | |(prefix)| |(postfix)| | | | | | | | | | | +* + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ----- + ------+ +*/ + +/**< Flag mask & bit position */ + +#define QAT_AUTH_MODE_BITPOS 4 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth mode */ + +#define QAT_AUTH_MODE_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Four bit mask used for determing the Auth mode */ + +#define QAT_AUTH_ALGO_BITPOS 0 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth Algo */ + +#define QAT_AUTH_ALGO_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Four bit mask used for determining the Auth algo */ + +#define QAT_AUTH_CMP_BITPOS 8 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth Compare */ + +#define QAT_AUTH_CMP_MASK 0x7F +/**< @ingroup icp_qat_hw_defs + * Seven bit mask used to determine the Auth Compare */ + +#define QAT_AUTH_SHA3_PADDING_DISABLE_BITPOS 16 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth h/w + * padding disable for SHA3. + * Flag set to 0 => h/w is required to pad (default) + * Flag set to 1 => No padding in h/w + */ + +#define QAT_AUTH_SHA3_PADDING_DISABLE_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Single bit mask used to determine the Auth h/w + * padding disable for SHA3. + */ + +#define QAT_AUTH_SHA3_PADDING_OVERRIDE_BITPOS 17 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth h/w + * padding override for SHA3. + * Flag set to 0 => default padding behaviour + * implemented in SHA3-256 slice will take effect + * (default hardware setting upon h/w reset) + * Flag set to 1 => SHA3-core will not use the padding + * sequence built into the SHA3 core. Instead, the + * padding sequence specified in bits 48-51 and 56-63 + * of the 64-bit auth config word will apply + * (corresponds with EAS bits 32-43). + */ + +#define QAT_AUTH_SHA3_PADDING_OVERRIDE_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Single bit mask used to determine the Auth h/w + * padding override for SHA3. + */ + +#define QAT_AUTH_ALGO_SHA3_BITPOS 22 +/**< @ingroup icp_qat_hw_defs + * Starting bit position for indicating the + * SHA3 Auth Algo + */ + +#define QAT_AUTH_ALGO_SHA3_MASK 0x3 +/**< @ingroup icp_qat_hw_defs + * Two bit mask used for determining the + * SHA3 Auth algo + */ + +/**< Flag mask & bit position */ + +#define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_BITPOS 16 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the SHA3 + * flexible programmable padding postfix. + * Note that these bits are set using macro + * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER and are + * defined relative to the 32-bit value that + * this macro returns. In effect, therefore, this + * defines starting bit position 48 within the + * 64-bit auth config word. + */ + +#define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Four-bit mask used to determine the SHA3 + * flexible programmable padding postfix + */ + +#define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_BITPOS 24 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the SHA3 + * flexible programmable padding prefix + * Note that these bits are set using macro + * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER and are + * defined relative to the 32-bit value that + * this macro returns. In effect, therefore, this + * defines starting bit position 56 within the + * 64-bit auth config word. + */ + +#define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_MASK 0xFF +/**< @ingroup icp_qat_hw_defs + * Eight-bit mask used to determine the SHA3 + * flexible programmable padding prefix + */ + +/**< Flag usage - see additional notes @description for + * ICP_QAT_HW_AUTH_CONFIG_BUILD and + * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER macros. +*/ + +#define QAT_AUTH_SHA3_HW_PADDING_ENABLE 0 +/**< @ingroup icp_qat_hw_defs + * This setting enables h/w padding for SHA3. + */ + +#define QAT_AUTH_SHA3_HW_PADDING_DISABLE 1 +/**< @ingroup icp_qat_hw_defs + * This setting disables h/w padding for SHA3. + */ + +#define QAT_AUTH_SHA3_PADDING_DISABLE_USE_DEFAULT 0 +/**< @ingroup icp_qat_hw_defs + * Default value for the Auth h/w padding disable. + * If set to 0 for SHA3-256, h/w padding is enabled. + * Padding_Disable is undefined for all non-SHA3-256 + * algos and is consequently set to the default of 0. + */ + +#define QAT_AUTH_SHA3_PADDING_OVERRIDE_USE_DEFAULT 0 +/**< @ingroup icp_qat_hw_defs + * Value for the Auth h/w padding override for SHA3. + * Flag set to 0 => default padding behaviour + * implemented in SHA3-256 slice will take effect + * (default hardware setting upon h/w reset) + * For this setting of the override flag, all the + * bits of the padding sequence specified + * in bits 48-51 and 56-63 of the 64-bit + * auth config word are set to 0 (reserved). + */ + +#define QAT_AUTH_SHA3_PADDING_OVERRIDE_PROGRAMMABLE 1 +/**< @ingroup icp_qat_hw_defs + * Value for the Auth h/w padding override for SHA3. + * Flag set to 1 => SHA3-core will not use the padding + * sequence built into the SHA3 core. Instead, the + * padding sequence specified in bits 48-51 and 56-63 + * of the 64-bit auth config word will apply + * (corresponds with EAS bits 32-43). + */ + +#define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_RESERVED 0 +/**< @ingroup icp_qat_hw_defs + * All the bits of the padding sequence specified in + * bits 48-51 of the 64-bit auth config word are set + * to 0 (reserved) if the padding override bit is set + * to 0, indicating default padding. + */ + +#define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_RESERVED 0 +/**< @ingroup icp_qat_hw_defs + * All the bits of the padding sequence specified in + * bits 56-63 of the 64-bit auth config word are set + * to 0 (reserved) if the padding override bit is set + * to 0, indicating default padding. + */ + +/** + *************************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * The derived configuration word for the auth slice is based on the inputs + * of mode, algorithm type and compare length. The total size of the auth + * config word in the setup block is 64 bits however the size of the value + * returned by this macro is assumed to be only 32 bits (for now) and sets + * the lower 32 bits of the auth config word. Unfortunately, changing the + * size of the returned value to 64 bits will also require changes to the + * shared RAM constants table so the macro size will remain at 32 bits. + * This means that the padding sequence bits specified in bits 48-51 and + * 56-63 of the 64-bit auth config word are NOT included in the + * ICP_QAT_HW_AUTH_CONFIG_BUILD macro and are defined in a + * separate macro, namely, ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER. + * + * For the digest generation case the compare length is a don't care value. + * Furthermore, if the client will be doing the digest validation, the + * compare_length will not be used. + * The padding and padding override bits for SHA3 are set internally + * by the macro. + * Padding_Disable is set it to 0 for SHA3-256 algo only i.e. we want to + * enable this to provide the ability to test with h/w padding enabled. + * Padding_Disable has no meaning for all non-SHA3-256 algos and is + * consequently set the default of 0. + * Padding Override is set to 0, implying that the padding behaviour + * implemented in the SHA3-256 slice will take effect (default hardware + * setting upon h/w reset). + * This flag has no meaning for other algos, so is also set to the default + * for non-SHA3-256 algos. + * + * @param mode Authentication mode to use + * @param algo Auth Algorithm to use + * @param cmp_len The length of the digest if the QAT is to the check + * + ****************************************************************************************/ +#define ICP_QAT_HW_AUTH_CONFIG_BUILD(mode, algo, cmp_len) \ + ((((mode)&QAT_AUTH_MODE_MASK) << QAT_AUTH_MODE_BITPOS) | \ + (((algo)&QAT_AUTH_ALGO_MASK) << QAT_AUTH_ALGO_BITPOS) | \ + (((algo >> 4) & QAT_AUTH_ALGO_SHA3_MASK) \ + << QAT_AUTH_ALGO_SHA3_BITPOS) | \ + (((QAT_AUTH_SHA3_PADDING_DISABLE_USE_DEFAULT)&QAT_AUTH_SHA3_PADDING_DISABLE_MASK) \ + << QAT_AUTH_SHA3_PADDING_DISABLE_BITPOS) | \ + (((QAT_AUTH_SHA3_PADDING_OVERRIDE_USE_DEFAULT)&QAT_AUTH_SHA3_PADDING_OVERRIDE_MASK) \ + << QAT_AUTH_SHA3_PADDING_OVERRIDE_BITPOS) | \ + (((cmp_len)&QAT_AUTH_CMP_MASK) << QAT_AUTH_CMP_BITPOS)) + +/** + *************************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * This macro sets the upper 32 bits of the 64-bit auth config word. + * The sequence bits specified in bits 48-51 and 56-63 of the 64-bit auth + * config word are included in this macro, which is therefore assumed to + * return a 32-bit value. + * Note that the Padding Override bit is set in macro + * ICP_QAT_HW_AUTH_CONFIG_BUILD. + * Since the Padding Override is set to 0 regardless, for now, all the bits + * of the padding sequence specified in bits 48-51 and 56-63 of the 64-bit + * auth config word are set to 0 (reserved). Note that the bit positions of + * the padding sequence bits are defined relative to the 32-bit value that + * this macro returns. + * + ****************************************************************************************/ +#define ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER \ + ((((QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_RESERVED)&QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_MASK) \ + << QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_BITPOS) | \ + (((QAT_AUTH_SHA3_PROG_PADDING_PREFIX_RESERVED)&QAT_AUTH_SHA3_PROG_PADDING_PREFIX_MASK) \ + << QAT_AUTH_SHA3_PROG_PADDING_PREFIX_BITPOS)) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Auth Counter structure + * + * @description + * 32 bit counter that tracks the number of data bytes passed through + * the slice. This is used by the padding logic for some algorithms. Note + * only the upper 32 bits are set. + * + *****************************************************************************/ +typedef struct icp_qat_hw_auth_counter_s { + uint32_t counter; + /**< Counter value */ + uint32_t reserved; + /**< Reserved */ +} icp_qat_hw_auth_counter_t; + +/* Private defines */ +#define QAT_AUTH_COUNT_MASK 0xFFFFFFFF +/**< @ingroup icp_qat_hw_defs + * Thirty two bit mask used for determining the Auth count */ + +#define QAT_AUTH_COUNT_BITPOS 0 +/**< @ingroup icp_qat_hw_defs + * Starting bit position indicating the Auth count. */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Macro to build the auth counter quad word + * + * @param val Counter value to set + * + *****************************************************************************/ +#define ICP_QAT_HW_AUTH_COUNT_BUILD(val) \ + (((val)&QAT_AUTH_COUNT_MASK) << QAT_AUTH_COUNT_BITPOS) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the common auth parameters + * @description + * This part of the configuration is constant for each service + * + *****************************************************************************/ +typedef struct icp_qat_hw_auth_setup_s { + icp_qat_hw_auth_config_t auth_config; + /**< Configuration word for the auth slice */ + icp_qat_hw_auth_counter_t auth_counter; + /**< Auth counter value for this request */ +} icp_qat_hw_auth_setup_t; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +#define QAT_HW_DEFAULT_ALIGNMENT 8 +#define QAT_HW_ROUND_UP(val, n) (((val) + ((n)-1)) & (~(n - 1))) + +/* State1 */ +#define ICP_QAT_HW_NULL_STATE1_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State1 block size for NULL hashing */ +#define ICP_QAT_HW_MD5_STATE1_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State1 block size for MD5 */ +#define ICP_QAT_HW_SHA1_STATE1_SZ 20 +/**< @ingroup icp_qat_hw_defs + * Define the state1 block size for SHA1 - Note that for the QAT HW the state + * is rounded to the nearest 8 byte multiple */ +#define ICP_QAT_HW_SHA224_STATE1_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA24 */ +#define ICP_QAT_HW_SHA3_224_STATE1_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA3_224 */ +#define ICP_QAT_HW_SHA256_STATE1_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA256 */ +#define ICP_QAT_HW_SHA3_256_STATE1_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA3_256 */ +#define ICP_QAT_HW_SHA384_STATE1_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA384 */ +#define ICP_QAT_HW_SHA3_384_STATE1_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA3_384 */ +#define ICP_QAT_HW_SHA512_STATE1_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA512 */ +#define ICP_QAT_HW_SHA3_512_STATE1_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State1 block size for SHA3_512 */ +#define ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State1 block size for XCBC */ +#define ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State1 block size for CBC */ +#define ICP_QAT_HW_AES_F9_STATE1_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State1 block size for AES F9 */ +#define ICP_QAT_HW_KASUMI_F9_STATE1_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State1 block size for Kasumi F9 */ +#define ICP_QAT_HW_GALOIS_128_STATE1_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State1 block size for Galois128 */ +#define ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ 8 +/**< @ingroup icp_cpm_hw_defs + * State1 block size for UIA2 */ +#define ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ 8 +/**< @ingroup icp_cpm_hw_defs + * State1 block size for EIA3 */ +#define ICP_QAT_HW_SHA3_STATEFUL_STATE1_SZ 200 +/** <@ingroup icp_cpm_hw_defs + * State1 block size for stateful SHA3 processing*/ +#define ICP_QAT_HW_SM3_STATE1_SZ 32 +/**< @ingroup icp_cpm_hw_defs + * State1 block size for SM3 */ + +/* State2 */ +#define ICP_QAT_HW_NULL_STATE2_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State2 block size for NULL hashing */ +#define ICP_QAT_HW_MD5_STATE2_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for MD5 */ +#define ICP_QAT_HW_SHA1_STATE2_SZ 20 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA1 - Note that for the QAT HW the state is rounded + * to the nearest 8 byte multiple */ +#define ICP_QAT_HW_SHA224_STATE2_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA224 */ +#define ICP_QAT_HW_SHA3_224_STATE2_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA3_224 */ +#define ICP_QAT_HW_SHA256_STATE2_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA256 */ +#define ICP_QAT_HW_SHA3_256_STATE2_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA3_256 */ +#define ICP_QAT_HW_SHA384_STATE2_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA384 */ +#define ICP_QAT_HW_SHA3_384_STATE2_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA3_384 */ +#define ICP_QAT_HW_SHA512_STATE2_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA512 */ +#define ICP_QAT_HW_SHA3_512_STATE2_SZ 64 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SHA3_512 */ +#define ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for XCBC */ +#define ICP_QAT_HW_AES_CBC_MAC_KEY_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for CBC */ +#define ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for AES Encrypted Counter 0 */ +#define ICP_QAT_HW_F9_IK_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for F9 IK */ +#define ICP_QAT_HW_F9_FK_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for F9 FK */ +#define ICP_QAT_HW_KASUMI_F9_STATE2_SZ \ + (ICP_QAT_HW_F9_IK_SZ + ICP_QAT_HW_F9_FK_SZ) +/**< @ingroup icp_qat_hw_defs + * State2 complete size for Kasumi F9 */ +#define ICP_QAT_HW_AES_F9_STATE2_SZ ICP_QAT_HW_KASUMI_F9_STATE2_SZ +/**< @ingroup icp_qat_hw_defs + * State2 complete size for AES F9 */ +#define ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ 24 +/**< @ingroup icp_cpm_hw_defs + * State2 block size for UIA2 */ +#define ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ 32 +/**< @ingroup icp_cpm_hw_defs + * State2 block size for EIA3 */ +#define ICP_QAT_HW_GALOIS_H_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for Galois Multiplier H */ +#define ICP_QAT_HW_GALOIS_LEN_A_SZ 8 +/**< @ingroup icp_qat_hw_defs + * State2 block size for Galois AAD length */ +#define ICP_QAT_HW_GALOIS_E_CTR0_SZ 16 +/**< @ingroup icp_qat_hw_defs + * State2 block size for Galois Encrypted Counter 0 */ +#define ICP_QAT_HW_SM3_STATE2_SZ 32 +/**< @ingroup icp_qat_hw_defs + * State2 block size for SM3 */ + +/* ************************************************************************* */ +/* ************************************************************************* */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of SHA512 auth algorithm processing struct + * @description + * This structs described the parameters to pass to the slice for + * configuring it for SHA512 processing. This is the largest possible + * setup block for authentication + * + *****************************************************************************/ +typedef struct icp_qat_hw_auth_sha512_s { + icp_qat_hw_auth_setup_t inner_setup; + /**< Inner loop configuration word for the slice */ + + uint8_t state1[ICP_QAT_HW_SHA512_STATE1_SZ]; + /**< Slice state1 variable */ + + icp_qat_hw_auth_setup_t outer_setup; + /**< Outer configuration word for the slice */ + + uint8_t state2[ICP_QAT_HW_SHA512_STATE2_SZ]; + /**< Slice state2 variable */ + +} icp_qat_hw_auth_sha512_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of SHA3_512 auth algorithm processing struct + * @description + * This structs described the parameters to pass to the slice for + * configuring it for SHA3_512 processing. This is the largest possible + * setup block for authentication + * + *****************************************************************************/ +typedef struct icp_qat_hw_auth_sha3_512_s { + icp_qat_hw_auth_setup_t inner_setup; + /**< Inner loop configuration word for the slice */ + + uint8_t state1[ICP_QAT_HW_SHA3_512_STATE1_SZ]; + /**< Slice state1 variable */ + + icp_qat_hw_auth_setup_t outer_setup; + /**< Outer configuration word for the slice */ + + /* State2 size is zero - this may change for future implementations */ + uint8_t state2[ICP_QAT_HW_SHA3_512_STATE2_SZ]; +} icp_qat_hw_auth_sha3_512_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Supported hardware authentication algorithms + * @description + * Common grouping of the auth algorithm types supported by the QAT + * + *****************************************************************************/ +typedef union icp_qat_hw_auth_algo_blk_u { + icp_qat_hw_auth_sha512_t sha512; + /**< SHA512 Hashing */ + +} icp_qat_hw_auth_algo_blk_t; + +#define ICP_QAT_HW_GALOIS_LEN_A_BITPOS 0 +/**< @ingroup icp_qat_hw_defs + * Bit position of the 32 bit A value in the 64 bit A configuration sent to + * the QAT */ + +#define ICP_QAT_HW_GALOIS_LEN_A_MASK 0xFFFFFFFF +/**< @ingroup icp_qat_hw_defs + * Mask value for A value */ + +/* ========================================================================= */ +/* CIPHER SLICE */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported Cipher Algorithm types + * @description + * Enumeration used to define the cipher algorithms + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_CIPHER_ALGO_NULL = 0, /*!< Null ciphering */ + ICP_QAT_HW_CIPHER_ALGO_DES = 1, /*!< DES ciphering */ + ICP_QAT_HW_CIPHER_ALGO_3DES = 2, /*!< 3DES ciphering */ + ICP_QAT_HW_CIPHER_ALGO_AES128 = 3, /*!< AES-128 ciphering */ + ICP_QAT_HW_CIPHER_ALGO_AES192 = 4, /*!< AES-192 ciphering */ + ICP_QAT_HW_CIPHER_ALGO_AES256 = 5, /*!< AES-256 ciphering */ + ICP_QAT_HW_CIPHER_ALGO_ARC4 = 6, /*!< ARC4 ciphering */ + ICP_QAT_HW_CIPHER_ALGO_KASUMI = 7, /*!< Kasumi */ + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 = 8, /*!< Snow_3G */ + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3 = 9, /*!< ZUC_3G */ + ICP_QAT_HW_CIPHER_ALGO_SM4 = 10, /*!< SM4 ciphering */ + ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305 = + 11, /*!< CHACHA POLY SPC AEAD */ + ICP_QAT_HW_CIPHER_DELIMITER = 12 /**< Delimiter type */ +} icp_qat_hw_cipher_algo_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported cipher modes of operation + * @description + * Enumeration used to define the cipher slice modes. + * + * @Note + * Only some algorithms are valid in some of the modes. If you dont know + * what you are doing then refer back to the EAS + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_CIPHER_ECB_MODE = 0, /*!< ECB mode */ + ICP_QAT_HW_CIPHER_CBC_MODE = 1, /*!< CBC more */ + ICP_QAT_HW_CIPHER_CTR_MODE = 2, /*!< CTR mode */ + ICP_QAT_HW_CIPHER_F8_MODE = 3, /*!< F8 mode */ + ICP_QAT_HW_CIPHER_AEAD_MODE = 4, /*!< AES-GCM SPC AEAD mode */ + ICP_QAT_HW_CIPHER_RESERVED_MODE = 5, /*!< Reserved */ + ICP_QAT_HW_CIPHER_XTS_MODE = 6, /*!< XTS mode */ + ICP_QAT_HW_CIPHER_MODE_DELIMITER = 7 /**< Delimiter type */ +} icp_qat_hw_cipher_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Cipher Configuration Struct + * + * @description + * Configuration data used for setting up the QAT Cipher Slice + * + *****************************************************************************/ + +typedef struct icp_qat_hw_cipher_config_s { + uint32_t val; + /**< Cipher slice configuration */ + + uint32_t reserved; + /**< Reserved */ +} icp_qat_hw_cipher_config_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the cipher direction + * @description + * Enumeration which is used to define the cipher direction to apply + * + *****************************************************************************/ + +typedef enum { + /*!< Flag to indicate that encryption is required */ + ICP_QAT_HW_CIPHER_ENCRYPT = 0, + /*!< Flag to indicate that decryption is required */ + ICP_QAT_HW_CIPHER_DECRYPT = 1, + +} icp_qat_hw_cipher_dir_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the cipher key conversion modes + * @description + * Enumeration which is used to define if cipher key conversion is needed + * + *****************************************************************************/ + +typedef enum { + /*!< Flag to indicate that no key convert is required */ + ICP_QAT_HW_CIPHER_NO_CONVERT = 0, + /*!< Flag to indicate that key conversion is required */ + ICP_QAT_HW_CIPHER_KEY_CONVERT = 1, +} icp_qat_hw_cipher_convert_t; + +/* Private defines */ + +/* Note: Bit positions have been arranged for little endian ordering */ + +#define QAT_CIPHER_MODE_BITPOS 4 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher mode bit position */ + +#define QAT_CIPHER_MODE_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Define for the cipher mode mask (four bits) */ + +#define QAT_CIPHER_ALGO_BITPOS 0 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher algo bit position */ + +#define QAT_CIPHER_ALGO_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Define for the cipher algo mask (four bits) */ + +#define QAT_CIPHER_CONVERT_BITPOS 9 +/**< @ingroup icp_qat_hw_defs + * Define the cipher convert key bit position */ + +#define QAT_CIPHER_CONVERT_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher convert key mask (one bit)*/ + +#define QAT_CIPHER_DIR_BITPOS 8 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher direction bit position */ + +#define QAT_CIPHER_DIR_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher direction mask (one bit) */ + +#define QAT_CIPHER_AEAD_HASH_CMP_LEN_MASK 0x1F +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD Hash compare length mask (5 bits)*/ + +#define QAT_CIPHER_AEAD_HASH_CMP_LEN_BITPOS 10 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD Hash compare length (5 bits)*/ + +#define QAT_CIPHER_AEAD_AAD_SIZE_LOWER_MASK 0xFF +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD AAD size lower byte mask */ + +#define QAT_CIPHER_AEAD_AAD_SIZE_UPPER_MASK 0x3F +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD AAD size upper 6 bits mask */ + +#define QAT_CIPHER_AEAD_AAD_UPPER_SHIFT 8 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD AAD size Upper byte shift */ + +#define QAT_CIPHER_AEAD_AAD_LOWER_SHIFT 24 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD AAD size Lower byte shift */ + +#define QAT_CIPHER_AEAD_AAD_SIZE_BITPOS 16 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher AEAD AAD size (14 bits)*/ + +#define QAT_CIPHER_MODE_F8_KEY_SZ_MULT 2 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher mode F8 key size */ + +#define QAT_CIPHER_MODE_XTS_KEY_SZ_MULT 2 +/**< @ingroup icp_qat_hw_defs + * Define for the cipher XTS mode key size */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Build the cipher configuration field + * + * @param mode Cipher Mode to use + * @param algo Cipher Algorithm to use + * @param convert Specify if the key is to be converted + * @param dir Specify the cipher direction either encrypt or decrypt + * + *****************************************************************************/ +#define ICP_QAT_HW_CIPHER_CONFIG_BUILD( \ + mode, algo, convert, dir, aead_hash_cmp_len) \ + ((((mode)&QAT_CIPHER_MODE_MASK) << QAT_CIPHER_MODE_BITPOS) | \ + (((algo)&QAT_CIPHER_ALGO_MASK) << QAT_CIPHER_ALGO_BITPOS) | \ + (((convert)&QAT_CIPHER_CONVERT_MASK) << QAT_CIPHER_CONVERT_BITPOS) | \ + (((dir)&QAT_CIPHER_DIR_MASK) << QAT_CIPHER_DIR_BITPOS) | \ + (((aead_hash_cmp_len)&QAT_CIPHER_AEAD_HASH_CMP_LEN_MASK) \ + << QAT_CIPHER_AEAD_HASH_CMP_LEN_BITPOS)) + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Build the second QW of cipher slice config + * + * @param aad_size Specify the size of associated authentication data + * for AEAD processing + * + ******************************************************************************/ +#define ICP_QAT_HW_CIPHER_CONFIG_BUILD_UPPER(aad_size) \ + (((((aad_size) >> QAT_CIPHER_AEAD_AAD_UPPER_SHIFT) & \ + QAT_CIPHER_AEAD_AAD_SIZE_UPPER_MASK) \ + << QAT_CIPHER_AEAD_AAD_SIZE_BITPOS) | \ + (((aad_size)&QAT_CIPHER_AEAD_AAD_SIZE_LOWER_MASK) \ + << QAT_CIPHER_AEAD_AAD_LOWER_SHIFT)) + +#define ICP_QAT_HW_DES_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the block size for DES. + * This used as either the size of the IV or CTR input value */ +#define ICP_QAT_HW_3DES_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for 3DES */ +#define ICP_QAT_HW_NULL_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for NULL */ +#define ICP_QAT_HW_AES_BLK_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for AES 128, 192 and 256 */ +#define ICP_QAT_HW_KASUMI_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for KASUMI */ +#define ICP_QAT_HW_SNOW_3G_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for SNOW_3G */ +#define ICP_QAT_HW_ZUC_3G_BLK_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for ZUC_3G */ +#define ICP_QAT_HW_NULL_KEY_SZ 256 +/**< @ingroup icp_qat_hw_defs + * Define the key size for NULL */ +#define ICP_QAT_HW_DES_KEY_SZ 8 +/**< @ingroup icp_qat_hw_defs + * Define the key size for DES */ +#define ICP_QAT_HW_3DES_KEY_SZ 24 +/**< @ingroup icp_qat_hw_defs + * Define the key size for 3DES */ +#define ICP_QAT_HW_AES_128_KEY_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES128 */ +#define ICP_QAT_HW_AES_192_KEY_SZ 24 +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES192 */ +#define ICP_QAT_HW_AES_256_KEY_SZ 32 +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES256 */ +#define ICP_QAT_HW_AES_128_F8_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES128 F8 */ +#define ICP_QAT_HW_AES_192_F8_KEY_SZ \ + (ICP_QAT_HW_AES_192_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES192 F8 */ +#define ICP_QAT_HW_AES_256_F8_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES256 F8 */ +#define ICP_QAT_HW_AES_128_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES128 XTS */ +#define ICP_QAT_HW_AES_256_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES256 XTS */ +#define ICP_QAT_HW_KASUMI_KEY_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the key size for Kasumi */ +#define ICP_QAT_HW_KASUMI_F8_KEY_SZ \ + (ICP_QAT_HW_KASUMI_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for Kasumi F8 */ +#define ICP_QAT_HW_AES_128_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES128 XTS */ +#define ICP_QAT_HW_AES_256_XTS_KEY_SZ \ + (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) +/**< @ingroup icp_qat_hw_defs + * Define the key size for AES256 XTS */ +#define ICP_QAT_HW_ARC4_KEY_SZ 256 +/**< @ingroup icp_qat_hw_defs + * Define the key size for ARC4 */ +#define ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ 16 +/**< @ingroup icp_cpm_hw_defs + * Define the key size for SNOW_3G_UEA2 */ +#define ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ 16 +/**< @ingroup icp_cpm_hw_defs + * Define the iv size for SNOW_3G_UEA2 */ +#define ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ 16 +/**< @ingroup icp_cpm_hw_defs + * Define the key size for ZUC_3G_EEA3 */ +#define ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ 16 +/**< @ingroup icp_cpm_hw_defs + * Define the iv size for ZUC_3G_EEA3 */ +#define ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR 2 +/**< @ingroup icp_cpm_hw_defs + * Number of the HW register to clear in F8 mode */ +/**< @ingroup icp_qat_hw_defs + * Define the State/ Initialization Vector size for CHACHAPOLY */ +#define ICP_QAT_HW_CHACHAPOLY_KEY_SZ 32 +/**< @ingroup icp_qat_hw_defs + * Define the key size for CHACHA20-Poly1305*/ +#define ICP_QAT_HW_CHACHAPOLY_IV_SZ 12 +/**< @ingroup icp_qat_hw_defs + * Define the block size for CHACHA20-Poly1305*/ +#define ICP_QAT_HW_CHACHAPOLY_BLK_SZ 64 +/**< @ingroup icp_qat_hw_defs + * Define the State/ Initialization Vector size for CHACHA20-Poly1305 */ +#define ICP_QAT_HW_CHACHAPOLY_CTR_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the key size for CHACHA20-Poly1305*/ +#define ICP_QAT_HW_SPC_CTR_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the Single Pass tag size*/ +#define ICP_QAT_HW_CHACHAPOLY_ICV__SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the key size for CHACHA20-Poly1305*/ +#define ICP_QAT_HW_CHACHAPOLY_AAD_MAX_LOG 14 +/**< @ingroup icp_qat_hw_defs + * Define the key size for CHACHA20-Poly1305*/ +#define ICP_QAT_HW_SM4_BLK_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the processing block size for SM4 */ +#define ICP_QAT_HW_SM4_KEY_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Number of the HW register to clear in F8 mode */ +#define ICP_QAT_HW_SM4_IV_SZ 16 +/**< @ingroup icp_qat_hw_defs + * Define the key size for SM4 */ + +/* + * SHRAM constants definitions + */ +#define INIT_SHRAM_CONSTANTS_TABLE_SZ (1024) +#define SHRAM_CONSTANTS_TABLE_SIZE_QWS (INIT_SHRAM_CONSTANTS_TABLE_SZ / 4 / 2) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of AES-256 F8 cipher algorithm processing struct + * @description + * This structs described the parameters to pass to the slice for + * configuring it for AES-256 F8 processing + * + *****************************************************************************/ +typedef struct icp_qat_hw_cipher_aes256_f8_s { + icp_qat_hw_cipher_config_t cipher_config; + /**< Cipher configuration word for the slice set to + * AES-256 and the F8 mode */ + + uint8_t key[ICP_QAT_HW_AES_256_F8_KEY_SZ]; + /**< Cipher key */ + +} icp_qat_hw_cipher_aes256_f8_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Supported hardware cipher algorithms + * @description + * Common grouping of the cipher algorithm types supported by the QAT. + * This is the largest possible cipher setup block size + * + *****************************************************************************/ +typedef union icp_qat_hw_cipher_algo_blk_u { + + icp_qat_hw_cipher_aes256_f8_t aes256_f8; + /**< AES-256 F8 Cipher */ + +} icp_qat_hw_cipher_algo_blk_t; + +/* ========================================================================= */ +/* TRNG SLICE */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported TRNG configuration modes + * @description + * Enumeration used to define the TRNG modes. Used by clients when + * configuring the TRNG for use + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_TRNG_DBL = 0, /*!< TRNG Disabled mode */ + ICP_QAT_HW_TRNG_NHT = 1, /*!< TRNG Normal Health Test mode */ + ICP_QAT_HW_TRNG_KAT = 4, /*!< TRNG Known Answer Test mode */ + ICP_QAT_HW_TRNG_DELIMITER = 8 /**< Delimiter type */ +} icp_qat_hw_trng_cfg_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported TRNG KAT (known answer test) modes + * @description + * Enumeration which is used to define the TRNG KAT modes. Used by clients + * when configuring the TRNG for testing + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_TRNG_NEG_0 = 0, /*!< TRNG Neg Zero Test */ + ICP_QAT_HW_TRNG_NEG_1 = 1, /*!< TRNG Neg One Test */ + ICP_QAT_HW_TRNG_POS = 2, /*!< TRNG POS Test */ + ICP_QAT_HW_TRNG_POS_VNC = 3, /*!< TRNG POS VNC Test */ + ICP_QAT_HW_TRNG_KAT_DELIMITER = 4 /**< Delimiter type */ +} icp_qat_hw_trng_kat_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * TRNG mode configuration structure. + * + * @description + * Definition of the format of the TRNG slice configuration. Used + * internally by the QAT FW for configuration of the KAT unit or the + * TRNG depending on the slice command i.e. either a set_slice_config or + * slice_wr_KAT_type + * + *****************************************************************************/ + +typedef struct icp_qat_hw_trng_config_s { + uint32_t val; + /**< Configuration used for setting up the TRNG slice */ + + uint32_t reserved; + /**< Reserved */ +} icp_qat_hw_trng_config_t; + +/* Private Defines */ + +/* Note: Bit positions have been arranged for little endian ordering */ + +#define QAT_TRNG_CONFIG_MODE_MASK 0x7 +/**< @ingroup icp_qat_hw_defs + * Mask for the TRNG configuration mode. (Three bits) */ + +#define QAT_TRNG_CONFIG_MODE_BITPOS 5 +/**< @ingroup icp_qat_hw_defs + * TRNG configuration mode bit positions start */ + +#define QAT_TRNG_KAT_MODE_MASK 0x3 +/**< @ingroup icp_qat_hw_defs + * Mask of two bits for the TRNG known answer test mode */ + +#define QAT_TRNG_KAT_MODE_BITPOS 6 +/**< @ingroup icp_qat_hw_defs + * TRNG known answer test mode bit positions start */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Build the configuration byte for the TRNG slice based on the mode + * + * @param mode Configuration mode parameter + * + *****************************************************************************/ +#define ICP_QAT_HW_TRNG_CONFIG_MODE_BUILD(mode) \ + (((mode)&QAT_TRNG_CONFIG_MODE_MASK) << QAT_TRNG_CONFIG_MODE_BITPOS) + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Build the configuration byte for the TRNG KAT based on the mode + * + * @param mode Configuration mode parameter + * + *****************************************************************************/ +#define ICP_QAT_HW_TRNG_KAT_MODE_BUILD(mode) \ + ((((mode)&QAT_TRNG_KAT_MODE_MASK) << QAT_TRNG_KAT_MODE_BITPOS)) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * TRNG test status structure. + * + * @description + * Definition of the format of the TRNG slice test status structure. Used + * internally by the QAT FW. + * + *****************************************************************************/ + +typedef struct icp_qat_hw_trng_test_status_s { + + uint32_t status; + /**< Status used for setting up the TRNG slice */ + + uint32_t fail_count; + /**< Comparator fail count */ +} icp_qat_hw_trng_test_status_t; + +#define ICP_QAT_HW_TRNG_TEST_NO_FAILURES 1 +/**< @ingroup icp_qat_hw_defs + * Flag to indicate that there were no Test Failures */ + +#define ICP_QAT_HW_TRNG_TEST_FAILURES_FOUND 0 +/**< @ingroup icp_qat_hw_defs + * Flag to indicate that there were Test Failures */ + +#define ICP_QAT_HW_TRNG_TEST_STATUS_VALID 1 +/**< @ingroup icp_qat_hw_defs + * Flag to indicate that there is no valid Test output */ + +#define ICP_QAT_HW_TRNG_TEST_STATUS_INVALID 0 +/**< @ingroup icp_qat_hw_defs + * Flag to indicate that the Test output is still invalid */ + +/* Private defines */ +#define QAT_TRNG_TEST_FAILURE_FLAG_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Mask of one bit used to determine the TRNG Test pass/fail */ + +#define QAT_TRNG_TEST_FAILURE_FLAG_BITPOS 4 +/**< @ingroup icp_qat_hw_defs + * Flag position to indicate that the TRNG Test status is pass of fail */ + +#define QAT_TRNG_TEST_STATUS_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Mask of one bit used to determine the TRNG Test staus */ + +#define QAT_TRNG_TEST_STATUS_BITPOS 1 +/**< @ingroup icp_qat_hw_defs + * Flag position to indicate the TRNG Test status */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Extract the fail bit for the TRNG slice + * + * @param status TRNG status value + * + *****************************************************************************/ + +#define ICP_QAT_HW_TRNG_FAIL_FLAG_GET(status) \ + (((status) >> QAT_TRNG_TEST_FAILURE_FLAG_BITPOS) & \ + QAT_TRNG_TEST_FAILURE_FLAG_MASK) + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Extract the status valid bit for the TRNG slice + * + * @param status TRNG status value + * + *****************************************************************************/ +#define ICP_QAT_HW_TRNG_STATUS_VALID_GET(status) \ + (((status) >> QAT_TRNG_TEST_STATUS_BITPOS) & QAT_TRNG_TEST_STATUS_MASK) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * TRNG entropy counters + * + * @description + * Definition of the format of the TRNG entropy counters. Used internally + * by the QAT FW. + * + *****************************************************************************/ + +typedef struct icp_qat_hw_trng_entropy_counts_s { + uint64_t raw_ones_count; + /**< Count of raw ones of entropy */ + + uint64_t raw_zeros_count; + /**< Count of raw zeros of entropy */ + + uint64_t cond_ones_count; + /**< Count of conditioned ones entropy */ + + uint64_t cond_zeros_count; + /**< Count of conditioned zeros entropy */ +} icp_qat_hw_trng_entropy_counts_t; + +/* Private defines */ +#define QAT_HW_TRNG_ENTROPY_STS_RSVD_SZ 4 +/**< @ingroup icp_qat_hw_defs + * TRNG entropy status reserved size in bytes */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * TRNG entropy available status. + * + * @description + * Definition of the format of the TRNG slice entropy status available. + * struct. Used internally by the QAT FW. + * + *****************************************************************************/ +typedef struct icp_qat_hw_trng_entropy_status_s { + uint32_t status; + /**< Entropy status in the TRNG */ + + uint8_t reserved[QAT_HW_TRNG_ENTROPY_STS_RSVD_SZ]; + /**< Reserved */ +} icp_qat_hw_trng_entropy_status_t; + +#define ICP_QAT_HW_TRNG_ENTROPY_AVAIL 1 +/**< @ingroup icp_qat_hw_defs + * Flag indicating that entropy data is available in the QAT TRNG slice */ + +#define ICP_QAT_HW_TRNG_ENTROPY_NOT_AVAIL 0 +/**< @ingroup icp_qat_hw_defs + * Flag indicating that no entropy data is available in the QAT TRNG slice */ + +/* Private defines */ +#define QAT_TRNG_ENTROPY_STATUS_MASK 1 +/**< @ingroup icp_qat_hw_defs + * Mask of one bit used to determine the TRNG Entropy status */ + +#define QAT_TRNG_ENTROPY_STATUS_BITPOS 0 +/**< @ingroup icp_qat_hw_defs + * Starting bit position for TRNG Entropy status. */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Extract the entropy available status bit + * + * @param status TRNG status value + * + *****************************************************************************/ +#define ICP_QAT_HW_TRNG_ENTROPY_STATUS_GET(status) \ + (((status) >> QAT_TRNG_ENTROPY_STATUS_BITPOS) & \ + QAT_TRNG_ENTROPY_STATUS_MASK) + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Entropy seed data + * + * @description + * This type is used for the definition of the entropy generated by a read + * of the TRNG slice + * + *****************************************************************************/ +typedef uint64_t icp_qat_hw_trng_entropy; + +/* ========================================================================= */ +/* COMPRESSION SLICE */ +/* ========================================================================= */ + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported compression directions + * @description + * Enumeration used to define the compression directions + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_COMPRESSION_DIR_COMPRESS = 0, /*!< Compression */ + ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS = 1, /*!< Decompression */ + ICP_QAT_HW_COMPRESSION_DIR_DELIMITER = 2 /**< Delimiter type */ +} icp_qat_hw_compression_direction_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported delayed match modes + * @description + * Enumeration used to define whether delayed match is enabled + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED = 0, + /*!< Delayed match disabled */ + + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED = 1, + /*!< Delayed match enabled + Note: This is the only valid mode - refer to CPM1.6 SAS */ + + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DELIMITER = 2 + /**< Delimiter type */ + +} icp_qat_hw_compression_delayed_match_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported compression algorithms + * @description + * Enumeration used to define the compression algorithms + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE = 0, /*!< Deflate compression */ + ICP_QAT_HW_COMPRESSION_DEPRECATED = 1, /*!< Deprecated */ + ICP_QAT_HW_COMPRESSION_ALGO_DELIMITER = 2 /**< Delimiter type */ +} icp_qat_hw_compression_algo_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported compression depths + * @description + * Enumeration used to define the compression slice depths. + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_COMPRESSION_DEPTH_1 = 0, + /*!< Search depth 1 (Fastest least exhaustive) */ + + ICP_QAT_HW_COMPRESSION_DEPTH_4 = 1, + /*!< Search depth 4 */ + + ICP_QAT_HW_COMPRESSION_DEPTH_8 = 2, + /*!< Search depth 8 */ + + ICP_QAT_HW_COMPRESSION_DEPTH_16 = 3, + /*!< Search depth 16 */ + + ICP_QAT_HW_COMPRESSION_DEPTH_128 = 4, + /*!< Search depth 128 (Slowest, most exhaustive) */ + + ICP_QAT_HW_COMPRESSION_DEPTH_DELIMITER = 5 + /**< Delimiter type */ + +} icp_qat_hw_compression_depth_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Definition of the supported file types + * @description + * Enumeration used to define the compression file types. + * + *****************************************************************************/ + +typedef enum { + ICP_QAT_HW_COMPRESSION_FILE_TYPE_0 = 0, + /*!< Use Static Trees */ + + ICP_QAT_HW_COMPRESSION_FILE_TYPE_1 = 1, + /*!< Use Semi-Dynamic Trees at offset 0 */ + + ICP_QAT_HW_COMPRESSION_FILE_TYPE_2 = 2, + /*!< Use Semi-Dynamic Trees at offset 320 */ + + ICP_QAT_HW_COMPRESSION_FILE_TYPE_3 = 3, + /*!< Use Semi-Dynamic Trees at offset 640 */ + + ICP_QAT_HW_COMPRESSION_FILE_TYPE_4 = 4, + /*!< Use Semi-Dynamic Trees at offset 960 */ + + ICP_QAT_HW_COMPRESSION_FILE_TYPE_DELIMITER = 5 + /**< Delimiter type */ + +} icp_qat_hw_compression_file_type_t; + +typedef enum { + BNP_SKIP_MODE_DISABLED = 0, + BNP_SKIP_MODE_AT_START = 1, + BNP_SKIP_MODE_AT_END = 2, + BNP_SKIP_MODE_STRIDE = 3 +} icp_qat_bnp_skip_mode_t; + +/** + ***************************************************************************** + * @ingroup icp_qat_hw_defs + * Compression Configuration Struct + * + * @description + * Configuration data used for setting up the QAT Compression Slice + * + *****************************************************************************/ + +typedef struct icp_qat_hw_compression_config_s { + uint32_t val; + /**< Compression slice configuration */ + + uint32_t reserved; + /**< Reserved */ +} icp_qat_hw_compression_config_t; + +/* Private defines */ +#define QAT_COMPRESSION_DIR_BITPOS 4 +/**< @ingroup icp_qat_hw_defs + * Define for the compression direction bit position */ + +#define QAT_COMPRESSION_DIR_MASK 0x7 +/**< @ingroup icp_qat_hw_defs + * Define for the compression direction mask (three bits) */ + +#define QAT_COMPRESSION_DELAYED_MATCH_BITPOS 16 +/**< @ingroup icp_qat_hw_defs + * Define for the compression delayed match bit position */ + +#define QAT_COMPRESSION_DELAYED_MATCH_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Define for the delayed match mask (one bit) */ + +#define QAT_COMPRESSION_ALGO_BITPOS 31 +/**< @ingroup icp_qat_hw_defs + * Define for the compression algorithm bit position */ + +#define QAT_COMPRESSION_ALGO_MASK 0x1 +/**< @ingroup icp_qat_hw_defs + * Define for the compression algorithm mask (one bit) */ + +#define QAT_COMPRESSION_DEPTH_BITPOS 28 +/**< @ingroup icp_qat_hw_defs + * Define for the compression depth bit position */ + +#define QAT_COMPRESSION_DEPTH_MASK 0x7 +/**< @ingroup icp_qat_hw_defs + * Define for the compression depth mask (three bits) */ + +#define QAT_COMPRESSION_FILE_TYPE_BITPOS 24 +/**< @ingroup icp_qat_hw_defs + * Define for the compression file type bit position */ + +#define QAT_COMPRESSION_FILE_TYPE_MASK 0xF +/**< @ingroup icp_qat_hw_defs + * Define for the compression file type mask (four bits) */ + +/** + ****************************************************************************** + * @ingroup icp_qat_hw_defs + * + * @description + * Build the compression slice configuration field + * + * @param dir Compression Direction to use, compress or decompress + * @param delayed Specify if delayed match should be enabled + * @param algo Compression algorithm to use + * @param depth Compression search depth to use + * @param filetype Compression file type to use, static or semi dynamic trees + * + *****************************************************************************/ +#define ICP_QAT_HW_COMPRESSION_CONFIG_BUILD( \ + dir, delayed, algo, depth, filetype) \ + ((((dir)&QAT_COMPRESSION_DIR_MASK) << QAT_COMPRESSION_DIR_BITPOS) | \ + (((delayed)&QAT_COMPRESSION_DELAYED_MATCH_MASK) \ + << QAT_COMPRESSION_DELAYED_MATCH_BITPOS) | \ + (((algo)&QAT_COMPRESSION_ALGO_MASK) << QAT_COMPRESSION_ALGO_BITPOS) | \ + (((depth)&QAT_COMPRESSION_DEPTH_MASK) \ + << QAT_COMPRESSION_DEPTH_BITPOS) | \ + (((filetype)&QAT_COMPRESSION_FILE_TYPE_MASK) \ + << QAT_COMPRESSION_FILE_TYPE_BITPOS)) + +/* ========================================================================= */ +/* TRANSLATOR SLICE */ +/* ========================================================================= */ + +/**< Translator slice configuration is set internally by the firmware */ + +#endif /* _ICP_QAT_HW_H_ */ diff --git a/sys/dev/qat/qat_api/freebsd_module.c b/sys/dev/qat/qat_api/freebsd_module.c new file mode 100644 index 00000000000..9e5e9b931f4 --- /dev/null +++ b/sys/dev/qat/qat_api/freebsd_module.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg.h" +#include "cpa.h" +#include "icp_accel_devices.h" +#include "adf_common_drv.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "lac_sal_ctrl.h" + +extern struct mtx *adfDevicesLock; + +static int +adf_module_load(void) +{ + CpaStatus ret = CPA_STATUS_SUCCESS; + + qatUtilsMutexInit(&adfDevicesLock); + ret = SalCtrl_AdfServicesRegister(); + if (ret != CPA_STATUS_SUCCESS) { + qatUtilsMutexDestroy(&adfDevicesLock); + return EFAULT; + } + + return 0; +} + +static int +adf_module_unload(void) +{ + CpaStatus ret = CPA_STATUS_SUCCESS; + + ret = SalCtrl_AdfServicesUnregister(); + if (ret != CPA_STATUS_SUCCESS) { + return EBUSY; + } + qatUtilsMutexDestroy(&adfDevicesLock); + + return 0; +} + +static int +adf_modevent(module_t mod, int type, void *arg) +{ + int error; + + switch (type) { + case MOD_LOAD: + error = adf_module_load(); + break; + case MOD_UNLOAD: + error = adf_module_unload(); + break; + default: + error = EOPNOTSUPP; + break; + } + + return (error); +} + +static moduledata_t adf_mod = { "qat_api", adf_modevent, 0 }; + +DECLARE_MODULE(qat_api, adf_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); +MODULE_VERSION(qat_api, 1); +MODULE_DEPEND(qat_api, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_api, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_api/include/cpa.h b/sys/dev/qat/qat_api/include/cpa.h new file mode 100644 index 00000000000..359f50e3d89 --- /dev/null +++ b/sys/dev/qat/qat_api/include/cpa.h @@ -0,0 +1,677 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa.h + * + * @defgroup cpa CPA API + * + * @description + * This is the top level API definition for Intel(R) QuickAssist Technology. + * It contains structures, data types and definitions that are common + * across the interface. + * + *****************************************************************************/ + +/** + ***************************************************************************** + * @defgroup cpa_BaseDataTypes Base Data Types + * @file cpa.h + * + * @ingroup cpa + * + * @description + * The base data types for the Intel CPA API. + * + *****************************************************************************/ + +#ifndef CPA_H +#define CPA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_types.h" + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance handle type. + * + * @description + * Handle used to uniquely identify an instance. + * + * @note + * Where only a single instantiation exists this field may be set to + * @ref CPA_INSTANCE_HANDLE_SINGLE. + * + *****************************************************************************/ +typedef void * CpaInstanceHandle; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Default instantiation handle value where there is only a single instance + * + * @description + * Used as an instance handle value where only one instance exists. + * + *****************************************************************************/ +#define CPA_INSTANCE_HANDLE_SINGLE ((CpaInstanceHandle)0) + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Physical memory address. + * @description + * Type for physical memory addresses. + *****************************************************************************/ +typedef Cpa64U CpaPhysicalAddr; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Virtual to physical address conversion routine. + * + * @description + * This function is used to convert virtual addresses to physical + * addresses. + * + * @context + * The function shall not be called in an interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pVirtualAddr Virtual address to be converted. + * + * @return + * Returns the corresponding physical address. + * On error, the value NULL is returned. + * + * @post + * None + * @see + * None + * + *****************************************************************************/ +typedef CpaPhysicalAddr (*CpaVirtualToPhysical)(void * pVirtualAddr); + + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Flat buffer structure containing a pointer and length member. + * + * @description + * A flat buffer structure. The data pointer, pData, is a virtual address. + * An API instance may require the actual data to be in contiguous + * physical memory as determined by @ref CpaInstanceInfo2. + * + *****************************************************************************/ +typedef struct _CpaFlatBuffer { + Cpa32U dataLenInBytes; + /**< Data length specified in bytes. + * When used as an input parameter to a function, the length specifies + * the current length of the buffer. + * When used as an output parameter to a function, the length passed in + * specifies the maximum length of the buffer on return (i.e. the allocated + * length). The implementation will not write past this length. On return, + * the length is always unchanged. */ + Cpa8U *pData; + /**< The data pointer is a virtual address, however the actual data pointed + * to is required to be in contiguous physical memory unless the field + requiresPhysicallyContiguousMemory in CpaInstanceInfo2 is false. */ +} CpaFlatBuffer; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Scatter/Gather buffer list containing an array of flat buffers. + * + * @description + * A scatter/gather buffer list structure. This buffer structure is + * typically used to represent a region of memory which is not + * physically contiguous, by describing it as a collection of + * buffers, each of which is physically contiguous. + * + * @note + * The memory for the pPrivateMetaData member must be allocated + * by the client as physically contiguous memory. When allocating + * memory for pPrivateMetaData, a call to the corresponding + * BufferListGetMetaSize function (e.g. cpaCyBufferListGetMetaSize) + * MUST be made to determine the size of the Meta Data Buffer. The + * returned size (in bytes) may then be passed in a memory allocation + * routine to allocate the pPrivateMetaData memory. + *****************************************************************************/ +typedef struct _CpaBufferList { + Cpa32U numBuffers; + /**< Number of buffers in the list */ + CpaFlatBuffer *pBuffers; + /**< Pointer to an unbounded array containing the number of CpaFlatBuffers + * defined by numBuffers + */ + void *pUserData; + /**< This is an opaque field that is not read or modified internally. */ + void *pPrivateMetaData; + /**< Private representation of this buffer list. The memory for this + * buffer needs to be allocated by the client as contiguous data. + * The amount of memory required is returned with a call to + * the corresponding BufferListGetMetaSize function. If that function + * returns a size of zero then no memory needs to be allocated, and this + * parameter can be NULL. + */ +} CpaBufferList; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Flat buffer structure with physical address. + * + * @description + * Functions taking this structure do not need to do any virtual to + * physical address translation before writing the buffer to hardware. + *****************************************************************************/ +typedef struct _CpaPhysFlatBuffer { + Cpa32U dataLenInBytes; + /**< Data length specified in bytes. + * When used as an input parameter to a function, the length specifies + * the current length of the buffer. + * When used as an output parameter to a function, the length passed in + * specifies the maximum length of the buffer on return (i.e. the allocated + * length). The implementation will not write past this length. On return, + * the length is always unchanged. + */ + Cpa32U reserved; + /**< Reserved for alignment */ + CpaPhysicalAddr bufferPhysAddr; + /**< The physical address at which the data resides. The data pointed + * to is required to be in contiguous physical memory. + */ +} CpaPhysFlatBuffer; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Scatter/gather list containing an array of flat buffers with + * physical addresses. + * + * @description + * Similar to @ref CpaBufferList, this buffer structure is typically + * used to represent a region of memory which is not physically + * contiguous, by describing it as a collection of buffers, each of + * which is physically contiguous. The difference is that, in this + * case, the individual "flat" buffers are represented using + * physical, rather than virtual, addresses. + *****************************************************************************/ +typedef struct _CpaPhysBufferList { + Cpa64U reserved0; + /**< Reserved for internal usage */ + Cpa32U numBuffers; + /**< Number of buffers in the list */ + Cpa32U reserved1; + /**< Reserved for alignment */ + CpaPhysFlatBuffer flatBuffers[]; + /**< Array of flat buffer structures, of size numBuffers */ +} CpaPhysBufferList; + + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Special value which can be taken by length fields on some of the + * "data plane" APIs to indicate that the buffer in question is of + * type CpaPhysBufferList, rather than simply an array of bytes. + ****************************************************************************/ +#define CPA_DP_BUFLIST ((Cpa32U)0xFFFFFFFF) + + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * API status value type definition + * + * @description + * This type definition is used for the return values used in all the + * API functions. Common values are defined, for example see + * @ref CPA_STATUS_SUCCESS, @ref CPA_STATUS_FAIL, etc. + *****************************************************************************/ +typedef Cpa32S CpaStatus; + +#define CPA_STATUS_SUCCESS (0) +/**< + * @ingroup cpa_BaseDataTypes + * Success status value. */ +#define CPA_STATUS_FAIL (-1) +/**< + * @ingroup cpa_BaseDataTypes + * Fail status value. */ +#define CPA_STATUS_RETRY (-2) +/**< + * @ingroup cpa_BaseDataTypes + * Retry status value. */ +#define CPA_STATUS_RESOURCE (-3) +/**< + * @ingroup cpa_BaseDataTypes + * The resource that has been requested is unavailable. Refer + * to relevant sections of the API for specifics on what the suggested + * course of action is. */ +#define CPA_STATUS_INVALID_PARAM (-4) +/**< + * @ingroup cpa_BaseDataTypes + * Invalid parameter has been passed in. */ +#define CPA_STATUS_FATAL (-5) +/**< + * @ingroup cpa_BaseDataTypes + * A serious error has occurred. Recommended course of action + * is to shutdown and restart the component. */ +#define CPA_STATUS_UNSUPPORTED (-6) +/**< + * @ingroup cpa_BaseDataTypes + * The function is not supported, at least not with the specific + * parameters supplied. This may be because a particular + * capability is not supported by the current implementation. */ +#define CPA_STATUS_RESTARTING (-7) +/**< + * @ingroup cpa_BaseDataTypes + * The API implementation is restarting. This may be reported if, for example, + * a hardware implementation is undergoing a reset. Recommended course of + * action is to retry the request. */ + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * API status string type definition + * @description + * This type definition is used for the generic status text strings + * provided by cpaXxGetStatusText API functions. Common values are + * defined, for example see @ref CPA_STATUS_STR_SUCCESS, + * @ref CPA_STATUS_FAIL, etc., as well as the maximum size + * @ref CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. + *****************************************************************************/ +#define CPA_STATUS_MAX_STR_LENGTH_IN_BYTES (255) +/**< + * @ingroup cpa_BaseDataTypes + * Maximum length of the Overall Status String (including generic and specific + * strings returned by calls to cpaXxGetStatusText) */ + +#define CPA_STATUS_STR_SUCCESS ("Operation was successful:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_SUCCESS. */ +#define CPA_STATUS_STR_FAIL ("General or unspecified error occurred:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_FAIL. */ +#define CPA_STATUS_STR_RETRY ("Recoverable error occurred:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_RETRY. */ +#define CPA_STATUS_STR_RESOURCE ("Required resource unavailable:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_RESOURCE. */ +#define CPA_STATUS_STR_INVALID_PARAM ("Invalid parameter supplied:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_INVALID_PARAM. */ +#define CPA_STATUS_STR_FATAL ("Fatal error has occurred:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_FATAL. */ +#define CPA_STATUS_STR_UNSUPPORTED ("Operation not supported:") +/**< + * @ingroup cpa_BaseDataTypes + * Status string for @ref CPA_STATUS_UNSUPPORTED. */ + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance Types + * + * @deprecated + * As of v1.3 of the Crypto API, this enum has been deprecated, + * replaced by @ref CpaAccelerationServiceType. + * + * @description + * Enumeration of the different instance types. + * + *****************************************************************************/ +typedef enum _CpaInstanceType +{ + CPA_INSTANCE_TYPE_CRYPTO = 0, + /**< Cryptographic instance type */ + CPA_INSTANCE_TYPE_DATA_COMPRESSION, + /**< Data compression instance type */ + CPA_INSTANCE_TYPE_RAID, + /**< RAID instance type */ + CPA_INSTANCE_TYPE_XML, + /**< XML instance type */ + CPA_INSTANCE_TYPE_REGEX + /**< Regular Expression instance type */ +} CpaInstanceType CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Service Type + * @description + * Enumeration of the different service types. + * + *****************************************************************************/ +typedef enum _CpaAccelerationServiceType +{ + CPA_ACC_SVC_TYPE_CRYPTO = CPA_INSTANCE_TYPE_CRYPTO, + /**< Cryptography */ + CPA_ACC_SVC_TYPE_DATA_COMPRESSION = CPA_INSTANCE_TYPE_DATA_COMPRESSION, + /**< Data Compression */ + CPA_ACC_SVC_TYPE_PATTERN_MATCH = CPA_INSTANCE_TYPE_REGEX, + /**< Pattern Match */ + CPA_ACC_SVC_TYPE_RAID = CPA_INSTANCE_TYPE_RAID, + /**< RAID */ + CPA_ACC_SVC_TYPE_XML = CPA_INSTANCE_TYPE_XML, + /**< XML */ + CPA_ACC_SVC_TYPE_VIDEO_ANALYTICS + /**< Video Analytics */ +} CpaAccelerationServiceType; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance State + * + * @deprecated + * As of v1.3 of the Crypto API, this enum has been deprecated, + * replaced by @ref CpaOperationalState. + * + * @description + * Enumeration of the different instance states that are possible. + * + *****************************************************************************/ +typedef enum _CpaInstanceState +{ + CPA_INSTANCE_STATE_INITIALISED = 0, + /**< Instance is in the initialized state and ready for use. */ + CPA_INSTANCE_STATE_SHUTDOWN + /**< Instance is in the shutdown state and not available for use. */ +} CpaInstanceState CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance operational state + * @description + * Enumeration of the different operational states that are possible. + * + *****************************************************************************/ +typedef enum _CpaOperationalState +{ + CPA_OPER_STATE_DOWN= 0, + /**< Instance is not available for use. May not yet be initialized, + * or stopped. */ + CPA_OPER_STATE_UP + /**< Instance is available for use. Has been initialized and started. */ +} CpaOperationalState; + +#define CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES 64 +/**< + * @ingroup cpa_BaseDataTypes + * Maximum instance info name string length in bytes */ +#define CPA_INSTANCE_MAX_ID_SIZE_IN_BYTES 128 +/**< + * @ingroup cpa_BaseDataTypes + * Maximum instance info id string length in bytes */ +#define CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES 64 +/**< + * @ingroup cpa_BaseDataTypes + * Maximum instance info version string length in bytes */ + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance Info Structure + * + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by CpaInstanceInfo2. + * + * @description + * Structure that contains the information to describe the instance. + * + *****************************************************************************/ +typedef struct _CpaInstanceInfo { + enum _CpaInstanceType type; + /**< Type definition for this instance. */ + enum _CpaInstanceState state; + /**< Operational state of the instance. */ + Cpa8U name[CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES]; + /**< Simple text string identifier for the instance. */ + Cpa8U version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES]; + /**< Version string. There may be multiple versions of the same type of + * instance accessible through a particular library. */ +} CpaInstanceInfo CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Physical Instance ID + * @description + * Identifies the physical instance of an accelerator execution + * engine. + * + * Accelerators grouped into "packages". Each accelerator can in + * turn contain one or more execution engines. Implementations of + * this API will define the packageId, acceleratorId, + * executionEngineId and busAddress as appropriate for the + * implementation. For example, for hardware-based accelerators, + * the packageId might identify the chip, which might contain + * multiple accelerators, each of which might contain multiple + * execution engines. The combination of packageId, acceleratorId + * and executionEngineId uniquely identifies the instance. + * + * Hardware based accelerators implementing this API may also provide + * information on the location of the accelerator in the busAddress + * field. This field will be defined as appropriate for the + * implementation. For example, for PCIe attached accelerators, + * the busAddress may contain the PCIe bus, device and function + * number of the accelerators. + * + *****************************************************************************/ +typedef struct _CpaPhysicalInstanceId { + Cpa16U packageId; + /**< Identifies the package within which the accelerator is + * contained. */ + Cpa16U acceleratorId; + /**< Identifies the specific accelerator within the package. */ + Cpa16U executionEngineId; + /**< Identifies the specific execution engine within the + * accelerator. */ + Cpa16U busAddress; + /**< Identifies the bus address associated with the accelerator + * execution engine. */ + Cpa32U kptAcHandle; + /**< Identifies the achandle of the accelerator. */ +} CpaPhysicalInstanceId; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance Info Structure, version 2 + * @description + * Structure that contains the information to describe the instance. + * + *****************************************************************************/ +typedef struct _CpaInstanceInfo2 { + CpaAccelerationServiceType accelerationServiceType; + /**< Type of service provided by this instance. */ +#define CPA_INST_VENDOR_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES + /**< Maximum length of the vendor name. */ + Cpa8U vendorName[CPA_INST_VENDOR_NAME_SIZE]; + /**< String identifying the vendor of the accelerator. */ + +#define CPA_INST_PART_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES + /**< Maximum length of the part name. */ + Cpa8U partName[CPA_INST_PART_NAME_SIZE]; + /**< String identifying the part (name and/or number). */ + +#define CPA_INST_SW_VERSION_SIZE CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES + /**< Maximum length of the software version string. */ + Cpa8U swVersion[CPA_INST_SW_VERSION_SIZE]; + /**< String identifying the version of the software associated with + * the instance. For hardware-based implementations of the API, + * this should be the driver version. For software-based + * implementations of the API, this should be the version of the + * library. + * + * Note that this should NOT be used to store the version of the + * API, nor should it be used to report the hardware revision + * (which can be captured as part of the @ref partName, if required). */ + +#define CPA_INST_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES + /**< Maximum length of the instance name. */ + Cpa8U instName[CPA_INST_NAME_SIZE]; + /**< String identifying the name of the instance. */ + +#define CPA_INST_ID_SIZE CPA_INSTANCE_MAX_ID_SIZE_IN_BYTES + Cpa8U instID[CPA_INST_ID_SIZE]; + /**< String containing a unique identifier for the instance */ + + CpaPhysicalInstanceId physInstId; + /**< Identifies the "physical instance" of the accelerator. */ + +#define CPA_MAX_CORES 256 + /**< Maximum number of cores to support in the coreAffinity bitmap. */ + CPA_BITMAP(coreAffinity, CPA_MAX_CORES); + /**< A bitmap identifying the core or cores to which the instance + * is affinitized in an SMP operating system. + * + * The term core here is used to mean a "logical" core - for example, + * in a dual-processor, quad-core system with hyperthreading (two + * threads per core), there would be 16 such cores (2 processors x + * 4 cores/processor x 2 threads/core). The numbering of these cores + * and the corresponding bit positions is OS-specific. Note that Linux + * refers to this as "processor affinity" or "CPU affinity", and refers + * to the bitmap as a "cpumask". + * + * The term "affinity" is used to mean that this is the core on which + * the callback function will be invoked when using the asynchronous + * mode of the API. In a hardware-based implementation of the API, + * this might be the core to which the interrupt is affinitized. + * In a software-based implementation, this might be the core to which + * the process running the algorithm is affinitized. Where there is + * no affinity, the bitmap can be set to all zeroes. + * + * This bitmap should be manipulated using the macros @ref + * CPA_BITMAP_BIT_SET, @ref CPA_BITMAP_BIT_CLEAR and @ref + * CPA_BITMAP_BIT_TEST. */ + + Cpa32U nodeAffinity; + /**< Identifies the processor complex, or node, to which the accelerator + * is physically connected, to help identify locality in NUMA systems. + * + * The values taken by this attribute will typically be in the range + * 0..n-1, where n is the number of nodes (processor complexes) in the + * system. For example, in a dual-processor configuration, n=2. The + * precise values and their interpretation are OS-specific. */ + + CpaOperationalState operState; + /**< Operational state of the instance. */ + CpaBoolean requiresPhysicallyContiguousMemory; + /**< Specifies whether the data pointed to by flat buffers + * (CpaFlatBuffer::pData) supplied to this instance must be in + * physically contiguous memory. */ + CpaBoolean isPolled; + /**< Specifies whether the instance must be polled, or is event driven. + * For hardware accelerators, the alternative to polling would be + * interrupts. */ + CpaBoolean isOffloaded; + /**< Identifies whether the instance uses hardware offload, or is a + * software-only implementation. */ +} CpaInstanceInfo2; + +/** + ***************************************************************************** + * @ingroup cpa_BaseDataTypes + * Instance Events + * @description + * Enumeration of the different events that will cause the registered + * Instance notification callback function to be invoked. + * + *****************************************************************************/ +typedef enum _CpaInstanceEvent +{ + CPA_INSTANCE_EVENT_RESTARTING = 0, + /**< Event type that triggers the registered instance notification callback + * function when and instance is restarting. The reason why an instance is + * restarting is implementation specific. For example a hardware + * implementation may send this event if the hardware device is about to + * be reset. + */ + CPA_INSTANCE_EVENT_RESTARTED, + /**< Event type that triggers the registered instance notification callback + * function when and instance has restarted. The reason why an instance has + * restarted is implementation specific. For example a hardware + * implementation may send this event after the hardware device has + * been reset. + */ + CPA_INSTANCE_EVENT_FATAL_ERROR + /**< Event type that triggers the registered instance notification callback + * function when an error has been detected that requires the device + * to be reset. + * This event will be sent by all instances using the device, both on the + * host and guests. + */ +} CpaInstanceEvent; + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_H */ diff --git a/sys/dev/qat/qat_api/include/cpa_dev.h b/sys/dev/qat/qat_api/include/cpa_dev.h new file mode 100644 index 00000000000..0beae449fcc --- /dev/null +++ b/sys/dev/qat/qat_api/include/cpa_dev.h @@ -0,0 +1,144 @@ +/**************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_dev.h + * + * @defgroup cpaDev Device API + * + * @ingroup cpa + * + * @description + * These functions specify the API for device level operation. + * + * @remarks + * + * + *****************************************************************************/ + +#ifndef CPA_DEV_H +#define CPA_DEV_H + +#ifdef __cplusplus +extern"C" { +#endif + + +#ifndef CPA_H +#include "cpa.h" +#endif + + + /***************************************************************************** + * @ingroup cpaDev + * Returns device information + * + * @description + * This data structure contains the device information. The device + * information are available to both Physical and Virtual Functions. + * Depending on the resource partitioning configuration, the services + * available may changes. This configuration will impact the size of the + * Security Association Database (SADB). Other properties such device SKU + * and device ID are also reported. + * + *****************************************************************************/ +typedef struct _CpaDeviceInfo { + Cpa32U sku; + /**< Identifies the SKU of the device. */ + Cpa16U bdf; + /**< Identifies the Bus Device Function of the device. + * Format is reported as follow: + * - bits<2:0> represent the function number. + * - bits<7:3> represent the device + * - bits<15:8> represent the bus + */ + Cpa32U deviceId; + /**< Returns the device ID. */ + Cpa32U numaNode; + /**< Return the local NUMA node mapped to the device. */ + CpaBoolean isVf; + /**< Return whether the device is currently used in a virtual function + * or not. */ + CpaBoolean dcEnabled; + /**< Compression service enabled */ + CpaBoolean cySymEnabled; + /**< Symetric crypto service enabled */ + CpaBoolean cyAsymEnabled; + /**< Asymetric crypto service enabled */ + CpaBoolean inlineEnabled; + /**< Inline service enabled */ + Cpa32U deviceMemorySizeAvailable; + /**< Return the size of the device memory available. This device memory + * section could be used for the intermediate buffers in the + * compression service. + */ +} CpaDeviceInfo; + + +/***************************************************************************** +* @ingroup cpaDev +* Returns number devices. +* +* @description +* This API returns the number of devices available to the application. +* If used on the host, it will return the number of physical devices. +* If used on the guest, it will return the number of function mapped +* to the virtual machine. +* +*****************************************************************************/ +CpaStatus cpaGetNumDevices (Cpa16U *numDevices); + +/***************************************************************************** +* @ingroup cpaDev +* Returns device information for a given device index. +* +* @description +* Returns device information for a given device index. This API must +* be used with cpaGetNumDevices(). +*****************************************************************************/ +CpaStatus cpaGetDeviceInfo (Cpa16U device, CpaDeviceInfo *deviceInfo); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_DEV_H */ diff --git a/sys/dev/qat/qat_api/include/cpa_types.h b/sys/dev/qat/qat_api/include/cpa_types.h new file mode 100644 index 00000000000..91781d390f6 --- /dev/null +++ b/sys/dev/qat/qat_api/include/cpa_types.h @@ -0,0 +1,244 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_types.h + * + * @defgroup cpa_Types CPA Type Definition + * + * @ingroup cpa + * + * @description + * This is the CPA Type Definitions. + * + *****************************************************************************/ + +#ifndef CPA_TYPES_H +#define CPA_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__FreeBSD__) && defined (_KERNEL) + +/* FreeBSD kernel mode */ +#include +#include +#include + +#else + +/* Linux, FreeBSD, or Windows user mode */ +#include +#include +#include + +#endif + +#if defined (WIN32) || defined (_WIN64) +/* nonstandard extension used : zero-sized array in struct/union */ +#pragma warning (disable: 4200) +#endif + +typedef uint8_t Cpa8U; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Unsigned byte base type. */ +typedef int8_t Cpa8S; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Signed byte base type. */ +typedef uint16_t Cpa16U; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Unsigned double-byte base type. */ +typedef int16_t Cpa16S; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Signed double-byte base type. */ +typedef uint32_t Cpa32U; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Unsigned quad-byte base type. */ +typedef int32_t Cpa32S; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Signed quad-byte base type. */ +typedef uint64_t Cpa64U; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Unsigned double-quad-byte base type. */ +typedef int64_t Cpa64S; +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Signed double-quad-byte base type. */ + +/***************************************************************************** + * Generic Base Data Type definitions + *****************************************************************************/ +#ifndef NULL +#define NULL (0) +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * NULL definition. */ +#endif + +#ifndef TRUE +#define TRUE (1==1) +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * True value definition. */ +#endif +#ifndef FALSE +#define FALSE (0==1) +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * False value definition. */ +#endif + +/** + ***************************************************************************** + * @ingroup cpa_Types + * Boolean type. + * + * @description + * Functions in this API use this type for Boolean variables that take + * true or false values. + * + *****************************************************************************/ +typedef enum _CpaBoolean +{ + CPA_FALSE = FALSE, /**< False value */ + CPA_TRUE = TRUE /**< True value */ +} CpaBoolean; + + +/** + ***************************************************************************** + * @ingroup cpa_Types + * Declare a bitmap of specified size (in bits). + * + * @description + * This macro is used to declare a bitmap of arbitrary size. + * + * To test whether a bit in the bitmap is set, use @ref + * CPA_BITMAP_BIT_TEST. + * + * While most uses of bitmaps on the API are read-only, macros are also + * provided to set (see @ref CPA_BITMAP_BIT_SET) and clear (see @ref + * CPA_BITMAP_BIT_CLEAR) bits in the bitmap. + *****************************************************************************/ +#define CPA_BITMAP(name, sizeInBits) \ + Cpa32U name[((sizeInBits)+31)/32] + +#define CPA_BITMAP_BIT_TEST(bitmask, bit) \ + ((bitmask[(bit)/32]) & (0x1 << ((bit)%32))) +/**< + * @ingroup cpa_Types + * Test a specified bit in the specified bitmap. The bitmap may have been + * declared using @ref CPA_BITMAP. Returns a Boolean (true if the bit is + * set, false otherwise). */ + +#define CPA_BITMAP_BIT_SET(bitmask, bit) \ + (bitmask[(bit)/32] |= (0x1 << ((bit)%32))) +/**< + * @file cpa_types.h + * @ingroup cpa_Types + * Set a specified bit in the specified bitmap. The bitmap may have been + * declared using @ref CPA_BITMAP. */ + +#define CPA_BITMAP_BIT_CLEAR(bitmask, bit) \ + (bitmask[(bit)/32] &= ~(0x1 << ((bit)%32))) +/**< + * @ingroup cpa_Types + * Clear a specified bit in the specified bitmap. The bitmap may have been + * declared using @ref CPA_BITMAP. */ + + +/** + ********************************************************************** + * + * @ingroup cpa_Types + * + * @description + * Declare a function or type and mark it as deprecated so that + * usages get flagged with a warning. + * + ********************************************************************** + */ +#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(_WIN64) +/* + * gcc and icc support the __attribute__ ((deprecated)) syntax for marking + * functions and other constructs as deprecated. + */ +/* + * Uncomment the deprecated macro if you need to see which structs are deprecated + */ +#define CPA_DEPRECATED +/*#define CPA_DEPRECATED __attribute__ ((deprecated)) */ +#else +/* + * for all other compilers, define deprecated to do nothing + * + */ +/* #define CPA_DEPRECATED_FUNC(func) func; #pragma deprecated(func) */ +#pragma message("WARNING: You need to implement the CPA_DEPRECATED macro for this compiler") +#define CPA_DEPRECATED +#endif + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_TYPES_H */ diff --git a/sys/dev/qat/qat_api/include/dc/cpa_dc.h b/sys/dev/qat/qat_api/include/dc/cpa_dc.h new file mode 100644 index 00000000000..52d98a67264 --- /dev/null +++ b/sys/dev/qat/qat_api/include/dc/cpa_dc.h @@ -0,0 +1,2461 @@ +/**************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_dc.h + * + * @defgroup cpaDc Data Compression API + * + * @ingroup cpa + * + * @description + * These functions specify the API for Data Compression operations. + * + * @remarks + * + * + *****************************************************************************/ + +#ifndef CPA_DC_H +#define CPA_DC_H + +#ifdef __cplusplus +extern"C" { +#endif + + +#ifndef CPA_H +#include "cpa.h" +#endif + +/** + ***************************************************************************** + * @ingroup cpaDc + * CPA Dc Major Version Number + * @description + * The CPA_DC API major version number. This number will be incremented + * when significant churn to the API has occurred. The combination of the + * major and minor number definitions represent the complete version number + * for this interface. + * + *****************************************************************************/ +#define CPA_DC_API_VERSION_NUM_MAJOR (2) + +/** + ***************************************************************************** + * @ingroup cpaDc + * CPA DC Minor Version Number + * @description + * The CPA_DC API minor version number. This number will be incremented + * when minor changes to the API has occurred. The combination of the major + * and minor number definitions represent the complete version number for + * this interface. + * + *****************************************************************************/ +#define CPA_DC_API_VERSION_NUM_MINOR (2) + +/** + ***************************************************************************** + * @ingroup cpaDc + * Compression API session handle type + * + * @description + * Handle used to uniquely identify a Compression API session handle. This + * handle is established upon registration with the API using + * cpaDcInitSession(). + * + * + * + *****************************************************************************/ +typedef void * CpaDcSessionHandle; + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported file types + * + * @description + * This enumerated lists identified file types. Used to select Huffman + * trees. + * File types are associated with Precompiled Huffman Trees. + * + * @deprecated + * As of v1.6 of the Compression API, this enum has been deprecated. + * + *****************************************************************************/ +typedef enum _CpaDcFileType +{ + CPA_DC_FT_ASCII, + /**< ASCII File Type */ + CPA_DC_FT_CSS, + /**< Cascading Style Sheet File Type */ + CPA_DC_FT_HTML, + /**< HTML or XML (or similar) file type */ + CPA_DC_FT_JAVA, + /**< File Java code or similar */ + CPA_DC_FT_OTHER + /**< Other file types */ +} CpaDcFileType; +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported flush flags + * + * @description + * This enumerated list identifies the types of flush that can be + * specified for stateful and stateless cpaDcCompressData and + * cpaDcDecompressData functions. + * + *****************************************************************************/ +typedef enum _CpaDcFlush +{ + CPA_DC_FLUSH_NONE = 0, + /**< No flush request. */ + CPA_DC_FLUSH_FINAL, + /**< Indicates that the input buffer contains all of the data for + the compression session allowing any buffered data to be released. + For Deflate, BFINAL is set in the compression header.*/ + CPA_DC_FLUSH_SYNC, + /**< Used for stateful deflate compression to indicate that all pending + output is flushed, byte aligned, to the output buffer. The session state + is not reset.*/ + CPA_DC_FLUSH_FULL + /**< Used for deflate compression to indicate that all pending output is + flushed to the output buffer and the session state is reset.*/ +} CpaDcFlush; +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported Huffman Tree types + * + * @description + * This enumeration lists support for Huffman Tree types. + * Selecting Static Huffman trees generates compressed blocks with an RFC + * 1951 header specifying "compressed with fixed Huffman trees". + * + * Selecting Full Dynamic Huffman trees generates compressed blocks with + * an RFC 1951 header specifying "compressed with dynamic Huffman codes". + * The headers are calculated on the data being compressed, requiring two + * passes. + * + * Selecting Precompiled Huffman Trees generates blocks with RFC 1951 + * dynamic headers. The headers are pre-calculated and are specified by + * the file type. + * + *****************************************************************************/ +typedef enum _CpaDcHuffType +{ + CPA_DC_HT_STATIC, + /**< Static Huffman Trees */ + CPA_DC_HT_PRECOMP, + /**< Precompiled Huffman Trees */ + CPA_DC_HT_FULL_DYNAMIC + /**< Full Dynamic Huffman Trees */ +} CpaDcHuffType; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported compression types + * + * @description + * This enumeration lists the supported data compression algorithms. + * In combination with CpaDcChecksum it is used to decide on the file + * header and footer format. + * + * @deprecated + * As of v1.6 of the Compression API, CPA_DC_LZS, CPA_DC_ELZS and + * CPA_DC_LZSS have been deprecated and should not be used. + * + *****************************************************************************/ +typedef enum _CpaDcCompType +{ + CPA_DC_LZS, + /**< LZS Compression */ + CPA_DC_ELZS, + /**< Extended LZS Compression */ + CPA_DC_LZSS, + /**< LZSS Compression */ + CPA_DC_DEFLATE + /**< Deflate Compression */ +} CpaDcCompType; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported checksum algorithms + * + * @description + * This enumeration lists the supported checksum algorithms + * Used to decide on file header and footer specifics. + * + *****************************************************************************/ +typedef enum _CpaDcChecksum +{ + CPA_DC_NONE, + /**< No checksums required */ + CPA_DC_CRC32, + /**< application requires a CRC32 checksum */ + CPA_DC_ADLER32 + /**< Application requires Adler-32 checksum */ +} CpaDcChecksum; + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported session directions + * + * @description + * This enumerated list identifies the direction of a session. + * A session can be compress, decompress or both. + * + *****************************************************************************/ +typedef enum _CpaDcSessionDir +{ + CPA_DC_DIR_COMPRESS, + /**< Session will be used for compression */ + CPA_DC_DIR_DECOMPRESS, + /**< Session will be used for decompression */ + CPA_DC_DIR_COMBINED + /**< Session will be used for both compression and decompression */ +} CpaDcSessionDir; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported session state settings + * + * @description + * This enumerated list identifies the stateful setting of a session. + * A session can be either stateful or stateless. + * + * Stateful sessions are limited to have only one in-flight message per + * session. This means a compress or decompress request must be complete + * before a new request can be started. This applies equally to sessions + * that are uni-directional in nature and sessions that are combined + * compress and decompress. Completion occurs when the synchronous function + * returns, or when the asynchronous callback function has completed. + * + *****************************************************************************/ +typedef enum _CpaDcSessionState +{ + CPA_DC_STATEFUL, + /**< Session will be stateful, implying that state may need to be + saved in some situations */ + CPA_DC_STATELESS + /**< Session will be stateless, implying no state will be stored*/ +} CpaDcSessionState; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported compression levels + * + * @description + * This enumerated lists the supported compressed levels. + * Lower values will result in less compressibility in less time. + * + * + *****************************************************************************/ +typedef enum _CpaDcCompLvl +{ + CPA_DC_L1 = 1, + /**< Compression level 1 */ + CPA_DC_L2, + /**< Compression level 2 */ + CPA_DC_L3, + /**< Compression level 3 */ + CPA_DC_L4, + /**< Compression level 4 */ + CPA_DC_L5, + /**< Compression level 5 */ + CPA_DC_L6, + /**< Compression level 6 */ + CPA_DC_L7, + /**< Compression level 7 */ + CPA_DC_L8, + /**< Compression level 8 */ + CPA_DC_L9 + /**< Compression level 9 */ +} CpaDcCompLvl; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported additional details from accelerator + * + * @description + * This enumeration lists the supported additional details from the + * accelerator. These may be useful in determining the best way to + * recover from a failure. + * + * + *****************************************************************************/ +typedef enum _CpaDcReqStatus +{ + CPA_DC_OK = 0, + /**< No error detected by compression slice */ + CPA_DC_INVALID_BLOCK_TYPE = -1, + /**< Invalid block type (type == 3) */ + CPA_DC_BAD_STORED_BLOCK_LEN = -2, + /**< Stored block length did not match one's complement */ + CPA_DC_TOO_MANY_CODES = -3, + /**< Too many length or distance codes */ + CPA_DC_INCOMPLETE_CODE_LENS = -4, + /**< Code length codes incomplete */ + CPA_DC_REPEATED_LENS = -5, + /**< Repeated lengths with no first length */ + CPA_DC_MORE_REPEAT = -6, + /**< Repeat more than specified lengths */ + CPA_DC_BAD_LITLEN_CODES = -7, + /**< Invalid literal/length code lengths */ + CPA_DC_BAD_DIST_CODES = -8, + /**< Invalid distance code lengths */ + CPA_DC_INVALID_CODE = -9, + /**< Invalid literal/length or distance code in fixed or dynamic block */ + CPA_DC_INVALID_DIST = -10, + /**< Distance is too far back in fixed or dynamic block */ + CPA_DC_OVERFLOW = -11, + /**< Overflow detected. This is an indication that output buffer has overflowed. + * For stateful sessions, this is a warning (the input can be adjusted and + * resubmitted). + * For stateless sessions this is an error condition */ + CPA_DC_SOFTERR = -12, + /**< Other non-fatal detected */ + CPA_DC_FATALERR = -13, + /**< Fatal error detected */ + CPA_DC_MAX_RESUBITERR = -14, + /**< On an error being detected, the firmware attempted to correct and resubmitted the + * request, however, the maximum resubmit value was exceeded */ + CPA_DC_INCOMPLETE_FILE_ERR = -15, + /**< The input file is incomplete. Note this is an indication that the request was + * submitted with a CPA_DC_FLUSH_FINAL, however, a BFINAL bit was not found in the + * request */ + CPA_DC_WDOG_TIMER_ERR = -16, + /**< The request was not completed as a watchdog timer hardware event occurred */ + CPA_DC_EP_HARDWARE_ERR = -17, + /**< Request was not completed as an end point hardware error occurred (for + * example, a parity error) */ + CPA_DC_VERIFY_ERROR = -18, + /**< Error detected during "compress and verify" operation */ + CPA_DC_EMPTY_DYM_BLK = -19, + /**< Decompression request contained an empty dynamic stored block + * (not supported) */ + CPA_DC_CRC_INTEG_ERR = -20, + /**< A data integrity CRC error was detected */ +} CpaDcReqStatus; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported modes for automatically selecting the best compression type. + * + * @description + * This enumeration lists the supported modes for automatically selecting + * the best Huffman encoding which would lead to the best compression + * results. + * + * The CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS value is deprecated + * and should not be used. + * + *****************************************************************************/ +typedef enum _CpaDcAutoSelectBest +{ + CPA_DC_ASB_DISABLED = 0, + /**< Auto select best mode is disabled */ + CPA_DC_ASB_STATIC_DYNAMIC = 1, + /**< Auto select between static and dynamic compression */ + CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS = 2, + /**< Auto select between uncompressed, static and dynamic compression, + * using stored block deflate headers if uncompressed is selected */ + CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS = 3 + /**< Auto select between uncompressed, static and dynamic compression, + * using no deflate headers if uncompressed is selected */ +} CpaDcAutoSelectBest; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Supported modes for skipping regions of input or output buffers. + * + * @description + * This enumeration lists the supported modes for skipping regions of + * input or output buffers. + * + *****************************************************************************/ +typedef enum _CpaDcSkipMode +{ + CPA_DC_SKIP_DISABLED = 0, + /**< Skip mode is disabled */ + CPA_DC_SKIP_AT_START = 1, + /**< Skip region is at the start of the buffer. */ + CPA_DC_SKIP_AT_END = 2, + /**< Skip region is at the end of the buffer. */ + CPA_DC_SKIP_STRIDE = 3 + /**< Skip region occurs at regular intervals within the buffer. + CpaDcSkipData.strideLength specifies the number of bytes between each + skip region. */ +} CpaDcSkipMode; + +/** + ***************************************************************************** + * @ingroup cpaDc + * Service specific return codes + * + * @description + * Compression specific return codes + * + * + *****************************************************************************/ + +#define CPA_DC_BAD_DATA (-100) + /**consumed arg. + * -# The implementation communicates the amount of data in the + * destination buffer list via pResults->produced arg. + * + * Source Buffer Setup Rules + * -# The buffer list must have the correct number of flat buffers. This + * is specified by the numBuffers element of the CpaBufferList. + * -# Each flat buffer must have a pointer to contiguous memory that has + * been allocated by the calling application. The + * number of octets to be compressed or decompressed must be stored + * in the dataLenInBytes element of the flat buffer. + * -# It is permissible to have one or more flat buffers with a zero length + * data store. This function will process all flat buffers until the + * destination buffer is full or all source data has been processed. + * If a buffer has zero length, then no data will be processed from + * that buffer. + * + * Source Buffer Processing Rules. + * -# The buffer list is processed in index order - SrcBuff->pBuffers[0] + * will be completely processed before SrcBuff->pBuffers[1] begins to + * be processed. + * -# The application must drain the destination buffers. + * If the source data was not completely consumed, the application + * must resubmit the request. + * -# On return, the pResults->consumed will indicate the number of bytes + * consumed from the input buffers. + * + * Destination Buffer Setup Rules + * -# The destination buffer list must have storage for processed data. + * This implies at least one flat buffer must exist in the buffer list. + * -# For each flat buffer in the buffer list, the dataLenInBytes element + * must be set to the size of the buffer space. + * -# It is permissible to have one or more flat buffers with a zero length + * data store. + * If a buffer has zero length, then no data will be added to + * that buffer. + * + * Destination Buffer Processing Rules. + * -# The buffer list is processed in index order - DestBuff->pBuffers[0] + * will be completely processed before DestBuff->pBuffers[1] begins to + * be processed. + * -# On return, the pResults->produced will indicate the number of bytes + * written to the output buffers. + * -# If processing has not been completed, the application must drain the + * destination buffers and resubmit the request. The application must + * reset the dataLenInBytes for each flat buffer in the destination + * buffer list. + * + * Checksum rules. + * If a checksum is specified in the session setup data, then: + * -# For the first request for a particular data segment the checksum + * is initialised internally by the implementation. + * -# The checksum is maintained by the implementation between calls + * until the flushFlag is set to CPA_DC_FLUSH_FINAL indicating the + * end of a particular data segment. + * -# Intermediate checksum values are returned to the application, + * via the CpaDcRqResults structure, in response to each request. + * However these checksum values are not guaranteed to the valid + * until the call with flushFlag set to CPA_DC_FLUSH_FINAL + * completes successfully. + * + * The application should set flushFlag to + * CPA_DC_FLUSH_FINAL to indicate processing a particular data segment + * is complete. It should be noted that this function may have to be + * called more than once to process data after the flushFlag parameter has + * been set to CPA_DC_FLUSH_FINAL if the destination buffer fills. Refer + * to buffer processing rules. + * + * For stateful operations, when the function is invoked with flushFlag + * set to CPA_DC_FLUSH_NONE or CPA_DC_FLUSH_SYNC, indicating more data + * is yet to come, the function may or may not retain data. When the + * function is invoked with flushFlag set to CPA_DC_FLUSH_FULL or + * CPA_DC_FLUSH_FINAL, the function will process all buffered data. + * + * For stateless operations, CPA_DC_FLUSH_FINAL will cause the BFINAL + * bit to be set for deflate compression. The initial checksum for the + * stateless operation should be set to 0. CPA_DC_FLUSH_NONE and + * CPA_DC_FLUSH_SYNC should not be used for stateless operations. + * + * It is possible to maintain checksum and length information across + * cpaDcCompressData() calls with a stateless session without maintaining + * the full history state that is maintained by a stateful session. In this + * mode of operation, an initial checksum value of 0 is passed into the + * first cpaDcCompressData() call with the flush flag set to + * CPA_DC_FLUSH_FULL. On subsequent calls to cpaDcCompressData() for this + * session, the checksum passed to cpaDcCompressData should be set to the + * checksum value produced by the previous call to cpaDcCompressData(). + * When the last block of input data is passed to cpaDcCompressData(), the + * flush flag should be set to CP_DC_FLUSH_FINAL. This will cause the BFINAL + * bit to be set in a deflate stream. It is the responsibility of the calling + * application to maintain overall lengths across the stateless requests + * and to pass the checksum produced by one request into the next request. + * + * When an instance supports compressAndVerifyAndRecover, it is enabled by + * default when using cpaDcCompressData(). If this feature needs to be + * disabled, cpaDcCompressData2() must be used. + * + * Synchronous or Asynchronous operation of the API is determined by + * the value of the callbackFn parameter passed to cpaDcInitSession() + * when the sessionHandle was setup. If a non-NULL value was specified + * then the supplied callback function will be invoked asynchronously + * with the response of this request. + * + * Response ordering: + * For each session, the implementation must maintain the order of + * responses. That is, if in asynchronous mode, the order of the callback + * functions must match the order of jobs submitted by this function. + * In a simple synchronous mode implementation, the practice of submitting + * a request and blocking on its completion ensure ordering is preserved. + * + * This limitation does not apply if the application employs multiple + * threads to service a single session. + * + * If this API is invoked asynchronous, the return code represents + * the success or not of asynchronously scheduling the request. + * The results of the operation, along with the amount of data consumed + * and produced become available when the callback function is invoked. + * As such, pResults->consumed and pResults->produced are available + * only when the operation is complete. + * + * The application must not use either the source or destination buffers + * until the callback has completed. + * + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcCompressData( CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag ); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Submit a request to compress a buffer of data. + * + * @description + * This API consumes data from the input buffer and generates compressed + * data in the output buffer. This API is very similar to + * cpaDcCompressData() except it provides a CpaDcOpData structure for + * passing additional input parameters not covered in cpaDcCompressData(). + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Target service instance. + * @param[in,out] pSessionHandle Session handle. + * @param[in] pSrcBuff Pointer to data buffer for compression. + * @param[in] pDestBuff Pointer to buffer space for data after + * compression. + * @param[in] pOpData Additional input parameters. + * @param[in,out] pResults Pointer to results structure + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated + * request. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_DC_BAD_DATA The input data was not properly formed. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * @post + * pSessionHandle has session related state information + * @note + * This function passes control to the compression service for processing + * + * @see + * cpaDcCompressData() + * + *****************************************************************************/ +CpaStatus +cpaDcCompressData2( CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag ); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Submit a request to decompress a buffer of data. + * + * @description + * This API consumes compressed data from the input buffer and generates + * uncompressed data in the output buffer. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Target service instance. + * @param[in,out] pSessionHandle Session handle. + * @param[in] pSrcBuff Pointer to data buffer for compression. + * @param[in] pDestBuff Pointer to buffer space for data + * after decompression. + * @param[in,out] pResults Pointer to results structure + * @param[in] flushFlag When set to CPA_DC_FLUSH_FINAL, indicates + * that the input buffer contains all of + * the data for the compression session, + * allowing the function to release + * history data. + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated + * request. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_DC_BAD_DATA The input data was not properly formed. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * @post + * pSessionHandle has session related state information + * @note + * This function passes control to the compression service for + * decompression. The function returns the status from the service. + * + * This function may be called repetitively with input until all of the + * input has been provided and all the output has been consumed. + * + * This function has identical buffer processing rules as + * cpaDcCompressData(). + * + * This function has identical checksum processing rules as + * cpaDcCompressData(). + * + * The application should set flushFlag to + * CPA_DC_FLUSH_FINAL to indicate processing a particular compressed + * data segment is complete. It should be noted that this function may + * have to be called more than once to process data after flushFlag + * has been set if the destination buffer fills. Refer to + * buffer processing rules in cpaDcCompressData(). + * + * Synchronous or Asynchronous operation of the API is determined by + * the value of the callbackFn parameter passed to cpaDcInitSession() + * when the sessionHandle was setup. If a non-NULL value was specified + * then the supplied callback function will be invoked asynchronously + * with the response of this request, along with the callbackTag + * specified in the function. + * + * The same response ordering constraints identified in the + * cpaDcCompressData API apply to this function. + * + * @see + * cpaDcCompressData() + * + *****************************************************************************/ +CpaStatus +cpaDcDecompressData( CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag ); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Submit a request to decompress a buffer of data. + * + * @description + * This API consumes compressed data from the input buffer and generates + * uncompressed data in the output buffer. This API is very similar to + * cpaDcDecompressData() except it provides a CpaDcOpData structure for + * passing additional input parameters not covered in cpaDcDecompressData(). + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Target service instance. + * @param[in,out] pSessionHandle Session handle. + * @param[in] pSrcBuff Pointer to data buffer for compression. + * @param[in] pDestBuff Pointer to buffer space for data + * after decompression. + * @param[in] pOpData Additional input parameters. + * @param[in,out] pResults Pointer to results structure + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated + * request. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_DC_BAD_DATA The input data was not properly formed. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * @post + * pSessionHandle has session related state information + * @note + * This function passes control to the compression service for + * decompression. The function returns the status from the service. + * + * @see + * cpaDcDecompressData() + * cpaDcCompressData2() + * cpaDcCompressData() + * + *****************************************************************************/ +CpaStatus +cpaDcDecompressData2( CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag ); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Generate compression header. + * + * @description + * This API generates the gzip or the zlib header and stores it in the + * output buffer. + * + * @context + * This function may be call from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in,out] pSessionHandle Session handle. + * @param[in] pDestBuff Pointer to data buffer where the + * compression header will go. + * @param[out] count Pointer to counter filled in with + * header size. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * + * @note + * This function can output a 10 byte gzip header or 2 byte zlib header to + * the destination buffer. The session properties are used to determine + * the header type. To output a header the session must have been + * initialized with CpaDcCompType CPA_DC_DEFLATE for any other value no + * header is produced. To output a gzip header the session must have been + * initialized with CpaDcChecksum CPA_DC_CRC32. To output a zlib header + * the session must have been initialized with CpaDcChecksum CPA_DC_ADLER32. + * For CpaDcChecksum CPA_DC_NONE no header is output. + * + * If the compression requires a gzip header, then this header requires + * at a minimum the following fields, defined in RFC1952: + * ID1: 0x1f + * ID2: 0x8b + * CM: Compression method = 8 for deflate + * + * The zlib header is defined in RFC1950 and this function must implement + * as a minimum: + * CM: four bit compression method - 8 is deflate with window size to + * 32k + * CINFO: four bit window size (see RFC1950 for details), 7 is 32k + * window + * FLG: defined as: + * - Bits 0 - 4: check bits for CM, CINFO and FLG (see RFC1950) + * - Bit 5: FDICT 0 = default, 1 is preset dictionary + * - Bits 6 - 7: FLEVEL, compression level (see RFC 1950) + * + * The counter parameter will be set + * to the number of bytes added to the buffer. The pData will be + * not be changed. + * + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcGenerateHeader( CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, Cpa32U *count ); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Generate compression footer. + * + * @description + * This API generates the footer for gzip or zlib and stores it in the + * output buffer. + * @context + * This function may be call from any context. + * @assumptions + * None + * @sideEffects + * All session variables are reset + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in,out] pSessionHandle Session handle. + * @param[in] pDestBuff Pointer to data buffer where the + * compression footer will go. + * @param[in,out] pResults Pointer to results structure filled by + * CpaDcCompressData. Updated with the + * results of this API call + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * pResults structure has been filled by CpaDcCompressData(). + * + * @note + * Depending on the session variables, this function can add the + * alder32 footer to the zlib compressed data as defined in RFC1950. If + * required, it can also add the gzip footer, which is the crc32 of the + * uncompressed data and the length of the uncompressed data. This + * section is defined in RFC1952. The session variables used to determine + * the header type are CpaDcCompType and CpaDcChecksum, see cpaDcGenerateHeader + * for more details. + * + * An artifact of invoking this function for writing the footer data is + * that all opaque session specific data is re-initialized. If the + * compression level and file types are consistent, the upper level + * application can continue processing compression requests using the + * same session handle. + * + * The produced element of the pResults structure will be incremented by the + * numbers bytes added to the buffer. The pointer to the buffer + * will not be modified. + * + * This function is not supported for stateless sessions. + * + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcGenerateFooter( CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, CpaDcRqResults *pResults ); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Retrieve statistics + * + * @description + * This API retrieves the current statistics for a compression instance. + * + * @context + * This function may be call from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Instance handle. + * @param[out] pStatistics Pointer to statistics structure. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcGetStats( CpaInstanceHandle dcInstance, + CpaDcStats *pStatistics ); + +/*****************************************************************************/ +/* Instance Discovery Functions */ + +/** + ***************************************************************************** + * @ingroup cpaDc + * Get the number of device instances that are supported by the API + * implementation. + * + * @description + * + * This function will get the number of device instances that are supported + * by an implementation of the compression API. This number is then used to + * determine the size of the array that must be passed to + * cpaDcGetInstances(). + * + * @context + * This function MUST NOT be called from an interrupt context as it MAY + * sleep. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[out] pNumInstances Pointer to where the number of + * instances will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated + * + * @see + * cpaDcGetInstances + * + *****************************************************************************/ +CpaStatus +cpaDcGetNumInstances(Cpa16U* pNumInstances); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Get the handles to the device instances that are supported by the + * API implementation. + * + * @description + * + * This function will return handles to the device instances that are + * supported by an implementation of the compression API. These instance + * handles can then be used as input parameters with other compression API + * functions. + * + * This function will populate an array that has been allocated by the + * caller. The size of this API is determined by the + * cpaDcGetNumInstances() function. + * + * @context + * This function MUST NOT be called from an interrupt context as it MAY + * sleep. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] numInstances Size of the array. + * @param[out] dcInstances Pointer to where the instance + * handles will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated + * + * @see + * cpaDcGetInstances + * + *****************************************************************************/ +CpaStatus +cpaDcGetInstances(Cpa16U numInstances, + CpaInstanceHandle* dcInstances); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Compression Component utility function to determine the number of + * intermediate buffers required by an implementation. + * + * @description + * This function will determine the number of intermediate buffer lists + * required by an implementation for a compression instance. These buffers + * should then be allocated and provided when calling @ref cpaDcStartInstance() + * to start a compression instance that will use dynamic compression. + * + * @context + * This function may sleep, and MUST NOT be called in interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * @param[in,out] instanceHandle Handle to an instance of this API to be + * initialized. + * @param[out] pNumBuffers When the function returns, this will + * specify the number of buffer lists that + * should be used as intermediate buffers + * when calling cpaDcStartInstance(). + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Suggested course of action + * is to shutdown and restart. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * cpaDcStartInstance() + * + *****************************************************************************/ +CpaStatus +cpaDcGetNumIntermediateBuffers(CpaInstanceHandle instanceHandle, + Cpa16U *pNumBuffers); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Compression Component Initialization and Start function. + * + * @description + * This function will initialize and start the compression component. + * It MUST be called before any other compress function is called. This + * function SHOULD be called only once (either for the very first time, + * or after an cpaDcStopInstance call which succeeded) per instance. + * Subsequent calls will have no effect. + * + * If required by an implementation, this function can be provided with + * instance specific intermediate buffers. The intent is to provide an + * instance specific location to store intermediate results during dynamic + * instance Huffman tree compression requests. The memory should be + * accessible by the compression engine. The buffers are to support + * deflate compression with dynamic Huffman Trees. Each buffer list + * should be similar in size to twice the destination buffer size passed + * to the compress API. The number of intermediate buffer lists may vary + * between implementations and so @ref cpaDcGetNumIntermediateBuffers() + * should be called first to determine the number of intermediate + * buffers required by the implementation. + * + * If not required, this parameter can be passed in as NULL. + * + * @context + * This function may sleep, and MUST NOT be called in interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * @param[in,out] instanceHandle Handle to an instance of this API to be + * initialized. + * @param[in] numBuffers Number of buffer lists represented by + * the pIntermediateBuffers parameter. + * Note: @ref cpaDcGetNumIntermediateBuffers() + * can be used to determine the number of + * intermediate buffers that an implementation + * requires. + * @param[in] pIntermediateBuffers Optional pointer to Instance specific + * DRAM buffer. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Suggested course of action + * is to shutdown and restart. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * cpaDcStopInstance() + * cpaDcGetNumIntermediateBuffers() + * + *****************************************************************************/ +CpaStatus +cpaDcStartInstance(CpaInstanceHandle instanceHandle, + Cpa16U numBuffers, + CpaBufferList **pIntermediateBuffers); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Compress Component Stop function. + * + * @description + * This function will stop the Compression component and free + * all system resources associated with it. The client MUST ensure that + * all outstanding operations have completed before calling this function. + * The recommended approach to ensure this is to deregister all session or + * callback handles before calling this function. If outstanding + * operations still exist when this function is invoked, the callback + * function for each of those operations will NOT be invoked and the + * shutdown will continue. If the component is to be restarted, then a + * call to cpaDcStartInstance is required. + * + * @context + * This function may sleep, and so MUST NOT be called in interrupt + * context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * @param[in] instanceHandle Handle to an instance of this API to be + * shutdown. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Suggested course of action + * is to ensure requests are not still being + * submitted and that all sessions are + * deregistered. If this does not help, then + * forcefully remove the component from the + * system. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaDcStartInstance + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * cpaDcStartInstance() + * + *****************************************************************************/ +CpaStatus +cpaDcStopInstance(CpaInstanceHandle instanceHandle); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Function to get information on a particular instance. + * + * @description + * This function will provide instance specific information through a + * @ref CpaInstanceInfo2 structure. + * + * @context + * This function will be executed in a context that requires that sleeping + * MUST NOT be permitted. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API to be + * initialized. + * @param[out] pInstanceInfo2 Pointer to the memory location allocated by + * the client into which the CpaInstanceInfo2 + * structure will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The client has retrieved an instanceHandle from successive calls to + * @ref cpaDcGetNumInstances and @ref cpaDcGetInstances. + * @post + * None + * @note + * None + * @see + * cpaDcGetNumInstances, + * cpaDcGetInstances, + * CpaInstanceInfo2 + * + *****************************************************************************/ +CpaStatus +cpaDcInstanceGetInfo2(const CpaInstanceHandle instanceHandle, + CpaInstanceInfo2 * pInstanceInfo2); + +/*****************************************************************************/ +/* Instance Notification Functions */ +/*****************************************************************************/ +/** + ***************************************************************************** + * @ingroup cpaDc + * Callback function for instance notification support. + * + * @description + * This is the prototype for the instance notification callback function. + * The callback function is passed in as a parameter to the + * @ref cpaDcInstanceSetNotificationCb function. + * + * @context + * This function will be executed in a context that requires that sleeping + * MUST NOT be permitted. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function calls. + * @param[in] instanceEvent The event that will trigger this function to + * get invoked. + * + * @retval + * None + * @pre + * Component has been initialized and the notification function has been + * set via the cpaDcInstanceSetNotificationCb function. + * @post + * None + * @note + * None + * @see + * cpaDcInstanceSetNotificationCb(), + * + *****************************************************************************/ +typedef void (*CpaDcInstanceNotificationCbFunc)( + const CpaInstanceHandle instanceHandle, + void * pCallbackTag, + const CpaInstanceEvent instanceEvent); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Subscribe for instance notifications. + * + * @description + * Clients of the CpaDc interface can subscribe for instance notifications + * by registering a @ref CpaDcInstanceNotificationCbFunc function. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pInstanceNotificationCb Instance notification callback + * function pointer. + * @param[in] pCallbackTag Opaque value provided by user while + * making individual function calls. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Instance has been initialized. + * @post + * None + * @note + * None + * @see + * CpaDcInstanceNotificationCbFunc + * + *****************************************************************************/ +CpaStatus +cpaDcInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaDcInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Get the size of the memory required to hold the session information. + * + * @description + * + * The client of the Data Compression API is responsible for + * allocating sufficient memory to hold session information and the context + * data. This function provides a means for determining the size of the + * session information and the size of the context data. + * + * @context + * No restrictions + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Instance handle. + * @param[in] pSessionData Pointer to a user instantiated structure + * containing session data. + * @param[out] pSessionSize On return, this parameter will be the size + * of the memory that will be + * required by cpaDcInitSession() for session + * data. + * @param[out] pContextSize On return, this parameter will be the size + * of the memory that will be required + * for context data. Context data is + * save/restore data including history and + * any implementation specific data that is + * required for a save/restore operation. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * Only a synchronous version of this function is provided. + * + * It is expected that context data is comprised of the history and + * any data stores that are specific to the history such as linked + * lists or hash tables. + * For stateless sessions the context size returned from this function + * will be zero. For stateful sessions the context size returned will + * depend on the session setup data. + * + * Session data is expected to include interim checksum values, various + * counters and other session related data that needs to persist + * between invocations. + * For a given implementation of this API, it is safe to assume that + * cpaDcGetSessionSize() will always return the same session size and + * that the size will not be different for different setup data + * parameters. However, it should be noted that the size may change: + * (1) between different implementations of the API (e.g. between software + * and hardware implementations or between different hardware + * implementations) + * (2) between different releases of the same API implementation. + * + * @see + * cpaDcInitSession() + * + *****************************************************************************/ +CpaStatus +cpaDcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData* pSessionData, + Cpa32U* pSessionSize, Cpa32U* pContextSize ); + +/** + ***************************************************************************** + * @ingroup cpaDc + * Function to return the size of the memory which must be allocated for + * the pPrivateMetaData member of CpaBufferList. + * + * @description + * This function is used to obtain the size (in bytes) required to allocate + * a buffer descriptor for the pPrivateMetaData member in the + * CpaBufferList structure. + * Should the function return zero then no meta data is required for the + * buffer list. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[in] numBuffers The number of pointers in the CpaBufferList. + * This is the maximum number of CpaFlatBuffers + * which may be contained in this CpaBufferList. + * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be + * allocated when the client wishes to allocate + * a cpaFlatBuffer. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * None + * @see + * cpaDcGetInstances() + * + *****************************************************************************/ +CpaStatus +cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Function to return a string indicating the specific error that occurred + * within the system. + * + * @description + * When a function returns any error including CPA_STATUS_SUCCESS, the + * client can invoke this function to get a string which describes the + * general error condition, and if available additional information on + * the specific error. + * The Client MUST allocate CPA_STATUS_MAX_STR_LENGTH_IN_BYTES bytes for the buffer + * string. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Handle to an instance of this API. + * @param[in] errStatus The error condition that occurred. + * @param[in,out] pStatusText Pointer to the string buffer that will + * be updated with the status text. The invoking + * application MUST allocate this buffer to be + * exactly CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Note, in this scenario + * it is INVALID to call this function a + * second time. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * None + * @see + * CpaStatus + * + *****************************************************************************/ + +CpaStatus +cpaDcGetStatusText(const CpaInstanceHandle dcInstance, + const CpaStatus errStatus, + Cpa8S * pStatusText); + + +/** + ***************************************************************************** + * @ingroup cpaDc + * Set Address Translation function + * + * @description + * This function is used to set the virtual to physical address + * translation routine for the instance. The specified routine + * is used by the instance to perform any required translation of + * a virtual address to a physical address. If the application + * does not invoke this function, then the instance will use its + * default method, such as virt2phys, for address translation. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Data Compression API instance handle. + * @param[in] virtual2Physical Routine that performs virtual to + * physical address translation. + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcSetAddressTranslation(const CpaInstanceHandle instanceHandle, + CpaVirtualToPhysical virtual2Physical); +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_DC_H */ diff --git a/sys/dev/qat/qat_api/include/dc/cpa_dc_bp.h b/sys/dev/qat/qat_api/include/dc/cpa_dc_bp.h new file mode 100644 index 00000000000..c3ab9e2d5e3 --- /dev/null +++ b/sys/dev/qat/qat_api/include/dc/cpa_dc_bp.h @@ -0,0 +1,320 @@ +/**************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_dc_bp.h + * + * @defgroup cpaDcBp Data Compression Batch and Pack API + * + * @ingroup cpaDc + * + * @description + * These functions specify the API for Data Compression operations related + * to the 'Batch and Pack' mode of operation. + * + * @remarks + * + * + *****************************************************************************/ + +#ifndef CPA_DC_BP_H +#define CPA_DC_BP_H + +#ifdef __cplusplus +extern"C" { +#endif + + +#include "cpa_dc.h" + +/** + ***************************************************************************** + * @ingroup cpaDcBp + * Batch request input parameters. + * @description + * This structure contains the request information for use with batched + * compression operations. + * + * + ****************************************************************************/ +typedef struct _CpaDcBatchOpData { + CpaDcOpData opData; + /**< Compression input parameters */ + CpaBufferList *pSrcBuff; + /**< Input buffer list containing the data to be compressed. */ + CpaBoolean resetSessionState; + /**< Reset the session state at the beginning of this request within + * the batch. Only applies to stateful sessions. When this flag is + * set, the history from previous requests in this session will not be + * used when compressing the input data for this request in the batch. + * */ +} CpaDcBatchOpData ; + +/** + ***************************************************************************** + * @ingroup cpaDcBp + * Submit a batch of requests to compress a batch of input buffers into + * a common output buffer. The same output buffer is used for each request + * in the batch. This is termed 'batch and pack'. + * + * @description + * This API consumes data from the input buffer and generates compressed + * data in the output buffer. + * This API compresses a batch of input buffers and concatenates the + * compressed data into the output buffer. A results structure is also + * generated for each request in the batch. + * + * @context + * When called as an asynchronous funnction it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] dcInstance Target service instance. + * @param[in,out] pSessionHandle Session handle. + * @param[in] numRequests Number of requests in the batch. + * @param[in] pBatchOpData Pointer to an array of CpaDcBatchOpData + * structures which contain the input buffers + * and parameters for each request in the + * batch. There should be numRequests entries + * in the array. + * @param[in] pDestBuff Pointer to buffer space for data after + * compression. + * @param[in,out] pResults Pointer to an array of results structures. + * There should be numRequests entries in the + * array. + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated + * request. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_DC_BAD_DATA The input data was not properly formed. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * + * @pre + * pSessionHandle has been setup using cpaDcInitSession() + * Session must be setup as a stateless sesssion. + * @note + * This function passes control to the compression service for processing + * + * In synchronous mode the function returns the error status returned from the + * service. In asynchronous mode the status is returned by the callback + * function. + * + * This function may be called repetitively with input until all of the input + * has been consumed by the compression service and all the output has been + * produced. + * + * When this function returns, it may be that all of the available buffers in + * the input list has not been compressed. This situation will occur when + * there is insufficient space in the output buffer. The calling application + * should note the amount of buffers processed, and then submit the request + * again, with a new output buffer and with the input buffer list containing + * the buffers that were not previously compressed. + * + * Relationship between input buffers and results buffers. + * -# Implementations of this API must not modify the individual + * flat buffers of the input buffer list. + * -# The implementation communicates the number of buffers + * consumed from the source buffer list via pResults->consumed arg. + * -# The implementation communicates the amount of data in the + * destination buffer list via pResults->produced arg. + * + * Source Buffer Setup Rules + * -# The buffer list must have the correct number of flat buffers. This + * is specified by the numBuffers element of the CpaBufferList. + * -# Each flat buffer must have a pointer to contiguous memory that has + * been allocated by the calling application. The number of octets to be + * compressed or decompressed must be stored in the dataLenInBytes element + * of the flat buffer. + * -# It is permissible to have one or more flat buffers with a zero length + * data store. This function will process all flat buffers until the + * destination buffer is full or all source data has been processed. + * If a buffer has zero length, then no data will be processed from + * that buffer. + * + * Source Buffer Processing Rules. + * -# The buffer list is processed in index order - SrcBuff->pBuffers[0] + * will be completely processed before SrcBuff->pBuffers[1] begins to + * be processed. + * -# The application must drain the destination buffers. + * If the source data was not completely consumed, the application + * must resubmit the request. + * -# On return, the pResults->consumed will indicate the number of buffers + * consumed from the input buffer list. + * + * Destination Buffer Setup Rules + * -# The destination buffer list must have storage for processed data and + * for the packed header information. + * This means that least two flat buffer must exist in the buffer list. + * The first buffer entry will be used for the header information. + * Subsequent entries will be used for the compressed data. + * -# For each flat buffer in the buffer list, the dataLenInBytes element + * must be set to the size of the buffer space. + * -# It is permissible to have one or more flat buffers with a zero length + * data store. + * If a buffer has zero length, then no data will be added to + * that buffer. + * + * Destination Buffer Processing Rules. + * -# The buffer list is processed in index order. + * -# On return, the pResults->produced will indicate the number of bytes + * of compressed data written to the output buffers. Note that this + * will not include the header information buffer. + * -# If processing has not been completed, the application must drain the + * destination buffers and resubmit the request. The application must reset + * the dataLenInBytes for each flat buffer in the destination buffer list. + * + * Synchronous or Asynchronous operation of the API is determined by + * the value of the callbackFn parameter passed to cpaDcInitSession() + * when the sessionHandle was setup. If a non-NULL value was specified + * then the supplied callback function will be invoked asynchronously + * with the response of this request. + * + * Response ordering: + * For each session, the implementation must maintain the order of + * responses. That is, if in asynchronous mode, the order of the callback + * functions must match the order of jobs submitted by this function. + * In a simple synchronous mode implementation, the practice of submitting + * a request and blocking on its completion ensure ordering is preserved. + * + * This limitation does not apply if the application employs multiple + * threads to service a single session. + * + * If this API is invoked asynchronous, the return code represents + * the success or not of asynchronously scheduling the request. + * The results of the operation, along with the amount of data consumed + * and produced become available when the callback function is invoked. + * As such, pResults->consumed and pResults->produced are available + * only when the operation is complete. + * + * The application must not use either the source or destination buffers + * until the callback has completed. + * + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaDcBPCompressData( CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + const Cpa32U numRequests, + CpaDcBatchOpData *pBatchOpData, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + void *callbackTag ); + +/** +***************************************************************************** +* @ingroup cpaDcBp +* Function to return the size of the memory which must be allocated for +* the pPrivateMetaData member of CpaBufferList contained within +* CpaDcBatchOpData. +* +* @description +* This function is used to obtain the size (in bytes) required to allocate +* a buffer descriptor for the pPrivateMetaData member in the +* CpaBufferList structure when Batch and Pack API are used. +* Should the function return zero then no meta data is required for the +* buffer list. +* +* @context +* This function may be called from any context. +* @assumptions +* None +* @sideEffects +* None +* @blocking +* No +* @reentrant +* No +* @threadSafe +* Yes +* +* @param[in] instanceHandle Handle to an instance of this API. +* @param[in] numJobs The number of jobs defined in the CpaDcBatchOpData +* table. +* @param[out] pSizeInBytes Pointer to the size in bytes of memory to be +* allocated when the client wishes to allocate +* a cpaFlatBuffer and the Batch and Pack OP data. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* +* @pre +* None +* @post +* None +* @note +* None +* @see +* cpaDcBPCompressData() +* +*****************************************************************************/ +CpaStatus +cpaDcBnpBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numJobs, + Cpa32U *pSizeInBytes); + + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_DC_BP_H */ diff --git a/sys/dev/qat/qat_api/include/dc/cpa_dc_dp.h b/sys/dev/qat/qat_api/include/dc/cpa_dc_dp.h new file mode 100644 index 00000000000..29511db2d10 --- /dev/null +++ b/sys/dev/qat/qat_api/include/dc/cpa_dc_dp.h @@ -0,0 +1,746 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_dc_dp.h + * + * @defgroup cpaDcDp Data Compression Data Plane API + * + * @ingroup cpaDc + * + * @description + * These data structures and functions specify the Data Plane API + * for compression and decompression operations. + * + * This API is recommended for data plane applications, in which the + * cost of offload - that is, the cycles consumed by the driver in + * sending requests to the hardware, and processing responses - needs + * to be minimized. In particular, use of this API is recommended + * if the following constraints are acceptable to your application: + * + * - Thread safety is not guaranteed. Each software thread should + * have access to its own unique instance (CpaInstanceHandle) to + * avoid contention. + * - Polling is used, rather than interrupts (which are expensive). + * Implementations of this API will provide a function (not + * defined as part of this API) to read responses from the hardware + * response queue and dispatch callback functions, as specified on + * this API. + * - Buffers and buffer lists are passed using physical addresses, + * to avoid virtual to physical address translation costs. + * - The ability to enqueue one or more requests without submitting + * them to the hardware allows for certain costs to be amortized + * across multiple requests. + * - Only asynchronous invocation is supported. + * - There is no support for partial packets. + * - Implementations may provide certain features as optional at + * build time, such as atomic counters. + * - There is no support for stateful operations. + * - The "default" instance (CPA_INSTANCE_HANDLE_SINGLE) is not + * supported on this API. The specific handle should be obtained + * using the instance discovery functions (@ref cpaDcGetNumInstances, + * @ref cpaDcGetInstances). + * + *****************************************************************************/ + +#ifndef CPA_DC_DP_H +#define CPA_DC_DP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_dc.h" + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * Operation Data for compression data plane API. + * + * @description + * This structure contains data relating to a request to perform + * compression processing on one or more data buffers. + * + * The physical memory to which this structure points should be + * at least 8-byte aligned. + * + * All reserved fields SHOULD NOT be written or read by the + * calling code. + * + * @see + * cpaDcDpEnqueueOp, cpaDcDpEnqueueOpBatch + ****************************************************************************/ +typedef struct _CpaDcDpOpData +{ + Cpa64U reserved0; + /**< Reserved for internal use. Source code should not read or write + * this field. + */ + Cpa32U bufferLenToCompress; + /**< The number of bytes from the source buffer to compress. This must be + * less than, or more typically equal to, the total size of the source + * buffer (or buffer list). + */ + + Cpa32U bufferLenForData; + /**< The maximum number of bytes that should be written to the destination + * buffer. This must be less than, or more typically equal to, the total + * size of the destination buffer (or buffer list). + */ + + Cpa64U reserved1; + /**< Reserved for internal use. Source code should not read or write */ + + Cpa64U reserved2; + /**< Reserved for internal use. Source code should not read or write */ + + Cpa64U reserved3; + /**< Reserved for internal use. Source code should not read or write */ + + CpaDcRqResults results; + /**< Results of the operation. Contents are valid upon completion. */ + + CpaInstanceHandle dcInstance; + /**< Instance to which the request is to be enqueued */ + + CpaDcSessionHandle pSessionHandle; + /**< DC Session associated with the stream of requests */ + + CpaPhysicalAddr srcBuffer; + /**< Physical address of the source buffer on which to operate. + * This is either the location of the data, of length srcBufferLen; or, + * if srcBufferLen has the special value @ref CPA_DP_BUFLIST, then + * srcBuffer contains the location where a @ref CpaPhysBufferList is + * stored. + */ + + Cpa32U srcBufferLen; + /**< If the source buffer is a "flat buffer", then this field + * specifies the size of the buffer, in bytes. If the source buffer + * is a "buffer list" (of type @ref CpaPhysBufferList), then this field + * should be set to the value @ref CPA_DP_BUFLIST. + */ + + CpaPhysicalAddr destBuffer; + /**< Physical address of the destination buffer on which to operate. + * This is either the location of the data, of length destBufferLen; or, + * if destBufferLen has the special value @ref CPA_DP_BUFLIST, then + * destBuffer contains the location where a @ref CpaPhysBufferList is + * stored. + */ + + Cpa32U destBufferLen; + /**< If the destination buffer is a "flat buffer", then this field + * specifies the size of the buffer, in bytes. If the destination buffer + * is a "buffer list" (of type @ref CpaPhysBufferList), then this field + * should be set to the value @ref CPA_DP_BUFLIST. + */ + + CpaDcSessionDir sessDirection; + /**pSessionHandle was setup using + * @ref cpaDcDpInitSession. + * The instance identified by pOpData->dcInstance has had a + * callback function registered via @ref cpaDcDpRegCbFunc. + * + * @post + * None + * + * @note + * A callback of type @ref CpaDcDpCallbackFn is generated in + * response to this function call. Any errors generated during + * processing are reported as part of the callback status code. + * + * @see + * @ref cpaDcDpPerformOpNow + *****************************************************************************/ + + +CpaStatus +cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, + const CpaBoolean performOpNow); + + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * Enqueue multiple requests to the compression data plane API. + * + * @description + * This function enqueues multiple requests to perform compression or + * decompression operations. + * + * The function is asynchronous; control is returned to the user once + * the request has been submitted. On completion of the request, the + * application may poll for responses, which will cause a callback + * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. + * Separate callbacks will be invoked for each request. + * Callbacks within a session and at the same priority are guaranteed + * to be in the same order in which they were submitted. + * + * The following restrictions apply to each element of the pOpData + * array: + * + * - The memory MUST be aligned on an 8-byte boundary. + * - The reserved fields of the structure MUST be set to zero. + * - The structure MUST reside in physically contiguous memory. + * + * @context + * This function will not sleep, and hence can be executed in a context + * that does not permit sleeping. + * + * @assumptions + * Client MUST allocate the request parameters to 8 byte alignment. + * Reserved elements of the CpaDcDpOpData structure MUST not used + * The CpaDcDpOpData structure MUST reside in physically + * contiguous memory. + * + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] numberRequests The number of requests in the array of + * CpaDcDpOpData structures. + * @param[in] pOpData An array of pointers to CpaDcDpOpData + * structures. Each CpaDcDpOpData + * structure contains the request parameters for + * that request. The client code allocates the + * memory for this structure. This component takes + * ownership of the memory until it is returned in + * the callback, which was registered on the + * instance via @ref cpaDcDpRegCbFunc. + * See the above Description for some restrictions + * that apply to this parameter. + * @param[in] performOpNow Flag to indicate whether the operation should be + * performed immediately (CPA_TRUE), or simply + * enqueued to be performed later (CPA_FALSE). + * In the latter case, the request is submitted + * to be performed either by calling this function + * again with this flag set to CPA_TRUE, or by + * invoking the function @ref + * cpaDcDpPerformOpNow. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The session identified by pOpData[i]->pSessionHandle was setup using + * @ref cpaDcDpInitSession. + * The instance identified by pOpData[i]->dcInstance has had a + * callback function registered via @ref cpaDcDpRegCbFunc. + * + * @post + * None + * + * @note + * Multiple callbacks of type @ref CpaDcDpCallbackFn are generated in + * response to this function call (one per request). Any errors + * generated during processing are reported as part of the callback + * status code. + * + * @see + * cpaDcDpEnqueueOp + *****************************************************************************/ +CpaStatus +cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaDcDpOpData *pOpData[], + const CpaBoolean performOpNow); + + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * Submit any previously enqueued requests to be performed now on the + * compression data plane API. + * + * @description + * This function triggers processing of previously enqueed requests on the + * referenced instance. + * + * + * @context + * Will not sleep. It can be executed in a context that does not + * permit sleeping. + * + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] dcInstance Instance to which the requests will be + * submitted. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via @ref cpaDcStartInstance function. + * A compression session has been previously setup using the + * @ref cpaDcDpInitSession function call. + * + * @post + * None + * + * @see + * cpaDcDpEnqueueOp, cpaDcDpEnqueueOpBatch + *****************************************************************************/ +CpaStatus +cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance); + + + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_DC_DP_H */ + diff --git a/sys/dev/qat/qat_api/include/icp_buffer_desc.h b/sys/dev/qat/qat_api/include/icp_buffer_desc.h new file mode 100644 index 00000000000..c7f9ea542c6 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_buffer_desc.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_buffer_desc.h + * + * @defgroup icp_BufferDesc Buffer descriptor for LAC + * + * @ingroup LacCommon + * + * @description + * This file contains details of the hardware buffer descriptors used to + * communicate with the QAT. + * + *****************************************************************************/ +#ifndef ICP_BUFFER_DESC_H +#define ICP_BUFFER_DESC_H + +#include "cpa.h" + +typedef Cpa64U icp_qat_addr_width_t; // hi32 first, lo32 second + +// Alignement constraint of the buffer list. +#define ICP_DESCRIPTOR_ALIGNMENT_BYTES 8 + +/** + ***************************************************************************** + * @ingroup icp_BufferDesc + * Buffer descriptors for FlatBuffers - used in communications with + * the QAT. + * + * @description + * A QAT friendly buffer descriptor. + * All buffer descriptor described in this structure are physcial + * and are 64 bit wide. + * + * Updates in the CpaFlatBuffer should be also reflected in this + * structure + * + *****************************************************************************/ +typedef struct icp_flat_buffer_desc_s { + Cpa32U dataLenInBytes; + Cpa32U reserved; + icp_qat_addr_width_t phyBuffer; + /**< The client will allocate memory for this using API function calls + * and the access layer will fill it and the QAT will read it. + */ +} icp_flat_buffer_desc_t; + +/** + ***************************************************************************** + * @ingroup icp_BufferDesc + * Buffer descriptors for BuffersLists - used in communications with + * the QAT. + * + * @description + * A QAT friendly buffer descriptor. + * All buffer descriptor described in this structure are physcial + * and are 64 bit wide. + * + * Updates in the CpaBufferList should be also reflected in this structure + * + *****************************************************************************/ +typedef struct icp_buffer_list_desc_s { + Cpa64U resrvd; + Cpa32U numBuffers; + Cpa32U reserved; + icp_flat_buffer_desc_t phyBuffers[]; + /**< Unbounded array of physical buffer pointers, these point to the + * FlatBufferDescs. The client will allocate memory for this using + * API function calls and the access layer will fill it and the QAT + * will read it. + */ +} icp_buffer_list_desc_t; + +#endif /* ICP_BUFFER_DESC_H */ diff --git a/sys/dev/qat/qat_api/include/icp_sal.h b/sys/dev/qat/qat_api/include/icp_sal.h new file mode 100644 index 00000000000..9c8689fb238 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file icp_sal.h + * + * @ingroup SalCommon + * + * Functions for both user space and kernel space. + * + ***************************************************************************/ + +#ifndef ICP_SAL_H +#define ICP_SAL_H + +/* + * icp_sal_get_dc_error + * + * @description: + * This function returns the occurrences of compression errors specified + * in the input parameter + * + * @context + * This function is called from the user process context + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * @param[in] dcError DC Error Type + * + * returns Number of failing requests of type dcError + */ +Cpa64U icp_sal_get_dc_error(Cpa8S dcError); + +#endif diff --git a/sys/dev/qat/qat_api/include/icp_sal_iommu.h b/sys/dev/qat/qat_api/include/icp_sal_iommu.h new file mode 100644 index 00000000000..214a30ac2d4 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal_iommu.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file icp_sal_iommu.h + * + * @ingroup SalUser + * + * Sal iommu wrapper functions. + * + ***************************************************************************/ + +#ifndef ICP_SAL_IOMMU_H +#define ICP_SAL_IOMMU_H + +/************************************************************************* + * @ingroup Sal + * @description + * Function returns page_size rounded size for iommu remapping + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] size Minimum required size. + * + * @retval page_size rounded size for iommu remapping. + * + *************************************************************************/ +size_t icp_sal_iommu_get_remap_size(size_t size); + +/************************************************************************* + * @ingroup Sal + * @description + * Function adds an entry into iommu remapping table + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] phaddr Host physical address. + * @param[in] iova Guest physical address. + * @param[in] size Size of the remapped region. + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + *************************************************************************/ +CpaStatus icp_sal_iommu_map(Cpa64U phaddr, Cpa64U iova, size_t size); + +/************************************************************************* + * @ingroup Sal + * @description + * Function removes an entry from iommu remapping table + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] iova Guest physical address to be removed. + * @param[in] size Size of the remapped region. + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + *************************************************************************/ +CpaStatus icp_sal_iommu_unmap(Cpa64U iova, size_t size); +#endif diff --git a/sys/dev/qat/qat_api/include/icp_sal_nrbg_ht.h b/sys/dev/qat/qat_api/include/icp_sal_nrbg_ht.h new file mode 100644 index 00000000000..ea4006b0b52 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal_nrbg_ht.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_sal_nrbg_ht.h + * + * @ingroup LacSym + * + * @description + * This file contains declaration of function used to test the health + * of NRBG entropy source. + * + *****************************************************************************/ +#ifndef ICP_SAL_NRBG_HT_H +#define ICP_SAL_NRBG_HT_H + +/** + ****************************************************************************** + * @ingroup LacSym + * NRBG Health Test + * + * @description + * This function performs a check on the deterministic parts of the + * NRBG. It also provides the caller the value of continuous random + * number generator test failures for n=64 bits, refer to FIPS 140-2 + * section 4.9.2 for details. A non-zero value for the counter does + * not necessarily indicate a failure; it is statistically possible + * that consecutive blocks of 64 bits will be identical, and the RNG + * will discard the identical block in such cases. This counter allows + * the calling application to monitor changes in this counter and to + * use this to decide whether to mark the NRBG as faulty, based on + * local policy or statistical model. + * + * @context + * MUST NOT be executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pContinuousRngTestFailures Number of continuous random number + * generator test failures. + * + * @retval CPA_STATUS_SUCCESS Health test passed. + * @retval CPA_STATUS_FAIL Health test failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + * @note + * The return value of this function is not impacted by the value + * of continuous random generator test failures. + * + *****************************************************************************/ +CpaStatus icp_sal_nrbgHealthTest(const CpaInstanceHandle instanceHandle, + Cpa32U *pContinuousRngTestFailures); + +#endif diff --git a/sys/dev/qat/qat_api/include/icp_sal_poll.h b/sys/dev/qat/qat_api/include/icp_sal_poll.h new file mode 100644 index 00000000000..d6d37d49a08 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal_poll.h @@ -0,0 +1,366 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file icp_sal_poll.h + * + * @defgroup SalPoll + * + * @ingroup SalPoll + * + * @description + * Polling APIs for instance polling. + * These functions retrieve requests on appropriate response rings and + * dispatch the associated callbacks. Callbacks are called in the + * context of the polling function itself. + * + * + ***************************************************************************/ + +#ifndef ICP_SAL_POLL_H +#define ICP_SAL_POLL_H + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll a Cy logical instance to retrieve requests that are on the + * response rings associated with that instance and dispatch the + * associated callbacks. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the rings + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle, + Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll a Sym Cy ring to retrieve requests that are on the + * response rings associated with that instance and dispatch the + * associated callbacks. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the rings + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle, + Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll an Asym Cy ring to retrieve requests that are on the + * response rings associated with that instance and dispatch the + * associated callbacks. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the rings + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_CyPollAsymRing(CpaInstanceHandle instanceHandle, + Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll a Cy NRBG ring to retrieve requests that are on the + * response rings associated with that instance and dispatch the + * associated callbacks. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the rings + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_CyPollNRBGRing(CpaInstanceHandle instanceHandle, + Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll the high priority symmetric response ring associated with a Cy + * logical instance to retrieve requests and dispatch the + * associated callbacks. + * + * This API is recommended for data plane applications, in which the + * cost of offload - that is, the cycles consumed by the driver in + * sending requests to the hardware, and processing responses - needs + * to be minimized. In particular, use of this API is recommended + * if the following constraints are acceptable to your application: + * + * - Thread safety is not guaranteed. Each software thread should + * have access to its own unique instance (CpaInstanceHandle) to + * avoid contention. + * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not + * supported on this API. The specific handle should be obtained + * using the instance discovery functions (@ref cpaCyGetNumInstances, + * @ref cpaCyGetInstances). + * + * This polling function should be used with the functions described + * in cpa_cy_sym_dp.h + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the ring + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_CyPollDpInstance(const CpaInstanceHandle instanceHandle, + const Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll a Dc logical instance to retrieve requests that are on the + * response ring associated with that instance and dispatch the + * associated callbacks. + * + * @context + * This function is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the ring + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_DcPollInstance(CpaInstanceHandle instanceHandle, + Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * Poll the response ring associated with a Dc logical instance to + * retrieve requests and dispatch the associated callbacks. + * + * This API is recommended for data plane applications, in which the + * cost of offload - that is, the cycles consumed by the driver in + * sending requests to the hardware, and processing responses - needs + * to be minimized. In particular, use of this API is recommended + * if the following constraints are acceptable to your application: + * + * - Thread safety is not guaranteed. Each software thread should + * have access to its own unique instance (CpaInstanceHandle) to + * avoid contention. + * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not + * supported on this API. The specific handle should be obtained + * using the instance discovery functions (@ref cpaDcGetNumInstances, + * @ref cpaDcGetInstances). + * + * This polling function should be used with the functions described + * in cpa_dc_dp.h + + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance handle. + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There are no responses on the ring + * associated with this instance + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, + Cpa32U responseQuota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * This function polls the rings on the given bank to determine + * if any of the rings contain messages to be read. The + * response quota is per ring. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] accelId Acceleration device Id, also known as + * packageId. This can be obtained using + * instance info functions ( + * @ref cpaCyInstanceGetInfo2 + * and @ref cpaDcInstanceGetInfo2) + * + * @param[in] bank_number Bank number + * + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There is no data on any ring on the bank + * or the bank is already being polled + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus +icp_sal_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota); + +/************************************************************************* + * @ingroup SalPoll + * @description + * This function polls the rings on all banks to determine + * if any of the rings contain messages to be read. The + * response quota is per ring. + * + * @context + * This functions is called from both the user and kernel context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] accelId Acceleration device Id, also known as + * packageId. This can be obtained using + * instance info functions ( + * @ref cpaCyInstanceGetInfo2 + * and @ref cpaDcInstanceGetInfo2) + * + * @param[in] response_quota The maximum number of messages that + * will be read in one polling. Setting + * the response quota to zero means that + * all messages on the ring will be read. + * + * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data + * @retval CPA_STATUS_RETRY There is no data on any ring on any bank + * or the banks are already being polled + * @retval CPA_STATUS_FAIL Indicates a failure + *************************************************************************/ +CpaStatus icp_sal_pollAllBanks(Cpa32U accelId, Cpa32U response_quota); + +#endif diff --git a/sys/dev/qat/qat_api/include/icp_sal_user.h b/sys/dev/qat/qat_api/include/icp_sal_user.h new file mode 100644 index 00000000000..af34d5aa194 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal_user.h @@ -0,0 +1,871 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file icp_sal_user.h + * + * @ingroup SalUser + * + * User space process init and shutdown functions. + * + ***************************************************************************/ + +#ifndef ICP_SAL_USER_H +#define ICP_SAL_USER_H + +/************************************************************************* + * @ingroup SalUser + * @description + * This function initialises and starts user space service access layer + * (SAL) - it registers SAL with ADF and initialises the ADF proxy. + * This function must only be called once per user space process. + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pProcessName Process address space name described in + * the config file for this device + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + *************************************************************************/ +CpaStatus icp_sal_userStart(const char *pProcessName); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function is to be used with simplified config file, where user + * defines many user space processes. The driver generates unique + * process names based on the pProcessName provided. + * For example: + * If a config file in simplified format contains: + * [SSL] + * NumProcesses = 3 + * + * Then three internal sections will be generated and the three + * applications can be started at a given time. Each application can call + * icp_sal_userStartMultiProcess("SSL"). In this case the driver will + * figure out the unique name to use for each process. + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pProcessName Process address space name described in + * the new format of the config file + * for this device. + * + * @param[in] limitDevAccess Specifies if the address space is limited + * to one device (true) or if it spans + * accross multiple devices. + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed. In this case user + * can wait and retry. + * + *************************************************************************/ +CpaStatus icp_sal_userStartMultiProcess(const char *pProcessName, + CpaBoolean limitDevAccess); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function stops and shuts down user space SAL + * - it deregisters SAL with ADF and shuts down ADF proxy + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userStop(void); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function gets the number of the available dynamic allocated + * crypto instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userCyGetAvailableNumDynInstances(Cpa32U *pNumCyInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function gets the number of the available dynamic allocated + * compression instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userDcGetAvailableNumDynInstances(Cpa32U *pNumDcInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function gets the number of the available dynamic allocated + * crypto instances which are from the specific device package. + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus +icp_sal_userCyGetAvailableNumDynInstancesByDevPkg(Cpa32U *pNumCyInstances, + Cpa32U devPkgID); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function gets the number of the available dynamic allocated + * crypto instances which are from the specific device package and specific + * accelerator. + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus +icp_sal_userCyGetAvailableNumDynInstancesByPkgAccel(Cpa32U *pNumCyInstances, + Cpa32U devPkgID, + Cpa32U accelerator_number); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function gets the number of the available dynamic allocated + * compression instances which are from the specific device package. + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus +icp_sal_userDcGetAvailableNumDynInstancesByDevPkg(Cpa32U *pNumDcInstances, + Cpa32U devPkgID); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function allocates crypto instances + * from dynamic crypto instance pool + * - it adds new allocated instances into crypto_services + * - it initializes new allocated instances + * - it starts new allocated instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userCyInstancesAlloc(Cpa32U numCyInstances, + CpaInstanceHandle *pCyInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function allocates crypto instances + * from dynamic crypto instance pool + * which are from the specific device package. + * - it adds new allocated instances into crypto_services + * - it initializes new allocated instances + * - it starts new allocated instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userCyInstancesAllocByDevPkg(Cpa32U numCyInstances, + CpaInstanceHandle *pCyInstances, + Cpa32U devPkgID); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function allocates crypto instances + * from dynamic crypto instance pool + * which are from the specific device package and specific accelerator + * - it adds new allocated instances into crypto_services + * - it initializes new allocated instances + * - it starts new allocated instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus +icp_sal_userCyInstancesAllocByPkgAccel(Cpa32U numCyInstances, + CpaInstanceHandle *pCyInstances, + Cpa32U devPkgID, + Cpa32U accelerator_number); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function frees crypto instances allocated + * from dynamic crypto instance pool + * - it stops the instances + * - it shutdowns the instances + * - it removes the instances from crypto_services + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userCyFreeInstances(Cpa32U numCyInstances, + CpaInstanceHandle *pCyInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function allocates compression instances + * from dynamic compression instance pool + * - it adds new allocated instances into compression_services + * - it initializes new allocated instances + * - it starts new allocated instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userDcInstancesAlloc(Cpa32U numDcInstances, + CpaInstanceHandle *pDcInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function allocates compression instances + * from dynamic compression instance pool + * which are from the specific device package. + * - it adds new allocated instances into compression_services + * - it initializes new allocated instances + * - it starts new allocated instances + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userDcInstancesAllocByDevPkg(Cpa32U numDcInstances, + CpaInstanceHandle *pDcInstances, + Cpa32U devPkgID); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function frees compression instances allocated + * from dynamic compression instance pool + * - it stops the instances + * - it shutdowns the instances + * - it removes the instances from compression_services + * + * @context + * This function is called from the user process context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_userDcFreeInstances(Cpa32U numDcInstances, + CpaInstanceHandle *pDcInstances); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function checks if new devices have been started and if so + * starts to use them. + * + * @context + * This function is called from the user process context + * in threadless mode + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_find_new_devices(void); + +/************************************************************************* + * @ingroup SalUser + * @description + * This function polls device events. + * + * @context + * This function is called from the user process context + * in threadless mode + * + * @assumptions + * None + * @sideEffects + * In case a device has beed stoped or restarted the application + * will get restarting/stop/shutdown events + * @reentrant + * No + * @threadSafe + * No + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + * + ************************************************************************/ +CpaStatus icp_sal_poll_device_events(void); + +/* + * icp_adf_check_device + * + * @description: + * This function checks the status of the firmware/hardware for a given device. + * This function is used as part of the heartbeat functionality. + * + * @context + * This function is called from the user process context + * @assumptions + * None + * @sideEffects + * In case a device is unresponsive the device will + * be restarted. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] accelId Device Id. + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + */ +CpaStatus icp_sal_check_device(Cpa32U accelId); + +/* + * icp_adf_check_all_devices + * + * @description: + * This function checks the status of the firmware/hardware for all devices. + * This function is used as part of the heartbeat functionality. + * + * @context + * This function is called from the user process context + * @assumptions + * None + * @sideEffects + * In case a device is unresponsive the device will + * be restarted. + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval CPA_STATUS_SUCCESS No error + * @retval CPA_STATUS_FAIL Operation failed + */ +CpaStatus icp_sal_check_all_devices(void); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to send messages to VF + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_userSendMsgToVf(Cpa32U accelId, Cpa32U vfNum, Cpa32U message); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to send messages to PF + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_userSendMsgToPf(Cpa32U accelId, Cpa32U message); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to get messages from VF + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_userGetMsgFromVf(Cpa32U accelId, + Cpa32U vfNum, + Cpa32U *message, + Cpa32U *messageCounter); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to get messages from PF + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_userGetMsgFromPf(Cpa32U accelId, + Cpa32U *message, + Cpa32U *messageCounter); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to get pfvf comms status + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_userGetPfVfcommsStatus(CpaBoolean *unreadMessage); + +/* + * @ingroup icp_sal_user + * @description + * This is a stub function to reset the device + * + * @context + * None + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +CpaStatus icp_sal_reset_device(Cpa32U accelId); + +/** + ***************************************************************************** + * @ingroup icp_sal_user + * Retrieve number of in flight requests for a nrbg tx ring + * from a crypto instance (Traditional API). + * + * @description + * This function is a part of back-pressure mechanism. + * Applications can query for inflight requests in + * the appropriate service/ring on each instance + * and select any instance with sufficient space or + * the instance with the lowest number. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Crypto API instance handle. + * @param[out] maxInflightRequests Maximal number of in flight requests. + * @param[out] numInflightRequests Current number of in flight requests. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus icp_sal_NrbgGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +/** + ***************************************************************************** + * @ingroup icp_sal_user + * Retrieve number of in flight requests for a symmetric tx ring + * from a crypto instance (Traditional API). + * + * @description + * This function is a part of back-pressure mechanism. + * Applications can query for inflight requests in + * the appropriate service/ring on each instance + * and select any instance with sufficient space or + * the instance with the lowest number. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Crypto API instance handle. + * @param[out] maxInflightRequests Maximal number of in flight requests. + * @param[out] numInflightRequests Current number of in flight requests. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +/** + ***************************************************************************** + * @ingroup icp_sal_user + * Retrieve number of in flight requests for an asymmetric tx ring + * from a crypto instance (Traditional API). + * + * @description + * This function is a part of back-pressure mechanism. + * Applications can query the appropriate service/ring on each instance + * and select any instance with sufficient space or + * the instance with the lowest number. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Crypto API instance handle. + * @param[out] maxInflightRequests Maximal number of in flight requests. + * @param[out] numInflightRequests Current number of in flight requests. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus icp_sal_AsymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +/** + ***************************************************************************** + * @ingroup icp_sal_user + * Retrieve number of in flight requests for a symmetric tx ring + * from a crypto instancei (Data Plane API). + * + * @description + * This function is a part of back-pressure mechanism. + * Applications can query the appropriate service/ring on each instance + * and select any instance with sufficient space or + * the instance with the lowest number. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Crypto API instance handle. + * @param[out] maxInflightRequests Maximal number of in flight requests. + * @param[out] numInflightRequests Current number of in flight requests. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +/** + ***************************************************************************** + * @ingroup icp_sal_user + * Updates the CSR with queued requests in the asymmetric tx ring. + * + * @description + * The function writes current shadow tail pointer of the asymmetric + * TX ring into ring's CSR. Updating the CSR will notify the HW that + * there are request(s) queued to be processed. The CSR is updated + * always, disregarding the current value of shadow tail pointer and + * the current CSR's tail value. + * + * @assumptions + * None + * @sideEffects + * None + * @blocking + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Crypto API instance handle. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus icp_sal_AsymPerformOpNow(CpaInstanceHandle instanceHandle); +#endif diff --git a/sys/dev/qat/qat_api/include/icp_sal_versions.h b/sys/dev/qat/qat_api/include/icp_sal_versions.h new file mode 100644 index 00000000000..0a013fe46b8 --- /dev/null +++ b/sys/dev/qat/qat_api/include/icp_sal_versions.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file icp_sal_versions.h + * + * @defgroup SalVersions + * + * @ingroup SalVersions + * + * API and structures definition for obtaining software and hardware versions + * + ***************************************************************************/ + +#ifndef _ICP_SAL_VERSIONS_H_ +#define _ICP_SAL_VERSIONS_H_ + +#define ICP_SAL_VERSIONS_FW_VERSION_SIZE 16 +/**< Max length of firmware version string */ +#define ICP_SAL_VERSIONS_SW_VERSION_SIZE 16 +/**< Max length of software version string */ +#define ICP_SAL_VERSIONS_MMP_VERSION_SIZE 16 +/**< Max length of MMP binary version string */ +#define ICP_SAL_VERSIONS_HW_VERSION_SIZE 4 +/**< Max length of hardware version string */ + +/* Part name and number of the accelerator device */ +#define SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER 3 +#define SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER 11 +#define SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER 0 + +/** +******************************************************************************* + * @ingroup SalVersions + * Structure holding versions information + * + * @description + * This structure stores information about versions of software + * and hardware being run on a particular device. + *****************************************************************************/ +typedef struct icp_sal_dev_version_info_s { + Cpa32U devId; + /**< Number of acceleration device for which this structure holds + * version + * information */ + Cpa8U firmwareVersion[ICP_SAL_VERSIONS_FW_VERSION_SIZE]; + /**< String identifying the version of the firmware associated with + * the device. */ + Cpa8U mmpVersion[ICP_SAL_VERSIONS_MMP_VERSION_SIZE]; + /**< String identifying the version of the MMP binary associated with + * the device. */ + Cpa8U softwareVersion[ICP_SAL_VERSIONS_SW_VERSION_SIZE]; + /**< String identifying the version of the software associated with + * the device. */ + Cpa8U hardwareVersion[ICP_SAL_VERSIONS_HW_VERSION_SIZE]; + /**< String identifying the version of the hardware (stepping and + * revision ID) associated with the device. */ +} icp_sal_dev_version_info_t; + +/** +******************************************************************************* + * @ingroup SalVersions + * Obtains the version information for a given device + * @description + * This function obtains hardware and software version information + * associated with a given device. + * + * @param[in] accelId ID of the acceleration device for which version + * information is to be obtained. + * @param[out] pVerInfo Pointer to a structure that will hold version + * information + * + * @context + * This function might sleep. It cannot be executed in a context that + * does not permit sleeping. + * @assumptions + * The system has been started + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @return CPA_STATUS_SUCCESS Operation finished successfully + * @return CPA_STATUS_INVALID_PARAM Invalid parameter passed to the function + * @return CPA_STATUS_RESOURCE System resources problem + * @return CPA_STATUS_FAIL Operation failed + * + *****************************************************************************/ +CpaStatus icp_sal_getDevVersionInfo(Cpa32U accelId, + icp_sal_dev_version_info_t *pVerInfo); + +#endif diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_common.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_common.h new file mode 100644 index 00000000000..aff4c717ac9 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_common.h @@ -0,0 +1,649 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_common.h + * + * @defgroup cpaCy Cryptographic API + * + * @ingroup cpa + * + * @description + * These functions specify the Cryptographic API. + * + *****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_common.h + * @defgroup cpaCyCommon Cryptographic Common API + * + * @ingroup cpaCy + * + * @description + * This file specifies items which are common for both the asymmetric + * (public key cryptography) and the symmetric operations for the + * Cryptographic API. + * + *****************************************************************************/ +#ifndef CPA_CY_COMMON_H +#define CPA_CY_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa.h" + +/** + ***************************************************************************** + * @ingroup cpa_cyCommon + * CPA CY Major Version Number + * @description + * The CPA_CY API major version number. This number will be incremented + * when significant churn to the API has occurred. The combination of the + * major and minor number definitions represent the complete version number + * for this interface. + * + *****************************************************************************/ +#define CPA_CY_API_VERSION_NUM_MAJOR (2) + +/** + ***************************************************************************** + * @ingroup cpa_cyCommon + * CPA CY Minor Version Number + * @description + * The CPA_CY API minor version number. This number will be incremented + * when minor changes to the API has occurred. The combination of the major + * and minor number definitions represent the complete version number for + * this interface. + * + *****************************************************************************/ +#define CPA_CY_API_VERSION_NUM_MINOR (3) + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Request priority + * @description + * Enumeration of priority of the request to be given to the API. + * Currently two levels - HIGH and NORMAL are supported. HIGH priority + * requests will be prioritized on a "best-effort" basis over requests + * that are marked with a NORMAL priority. + * + *****************************************************************************/ +typedef enum _CpaCyPriority +{ + CPA_CY_PRIORITY_NORMAL = 1, /**< Normal priority */ + CPA_CY_PRIORITY_HIGH /**< High priority */ +} CpaCyPriority; + +/*****************************************************************************/ +/* Callback Definitions */ +/*****************************************************************************/ +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Definition of the crypto generic callback function + * + * @description + * This data structure specifies the prototype for a generic callback + * function + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag Opaque value provided by user while making individual + * function call. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque Pointer to the operation data that was + * submitted in the request + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyKeyGenSsl() + * + *****************************************************************************/ +typedef void (*CpaCyGenericCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Definition of generic callback function with an additional output + * CpaFlatBuffer parameter. + * + * @description + * This data structure specifies the prototype for a generic callback + * function which provides an output buffer (of type CpaFlatBuffer). + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag Opaque value provided by user while making individual + * function call. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque Pointer to the operation data that was + * submitted in the request + * @param[in] pOut Pointer to the output buffer provided in the request + * invoking this callback. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * None + * + *****************************************************************************/ +typedef void (*CpaCyGenFlatBufCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpdata, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Function to return the size of the memory which must be allocated for + * the pPrivateMetaData member of CpaBufferList. + * + * @description + * This function is used obtain the size (in bytes) required to allocate + * a buffer descriptor for the pPrivateMetaData member in the + * CpaBufferList the structure. + * Should the function return zero then no meta data is required for the + * buffer list. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[in] numBuffers The number of pointers in the CpaBufferList. + * this is the maximum number of CpaFlatBuffers + * which may be contained in this CpaBufferList. + * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be + * allocated when the client wishes to allocate + * a cpaFlatBuffer + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None. + * @post + * None + * @note + * None + * @see + * cpaCyGetInstances() + * + *****************************************************************************/ +CpaStatus +cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Function to return a string indicating the specific error that occurred + * for a particular instance. + * + * @description + * When a function invocation on a particular instance returns an error, + * the client can invoke this function to query the instance for a null + * terminated string which describes the general error condition, and if + * available additional text on the specific error. + * The Client MUST allocate CPA_STATUS_MAX_STR_LENGTH_IN_BYTES bytes for + * the buffer string. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[in] errStatus The error condition that occurred + * @param[out] pStatusText Pointer to the string buffer that will be + * updated with a null terminated status text + * string. + * The invoking application MUST allocate this + * buffer to be CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Note, In this scenario it + * is INVALID to call this function a further + * time. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None. + * @post + * None + * @note + * None + * @see + * CpaStatus + * + *****************************************************************************/ +CpaStatus +cpaCyGetStatusText(const CpaInstanceHandle instanceHandle, + CpaStatus errStatus, + Cpa8S *pStatusText); + +/*****************************************************************************/ +/* Instance Discovery Functions */ +/*****************************************************************************/ +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Get the number of instances that are supported by the API + * implementation. + * + * @description + * This function will get the number of instances that are supported + * by an implementation of the Cryptographic API. This number is then + * used to determine the size of the array that must be passed to + * @ref cpaCyGetInstances(). + * + * @context + * This function MUST NOT be called from an interrupt context as it MAY + * sleep. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[out] pNumInstances Pointer to where the number of + * instances will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated + * + * @see + * cpaCyGetInstances + * + *****************************************************************************/ +CpaStatus +cpaCyGetNumInstances(Cpa16U *pNumInstances); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Get the handles to the instances that are supported by the + * API implementation. + * + * @description + * This function will return handles to the instances that are + * supported by an implementation of the Cryptographic API. These + * instance handles can then be used as input parameters with other + * Cryptographic API functions. + * + * This function will populate an array that has been allocated by the + * caller. The size of this API will have been determined by the + * cpaCyGetNumInstances() function. + * + * @context + * This function MUST NOT be called from an interrupt context as it MAY + * sleep. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] numInstances Size of the array. If the value is not + * the same as the number of instances + * supported, then an error (@ref + * CPA_STATUS_INVALID_PARAM) is returned. + * @param[in,out] cyInstances Pointer to where the instance + * handles will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated + * + * @see + * cpaCyGetNumInstances + * + *****************************************************************************/ +CpaStatus +cpaCyGetInstances(Cpa16U numInstances, + CpaInstanceHandle *cyInstances); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Function to get information on a particular instance. + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyInstanceGetInfo2. + * + * @description + * This function will provide instance specific information through a + * @ref CpaInstanceInfo structure. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API to be + * initialized. + * @param[out] pInstanceInfo Pointer to the memory location allocated by + * the client into which the CpaInstanceInfo + * structure will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The client has retrieved an instanceHandle from successive calls to + * @ref cpaCyGetNumInstances and @ref cpaCyGetInstances. + * @post + * None + * @note + * None + * @see + * cpaCyGetNumInstances, + * cpaCyGetInstances, + * CpaInstanceInfo + * + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle, + struct _CpaInstanceInfo * pInstanceInfo); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Function to get information on a particular instance. + * + * @description + * This function will provide instance specific information through a + * @ref CpaInstanceInfo2 structure. + * Supersedes @ref cpaCyInstanceGetInfo. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API to be + * initialized. + * @param[out] pInstanceInfo2 Pointer to the memory location allocated by + * the client into which the CpaInstanceInfo2 + * structure will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The client has retrieved an instanceHandle from successive calls to + * @ref cpaCyGetNumInstances and @ref cpaCyGetInstances. + * @post + * None + * @note + * None + * @see + * cpaCyGetNumInstances, + * cpaCyGetInstances, + * CpaInstanceInfo + * + *****************************************************************************/ +CpaStatus +cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle, + CpaInstanceInfo2 * pInstanceInfo2); + +/*****************************************************************************/ +/* Instance Notification Functions */ +/*****************************************************************************/ +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Callback function for instance notification support. + * + * @description + * This is the prototype for the instance notification callback function. + * The callback function is passed in as a parameter to the + * @ref cpaCyInstanceSetNotificationCb function. + * + * @context + * This function will be executed in a context that requires that sleeping + * MUST NOT be permitted. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function calls. + * @param[in] instanceEvent The event that will trigger this function to + * get invoked. + * + * @retval + * None + * @pre + * Component has been initialized and the notification function has been + * set via the cpaCyInstanceSetNotificationCb function. + * @post + * None + * @note + * None + * @see + * cpaCyInstanceSetNotificationCb(), + * + *****************************************************************************/ +typedef void (*CpaCyInstanceNotificationCbFunc)( + const CpaInstanceHandle instanceHandle, + void * pCallbackTag, + const CpaInstanceEvent instanceEvent); + +/** + ***************************************************************************** + * @ingroup cpaCyCommon + * Subscribe for instance notifications. + * + * @description + * Clients of the CpaCy interface can subscribe for instance notifications + * by registering a @ref CpaCyInstanceNotificationCbFunc function. + * + * @context + * This function may be called from any context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pInstanceNotificationCb Instance notification callback + * function pointer. + * @param[in] pCallbackTag Opaque value provided by user while + * making individual function calls. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Instance has been initialized. + * @post + * None + * @note + * None + * @see + * CpaCyInstanceNotificationCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_COMMON_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_dh.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_dh.h new file mode 100644 index 00000000000..e5123c89aca --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_dh.h @@ -0,0 +1,514 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_dh.h + * + * @defgroup cpaCyDh Diffie-Hellman (DH) API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) operations for use with Diffie-Hellman algorithm. + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + *****************************************************************************/ + +#ifndef CPA_CY_DH_H +#define CPA_CY_DH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Diffie-Hellman Phase 1 Key Generation Data. + * @description + * This structure lists the different items that are required in the + * cpaCyDhKeyGenPhase1 function. The client MUST allocate the memory for + * this structure. When the structure is passed into the function, + * ownership of the memory passes to the function. Ownership of the memory + * returns to the client when this structure is returned with the + * CpaCyDhPhase1KeyGenOpData structure. + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyDhKeyGenPhase1 function, and + * before it has been returned in the callback, undefined behavior will + * result. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. primeP.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyDhPhase1KeyGenOpData { + CpaFlatBuffer primeP; + /**< Flat buffer containing a pointer to the random odd prime number (p). + * The bit-length of this number may be one of 768, 1024, 1536, 2048, + * 3072 or 4096. + */ + CpaFlatBuffer baseG; + /**< Flat buffer containing a pointer to base (g). This MUST comply with + * the following: + * 0 < g < p. + */ + CpaFlatBuffer privateValueX; + /**< Flat buffer containing a pointer to the private value (x). This is a + * random value which MUST satisfy the following condition: + * 0 < PrivateValueX < (PrimeP - 1) + * + * Refer to PKCS #3: Diffie-Hellman Key-Agreement Standard for details. + * The client creating this data MUST ensure the compliance of this value + * with the standard. Note: This value is also needed to complete local + * phase 2 Diffie-Hellman operation.*/ +} CpaCyDhPhase1KeyGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Diffie-Hellman Phase 2 Secret Key Generation Data. + * @description + * This structure lists the different items that required in the + * cpaCyDhKeyGenPhase2Secret function. The client MUST allocate the + * memory for this structure. When the structure is passed into the + * function, ownership of the memory passes to the function. Ownership of + * the memory returns to the client when this structure is returned with + * the callback. + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyDhKeyGenPhase2Secret + * function, and before it has been returned in the callback, undefined + * behavior will result. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. primeP.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyDhPhase2SecretKeyGenOpData { + CpaFlatBuffer primeP; + /**< Flat buffer containing a pointer to the random odd prime number (p). + * The bit-length of this number may be one of 768, 1024, 1536, 2048, + * 3072 or 4096. + * This SHOULD be same prime number as was used in the phase 1 key + * generation operation. */ + CpaFlatBuffer remoteOctetStringPV; + /**< Flat buffer containing a pointer to the remote entity + * octet string Public Value (PV). */ + CpaFlatBuffer privateValueX; + /**< Flat buffer containing a pointer to the private value (x). This + * value may have been used in a call to the cpaCyDhKeyGenPhase1 function. + * This is a random value which MUST satisfy the following condition: + * 0 < privateValueX < (primeP - 1). */ +} CpaCyDhPhase2SecretKeyGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Diffie-Hellman Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyDhStats64. + * @description + * This structure contains statistics on the Diffie-Hellman operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + ****************************************************************************/ +typedef struct _CpaCyDhStats { + Cpa32U numDhPhase1KeyGenRequests; + /**< Total number of successful Diffie-Hellman phase 1 key + * generation requests. */ + Cpa32U numDhPhase1KeyGenRequestErrors; + /**< Total number of Diffie-Hellman phase 1 key generation requests + * that had an error and could not be processed. */ + Cpa32U numDhPhase1KeyGenCompleted; + /**< Total number of Diffie-Hellman phase 1 key generation operations + * that completed successfully. */ + Cpa32U numDhPhase1KeyGenCompletedErrors; + /**< Total number of Diffie-Hellman phase 1 key generation operations + * that could not be completed successfully due to errors. */ + Cpa32U numDhPhase2KeyGenRequests; + /**< Total number of successful Diffie-Hellman phase 2 key + * generation requests. */ + Cpa32U numDhPhase2KeyGenRequestErrors; + /**< Total number of Diffie-Hellman phase 2 key generation requests + * that had an error and could not be processed. */ + Cpa32U numDhPhase2KeyGenCompleted; + /**< Total number of Diffie-Hellman phase 2 key generation operations + * that completed successfully. */ + Cpa32U numDhPhase2KeyGenCompletedErrors; + /**< Total number of Diffie-Hellman phase 2 key generation operations + * that could not be completed successfully due to errors. */ +} CpaCyDhStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Diffie-Hellman Statistics (64-bit version). + * @description + * This structure contains the 64-bit version of the statistics on the + * Diffie-Hellman operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + ****************************************************************************/ +typedef struct _CpaCyDhStats64 { + Cpa64U numDhPhase1KeyGenRequests; + /**< Total number of successful Diffie-Hellman phase 1 key + * generation requests. */ + Cpa64U numDhPhase1KeyGenRequestErrors; + /**< Total number of Diffie-Hellman phase 1 key generation requests + * that had an error and could not be processed. */ + Cpa64U numDhPhase1KeyGenCompleted; + /**< Total number of Diffie-Hellman phase 1 key generation operations + * that completed successfully. */ + Cpa64U numDhPhase1KeyGenCompletedErrors; + /**< Total number of Diffie-Hellman phase 1 key generation operations + * that could not be completed successfully due to errors. */ + Cpa64U numDhPhase2KeyGenRequests; + /**< Total number of successful Diffie-Hellman phase 2 key + * generation requests. */ + Cpa64U numDhPhase2KeyGenRequestErrors; + /**< Total number of Diffie-Hellman phase 2 key generation requests + * that had an error and could not be processed. */ + Cpa64U numDhPhase2KeyGenCompleted; + /**< Total number of Diffie-Hellman phase 2 key generation operations + * that completed successfully. */ + Cpa64U numDhPhase2KeyGenCompletedErrors; + /**< Total number of Diffie-Hellman phase 2 key generation operations + * that could not be completed successfully due to errors. */ +} CpaCyDhStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Function to implement Diffie-Hellman phase 1 operations. + * + * @description + * This function may be used to implement the Diffie-Hellman phase 1 + * operations as defined in the PKCS #3 standard. It may be used to + * generate the the (local) octet string public value (PV) key. + * The prime number sizes specified in RFC 2409, 4306, and part of + * RFC 3526 are supported (bit sizes 6144 and 8192 from RFC 3536 are not + * supported). + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pDhPhase1Cb Pointer to a callback function to be invoked + * when the operation is complete. If the + * pointer is set to a NULL value the function + * will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the callback + * @param[in] pPhase1KeyGenData Structure containing all the data needed + * to perform the DH Phase 1 key generation + * operation. The client code allocates the + * memory for this structure. This component + * takes ownership of the memory until it is + * returned in the callback. + * @param[out] pLocalOctetStringPV Pointer to memory allocated by the client + * into which the (local) octet string Public + * Value (PV) will be written. This value + * needs to be sent to the remote entity with + * which Diffie-Hellman is negotiating. + * The size of this buffer in bytes (as + * represented by the dataLenInBytes field) + * MUST be at least big enough to store + * the public value, which may have a bit + * length up to that of pPrimeP. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pDhPhase1Cb is non-NULL an asynchronous callback of type + * CpaCyGenFlatBufCbFunc is generated in response to this function + * call. Any errors generated during processing are reported in the + * structure returned in the callback. + * + * @see + * CpaCyGenFlatBufCbFunc, + * CpaCyDhPhase1KeyGenOpData + * + *****************************************************************************/ +CpaStatus +cpaCyDhKeyGenPhase1(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase1Cb, + void *pCallbackTag, + const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, + CpaFlatBuffer *pLocalOctetStringPV); + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Function to implement Diffie-Hellman phase 2 operations. + * + * @description + * This function may be used to implement the Diffie-Hellman phase 2 + * operation as defined in the PKCS #3 standard. It may be used to + * generate the Diffie-Hellman shared secret key. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pDhPhase2Cb Pointer to a callback function to be + * invoked when the operation is complete. + * If the pointer is set to a NULL value + * the function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in + * the callback. + * @param[in] pPhase2SecretKeyGenData Structure containing all the data + * needed to perform the DH Phase 2 + * secret key generation operation. The + * client code allocates the memory for + * this structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pOctetStringSecretKey Pointer to memory allocated by the + * client into which the octet string + * secret key will be written. + * The size of this buffer in bytes (as + * represented by the dataLenInBytes field) + * MUST be at least big enough to store + * the public value, which may have a bit + * length up to that of pPrimeP. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pDhPhase2Cb is non-NULL an asynchronous callback of type + * CpaCyGenFlatBufCbFunc is generated in response to this function + * call. Any errors generated during processing are reported in the + * structure returned in the callback. + * + * @see + * CpaCyGenFlatBufCbFunc, + * CpaCyDhPhase2SecretKeyGenOpData + * + *****************************************************************************/ +CpaStatus +cpaCyDhKeyGenPhase2Secret(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase2Cb, + void *pCallbackTag, + const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, + CpaFlatBuffer *pOctetStringSecretKey); + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Query statistics for Diffie-Hellman operations + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyDhQueryStats64(). + * + * @description + * This function will query a specific Instance handle for Diffie- + * Hellman statistics. The user MUST allocate the CpaCyDhStats + * structure and pass the reference to that structure into this function + * call. This function writes the statistic results into the passed in + * CpaCyDhStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pDhStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyDhStats + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyDhQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCyDhStats *pDhStats); + +/** + ***************************************************************************** + * @ingroup cpaCyDh + * Query statistics (64-bit version) for Diffie-Hellman operations + * + * @description + * This function will query a specific Instance handle for the 64-bit + * version of the Diffie-Hellman statistics. The user MUST allocate the + * CpaCyDhStats64 structure and pass the reference to that structure into + * this function call. This function writes the statistic results into + * the passed in CpaCyDhStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pDhStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyDhStats64 + *****************************************************************************/ +CpaStatus +cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDhStats64 *pDhStats); + +/*****************************************************************************/ + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_DH_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_dsa.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_dsa.h new file mode 100644 index 00000000000..01fc6f2f04b --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_dsa.h @@ -0,0 +1,1443 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_dsa.h + * + * @defgroup cpaCyDsa Digital Signature Algorithm (DSA) API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) Digital Signature Algorithm (DSA) operations. + * + * Support is provided for FIPS PUB 186-2 with Change Notice 1 + * specification, and optionally for FIPS PUB 186-3. If an + * implementation does not support FIPS PUB 186-3, then the + * corresponding functions may return a status of @ref + * CPA_STATUS_FAIL. + * + * Support for FIPS PUB 186-2 with Change Notice 1 implies supporting + * the following choice for the pair L and N: + * - L = 1024, N = 160 + * + * Support for FIPS PUB 186-3 implies supporting the following choices + * for the pair L and N: + * + * - L = 1024, N = 160 + * - L = 2048, N = 224 + * - L = 2048, N = 256 + * - L = 3072, N = 256 + * + * Only the modular math aspects of DSA parameter generation and message + * signature generation and verification are implemented here. For full + * DSA support, this DSA API SHOULD be used in conjunction with other + * parts of this overall Cryptographic API. In particular the Symmetric + * functions (for hashing), the Random Number Generation functions, and + * the Prime Number Test functions will be required. + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + *****************************************************************************/ + +#ifndef CPA_CY_DSA_H +#define CPA_CY_DSA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA P Parameter Generation Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaGenPParam + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. X.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaGenPParam + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaGenPParam() + * + *****************************************************************************/ +typedef struct _CpaCyDsaPParamGenOpData { + CpaFlatBuffer X; + /**< 2^(L-1) <= X < 2^L (from FIPS 186-3) */ + CpaFlatBuffer Q; + /**< DSA group parameter q */ +} CpaCyDsaPParamGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA G Parameter Generation Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaGenGParam + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. P.pData[0] = MSB. + * + * All numbers MUST be stored in big-endian order. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaGenGParam + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaGenGParam() + * + *****************************************************************************/ +typedef struct _CpaCyDsaGParamGenOpData { + CpaFlatBuffer P; + /**< DSA group parameter p */ + CpaFlatBuffer Q; + /**< DSA group parameter q */ + CpaFlatBuffer H; + /**< any integer with 1 < h < p - 1 */ +} CpaCyDsaGParamGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA Y Parameter Generation Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaGenYParam + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. P.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaGenYParam + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaGenYParam() + * + *****************************************************************************/ +typedef struct _CpaCyDsaYParamGenOpData { + CpaFlatBuffer P; + /**< DSA group parameter p */ + CpaFlatBuffer G; + /**< DSA group parameter g */ + CpaFlatBuffer X; + /**< DSA private key x */ +} CpaCyDsaYParamGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA R Sign Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaSignR + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. P.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaSignR + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaSignR() + * + *****************************************************************************/ +typedef struct _CpaCyDsaRSignOpData { + CpaFlatBuffer P; + /**< DSA group parameter p */ + CpaFlatBuffer Q; + /**< DSA group parameter q */ + CpaFlatBuffer G; + /**< DSA group parameter g */ + CpaFlatBuffer K; + /**< DSA secret parameter k for signing */ +} CpaCyDsaRSignOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA S Sign Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaSignS + * function. The client MUST allocate the memory for this structure and + * the items pointed to by this structure. When the structure is passed + * into the function, ownership of the memory passes to the function. + * Ownership of the memory returns to the client when this structure is + * returned in the callback function. + * + * For optimal performance all data SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. Q.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaSignS + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaSignS() + * + *****************************************************************************/ +typedef struct _CpaCyDsaSSignOpData { + CpaFlatBuffer Q; + /**< DSA group parameter q */ + CpaFlatBuffer X; + /**< DSA private key x */ + CpaFlatBuffer K; + /**< DSA secret parameter k for signing */ + CpaFlatBuffer R; + /**< DSA message signature r */ + CpaFlatBuffer Z; + /**< The leftmost min(N, outlen) bits of Hash(M), where: + * - N is the bit length of q + * - outlen is the bit length of the hash function output block + * - M is the message to be signed + */ +} CpaCyDsaSSignOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA R & S Sign Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaSignRS + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. P.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaSignRS + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaSignRS() + * + *****************************************************************************/ +typedef struct _CpaCyDsaRSSignOpData { + CpaFlatBuffer P; + /**< DSA group parameter p */ + CpaFlatBuffer Q; + /**< DSA group parameter q */ + CpaFlatBuffer G; + /**< DSA group parameter g */ + CpaFlatBuffer X; + /**< DSA private key x */ + CpaFlatBuffer K; + /**< DSA secret parameter k for signing */ + CpaFlatBuffer Z; + /**< The leftmost min(N, outlen) bits of Hash(M), where: + * - N is the bit length of q + * - outlen is the bit length of the hash function output block + * - M is the message to be signed + */ +} CpaCyDsaRSSignOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * DSA Verify Operation Data. + * @description + * This structure contains the operation data for the cpaCyDsaVerify + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. P.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyDsaVerify + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyDsaVerify() + * + *****************************************************************************/ +typedef struct _CpaCyDsaVerifyOpData { + CpaFlatBuffer P; + /**< DSA group parameter p */ + CpaFlatBuffer Q; + /**< DSA group parameter q */ + CpaFlatBuffer G; + /**< DSA group parameter g */ + CpaFlatBuffer Y; + /**< DSA public key y */ + CpaFlatBuffer Z; + /**< The leftmost min(N, outlen) bits of Hash(M'), where: + * - N is the bit length of q + * - outlen is the bit length of the hash function output block + * - M is the message to be signed + */ + CpaFlatBuffer R; + /**< DSA message signature r */ + CpaFlatBuffer S; + /**< DSA message signature s */ +} CpaCyDsaVerifyOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Cryptographic DSA Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyDsaStats64. + * @description + * This structure contains statistics on the Cryptographic DSA + * operations. Statistics are set to zero when the component is + * initialized, and are collected per instance. + ****************************************************************************/ +typedef struct _CpaCyDsaStats { + Cpa32U numDsaPParamGenRequests; + /**< Total number of successful DSA P parameter generation requests. */ + Cpa32U numDsaPParamGenRequestErrors; + /**< Total number of DSA P parameter generation requests that had an + * error and could not be processed. */ + Cpa32U numDsaPParamGenCompleted; + /**< Total number of DSA P parameter generation operations that + * completed successfully. */ + Cpa32U numDsaPParamGenCompletedErrors; + /**< Total number of DSA P parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa32U numDsaGParamGenRequests; + /**< Total number of successful DSA G parameter generation requests. */ + Cpa32U numDsaGParamGenRequestErrors; + /**< Total number of DSA G parameter generation requests that had an + * error and could not be processed. */ + Cpa32U numDsaGParamGenCompleted; + /**< Total number of DSA G parameter generation operations that + * completed successfully. */ + Cpa32U numDsaGParamGenCompletedErrors; + /**< Total number of DSA G parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa32U numDsaYParamGenRequests; + /**< Total number of successful DSA Y parameter generation requests. */ + Cpa32U numDsaYParamGenRequestErrors; + /**< Total number of DSA Y parameter generation requests that had an + * error and could not be processed. */ + Cpa32U numDsaYParamGenCompleted; + /**< Total number of DSA Y parameter generation operations that + * completed successfully. */ + Cpa32U numDsaYParamGenCompletedErrors; + /**< Total number of DSA Y parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa32U numDsaRSignRequests; + /**< Total number of successful DSA R sign generation requests. */ + Cpa32U numDsaRSignRequestErrors; + /**< Total number of DSA R sign requests that had an error and could + * not be processed. */ + Cpa32U numDsaRSignCompleted; + /**< Total number of DSA R sign operations that completed + * successfully. */ + Cpa32U numDsaRSignCompletedErrors; + /**< Total number of DSA R sign operations that could not be completed + * successfully due to errors. */ + Cpa32U numDsaSSignRequests; + /**< Total number of successful DSA S sign generation requests. */ + Cpa32U numDsaSSignRequestErrors; + /**< Total number of DSA S sign requests that had an error and could + * not be processed. */ + Cpa32U numDsaSSignCompleted; + /**< Total number of DSA S sign operations that completed + * successfully. */ + Cpa32U numDsaSSignCompletedErrors; + /**< Total number of DSA S sign operations that could not be completed + * successfully due to errors. */ + Cpa32U numDsaRSSignRequests; + /**< Total number of successful DSA RS sign generation requests. */ + Cpa32U numDsaRSSignRequestErrors; + /**< Total number of DSA RS sign requests that had an error and could + * not be processed. */ + Cpa32U numDsaRSSignCompleted; + /**< Total number of DSA RS sign operations that completed + * successfully. */ + Cpa32U numDsaRSSignCompletedErrors; + /**< Total number of DSA RS sign operations that could not be completed + * successfully due to errors. */ + Cpa32U numDsaVerifyRequests; + /**< Total number of successful DSA verify generation requests. */ + Cpa32U numDsaVerifyRequestErrors; + /**< Total number of DSA verify requests that had an error and could + * not be processed. */ + Cpa32U numDsaVerifyCompleted; + /**< Total number of DSA verify operations that completed + * successfully. */ + Cpa32U numDsaVerifyCompletedErrors; + /**< Total number of DSA verify operations that could not be completed + * successfully due to errors. */ + Cpa32U numDsaVerifyFailures; + /**< Total number of DSA verify operations that executed successfully + * but the outcome of the test was that the verification failed. + * Note that this does not indicate an error. */ +} CpaCyDsaStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Cryptographic DSA Statistics (64-bit version). + * @description + * This structure contains 64-bit version of the statistics on the + * Cryptographic DSA operations. + * Statistics are set to zero when the component is + * initialized, and are collected per instance. + ****************************************************************************/ +typedef struct _CpaCyDsaStats64 { + Cpa64U numDsaPParamGenRequests; + /**< Total number of successful DSA P parameter generation requests. */ + Cpa64U numDsaPParamGenRequestErrors; + /**< Total number of DSA P parameter generation requests that had an + * error and could not be processed. */ + Cpa64U numDsaPParamGenCompleted; + /**< Total number of DSA P parameter generation operations that + * completed successfully. */ + Cpa64U numDsaPParamGenCompletedErrors; + /**< Total number of DSA P parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa64U numDsaGParamGenRequests; + /**< Total number of successful DSA G parameter generation requests. */ + Cpa64U numDsaGParamGenRequestErrors; + /**< Total number of DSA G parameter generation requests that had an + * error and could not be processed. */ + Cpa64U numDsaGParamGenCompleted; + /**< Total number of DSA G parameter generation operations that + * completed successfully. */ + Cpa64U numDsaGParamGenCompletedErrors; + /**< Total number of DSA G parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa64U numDsaYParamGenRequests; + /**< Total number of successful DSA Y parameter generation requests. */ + Cpa64U numDsaYParamGenRequestErrors; + /**< Total number of DSA Y parameter generation requests that had an + * error and could not be processed. */ + Cpa64U numDsaYParamGenCompleted; + /**< Total number of DSA Y parameter generation operations that + * completed successfully. */ + Cpa64U numDsaYParamGenCompletedErrors; + /**< Total number of DSA Y parameter generation operations that could + * not be completed successfully due to errors. */ + Cpa64U numDsaRSignRequests; + /**< Total number of successful DSA R sign generation requests. */ + Cpa64U numDsaRSignRequestErrors; + /**< Total number of DSA R sign requests that had an error and could + * not be processed. */ + Cpa64U numDsaRSignCompleted; + /**< Total number of DSA R sign operations that completed + * successfully. */ + Cpa64U numDsaRSignCompletedErrors; + /**< Total number of DSA R sign operations that could not be completed + * successfully due to errors. */ + Cpa64U numDsaSSignRequests; + /**< Total number of successful DSA S sign generation requests. */ + Cpa64U numDsaSSignRequestErrors; + /**< Total number of DSA S sign requests that had an error and could + * not be processed. */ + Cpa64U numDsaSSignCompleted; + /**< Total number of DSA S sign operations that completed + * successfully. */ + Cpa64U numDsaSSignCompletedErrors; + /**< Total number of DSA S sign operations that could not be completed + * successfully due to errors. */ + Cpa64U numDsaRSSignRequests; + /**< Total number of successful DSA RS sign generation requests. */ + Cpa64U numDsaRSSignRequestErrors; + /**< Total number of DSA RS sign requests that had an error and could + * not be processed. */ + Cpa64U numDsaRSSignCompleted; + /**< Total number of DSA RS sign operations that completed + * successfully. */ + Cpa64U numDsaRSSignCompletedErrors; + /**< Total number of DSA RS sign operations that could not be completed + * successfully due to errors. */ + Cpa64U numDsaVerifyRequests; + /**< Total number of successful DSA verify generation requests. */ + Cpa64U numDsaVerifyRequestErrors; + /**< Total number of DSA verify requests that had an error and could + * not be processed. */ + Cpa64U numDsaVerifyCompleted; + /**< Total number of DSA verify operations that completed + * successfully. */ + Cpa64U numDsaVerifyCompletedErrors; + /**< Total number of DSA verify operations that could not be completed + * successfully due to errors. */ + Cpa64U numDsaVerifyFailures; + /**< Total number of DSA verify operations that executed successfully + * but the outcome of the test was that the verification failed. + * Note that this does not indicate an error. */ +} CpaCyDsaStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Definition of a generic callback function invoked for a number of the + * DSA API functions.. + * + * @description + * This is the prototype for the cpaCyDsaGenCbFunc callback function. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque pointer to Operation data supplied in + * request. + * @param[in] protocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[in] pOut Output data from the request. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyDsaGenPParam() + * cpaCyDsaGenGParam() + * cpaCyDsaSignR() + * cpaCyDsaSignS() + * + *****************************************************************************/ +typedef void (*CpaCyDsaGenCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean protocolStatus, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Definition of callback function invoked for cpaCyDsaSignRS + * requests. + * + * @description + * This is the prototype for the cpaCyDsaSignRS callback function, which + * will provide the DSA message signature r and s parameters. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Operation data pointer supplied in request. + * @param[in] protocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[in] pR DSA message signature r. + * @param[in] pS DSA message signature s. + * + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyDsaSignRS() + * + *****************************************************************************/ +typedef void (*CpaCyDsaRSSignCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean protocolStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Definition of callback function invoked for cpaCyDsaVerify + * requests. + * + * @description + * This is the prototype for the cpaCyDsaVerify callback function. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Operation data pointer supplied in request. + * @param[in] verifyStatus The verification passed or failed. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyDsaVerify() + * + *****************************************************************************/ +typedef void (*CpaCyDsaVerifyCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean verifyStatus); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA P Parameter. + * + * @description + * + * This function performs FIPS 186-3 Appendix A.1.1.2 steps 11.4 and 11.5, + * and part of step 11.7: + * + * 11.4. c = X mod 2q. + * 11.5. p = X - (c - 1). + * 11.7. Test whether or not p is prime as specified in Appendix C.3. + * [Note that a GCD test against ~1400 small primes is performed + * on p to eliminate ~94% of composites - this is NOT a "robust" + * primality test, as specified in Appendix C.3.] + * + * The protocol status, returned in the callback function as parameter + * protocolStatus (or, in the case of synchronous invocation, in the + * parameter *pProtocolStatus) is used to indicate whether the value p is + * in the right range and has passed the limited primality test. + * + * Specifically, (protocolStatus == CPA_TRUE) means p is in the right range + * and SHOULD be subjected to a robust primality test as specified in + * FIPS 186-3 Appendix C.3 (for example, 40 rounds of Miller-Rabin). + * Meanwhile, (protocolStatus == CPA_FALSE) means p is either composite, + * or p < 2^(L-1), in which case the value of p gets set to zero. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is + * set to a NULL value the function will + * operate synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pP Candidate for DSA parameter p, p odd and + * 2^(L-1) < p < X + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaPParamGenCbFunc is generated in response to this + * function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaPParamGenOpData, + * CpaCyDsaGenCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyDsaGenPParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void * pCallbackTag, + const CpaCyDsaPParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pP); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA G Parameter. + * + * @description + * This function performs FIPS 186-3 Appendix A.2.1, steps 1 and 3, + * and part of step 4: + * + * 1. e = (p - 1)/q. + * 3. Set g = h^e mod p. + * 4. If (g = 1), then go to step 2. + * Here, the implementation will check for g == 1, and return + * status accordingly. + * + * + * The protocol status, returned in the callback function as parameter + * protocolStatus (or, in the case of synchronous invocation, in the + * parameter *pProtocolStatus) is used to indicate whether the value g is + * acceptable. + * + * Specifically, (protocolStatus == CPA_TRUE) means g is acceptable. + * Meanwhile, (protocolStatus == CPA_FALSE) means g == 1, so a + * different value of h SHOULD be used to generate another value of g. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pG g = h^((p-1)/q) mod p. + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaGParamGenCbFunc is generated in response to this + * function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaGParamGenOpData, + * CpaCyDsaGenCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyDsaGenGParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaGParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pG); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA Y Parameter. + * + * @description + * + * This function performs modular exponentiation to generate y as + * described in FIPS 186-3 section 4.1: + * y = g^x mod p + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pY y = g^x mod p* + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaYParamGenCbFunc is generated in response to this + * function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaYParamGenOpData, + * CpaCyDsaGenCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyDsaGenYParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaYParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pY); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA R Signature. + * + * @description + * This function generates the DSA R signature as described in FIPS 186-3 + * Section 4.6: + * r = (g^k mod p) mod q + * + * The protocol status, returned in the callback function as parameter + * protocolStatus (or, in the case of synchronous invocation, in the + * parameter *pProtocolStatus) is used to indicate whether the value r == 0. + * + * Specifically, (protocolStatus == CPA_TRUE) means r != 0, while + * (protocolStatus == CPA_FALSE) means r == 0. + * + * Generation of signature r does not depend on the content of the message + * being signed, so this operation can be done in advance for different + * values of k. Then once each message becomes available only the + * signature s needs to be generated. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pR DSA message signature r. + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaRSignCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaRSignOpData, + * CpaCyDsaGenCbFunc, + * cpaCyDsaSignS(), + * cpaCyDsaSignRS() + * + *****************************************************************************/ +CpaStatus +cpaCyDsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA S Signature. + * + * @description + * This function generates the DSA S signature as described in FIPS 186-3 + * Section 4.6: + * s = (k^-1(z + xr)) mod q + * + * Here, z = the leftmost min(N, outlen) bits of Hash(M). This function + * does not perform the SHA digest; z is computed by the caller and + * passed as a parameter in the pOpData field. + * + * The protocol status, returned in the callback function as parameter + * protocolStatus (or, in the case of synchronous invocation, in the + * parameter *pProtocolStatus) is used to indicate whether the value s == 0. + * + * Specifically, (protocolStatus == CPA_TRUE) means s != 0, while + * (protocolStatus == CPA_FALSE) means s == 0. + * + * If signature r has been generated in advance, then this function can be + * used to generate the signature s once the message becomes available. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pS DSA message signature s. + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaSSignCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaSSignOpData, + * CpaCyDsaGenCbFunc, + * cpaCyDsaSignR(), + * cpaCyDsaSignRS() + * + *****************************************************************************/ +CpaStatus +cpaCyDsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pS); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Generate DSA R and S Signatures. + * + * @description + * This function generates the DSA R and S signatures as described in + * FIPS 186-3 Section 4.6: + * + * r = (g^k mod p) mod q + * s = (k^-1(z + xr)) mod q + * + * Here, z = the leftmost min(N, outlen) bits of Hash(M). This function + * does not perform the SHA digest; z is computed by the caller and + * passed as a parameter in the pOpData field. + * + * The protocol status, returned in the callback function as parameter + * protocolStatus (or, in the case of synchronous invocation, in the + * parameter *pProtocolStatus) is used to indicate whether either of + * the values r or s are zero. + * + * Specifically, (protocolStatus == CPA_TRUE) means neither is zero (i.e. + * (r != 0) && (s != 0)), while (protocolStatus == CPA_FALSE) means that at + * least one of r or s is zero (i.e. (r == 0) || (s == 0)). + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pProtocolStatus The result passes/fails the DSA protocol + * related checks. + * @param[out] pR DSA message signature r. + * @param[out] pS DSA message signature s. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaRSSignCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaRSSignOpData, + * CpaCyDsaRSSignCbFunc, + * cpaCyDsaSignR(), + * cpaCyDsaSignS() + * + *****************************************************************************/ +CpaStatus +cpaCyDsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaRSSignCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Verify DSA R and S signatures. + * + * @description + * This function performs FIPS 186-3 Section 4.7: + * w = (s')^-1 mod q + * u1 = (zw) mod q + * u2 = ((r')w) mod q + * v = (((g)^u1 (y)^u2) mod p) mod q + * + * Here, z = the leftmost min(N, outlen) bits of Hash(M'). This function + * does not perform the SHA digest; z is computed by the caller and + * passed as a parameter in the pOpData field. + * + * A response status of ok (verifyStatus == CPA_TRUE) means v = r'. + * A response status of not ok (verifyStatus == CPA_FALSE) means v != r'. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pVerifyStatus The verification passed or failed. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyDsaVerifyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyDsaVerifyOpData, + * CpaCyDsaVerifyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyDsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyDsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Query statistics for a specific DSA instance. + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyDsaQueryStats64(). + * + * @description + * This function will query a specific instance of the DSA implementation + * for statistics. The user MUST allocate the CpaCyDsaStats structure + * and pass the reference to that structure into this function call. This + * function writes the statistic results into the passed in + * CpaCyDsaStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pDsaStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyDsaStats + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyDsaQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCyDsaStats *pDsaStats); + +/** + ***************************************************************************** + * @ingroup cpaCyDsa + * Query 64-bit statistics for a specific DSA instance. + * + * @description + * This function will query a specific instance of the DSA implementation + * for 64-bit statistics. The user MUST allocate the CpaCyDsaStats64 + * structure and pass the reference to that structure into this function. + * This function writes the statistic results into the passed in + * CpaCyDsaStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pDsaStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyDsaStats + *****************************************************************************/ +CpaStatus +cpaCyDsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDsaStats64 *pDsaStats); + +/*****************************************************************************/ + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_DSA_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_ec.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_ec.h new file mode 100644 index 00000000000..f93a7ab1093 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_ec.h @@ -0,0 +1,766 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_ec.h + * + * @defgroup cpaCyEc Elliptic Curve (EC) API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) Elliptic Curve (EC) operations. + * + * All implementations will support at least the following: + * + * - "NIST RECOMMENDED ELLIPTIC CURVES FOR FEDERAL GOVERNMENT USE" + * as defined by + * http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf + * + * - Random curves where the max(log2(q), log2(n) + log2(h)) <= 512 + * where q is the modulus, n is the order of the curve and h is the + * cofactor + * + * For Montgomery and Edwards 25519 and 448 elliptic curves, + * the following operations are supported: + * 1. Montgomery 25519 Curve | scalar point Multiplication + * Input: Montgomery affine coordinate X of point P + * Scalar k + * Output: Montgomery affine coordinate X of point [k/P + * Decode: Scalar k always decoded by implementation + * + * 2. Montgomery 25519 Curve | generator point Multiplication + * Input: Scalar k + * Output: Montgomery affine coordinate X of point [k]G + * Decode: Scalar k always decoded by implementation + * + * 3. Twisted Edwards 25519 Curve | scalar point Multiplication + * Input: Twisted Edwards affine coordinate X of point P + * Twisted Edwards affine coordinate Y of point P + * Scalar k + * Output: Twisted Edwards affine coordinate X of point [k]P + * Twisted Edwards affine coordinate Y of point [k]P + * Decode: Caller must specify if decoding is required + * + * 4. Twisted Edwards 25519 Curve | generator point Multiplication + * Input: Scalar k + * Output: Twisted Edwards affine coordinate X of point [k]G + * Twisted Edwards affine coordinate Y of point [k]G + * Decode: Caller must specify if decoding is required + * + * 5. Montgomery 448 Curve | scalar point Multiplication + * Input: Montgomery affine coordinate X of point P + * Scalar k + * Output: Montgomery affine coordinate X of point [k]P + * Decode: Scalar k always decoded by implementation + * + * 6. Montgomery 448 Curve | generator point Multiplication + * Input: Scalar k + * Output: Montgomery affine coordinate X of point [k]G + * Decode: Scalar k always decoded by implementation + * + * 7. Edwards 448 Curve | scalar point Multiplication + * Input: Edwards affine coordinate X of point P + * Edwards affine coordinate Y of point P + * Scalar k + * Output: Edwards affine coordinate X of point [k]P + * Edwards affine coordinate Y of point [k]P + * Decode: Caller must specify if decoding is required + * + * 8. Edwards 448 Curve | generator point Multiplication + * Input: Scalar k + * Output: Edwards affine coordinate X of point [k]G + * Edwards affine coordinate Y of point [k]G + * Decode: Caller must specify if decoding is required + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + * + * In addition, the bit length of large numbers passed to the API + * MUST NOT exceed 576 bits for Elliptic Curve operations. + *****************************************************************************/ + +#ifndef CPA_CY_EC_H_ +#define CPA_CY_EC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Field types for Elliptic Curve + + * @description + * As defined by FIPS-186-3, for each cryptovariable length, there are + * two kinds of fields. + *

        + *
      • A prime field is the field GF(p) which contains a prime number + * p of elements. The elements of this field are the integers modulo + * p, and the field arithmetic is implemented in terms of the + * arithmetic of integers modulo p.
      • + * + *
      • A binary field is the field GF(2^m) which contains 2^m elements + * for some m (called the degree of the field). The elements of + * this field are the bit strings of length m, and the field + * arithmetic is implemented in terms of operations on the bits.
      • + *
      + *****************************************************************************/ +typedef enum _CpaCyEcFieldType +{ + CPA_CY_EC_FIELD_TYPE_PRIME = 1, + /**< A prime field, GF(p) */ + CPA_CY_EC_FIELD_TYPE_BINARY, + /**< A binary field, GF(2^m) */ +} CpaCyEcFieldType; + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Curve types for Elliptic Curves defined in RFC#7748 + + * @description + * As defined by RFC 7748, there are four elliptic curves in this + * group. The Montgomery curves are denoted curve25519 and curve448, + * and the birationally equivalent Twisted Edwards curves are denoted + * edwards25519 and edwards448 + * + *****************************************************************************/ +typedef enum _CpaCyEcMontEdwdsCurveType +{ + CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE = 1, + /**< Montgomery 25519 curve */ + CPA_CY_EC_MONTEDWDS_ED25519_TYPE, + /**< Twisted Edwards 25519 curve */ + CPA_CY_EC_MONTEDWDS_CURVE448_TYPE, + /**< Montgomery 448 curve */ + CPA_CY_EC_MONTEDWDS_ED448_TYPE, + /**< Twisted Edwards 448 curve */ +} CpaCyEcMontEdwdsCurveType; + +/** + ***************************************************************************** + * @file cpa_cy_ec.h + * @ingroup cpaCyEc + * EC Point Multiplication Operation Data. + * + * @description + * This structure contains the operation data for the cpaCyEcPointMultiply + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcPointMultiply + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcPointMultiply() + * + *****************************************************************************/ +typedef struct _CpaCyEcPointMultiplyOpData { + CpaFlatBuffer k; + /**< scalar multiplier (k > 0 and k < n) */ + CpaFlatBuffer xg; + /**< x coordinate of curve point */ + CpaFlatBuffer yg; + /**< y coordinate of curve point */ + CpaFlatBuffer a; + /**< a elliptic curve coefficient */ + CpaFlatBuffer b; + /**< b elliptic curve coefficient */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^m)*/ + CpaFlatBuffer h; + /**< cofactor of the operation. + * If the cofactor is NOT required then set the cofactor to 1 or the + * data pointer of the Flat Buffer to NULL. */ + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcPointMultiplyOpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * EC Point Verification Operation Data. + * + * @description + * This structure contains the operation data for the cpaCyEcPointVerify + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the CpaCyEcPointVerify + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcPointVerify() + * + *****************************************************************************/ +typedef struct _CpaCyEcPointVerifyOpData { + CpaFlatBuffer xq; + /**< x coordinate candidate point */ + CpaFlatBuffer yq; + /**< y coordinate candidate point */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^m) */ + CpaFlatBuffer a; + /**< a elliptic curve coefficient */ + CpaFlatBuffer b; + /**< b elliptic curve coefficient */ + + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcPointVerifyOpData; + +/** + ***************************************************************************** + * @file cpa_cy_ec.h + * @ingroup cpaCyEc + * EC Point Multiplication Operation Data for Edwards or + 8 Montgomery curves as specificied in RFC#7748. + * + * @description + * This structure contains the operation data for the + * cpaCyEcMontEdwdsPointMultiply function. + * The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcPointMultiply + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * All buffers in this structure need to be: + * - 32 bytes in size for 25519 curves + * - 64 bytes in size for 448 curves + * + * @see + * cpaCyEcMontEdwdsPointMultiply() + * + *****************************************************************************/ +typedef struct _CpaCyEcMontEdwdsPointMultiplyOpData { + CpaCyEcMontEdwdsCurveType curveType; + /**< field type for the operation */ + CpaBoolean generator; + /**< True if the operation is a generator multiplication (kG) + * False if it is a variable point multiplcation (kP). */ + CpaFlatBuffer k; + /**< k or generator for the operation */ + CpaFlatBuffer x; + /**< x value. Used in scalar varable point multiplication operations. + * Not required if the generator is True. Must be NULL if not required. + * The size of the buffer MUST be 32B for 25519 curves and 64B for 448 + * curves */ + CpaFlatBuffer y; + /**< y value. Used in variable point multiplication of operations. + * Not required for curves defined only on scalar operations. + * Not required if the generator is True. + * Must be NULL if not required. + * The size of the buffer MUST be 32B for 25519 curves and 64B for 448 + * curves */ +} CpaCyEcMontEdwdsPointMultiplyOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Cryptographic EC Statistics. + * + * @description + * This structure contains statistics on the Cryptographic EC + * operations. Statistics are set to zero when the component is + * initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyEcStats64 { + Cpa64U numEcPointMultiplyRequests; + /**< Total number of EC Point Multiplication operation requests. */ + Cpa64U numEcPointMultiplyRequestErrors; + /**< Total number of EC Point Multiplication operation requests that had an + * error and could not be processed. */ + Cpa64U numEcPointMultiplyCompleted; + /**< Total number of EC Point Multiplication operation requests that + * completed successfully. */ + Cpa64U numEcPointMultiplyCompletedError; + /**< Total number of EC Point Multiplication operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcPointMultiplyCompletedOutputInvalid; + /**< Total number of EC Point Multiplication operation requests that could + * not be completed successfully due to an invalid output. + * Note that this does not indicate an error. */ + Cpa64U numEcPointVerifyRequests; + /**< Total number of EC Point Verification operation requests. */ + Cpa64U numEcPointVerifyRequestErrors; + /**< Total number of EC Point Verification operation requests that had an + * error and could not be processed. */ + Cpa64U numEcPointVerifyCompleted; + /**< Total number of EC Point Verification operation requests that completed + * successfully. */ + Cpa64U numEcPointVerifyCompletedErrors; + /**< Total number of EC Point Verification operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcPointVerifyCompletedOutputInvalid; + /**< Total number of EC Point Verification operation requests that had an + * invalid output. Note that this does not indicate an error. */ +} CpaCyEcStats64; + + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Definition of callback function invoked for cpaCyEcPointMultiply + * requests. + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque pointer to Operation data supplied in + * request. + * @param[in] multiplyStatus Status of the point multiplication. + * @param[in] pXk x coordinate of resultant EC point. + * @param[in] pYk y coordinate of resultant EC point. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcPointMultiply() + * + *****************************************************************************/ +typedef void (*CpaCyEcPointMultiplyCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean multiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk); + + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Definition of callback function invoked for cpaCyEcPointVerify + * requests. + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Operation data pointer supplied in request. + * @param[in] verifyStatus Set to CPA_FALSE if the point is NOT on the + * curve or at infinity. Set to CPA_TRUE if the + * point is on the curve. + * + * @return + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcPointVerify() + * + *****************************************************************************/ +typedef void (*CpaCyEcPointVerifyCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean verifyStatus); + + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Perform EC Point Multiplication. + * + * @description + * This function performs Elliptic Curve Point Multiplication as per + * ANSI X9.63 Annex D.3.2. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pMultiplyStatus In synchronous mode, the multiply output is + * valid (CPA_TRUE) or the output is invalid + * (CPA_FALSE). + * @param[out] pXk Pointer to xk flat buffer. + * @param[out] pYk Pointer to yk flat buffer. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyEcPointMultiplyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyEcPointMultiplyOpData, + * CpaCyEcPointMultiplyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyEcPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk); + + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Verify that a point is on an elliptic curve. + * + * @description + * This function performs Elliptic Curve Point Verification, as per + * steps a, b and c of ANSI X9.62 Annex A.4.2. (To perform the final + * step d, the user can call @ref cpaCyEcPointMultiply.) + * + * This function checks if the specified point satisfies the + * Weierstrass equation for an Elliptic Curve. + * + * For GF(p): + * y^2 = (x^3 + ax + b) mod p + * For GF(2^m): + * y^2 + xy = x^3 + ax^2 + b mod p + * where p is the irreducible polynomial over GF(2^m) + * + * Use this function to verify a point is in the correct range and is + * NOT the point at infinity. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pVerifyStatus In synchronous mode, set to CPA_FALSE if the + * point is NOT on the curve or at infinity. Set + * to CPA_TRUE if the point is on the curve. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyEcPointVerifyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyEcPointVerifyOpData, + * CpaCyEcPointVerifyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyEcPointVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus); + +/** + ***************************************************************************** + * @file cpa_cy_ec.h + * @ingroup cpaCyEc + * Perform EC Point Multiplication on an Edwards or Montgomery curve as + * defined in RFC#7748. + * + * @description + * This function performs Elliptic Curve Point Multiplication as per + * RFC#7748 + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pMultiplyStatus In synchronous mode, the multiply output is + * valid (CPA_TRUE) or the output is invalid + * (CPA_FALSE). + * @param[out] pXk Pointer to xk flat buffer. + * @param[out] pYk Pointer to yk flat buffer. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyEcPointMultiplyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyEcMontEdwdsPointMultiplyOpData, + * CpaCyEcMontEdwdsPointMultiplyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyEcMontEdwdsPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk); + +/** + ***************************************************************************** + * @ingroup cpaCyEc + * Query statistics for a specific EC instance. + * + * @description + * This function will query a specific instance of the EC implementation + * for statistics. The user MUST allocate the CpaCyEcStats64 structure + * and pass the reference to that structure into this function call. This + * function writes the statistic results into the passed in + * CpaCyEcStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pEcStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyEcStats64 + *****************************************************************************/ +CpaStatus +cpaCyEcQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcStats64 *pEcStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /*CPA_CY_EC_H_*/ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdh.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdh.h new file mode 100644 index 00000000000..f520a3720e3 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdh.h @@ -0,0 +1,358 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_ecdh.h + * + * @defgroup cpaCyEcdh Elliptic Curve Diffie-Hellman (ECDH) API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) Elliptic Curve Diffie-Hellman (ECDH) operations. + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + * + * In addition, the bit length of large numbers passed to the API + * MUST NOT exceed 576 bits for Elliptic Curve operations. + *****************************************************************************/ + +#ifndef CPA_CY_ECDH_H_ +#define CPA_CY_ECDH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" +#include "cpa_cy_ec.h" + +/** + ***************************************************************************** + * @ingroup cpaCyEcdh + * ECDH Point Multiplication Operation Data. + * + * @description + * This structure contains the operation data for the + * cpaCyEcdhPointMultiply function. The client MUST allocate the memory + * for this structure and the items pointed to by this structure. When + * the structure is passed into the function, ownership of the memory + * passes to the function. Ownership of the memory returns to the client + * when this structure is returned in the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcdhPointMultiply + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcdhPointMultiply() + * + *****************************************************************************/ +typedef struct _CpaCyEcdhPointMultiplyOpData { + CpaFlatBuffer k; + /**< scalar multiplier (k > 0 and k < n) */ + CpaFlatBuffer xg; + /**< x coordinate of curve point */ + CpaFlatBuffer yg; + /**< y coordinate of curve point */ + CpaFlatBuffer a; + /**< a equation coefficient */ + CpaFlatBuffer b; + /**< b equation coefficient */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^r) */ + CpaFlatBuffer h; + /**< cofactor of the operation. + * If the cofactor is NOT required then set the cofactor to 1 or the + * data pointer of the Flat Buffer to NULL. + * There are some restrictions on the value of the cofactor. + * Implementations of this API will support at least the following: + *
        + *
      • NIST standard curves and their cofactors (1, 2 and 4)
      • + * + *
      • Random curves where max(log2(p), log2(n)+log2(h)) <= 512, where + * p is the modulus, n is the order of the curve and h is the cofactor + *
      • + *
      + */ + + CpaCyEcFieldType fieldType; + /**< field type for the operation */ + CpaBoolean pointVerify; + /**< set to CPA_TRUE to do a verification before the multiplication */ +} CpaCyEcdhPointMultiplyOpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdh + * Cryptographic ECDH Statistics. + * @description + * This structure contains statistics on the Cryptographic ECDH + * operations. Statistics are set to zero when the component is + * initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyEcdhStats64 { + Cpa64U numEcdhPointMultiplyRequests; + /**< Total number of ECDH Point Multiplication operation requests. */ + Cpa64U numEcdhPointMultiplyRequestErrors; + /**< Total number of ECDH Point Multiplication operation requests that had + * an error and could not be processed. */ + Cpa64U numEcdhPointMultiplyCompleted; + /**< Total number of ECDH Point Multiplication operation requests that + * completed successfully. */ + Cpa64U numEcdhPointMultiplyCompletedError; + /**< Total number of ECDH Point Multiplication operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcdhRequestCompletedOutputInvalid; + /**< Total number of ECDH Point Multiplication or Point Verify operation + * requests that could not be completed successfully due to an invalid + * output. + * Note that this does not indicate an error. */ +} CpaCyEcdhStats64; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdh + * Definition of callback function invoked for cpaCyEcdhPointMultiply + * requests. + * + * @description + * This is the prototype for the CpaCyEcdhPointMultiplyCbFunc callback + * function + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque pointer to Operation data supplied in + * request. + * @param[in] pXk Output x coordinate from the request. + * @param[in] pYk Output y coordinate from the request. + * @param[in] multiplyStatus Status of the point multiplication and the + * verification when the pointVerify bit is set + * in the CpaCyEcdhPointMultiplyOpData structure. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcdhPointMultiply() + * + *****************************************************************************/ +typedef void (*CpaCyEcdhPointMultiplyCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean multiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdh + * ECDH Point Multiplication. + * + * @description + * This function performs ECDH Point Multiplication as defined in + * ANSI X9.63 2001 section 5.4 + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pMultiplyStatus In synchronous mode, the status of the point + * multiplication and the verification when the + * pointVerify bit is set in the + * CpaCyEcdhPointMultiplyOpData structure. Set to + * CPA_FALSE if the point is NOT on the curve or + * at infinity. Set to CPA_TRUE if the point is + * on the curve. + * @param[out] pXk Pointer to x coordinate flat buffer. + * @param[out] pYk Pointer to y coordinate flat buffer. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyEcdhPointMultiplyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyEcdhPointMultiplyOpData, + * CpaCyEcdhPointMultiplyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyEcdhPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcdhPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdhPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdh + * Query statistics for a specific ECDH instance. + * + * @description + * This function will query a specific instance of the ECDH implementation + * for statistics. The user MUST allocate the CpaCyEcdhStats64 structure + * and pass the reference to that structure into this function call. This + * function writes the statistic results into the passed in + * CpaCyEcdhStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pEcdhStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyEcdhStats64 + *****************************************************************************/ +CpaStatus +cpaCyEcdhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdhStats64 *pEcdhStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /*CPA_CY_ECDH_H_*/ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdsa.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdsa.h new file mode 100644 index 00000000000..ee9353f6d27 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_ecdsa.h @@ -0,0 +1,839 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_ecdsa.h + * + * @defgroup cpaCyEcdsa Elliptic Curve Digital Signature Algorithm (ECDSA) API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) Elliptic Curve Digital Signature Algorithm (ECDSA) + * operations. + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + * + * In addition, the bit length of large numbers passed to the API + * MUST NOT exceed 576 bits for Elliptic Curve operations. + *****************************************************************************/ + +#ifndef CPA_CY_ECDSA_H_ +#define CPA_CY_ECDSA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" +#include "cpa_cy_ec.h" + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * ECDSA Sign R Operation Data. + * @description + * This structure contains the operation data for the cpaCyEcdsaSignR + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcdsaSignR + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcdsaSignR() + * + *****************************************************************************/ +typedef struct _CpaCyEcdsaSignROpData { + CpaFlatBuffer xg; + /**< x coordinate of base point G */ + CpaFlatBuffer yg; + /**< y coordinate of base point G */ + CpaFlatBuffer n; + /**< order of the base point G, which shall be prime */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^r) */ + CpaFlatBuffer a; + /**< a elliptic curve coefficient */ + CpaFlatBuffer b; + /**< b elliptic curve coefficient */ + CpaFlatBuffer k; + /**< random value (k > 0 and k < n) */ + + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcdsaSignROpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * ECDSA Sign S Operation Data. + * @description + * This structure contains the operation data for the cpaCyEcdsaSignS + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcdsaSignS + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcdsaSignS() + * + *****************************************************************************/ +typedef struct _CpaCyEcdsaSignSOpData { + CpaFlatBuffer m; + /**< digest of the message to be signed */ + CpaFlatBuffer d; + /**< private key */ + CpaFlatBuffer r; + /**< Ecdsa r signature value */ + CpaFlatBuffer k; + /**< random value (k > 0 and k < n) */ + CpaFlatBuffer n; + /**< order of the base point G, which shall be prime */ + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcdsaSignSOpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * ECDSA Sign R & S Operation Data. + * @description + * This structure contains the operation data for the cpaCyEcdsaSignRS + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcdsaSignRS + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyEcdsaSignRS() + * + *****************************************************************************/ +typedef struct _CpaCyEcdsaSignRSOpData { + CpaFlatBuffer xg; + /**< x coordinate of base point G */ + CpaFlatBuffer yg; + /**< y coordinate of base point G */ + CpaFlatBuffer n; + /**< order of the base point G, which shall be prime */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^r) */ + CpaFlatBuffer a; + /**< a elliptic curve coefficient */ + CpaFlatBuffer b; + /**< b elliptic curve coefficient */ + CpaFlatBuffer k; + /**< random value (k > 0 and k < n) */ + CpaFlatBuffer m; + /**< digest of the message to be signed */ + CpaFlatBuffer d; + /**< private key */ + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcdsaSignRSOpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * ECDSA Verify Operation Data, for Public Key. + + * @description + * This structure contains the operation data for the CpaCyEcdsaVerify + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * For optimal performance all data buffers SHOULD be 8-byte aligned. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. a.pData[0] = MSB. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyEcdsaVerify + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * CpaCyEcdsaVerify() + * + *****************************************************************************/ +typedef struct _CpaCyEcdsaVerifyOpData { + CpaFlatBuffer xg; + /**< x coordinate of base point G */ + CpaFlatBuffer yg; + /**< y coordinate of base point G */ + CpaFlatBuffer n; + /**< order of the base point G, which shall be prime */ + CpaFlatBuffer q; + /**< prime modulus or irreducible polynomial over GF(2^r) */ + CpaFlatBuffer a; + /**< a elliptic curve coefficient */ + CpaFlatBuffer b; + /**< b elliptic curve coefficient */ + CpaFlatBuffer m; + /**< digest of the message to be signed */ + CpaFlatBuffer r; + /**< ECDSA r signature value (r > 0 and r < n) */ + CpaFlatBuffer s; + /**< ECDSA s signature value (s > 0 and s < n) */ + CpaFlatBuffer xp; + /**< x coordinate of point P (public key) */ + CpaFlatBuffer yp; + /**< y coordinate of point P (public key) */ + CpaCyEcFieldType fieldType; + /**< field type for the operation */ +} CpaCyEcdsaVerifyOpData; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Cryptographic ECDSA Statistics. + * @description + * This structure contains statistics on the Cryptographic ECDSA + * operations. Statistics are set to zero when the component is + * initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyEcdsaStats64 { + Cpa64U numEcdsaSignRRequests; + /**< Total number of ECDSA Sign R operation requests. */ + Cpa64U numEcdsaSignRRequestErrors; + /**< Total number of ECDSA Sign R operation requests that had an error and + * could not be processed. */ + Cpa64U numEcdsaSignRCompleted; + /**< Total number of ECDSA Sign R operation requests that completed + * successfully. */ + Cpa64U numEcdsaSignRCompletedErrors; + /**< Total number of ECDSA Sign R operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcdsaSignRCompletedOutputInvalid; + /**< Total number of ECDSA Sign R operation requests could not be completed + * successfully due to an invalid output. + * Note that this does not indicate an error. */ + Cpa64U numEcdsaSignSRequests; + /**< Total number of ECDSA Sign S operation requests. */ + Cpa64U numEcdsaSignSRequestErrors; + /**< Total number of ECDSA Sign S operation requests that had an error and + * could not be processed. */ + Cpa64U numEcdsaSignSCompleted; + /**< Total number of ECDSA Sign S operation requests that completed + * successfully. */ + Cpa64U numEcdsaSignSCompletedErrors; + /**< Total number of ECDSA Sign S operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcdsaSignSCompletedOutputInvalid; + /**< Total number of ECDSA Sign S operation requests could not be completed + * successfully due to an invalid output. + * Note that this does not indicate an error. */ + Cpa64U numEcdsaSignRSRequests; + /**< Total number of ECDSA Sign R & S operation requests. */ + Cpa64U numEcdsaSignRSRequestErrors; + /**< Total number of ECDSA Sign R & S operation requests that had an + * error and could not be processed. */ + Cpa64U numEcdsaSignRSCompleted; + /**< Total number of ECDSA Sign R & S operation requests that completed + * successfully. */ + Cpa64U numEcdsaSignRSCompletedErrors; + /**< Total number of ECDSA Sign R & S operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcdsaSignRSCompletedOutputInvalid; + /**< Total number of ECDSA Sign R & S operation requests could not be + * completed successfully due to an invalid output. + * Note that this does not indicate an error. */ + Cpa64U numEcdsaVerifyRequests; + /**< Total number of ECDSA Verification operation requests. */ + Cpa64U numEcdsaVerifyRequestErrors; + /**< Total number of ECDSA Verification operation requests that had an + * error and could not be processed. */ + Cpa64U numEcdsaVerifyCompleted; + /**< Total number of ECDSA Verification operation requests that completed + * successfully. */ + Cpa64U numEcdsaVerifyCompletedErrors; + /**< Total number of ECDSA Verification operation requests that could + * not be completed successfully due to errors. */ + Cpa64U numEcdsaVerifyCompletedOutputInvalid; + /**< Total number of ECDSA Verification operation requests that resulted + * in an invalid output. + * Note that this does not indicate an error. */ +} CpaCyEcdsaStats64; + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Definition of a generic callback function invoked for a number of the + * ECDSA Sign API functions. + * + * @description + * This is the prototype for the CpaCyEcdsaGenSignCbFunc callback function. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque pointer to Operation data supplied in + * request. + * @param[in] multiplyStatus Status of the point multiplication. + * @param[in] pOut Output data from the request. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcdsaSignR() + * cpaCyEcdsaSignS() + * + *****************************************************************************/ +typedef void (*CpaCyEcdsaGenSignCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean multiplyStatus, + CpaFlatBuffer *pOut); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Definition of callback function invoked for cpaCyEcdsaSignRS + * requests. + * + * @description + * This is the prototype for the CpaCyEcdsaSignRSCbFunc callback function, + * which will provide the ECDSA message signature r and s parameters. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Operation data pointer supplied in request. + * @param[in] multiplyStatus Status of the point multiplication. + * @param[in] pR Ecdsa message signature r. + * @param[in] pS Ecdsa message signature s. + * + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcdsaSignRS() + * + *****************************************************************************/ +typedef void (*CpaCyEcdsaSignRSCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean multiplyStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Definition of callback function invoked for cpaCyEcdsaVerify requests. + * + * @description + * This is the prototype for the CpaCyEcdsaVerifyCbFunc callback function. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Operation data pointer supplied in request. + * @param[in] verifyStatus The verification status. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyEcdsaVerify() + * + *****************************************************************************/ +typedef void (*CpaCyEcdsaVerifyCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean verifyStatus); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Generate ECDSA Signature R. + * + * @description + * This function generates ECDSA Signature R as per ANSI X9.62 2005 + * section 7.3. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pSignStatus In synchronous mode, the multiply output is + * valid (CPA_TRUE) or the output is invalid + * (CPA_FALSE). + * @param[out] pR ECDSA message signature r. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback is generated in response + * to this function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * None + *****************************************************************************/ +CpaStatus +cpaCyEcdsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignROpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Generate ECDSA Signature S. + * + * @description + * This function generates ECDSA Signature S as per ANSI X9.62 2005 + * section 7.3. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pSignStatus In synchronous mode, the multiply output is + * valid (CPA_TRUE) or the output is invalid + * (CPA_FALSE). + * @param[out] pS ECDSA message signature s. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback is generated in response + * to this function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * None + *****************************************************************************/ +CpaStatus +cpaCyEcdsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pS); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Generate ECDSA Signature R & S. + * + * @description + * This function generates ECDSA Signature R & S as per ANSI X9.62 2005 + * section 7.3. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to a + * NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pSignStatus In synchronous mode, the multiply output is + * valid (CPA_TRUE) or the output is invalid + * (CPA_FALSE). + * @param[out] pR ECDSA message signature r. + * @param[out] pS ECDSA message signature s. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback is generated in response + * to this function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * None + *****************************************************************************/ +CpaStatus +cpaCyEcdsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaSignRSCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignRSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Verify ECDSA Public Key. + * + * @description + * This function performs ECDSA Verify as per ANSI X9.62 2005 section 7.4. + * + * A response status of ok (verifyStatus == CPA_TRUE) means that the + * signature was verified + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pVerifyStatus In synchronous mode, set to CPA_FALSE if the + * point is NOT on the curve or at infinity. Set + * to CPA_TRUE if the point is on the curve. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyEcdsaVerifyCbFunc is generated in response to this function + * call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyEcdsaVerifyOpData, + * CpaCyEcdsaVerifyCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyEcdsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus); + + +/** + ***************************************************************************** + * @ingroup cpaCyEcdsa + * Query statistics for a specific ECDSA instance. + * + * @description + * This function will query a specific instance of the ECDSA implementation + * for statistics. The user MUST allocate the CpaCyEcdsaStats64 structure + * and pass the reference to that structure into this function call. This + * function writes the statistic results into the passed in + * CpaCyEcdsaStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pEcdsaStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyEcdsaStats64 + *****************************************************************************/ +CpaStatus +cpaCyEcdsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdsaStats64 *pEcdsaStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /*CPA_CY_ECDSA_H_*/ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_im.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_im.h new file mode 100644 index 00000000000..25463a78cac --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_im.h @@ -0,0 +1,339 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_im.h + * + * @defgroup cpaCyInstMaint Cryptographic Instance Management API + * + * @ingroup cpaCy + * + * @description + * These functions specify the Instance Management API for available + * Cryptographic Instances. It is expected that these functions will only be + * called via a single system maintenance entity, rather than individual + * clients. + * + *****************************************************************************/ + +#ifndef CPA_CY_IM_H_ +#define CPA_CY_IM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyInstMaint + * Cryptographic Component Initialization and Start function. + * + * @description + * This function will initialize and start the Cryptographic component. + * It MUST be called before any other crypto function is called. This + * function SHOULD be called only once (either for the very first time, + * or after an cpaCyStopInstance call which succeeded) per instance. + * Subsequent calls will have no effect. + * + * @context + * This function may sleep, and MUST NOT be called in interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * @param[out] instanceHandle Handle to an instance of this API to be + * initialized. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Suggested course of action + * is to shutdown and restart. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None. + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * cpaCyStopInstance() + * + *****************************************************************************/ +CpaStatus +cpaCyStartInstance(CpaInstanceHandle instanceHandle); + +/** + ***************************************************************************** + * @ingroup cpaCyInstMaint + * Cryptographic Component Stop function. + * + * @description + * This function will stop the Cryptographic component and free + * all system resources associated with it. The client MUST ensure that + * all outstanding operations have completed before calling this function. + * The recommended approach to ensure this is to deregister all session or + * callback handles before calling this function. If outstanding + * operations still exist when this function is invoked, the callback + * function for each of those operations will NOT be invoked and the + * shutdown will continue. If the component is to be restarted, then a + * call to cpaCyStartInstance is required. + * + * @context + * This function may sleep, and so MUST NOT be called in interrupt + * context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * @param[in] instanceHandle Handle to an instance of this API to be + * shutdown. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. Suggested course of action + * is to ensure requests are not still being + * submitted and that all sessions are + * deregistered. If this does not help, then + * forcefully remove the component from the + * system. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance. + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * cpaCyStartInstance() + * + *****************************************************************************/ +CpaStatus +cpaCyStopInstance(CpaInstanceHandle instanceHandle); + +/** + ***************************************************************************** + * @ingroup cpaCyInstMaint + * Cryptographic Capabilities Info + * + * @description + * This structure contains the capabilities that vary across API + * implementations. This structure is used in conjunction with + * @ref cpaCyQueryCapabilities() to determine the capabilities supported + * by a particular API implementation. + * + * The client MUST allocate memory for this structure and any members + * that require memory. When the structure is passed into the function + * ownership of the memory passes to the function. Ownership of the + * memory returns to the client when the function returns. + *****************************************************************************/ +typedef struct _CpaCyCapabilitiesInfo +{ + CpaBoolean symSupported; + /**< CPA_TRUE if instance supports the symmetric cryptography API. + * See @ref cpaCySym. */ + CpaBoolean symDpSupported; + /**< CPA_TRUE if instance supports the symmetric cryptography + * data plane API. + * See @ref cpaCySymDp. */ + CpaBoolean dhSupported; + /**< CPA_TRUE if instance supports the Diffie Hellman API. + * See @ref cpaCyDh. */ + CpaBoolean dsaSupported; + /**< CPA_TRUE if instance supports the DSA API. + * See @ref cpaCyDsa. */ + CpaBoolean rsaSupported; + /**< CPA_TRUE if instance supports the RSA API. + * See @ref cpaCyRsa. */ + CpaBoolean ecSupported; + /**< CPA_TRUE if instance supports the Elliptic Curve API. + * See @ref cpaCyEc. */ + CpaBoolean ecdhSupported; + /**< CPA_TRUE if instance supports the Elliptic Curve Diffie Hellman API. + * See @ref cpaCyEcdh. */ + CpaBoolean ecdsaSupported; + /**< CPA_TRUE if instance supports the Elliptic Curve DSA API. + * See @ref cpaCyEcdsa. */ + CpaBoolean keySupported; + /**< CPA_TRUE if instance supports the Key Generation API. + * See @ref cpaCyKeyGen. */ + CpaBoolean lnSupported; + /**< CPA_TRUE if instance supports the Large Number API. + * See @ref cpaCyLn. */ + CpaBoolean primeSupported; + /**< CPA_TRUE if instance supports the prime number testing API. + * See @ref cpaCyPrime. */ + CpaBoolean drbgSupported; + /**< CPA_TRUE if instance supports the DRBG API. + * See @ref cpaCyDrbg. */ + CpaBoolean nrbgSupported; + /**< CPA_TRUE if instance supports the NRBG API. + * See @ref cpaCyNrbg. */ + CpaBoolean randSupported; + /**< CPA_TRUE if instance supports the random bit/number generation API. + * See @ref cpaCyRand. */ + CpaBoolean kptSupported; + /**< CPA_TRUE if instance supports the Intel(R) KPT Cryptographic API. + * See @ref cpaCyKpt. */ + CpaBoolean hkdfSupported; + /**< CPA_TRUE if instance supports the HKDF components of the KeyGen API. + * See @ref cpaCyKeyGen. */ + CpaBoolean extAlgchainSupported; + /**< CPA_TRUE if instance supports algorithm chaining for certain + * wireless algorithms. Please refer to implementation for details. + * See @ref cpaCySym. */ + CpaBoolean ecEdMontSupported; + /**< CPA_TRUE if instance supports the Edwards and Montgomery elliptic + * curves of the EC API. + * See @ref cpaCyEc */ +} CpaCyCapabilitiesInfo; + +/** + ***************************************************************************** + * @ingroup cpaCyInstMaint + * Returns capabilities of a Cryptographic API instance + * + * @description + * This function is used to query the instance capabilities. + * + * @context + * The function shall not be called in an interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[out] pCapInfo Pointer to capabilities info structure. + * All fields in the structure + * are populated by the API instance. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The instance has been initialized via the @ref cpaCyStartInstance + * function. + * @post + * None + *****************************************************************************/ +CpaStatus +cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle, + CpaCyCapabilitiesInfo * pCapInfo); + +/** + ***************************************************************************** + * @ingroup cpaCyInstMaint + * Sets the address translation function + * + * @description + * This function is used to set the virtual to physical address + * translation routine for the instance. The specified routine + * is used by the instance to perform any required translation of + * a virtual address to a physical address. If the application + * does not invoke this function, then the instance will use its + * default method, such as virt2phys, for address translation. + + * @context + * The function shall not be called in an interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[in] virtual2Physical Routine that performs virtual to + * physical address translation. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * None + * @post + * None + * @see + * None + * + *****************************************************************************/ +CpaStatus +cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle, + CpaVirtualToPhysical virtual2Physical); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /*CPA_CY_IM_H_*/ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_key.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_key.h new file mode 100644 index 00000000000..6162647b120 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_key.h @@ -0,0 +1,1207 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * + * @defgroup cpaCyKeyGen Cryptographic Key and Mask Generation API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for key and mask generation + * operations. + * + *****************************************************************************/ + +#ifndef CPA_CY_KEY_H +#define CPA_CY_KEY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" +#include "cpa_cy_sym.h" /* needed for hash algorithm, for MGF */ + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * SSL or TLS key generation random number length. + * + * @description + * Defines the permitted SSL or TLS random number length in bytes that + * may be used with the functions @ref cpaCyKeyGenSsl and @ref + * cpaCyKeyGenTls. This is the length of the client or server random + * number values. + *****************************************************************************/ +#define CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES (32) + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * SSL Operation Types + * @description + * Enumeration of the different SSL operations that can be specified in + * the struct @ref CpaCyKeyGenSslOpData. It identifies the label. + *****************************************************************************/ +typedef enum _CpaCyKeySslOp +{ + CPA_CY_KEY_SSL_OP_MASTER_SECRET_DERIVE = 1, + /**< Derive the master secret */ + CPA_CY_KEY_SSL_OP_KEY_MATERIAL_DERIVE, + /**< Derive the key material */ + CPA_CY_KEY_SSL_OP_USER_DEFINED + /**< User Defined Operation for custom labels*/ +} CpaCyKeySslOp; + + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * SSL data for key generation functions + * @description + * This structure contains data for use in key generation operations for + * SSL. For specific SSL key generation operations, the structure fields + * MUST be set as follows: + * + * @par SSL Master-Secret Derivation: + *
      sslOp = CPA_CY_KEY_SSL_OP_MASTER_SECRET_DERIVE + *
      secret = pre-master secret key + *
      seed = client_random + server_random + *
      userLabel = NULL + * + * @par SSL Key-Material Derivation: + *
      sslOp = CPA_CY_KEY_SSL_OP_KEY_MATERIAL_DERIVE + *
      secret = master secret key + *
      seed = server_random + client_random + *
      userLabel = NULL + * + *
      Note that the client/server random order is reversed from that + * used for master-secret derivation. + * + * @note Each of the client and server random numbers need to be of + * length CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES. + * + * @note In each of the above descriptions, + indicates concatenation. + * + * @note The label used is predetermined by the SSL operation in line + * with the SSL 3.0 specification, and can be overridden by using + * a user defined operation CPA_CY_KEY_SSL_OP_USER_DEFINED and + * associated userLabel. + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenSslOpData { + CpaCyKeySslOp sslOp; + /**< Indicate the SSL operation to be performed */ + CpaFlatBuffer secret; + /**< Flat buffer containing a pointer to either the master or pre-master + * secret key. The length field indicates the length of the secret key in + * bytes. Implementation-specific limits may apply to this length. */ + CpaFlatBuffer seed; + /**< Flat buffer containing a pointer to the seed data. + * Implementation-specific limits may apply to this length. */ + CpaFlatBuffer info; + /**< Flat buffer containing a pointer to the info data. + * Implementation-specific limits may apply to this length. */ + Cpa32U generatedKeyLenInBytes; + /**< The requested length of the generated key in bytes. + * Implementation-specific limits may apply to this length. */ + CpaFlatBuffer userLabel; + /**< Optional flat buffer containing a pointer to a user defined label. + * The length field indicates the length of the label in bytes. To use this + * field, the sslOp must be CPA_CY_KEY_SSL_OP_USER_DEFINED, + * or otherwise it is ignored and can be set to NULL. + * Implementation-specific limits + * may apply to this length. */ +} CpaCyKeyGenSslOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * TLS Operation Types + * @description + * Enumeration of the different TLS operations that can be specified in + * the CpaCyKeyGenTlsOpData. It identifies the label. + * + * The functions @ref cpaCyKeyGenTls and @ref cpaCyKeyGenTls2 + * accelerate the TLS PRF, which is defined as part of RFC2246 (TLS + * v1.0), RFC4346 (TLS v1.1), and RFC5246 (TLS v1.2). + * One of the inputs to each of these functions is a label. + * This enumerated type defines values that correspond to some of + * the required labels. + * However, for some of the operations/labels required by these RFCs, + * no values are specified. + * + * In such cases, a user-defined value must be provided. The client + * should use the enum value @ref CPA_CY_KEY_TLS_OP_USER_DEFINED, and + * pass the label using the userLabel field of the @ref + * CpaCyKeyGenTlsOpData data structure. + * + *****************************************************************************/ +typedef enum _CpaCyKeyTlsOp +{ + CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE = 1, + /**< Derive the master secret using the TLS PRF. + * Corresponds to RFC2246/5246 section 8.1, operation "Computing the + * master secret", label "master secret". */ + CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE, + /**< Derive the key material using the TLS PRF. + * Corresponds to RFC2246/5246 section 6.3, operation "Derive the key + * material", label "key expansion". */ + CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE, + /**< Derive the client finished tag using the TLS PRF. + * Corresponds to RFC2246/5246 section 7.4.9, operation "Client finished", + * label "client finished". */ + CPA_CY_KEY_TLS_OP_SERVER_FINISHED_DERIVE, + /**< Derive the server finished tag using the TLS PRF. + * Corresponds to RFC2246/5246 section 7.4.9, operation "Server finished", + * label "server finished". */ + CPA_CY_KEY_TLS_OP_USER_DEFINED + /**< User Defined Operation for custom labels. */ + +} CpaCyKeyTlsOp; + + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS Operation Types + * @description + * Enumeration of the different TLS operations that can be specified in + * the CpaCyKeyGenHKDFOpData. + * + * The function @ref cpaCyKeyGenTls3 + * accelerates the TLS HKDF, which is defined as part of RFC5869 (HKDF) + * and RFC8446 (TLS v1.3). + * + * This enumerated type defines the support HKDF operations for + * extraction and expansion of keying material. + * + *****************************************************************************/ +typedef enum _CpaCyKeyHKDFOp +{ + CPA_CY_HKDF_KEY_EXTRACT = 12, + /**< HKDF Extract operation + * Corresponds to RFC5869 section 2.2, step 1 "Extract" */ + CPA_CY_HKDF_KEY_EXPAND, + /**< HKDF Expand operation + * Corresponds to RFC5869 section 2.3, step 2 "Expand" */ + CPA_CY_HKDF_KEY_EXTRACT_EXPAND, + /**< HKDF operation + * This performs HKDF_EXTRACT and HKDF_EXPAND in a single + * API invocation. */ + CPA_CY_HKDF_KEY_EXPAND_LABEL , + /**< HKDF Expand label operation for TLS 1.3 + * Corresponds to RFC8446 section 7.1 Key Schedule definition for + * HKDF-Expand-Label, which refers to HKDF-Expand defined in RFC5869. */ + CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL + /**< HKDF Extract plus Expand label operation for TLS 1.3 + * Corresponds to RFC5869 section 2.2, step 1 "Extract" followed by + * RFC8446 section 7.1 Key Schedule definition for + * HKDF-Expand-Label, which refers to HKDF-Expand defined in RFC5869. */ +} CpaCyKeyHKDFOp; + + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS Operation Types + * @description + * Enumeration of the different cipher suites that may be used in a TLS + * v1.3 operation. This value is used to infer the sizes of the key + * and iv sublabel. + * + * The function @ref cpaCyKeyGenTls3 + * accelerates the TLS HKDF, which is defined as part of RFC5869 (HKDF) + * and RFC8446 (TLS v1.3). + * + * This enumerated type defines the supported cipher suites in the + * TLS operation that require HKDF key operations. + * + *****************************************************************************/ +typedef enum _CpaCyKeyHKDFCipherSuite +{ + CPA_CY_HKDF_TLS_AES_128_GCM_SHA256 = 1, + CPA_CY_HKDF_TLS_AES_256_GCM_SHA384, + CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256 , + CPA_CY_HKDF_TLS_AES_128_CCM_SHA256, + CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256 +} CpaCyKeyHKDFCipherSuite; + + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS Operation Types + * @description + * Bitwise constants for HKDF sublabels + * + * These definitions provide bit settings for sublabels for + * HKDF-ExpandLabel operations. + * + *
      key sublabel to generate "key" keying material + *
      iv sublabel to generate "iv" keying material + *
      resumption sublabel to generate "resumption" keying material + *
      finished sublabel to generate "finished" keying material + * + *****************************************************************************/ + +#define CPA_CY_HKDF_SUBLABEL_KEY ((Cpa16U)0x0001) + /**< Bit for creation of key material for 'key' sublabel */ +#define CPA_CY_HKDF_SUBLABEL_IV ((Cpa16U)0x0002) + /**< Bit for creation of key material for 'iv' sublabel */ +#define CPA_CY_HKDF_SUBLABEL_RESUMPTION ((Cpa16U)0x0004) + /**< Bit for creation of key material for 'resumption' sublabel */ +#define CPA_CY_HKDF_SUBLABEL_FINISHED ((Cpa16U)0x0008) + /**< Bit for creation of key material for 'finished' sublabel */ + +#define CPA_CY_HKDF_KEY_MAX_SECRET_SZ ((Cpa8U)64) + /** space in bytes PSK or (EC)DH */ +#define CPA_CY_HKDF_KEY_MAX_HMAC_SZ ((Cpa8U)48) + /** space in bytes of CPA_CY_SYM_HASH_SHA384 result */ +#define CPA_CY_HKDF_KEY_MAX_INFO_SZ ((Cpa8U)80) + /** space in bytes of largest info needed for TLS 1.3, + * rounded up to multiple of 8 */ +#define CPA_CY_HKDF_KEY_MAX_LABEL_SZ ((Cpa8U)78) + /** space in bytes of largest label for TLS 1.3 */ +#define CPA_CY_HKDF_KEY_MAX_LABEL_COUNT ((Cpa8U)4) + /** Maximum number of labels in op structure */ + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS data for key generation functions + * @description + * This structure contains data for describing label for the + * HKDF Extract Label function + * + * @par Extract Label Function + *
      labelLen = length of the label field + *
      contextLen = length of the context field + *
      sublabelFlag = Mask of sub labels required for this label. + *
      label = label as defined in RFC8446 + *
      context = context as defined in RFC8446 + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenHKDFExpandLabel +{ + Cpa8U label[CPA_CY_HKDF_KEY_MAX_LABEL_SZ]; + /**< HKDFLabel field as defined in RFC8446 sec 7.1. + */ + Cpa8U labelLen; + /**< The length, in bytes of the label */ + Cpa8U sublabelFlag; + /**< mask of sublabels to be generated. + * This flag is composed of zero or more of: + * CPA_CY_HKDF_SUBLABEL_KEY + * CPA_CY_HKDF_SUBLABEL_IV + * CPA_CY_HKDF_SUBLABEL_RESUMPTION + * CPA_CY_HKDF_SUBLABEL_FINISHED + */ +} CpaCyKeyGenHKDFExpandLabel; + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS data for key generation functions + * @description + * This structure contains data for all HKDF operations: + *
      HKDF Extract + *
      HKDF Expand + *
      HKDF Expand Label + *
      HKDF Extract and Expand + *
      HKDF Extract and Expand Label + * + * @par HKDF Map Structure Elements + *
      secret - IKM value for extract operations or PRK for expand + * or expand operations. + *
      seed - contains the salt for extract + * operations + *
      info - contains the info data for extract operations + *
      labels - See notes above + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenHKDFOpData +{ + CpaCyKeyHKDFOp hkdfKeyOp; + /**< Keying operation to be performed. */ + Cpa8U secretLen; + /**< Length of secret field */ + Cpa16U seedLen; + /**< Length of seed field */ + Cpa16U infoLen; + /**< Length of info field */ + Cpa16U numLabels; + /**< Number of filled CpaCyKeyGenHKDFExpandLabel elements */ + Cpa8U secret[CPA_CY_HKDF_KEY_MAX_SECRET_SZ]; + /**< Input Key Material or PRK */ + Cpa8U seed[CPA_CY_HKDF_KEY_MAX_HMAC_SZ]; + /**< Input salt */ + Cpa8U info[CPA_CY_HKDF_KEY_MAX_INFO_SZ]; + /**< info field */ + CpaCyKeyGenHKDFExpandLabel label[CPA_CY_HKDF_KEY_MAX_LABEL_COUNT]; + /**< array of Expand Label structures */ +} CpaCyKeyGenHKDFOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * TLS data for key generation functions + * @description + * This structure contains data for use in key generation operations for + * TLS. For specific TLS key generation operations, the structure fields + * MUST be set as follows: + * + * @par TLS Master-Secret Derivation: + *
      tlsOp = CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE + *
      secret = pre-master secret key + *
      seed = client_random + server_random + *
      userLabel = NULL + * + * @par TLS Key-Material Derivation: + *
      tlsOp = CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE + *
      secret = master secret key + *
      seed = server_random + client_random + *
      userLabel = NULL + * + *
      Note that the client/server random order is reversed from + * that used for Master-Secret Derivation. + * + * @par TLS Client finished/Server finished tag Derivation: + *
      tlsOp = CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE (client) + *
      or CPA_CY_KEY_TLS_OP_SERVER_FINISHED_DERIVE (server) + *
      secret = master secret key + *
      seed = MD5(handshake_messages) + SHA-1(handshake_messages) + *
      userLabel = NULL + * + * @note Each of the client and server random seeds need to be of + * length CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES. + * @note In each of the above descriptions, + indicates concatenation. + * @note The label used is predetermined by the TLS operation in line + * with the TLS specifications, and can be overridden by using + * a user defined operation CPA_CY_KEY_TLS_OP_USER_DEFINED + * and associated userLabel. + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenTlsOpData { + CpaCyKeyTlsOp tlsOp; + /**< TLS operation to be performed */ + CpaFlatBuffer secret; + /**< Flat buffer containing a pointer to either the master or pre-master + * secret key. The length field indicates the length of the secret in + * bytes. */ + CpaFlatBuffer seed; + /**< Flat buffer containing a pointer to the seed data. + * Implementation-specific limits may apply to this length. */ + Cpa32U generatedKeyLenInBytes; + /**< The requested length of the generated key in bytes. + * Implementation-specific limits may apply to this length. */ + CpaFlatBuffer userLabel; + /**< Optional flat buffer containing a pointer to a user defined label. + * The length field indicates the length of the label in bytes. To use this + * field, the tlsOp must be CPA_CY_KEY_TLS_OP_USER_DEFINED. + * Implementation-specific limits may apply to this length. */ +} CpaCyKeyGenTlsOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Key Generation Mask Generation Function (MGF) Data + * @description + * This structure contains data relating to Mask Generation Function + * key generation operations. + * + * @note The default hash algorithm used by the MGF is SHA-1. If a + * different hash algorithm is preferred, then see the extended + * version of this structure, @ref CpaCyKeyGenMgfOpDataExt. + * @see + * cpaCyKeyGenMgf + ****************************************************************************/ +typedef struct _CpaCyKeyGenMgfOpData { + CpaFlatBuffer seedBuffer; + /**< Caller MUST allocate a buffer and populate with the input seed + * data. For optimal performance the start of the seed SHOULD be allocated + * on an 8-byte boundary. The length field represents the seed length in + * bytes. Implementation-specific limits may apply to this length. */ + Cpa32U maskLenInBytes; + /**< The requested length of the generated mask in bytes. + * Implementation-specific limits may apply to this length. */ +} CpaCyKeyGenMgfOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Extension to the original Key Generation Mask Generation Function + * (MGF) Data + * @description + * This structure is an extension to the original MGF data structure. + * The extension allows the hash function to be specified. + * @note + * This structure is separate from the base @ref CpaCyKeyGenMgfOpData + * structure in order to retain backwards compatibility with the + * original version of the API. + * @see + * cpaCyKeyGenMgfExt + ****************************************************************************/ +typedef struct _CpaCyKeyGenMgfOpDataExt { + CpaCyKeyGenMgfOpData baseOpData; + /**< "Base" operational data for MGF generation */ + CpaCySymHashAlgorithm hashAlgorithm; + /**< Specifies the hash algorithm to be used by the Mask Generation + * Function */ +} CpaCyKeyGenMgfOpDataExt; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Key Generation Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyKeyGenStats64. + * @description + * This structure contains statistics on the key and mask generation + * operations. Statistics are set to zero when the component is + * initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenStats { + Cpa32U numSslKeyGenRequests; + /**< Total number of successful SSL key generation requests. */ + Cpa32U numSslKeyGenRequestErrors; + /**< Total number of SSL key generation requests that had an error and + * could not be processed. */ + Cpa32U numSslKeyGenCompleted; + /**< Total number of SSL key generation operations that completed + * successfully. */ + Cpa32U numSslKeyGenCompletedErrors; + /**< Total number of SSL key generation operations that could not be + * completed successfully due to errors. */ + Cpa32U numTlsKeyGenRequests; + /**< Total number of successful TLS key generation requests. */ + Cpa32U numTlsKeyGenRequestErrors; + /**< Total number of TLS key generation requests that had an error and + * could not be processed. */ + Cpa32U numTlsKeyGenCompleted; + /**< Total number of TLS key generation operations that completed + * successfully. */ + Cpa32U numTlsKeyGenCompletedErrors; + /**< Total number of TLS key generation operations that could not be + * completed successfully due to errors. */ + Cpa32U numMgfKeyGenRequests; + /**< Total number of successful MGF key generation requests (including + * "extended" MGF requests). */ + Cpa32U numMgfKeyGenRequestErrors; + /**< Total number of MGF key generation requests that had an error and + * could not be processed. */ + Cpa32U numMgfKeyGenCompleted; + /**< Total number of MGF key generation operations that completed + * successfully. */ + Cpa32U numMgfKeyGenCompletedErrors; + /**< Total number of MGF key generation operations that could not be + * completed successfully due to errors. */ +} CpaCyKeyGenStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Key Generation Statistics (64-bit version). + * @description + * This structure contains the 64-bit version of the statistics + * on the key and mask generation operations. + * Statistics are set to zero when the component is + * initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyKeyGenStats64 { + Cpa64U numSslKeyGenRequests; + /**< Total number of successful SSL key generation requests. */ + Cpa64U numSslKeyGenRequestErrors; + /**< Total number of SSL key generation requests that had an error and + * could not be processed. */ + Cpa64U numSslKeyGenCompleted; + /**< Total number of SSL key generation operations that completed + * successfully. */ + Cpa64U numSslKeyGenCompletedErrors; + /**< Total number of SSL key generation operations that could not be + * completed successfully due to errors. */ + Cpa64U numTlsKeyGenRequests; + /**< Total number of successful TLS key generation requests. */ + Cpa64U numTlsKeyGenRequestErrors; + /**< Total number of TLS key generation requests that had an error and + * could not be processed. */ + Cpa64U numTlsKeyGenCompleted; + /**< Total number of TLS key generation operations that completed + * successfully. */ + Cpa64U numTlsKeyGenCompletedErrors; + /**< Total number of TLS key generation operations that could not be + * completed successfully due to errors. */ + Cpa64U numMgfKeyGenRequests; + /**< Total number of successful MGF key generation requests (including + * "extended" MGF requests). */ + Cpa64U numMgfKeyGenRequestErrors; + /**< Total number of MGF key generation requests that had an error and + * could not be processed. */ + Cpa64U numMgfKeyGenCompleted; + /**< Total number of MGF key generation operations that completed + * successfully. */ + Cpa64U numMgfKeyGenCompletedErrors; + /**< Total number of MGF key generation operations that could not be + * completed successfully due to errors. */ +} CpaCyKeyGenStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * SSL Key Generation Function. + * @description + * This function is used for SSL key generation. It implements the key + * generation function defined in section 6.2.2 of the SSL 3.0 + * specification as described in + * http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt. + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenSslOpData Structure containing all the data + * needed to perform the SSL key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @see + * CpaCyKeyGenSslOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenSsl(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenSslOpData *pKeyGenSslOpData, + CpaFlatBuffer *pGeneratedKeyBuffer); + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * TLS Key Generation Function. + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC2246 (TLS v1.0) + * and RFC4346 (TLS v1.1). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Structure containing all the data + * needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @see + * CpaCyKeyGenTlsOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenTls(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaFlatBuffer *pGeneratedKeyBuffer); + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * TLS Key Generation Function version 2. + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC5246 (TLS v1.2). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Structure containing all the data + * needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @see + * CpaCyKeyGenTlsOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenTls2(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaCySymHashAlgorithm hashAlgorithm, + CpaFlatBuffer *pGeneratedKeyBuffer); + + +/** + ***************************************************************************** + * @file cpa_cy_key.h + * @ingroup cpaCyKeyGen + * TLS Key Generation Function version 3. + * @description + * This function is used for TLS key generation. It implements the + * TLS HKDF (HMAC Key Derivation Function) as defined by + * RFC5689 (HKDF) and RFC8446 (TLS 1.3). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Structure containing all the data + * needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. The memory + * must be pinned and contiguous, suitable + * for DMA operations. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @see + * CpaCyGenFlatBufCbFunc + * CpaCyKeyGenHKDFOpData + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenTls3(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + CpaCyKeyHKDFCipherSuite cipherSuite, + CpaFlatBuffer *pGeneratedKeyBuffer); + + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Mask Generation Function. + * @description + * This function implements the mask generation function MGF1 as + * defined by PKCS#1 v2.1, and RFC3447. The input seed is taken + * as a flat buffer and the generated mask is returned to caller in a + * flat destination data buffer. + * + * @note The default hash algorithm used by the MGF is SHA-1. If a + * different hash algorithm is preferred, then see the "extended" + * version of this function, @ref cpaCyKeyGenMgfExt. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the + * callback. + * @param[in] pKeyGenMgfOpData Structure containing all the data needed + * to perform the MGF key generation + * operation. The client code allocates the + * memory for this structure. This + * component takes ownership of the memory + * until it is returned in the callback. + * @param[out] pGeneratedMaskBuffer Caller MUST allocate a sufficient buffer + * to hold the generated mask. The data + * pointer SHOULD be aligned on an 8-byte + * boundary. The length field passed in + * represents the size of the buffer in + * bytes. The value that is returned is the + * size of the generated mask in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @see + * CpaCyKeyGenMgfOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenMgf(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer); + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Extended Mask Generation Function. + * @description + * This function is used for mask generation. It differs from the "base" + * version of the function (@ref cpaCyKeyGenMgf) in that it allows + * the hash function used by the Mask Generation Function to be + * specified. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the + * callback. + * @param[in] pKeyGenMgfOpDataExt Structure containing all the data needed + * to perform the extended MGF key generation + * operation. The client code allocates the + * memory for this structure. This + * component takes ownership of the memory + * until it is returned in the callback. + * @param[out] pGeneratedMaskBuffer Caller MUST allocate a sufficient buffer + * to hold the generated mask. The data + * pointer SHOULD be aligned on an 8-byte + * boundary. The length field passed in + * represents the size of the buffer in + * bytes. The value that is returned is the + * size of the generated mask in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * This function is only used to generate a mask keys from seed + * material. + * @see + * CpaCyKeyGenMgfOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyKeyGenMgfExt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpDataExt *pKeyGenMgfOpDataExt, + CpaFlatBuffer *pGeneratedMaskBuffer); + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Queries the Key and Mask generation statistics specific to + * an instance. + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyKeyGenQueryStats64(). + * + * @description + * This function will query a specific instance for key and mask + * generation statistics. The user MUST allocate the CpaCyKeyGenStats + * structure and pass the reference to that into this function call. This + * function will write the statistic results into the passed in + * CpaCyKeyGenStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pKeyGenStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * + * @see + * CpaCyKeyGenStats + * + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyKeyGenQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCyKeyGenStats *pKeyGenStats); + +/** + ***************************************************************************** + * @ingroup cpaCyKeyGen + * Queries the Key and Mask generation statistics (64-bit version) + * specific to an instance. + * + * @description + * This function will query a specific instance for key and mask + * generation statistics. The user MUST allocate the CpaCyKeyGenStats64 + * structure and pass the reference to that into this function call. This + * function will write the statistic results into the passed in + * CpaCyKeyGenStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pKeyGenStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. + * Resubmit the request. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * + * @see + * CpaCyKeyGenStats64 + *****************************************************************************/ +CpaStatus +cpaCyKeyGenQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyKeyGenStats64 *pKeyGenStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_KEY_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_ln.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_ln.h new file mode 100644 index 00000000000..d5790bff6c6 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_ln.h @@ -0,0 +1,519 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_ln.h + * + * @defgroup cpaCyLn Cryptographic Large Number API + * + * @ingroup cpaCy + * + * @description + * These functions specify the Cryptographic API for Large Number + * Operations. + * + * @note + * Large numbers are represented on the QuickAssist API using octet + * strings, stored in structures of type @ref CpaFlatBuffer. These + * octet strings are encoded as described by PKCS#1 v2.1, section 4, + * which is consistent with ASN.1 syntax. The following text + * summarizes this. Any exceptions to this encoding are specified + * on the specific data structure or function to which the exception + * applies. + * + * An n-bit number, N, has a value in the range 2^(n-1) through 2^(n)-1. + * In other words, its most significant bit, bit n-1 (where bit-counting + * starts from zero) MUST be set to 1. We can also state that the + * bit-length n of a number N is defined by n = floor(log2(N))+1. + * + * The buffer, b, in which an n-bit number N is stored, must be "large + * enough". In other words, b.dataLenInBytes must be at least + * minLenInBytes = ceiling(n/8). + * + * The number is stored in a "big endian" format. This means that the + * least significant byte (LSB) is b[b.dataLenInBytes-1], while the + * most significant byte (MSB) is b[b.dataLenInBytes-minLenInBytes]. + * In the case where the buffer is "exactly" the right size, then the + * MSB is b[0]. Otherwise, all bytes from b[0] up to the MSB MUST be + * set to 0x00. + * + * The largest bit-length we support today is 4096 bits. In other + * words, we can deal with numbers up to a value of (2^4096)-1. + * + *****************************************************************************/ + +#ifndef CPA_CY_LN_H +#define CPA_CY_LN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Modular Exponentiation Function Operation Data. + * @description + * This structure lists the different items that are required in the + * cpaCyLnModExp function. The client MUST allocate the memory for + * this structure. When the structure is passed into the function, + * ownership of the memory passes to the function. Ownership of the memory + * returns to the client when this structure is returned in the callback. + * The operation size in bits is equal to the size of whichever of the + * following is largest: the modulus, the base or the exponent. + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyLnModExp function, and + * before it has been returned in the callback, undefined behavior will + * result. + + * The values of the base, the exponent and the modulus MUST all be less + * than 2^4096, and the modulus must not be equal to zero. + *****************************************************************************/ +typedef struct _CpaCyLnModExpOpData { + CpaFlatBuffer modulus; + /**< Flat buffer containing a pointer to the modulus. + * This number may be up to 4096 bits in length, and MUST be greater + * than zero. + */ + CpaFlatBuffer base; + /**< Flat buffer containing a pointer to the base. + * This number may be up to 4096 bits in length. + */ + CpaFlatBuffer exponent; + /**< Flat buffer containing a pointer to the exponent. + * This number may be up to 4096 bits in length. + */ +} CpaCyLnModExpOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Modular Inversion Function Operation Data. + * @description + * This structure lists the different items that are required in the + * function @ref cpaCyLnModInv. The client MUST allocate the memory for + * this structure. When the structure is passed into the function, + * ownership of the memory passes to the function. Ownership of the + * memory returns to the client when this structure is returned in the + * callback. + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyLnModInv function, and + * before it has been returned in the callback, undefined behavior will + * result. + * + * Note that the values of A and B MUST NOT both be even numbers, and + * both MUST be less than 2^4096. + *****************************************************************************/ +typedef struct _CpaCyLnModInvOpData { + CpaFlatBuffer A; + /**< Flat buffer containing a pointer to the value that will be + * inverted. + * This number may be up to 4096 bits in length, it MUST NOT be zero, + * and it MUST be co-prime with B. + */ + CpaFlatBuffer B; + /**< Flat buffer containing a pointer to the value that will be used as + * the modulus. + * This number may be up to 4096 bits in length, it MUST NOT be zero, + * and it MUST be co-prime with A. + */ +} CpaCyLnModInvOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Look Aside Cryptographic large number Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyLnStats64. + * @description + * This structure contains statistics on the Look Aside Cryptographic + * large number operations. Statistics are set to zero when the component + * is initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyLnStats { + Cpa32U numLnModExpRequests; + /**< Total number of successful large number modular exponentiation + * requests.*/ + Cpa32U numLnModExpRequestErrors; + /**< Total number of large number modular exponentiation requests that + * had an error and could not be processed. */ + Cpa32U numLnModExpCompleted; + /**< Total number of large number modular exponentiation operations + * that completed successfully. */ + Cpa32U numLnModExpCompletedErrors; + /**< Total number of large number modular exponentiation operations + * that could not be completed successfully due to errors. */ + Cpa32U numLnModInvRequests; + /**< Total number of successful large number modular inversion + * requests.*/ + Cpa32U numLnModInvRequestErrors; + /**< Total number of large number modular inversion requests that + * had an error and could not be processed. */ + Cpa32U numLnModInvCompleted; + /**< Total number of large number modular inversion operations + * that completed successfully. */ + Cpa32U numLnModInvCompletedErrors; + /**< Total number of large number modular inversion operations + * that could not be completed successfully due to errors. */ +} CpaCyLnStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Look Aside Cryptographic large number Statistics. + * @description + * This structure contains statistics on the Look Aside Cryptographic + * large number operations. Statistics are set to zero when the component + * is initialized, and are collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyLnStats64 { + Cpa64U numLnModExpRequests; + /**< Total number of successful large number modular exponentiation + * requests.*/ + Cpa64U numLnModExpRequestErrors; + /**< Total number of large number modular exponentiation requests that + * had an error and could not be processed. */ + Cpa64U numLnModExpCompleted; + /**< Total number of large number modular exponentiation operations + * that completed successfully. */ + Cpa64U numLnModExpCompletedErrors; + /**< Total number of large number modular exponentiation operations + * that could not be completed successfully due to errors. */ + Cpa64U numLnModInvRequests; + /**< Total number of successful large number modular inversion + * requests.*/ + Cpa64U numLnModInvRequestErrors; + /**< Total number of large number modular inversion requests that + * had an error and could not be processed. */ + Cpa64U numLnModInvCompleted; + /**< Total number of large number modular inversion operations + * that completed successfully. */ + Cpa64U numLnModInvCompletedErrors; + /**< Total number of large number modular inversion operations + * that could not be completed successfully due to errors. */ +} CpaCyLnStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Perform modular exponentiation operation. + * + * @description + * This function performs modular exponentiation. It computes the + * following result based on the inputs: + * + * result = (base ^ exponent) mod modulus + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pLnModExpCb Pointer to callback function to be + * invoked when the operation is complete. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the callback. + * @param[in] pLnModExpOpData Structure containing all the data needed + * to perform the LN modular exponentiation + * operation. The client code allocates + * the memory for this structure. This + * component takes ownership of the memory + * until it is returned in the callback. + * @param[out] pResult Pointer to a flat buffer containing a + * pointer to memory allocated by the client + * into which the result will be written. + * The size of the memory required MUST be + * larger than or equal to the size + * required to store the modulus. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * When pLnModExpCb is non null, an asynchronous callback of type + * CpaCyLnModExpCbFunc is generated in response to this function call. + * Any errors generated during processing are reported in the structure + * returned in the callback. + * + * @see + * CpaCyLnModExpOpData, CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyLnModExp(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModExpCb, + void *pCallbackTag, + const CpaCyLnModExpOpData *pLnModExpOpData, + CpaFlatBuffer *pResult); + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Perform modular inversion operation. + * + * @description + * This function performs modular inversion. It computes the following + * result based on the inputs: + * + * result = (1/A) mod B. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pLnModInvCb Pointer to callback function to be + * invoked when the operation is complete. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the + * callback. + * @param[in] pLnModInvOpData Structure containing all the data + * needed to perform the LN modular + * inversion operation. The client code + * allocates the memory for this structure. + * This component takes ownership of the + * memory until it is returned in the + * callback. + * @param[out] pResult Pointer to a flat buffer containing a + * pointer to memory allocated by the client + * into which the result will be written. + * The size of the memory required MUST be + * larger than or equal to the size + * required to store the modulus. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * When pLnModInvCb is non null, an asynchronous callback of type + * CpaCyLnModInvCbFunc is generated in response to this function call. + * Any errors generated during processing are reported in the structure + * returned in the callback. + * + * @see + * CpaCyLnModInvOpData, + * CpaCyGenFlatBufCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyLnModInv(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModInvCb, + void *pCallbackTag, + const CpaCyLnModInvOpData *pLnModInvOpData, + CpaFlatBuffer *pResult); + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Query statistics for large number operations + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyLnStatsQuery64(). + * + * @description + * This function will query a specific instance handle for large number + * statistics. The user MUST allocate the CpaCyLnStats structure and pass + * the reference to that structure into this function call. This function + * writes the statistic results into the passed in CpaCyLnStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pLnStats Pointer to memory into which the + * statistics will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Acceleration Services unit has been initialized. + * + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * + * @see + * CpaCyLnStats + * + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyLnStatsQuery(const CpaInstanceHandle instanceHandle, + struct _CpaCyLnStats *pLnStats); + +/** + ***************************************************************************** + * @ingroup cpaCyLn + * Query statistics (64-bit version) for large number operations + * + * @description + * This function will query a specific instance handle for the 64-bit + * version of the large number statistics. + * The user MUST allocate the CpaCyLnStats64 structure and pass + * the reference to that structure into this function call. This function + * writes the statistic results into the passed in CpaCyLnStats64 + * structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pLnStats Pointer to memory into which the + * statistics will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Acceleration Services unit has been initialized. + * + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * + * @see + * CpaCyLnStats + *****************************************************************************/ +CpaStatus +cpaCyLnStatsQuery64(const CpaInstanceHandle instanceHandle, + CpaCyLnStats64 *pLnStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_LN_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_prime.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_prime.h new file mode 100644 index 00000000000..21e2b1e9081 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_prime.h @@ -0,0 +1,450 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_prime.h + * + * @defgroup cpaCyPrime Prime Number Test API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for the prime number test operations. + * + * For prime number generation, this API SHOULD be used in conjunction + * with the Deterministic Random Bit Generation API (@ref cpaCyDrbg). + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + * + * In addition, the bit length of large numbers passed to the API + * MUST NOT exceed 576 bits for Elliptic Curve operations. + *****************************************************************************/ + +#ifndef CPA_CY_PRIME_H +#define CPA_CY_PRIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyPrime + * Prime Test Operation Data. + * @description + * This structure contains the operation data for the cpaCyPrimeTest + * function. The client MUST allocate the memory for this structure and the + * items pointed to by this structure. When the structure is passed into + * the function, ownership of the memory passes to the function. Ownership + * of the memory returns to the client when this structure is returned in + * the callback function. + * + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. primeCandidate.pData[0] = MSB. + * + * All numbers MUST be stored in big-endian order. + * + * @note + * If the client modifies or frees the memory referenced in this + * structure after it has been submitted to the cpaCyPrimeTest + * function, and before it has been returned in the callback, undefined + * behavior will result. + * + * @see + * cpaCyPrimeTest() + * + *****************************************************************************/ +typedef struct _CpaCyPrimeTestOpData { + CpaFlatBuffer primeCandidate; + /**< The prime number candidate to test */ + CpaBoolean performGcdTest; + /**< A value of CPA_TRUE means perform a GCD Primality Test */ + CpaBoolean performFermatTest; + /**< A value of CPA_TRUE means perform a Fermat Primality Test */ + Cpa32U numMillerRabinRounds; + /**< Number of Miller Rabin Primality Test rounds. Set to 0 to perform + * zero Miller Rabin tests. The maximum number of rounds supported is 50. + */ + CpaFlatBuffer millerRabinRandomInput; + /**< Flat buffer containing a pointer to an array of n random numbers + * for Miller Rabin Primality Tests. The size of the buffer MUST be + * + * n * (MAX(64,x)) + * + * where: + * + * - n is the requested number of rounds. + * - x is the minimum number of bytes required to represent the prime + * candidate, i.e. x = ceiling((ceiling(log2(p)))/8). + * + * Each random number MUST be greater than 1 and less than the prime + * candidate - 1, with leading zeroes as necessary. + */ + CpaBoolean performLucasTest; + /**< An CPA_TRUE value means perform a Lucas Primality Test */ +} CpaCyPrimeTestOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyPrime + * Prime Number Test Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyPrimeStats64. + * @description + * This structure contains statistics on the prime number test operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + * + ****************************************************************************/ +typedef struct _CpaCyPrimeStats { + Cpa32U numPrimeTestRequests; + /**< Total number of successful prime number test requests.*/ + Cpa32U numPrimeTestRequestErrors; + /**< Total number of prime number test requests that had an + * error and could not be processed. */ + Cpa32U numPrimeTestCompleted; + /**< Total number of prime number test operations that completed + * successfully. */ + Cpa32U numPrimeTestCompletedErrors; + /**< Total number of prime number test operations that could not be + * completed successfully due to errors. */ + Cpa32U numPrimeTestFailures; + /**< Total number of prime number test operations that executed + * successfully but the outcome of the test was that the number was not + * prime. */ +} CpaCyPrimeStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyPrime + * Prime Number Test Statistics (64-bit version). + * @description + * This structure contains a 64-bit version of the statistics on the + * prime number test operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + ****************************************************************************/ +typedef struct _CpaCyPrimeStats64 { + Cpa64U numPrimeTestRequests; + /**< Total number of successful prime number test requests.*/ + Cpa64U numPrimeTestRequestErrors; + /**< Total number of prime number test requests that had an + * error and could not be processed. */ + Cpa64U numPrimeTestCompleted; + /**< Total number of prime number test operations that completed + * successfully. */ + Cpa64U numPrimeTestCompletedErrors; + /**< Total number of prime number test operations that could not be + * completed successfully due to errors. */ + Cpa64U numPrimeTestFailures; + /**< Total number of prime number test operations that executed + * successfully but the outcome of the test was that the number was not + * prime. */ +} CpaCyPrimeStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyPrime + * Definition of callback function invoked for cpaCyPrimeTest + * requests. + * + * @description + * This is the prototype for the cpaCyPrimeTest callback function. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pOpData Opaque pointer to the Operation data pointer + * supplied in request. + * @param[in] testPassed A value of CPA_TRUE means the prime candidate + * is probably prime. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCyPrimeTest() + * + *****************************************************************************/ +typedef void (*CpaCyPrimeTestCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean testPassed); + +/** + ***************************************************************************** + * @ingroup cpaCyPrime + * Prime Number Test Function. + * + * @description + * This function will test probabilistically if a number is prime. Refer + * to ANSI X9.80 2005 for details. The primality result will be returned + * in the asynchronous callback. + * + * The following combination of GCD, Fermat, Miller-Rabin, and Lucas + * testing is supported: + * (up to 1x GCD) + (up to 1x Fermat) + (up to 50x Miller-Rabin rounds) + + * (up to 1x Lucas) + * For example: + * (1x GCD) + (25x Miller-Rabin) + (1x Lucas); + * (1x GCD) + (1x Fermat); + * (50x Miller-rabin); + * + * Tests are always performed in order of increasing complexity, for + * example GCD first, then Fermat, then Miller-Rabin, and finally Lucas. + * + * For all of the primality tests, the following prime number "sizes" + * (length in bits) are supported: all sizes up to and including 512 + * bits, as well as sizes 768, 1024, 1536, 2048, 3072 and 4096. + * + * Candidate prime numbers MUST match these sizes accordingly, with + * leading zeroes present where necessary. + * + * When this prime number test is used in conjunction with combined + * Miller-Rabin and Lucas tests, it may be used as a means of performing + * a self test operation on the random data generator. + * + * A response status of ok (pass == CPA_TRUE) means all requested + * primality tests passed, and the prime candidate is probably prime + * (the exact probability depends on the primality tests requested). + * A response status of not ok (pass == CPA_FALSE) means one of the + * requested primality tests failed (the prime candidate has been found + * to be composite). + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCb Callback function pointer. If this is set to + * a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag User-supplied value to help identify request. + * @param[in] pOpData Structure containing all the data needed to + * perform the operation. The client code + * allocates the memory for this structure. This + * component takes ownership of the memory until + * it is returned in the callback. + * @param[out] pTestPassed A value of CPA_TRUE means the prime candidate + * is probably prime. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pCb is non-NULL an asynchronous callback of type + * CpaCyPrimeTestCbFunc is generated in response to this function call. + * For optimal performance, data pointers SHOULD be 8-byte aligned. + * + * @see + * CpaCyPrimeTestOpData, CpaCyPrimeTestCbFunc + * + *****************************************************************************/ +CpaStatus +cpaCyPrimeTest(const CpaInstanceHandle instanceHandle, + const CpaCyPrimeTestCbFunc pCb, + void *pCallbackTag, + const CpaCyPrimeTestOpData *pOpData, + CpaBoolean *pTestPassed); + +/****************************************************************************** + * @ingroup cpaCyPrime + * Query prime number statistics specific to an instance. + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyPrimeQueryStats64(). + * + * @description + * This function will query a specific instance for prime number + * statistics. The user MUST allocate the CpaCyPrimeStats structure + * and pass the reference to that into this function call. This function + * will write the statistic results into the passed in + * CpaCyPrimeStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pPrimeStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyPrimeQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCyPrimeStats *pPrimeStats); + + +/****************************************************************************** + * @ingroup cpaCyPrime + * Query prime number statistics specific to an instance. + * + * @description + * This function will query a specific instance for the 64-bit + * version of the prime number statistics. + * The user MUST allocate the CpaCyPrimeStats64 structure + * and pass the reference to that into this function call. This function + * will write the statistic results into the passed in + * CpaCyPrimeStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pPrimeStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + *****************************************************************************/ +CpaStatus +cpaCyPrimeQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyPrimeStats64 *pPrimeStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_PRIME_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_rsa.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_rsa.h new file mode 100644 index 00000000000..a9ca9595bad --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_rsa.h @@ -0,0 +1,907 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_rsa.h + * + * @defgroup cpaCyRsa RSA API + * + * @ingroup cpaCy + * + * @description + * These functions specify the API for Public Key Encryption + * (Cryptography) RSA operations. The PKCS #1 V2.1 specification is + * supported, however the support is limited to "two-prime" mode. RSA + * multi-prime is not supported. + * + * @note + * These functions implement RSA cryptographic primitives. RSA padding + * schemes are not implemented. For padding schemes that require the mgf + * function see @ref cpaCyKeyGen. + * + * @note + * Large numbers are represented on the QuickAssist API as described + * in the Large Number API (@ref cpaCyLn). + *****************************************************************************/ + +#ifndef CPA_CY_RSA_H +#define CPA_CY_RSA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Version. + * @description + * This enumeration lists the version identifier for the PKCS #1 V2.1 + * standard. + * @note + * Multi-prime (more than two primes) is not supported. + * + *****************************************************************************/ +typedef enum _CpaCyRsaVersion +{ + CPA_CY_RSA_VERSION_TWO_PRIME = 1 + /**< The version supported is "two-prime". */ +} CpaCyRsaVersion; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Public Key Structure. + * @description + * This structure contains the two components which comprise the RSA + * public key as defined in the PKCS #1 V2.1 standard. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. modulusN.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyRsaPublicKey { + CpaFlatBuffer modulusN; + /**< The modulus (n). + * For key generation operations, the client MUST allocate the memory + * for this parameter; its value is generated. + * For encrypt operations this parameter is an input. */ + CpaFlatBuffer publicExponentE; + /**< The public exponent (e). + * For key generation operations, this field is unused. It is NOT + * generated by the interface; it is the responsibility of the client + * to set this to the same value as the corresponding parameter on + * the CpaCyRsaKeyGenOpData structure before using the key for + * encryption. + * For encrypt operations this parameter is an input. */ +} CpaCyRsaPublicKey; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Private Key Structure For Representation 1. + * @description + * This structure contains the first representation that can be used for + * describing the RSA private key, represented by the tuple of the + * modulus (n) and the private exponent (d). + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. modulusN.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyRsaPrivateKeyRep1 { + CpaFlatBuffer modulusN; + /**< The modulus (n). For key generation operations the memory MUST + * be allocated by the client and the value is generated. For other + * operations this is an input. Permitted lengths are: + * + * - 512 bits (64 bytes), + * - 1024 bits (128 bytes), + * - 1536 bits (192 bytes), + * - 2048 bits (256 bytes), + * - 3072 bits (384 bytes), or + * - 4096 bits (512 bytes). + */ + CpaFlatBuffer privateExponentD; + /**< The private exponent (d). For key generation operations the + * memory MUST be allocated by the client and the value is generated. For + * other operations this is an input. + * NOTE: It is important that the value D is big enough. It is STRONGLY + * recommended that this value is at least half the length of the modulus + * N to protect against the Wiener attack. */ +} CpaCyRsaPrivateKeyRep1; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Private Key Structure For Representation 2. + * @description + * This structure contains the second representation that can be used for + * describing the RSA private key. The quintuple of p, q, dP, dQ, and qInv + * (explained below and in the spec) are required for the second + * representation. The optional sequence of triplets are not included. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. prime1P.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyRsaPrivateKeyRep2 { + CpaFlatBuffer prime1P; + /**< The first large prime (p). + * For key generation operations, this field is unused. */ + CpaFlatBuffer prime2Q; + /**< The second large prime (q). + * For key generation operations, this field is unused. */ + CpaFlatBuffer exponent1Dp; + /**< The first factor CRT exponent (dP). d mod (p-1). */ + CpaFlatBuffer exponent2Dq; + /**< The second factor CRT exponent (dQ). d mod (q-1). */ + CpaFlatBuffer coefficientQInv; + /**< The (first) Chinese Remainder Theorem (CRT) coefficient (qInv). + * (inverse of q) mod p. */ +} CpaCyRsaPrivateKeyRep2; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA private key representation type. + * @description + * This enumeration lists which PKCS V2.1 representation of the private + * key is being used. + * + *****************************************************************************/ +typedef enum _CpaCyRsaPrivateKeyRepType +{ + CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1= 1, + /**< The first representation of the RSA private key. */ + CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2 + /**< The second representation of the RSA private key. */ +} CpaCyRsaPrivateKeyRepType; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Private Key Structure. + * @description + * This structure contains the two representations that can be used for + * describing the RSA private key. The privateKeyRepType will be used to + * identify which representation is to be used. Typically, using the + * second representation results in faster decryption operations. + * + *****************************************************************************/ +typedef struct _CpaCyRsaPrivateKey { + CpaCyRsaVersion version; + /**< Indicates the version of the PKCS #1 specification that is + * supported. + * Note that this applies to both representations. */ + CpaCyRsaPrivateKeyRepType privateKeyRepType; + /**< This value is used to identify which of the private key + * representation types in this structure is relevant. + * When performing key generation operations for Type 2 representations, + * memory must also be allocated for the type 1 representations, and values + * for both will be returned. */ + CpaCyRsaPrivateKeyRep1 privateKeyRep1; + /**< This is the first representation of the RSA private key as + * defined in the PKCS #1 V2.1 specification. For key generation operations + * the memory for this structure is allocated by the client and the + * specific values are generated. For other operations this is an input + * parameter. */ + CpaCyRsaPrivateKeyRep2 privateKeyRep2; + /**< This is the second representation of the RSA private key as + * defined in the PKCS #1 V2.1 specification. For key generation operations + * the memory for this structure is allocated by the client and the + * specific values are generated. For other operations this is an input + * parameter. */ +} CpaCyRsaPrivateKey; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Key Generation Data. + * @description + * This structure lists the different items that are required in the + * cpaCyRsaGenKey function. The client MUST allocate the memory for this + * structure. When the structure is passed into the function, ownership of + * the memory passes to the function. Ownership of the memory returns to + * the client when this structure is returned in the + * CpaCyRsaKeyGenCbFunc callback function. + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyRsaGenKey function, and + * before it has been returned in the callback, undefined behavior will + * result. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. prime1P.pData[0] = MSB. + * + * The following limitations on the permutations of the supported bit + * lengths of p, q and n (written as {p, q, n}) apply: + * + * - {256, 256, 512} or + * - {512, 512, 1024} or + * - {768, 768, 1536} or + * - {1024, 1024, 2048} or + * - {1536, 1536, 3072} or + * - {2048, 2048, 4096}. + * + *****************************************************************************/ +typedef struct _CpaCyRsaKeyGenOpData { + CpaFlatBuffer prime1P; + /**< A large random prime number (p). This MUST be created by the + * client. Permitted bit lengths are: 256, 512, 768, 1024, 1536 or 2048. + * Limitations apply - refer to the description above for details. */ + CpaFlatBuffer prime2Q; + /**< A large random prime number (q). This MUST be created by the + * client. Permitted bit lengths are: 256, 512, 768, 1024, 1536 or 2048. + * Limitations apply - refer to the description above for details. If the + * private key representation type is 2, then this pointer will be assigned + * to the relevant structure member of the representation 2 private key. */ + Cpa32U modulusLenInBytes; + /**< The bit length of the modulus (n). This is the modulus length for + * both the private and public keys. The length of the modulus N parameter + * for the private key representation 1 structure and the public key + * structures will be assigned to this value. References to the strength of + * RSA actually refer to this bit length. Recommended minimum is 1024 bits. + * Permitted lengths are: + * - 512 bits (64 bytes), + * - 1024 bits (128 bytes), + * - 1536 bits (192 bytes), + * - 2048 bits (256 bytes), + * - 3072 bits (384 bytes), or + * - 4096 bits (512 bytes). + * Limitations apply - refer to description above for details. */ + CpaCyRsaVersion version; + /**< Indicates the version of the PKCS #1 specification that is + * supported. + * Note that this applies to both representations. */ + CpaCyRsaPrivateKeyRepType privateKeyRepType; + /**< This value is used to identify which of the private key + * representation types is required to be generated. */ + CpaFlatBuffer publicExponentE; + /**< The public exponent (e). */ +} CpaCyRsaKeyGenOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Encryption Primitive Operation Data + * @description + * This structure lists the different items that are required in the + * cpaCyRsaEncrypt function. As the RSA encryption primitive and + * verification primitive operations are mathematically identical this + * structure may also be used to perform an RSA verification primitive + * operation. + * When performing an RSA encryption primitive operation, the input data + * is the message and the output data is the cipher text. + * When performing an RSA verification primitive operation, the input data + * is the signature and the output data is the message. + * The client MUST allocate the memory for this structure. When the + * structure is passed into the function, ownership of the memory passes + * to the function. Ownership of the memory returns to the client when + * this structure is returned in the CpaCyRsaEncryptCbFunc + * callback function. + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyRsaEncrypt function, and + * before it has been returned in the callback, undefined behavior will + * result. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. inputData.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyRsaEncryptOpData { + CpaCyRsaPublicKey *pPublicKey; + /**< Pointer to the public key. */ + CpaFlatBuffer inputData; + /**< The input data that the RSA encryption primitive operation is + * performed on. The data pointed to is an integer that MUST be in big- + * endian order. The value MUST be between 0 and the modulus n - 1. */ +} CpaCyRsaEncryptOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Decryption Primitive Operation Data + * @description + * This structure lists the different items that are required in the + * cpaCyRsaDecrypt function. As the RSA decryption primitive and + * signature primitive operations are mathematically identical this + * structure may also be used to perform an RSA signature primitive + * operation. + * When performing an RSA decryption primitive operation, the input data + * is the cipher text and the output data is the message text. + * When performing an RSA signature primitive operation, the input data + * is the message and the output data is the signature. + * The client MUST allocate the memory for this structure. When the + * structure is passed into the function, ownership of the memory passes + * to he function. Ownership of the memory returns to the client when + * this structure is returned in the CpaCyRsaDecryptCbFunc + * callback function. + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCyRsaDecrypt function, and + * before it has been returned in the callback, undefined behavior will + * result. + * All values in this structure are required to be in Most Significant Byte + * first order, e.g. inputData.pData[0] = MSB. + * + *****************************************************************************/ +typedef struct _CpaCyRsaDecryptOpData { + CpaCyRsaPrivateKey *pRecipientPrivateKey; + /**< Pointer to the recipient's RSA private key. */ + CpaFlatBuffer inputData; + /**< The input data that the RSA decryption primitive operation is + * performed on. The data pointed to is an integer that MUST be in big- + * endian order. The value MUST be between 0 and the modulus n - 1. */ +} CpaCyRsaDecryptOpData; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Statistics. + * @deprecated + * As of v1.3 of the Crypto API, this structure has been deprecated, + * replaced by @ref CpaCyRsaStats64. + * @description + * This structure contains statistics on the RSA operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + ****************************************************************************/ +typedef struct _CpaCyRsaStats { + Cpa32U numRsaKeyGenRequests; + /**< Total number of successful RSA key generation requests. */ + Cpa32U numRsaKeyGenRequestErrors; + /**< Total number of RSA key generation requests that had an error and + * could not be processed. */ + Cpa32U numRsaKeyGenCompleted; + /**< Total number of RSA key generation operations that completed + * successfully. */ + Cpa32U numRsaKeyGenCompletedErrors; + /**< Total number of RSA key generation operations that could not be + * completed successfully due to errors. */ + Cpa32U numRsaEncryptRequests; + /**< Total number of successful RSA encrypt operation requests. */ + Cpa32U numRsaEncryptRequestErrors; + /**< Total number of RSA encrypt requests that had an error and could + * not be processed. */ + Cpa32U numRsaEncryptCompleted; + /**< Total number of RSA encrypt operations that completed + * successfully. */ + Cpa32U numRsaEncryptCompletedErrors; + /**< Total number of RSA encrypt operations that could not be + * completed successfully due to errors. */ + Cpa32U numRsaDecryptRequests; + /**< Total number of successful RSA decrypt operation requests. */ + Cpa32U numRsaDecryptRequestErrors; + /**< Total number of RSA decrypt requests that had an error and could + * not be processed. */ + Cpa32U numRsaDecryptCompleted; + /**< Total number of RSA decrypt operations that completed + * successfully. */ + Cpa32U numRsaDecryptCompletedErrors; + /**< Total number of RSA decrypt operations that could not be + * completed successfully due to errors. */ +} CpaCyRsaStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * RSA Statistics (64-bit version). + * @description + * This structure contains 64-bit version of the statistics on the RSA + * operations. + * Statistics are set to zero when the component is initialized, and are + * collected per instance. + ****************************************************************************/ +typedef struct _CpaCyRsaStats64 { + Cpa64U numRsaKeyGenRequests; + /**< Total number of successful RSA key generation requests. */ + Cpa64U numRsaKeyGenRequestErrors; + /**< Total number of RSA key generation requests that had an error and + * could not be processed. */ + Cpa64U numRsaKeyGenCompleted; + /**< Total number of RSA key generation operations that completed + * successfully. */ + Cpa64U numRsaKeyGenCompletedErrors; + /**< Total number of RSA key generation operations that could not be + * completed successfully due to errors. */ + Cpa64U numRsaEncryptRequests; + /**< Total number of successful RSA encrypt operation requests. */ + Cpa64U numRsaEncryptRequestErrors; + /**< Total number of RSA encrypt requests that had an error and could + * not be processed. */ + Cpa64U numRsaEncryptCompleted; + /**< Total number of RSA encrypt operations that completed + * successfully. */ + Cpa64U numRsaEncryptCompletedErrors; + /**< Total number of RSA encrypt operations that could not be + * completed successfully due to errors. */ + Cpa64U numRsaDecryptRequests; + /**< Total number of successful RSA decrypt operation requests. */ + Cpa64U numRsaDecryptRequestErrors; + /**< Total number of RSA decrypt requests that had an error and could + * not be processed. */ + Cpa64U numRsaDecryptCompleted; + /**< Total number of RSA decrypt operations that completed + * successfully. */ + Cpa64U numRsaDecryptCompletedErrors; + /**< Total number of RSA decrypt operations that could not be + * completed successfully due to errors. */ +} CpaCyRsaStats64; + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Definition of the RSA key generation callback function. + * + * @description + * This is the prototype for the RSA key generation callback function. The + * callback function pointer is passed in as a parameter to the + * cpaCyRsaGenKey function. It will be invoked once the request has + * completed. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function calls. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] pKeyGenOpData Structure with output params for callback. + * @param[in] pPrivateKey Structure which contains pointers to the memory + * into which the generated private key will be + * written. + * @param[in] pPublicKey Structure which contains pointers to the memory + * into which the generated public key will be + * written. The pointer to the public exponent (e) + * that is returned in this structure is equal to + * the input public exponent. + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * CpaCyRsaPrivateKey, + * CpaCyRsaPublicKey, + * cpaCyRsaGenKey() + * + *****************************************************************************/ +typedef void (*CpaCyRsaKeyGenCbFunc)(void *pCallbackTag, + CpaStatus status, + void *pKeyGenOpData, + CpaCyRsaPrivateKey *pPrivateKey, + CpaCyRsaPublicKey *pPublicKey); + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Generate RSA keys. + * + * @description + * This function will generate private and public keys for RSA as specified + * in the PKCS #1 V2.1 standard. Both representation types of the private + * key may be generated. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pRsaKeyGenCb Pointer to the callback function to be invoked + * when the operation is complete. If this is + * set to a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. Will + * be returned unchanged in the callback. + * @param[in] pKeyGenOpData Structure containing all the data needed to + * perform the RSA key generation operation. The + * client code allocates the memory for this + * structure. This component takes ownership of + * the memory until it is returned in the + * callback. + * @param[out] pPrivateKey Structure which contains pointers to the memory + * into which the generated private key will be + * written. The client MUST allocate memory + * for this structure, and for the pointers + * within it, recursively; on return, these will + * be populated. + * @param[out] pPublicKey Structure which contains pointers to the memory + * into which the generated public key will be + * written. The memory for this structure and + * for the modulusN parameter MUST be allocated + * by the client, and will be populated on return + * from the call. The field publicExponentE + * is not modified or touched in any way; it is + * the responsibility of the client to set this + * to the same value as the corresponding + * parameter on the CpaCyRsaKeyGenOpData + * structure before using the key for encryption. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pRsaKeyGenCb is non-NULL, an asynchronous callback of type is + * generated in response to this function call. + * Any errors generated during processing are reported as part of the + * callback status code. For optimal performance, data pointers SHOULD be + * 8-byte aligned. + * @see + * CpaCyRsaKeyGenOpData, + * CpaCyRsaKeyGenCbFunc, + * cpaCyRsaEncrypt(), + * cpaCyRsaDecrypt() + * + *****************************************************************************/ +CpaStatus +cpaCyRsaGenKey(const CpaInstanceHandle instanceHandle, + const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, + void *pCallbackTag, + const CpaCyRsaKeyGenOpData *pKeyGenOpData, + CpaCyRsaPrivateKey *pPrivateKey, + CpaCyRsaPublicKey *pPublicKey); + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Perform the RSA encrypt (or verify) primitive operation on the input + * data. + * + * @description + * This function will perform an RSA encryption primitive operation on the + * input data using the specified RSA public key. As the RSA encryption + * primitive and verification primitive operations are mathematically + * identical this function may also be used to perform an RSA verification + * primitive operation. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pRsaEncryptCb Pointer to callback function to be invoked + * when the operation is complete. If this is + * set to a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. Will + * be returned unchanged in the callback. + * @param[in] pEncryptOpData Structure containing all the data needed to + * perform the RSA encryption operation. The + * client code allocates the memory for this + * structure. This component takes ownership of + * the memory until it is returned in the + * callback. + * @param[out] pOutputData Pointer to structure into which the result of + * the RSA encryption primitive is written. The + * client MUST allocate this memory. The data + * pointed to is an integer in big-endian order. + * The value will be between 0 and the modulus + * n - 1. + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pRsaEncryptCb is non-NULL an asynchronous callback of type is + * generated in response to this function call. + * Any errors generated during processing are reported as part of the + * callback status code. For optimal performance, data pointers SHOULD be + * 8-byte aligned. + * @see + * CpaCyGenFlatBufCbFunc + * CpaCyRsaEncryptOpData + * cpaCyRsaGenKey() + * cpaCyRsaDecrypt() + * + *****************************************************************************/ +CpaStatus +cpaCyRsaEncrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaEncryptCb, + void *pCallbackTag, + const CpaCyRsaEncryptOpData *pEncryptOpData, + CpaFlatBuffer *pOutputData); + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Perform the RSA decrypt (or sign) primitive operation on the input + * data. + * + * @description + * This function will perform an RSA decryption primitive operation on the + * input data using the specified RSA private key. As the RSA decryption + * primitive and signing primitive operations are mathematically identical + * this function may also be used to perform an RSA signing primitive + * operation. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pRsaDecryptCb Pointer to callback function to be invoked + * when the operation is complete. If this is + * set to a NULL value the function will operate + * synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * Will be returned unchanged in the callback. + * @param[in] pDecryptOpData Structure containing all the data needed to + * perform the RSA decrypt operation. The + * client code allocates the memory for this + * structure. This component takes ownership + * of the memory until it is returned in the + * callback. + * @param[out] pOutputData Pointer to structure into which the result of + * the RSA decryption primitive is written. The + * client MUST allocate this memory. The data + * pointed to is an integer in big-endian order. + * The value will be between 0 and the modulus + * n - 1. + * On invocation the callback function will + * contain this parameter in the pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * When pRsaDecryptCb is non-NULL an asynchronous callback is generated in + * response to this function call. + * Any errors generated during processing are reported as part of the + * callback status code. For optimal performance, data pointers SHOULD be + * 8-byte aligned. + * @see + * CpaCyRsaDecryptOpData, + * CpaCyGenFlatBufCbFunc, + * cpaCyRsaGenKey(), + * cpaCyRsaEncrypt() + * + *****************************************************************************/ +CpaStatus +cpaCyRsaDecrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaDecryptCb, + void *pCallbackTag, + const CpaCyRsaDecryptOpData *pDecryptOpData, + CpaFlatBuffer * pOutputData); + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Query statistics for a specific RSA instance. + * + * @deprecated + * As of v1.3 of the Crypto API, this function has been deprecated, + * replaced by @ref cpaCyRsaQueryStats64(). + * + * @description + * This function will query a specific instance for RSA statistics. The + * user MUST allocate the CpaCyRsaStats structure and pass the + * reference to that into this function call. This function will write the + * statistic results into the passed in CpaCyRsaStats structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pRsaStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyRsaStats + * + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCyRsaQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCyRsaStats *pRsaStats); + +/** + ***************************************************************************** + * @ingroup cpaCyRsa + * Query statistics (64-bit version) for a specific RSA instance. + * + * @description + * This function will query a specific instance for RSA statistics. The + * user MUST allocate the CpaCyRsaStats64 structure and pass the + * reference to that into this function call. This function will write the + * statistic results into the passed in CpaCyRsaStats64 structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pRsaStats Pointer to memory into which the statistics + * will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner and no asynchronous + * callback will be generated. + * @see + * CpaCyRsaStats64 + *****************************************************************************/ +CpaStatus +cpaCyRsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyRsaStats64 *pRsaStats); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_RSA_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_sym.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_sym.h new file mode 100644 index 00000000000..416f4aa4bea --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_sym.h @@ -0,0 +1,1844 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_sym.h + * + * @defgroup cpaCySym Symmetric Cipher and Hash Cryptographic API + * + * @ingroup cpaCy + * + * @description + * These functions specify the Cryptographic API for symmetric cipher, + * hash, and combined cipher and hash operations. + * + *****************************************************************************/ + +#ifndef CPA_CY_SYM_H +#define CPA_CY_SYM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Cryptographic component symmetric session context handle. + * @description + * Handle to a cryptographic session context. The memory for this handle + * is allocated by the client. The size of the memory that the client needs + * to allocate is determined by a call to the @ref + * cpaCySymSessionCtxGetSize or @ref cpaCySymSessionCtxGetDynamicSize + * functions. The session context memory is initialized with a call to + * the @ref cpaCySymInitSession function. + * This memory MUST not be freed until a call to @ref + * cpaCySymRemoveSession has completed successfully. + * + *****************************************************************************/ +typedef void * CpaCySymSessionCtx; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Packet type for the cpaCySymPerformOp function + * + * @description + * Enumeration which is used to indicate to the symmetric cryptographic + * perform function on which type of packet the operation is required to + * be invoked. Multi-part cipher and hash operations are useful when + * processing needs to be performed on a message which is available to + * the client in multiple parts (for example due to network fragmentation + * of the packet). + * + * @note + * There are some restrictions regarding the operations on which + * partial packet processing is supported. For details, see the + * function @ref cpaCySymPerformOp. + * + * @see + * cpaCySymPerformOp() + * + *****************************************************************************/ +typedef enum _CpaCySymPacketType +{ + CPA_CY_SYM_PACKET_TYPE_FULL = 1, + /**< Perform an operation on a full packet*/ + CPA_CY_SYM_PACKET_TYPE_PARTIAL, + /**< Perform a partial operation and maintain the state of the partial + * operation within the session. This is used for either the first or + * subsequent packets within a partial packet flow. */ + CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL + /**< Complete the last part of a multi-part operation */ +} CpaCySymPacketType; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Types of operations supported by the cpaCySymPerformOp function. + * @description + * This enumeration lists different types of operations supported by the + * cpaCySymPerformOp function. The operation type is defined during + * session registration and cannot be changed for a session once it has + * been setup. + * @see + * cpaCySymPerformOp + *****************************************************************************/ +typedef enum _CpaCySymOp +{ + CPA_CY_SYM_OP_NONE=0, + /**< No operation */ + CPA_CY_SYM_OP_CIPHER, + /**< Cipher only operation on the data */ + CPA_CY_SYM_OP_HASH, + /**< Hash only operation on the data */ + CPA_CY_SYM_OP_ALGORITHM_CHAINING + /**< Chain any cipher with any hash operation. The order depends on + * the value in the CpaCySymAlgChainOrder enum. + * + * This value is also used for authenticated ciphers (GCM and CCM), in + * which case the cipherAlgorithm should take one of the values @ref + * CPA_CY_SYM_CIPHER_AES_CCM or @ref CPA_CY_SYM_CIPHER_AES_GCM, while the + * hashAlgorithm should take the corresponding value @ref + * CPA_CY_SYM_HASH_AES_CCM or @ref CPA_CY_SYM_HASH_AES_GCM. + */ +} CpaCySymOp; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Cipher algorithms. + * @description + * This enumeration lists supported cipher algorithms and modes. + * + *****************************************************************************/ +typedef enum _CpaCySymCipherAlgorithm +{ + CPA_CY_SYM_CIPHER_NULL = 1, + /**< NULL cipher algorithm. No mode applies to the NULL algorithm. */ + CPA_CY_SYM_CIPHER_ARC4, + /**< (A)RC4 cipher algorithm */ + CPA_CY_SYM_CIPHER_AES_ECB, + /**< AES algorithm in ECB mode */ + CPA_CY_SYM_CIPHER_AES_CBC, + /**< AES algorithm in CBC mode */ + CPA_CY_SYM_CIPHER_AES_CTR, + /**< AES algorithm in Counter mode */ + CPA_CY_SYM_CIPHER_AES_CCM, + /**< AES algorithm in CCM mode. This authenticated cipher is only supported + * when the hash mode is also set to CPA_CY_SYM_HASH_MODE_AUTH. When this + * cipher algorithm is used the CPA_CY_SYM_HASH_AES_CCM element of the + * CpaCySymHashAlgorithm enum MUST be used to set up the related + * CpaCySymHashSetupData structure in the session context. */ + CPA_CY_SYM_CIPHER_AES_GCM, + /**< AES algorithm in GCM mode. This authenticated cipher is only supported + * when the hash mode is also set to CPA_CY_SYM_HASH_MODE_AUTH. When this + * cipher algorithm is used the CPA_CY_SYM_HASH_AES_GCM element of the + * CpaCySymHashAlgorithm enum MUST be used to set up the related + * CpaCySymHashSetupData structure in the session context. */ + CPA_CY_SYM_CIPHER_DES_ECB, + /**< DES algorithm in ECB mode */ + CPA_CY_SYM_CIPHER_DES_CBC, + /**< DES algorithm in CBC mode */ + CPA_CY_SYM_CIPHER_3DES_ECB, + /**< Triple DES algorithm in ECB mode */ + CPA_CY_SYM_CIPHER_3DES_CBC, + /**< Triple DES algorithm in CBC mode */ + CPA_CY_SYM_CIPHER_3DES_CTR, + /**< Triple DES algorithm in CTR mode */ + CPA_CY_SYM_CIPHER_KASUMI_F8, + /**< Kasumi algorithm in F8 mode */ + CPA_CY_SYM_CIPHER_SNOW3G_UEA2, + /**< SNOW3G algorithm in UEA2 mode */ + CPA_CY_SYM_CIPHER_AES_F8, + /**< AES algorithm in F8 mode */ + CPA_CY_SYM_CIPHER_AES_XTS, + /**< AES algorithm in XTS mode */ + CPA_CY_SYM_CIPHER_ZUC_EEA3, + /**< ZUC algorithm in EEA3 mode */ + CPA_CY_SYM_CIPHER_CHACHA, + /**< ChaCha20 Cipher Algorithm. This cipher is only supported for + * algorithm chaining. When selected, the hash algorithm must be set to + * CPA_CY_SYM_HASH_POLY and the hash mode must be set to + * CPA_CY_SYM_HASH_MODE_AUTH. */ + CPA_CY_SYM_CIPHER_SM4_ECB, + /**< SM4 algorithm in ECB mode This cipher supports 128 bit keys only and + * does not support partial processing. */ + CPA_CY_SYM_CIPHER_SM4_CBC, + /**< SM4 algorithm in CBC mode This cipher supports 128 bit keys only and + * does not support partial processing. */ + CPA_CY_SYM_CIPHER_SM4_CTR + /**< SM4 algorithm in CTR mode This cipher supports 128 bit keys only and + * does not support partial processing. */ +} CpaCySymCipherAlgorithm; + +/** + * @ingroup cpaCySym + * Size of bitmap needed for cipher "capabilities" type. + * + * @description + * Defines the number of bits in the bitmap to represent supported + * ciphers in the type @ref CpaCySymCapabilitiesInfo. Should be set to + * at least one greater than the largest value in the enumerated type + * @ref CpaCySymHashAlgorithm, so that the value of the enum constant + * can also be used as the bit position in the bitmap. + * + * A larger value was chosen to allow for extensibility without the need + * to change the size of the bitmap (to ease backwards compatibility in + * future versions of the API). + */ +#define CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE (32) + + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Symmetric Cipher Direction + * @description + * This enum indicates the cipher direction (encryption or decryption). + * + *****************************************************************************/ +typedef enum _CpaCySymCipherDirection +{ + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT = 1, + /**< Encrypt Data */ + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT + /**< Decrypt Data */ +} CpaCySymCipherDirection; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Symmetric Cipher Setup Data. + * @description + * This structure contains data relating to Cipher (Encryption and + * Decryption) to set up a session. + * + *****************************************************************************/ +typedef struct _CpaCySymCipherSetupData { + CpaCySymCipherAlgorithm cipherAlgorithm; + /**< Cipher algorithm and mode */ + Cpa32U cipherKeyLenInBytes; + /**< Cipher key length in bytes. For AES it can be 128 bits (16 bytes), + * 192 bits (24 bytes) or 256 bits (32 bytes). + * For the CCM mode of operation, the only supported key length is 128 bits + * (16 bytes). + * For the CPA_CY_SYM_CIPHER_AES_F8 mode of operation, cipherKeyLenInBytes + * should be set to the combined length of the encryption key and the + * keymask. Since the keymask and the encryption key are the same size, + * cipherKeyLenInBytes should be set to 2 x the AES encryption key length. + * For the AES-XTS mode of operation: + * - Two keys must be provided and cipherKeyLenInBytes refers to total + * length of the two keys. + * - Each key can be either 128 bits (16 bytes) or 256 bits (32 bytes). + * - Both keys must have the same size. */ + Cpa8U *pCipherKey; + /**< Cipher key + * For the CPA_CY_SYM_CIPHER_AES_F8 mode of operation, pCipherKey will + * point to a concatenation of the AES encryption key followed by a + * keymask. As per RFC3711, the keymask should be padded with trailing + * bytes to match the length of the encryption key used. + * For AES-XTS mode of operation, two keys must be provided and pCipherKey + * must point to the two keys concatenated together (Key1 || Key2). + * cipherKeyLenInBytes will contain the total size of both keys. */ + CpaCySymCipherDirection cipherDirection; + /**< This parameter determines if the cipher operation is an encrypt or + * a decrypt operation. + * For the RC4 algorithm and the F8/CTR modes, only encrypt operations + * are valid. */ +} CpaCySymCipherSetupData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Symmetric Hash mode + * @description + * This enum indicates the Hash Mode. + * + *****************************************************************************/ +typedef enum _CpaCySymHashMode +{ + CPA_CY_SYM_HASH_MODE_PLAIN = 1, + /**< Plain hash. Can be specified for MD5 and the SHA family of + * hash algorithms. */ + CPA_CY_SYM_HASH_MODE_AUTH, + /**< Authenticated hash. This mode may be used in conjunction with the + * MD5 and SHA family of algorithms to specify HMAC. It MUST also be + * specified with all of the remaining algorithms, all of which are in + * fact authentication algorithms. + */ + CPA_CY_SYM_HASH_MODE_NESTED + /**< Nested hash. Can be specified for MD5 and the SHA family of + * hash algorithms. */ +} CpaCySymHashMode; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Hash algorithms. + * @description + * This enumeration lists supported hash algorithms. + * + *****************************************************************************/ +typedef enum _CpaCySymHashAlgorithm +{ + CPA_CY_SYM_HASH_NONE = 0, + /**< No hash algorithm. */ + CPA_CY_SYM_HASH_MD5, + /**< MD5 algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_SHA1, + /**< 128 bit SHA algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_SHA224, + /**< 224 bit SHA algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_SHA256, + /**< 256 bit SHA algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_SHA384, + /**< 384 bit SHA algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_SHA512, + /**< 512 bit SHA algorithm. Supported in all 3 hash modes */ + CPA_CY_SYM_HASH_AES_XCBC, + /**< AES XCBC algorithm. This is only supported in the hash mode + * CPA_CY_SYM_HASH_MODE_AUTH. */ + CPA_CY_SYM_HASH_AES_CCM, + /**< AES algorithm in CCM mode. This authenticated cipher requires that the + * hash mode is set to CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm + * is used, the CPA_CY_SYM_CIPHER_AES_CCM element of the + * CpaCySymCipherAlgorithm enum MUST be used to set up the related + * CpaCySymCipherSetupData structure in the session context. */ + CPA_CY_SYM_HASH_AES_GCM, + /**< AES algorithm in GCM mode. This authenticated cipher requires that the + * hash mode is set to CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm + * is used, the CPA_CY_SYM_CIPHER_AES_GCM element of the + * CpaCySymCipherAlgorithm enum MUST be used to set up the related + * CpaCySymCipherSetupData structure in the session context. */ + CPA_CY_SYM_HASH_KASUMI_F9, + /**< Kasumi algorithm in F9 mode. This is only supported in the hash + * mode CPA_CY_SYM_HASH_MODE_AUTH. */ + CPA_CY_SYM_HASH_SNOW3G_UIA2, + /**< SNOW3G algorithm in UIA2 mode. This is only supported in the hash + * mode CPA_CY_SYM_HASH_MODE_AUTH. */ + CPA_CY_SYM_HASH_AES_CMAC, + /**< AES CMAC algorithm. This is only supported in the hash mode + * CPA_CY_SYM_HASH_MODE_AUTH. */ + CPA_CY_SYM_HASH_AES_GMAC, + /**< AES GMAC algorithm. This is only supported in the hash mode + * CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm + * is used, the CPA_CY_SYM_CIPHER_AES_GCM element of the + * CpaCySymCipherAlgorithm enum MUST be used to set up the related + * CpaCySymCipherSetupData structure in the session context. */ + CPA_CY_SYM_HASH_AES_CBC_MAC, + /**< AES-CBC-MAC algorithm. This is only supported in the hash mode + * CPA_CY_SYM_HASH_MODE_AUTH. Only 128-bit keys are supported. */ + CPA_CY_SYM_HASH_ZUC_EIA3, + /**< ZUC algorithm in EIA3 mode */ + CPA_CY_SYM_HASH_SHA3_224, + /**< 224 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and + * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash + * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. + */ + CPA_CY_SYM_HASH_SHA3_256, + /**< 256 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and + * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash + * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. + * Partial requests are not supported, that is, only requests + * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ + CPA_CY_SYM_HASH_SHA3_384, + /**< 384 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and + * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash + * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. + * Partial requests are not supported, that is, only requests + * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ + CPA_CY_SYM_HASH_SHA3_512, + /**< 512 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and + * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash + * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. + * Partial requests are not supported, that is, only requests + * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ + CPA_CY_SYM_HASH_SHAKE_128, + /**< 128 bit SHAKE algorithm. This is only supported in the hash + * mode CPA_CY_SYM_HASH_MODE_PLAIN. Partial requests are not + * supported, that is, only requests of CPA_CY_SYM_PACKET_TYPE_FULL + * are supported. */ + CPA_CY_SYM_HASH_SHAKE_256, + /**< 256 bit SHAKE algorithm. This is only supported in the hash + * mode CPA_CY_SYM_HASH_MODE_PLAIN. Partial requests are not + * supported, that is, only requests of CPA_CY_SYM_PACKET_TYPE_FULL + * are supported. */ + CPA_CY_SYM_HASH_POLY, + /**< Poly1305 hash algorithm. This is only supported in the hash mode + * CPA_CY_SYM_HASH_MODE_AUTH. This hash algorithm is only supported + * as part of an algorithm chain with AES_CY_SYM_CIPHER_CHACHA to + * implement the ChaCha20-Poly1305 AEAD algorithm. */ + CPA_CY_SYM_HASH_SM3 + /**< SM3 hash algorithm. Supported in all 3 hash modes. */ + } CpaCySymHashAlgorithm; + +/** + * @ingroup cpaCySym + * Size of bitmap needed for hash "capabilities" type. + * + * @description + * Defines the number of bits in the bitmap to represent supported + * hashes in the type @ref CpaCySymCapabilitiesInfo. Should be set to + * at least one greater than the largest value in the enumerated type + * @ref CpaCySymHashAlgorithm, so that the value of the enum constant + * can also be used as the bit position in the bitmap. + * + * A larger value was chosen to allow for extensibility without the need + * to change the size of the bitmap (to ease backwards compatibility in + * future versions of the API). + */ +#define CPA_CY_SYM_HASH_CAP_BITMAP_SIZE (32) + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Hash Mode Nested Setup Data. + * @description + * This structure contains data relating to a hash session in + * CPA_CY_SYM_HASH_MODE_NESTED mode. + * + *****************************************************************************/ +typedef struct _CpaCySymHashNestedModeSetupData { + Cpa8U *pInnerPrefixData; + /**< A pointer to a buffer holding the Inner Prefix data. For optimal + * performance the prefix data SHOULD be 8-byte aligned. This data is + * prepended to the data being hashed before the inner hash operation is + * performed. */ + Cpa32U innerPrefixLenInBytes; + /**< The inner prefix length in bytes. The maximum size the prefix data + * can be is 255 bytes. */ + CpaCySymHashAlgorithm outerHashAlgorithm; + /**< The hash algorithm used for the outer hash. Note: The inner hash + * algorithm is provided in the hash context. */ + Cpa8U *pOuterPrefixData; + /**< A pointer to a buffer holding the Outer Prefix data. For optimal + * performance the prefix data SHOULD be 8-byte aligned. This data is + * prepended to the output from the inner hash operation before the outer + * hash operation is performed.*/ + Cpa32U outerPrefixLenInBytes; + /**< The outer prefix length in bytes. The maximum size the prefix data + * can be is 255 bytes. */ +} CpaCySymHashNestedModeSetupData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Hash Auth Mode Setup Data. + * @description + * This structure contains data relating to a hash session in + * CPA_CY_SYM_HASH_MODE_AUTH mode. + * + *****************************************************************************/ +typedef struct _CpaCySymHashAuthModeSetupData { + Cpa8U *authKey; + /**< Authentication key pointer. + * For the GCM (@ref CPA_CY_SYM_HASH_AES_GCM) and CCM (@ref + * CPA_CY_SYM_HASH_AES_CCM) modes of operation, this field is ignored; + * the authentication key is the same as the cipher key (see + * the field pCipherKey in struct @ref CpaCySymCipherSetupData). + */ + Cpa32U authKeyLenInBytes; + /**< Length of the authentication key in bytes. The key length MUST be + * less than or equal to the block size of the algorithm. It is the client's + * responsibility to ensure that the key length is compliant with the + * standard being used (for example RFC 2104, FIPS 198a). + * + * For the GCM (@ref CPA_CY_SYM_HASH_AES_GCM) and CCM (@ref + * CPA_CY_SYM_HASH_AES_CCM) modes of operation, this field is ignored; + * the authentication key is the same as the cipher key, and so is its + * length (see the field cipherKeyLenInBytes in struct @ref + * CpaCySymCipherSetupData). + */ + Cpa32U aadLenInBytes; + /**< The length of the additional authenticated data (AAD) in bytes. + * The maximum permitted value is 240 bytes, unless otherwise + * specified below. + * + * This field must be specified when the hash algorithm is one of the + * following: + + * - For SNOW3G (@ref CPA_CY_SYM_HASH_SNOW3G_UIA2), this is the + * length of the IV (which should be 16). + * - For GCM (@ref CPA_CY_SYM_HASH_AES_GCM). In this case, this is the + * length of the Additional Authenticated Data (called A, in NIST + * SP800-38D). + * - For CCM (@ref CPA_CY_SYM_HASH_AES_CCM). In this case, this is the + * length of the associated data (called A, in NIST SP800-38C). + * Note that this does NOT include the length of any padding, or the + * 18 bytes reserved at the start of the above field to store the + * block B0 and the encoded length. The maximum permitted value in + * this case is 222 bytes. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of operation + * this field is not used and should be set to 0. Instead the length + * of the AAD data is specified in the messageLenToHashInBytes field of + * the CpaCySymOpData structure. + */ +} CpaCySymHashAuthModeSetupData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Hash Setup Data. + * @description + * This structure contains data relating to a hash session. The fields + * hashAlgorithm, hashMode and digestResultLenInBytes are common to all + * three hash modes and MUST be set for each mode. + * + *****************************************************************************/ +typedef struct _CpaCySymHashSetupData { + CpaCySymHashAlgorithm hashAlgorithm; + /**< Hash algorithm. For mode CPA_CY_SYM_MODE_HASH_NESTED, this is the + * inner hash algorithm. */ + CpaCySymHashMode hashMode; + /**< Mode of the hash operation. Valid options include plain, auth or + * nested hash mode. */ + Cpa32U digestResultLenInBytes; + /**< Length of the digest to be returned. If the verify option is set, + * this specifies the length of the digest to be compared for the + * session. + * + * For CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this is the octet length + * of the MAC, which can be one of 4, 6, 8, 10, 12, 14 or 16. + * + * For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), this is the length in bytes + * of the authentication tag. + * + * If the value is less than the maximum length allowed by the hash, + * the result shall be truncated. If the value is greater than the + * maximum length allowed by the hash, an error (@ref + * CPA_STATUS_INVALID_PARAM) is returned from the function @ref + * cpaCySymInitSession. + * + * In the case of nested hash, it is the outer hash which determines + * the maximum length allowed. */ + CpaCySymHashAuthModeSetupData authModeSetupData; + /**< Authentication Mode Setup Data. + * Only valid for mode CPA_CY_SYM_MODE_HASH_AUTH */ + CpaCySymHashNestedModeSetupData nestedModeSetupData; + /**< Nested Hash Mode Setup Data + * Only valid for mode CPA_CY_SYM_MODE_HASH_NESTED */ +} CpaCySymHashSetupData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Algorithm Chaining Operation Ordering + * @description + * This enum defines the ordering of operations for algorithm chaining. + * + ****************************************************************************/ +typedef enum _CpaCySymAlgChainOrder +{ + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER = 1, + /**< Perform the hash operation followed by the cipher operation. If it is + * required that the result of the hash (i.e. the digest) is going to be + * included in the data to be ciphered, then: + * + *
        + *
      • The digest MUST be placed in the destination buffer at the + * location corresponding to the end of the data region to be hashed + * (hashStartSrcOffsetInBytes + messageLenToHashInBytes), + * i.e. there must be no gaps between the start of the digest and the + * end of the data region to be hashed.
      • + *
      • The messageLenToCipherInBytes member of the CpaCySymOpData + * structure must be equal to the overall length of the plain text, + * the digest length and any (optional) trailing data that is to be + * included.
      • + *
      • The messageLenToCipherInBytes must be a multiple to the block + * size if a block cipher is being used.
      • + *
      + * + * The following is an example of the layout of the buffer before the + * operation, after the hash, and after the cipher: + +@verbatim + ++-------------------------+---------------+ +| Plaintext | Tail | ++-------------------------+---------------+ +<-messageLenToHashInBytes-> + ++-------------------------+--------+------+ +| Plaintext | Digest | Tail | ++-------------------------+--------+------+ +<--------messageLenToCipherInBytes--------> + ++-----------------------------------------+ +| Cipher Text | ++-----------------------------------------+ + +@endverbatim + */ + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH + /**< Perform the cipher operation followed by the hash operation. + * The hash operation will be performed on the ciphertext resulting from + * the cipher operation. + * + * The following is an example of the layout of the buffer before the + * operation, after the cipher, and after the hash: + +@verbatim + ++--------+---------------------------+---------------+ +| Head | Plaintext | Tail | ++--------+---------------------------+---------------+ + <-messageLenToCipherInBytes-> + ++--------+---------------------------+---------------+ +| Head | Ciphertext | Tail | ++--------+---------------------------+---------------+ +<------messageLenToHashInBytes-------> + ++--------+---------------------------+--------+------+ +| Head | Ciphertext | Digest | Tail | ++--------+---------------------------+--------+------+ + +@endverbatim + * + */ +} CpaCySymAlgChainOrder; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Session Setup Data. + * @description + * This structure contains data relating to setting up a session. The + * client needs to complete the information in this structure in order to + * setup a session. + * + ****************************************************************************/ +typedef struct _CpaCySymSessionSetupData { + CpaCyPriority sessionPriority; + /**< Priority of this session */ + CpaCySymOp symOperation; + /**< Operation to perfom */ + CpaCySymCipherSetupData cipherSetupData; + /**< Cipher Setup Data for the session. This member is ignored for the + * CPA_CY_SYM_OP_HASH operation. */ + CpaCySymHashSetupData hashSetupData; + /**< Hash Setup Data for a session. This member is ignored for the + * CPA_CY_SYM_OP_CIPHER operation. */ + CpaCySymAlgChainOrder algChainOrder; + /**< If this operation data structure relates to an algorithm chaining + * session then this parameter determines the order in which the chained + * operations are performed. If this structure does not relate to an + * algorithm chaining session then this parameter will be ignored. + * + * @note In the case of authenticated ciphers (GCM and CCM), which are + * also presented as "algorithm chaining", this value is also ignored. + * The chaining order is defined by the authenticated cipher, in those + * cases. */ + CpaBoolean digestIsAppended; + /**< Flag indicating whether the digest is appended immediately following + * the region over which the digest is computed. This is true for both + * IPsec packets and SSL/TLS records. + * + * If this flag is set, then the value of the pDigestResult field of + * the structure @ref CpaCySymOpData is ignored. + * + * @note The value of this field is ignored for the authenticated cipher + * AES_CCM as the digest must be appended in this case. + * + * @note Setting digestIsAppended for hash only operations when + * verifyDigest is also set is not supported. For hash only operations + * when verifyDigest is set, digestIsAppended should be set to CPA_FALSE. + */ + CpaBoolean verifyDigest; + /**< This flag is relevant only for operations which generate a message + * digest. If set to true, the computed digest will not be written back + * to the buffer location specified by other parameters, but instead will + * be verified (i.e. compared to the value passed in at that location). + * The number of bytes to be written or compared is indicated by the + * digest output length for the session. + * @note This option is only valid for full packets and for final + * partial packets when using partials without algorithm chaining. + * @note The value of this field is ignored for the authenticated ciphers + * (AES_CCM and AES_GCM). Digest verification is always done for these + * (when the direction is decrypt) and unless the DP API is used, + * the message buffer will be zeroed if verification fails. When using the + * DP API, it is the API clients responsibility to clear the message + * buffer when digest verification fails. + */ + CpaBoolean partialsNotRequired; + /**< This flag indicates if partial packet processing is required for this + * session. If set to true, partial packet processing will not be enabled + * for this session and any calls to cpaCySymPerformOp() with the + * packetType parameter set to a value other than + * CPA_CY_SYM_PACKET_TYPE_FULL will fail. + */ +} CpaCySymSessionSetupData ; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Session Update Data. + * @description + * This structure contains data relating to resetting a session. + ****************************************************************************/ +typedef struct _CpaCySymSessionUpdateData { + Cpa32U flags; + /**< Flags indicating which fields to update. + * All bits should be set to 0 except those fields to be updated. + */ +#define CPA_CY_SYM_SESUPD_CIPHER_KEY 1 << 0 +#define CPA_CY_SYM_SESUPD_CIPHER_DIR 1 << 1 +#define CPA_CY_SYM_SESUPD_AUTH_KEY 1 << 2 + Cpa8U *pCipherKey; + /**< Cipher key. + * The same restrictions apply as described in the corresponding field + * of the data structure @ref CpaCySymCipherSetupData. + */ + CpaCySymCipherDirection cipherDirection; + /**< This parameter determines if the cipher operation is an encrypt or + * a decrypt operation. + * The same restrictions apply as described in the corresponding field + * of the data structure @ref CpaCySymCipherSetupData. + */ + Cpa8U *authKey; + /**< Authentication key pointer. + * The same restrictions apply as described in the corresponding field + * of the data structure @ref CpaCySymHashAuthModeSetupData. + */ +} CpaCySymSessionUpdateData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Cryptographic Component Operation Data. + * @description + * This structure contains data relating to performing cryptographic + * processing on a data buffer. This request is used with + * cpaCySymPerformOp() call for performing cipher, hash, auth cipher + * or a combined hash and cipher operation. + * + * @see + * CpaCySymPacketType + * + * @note + * If the client modifies or frees the memory referenced in this structure + * after it has been submitted to the cpaCySymPerformOp function, and + * before it has been returned in the callback, undefined behavior will + * result. + ****************************************************************************/ +typedef struct _CpaCySymOpData { + CpaCySymSessionCtx sessionCtx; + /**< Handle for the initialized session context */ + CpaCySymPacketType packetType; + /**< Selects the packet type */ + Cpa8U *pIv; + /**< Initialization Vector or Counter. + * + * - For block ciphers in CBC or F8 mode, or for Kasumi in F8 mode, or for + * SNOW3G in UEA2 mode, this is the Initialization Vector (IV) + * value. + * - For block ciphers in CTR mode, this is the counter. + * - For GCM mode, this is either the IV (if the length is 96 bits) or J0 + * (for other sizes), where J0 is as defined by NIST SP800-38D. + * Regardless of the IV length, a full 16 bytes needs to be allocated. + * - For CCM mode, the first byte is reserved, and the nonce should be + * written starting at &pIv[1] (to allow space for the implementation + * to write in the flags in the first byte). Note that a full 16 bytes + * should be allocated, even though the ivLenInBytes field will have + * a value less than this. + * The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. + * - For AES-XTS, this is the 128bit tweak, i, from IEEE Std 1619-2007. + * + * For optimum performance, the data pointed to SHOULD be 8-byte + * aligned. + * + * The IV/Counter will be updated after every partial cryptographic + * operation. + */ + Cpa32U ivLenInBytes; + /**< Length of valid IV data pointed to by the pIv parameter. + * + * - For block ciphers in CBC or F8 mode, or for Kasumi in F8 mode, or for + * SNOW3G in UEA2 mode, this is the length of the IV (which + * must be the same as the block length of the cipher). + * - For block ciphers in CTR mode, this is the length of the counter + * (which must be the same as the block length of the cipher). + * - For GCM mode, this is either 12 (for 96-bit IVs) or 16, in which + * case pIv points to J0. + * - For CCM mode, this is the length of the nonce, which can be in the + * range 7 to 13 inclusive. + */ + Cpa32U cryptoStartSrcOffsetInBytes; + /**< Starting point for cipher processing, specified as number of bytes + * from start of data in the source buffer. The result of the cipher + * operation will be written back into the output buffer starting + * at this location. + */ + Cpa32U messageLenToCipherInBytes; + /**< The message length, in bytes, of the source buffer on which the + * cryptographic operation will be computed. This must be a multiple of + * the block size if a block cipher is being used. This is also the same + * as the result length. + * + * @note In the case of CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this value + * should not include the length of the padding or the length of the + * MAC; the driver will compute the actual number of bytes over which + * the encryption will occur, which will include these values. + * + * @note There are limitations on this length for partial + * operations. Refer to the cpaCySymPerformOp function description for + * details. + * + * @note On some implementations, this length may be limited to a 16-bit + * value (65535 bytes). + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC), this field + * should be set to 0. + */ + Cpa32U hashStartSrcOffsetInBytes; + /**< Starting point for hash processing, specified as number of bytes + * from start of packet in source buffer. + * + * @note For CCM and GCM modes of operation, this field is ignored. + * The field @ref pAdditionalAuthData field should be set instead. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field specifies the start of the AAD data in + * the source buffer. + */ + Cpa32U messageLenToHashInBytes; + /**< The message length, in bytes, of the source buffer that the hash + * will be computed on. + * + * @note There are limitations on this length for partial operations. + * Refer to the @ref cpaCySymPerformOp function description for details. + * + * @note For CCM and GCM modes of operation, this field is ignored. + * The field @ref pAdditionalAuthData field should be set instead. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field specifies the length of the AAD data in the + * source buffer. The maximum length supported for AAD data for AES-GMAC + * is 16383 bytes. + * + * @note On some implementations, this length may be limited to a 16-bit + * value (65535 bytes). + */ + Cpa8U *pDigestResult; + /**< If the digestIsAppended member of the @ref CpaCySymSessionSetupData + * structure is NOT set then this is a pointer to the location where the + * digest result should be inserted (in the case of digest generation) + * or where the purported digest exists (in the case of digest verification). + * + * At session registration time, the client specified the digest result + * length with the digestResultLenInBytes member of the @ref + * CpaCySymHashSetupData structure. The client must allocate at least + * digestResultLenInBytes of physically contiguous memory at this location. + * + * For partial packet processing without algorithm chaining, this pointer + * will be ignored for all but the final partial operation. + * + * For digest generation, the digest result will overwrite any data + * at this location. + * + * @note For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), for "digest result" + * read "authentication tag T". + * + * If the digestIsAppended member of the @ref CpaCySymSessionSetupData + * structure is set then this value is ignored and the digest result + * is understood to be in the destination buffer for digest generation, + * and in the source buffer for digest verification. The location of the + * digest result in this case is immediately following the region over + * which the digest is computed. + * + */ + Cpa8U *pAdditionalAuthData; + /**< Pointer to Additional Authenticated Data (AAD) needed for + * authenticated cipher mechanisms (CCM and GCM), and to the IV for + * SNOW3G authentication (@ref CPA_CY_SYM_HASH_SNOW3G_UIA2). + * For other authentication mechanisms this pointer is ignored. + * + * The length of the data pointed to by this field is set up for + * the session in the @ref CpaCySymHashAuthModeSetupData structure + * as part of the @ref cpaCySymInitSession function call. This length + * must not exceed 240 bytes. + * + * Specifically for CCM (@ref CPA_CY_SYM_HASH_AES_CCM), the caller + * should setup this field as follows: + * + * - the nonce should be written starting at an offset of one byte + * into the array, leaving room for the implementation to write in + * the flags to the first byte. For example, + *
      + * memcpy(&pOpData->pAdditionalAuthData[1], pNonce, nonceLen); + *
      + * The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. + * + * - the additional authentication data itself should be written + * starting at an offset of 18 bytes into the array, leaving room for + * the length encoding in the first two bytes of the second block. + * For example, + *
      + * memcpy(&pOpData->pAdditionalAuthData[18], pAad, aadLen); + *
      + * The macro @ref CPA_CY_SYM_CCM_SET_AAD may be used here. + * + * - the array should be big enough to hold the above fields, plus + * any padding to round this up to the nearest multiple of the + * block size (16 bytes). Padding will be added by the + * implementation. + * + * Finally, for GCM (@ref CPA_CY_SYM_HASH_AES_GCM), the caller + * should setup this field as follows: + * + * - the AAD is written in starting at byte 0 + * - the array must be big enough to hold the AAD, plus any padding + * to round this up to the nearest multiple of the block size (16 + * bytes). Padding will be added by the implementation. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field is not used and should be set to 0. Instead + * the AAD data should be placed in the source buffer. + */ +} CpaCySymOpData; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Setup the nonce for CCM. + * @description + * This macro sets the nonce in the appropriate locations of the + * @ref CpaCySymOpData struct for the authenticated encryption + * algorithm @ref CPA_CY_SYM_HASH_AES_CCM. + ****************************************************************************/ +#define CPA_CY_SYM_CCM_SET_NONCE(pOpData, pNonce, nonceLen) do { \ + memcpy(&pOpData->pIv[1], pNonce, nonceLen); \ + memcpy(&pOpData->pAdditionalAuthData[1], pNonce, nonceLen); \ + } while (0) + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Setup the additional authentication data for CCM. + * @description + * This macro sets the additional authentication data in the + * appropriate location of the@ref CpaCySymOpData struct for the + * authenticated encryptionalgorithm @ref CPA_CY_SYM_HASH_AES_CCM. + ****************************************************************************/ +#define CPA_CY_SYM_CCM_SET_AAD(pOpData, pAad, aadLen) do { \ + memcpy(&pOpData->pAdditionalAuthData[18], pAad, aadLen); \ + } while (0) + + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Cryptographic Component Statistics. + * @deprecated + * As of v1.3 of the cryptographic API, this structure has been + * deprecated, replaced by @ref CpaCySymStats64. + * @description + * This structure contains statistics on the Symmetric Cryptographic + * operations. Statistics are set to zero when the component is + * initialized. + ****************************************************************************/ +typedef struct _CpaCySymStats { + Cpa32U numSessionsInitialized; + /**< Number of session initialized */ + Cpa32U numSessionsRemoved; + /**< Number of sessions removed */ + Cpa32U numSessionErrors; + /**< Number of session initialized and removed errors. */ + Cpa32U numSymOpRequests; + /**< Number of successful symmetric operation requests. */ + Cpa32U numSymOpRequestErrors; + /**< Number of operation requests that had an error and could + * not be processed. */ + Cpa32U numSymOpCompleted; + /**< Number of operations that completed successfully. */ + Cpa32U numSymOpCompletedErrors; + /**< Number of operations that could not be completed + * successfully due to errors. */ + Cpa32U numSymOpVerifyFailures; + /**< Number of operations that completed successfully, but the + * result of the digest verification test was that it failed. + * Note that this does not indicate an error condition. */ +} CpaCySymStats CPA_DEPRECATED; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Cryptographic Component Statistics (64-bit version). + * @description + * This structure contains a 64-bit version of the statistics on + * the Symmetric Cryptographic operations. + * Statistics are set to zero when the component is initialized. + ****************************************************************************/ +typedef struct _CpaCySymStats64 { + Cpa64U numSessionsInitialized; + /**< Number of session initialized */ + Cpa64U numSessionsRemoved; + /**< Number of sessions removed */ + Cpa64U numSessionErrors; + /**< Number of session initialized and removed errors. */ + Cpa64U numSymOpRequests; + /**< Number of successful symmetric operation requests. */ + Cpa64U numSymOpRequestErrors; + /**< Number of operation requests that had an error and could + * not be processed. */ + Cpa64U numSymOpCompleted; + /**< Number of operations that completed successfully. */ + Cpa64U numSymOpCompletedErrors; + /**< Number of operations that could not be completed + * successfully due to errors. */ + Cpa64U numSymOpVerifyFailures; + /**< Number of operations that completed successfully, but the + * result of the digest verification test was that it failed. + * Note that this does not indicate an error condition. */ +} CpaCySymStats64; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Definition of callback function + * + * @description + * This is the callback function prototype. The callback function is + * registered by the application using the cpaCySymInitSession() + * function call. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function call. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] operationType Identifies the operation type that was + * requested in the cpaCySymPerformOp function. + * @param[in] pOpData Pointer to structure with input parameters. + * @param[in] pDstBuffer Caller MUST allocate a sufficiently sized + * destination buffer to hold the data output. For + * out-of-place processing the data outside the + * cryptographic regions in the source buffer are + * copied into the destination buffer. To perform + * "in-place" processing set the pDstBuffer + * parameter in cpaCySymPerformOp function to point + * at the same location as pSrcBuffer. For optimum + * performance, the data pointed to SHOULD be + * 8-byte aligned. + * @param[in] verifyResult This parameter is valid when the verifyDigest + * option is set in the CpaCySymSessionSetupData + * structure. A value of CPA_TRUE indicates that + * the compare succeeded. A value of CPA_FALSE + * indicates that the compare failed for an + * unspecified reason. + * + * @retval + * None + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * cpaCySymInitSession(), + * cpaCySymRemoveSession() + * + *****************************************************************************/ +typedef void (*CpaCySymCbFunc)(void *pCallbackTag, + CpaStatus status, + const CpaCySymOp operationType, + void *pOpData, + CpaBufferList *pDstBuffer, + CpaBoolean verifyResult); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Gets the size required to store a session context. + * + * @description + * This function is used by the client to determine the size of the memory + * it must allocate in order to store the session context. This MUST be + * called before the client allocates the memory for the session context + * and before the client calls the @ref cpaCySymInitSession function. + * + * For a given implementation of this API, it is safe to assume that + * cpaCySymSessionCtxGetSize() will always return the same size and that + * the size will not be different for different setup data parameters. + * However, it should be noted that the size may change: + * (1) between different implementations of the API (e.g. between software + * and hardware implementations or between different hardware + * implementations) + * (2) between different releases of the same API implementation. + * + * The size returned by this function is the smallest size needed to + * support all possible combinations of setup data parameters. Some + * setup data parameter combinations may fit within a smaller session + * context size. The alternate cpaCySymSessionCtxGetDynamicSize() + * function will return the smallest size needed to fit the + * provided setup data parameters. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pSessionSetupData Pointer to session setup data which + * contains parameters which are static + * for a given cryptographic session such + * as operation type, mechanisms, and keys + * for cipher and/or hash operations. + * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required + * to hold the Session Context. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * CpaCySymSessionSetupData + * cpaCySymInitSession() + * cpaCySymSessionCtxGetDynamicSize() + * cpaCySymPerformOp() + * + *****************************************************************************/ +CpaStatus +cpaCySymSessionCtxGetSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Gets the minimum size required to store a session context. + * + * @description + * This function is used by the client to determine the smallest size of + * the memory it must allocate in order to store the session context. + * This MUST be called before the client allocates the memory for the + * session context and before the client calls the @ref cpaCySymInitSession + * function. + * + * This function is an alternate to cpaCySymSessionGetSize(). + * cpaCySymSessionCtxGetSize() will return a fixed size which is the + * minimum memory size needed to support all possible setup data parameter + * combinations. cpaCySymSessionCtxGetDynamicSize() will return the + * minimum memory size needed to support the specific session setup + * data parmeters provided. This size may be different for different setup + * data parameters. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pSessionSetupData Pointer to session setup data which + * contains parameters which are static + * for a given cryptographic session such + * as operation type, mechanisms, and keys + * for cipher and/or hash operations. + * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required + * to hold the Session Context. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * CpaCySymSessionSetupData + * cpaCySymInitSession() + * cpaCySymSessionCtxGetSize() + * cpaCySymPerformOp() + * + *****************************************************************************/ +CpaStatus +cpaCySymSessionCtxGetDynamicSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Initialize a session for symmetric cryptographic API. + * + * @description + * This function is used by the client to initialize an asynchronous + * completion callback function for the symmetric cryptographic + * operations. Clients MAY register multiple callback functions using + * this function. + * The callback function is identified by the combination of userContext, + * pSymCb and session context (sessionCtx). The session context is the + * handle to the session and needs to be passed when processing calls. + * Callbacks on completion of operations within a session are guaranteed + * to be in the same order they were submitted in. + * + * @context + * This is a synchronous function and it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pSymCb Pointer to callback function to be + * registered. Set to NULL if the + * cpaCySymPerformOp function is required to + * work in a synchronous manner. + * @param[in] pSessionSetupData Pointer to session setup data which contains + * parameters which are static for a given + * cryptographic session such as operation + * type, mechanisms, and keys for cipher and/or + * hash operations. + * @param[out] sessionCtx Pointer to the memory allocated by the + * client to store the session context. This + * will be initialized with this function. This + * value needs to be passed to subsequent + * processing calls. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * CpaCySymSessionCtx, + * CpaCySymCbFunc, + * CpaCySymSessionSetupData, + * cpaCySymRemoveSession(), + * cpaCySymPerformOp() + * + *****************************************************************************/ +CpaStatus +cpaCySymInitSession(const CpaInstanceHandle instanceHandle, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymSessionCtx sessionCtx); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Remove (delete) a symmetric cryptographic session. + * + * @description + * This function will remove a previously initialized session context + * and the installed callback handler function. Removal will fail if + * outstanding calls still exist for the initialized session handle. + * The client needs to retry the remove function at a later time. + * The memory for the session context MUST not be freed until this call + * has completed successfully. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in,out] pSessionCtx Session context to be removed. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * CpaCySymSessionCtx, + * cpaCySymInitSession() + * + *****************************************************************************/ +CpaStatus +cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle, + CpaCySymSessionCtx pSessionCtx); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Update a session. + * + * @description + * This function is used to update certain parameters of a session, as + * specified by the CpaCySymSessionUpdateData data structure. + * + * It can be used on sessions created with either the so-called + * Traditional API (@ref cpaCySymInitSession) or the Data Plane API + * (@ref cpaCySymDpInitSession). + * + * In order for this function to operate correctly, two criteria must + * be met: + * + * - In the case of sessions created with the Traditional API, the + * session must be stateless, i.e. the field partialsNotRequired of + * the CpaCySymSessionSetupData data structure must be FALSE. + * (Sessions created using the Data Plane API are always stateless.) + * + * - There must be no outstanding requests in flight for the session. + * The application can call the function @ref cpaCySymSessionInUse + * to test for this. + * + * Note that in the case of multi-threaded applications (which are + * supported using the Traditional API only), this function may fail + * even if a previous invocation of the function @ref + * cpaCySymSessionInUse indicated that there were no outstanding + * requests. + * + * @param[in] sessionCtx Identifies the session to be reset. + * @param[in] pSessionUpdateData Pointer to session data which contains + * the parameters to be updated. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + *****************************************************************************/ +CpaStatus +cpaCySymUpdateSession(CpaCySymSessionCtx sessionCtx, + const CpaCySymSessionUpdateData *pSessionUpdateData); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Indicates whether there are outstanding requests on a given + * session. + * + * @description + * This function is used to test whether there are outstanding + * requests in flight for a specified session. This may be used + * before resetting session parameters using the function @ref + * cpaCySymResetSession. See some additional notes on + * multi-threaded applications described on that function. + * + * @param[in] sessionCtx Identifies the session to be reset. + * @param[out] pSessionInUse Returns CPA_TRUE if there are + * outstanding requests on the session, + * or CPA_FALSE otherwise. +*****************************************************************************/ +CpaStatus +cpaCySymSessionInUse(CpaCySymSessionCtx sessionCtx, + CpaBoolean* pSessionInUse); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Perform a symmetric cryptographic operation on an existing session. + * + * @description + * Performs a cipher, hash or combined (cipher and hash) operation on + * the source data buffer using supported symmetric key algorithms and + * modes. + * + * This function maintains cryptographic state between calls for + * partial cryptographic operations. If a partial cryptographic + * operation is being performed, then on a per-session basis, the next + * part of the multi-part message can be submitted prior to previous + * parts being completed, the only limitation being that all parts + * must be performed in sequential order. + * + * If for any reason a client wishes to terminate the partial packet + * processing on the session (for example if a packet fragment was lost) + * then the client MUST remove the session. + * + * When using partial packet processing with algorithm chaining, only + * the cipher state is maintained between calls. The hash state is + * not be maintained between calls. Instead the hash digest will be + * generated/verified for each call. If both the cipher state and + * hash state need to be maintained between calls, algorithm chaining + * cannot be used. + + * The following restrictions apply to the length: + * + * - When performing block based operations on a partial packet + * (excluding the final partial packet), the data that is to be + * operated on MUST be a multiple of the block size of the algorithm + * being used. This restriction only applies to the cipher state + * when using partial packets with algorithm chaining. + * + * - The final block must not be of length zero (0) if the operation + * being performed is the authentication algorithm @ref + * CPA_CY_SYM_HASH_AES_XCBC. This is because this algorithm requires + * that the final block be XORed with another value internally. + * If the length is zero, then the return code @ref + * CPA_STATUS_INVALID_PARAM will be returned. + * + * - The length of the final block must be greater than or equal to + * 16 bytes when using the @ref CPA_CY_SYM_CIPHER_AES_XTS cipher + * algorithm. + * + * Partial packet processing is supported only when the following + * conditions are true: + * + * - The cipher, hash or authentication operation is "in place" (that is, + * pDstBuffer == pSrcBuffer) + * + * - The cipher or hash algorithm is NOT one of Kasumi or SNOW3G + * + * - The cipher mode is NOT F8 mode. + * + * - The hash algorithm is NOT SHAKE + * + * - The cipher algorithm is not SM4 + * + * - The cipher algorithm is not CPA_CY_SYM_CIPHER_CHACHA and the hash + * algorithm is not CPA_CY_SYM_HASH_POLY. + * + * - The instance/implementation supports partial packets as one of + * its capabilities (see @ref CpaCySymCapabilitiesInfo). + * + * The term "in-place" means that the result of the cryptographic + * operation is written into the source buffer. The term "out-of-place" + * means that the result of the cryptographic operation is written into + * the destination buffer. To perform "in-place" processing, set the + * pDstBuffer parameter to point at the same location as the pSrcBuffer + * parameter. + * + * @context + * When called as an asynchronous function it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * When called as a synchronous function it may sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes when configured to operate in synchronous mode. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pCallbackTag Opaque data that will be returned to the client + * in the callback. + * @param[in] pOpData Pointer to a structure containing request + * parameters. The client code allocates the memory + * for this structure. This component takes + * ownership of the memory until it is returned in + * the callback. + * @param[in] pSrcBuffer The source buffer. The caller MUST allocate + * the source buffer and populate it + * with data. For optimum performance, the data + * pointed to SHOULD be 8-byte aligned. For + * block ciphers, the data passed in MUST be + * a multiple of the relevant block size. + * i.e. padding WILL NOT be applied to the data. + * For optimum performance, the buffer should + * only contain the data region that the + * cryptographic operation(s) must be performed on. + * Any additional data in the source buffer may be + * copied to the destination buffer and this copy + * may degrade performance. + * @param[out] pDstBuffer The destination buffer. The caller MUST + * allocate a sufficiently sized destination + * buffer to hold the data output (including + * the authentication tag in the case of CCM). + * Furthermore, the destination buffer must be the + * same size as the source buffer (i.e. the sum of + * lengths of the buffers in the buffer list must + * be the same). This effectively means that the + * source buffer must in fact be big enough to hold + * the output data, too. This is because, + * for out-of-place processing, the data outside the + * regions in the source buffer on which + * cryptographic operations are performed are copied + * into the destination buffer. To perform + * "in-place" processing set the pDstBuffer + * parameter in cpaCySymPerformOp function to point + * at the same location as pSrcBuffer. For optimum + * performance, the data pointed to SHOULD be + * 8-byte aligned. + * @param[out] pVerifyResult In synchronous mode, this parameter is returned + * when the verifyDigest option is set in the + * CpaCySymSessionSetupData structure. A value of + * CPA_TRUE indicates that the compare succeeded. A + * value of CPA_FALSE indicates that the compare + * failed for an unspecified reason. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resource. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized via cpaCyStartInstance function. + * A Cryptographic session has been previously setup using the + * @ref cpaCySymInitSession function call. + * @post + * None + * + * @note + * When in asynchronous mode, a callback of type CpaCySymCbFunc is + * generated in response to this function call. Any errors generated during + * processing are reported as part of the callback status code. + * + * @see + * CpaCySymOpData, + * cpaCySymInitSession(), + * cpaCySymRemoveSession() + *****************************************************************************/ +CpaStatus +cpaCySymPerformOp(const CpaInstanceHandle instanceHandle, + void *pCallbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Query symmetric cryptographic statistics for a specific instance. + * + * @deprecated + * As of v1.3 of the cryptographic API, this function has been + * deprecated, replaced by @ref cpaCySymQueryStats64(). + * + * @description + * This function will query a specific instance for statistics. The + * user MUST allocate the CpaCySymStats structure and pass the + * reference to that into this function call. This function will write + * the statistic results into the passed in CpaCySymStats + * structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pSymStats Pointer to memory into which the + * statistics will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner, i.e. no asynchronous + * callback will be generated. + * @see + * CpaCySymStats + *****************************************************************************/ +CpaStatus CPA_DEPRECATED +cpaCySymQueryStats(const CpaInstanceHandle instanceHandle, + struct _CpaCySymStats *pSymStats); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Query symmetric cryptographic statistics (64-bit version) for a + * specific instance. + * + * @description + * This function will query a specific instance for statistics. The + * user MUST allocate the CpaCySymStats64 structure and pass the + * reference to that into this function call. This function will write + * the statistic results into the passed in CpaCySymStats64 + * structure. + * + * Note: statistics returned by this function do not interrupt current data + * processing and as such can be slightly out of sync with operations that + * are in progress during the statistics retrieval process. + * + * @context + * This is a synchronous function and it can sleep. It MUST NOT be + * executed in a context that DOES NOT permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[out] pSymStats Pointer to memory into which the + * statistics will be written. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * This function operates in a synchronous manner, i.e. no asynchronous + * callback will be generated. + * @see + * CpaCySymStats64 + *****************************************************************************/ +CpaStatus +cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCySymStats64 *pSymStats); + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Symmetric Capabilities Info + * + * @description + * This structure contains the capabilities that vary across + * implementations of the symmetric sub-API of the cryptographic API. + * This structure is used in conjunction with @ref + * cpaCySymQueryCapabilities() to determine the capabilities supported + * by a particular API implementation. + * + * For example, to see if an implementation supports cipher + * @ref CPA_CY_SYM_CIPHER_AES_CBC, use the code + * + * @code + +if (CPA_BITMAP_BIT_TEST(capInfo.ciphers, CPA_CY_SYM_CIPHER_AES_CBC)) +{ + // algo is supported +} +else +{ + // algo is not supported +} + * @endcode + * + * The client MUST allocate memory for this structure and any members + * that require memory. When the structure is passed into the function + * ownership of the memory passes to the function. Ownership of the + * memory returns to the client when the function returns. + *****************************************************************************/ +typedef struct _CpaCySymCapabilitiesInfo +{ + CPA_BITMAP(ciphers, CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE); + /**< Bitmap representing which cipher algorithms (and modes) are + * supported by the instance. + * Bits can be tested using the macro @ref CPA_BITMAP_BIT_TEST. + * The bit positions are those specified in the enumerated type + * @ref CpaCySymCipherAlgorithm. */ + CPA_BITMAP(hashes, CPA_CY_SYM_HASH_CAP_BITMAP_SIZE); + /**< Bitmap representing which hash/authentication algorithms are + * supported by the instance. + * Bits can be tested using the macro @ref CPA_BITMAP_BIT_TEST. + * The bit positions are those specified in the enumerated type + * @ref CpaCySymHashAlgorithm. */ + CpaBoolean partialPacketSupported; + /**< CPA_TRUE if instance supports partial packets. + * See @ref CpaCySymPacketType. */ +} CpaCySymCapabilitiesInfo; + +/** + ***************************************************************************** + * @ingroup cpaCySym + * Returns capabilities of the symmetric API group of a Cryptographic + * API instance. + * + * @description + * This function is used to determine which specific capabilities are + * supported within the symmetric sub-group of the Cryptographic API. + * + * @context + * The function shall not be called in an interrupt context. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * This function is synchronous and blocking. + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Handle to an instance of this API. + * @param[out] pCapInfo Pointer to capabilities info structure. + * All fields in the structure + * are populated by the API instance. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The instance has been initialized via the @ref cpaCyStartInstance + * function. + * @post + * None + *****************************************************************************/ +CpaStatus +cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle, + CpaCySymCapabilitiesInfo * pCapInfo); + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_SYM_H */ diff --git a/sys/dev/qat/qat_api/include/lac/cpa_cy_sym_dp.h b/sys/dev/qat/qat_api/include/lac/cpa_cy_sym_dp.h new file mode 100644 index 00000000000..df6cc922b45 --- /dev/null +++ b/sys/dev/qat/qat_api/include/lac/cpa_cy_sym_dp.h @@ -0,0 +1,986 @@ +/*************************************************************************** + * + * BSD LICENSE + * + * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + ***************************************************************************/ + +/* + ***************************************************************************** + * Doxygen group definitions + ****************************************************************************/ + +/** + ***************************************************************************** + * @file cpa_cy_sym_dp.h + * + * @defgroup cpaCySymDp Symmetric cryptographic Data Plane API + * + * @ingroup cpaCySym + * + * @description + * These data structures and functions specify the Data Plane API + * for symmetric cipher, hash, and combined cipher and hash + * operations. + * + * This API is recommended for data plane applications, in which the + * cost of offload - that is, the cycles consumed by the driver in + * sending requests to the hardware, and processing responses - needs + * to be minimized. In particular, use of this API is recommended + * if the following constraints are acceptable to your application: + * + * - Thread safety is not guaranteed. Each software thread should + * have access to its own unique instance (CpaInstanceHandle) to + * avoid contention. + * - Polling is used, rather than interrupts (which are expensive). + * Implementations of this API will provide a function (not + * defined as part of this API) to read responses from the hardware + * response queue and dispatch callback functions, as specified on + * this API. + * - Buffers and buffer lists are passed using physical addresses, + * to avoid virtual to physical address translation costs. + * - For GCM and CCM modes of AES, when performing decryption and + * verification, if verification fails, then the message buffer + * will NOT be zeroed. (This is a consequence of using physical + * addresses for the buffers.) + * - The ability to enqueue one or more requests without submitting + * them to the hardware allows for certain costs to be amortized + * across multiple requests. + * - Only asynchronous invocation is supported. + * - There is no support for partial packets. + * - Implementations may provide certain features as optional at + * build time, such as atomic counters. + * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not + * supported on this API. The specific handle should be obtained + * using the instance discovery functions (@ref cpaCyGetNumInstances, + * @ref cpaCyGetInstances). + * + * @note Performance Trade-Offs + * Different implementations of this API may have different performance + * trade-offs; please refer to the documentation for your implementation + * for details. However, the following concepts informed the definition + * of this API. + * + * The API distinguishes between enqueuing a request and actually + * submitting that request to the cryptographic acceleration + * engine to be performed. This allows multiple requests to be enqueued + * (either individually or in batch), and then for all enqueued requests + * to be submitted in a single operation. The rationale is that in some + * (especially hardware-based) implementations, the submit operation + * is expensive; for example, it may incur an MMIO instruction. The + * API allows this cost to be amortized over a number of requests. The + * precise number of such requests can be tuned for optimal + * performance. + * + * Specifically: + * + * - The function @ref cpaCySymDpEnqueueOp allows one request to be + * enqueued, and optionally for that request (and all previously + * enqueued requests) to be submitted. + * - The function @ref cpaCySymDpEnqueueOpBatch allows multiple + * requests to be enqueued, and optionally for those requests (and all + * previously enqueued requests) to be submitted. + * - The function @ref cpaCySymDpPerformOpNow enqueues no requests, but + * submits all previously enqueued requests. + *****************************************************************************/ + +#ifndef CPA_CY_SYM_DP_H +#define CPA_CY_SYM_DP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpa_cy_common.h" +#include "cpa_cy_sym.h" + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Cryptographic component symmetric session context handle for the + * data plane API. + * @description + * Handle to a cryptographic data plane session context. The memory for + * this handle is allocated by the client. The size of the memory that + * the client needs to allocate is determined by a call to the @ref + * cpaCySymDpSessionCtxGetSize or @ref cpaCySymDpSessionCtxGetDynamicSize + * functions. The session context memory is initialized with a call to + * the @ref cpaCySymInitSession function. + * This memory MUST not be freed until a call to @ref + * cpaCySymDpRemoveSession has completed successfully. + * + *****************************************************************************/ +typedef void * CpaCySymDpSessionCtx; + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Operation Data for cryptographic data plane API. + * + * @description + * This structure contains data relating to a request to perform + * symmetric cryptographic processing on one or more data buffers. + * + * The physical memory to which this structure points needs to be + * at least 8-byte aligned. + * + * All reserved fields SHOULD NOT be written or read by the + * calling code. + * + * @see + * cpaCySymDpEnqueueOp, cpaCySymDpEnqueueOpBatch + ****************************************************************************/ +typedef struct _CpaCySymDpOpData { + Cpa64U reserved0; + /**< Reserved for internal usage. */ + Cpa32U cryptoStartSrcOffsetInBytes; + /**< Starting point for cipher processing, specified as number of bytes + * from start of data in the source buffer. The result of the cipher + * operation will be written back into the buffer starting at this + * location in the destination buffer. + */ + Cpa32U messageLenToCipherInBytes; + /**< The message length, in bytes, of the source buffer on which the + * cryptographic operation will be computed. This must be a multiple of + * the block size if a block cipher is being used. This is also the + * same as the result length. + * + * @note In the case of CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this value + * should not include the length of the padding or the length of the + * MAC; the driver will compute the actual number of bytes over which + * the encryption will occur, which will include these values. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC), this field + * should be set to 0. + * + * @note On some implementations, this length may be limited to a 16-bit + * value (65535 bytes). + */ + CpaPhysicalAddr iv; + /**< Initialization Vector or Counter. Specifically, this is the + * physical address of one of the following: + * + * - For block ciphers in CBC mode, or for Kasumi in F8 mode, or for + * SNOW3G in UEA2 mode, this is the Initialization Vector (IV) + * value. + * - For ARC4, this is reserved for internal usage. + * - For block ciphers in CTR mode, this is the counter. + * - For GCM mode, this is either the IV (if the length is 96 bits) or J0 + * (for other sizes), where J0 is as defined by NIST SP800-38D. + * Regardless of the IV length, a full 16 bytes needs to be allocated. + * - For CCM mode, the first byte is reserved, and the nonce should be + * written starting at &pIv[1] (to allow space for the implementation + * to write in the flags in the first byte). Note that a full 16 bytes + * should be allocated, even though the ivLenInBytes field will have + * a value less than this. + * The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. + */ + Cpa64U reserved1; + /**< Reserved for internal usage. */ + Cpa32U hashStartSrcOffsetInBytes; + /**< Starting point for hash processing, specified as number of bytes + * from start of packet in source buffer. + * + * @note For CCM and GCM modes of operation, this value in this field + * is ignored, and the field is reserved for internal usage. + * The fields @ref additionalAuthData and @ref pAdditionalAuthData + * should be set instead. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field specifies the start of the AAD data in + * the source buffer. + */ + Cpa32U messageLenToHashInBytes; + /**< The message length, in bytes, of the source buffer that the hash + * will be computed on. + * + * @note For CCM and GCM modes of operation, this value in this field + * is ignored, and the field is reserved for internal usage. + * The fields @ref additionalAuthData and @ref pAdditionalAuthData + * should be set instead. + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field specifies the length of the AAD data in the + * source buffer. + * + * @note On some implementations, this length may be limited to a 16-bit + * value (65535 bytes). + */ + CpaPhysicalAddr additionalAuthData; + /**< Physical address of the Additional Authenticated Data (AAD), + * which is needed for authenticated cipher mechanisms (CCM and + * GCM), and to the IV for SNOW3G authentication (@ref + * CPA_CY_SYM_HASH_SNOW3G_UIA2). For other authentication + * mechanisms, this value is ignored, and the field is reserved for + * internal usage. + * + * The length of the data pointed to by this field is set up for + * the session in the @ref CpaCySymHashAuthModeSetupData structure + * as part of the @ref cpaCySymDpInitSession function call. This length + * must not exceed 240 bytes. + + * If AAD is not used, this address must be set to zero. + * + * Specifically for CCM (@ref CPA_CY_SYM_HASH_AES_CCM) and GCM (@ref + * CPA_CY_SYM_HASH_AES_GCM), the caller should be setup as described in + * the same way as the corresponding field, pAdditionalAuthData, on the + * "traditional" API (see the @ref CpaCySymOpData). + * + * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of + * operation, this field is not used and should be set to 0. Instead + * the AAD data should be placed in the source buffer. + * + */ + CpaPhysicalAddr digestResult; + /**< If the digestIsAppended member of the @ref CpaCySymSessionSetupData + * structure is NOT set then this is the physical address of the location + * where the digest result should be inserted (in the case of digest + * generation) or where the purported digest exists (in the case of digest + * verification). + * + * At session registration time, the client specified the digest result + * length with the digestResultLenInBytes member of the @ref + * CpaCySymHashSetupData structure. The client must allocate at least + * digestResultLenInBytes of physically contiguous memory at this location. + * + * For digest generation, the digest result will overwrite any data + * at this location. + * + * @note For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), for "digest result" + * read "authentication tag T". + * + * If the digestIsAppended member of the @ref CpaCySymSessionSetupData + * structure is set then this value is ignored and the digest result + * is understood to be in the destination buffer for digest generation, + * and in the source buffer for digest verification. The location of the + * digest result in this case is immediately following the region over + * which the digest is computed. + */ + + CpaInstanceHandle instanceHandle; + /**< Instance to which the request is to be enqueued. + * @note A callback function must have been registered on the instance + * using @ref cpaCySymDpRegCbFunc. + */ + CpaCySymDpSessionCtx sessionCtx; + /**< Session context specifying the cryptographic parameters for this + * request. + * @note The session must have been created using @ref + * cpaCySymDpInitSession. + */ + Cpa32U ivLenInBytes; + /**< Length of valid IV data pointed to by the pIv parameter. + * + * - For block ciphers in CBC mode, or for Kasumi in F8 mode, or for + * SNOW3G in UEA2 mode, this is the length of the IV (which + * must be the same as the block length of the cipher). + * - For block ciphers in CTR mode, this is the length of the counter + * (which must be the same as the block length of the cipher). + * - For GCM mode, this is either 12 (for 96-bit IVs) or 16, in which + * case pIv points to J0. + * - For CCM mode, this is the length of the nonce, which can be in the + * range 7 to 13 inclusive. + */ + CpaPhysicalAddr srcBuffer; + /**< Physical address of the source buffer on which to operate. + * This is either: + * + * - The location of the data, of length srcBufferLen; or, + * - If srcBufferLen has the special value @ref CPA_DP_BUFLIST, then + * srcBuffer contains the location where a @ref CpaPhysBufferList is + * stored. In this case, the CpaPhysBufferList MUST be aligned + * on an 8-byte boundary. + * - For optimum performance, the buffer should only contain the data + * region that the cryptographic operation(s) must be performed on. + * Any additional data in the source buffer may be copied to the + * destination buffer and this copy may degrade performance. + */ + Cpa32U srcBufferLen; + /**< Length of source buffer, or @ref CPA_DP_BUFLIST. */ + CpaPhysicalAddr dstBuffer; + /**< Physical address of the destination buffer on which to operate. + * This is either: + * + * - The location of the data, of length srcBufferLen; or, + * - If srcBufferLen has the special value @ref CPA_DP_BUFLIST, then + * srcBuffer contains the location where a @ref CpaPhysBufferList is + * stored. In this case, the CpaPhysBufferList MUST be aligned + * on an 8-byte boundary. + * + * For "in-place" operation, the dstBuffer may be identical to the + * srcBuffer. + */ + Cpa32U dstBufferLen; + /**< Length of destination buffer, or @ref CPA_DP_BUFLIST. */ + + CpaPhysicalAddr thisPhys; + /**< Physical address of this data structure */ + + Cpa8U* pIv; + /**< Pointer to (and therefore, the virtual address of) the IV field + * above. + * Needed here because the driver in some cases writes to this field, + * in addition to sending it to the accelerator. + */ + Cpa8U *pAdditionalAuthData; + /**< Pointer to (and therefore, the virtual address of) the + * additionalAuthData field above. + * Needed here because the driver in some cases writes to this field, + * in addition to sending it to the accelerator. + */ + void* pCallbackTag; + /**< Opaque data that will be returned to the client in the function + * completion callback. + * + * This opaque data is not used by the implementation of the API, + * but is simply returned as part of the asynchronous response. + * It may be used to store information that might be useful when + * processing the response later. + */ +} CpaCySymDpOpData; + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Definition of callback function for cryptographic data plane API. + * + * @description + * This is the callback function prototype. The callback function is + * registered by the application using the @ref cpaCySymDpRegCbFunc + * function call, and called back on completion of asycnhronous + * requests made via calls to @ref cpaCySymDpEnqueueOp or @ref + * cpaCySymDpEnqueueOpBatch. + * + * @context + * This callback function can be executed in a context that DOES NOT + * permit sleeping to occur. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] pOpData Pointer to the CpaCySymDpOpData object which + * was supplied as part of the original request. + * @param[in] status Status of the operation. Valid values are + * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and + * CPA_STATUS_UNSUPPORTED. + * @param[in] verifyResult This parameter is valid when the verifyDigest + * option is set in the CpaCySymSessionSetupData + * structure. A value of CPA_TRUE indicates that + * the compare succeeded. A value of CPA_FALSE + * indicates that the compare failed. + * + * @return + * None + * @pre + * Component has been initialized. + * Callback has been registered with @ref cpaCySymDpRegCbFunc. + * @post + * None + * @note + * None + * @see + * cpaCySymDpRegCbFunc + *****************************************************************************/ +typedef void (*CpaCySymDpCbFunc)(CpaCySymDpOpData *pOpData, + CpaStatus status, + CpaBoolean verifyResult); + + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Registration of the operation completion callback function. + * + * @description + * This function allows a completion callback function to be registered. + * The registered callback function is invoked on completion of + * asycnhronous requests made via calls to @ref cpaCySymDpEnqueueOp + * or @ref cpaCySymDpEnqueueOpBatch. + * + * If a callback function was previously registered, it is overwritten. + * + * @context + * This is a synchronous function and it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance on which the callback function is to be + * registered. + * @param[in] pSymNewCb Callback function for this instance. + + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * Component has been initialized. + * @post + * None + * @note + * None + * @see + * CpaCySymDpCbFunc + *****************************************************************************/ +CpaStatus cpaCySymDpRegCbFunc(const CpaInstanceHandle instanceHandle, + const CpaCySymDpCbFunc pSymNewCb); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Gets the size required to store a session context for the data plane + * API. + * + * @description + * This function is used by the client to determine the size of the memory + * it must allocate in order to store the session context. This MUST be + * called before the client allocates the memory for the session context + * and before the client calls the @ref cpaCySymDpInitSession function. + * + * For a given implementation of this API, it is safe to assume that + * cpaCySymDpSessionCtxGetSize() will always return the same size and that + * the size will not be different for different setup data parameters. + * However, it should be noted that the size may change: + * (1) between different implementations of the API (e.g. between software + * and hardware implementations or between different hardware + * implementations) + * (2) between different releases of the same API implementation. + * + * The size returned by this function is the smallest size needed to + * support all possible combinations of setup data parameters. Some + * setup data parameter combinations may fit within a smaller session + * context size. The alternate cpaCySymDpSessionCtxGetDynamicSize() + * function will return the smallest size needed to fit the + * provided setup data parameters. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pSessionSetupData Pointer to session setup data which + * contains parameters which are static + * for a given cryptographic session such + * as operation type, mechanisms, and keys + * for cipher and/or hash operations. + * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required + * to hold the Session Context. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * CpaCySymSessionSetupData + * cpaCySymDpSessionCtxGetDynamicSize() + * cpaCySymDpInitSession() + *****************************************************************************/ +CpaStatus +cpaCySymDpSessionCtxGetSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Gets the minimum size required to store a session context for the data + * plane API. + * + * @description + * This function is used by the client to determine the smallest size of + * the memory it must allocate in order to store the session context. + * This MUST be called before the client allocates the memory for the + * session context and before the client calls the + * @ref cpaCySymDpInitSession function. + * + * This function is an alternate to cpaCySymDpSessionGetSize(). + * cpaCySymDpSessionCtxGetSize() will return a fixed size which is the + * minimum memory size needed to support all possible setup data parameter + * combinations. cpaCySymDpSessionCtxGetDynamicSize() will return the + * minimum memory size needed to support the specific session setup + * data parmeters provided. This size may be different for different setup + * data parameters. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] instanceHandle Instance handle. + * @param[in] pSessionSetupData Pointer to session setup data which + * contains parameters which are static + * for a given cryptographic session such + * as operation type, mechanisms, and keys + * for cipher and/or hash operations. + * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required + * to hold the Session Context. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * CpaCySymSessionSetupData + * cpaCySymDpSessionCtxGetSize() + * cpaCySymDpInitSession() + *****************************************************************************/ +CpaStatus +cpaCySymDpSessionCtxGetDynamicSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Initialize a session for the symmetric cryptographic data plane API. + * + * @description + * This function is used by the client to initialize an asynchronous + * session context for symmetric cryptographic data plane operations. + * The returned session context is the handle to the session and needs to + * be passed when requesting cryptographic operations to be performed. + * + * Only sessions created using this function may be used when + * invoking functions on this API + * + * The session can be removed using @ref cpaCySymDpRemoveSession. + * + * @context + * This is a synchronous function and it cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance to which the requests will be + * submitted. + * @param[in] pSessionSetupData Pointer to session setup data which + * contains parameters that are static + * for a given cryptographic session such + * as operation type, algorithm, and keys + * for cipher and/or hash operations. + * @param[out] sessionCtx Pointer to the memory allocated by the + * client to store the session context. This + * memory must be physically contiguous, and + * its length (in bytes) must be at least as + * big as specified by a call to @ref + * cpaCySymDpSessionCtxGetSize. This memory + * will be initialized with this function. This + * value needs to be passed to subsequent + * processing calls. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * This is a synchronous function and has no completion callback + * associated with it. + * @see + * cpaCySymDpSessionCtxGetSize, cpaCySymDpRemoveSession + *****************************************************************************/ +CpaStatus +cpaCySymDpInitSession(CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymDpSessionCtx sessionCtx); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Remove (delete) a symmetric cryptographic session for the data plane + * API. + * + * @description + * This function will remove a previously initialized session context + * and the installed callback handler function. Removal will fail if + * outstanding calls still exist for the initialized session handle. + * The client needs to retry the remove function at a later time. + * The memory for the session context MUST not be freed until this call + * has completed successfully. + * + * @context + * This is a synchronous function that cannot sleep. It can be + * executed in a context that does not permit sleeping. + * @assumptions + * None + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance handle. + * @param[in,out] sessionCtx Session context to be removed. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * @post + * None + * @note + * Note that this is a synchronous function and has no completion callback + * associated with it. + * + * @see + * CpaCySymDpSessionCtx, + * cpaCySymDpInitSession() + * + *****************************************************************************/ +CpaStatus +cpaCySymDpRemoveSession(const CpaInstanceHandle instanceHandle, + CpaCySymDpSessionCtx sessionCtx); + + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Enqueue a single symmetric cryptographic request. + * + * @description + * This function enqueues a single request to perform a cipher, + * hash or combined (cipher and hash) operation. Optionally, the + * request is also submitted to the cryptographic engine to be + * performed. + * + * See note about performance trade-offs on the @ref cpaCySymDp API. + * + * The function is asynchronous; control is returned to the user once + * the request has been submitted. On completion of the request, the + * application may poll for responses, which will cause a callback + * function (registered via @ref cpaCySymDpRegCbFunc) to be invoked. + * Callbacks within a session are guaranteed to be in the same order + * in which they were submitted. + * + * The following restrictions apply to the pOpData parameter: + * + * - The memory MUST be aligned on an 8-byte boundary. + * - The structure MUST reside in physically contiguous memory. + * - The reserved fields of the structure SHOULD NOT be written + * or read by the calling code. + * + * @context + * This function will not sleep, and hence can be executed in a context + * that does not permit sleeping. + * + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] pOpData Pointer to a structure containing the + * request parameters. The client code allocates + * the memory for this structure. This component + * takes ownership of the memory until it is + * returned in the callback, which was registered + * on the instance via @ref cpaCySymDpRegCbFunc. + * See the above Description for restrictions + * that apply to this parameter. + * @param[in] performOpNow Flag to specify whether the operation should be + * performed immediately (CPA_TRUE), or simply + * enqueued to be performed later (CPA_FALSE). + * In the latter case, the request is submitted + * to be performed either by calling this function + * again with this flag set to CPA_TRUE, or by + * invoking the function @ref + * cpaCySymDpPerformOpNow. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The session identified by pOpData->sessionCtx was setup using + * @ref cpaCySymDpInitSession. + * The instance identified by pOpData->instanceHandle has had a + * callback function registered via @ref cpaCySymDpRegCbFunc. + * + * @post + * None + * + * @note + * A callback of type @ref CpaCySymDpCbFunc is generated in response to + * this function call. Any errors generated during processing are + * reported as part of the callback status code. + * + * @see + * cpaCySymDpInitSession, + * cpaCySymDpPerformOpNow + *****************************************************************************/ +CpaStatus +cpaCySymDpEnqueueOp(CpaCySymDpOpData *pOpData, + const CpaBoolean performOpNow); + + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Enqueue multiple requests to the symmetric cryptographic data plane + * API. + * + * @description + * This function enqueues multiple requests to perform cipher, hash + * or combined (cipher and hash) operations. + + * See note about performance trade-offs on the @ref cpaCySymDp API. + * + * The function is asynchronous; control is returned to the user once + * the request has been submitted. On completion of the request, the + * application may poll for responses, which will cause a callback + * function (registered via @ref cpaCySymDpRegCbFunc) to be invoked. + * Separate callbacks will be invoked for each request. + * Callbacks within a session are guaranteed to be in the same order + * in which they were submitted. + * + * The following restrictions apply to each element of the pOpData + * array: + * + * - The memory MUST be aligned on an 8-byte boundary. + * - The structure MUST reside in physically contiguous memory. + * - The reserved fields of the structure SHOULD NOT be + * written or read by the calling code. + * + * @context + * This function will not sleep, and hence can be executed in a context + * that does not permit sleeping. + * + * @assumptions + * Client MUST allocate the request parameters to 8 byte alignment. + * Reserved elements of the CpaCySymDpOpData structure MUST be 0. + * The CpaCySymDpOpData structure MUST reside in physically + * contiguous memory. + * + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] numberRequests The number of requests in the array of + * CpaCySymDpOpData structures. + * @param[in] pOpData An array of pointers to CpaCySymDpOpData + * structures. Each of the CpaCySymDpOpData + * structure contains the request parameters for + * that request. The client code allocates the + * memory for this structure. This component takes + * ownership of the memory until it is returned in + * the callback, which was registered on the + * instance via @ref cpaCySymDpRegCbFunc. + * See the above Description for restrictions + * that apply to this parameter. + * @param[in] performOpNow Flag to specify whether the operation should be + * performed immediately (CPA_TRUE), or simply + * enqueued to be performed later (CPA_FALSE). + * In the latter case, the request is submitted + * to be performed either by calling this function + * again with this flag set to CPA_TRUE, or by + * invoking the function @ref + * cpaCySymDpPerformOpNow. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The session identified by pOpData[i]->sessionCtx was setup using + * @ref cpaCySymDpInitSession. + * The instance identified by pOpData->instanceHandle[i] has had a + * callback function registered via @ref cpaCySymDpRegCbFunc. + * + * @post + * None + * + * @note + * Multiple callbacks of type @ref CpaCySymDpCbFunc are generated in + * response to this function call (one per request). Any errors + * generated during processing are reported as part of the callback + * status code. + * + * @see + * cpaCySymDpInitSession, + * cpaCySymDpEnqueueOp + *****************************************************************************/ +CpaStatus +cpaCySymDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaCySymDpOpData *pOpData[], + const CpaBoolean performOpNow); + + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Submit any previously enqueued requests to be performed now on the + * symmetric cryptographic data plane API. + * + * @description + * If any requests/operations were enqueued via calls to @ref + * cpaCySymDpEnqueueOp and/or @ref cpaCySymDpEnqueueOpBatch, but with + * the flag performOpNow set to @ref CPA_FALSE, then these operations + * will now be submitted to the accelerator to be performed. + * + * See note about performance trade-offs on the @ref cpaCySymDp API. + * + * @context + * Will not sleep. It can be executed in a context that does not + * permit sleeping. + * + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + * @param[in] instanceHandle Instance to which the requests will be + * submitted. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit + * the request. + * @retval CPA_STATUS_UNSUPPORTED Function is not supported. + * + * @pre + * The component has been initialized. + * A cryptographic session has been previously setup using the + * @ref cpaCySymDpInitSession function call. + * + * @post + * None + * + * @see + * cpaCySymDpEnqueueOp, cpaCySymDpEnqueueOpBatch + *****************************************************************************/ +CpaStatus +cpaCySymDpPerformOpNow(CpaInstanceHandle instanceHandle); + + +#ifdef __cplusplus +} /* close the extern "C" { */ +#endif + +#endif /* CPA_CY_SYM_DP_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/adf_kernel_types.h b/sys/dev/qat/qat_api/qat_direct/include/adf_kernel_types.h new file mode 100644 index 00000000000..4dde7de8b3e --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/adf_kernel_types.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_KERNEL_TYPES_H +#define ADF_KERNEL_TYPES_H + +#define u64 uint64_t +#define u32 uint32_t +#define u16 uint16_t +#define u8 uint8_t +#define s64 int64_t +#define s32 int32_t +#define s16 int16_t +#define s8 int8_t + +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif + +#endif diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_accel_devices.h b/sys/dev/qat/qat_api/qat_direct/include/icp_accel_devices.h new file mode 100644 index 00000000000..3733fec2c9e --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_accel_devices.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_accel_devices.h + * + * @defgroup Acceleration Driver Framework + * + * @ingroup icp_Adf + * + * @description + * This is the top level header file that contains the layout of the ADF + * icp_accel_dev_t structure and related macros/definitions. + * It can be used to dereference the icp_accel_dev_t *passed into upper + * layers. + * + *****************************************************************************/ + +#ifndef ICP_ACCEL_DEVICES_H_ +#define ICP_ACCEL_DEVICES_H_ + +#include "cpa.h" +#include "qat_utils.h" +#include "adf_accel_devices.h" + +#define ADF_CFG_NO_INSTANCE 0xFFFFFFFF + +#define ICP_DC_TX_RING_0 6 +#define ICP_DC_TX_RING_1 7 +#define ICP_RX_RINGS_OFFSET 8 +#define ICP_RINGS_PER_BANK 16 + +/* Number of worker threads per AE */ +#define ICP_ARB_WRK_THREAD_TO_SARB 12 +#define MAX_ACCEL_NAME_LEN 16 +#define ADF_DEVICE_NAME_LENGTH 32 +#define ADF_DEVICE_TYPE_LENGTH 8 + +#define ADF_CTL_DEVICE_NAME "/dev/qat_adf_ctl" + +/** + ***************************************************************************** + * @ingroup icp_AdfAccelHandle + * + * @description + * Accelerator capabilities + * + *****************************************************************************/ +typedef enum { + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = 0x01, + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = 0x02, + ICP_ACCEL_CAPABILITIES_CIPHER = 0x04, + ICP_ACCEL_CAPABILITIES_AUTHENTICATION = 0x08, + ICP_ACCEL_CAPABILITIES_RESERVED_1 = 0x10, + ICP_ACCEL_CAPABILITIES_COMPRESSION = 0x20, + ICP_ACCEL_CAPABILITIES_DEPRECATED = 0x40, + ICP_ACCEL_CAPABILITIES_RANDOM_NUMBER = 0x80, + ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC = 0x100, + ICP_ACCEL_CAPABILITIES_SHA3 = 0x200, + ICP_ACCEL_CAPABILITIES_KPT = 0x400, + ICP_ACCEL_CAPABILITIES_RL = 0x800, + ICP_ACCEL_CAPABILITIES_HKDF = 0x1000, + ICP_ACCEL_CAPABILITIES_ECEDMONT = 0x2000, + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN = 0x4000, + ICP_ACCEL_CAPABILITIES_SHA3_EXT = 0x8000, + ICP_ACCEL_CAPABILITIES_AESGCM_SPC = 0x10000, + ICP_ACCEL_CAPABILITIES_CHACHA_POLY = 0x20000, + ICP_ACCEL_CAPABILITIES_SM2 = 0x40000, + ICP_ACCEL_CAPABILITIES_SM3 = 0x80000, + ICP_ACCEL_CAPABILITIES_SM4 = 0x100000, + ICP_ACCEL_CAPABILITIES_INLINE = 0x200000, + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY = 0x400000, + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64 = 0x800000, + ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = 0x1000000, + ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION = 0x2000000, + ICP_ACCEL_CAPABILITIES_AES_V2 = 0x4000000, + ICP_ACCEL_CAPABILITIES_KPT2 = 0x8000000, +} icp_accel_capabilities_t; + +/** + ***************************************************************************** + * @ingroup icp_AdfAccelHandle + * + * @description + * Device Configuration Data Structure + * + *****************************************************************************/ + +typedef enum device_type_e { + DEVICE_UNKNOWN = 0, + DEVICE_DH895XCC, + DEVICE_DH895XCCVF, + DEVICE_C62X, + DEVICE_C62XVF, + DEVICE_C3XXX, + DEVICE_C3XXXVF, + DEVICE_200XX, + DEVICE_200XXVF, + DEVICE_C4XXX, + DEVICE_C4XXXVF +} device_type_t; + +/* + * Enumeration on Service Type + */ +typedef enum adf_service_type_s { + ADF_SERVICE_CRYPTO, + ADF_SERVICE_COMPRESS, + ADF_SERVICE_MAX /* this is always the last one */ +} adf_service_type_t; + +typedef struct accel_dev_s { + /* Some generic information */ + Cpa32U accelId; + Cpa8U *pAccelName; /* Name given to accelerator */ + Cpa32U aeMask; /* Acceleration Engine mask */ + device_type_t deviceType; /* Device Type */ + /* Device name for SAL */ + char deviceName[ADF_DEVICE_NAME_LENGTH + 1]; + Cpa32U accelCapabilitiesMask; /* Accelerator's capabilities + mask */ + Cpa32U dcExtendedFeatures; /* bit field of features */ + QatUtilsAtomic usageCounter; /* Usage counter. Prevents + shutting down the dev if not 0*/ + Cpa32U deviceMemAvail; /* Device memory for intermediate buffers */ + /* Component specific fields - cast to relevent layer */ + void *pRingInflight; /* For offload optimization */ + void *pSalHandle; /* For SAL*/ + void *pQatStats; /* For QATAL/SAL stats */ + void *ringInfoCallBack; /* Callback for user space + ring enabling */ + void *pShramConstants; /* Virtual address of Shram constants page */ + Cpa64U pShramConstantsDma; /* Bus address of Shram constants page */ + + /* Status of ADF and registered subsystems */ + Cpa32U adfSubsystemStatus; + /* Physical processor to which the dev is connected */ + Cpa8U pkg_id; + enum dev_sku_info sku; + Cpa32U pciDevId; + Cpa8U devFileName[ADF_DEVICE_NAME_LENGTH]; + Cpa32S csrFileHdl; + Cpa32S ringFileHdl; + void *accel; + + Cpa32U maxNumBanks; + Cpa32U maxNumRingsPerBank; + + /* pointer to dynamic instance resource manager */ + void *pInstMgr; + void *banks; /* banks information */ + struct adf_accel_dev *accel_dev; + struct accel_dev_s *pPrev; + struct accel_dev_s *pNext; +} icp_accel_dev_t; + +#endif /* ICP_ACCEL_HANDLE_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_accel_mgr.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_accel_mgr.h new file mode 100644 index 00000000000..43d154433fe --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_accel_mgr.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_adf_accel_mgr.h + * + * @description + * This file contains the function prototype for accel + * instances management + * + *****************************************************************************/ +#ifndef ICP_ADF_ACCEL_MGR_H +#define ICP_ADF_ACCEL_MGR_H + +/* + * Device reset mode type. + * If device reset is triggered from atomic context + * it needs to be in ICP_ADF_DEV_RESET_ASYNC mode. + * Otherwise can be either. + */ +typedef enum icp_adf_dev_reset_mode_e { + ICP_ADF_DEV_RESET_ASYNC = 0, + ICP_ADF_DEV_RESET_SYNC +} icp_adf_dev_reset_mode_t; + +/* + * icp_adf_reset_dev + * + * Description: + * Function resets the given device. + * If device reset is triggered from atomic context + * it needs to be in ICP_ADF_DEV_RESET_ASYNC mode. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_reset_dev(icp_accel_dev_t *accel_dev, + icp_adf_dev_reset_mode_t mode); + +/* + * icp_adf_is_dev_in_reset + * Check if device is in reset state. + * + * Returns: + * CPA_TRUE device is in reset state + * CPA_FALS device is not in reset state + */ +CpaBoolean icp_adf_is_dev_in_reset(icp_accel_dev_t *accel_dev); + +/* + * icp_amgr_getNumInstances + * + * Description: + * Returns number of accel instances in the system. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getNumInstances(Cpa16U *pNumInstances); + +/* + * icp_amgr_getInstances + * + * Description: + * Returns table of accel instances in the system. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getInstances(Cpa16U numInstances, + icp_accel_dev_t **pAccel_devs); +/* + * icp_amgr_getAccelDevByName + * + * Description: + * Returns the accel instance by name. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getAccelDevByName(unsigned char *instanceName, + icp_accel_dev_t **pAccel_dev); +/* + * icp_amgr_getAccelDevByCapabilities + * + * Description: + * Returns a started accel device that implements the capabilities + * specified in capabilitiesMask. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getAccelDevByCapabilities(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances); +/* + * icp_amgr_getAllAccelDevByCapabilities + * + * Description: + * Returns table of accel devices that are started and implement + * the capabilities specified in capabilitiesMask. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getAllAccelDevByCapabilities(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances); + +/* + * icp_amgr_getAccelDevCapabilities + * Returns accel devices capabilities specified in capabilitiesMask. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getAccelDevCapabilities(icp_accel_dev_t *accel_dev, + Cpa32U *pCapabilitiesMask); + +/* + * icp_amgr_getAllAccelDevByEachCapability + * + * Description: + * Returns table of accel devices that are started and implement + * each of the capability specified in capabilitiesMask. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_amgr_getAllAccelDevByEachCapability(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances); + +/* + * icp_qa_dev_get + * + * Description: + * Function increments the device usage counter. + * + * Returns: void + */ +void icp_qa_dev_get(icp_accel_dev_t *pDev); + +/* + * icp_qa_dev_put + * + * Description: + * Function decrements the device usage counter. + * + * Returns: void + */ +void icp_qa_dev_put(icp_accel_dev_t *pDev); + +/* + * icp_adf_getAccelDevByAccelId + * + * Description: + * Gets the accel_dev structure based on accelId + * + * Returns: a pointer to the accelerator structure or NULL if not found. + */ +icp_accel_dev_t *icp_adf_getAccelDevByAccelId(Cpa32U accelId); + +#endif /* ICP_ADF_ACCEL_MGR_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_cfg.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_cfg.h new file mode 100644 index 00000000000..db1e111f07b --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_cfg.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/****************************************************************************** + * @file icp_adf_cfg.h + * + * @defgroup icp_AdfCfg Acceleration Driver Framework Configuration Interface. + * + * @ingroup icp_Adf + * + * @description + * This is the top level header file for the run-time system configuration + * parameters. This interface may be used by components of this API to + * access the supported run-time configuration parameters. + * + *****************************************************************************/ + +#ifndef ICP_ADF_CFG_H +#define ICP_ADF_CFG_H + +#include "cpa.h" +#include "icp_accel_devices.h" + +/****************************************************************************** +* Section for #define's & typedef's +******************************************************************************/ +/* Address of the UOF firmware */ +#define ICP_CFG_UOF_ADDRESS_KEY ("Firmware_UofAddress") +/* Size of the UOF firmware */ +#define ICP_CFG_UOF_SIZE_BYTES_KEY ("Firmware_UofSizeInBytes") +/* Address of the MMP firmware */ +#define ICP_CFG_MMP_ADDRESS_KEY ("Firmware_MmpAddress") +/* Size of the MMP firmware */ +#define ICP_CFG_MMP_SIZE_BYTES_KEY ("Firmware_MMpSizeInBytes") +/* MMP firmware version */ +#define ICP_CFG_MMP_VER_KEY ("Firmware_MmpVer") +/* UOF firmware version */ +#define ICP_CFG_UOF_VER_KEY ("Firmware_UofVer") +/* Tools version */ +#define ICP_CFG_TOOLS_VER_KEY ("Firmware_ToolsVer") +/* Hardware rev id */ +#define ICP_CFG_HW_REV_ID_KEY ("HW_RevId") +/* Lowest Compatible Driver Version */ +#define ICP_CFG_LO_COMPATIBLE_DRV_KEY ("Lowest_Compat_Drv_Ver") +/* Pke Service Disabled flag */ +#define ICP_CFG_PKE_DISABLED ("PkeServiceDisabled") +/* SRAM Physical Address Key */ +#define ADF_SRAM_PHYSICAL_ADDRESS ("Sram_PhysicalAddress") +/* SRAM Virtual Address Key */ +#define ADF_SRAM_VIRTUAL_ADDRESS ("Sram_VirtualAddress") +/* SRAM Size In Bytes Key */ +#define ADF_SRAM_SIZE_IN_BYTES ("Sram_SizeInBytes") +/* Device node id, tells to which die the device is + * connected to */ +#define ADF_DEV_NODE_ID ("Device_NodeId") +/* Device package id, this is accel_dev id */ +#define ADF_DEV_PKG_ID ("Device_PkgId") +/* Device bus address, B.D.F (Bus(8bits),Device(5bits),Function(3bits)) */ +#define ADF_DEV_BUS_ADDRESS ("Device_BusAddress") +/* Number of Acceleration Engines */ +#define ADF_DEV_NUM_AE ("Device_Num_AE") +/* Number of Accelerators */ +#define ADF_DEV_NUM_ACCEL ("Device_Num_Accel") +/* Max Number of Acceleration Engines */ +#define ADF_DEV_MAX_AE ("Device_Max_AE") +/* Max Number of Accelerators */ +#define ADF_DEV_MAX_ACCEL ("Device_Max_Accel") +/* QAT/AE Mask*/ +#define ADF_DEV_MAX_RING_PER_QAT ("Device_Max_Num_Rings_per_Accel") +/* Number of Accelerators */ +#define ADF_DEV_ACCELAE_MASK_FMT ("Device_Accel_AE_Mask_%d") +/* VF ring offset */ +#define ADF_VF_RING_OFFSET_KEY ("VF_RingOffset") +/* Mask of Accelerators */ +#define ADF_DEV_AE_MASK ("Device_AE_Mask") +/* Whether or not arbitration is supported */ +#define ADF_DEV_ARB_SUPPORTED ("ArbitrationSupported") +/* Slice Watch Dog Timer for CySym+Comp */ +#define ADF_DEV_SSM_WDT_BULK ("CySymAndDcWatchDogTimer") +/* Slice Watch Dog Timer for CyAsym */ +#define ADF_DEV_SSM_WDT_PKE ("CyAsymWatchDogTimer") + +/* String names for the exposed sections of config file. */ +#define GENERAL_SEC "GENERAL" +#define WIRELESS_SEC "WIRELESS_INT_" +#define DYN_SEC "DYN" +#define DEV_LIMIT_CFG_ACCESS_TMPL "_D_L_ACC" +/*#define WIRELESS_ENABLED "WirelessEnabled"*/ + +/* + * icp_adf_cfgGetParamValue + * + * Description: + * This function is used to determine the value for a given parameter name. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_cfgGetParamValue(icp_accel_dev_t *accel_dev, + const char *section, + const char *param_name, + char *param_value); +/* + * icp_adf_cfgGetRingNumber + * + * Description: + * Function returns ring number configured for the service. + * NOTE: this function will only be used by QATAL in kernelspace. + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_cfgGetRingNumber(icp_accel_dev_t *accel_dev, + const char *section_name, + const Cpa32U accel_num, + const Cpa32U bank_num, + const char *pServiceName, + Cpa32U *pRingNum); + +/* + * icp_adf_get_busAddress + * Gets the B.D.F. of the physical device + */ +Cpa16U icp_adf_get_busAddress(Cpa16U packageId); + +#endif /* ICP_ADF_CFG_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_debug.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_debug.h new file mode 100644 index 00000000000..d0a6346dfa4 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_debug.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/****************************************************************************** + * @file icp_adf_debug.h + * + * @description + * This header file that contains the prototypes and definitions required + * for ADF debug feature. + * +*****************************************************************************/ +#ifndef ICP_ADF_DEBUG_H +#define ICP_ADF_DEBUG_H + +/* + * adf_proc_type_t + * Type of proc file. Simple for files where read funct + * prints less than page size (4kB) and seq type for files + * where read function needs to print more that page size. + */ +typedef enum adf_proc_type_e { + ADF_PROC_SIMPLE = 1, + ADF_PROC_SEQ +} adf_proc_type_t; + +/* + * debug_dir_info_t + * Struct which is used to hold information about a debug directory + * under the proc filesystem. + * Client should only set name and parent fields. + */ +typedef struct debug_dir_info_s { + char *name; + struct debug_dir_info_s *parent; + /* The below fields are used internally by the driver */ + struct debug_dir_info_s *dirChildListHead; + struct debug_dir_info_s *dirChildListTail; + struct debug_dir_info_s *pNext; + struct debug_dir_info_s *pPrev; + struct debug_file_info_s *fileListHead; + struct debug_file_info_s *fileListTail; + void *proc_entry; +} debug_dir_info_t; + +/* + * Read handle type for simple proc file + * Function is called only once and can print up to 4kB (size) + * Function should return number of bytes printed. + */ +typedef int (*file_read)(void *private_data, char *buff, int size); + +/* + * Read handle type for sequential proc file + * Function can be called more than once. It will be called until the + * return value is not 0. offset should be used to mark the starting + * point for next step. In one go function can print up to 4kB (size). + * Function should return 0 (zero) if all info is printed or + * offset from where to start in next step. + */ +typedef int (*file_read_seq)(void *private_data, + char *buff, + int size, + int offset); + +/* + * debug_file_info_t + * Struct which is used to hold information about a debug file + * under the proc filesystem. + * Client should only set name, type, private_data, parent fields, + * and read or seq_read pointers depending on type used. + */ +typedef struct debug_file_info_s { + char *name; + struct debug_dir_info_s *parent; + adf_proc_type_t type; + file_read read; + file_read_seq seq_read; + void *private_data; + /* The below fields are used internally by the driver */ + struct debug_file_info_s *pNext; + struct debug_file_info_s *pPrev; + void *page; + Cpa32U offset; + void *proc_entry; +} debug_file_info_t; + +/* + * icp_adf_debugAddDir + * + * Description: + * Function used by subsystem to register a new + * directory under the proc filesystem + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_debugAddDir(icp_accel_dev_t *accel_dev, + debug_dir_info_t *dir_info); + +/* + * icp_adf_debugRemoveDir + * + * Description: + * Function used by subsystem to remove an existing + * directory for which debug output may be stored + * in the proc filesystem. + * +*/ +void icp_adf_debugRemoveDir(debug_dir_info_t *dir_info); + +/* + * icp_adf_debugAddFile + * + * Description: + * Function used by subsystem to add a new file under + * the proc file system in which debug output may be written + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_debugAddFile(icp_accel_dev_t *accel_dev, + debug_file_info_t *file_info); + +/* + * icp_adf_debugRemoveFile + * + * Description: + * Function used by subsystem to remove an existing file under + * the proc filesystem in which debug output may be written + * + */ +void icp_adf_debugRemoveFile(debug_file_info_t *file_info); + +#endif /* ICP_ADF_DEBUG_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_esram.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_esram.h new file mode 100644 index 00000000000..c8bd7f5d057 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_esram.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/****************************************************************************** + * @file icp_adf_esram.h + * + * @description + * This file contains the ADF interface to retrieve eSRAM information + * + *****************************************************************************/ +#ifndef ICP_ADF_ESRAM_H +#define ICP_ADF_ESRAM_H + +/* + * icp_adf_esramGetAddress + * + * Description: + * Returns the eSRAM's physical and virtual addresses and its size in bytes. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_esramGetAddress(icp_accel_dev_t *accel_dev, + Cpa32U accelNumber, + Cpa64U *pPhysAddr, + Cpa64U *pVirtAddr, + Cpa32U *pSize); + +#endif /* ICP_ADF_ESRAM_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_init.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_init.h new file mode 100644 index 00000000000..40381a7689a --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_init.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_adf_init.h + * + * @description + * This file contains the function prototype used to register a subsystem + * into the Acceleration Driver Framework (ADF). + * + *****************************************************************************/ +#ifndef ICP_ADF_INIT_H +#define ICP_ADF_INIT_H + +#include "icp_accel_devices.h" +#include "adf_kernel_types.h" +#include "adf_cfg_common.h" + +/* + * Events that will be sending to subsystem. The order of the enum + * declaration matters. It should be defined so that the messages can be + * sent in loop. + */ +typedef enum icp_adf_subsystemEvent_s { + ICP_ADF_EVENT_INIT = 0, + ICP_ADF_EVENT_START, + ICP_ADF_EVENT_STOP, + ICP_ADF_EVENT_SHUTDOWN, + ICP_ADF_EVENT_RESTARING, + ICP_ADF_EVENT_RESTARTED, + ICP_ADF_EVENT_ERROR, + ICP_ADF_EVENT_END +} icp_adf_subsystemEvent_t; + +/* + * Ring info operation used to enable or disable ring polling by ME + */ +typedef enum icp_adf_ringInfoOperation_e { + ICP_ADF_RING_ENABLE = 0, + ICP_ADF_RING_DISABLE +} icp_adf_ringInfoOperation_t; + +/* + * Ring generic serivce info private data + */ +typedef enum icp_adf_ringInfoService_e { + ICP_ADF_RING_SERVICE_0 = 0, + ICP_ADF_RING_SERVICE_1, + ICP_ADF_RING_SERVICE_2, + ICP_ADF_RING_SERVICE_3, + ICP_ADF_RING_SERVICE_4, + ICP_ADF_RING_SERVICE_5, + ICP_ADF_RING_SERVICE_6, + ICP_ADF_RING_SERVICE_7, + ICP_ADF_RING_SERVICE_8, + ICP_ADF_RING_SERVICE_9, + ICP_ADF_RING_SERVICE_10, +} icp_adf_ringInfoService_t; + +/* + * Ring info callback. Function is used to send operation and ring info + * to enable or disable ring polling by ME + */ +typedef CpaStatus (*ringInfoCb)(icp_accel_dev_t *accel_dev, + Cpa32U ringNumber, + icp_adf_ringInfoOperation_t operation, + icp_adf_ringInfoService_t info); + +/* + * Registration handle structure + * Each subservice has to have an instance of it. + */ +typedef struct subservice_registation_handle_s { + CpaStatus (*subserviceEventHandler)(icp_accel_dev_t *accel_dev, + icp_adf_subsystemEvent_t event, + void *param); + struct { + Cpa32U subsystemInitBit : 1; + Cpa32U subsystemStartBit : 1; + Cpa32U subsystemFailedBit : 1; + } subsystemStatus[ADF_MAX_DEVICES]; + char *subsystem_name; + struct subservice_registation_handle_s *pNext; + struct subservice_registation_handle_s *pPrev; +} subservice_registation_handle_t; + +/* + * icp_adf_subsystemRegister + * + * Description: + * Function used by subsystem to register within ADF + * Should be called during insertion of a subsystem + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_subsystemRegister(subservice_registation_handle_t *handle); + +/* + * icp_adf_subsystemUnregister + * + * Description: + * Function used by subsystem to unregister from ADF + * Should be called while subsystem in removed + * If the subsystem is initialised and/or started + * it will be stopped and shutdown by this function + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_subsystemUnregister(subservice_registation_handle_t *handle); + +/* + * icp_adf_accesLayerRingInfoCbRegister + * + * Description: + * Function register access layer callback, which sends ring info message + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_accesLayerRingInfoCbRegister(icp_accel_dev_t *accel_dev, + ringInfoCb); + +/* + * icp_adf_accesLayerRingInfoCbUnregister + * + * Description: + * Function unregister access layer callback for ring info message + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +void icp_adf_accesLayerRingInfoCbUnregister(icp_accel_dev_t *accel_dev); + +/* + * icp_adf_isSubsystemStarted + * + * Description: + * Function returns true if the service is started on a device + * + * Returns: + * CPA_TRUE if subsystem is started + * CPA_FALSE if subsystem is not started + */ + +CpaBoolean +icp_adf_isSubsystemStarted(subservice_registation_handle_t *subsystem_hdl); + +/* + * icp_adf_isDevStarted + * + * Description: + * Function returns true if the device is started + * Returns: + * CPA_TRUE if dev is started + * CPA_FALSE if dev is not started + */ +CpaBoolean icp_adf_isDevStarted(icp_accel_dev_t *accel_dev); + +/* + * adf_subsystemRestarting + * + * Description: + * Function sends restarting event to all subsystems. + * This function should be used by error handling function only + * + * Returns: + * CPA_TRUE on success + * CPA_FALSE on failure + */ +CpaStatus adf_subsystemRestarting(icp_accel_dev_t *accel_dev); + +/* + * adf_subsystemRestarted + * + * Description: + * Function sends restarted event to all subsystems. + * This function should be used by error handling function only + * + * Returns: + * CPA_TRUE on success + * CPA_FALSE on failure + */ +CpaStatus adf_subsystemRestarted(icp_accel_dev_t *accel_dev); + +/* + * adf_subsystemError + * + * Description: + * Function sends error event to all subsystems. + * This function should be used by error handling funct. only + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus adf_subsystemError(icp_accel_dev_t *accel_dev); + +/* + * reset_adf_subsystemTable + * + * Description: + * Function to reset subsystem table head, the pointer + * to the head of the list and lock. + * + * Returns: void + */ +void reset_adf_subsystemTable(void); + +#endif /* ICP_ADF_INIT_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_poll.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_poll.h new file mode 100644 index 00000000000..d5a9cac4f4c --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_poll.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_adf_poll.h + * + * @description + * File contains Public API Definitions for the polling method. + * + *****************************************************************************/ +#ifndef ICP_ADF_POLL_H +#define ICP_ADF_POLL_H + +#include "cpa.h" +/* + * icp_adf_pollInstance + * + * Description: + * Poll an instance. In order to poll an instance + * sal will pass in a table of trans handles from which + * the ring to be polled can be obtained and subsequently + * polled. + * + * Returns: + * CPA_STATUS_SUCCESS on polling a ring with data + * CPA_STATUS_FAIL on failure + * CPA_STATUS_RETRY if ring has no data on it + * or ring is already being polled. + */ +CpaStatus icp_adf_pollInstance(icp_comms_trans_handle *trans_hnd, + Cpa32U num_transHandles, + Cpa32U response_quota); + +/* + * icp_adf_check_RespInstance + * + * Description: + * Check whether an instance is empty or has remaining responses on it. In + * order to check an instance for the remaining responses, sal will pass in + * a table of trans handles from which the instance to be checked can be + * obtained and subsequently checked. + * + * Returns: + * CPA_STATUS_SUCCESS if response ring is empty + * CPA_STATUS_FAIL on failure + * CPA_STATUS_RETRY if response ring is not empty + * CPA_STATUS_INVALID_PARAM Invalid parameter passed in + */ +CpaStatus icp_adf_check_RespInstance(icp_comms_trans_handle *trans_hnd, + Cpa32U num_transHandles); + +#endif /* ICP_ADF_POLL_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport.h new file mode 100644 index 00000000000..d39e017c37c --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport.h @@ -0,0 +1,286 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_adf_transport.h + * + * @description + * File contains Public API Definitions for ADF transport. + * + *****************************************************************************/ +#ifndef ICP_ADF_TRANSPORT_H +#define ICP_ADF_TRANSPORT_H + +#include "cpa.h" + +/* + * Enumeration on Transport Types exposed + */ +typedef enum icp_transport_type_e { + ICP_TRANS_TYPE_NONE = 0, + ICP_TRANS_TYPE_ETR, + ICP_TRANS_TYPE_DP_ETR, + ICP_TRANS_TYPE_ADMINREG, + ICP_TRANS_TYPE_DELIMIT +} icp_transport_type; + +/* + * Enumeration on response delivery method + */ +typedef enum icp_resp_deliv_method_e { + ICP_RESP_TYPE_NONE = 0, + ICP_RESP_TYPE_IRQ, + ICP_RESP_TYPE_POLL, + ICP_RESP_TYPE_DELIMIT +} icp_resp_deliv_method; + +/* + * Unique identifier of a transport handle + */ +typedef Cpa32U icp_trans_identifier; + +/* + * Opaque Transport Handle + */ +typedef void *icp_comms_trans_handle; + +/* + * Function Pointer invoked when a set of messages is received for the given + * transport handle + */ +typedef void (*icp_trans_callback)(void *pMsg); + +/* + * icp_adf_getDynInstance + * + * Description: + * Get an available instance from dynamic instance pool + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + */ +CpaStatus icp_adf_getDynInstance(icp_accel_dev_t *accel_dev, + adf_service_type_t stype, + Cpa32U *pinstance_id); + +/* + * icp_adf_putDynInstance + * + * Description: + * Put back an instance to dynamic instance pool + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + */ +CpaStatus icp_adf_putDynInstance(icp_accel_dev_t *accel_dev, + adf_service_type_t stype, + Cpa32U instance_id); + +/* + * icp_adf_getNumAvailDynInstance + * + * Description: + * Get the number of the available dynamic instances + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + */ +CpaStatus icp_adf_getNumAvailDynInstance(icp_accel_dev_t *accel_dev, + adf_service_type_t stype, + Cpa32U *num); + +/* + * icp_adf_transGetFdForHandle + * + * Description: + * Get a file descriptor for a particular transaction handle. + * If more than one transaction handler + * are ever present, this will need to be refactored to + * return the appropriate fd of the appropriate bank. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + * + */ +CpaStatus icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd, + int *fd); + +/* + * icp_adf_transCreateHandle + * + * Description: + * Create a transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + * The message size is variable: requests can be 64 or 128 bytes, responses + * can be 16, 32 or 64 bytes. + * Supported num_msgs: + * 32, 64, 128, 256, 512, 1024, 2048 number of messages. + * + */ +CpaStatus icp_adf_transCreateHandle(icp_accel_dev_t *accel_dev, + icp_transport_type trans_type, + const char *section, + const Cpa32U accel_nr, + const Cpa32U bank_nr, + const char *service_name, + const icp_adf_ringInfoService_t info, + icp_trans_callback callback, + icp_resp_deliv_method resp, + const Cpa32U num_msgs, + const Cpa32U msg_size, + icp_comms_trans_handle *trans_handle); + +/* + * icp_adf_transReinitHandle + * + * Description: + * Reinitialize a transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + * The message size is variable: requests can be 64 or 128 bytes, responses + * can be 16, 32 or 64 bytes. + * Supported num_msgs: + * 32, 64, 128, 256, 512, 1024, 2048 number of messages. + * + */ +CpaStatus icp_adf_transReinitHandle(icp_accel_dev_t *accel_dev, + icp_transport_type trans_type, + const char *section, + const Cpa32U accel_nr, + const Cpa32U bank_nr, + const char *service_name, + const icp_adf_ringInfoService_t info, + icp_trans_callback callback, + icp_resp_deliv_method resp, + const Cpa32U num_msgs, + const Cpa32U msg_size, + icp_comms_trans_handle *trans_handle); + +/* + * icp_adf_transGetHandle + * + * Description: + * Gets a pointer to a previously created transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + * + */ +CpaStatus icp_adf_transGetHandle(icp_accel_dev_t *accel_dev, + icp_transport_type trans_type, + const char *section, + const Cpa32U accel_nr, + const Cpa32U bank_nr, + const char *service_name, + icp_comms_trans_handle *trans_handle); + +/* + * icp_adf_transReleaseHandle + * + * Description: + * Release a transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle); + +/* + * icp_adf_transResetHandle + * + * Description: + * Reset a transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_transResetHandle(icp_comms_trans_handle trans_handle); + +/* + * icp_adf_transPutMsg + * + * Description: + * Put Message onto the transport handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_transPutMsg(icp_comms_trans_handle trans_handle, + Cpa32U *inBufs, + Cpa32U bufLen); + +/* + * icp_adf_getInflightRequests + * + * Description: + * Retrieve in flight requests from the transport handle. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +/* + * icp_adf_transPutMsgSync + * + * Description: + * Put Message onto the transport handle and waits for a response. + * Note: Not all transports support method. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_transPutMsgSync(icp_comms_trans_handle trans_handle, + Cpa32U *inBuf, + Cpa32U *outBuf, + Cpa32U bufsLen); + +/* + * icp_adf_transGetRingNum + * + * Description: + * Function Returns ring number of the given trans_handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle, + Cpa32U *ringNum); + +/* + * icp_adf_flush_requests + * + * Description: + * Function flushes the enqueued requests on the trans_handle + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus icp_adf_flush_requests(icp_comms_trans_handle trans_handle); + +#endif /* ICP_ADF_TRANSPORT_H */ diff --git a/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport_dp.h b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport_dp.h new file mode 100644 index 00000000000..63d5862c635 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_direct/include/icp_adf_transport_dp.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/***************************************************************************** + * @file icp_adf_transport_dp.h + * + * @description + * File contains Public API definitions for ADF transport for data plane. + * + *****************************************************************************/ +#ifndef ICP_ADF_TRANSPORT_DP_H +#define ICP_ADF_TRANSPORT_DP_H + +#include "cpa.h" +#include "icp_adf_transport.h" + +/* + * icp_adf_getQueueMemory + * Data plane support function - returns the pointer to next message on the ring + * or NULL if there is not enough space. + */ +extern void icp_adf_getQueueMemory(icp_comms_trans_handle trans_handle, + Cpa32U numberRequests, + void **pCurrentQatMsg); +/* + * icp_adf_getSingleQueueAddr + * Data plane support function - returns the pointer to next message on the ring + * or NULL if there is not enough space - it also updates the shadow tail copy. + */ +extern void icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_handle, + void **pCurrentQatMsg); + +/* + * icp_adf_getQueueNext + * Data plane support function - increments the tail pointer and returns + * the pointer to next message on the ring. + */ +extern void icp_adf_getQueueNext(icp_comms_trans_handle trans_handle, + void **pCurrentQatMsg); + +/* + * icp_adf_updateQueueTail + * Data plane support function - Writes the tail shadow copy to the device. + */ +extern void icp_adf_updateQueueTail(icp_comms_trans_handle trans_handle); + +/* + * icp_adf_isRingEmpty + * Data plane support function - check if the ring is empty + */ +extern CpaBoolean icp_adf_isRingEmpty(icp_comms_trans_handle trans_handle); + +/* + * icp_adf_pollQueue + * Data plane support function - Poll messages from the queue. + */ +extern CpaStatus icp_adf_pollQueue(icp_comms_trans_handle trans_handle, + Cpa32U response_quota); + +/* + * icp_adf_queueDataToSend + * LAC lite support function - Indicates if there is data on the ring to be + * send. This should only be called on request rings. If the function returns + * true then it is ok to call icp_adf_updateQueueTail() function on this ring. + */ +extern CpaBoolean icp_adf_queueDataToSend(icp_comms_trans_handle trans_hnd); + +/* + * icp_adf_dp_getInflightRequests + * Retrieve in flight requests from the transport handle. + * Data plane API - no locks. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +extern CpaStatus +icp_adf_dp_getInflightRequests(icp_comms_trans_handle trans_handle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests); + +#endif /* ICP_ADF_TRANSPORT_DP_H */ diff --git a/sys/dev/qat/qat_api/qat_kernel/src/lac_adf_interface_freebsd.c b/sys/dev/qat/qat_api/qat_kernel/src/lac_adf_interface_freebsd.c new file mode 100644 index 00000000000..7669e21eeaa --- /dev/null +++ b/sys/dev/qat/qat_api/qat_kernel/src/lac_adf_interface_freebsd.c @@ -0,0 +1,424 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg.h" +#include "cpa.h" +#include "icp_accel_devices.h" +#include "adf_common_drv.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "lac_sal_ctrl.h" + +static subservice_registation_handle_t *salService = NULL; +static struct service_hndl adfService = { 0 }; +static icp_accel_dev_t *adfDevices = NULL; +static icp_accel_dev_t *adfDevicesHead = NULL; +struct mtx *adfDevicesLock; + +/* + * Need to keep track of what device is currently in reset state + */ +static char accel_dev_reset_stat[ADF_MAX_DEVICES] = { 0 }; + +/* + * Need to keep track of what device is currently in error state + */ +static char accel_dev_error_stat[ADF_MAX_DEVICES] = { 0 }; + +/* + * Need to preserve sal handle during restart + */ +static void *accel_dev_sal_hdl_ptr[ADF_MAX_DEVICES] = { 0 }; + +static icp_accel_dev_t * +create_adf_dev_structure(struct adf_accel_dev *accel_dev) +{ + icp_accel_dev_t *adf = NULL; + + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + + adf = malloc(sizeof(*adf), M_QAT, M_WAITOK); + memset(adf, 0, sizeof(*adf)); + adf->accelId = accel_dev->accel_id; + adf->pAccelName = (char *)hw_data->dev_class->name; + adf->deviceType = (device_type_t)hw_data->dev_class->type; + strlcpy(adf->deviceName, + hw_data->dev_class->name, + sizeof(adf->deviceName)); + adf->accelCapabilitiesMask = hw_data->accel_capabilities_mask; + adf->sku = hw_data->get_sku(hw_data); + adf->accel_dev = accel_dev; + accel_dev->lac_dev = adf; + + return adf; +} + +/* + * adf_event_handler + * Handle device init/uninit/start/stop event + */ +static CpaStatus +adf_event_handler(struct adf_accel_dev *accel_dev, enum adf_event event) +{ + CpaStatus status = CPA_STATUS_FAIL; + icp_accel_dev_t *adf = NULL; + + if (!adf_cfg_sec_find(accel_dev, ADF_KERNEL_SAL_SEC)) { + return CPA_STATUS_SUCCESS; + } + + if (event == ADF_EVENT_INIT) { + adf = create_adf_dev_structure(accel_dev); + if (NULL == adf) { + return CPA_STATUS_FAIL; + } + if (accel_dev_sal_hdl_ptr[accel_dev->accel_id]) { + adf->pSalHandle = + accel_dev_sal_hdl_ptr[accel_dev->accel_id]; + accel_dev_sal_hdl_ptr[accel_dev->accel_id] = NULL; + } + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + ICP_ADD_ELEMENT_TO_END_OF_LIST(adf, adfDevices, adfDevicesHead); + qatUtilsMutexUnlock(&adfDevicesLock); + } else { + adf = accel_dev->lac_dev; + } + + if (event == ADF_EVENT_START) { + adf->dcExtendedFeatures = + accel_dev->hw_device->extended_dc_capabilities; + } + + if (event == ADF_EVENT_RESTARTING) { + accel_dev_reset_stat[accel_dev->accel_id] = 1; + accel_dev_sal_hdl_ptr[accel_dev->accel_id] = adf->pSalHandle; + } + + if (event == ADF_EVENT_RESTARTED) { + accel_dev_reset_stat[accel_dev->accel_id] = 0; + accel_dev_error_stat[accel_dev->accel_id] = 0; + } + + status = + salService->subserviceEventHandler(adf, + (icp_adf_subsystemEvent_t)event, + NULL); + + if (event == ADF_EVENT_ERROR) { + accel_dev_error_stat[accel_dev->accel_id] = 1; + } + + if ((status == CPA_STATUS_SUCCESS && event == ADF_EVENT_SHUTDOWN) || + (status != CPA_STATUS_SUCCESS && event == ADF_EVENT_INIT)) { + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + ICP_REMOVE_ELEMENT_FROM_LIST(adf, adfDevices, adfDevicesHead); + qatUtilsMutexUnlock(&adfDevicesLock); + accel_dev->lac_dev = NULL; + free(adf, M_QAT); + } + + if (status == CPA_STATUS_SUCCESS && event == ADF_EVENT_START) { + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + adf->adfSubsystemStatus = 1; + qatUtilsMutexUnlock(&adfDevicesLock); + } + + if ((status == CPA_STATUS_SUCCESS && event == ADF_EVENT_STOP) || + (status == CPA_STATUS_RETRY && event == ADF_EVENT_STOP)) { + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + adf->adfSubsystemStatus = 0; + qatUtilsMutexUnlock(&adfDevicesLock); + status = CPA_STATUS_SUCCESS; + } + + return status; +} + +/* + * icp_adf_subsystemRegister + * adapter function from SAL to adf driver + * call adf_service_register from adf driver directly with same + * parameters + */ +CpaStatus +icp_adf_subsystemRegister( + subservice_registation_handle_t *sal_service_reg_handle) +{ + if (salService != NULL) + return CPA_STATUS_FAIL; + + salService = sal_service_reg_handle; + adfService.name = sal_service_reg_handle->subsystem_name; + adfService.event_hld = adf_event_handler; + + if (adf_service_register(&adfService) == 0) { + return CPA_STATUS_SUCCESS; + } else { + salService = NULL; + return CPA_STATUS_FAIL; + } +} + +/* + * icp_adf_subsystemUnegister + * adapter function from SAL to adf driver + */ +CpaStatus +icp_adf_subsystemUnregister( + subservice_registation_handle_t *sal_service_reg_handle) +{ + if (adf_service_unregister(&adfService) == 0) { + salService = NULL; + return CPA_STATUS_SUCCESS; + } else { + return CPA_STATUS_FAIL; + } +} + +/* + * icp_adf_cfgGetParamValue + * get parameter value from section @section with key @param + */ +CpaStatus +icp_adf_cfgGetParamValue(icp_accel_dev_t *adf, + const char *section, + const char *param, + char *value) +{ + if (adf_cfg_get_param_value(adf->accel_dev, section, param, value) == + 0) { + return CPA_STATUS_SUCCESS; + } else { + return CPA_STATUS_FAIL; + } +} + +CpaBoolean +icp_adf_is_dev_in_reset(icp_accel_dev_t *accel_dev) +{ + return (CpaBoolean)accel_dev_reset_stat[accel_dev->accelId]; +} + +CpaStatus +icp_adf_debugAddDir(icp_accel_dev_t *adf, debug_dir_info_t *dir_info) +{ + return CPA_STATUS_SUCCESS; +} + +void +icp_adf_debugRemoveDir(debug_dir_info_t *dir_info) +{ +} + +CpaStatus +icp_adf_debugAddFile(icp_accel_dev_t *adf, debug_file_info_t *file_info) +{ + return CPA_STATUS_SUCCESS; +} + +void +icp_adf_debugRemoveFile(debug_file_info_t *file_info) +{ +} + +/* + * icp_adf_getAccelDevByAccelId + * return acceleration device with id @accelId + */ +icp_accel_dev_t * +icp_adf_getAccelDevByAccelId(Cpa32U accelId) +{ + icp_accel_dev_t *adf = NULL; + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + adf = adfDevicesHead; + while (adf != NULL && adf->accelId != accelId) + adf = adf->pNext; + qatUtilsMutexUnlock(&adfDevicesLock); + return adf; +} + +/* + * icp_amgr_getNumInstances + * Return the number of acceleration devices it the system. + */ +CpaStatus +icp_amgr_getNumInstances(Cpa16U *pNumInstances) +{ + icp_accel_dev_t *adf = NULL; + Cpa16U count = 0; + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) + count++; + qatUtilsMutexUnlock(&adfDevicesLock); + *pNumInstances = count; + return CPA_STATUS_SUCCESS; +} + +/* + * icp_amgr_getAccelDevByCapabilities + * Returns a started accel device that implements + * the capabilities specified in capabilitiesMask. + */ +CpaStatus +icp_amgr_getAccelDevByCapabilities(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances) +{ + icp_accel_dev_t *adf = NULL; + *pNumInstances = 0; + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) { + if (adf->accelCapabilitiesMask & capabilitiesMask) { + if (adf->adfSubsystemStatus) { + pAccel_devs[0] = adf; + *pNumInstances = 1; + qatUtilsMutexUnlock(&adfDevicesLock); + return CPA_STATUS_SUCCESS; + } + } + } + qatUtilsMutexUnlock(&adfDevicesLock); + return CPA_STATUS_FAIL; +} + +/* + * icp_amgr_getAllAccelDevByEachCapabilities + * Returns table of accel devices that are started and implement + * each of the capabilities specified in capabilitiesMask. + */ +CpaStatus +icp_amgr_getAllAccelDevByEachCapability(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances) +{ + icp_accel_dev_t *adf = NULL; + *pNumInstances = 0; + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) { + Cpa32U enabled_caps = + adf->accelCapabilitiesMask & capabilitiesMask; + if (enabled_caps == capabilitiesMask) { + if (adf->adfSubsystemStatus) { + pAccel_devs[(*pNumInstances)++] = + (icp_accel_dev_t *)adf; + } + } + } + qatUtilsMutexUnlock(&adfDevicesLock); + return CPA_STATUS_SUCCESS; +} + +/* + * icp_amgr_getAllAccelDevByCapabilities + * Fetches accel devices based on the capability + * and returns the count of the device + */ +CpaStatus +icp_amgr_getAllAccelDevByCapabilities(Cpa32U capabilitiesMask, + icp_accel_dev_t **pAccel_devs, + Cpa16U *pNumInstances) +{ + icp_accel_dev_t *adf = NULL; + Cpa16U i = 0; + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) { + if (adf->accelCapabilitiesMask & capabilitiesMask) { + if (adf->adfSubsystemStatus) { + pAccel_devs[i++] = adf; + } + } + } + qatUtilsMutexUnlock(&adfDevicesLock); + *pNumInstances = i; + return CPA_STATUS_SUCCESS; +} + +/* + * icp_amgr_getAccelDevCapabilities + * Returns accel devices capabilities specified in capabilitiesMask. + * + * Returns: + * CPA_STATUS_SUCCESS on success + * CPA_STATUS_FAIL on failure + */ +CpaStatus +icp_amgr_getAccelDevCapabilities(icp_accel_dev_t *accel_dev, + Cpa32U *pCapabilitiesMask) +{ + ICP_CHECK_FOR_NULL_PARAM(accel_dev); + ICP_CHECK_FOR_NULL_PARAM(pCapabilitiesMask); + + *pCapabilitiesMask = accel_dev->accelCapabilitiesMask; + return CPA_STATUS_SUCCESS; +} + +/* + * icp_qa_dev_get + * + * Description: + * Function increments the device usage counter. + * + * Returns: void + */ +void +icp_qa_dev_get(icp_accel_dev_t *pDev) +{ + ICP_CHECK_FOR_NULL_PARAM_VOID(pDev); + adf_dev_get(pDev->accel_dev); +} + +/* + * icp_qa_dev_put + * + * Description: + * Function decrements the device usage counter. + * + * Returns: void + */ +void +icp_qa_dev_put(icp_accel_dev_t *pDev) +{ + ICP_CHECK_FOR_NULL_PARAM_VOID(pDev); + adf_dev_put(pDev->accel_dev); +} + +Cpa16U +icp_adf_get_busAddress(Cpa16U packageId) +{ + Cpa16U busAddr = 0xFFFF; + icp_accel_dev_t *adf = NULL; + + qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER); + for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) { + if (adf->accelId == packageId) { + busAddr = pci_get_bus(accel_to_pci_dev(adf->accel_dev)) + << 8 | + pci_get_slot(accel_to_pci_dev(adf->accel_dev)) + << 3 | + pci_get_function(accel_to_pci_dev(adf->accel_dev)); + break; + } + } + qatUtilsMutexUnlock(&adfDevicesLock); + return busAddr; +} + +CpaBoolean +icp_adf_isSubsystemStarted(subservice_registation_handle_t *subsystem_hdl) +{ + if (subsystem_hdl == salService) + return CPA_TRUE; + else + return CPA_FALSE; +} + +CpaBoolean +icp_adf_is_dev_in_error(icp_accel_dev_t *accel_dev) +{ + return (CpaBoolean)accel_dev_error_stat[accel_dev->accelId]; +} diff --git a/sys/dev/qat/qat_api/qat_kernel/src/lac_symbols.c b/sys/dev/qat/qat_api/qat_kernel/src/lac_symbols.c new file mode 100644 index 00000000000..182bc1b3ffb --- /dev/null +++ b/sys/dev/qat/qat_api/qat_kernel/src/lac_symbols.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/****************************************************************************** + * @file lac_symbols.c + * + * This file contains all the symbols that are exported by the Look Aside + * kernel Module. + * + *****************************************************************************/ +#include +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_dp.h" +#include "cpa_dc_bp.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_poll.h" +#include "icp_sal_poll.h" +#include "icp_sal_iommu.h" +#include "icp_sal_versions.h" +#include "lac_common.h" + +/* Symbols for getting version information */ +EXPORT_SYMBOL(icp_sal_getDevVersionInfo); + +/* DC Compression */ +EXPORT_SYMBOL(cpaDcGetNumIntermediateBuffers); +EXPORT_SYMBOL(cpaDcInitSession); +EXPORT_SYMBOL(cpaDcResetSession); +EXPORT_SYMBOL(cpaDcUpdateSession); +EXPORT_SYMBOL(cpaDcRemoveSession); +EXPORT_SYMBOL(cpaDcCompressData); +EXPORT_SYMBOL(cpaDcDecompressData); +EXPORT_SYMBOL(cpaDcGenerateHeader); +EXPORT_SYMBOL(cpaDcGenerateFooter); +EXPORT_SYMBOL(cpaDcGetStats); +EXPORT_SYMBOL(cpaDcGetInstances); +EXPORT_SYMBOL(cpaDcGetNumInstances); +EXPORT_SYMBOL(cpaDcGetSessionSize); +EXPORT_SYMBOL(cpaDcGetStatusText); +EXPORT_SYMBOL(cpaDcBufferListGetMetaSize); +EXPORT_SYMBOL(cpaDcBnpBufferListGetMetaSize); +EXPORT_SYMBOL(cpaDcDeflateCompressBound); +EXPORT_SYMBOL(cpaDcInstanceGetInfo2); +EXPORT_SYMBOL(cpaDcQueryCapabilities); +EXPORT_SYMBOL(cpaDcSetAddressTranslation); +EXPORT_SYMBOL(cpaDcStartInstance); +EXPORT_SYMBOL(cpaDcStopInstance); +EXPORT_SYMBOL(cpaDcBPCompressData); +EXPORT_SYMBOL(cpaDcCompressData2); +EXPORT_SYMBOL(cpaDcDecompressData2); + +/* DcDp Compression */ +EXPORT_SYMBOL(cpaDcDpGetSessionSize); +EXPORT_SYMBOL(cpaDcDpInitSession); +EXPORT_SYMBOL(cpaDcDpRemoveSession); +EXPORT_SYMBOL(cpaDcDpUpdateSession); +EXPORT_SYMBOL(cpaDcDpRegCbFunc); +EXPORT_SYMBOL(cpaDcDpEnqueueOp); +EXPORT_SYMBOL(cpaDcDpEnqueueOpBatch); +EXPORT_SYMBOL(cpaDcDpPerformOpNow); + +EXPORT_SYMBOL(icp_sal_DcPollInstance); +EXPORT_SYMBOL(icp_sal_DcPollDpInstance); +EXPORT_SYMBOL(icp_sal_pollBank); +EXPORT_SYMBOL(icp_sal_pollAllBanks); + +/* sal iommu symbols */ +EXPORT_SYMBOL(icp_sal_iommu_get_remap_size); +EXPORT_SYMBOL(icp_sal_iommu_map); +EXPORT_SYMBOL(icp_sal_iommu_unmap); + +EXPORT_SYMBOL(icp_sal_get_dc_error); diff --git a/sys/dev/qat/qat_api/qat_kernel/src/qat_transport.c b/sys/dev/qat/qat_api/qat_kernel/src/qat_transport.c new file mode 100644 index 00000000000..f8aa6e0ac3e --- /dev/null +++ b/sys/dev/qat/qat_api/qat_kernel/src/qat_transport.c @@ -0,0 +1,426 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" + +#include "cpa.h" +#include "icp_adf_init.h" +#include "icp_adf_transport_dp.h" + +/* + * adf_modulo + * result = data % ( 2 ^ shift ) + */ +static inline Cpa32U +adf_modulo(Cpa32U data, Cpa32U shift) +{ + Cpa32U div = data >> shift; + Cpa32U mult = div << shift; + + return data - mult; +} + +/* + * icp_adf_transCreateHandle + * crete transport handle for a service + * call adf_create_ring from adf driver directly with same parameters + */ +CpaStatus +icp_adf_transCreateHandle(icp_accel_dev_t *adf, + icp_transport_type trans_type, + const char *section, + const uint32_t accel_nr, + const uint32_t bank_nr, + const char *service_name, + const icp_adf_ringInfoService_t info, + icp_trans_callback callback, + icp_resp_deliv_method resp, + const uint32_t num_msgs, + const uint32_t msg_size, + icp_comms_trans_handle *trans_handle) +{ + CpaStatus status; + int error; + + ICP_CHECK_FOR_NULL_PARAM(trans_handle); + ICP_CHECK_FOR_NULL_PARAM(adf); + + error = adf_create_ring(adf->accel_dev, + section, + bank_nr, + num_msgs, + msg_size, + service_name, + callback, + ((resp == ICP_RESP_TYPE_IRQ) ? 0 : 1), + (struct adf_etr_ring_data **)trans_handle); + if (!error) + status = CPA_STATUS_SUCCESS; + else + status = CPA_STATUS_FAIL; + + return status; +} + +/* + * icp_adf_transReinitHandle + * Reinitialize transport handle for a service + */ +CpaStatus +icp_adf_transReinitHandle(icp_accel_dev_t *adf, + icp_transport_type trans_type, + const char *section, + const uint32_t accel_nr, + const uint32_t bank_nr, + const char *service_name, + const icp_adf_ringInfoService_t info, + icp_trans_callback callback, + icp_resp_deliv_method resp, + const uint32_t num_msgs, + const uint32_t msg_size, + icp_comms_trans_handle *trans_handle) +{ + return CPA_STATUS_SUCCESS; +} +/* + * icp_adf_transReleaseHandle + * destroy a transport handle, call adf_remove_ring from adf driver directly + */ +CpaStatus +icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle) +{ + struct adf_etr_ring_data *ring = trans_handle; + + ICP_CHECK_FOR_NULL_PARAM(ring); + adf_remove_ring(ring); + + return CPA_STATUS_SUCCESS; +} + +/* + * icp_adf_transResetHandle + * clean a transport handle, call adf_remove_ring from adf driver directly + */ +CpaStatus +icp_adf_transResetHandle(icp_comms_trans_handle trans_handle) +{ + return CPA_STATUS_SUCCESS; +} + +/* + * icp_adf_transGetRingNum + * get ring number from a transport handle + */ +CpaStatus +icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle, uint32_t *ringNum) +{ + struct adf_etr_ring_data *ring = trans_handle; + + ICP_CHECK_FOR_NULL_PARAM(ring); + ICP_CHECK_FOR_NULL_PARAM(ringNum); + *ringNum = (uint32_t)(ring->ring_number); + + return CPA_STATUS_SUCCESS; +} + +/* + * icp_adf_transPutMsg + * send a request to transport handle + * call adf_send_message from adf driver directly + */ +CpaStatus +icp_adf_transPutMsg(icp_comms_trans_handle trans_handle, + uint32_t *inBuf, + uint32_t bufLen) +{ + struct adf_etr_ring_data *ring = trans_handle; + CpaStatus status = CPA_STATUS_FAIL; + int error = EFAULT; + + ICP_CHECK_FOR_NULL_PARAM(ring); + + error = adf_send_message(ring, inBuf); + if (EAGAIN == error) + status = CPA_STATUS_RETRY; + else if (0 == error) + status = CPA_STATUS_SUCCESS; + else + status = CPA_STATUS_FAIL; + + return status; +} + +CpaStatus +icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + struct adf_etr_ring_data *ring = trans_handle; + ICP_CHECK_FOR_NULL_PARAM(ring); + ICP_CHECK_FOR_NULL_PARAM(maxInflightRequests); + ICP_CHECK_FOR_NULL_PARAM(numInflightRequests); + /* + * XXX: The qat_direct version of this routine returns max - 1, not + * the absolute max. + */ + *numInflightRequests = (*(uint32_t *)ring->inflights); + *maxInflightRequests = + ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_adf_dp_getInflightRequests(icp_comms_trans_handle trans_handle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + ICP_CHECK_FOR_NULL_PARAM(trans_handle); + ICP_CHECK_FOR_NULL_PARAM(maxInflightRequests); + ICP_CHECK_FOR_NULL_PARAM(numInflightRequests); + + return icp_adf_getInflightRequests(trans_handle, + maxInflightRequests, + numInflightRequests); +} + +/* + * This function allows the user to poll the response ring. The + * ring number to be polled is supplied by the user via the + * trans handle for that ring. The trans_hnd is a pointer + * to an array of trans handles. This ring is + * only polled if it contains data. + * This method is used as an alternative to the reading messages + * via the ISR method. + * This function will return RETRY if the ring is empty. + */ +CpaStatus +icp_adf_pollInstance(icp_comms_trans_handle *trans_hnd, + Cpa32U num_transHandles, + Cpa32U response_quota) +{ + Cpa32U resp_total = 0; + Cpa32U num_resp; + struct adf_etr_ring_data *ring = NULL; + struct adf_etr_bank_data *bank = NULL; + Cpa32U i; + + ICP_CHECK_FOR_NULL_PARAM(trans_hnd); + + for (i = 0; i < num_transHandles; i++) { + ring = trans_hnd[i]; + if (!ring) + continue; + bank = ring->bank; + + /* If the ring in question is empty try the next ring.*/ + if (!bank || !bank->ring_mask) { + continue; + } + + num_resp = adf_handle_response(ring, response_quota); + resp_total += num_resp; + } + + /* If any of the rings in the instance had data and was polled + * return SUCCESS. */ + if (resp_total) + return CPA_STATUS_SUCCESS; + else + return CPA_STATUS_RETRY; +} + +/* + * This function allows the user to check the response ring. The + * ring number to be polled is supplied by the user via the + * trans handle for that ring. The trans_hnd is a pointer + * to an array of trans handles. + * This function now is a empty function. + */ +CpaStatus +icp_adf_check_RespInstance(icp_comms_trans_handle *trans_hnd, + Cpa32U num_transHandles) +{ + return CPA_STATUS_SUCCESS; +} + +/* + * icp_sal_pollBank + * poll bank with id bank_number inside acceleration device with id @accelId + */ +CpaStatus +icp_sal_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota) +{ + int ret; + + ret = adf_poll_bank(accelId, bank_number, response_quota); + if (!ret) + return CPA_STATUS_SUCCESS; + else if (EAGAIN == ret) + return CPA_STATUS_RETRY; + + return CPA_STATUS_FAIL; +} + +/* + * icp_sal_pollAllBanks + * poll all banks inside acceleration device with id @accelId + */ +CpaStatus +icp_sal_pollAllBanks(Cpa32U accelId, Cpa32U response_quota) +{ + int ret = 0; + + ret = adf_poll_all_banks(accelId, response_quota); + if (!ret) + return CPA_STATUS_SUCCESS; + else if (ret == EAGAIN) + return CPA_STATUS_RETRY; + + return CPA_STATUS_FAIL; +} + +/* + * icp_adf_getQueueMemory + * Data plane support function - returns the pointer to next message on the ring + * or NULL if there is not enough space. + */ +void +icp_adf_getQueueMemory(icp_comms_trans_handle trans_handle, + Cpa32U numberRequests, + void **pCurrentQatMsg) +{ + struct adf_etr_ring_data *ring = trans_handle; + Cpa64U flight; + + ICP_CHECK_FOR_NULL_PARAM_VOID(ring); + + /* Check if there is enough space in the ring */ + flight = atomic_add_return(numberRequests, ring->inflights); + if (flight > ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) { + atomic_sub(numberRequests, ring->inflights); + *pCurrentQatMsg = NULL; + return; + } + + /* We have enough space - get the address of next message */ + *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail); +} + +/* + * icp_adf_getSingleQueueAddr + * Data plane support function - returns the pointer to next message on the ring + * or NULL if there is not enough space - it also updates the shadow tail copy. + */ +void +icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_handle, + void **pCurrentQatMsg) +{ + struct adf_etr_ring_data *ring = trans_handle; + Cpa64U flight; + + ICP_CHECK_FOR_NULL_PARAM_VOID(ring); + ICP_CHECK_FOR_NULL_PARAM_VOID(pCurrentQatMsg); + + /* Check if there is enough space in the ring */ + flight = atomic_add_return(1, ring->inflights); + if (flight > ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) { + atomic_dec(ring->inflights); + *pCurrentQatMsg = NULL; + return; + } + + /* We have enough space - get the address of next message */ + *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail); + + /* Update the shadow tail */ + ring->tail = + adf_modulo(ring->tail + ADF_MSG_SIZE_TO_BYTES(ring->msg_size), + ADF_RING_SIZE_MODULO(ring->ring_size)); +} + +/* + * icp_adf_getQueueNext + * Data plane support function - increments the tail pointer and returns + * the pointer to next message on the ring. + */ +void +icp_adf_getQueueNext(icp_comms_trans_handle trans_handle, void **pCurrentQatMsg) +{ + struct adf_etr_ring_data *ring = trans_handle; + + ICP_CHECK_FOR_NULL_PARAM_VOID(ring); + ICP_CHECK_FOR_NULL_PARAM_VOID(pCurrentQatMsg); + + /* Increment tail to next message */ + ring->tail = + adf_modulo(ring->tail + ADF_MSG_SIZE_TO_BYTES(ring->msg_size), + ADF_RING_SIZE_MODULO(ring->ring_size)); + + /* Get the address of next message */ + *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail); +} + +/* + * icp_adf_updateQueueTail + * Data plane support function - Writes the tail shadow copy to the device. + */ +void +icp_adf_updateQueueTail(icp_comms_trans_handle trans_handle) +{ + struct adf_etr_ring_data *ring = trans_handle; + + ICP_CHECK_FOR_NULL_PARAM_VOID(ring); + + WRITE_CSR_RING_TAIL(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring->tail); + ring->csr_tail_offset = ring->tail; +} + +/* + * icp_adf_pollQueue + * Data plane support function - Poll messages from the queue. + */ +CpaStatus +icp_adf_pollQueue(icp_comms_trans_handle trans_handle, Cpa32U response_quota) +{ + Cpa32U num_resp; + struct adf_etr_ring_data *ring = trans_handle; + + ICP_CHECK_FOR_NULL_PARAM(ring); + + num_resp = adf_handle_response(ring, response_quota); + + if (num_resp) + return CPA_STATUS_SUCCESS; + else + return CPA_STATUS_RETRY; +} + +/* + * icp_adf_queueDataToSend + * Data-plane support function - Indicates if there is data on the ring to be + * sent. This should only be called on request rings. If the function returns + * true then it is ok to call icp_adf_updateQueueTail() function on this ring. + */ +CpaBoolean +icp_adf_queueDataToSend(icp_comms_trans_handle trans_handle) +{ + struct adf_etr_ring_data *ring = trans_handle; + + if (ring->tail != ring->csr_tail_offset) + return CPA_TRUE; + else + return CPA_FALSE; +} + +/* + * This icp API won't be supported in kernel space currently + */ +CpaStatus +icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd, int *fd) +{ + return CPA_STATUS_UNSUPPORTED; +} diff --git a/sys/dev/qat/qat_api/qat_utils/include/qat_utils.h b/sys/dev/qat/qat_api/qat_utils/include/qat_utils.h new file mode 100644 index 00000000000..c30a1978598 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/include/qat_utils.h @@ -0,0 +1,851 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef QAT_UTILS_H +#define QAT_UTILS_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __x86_64__ +#include +#else +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cpa.h" + +#define QAT_UTILS_LOG(...) printf("QAT: "__VA_ARGS__) + +#define QAT_UTILS_WAIT_FOREVER (-1) +#define QAT_UTILS_WAIT_NONE 0 + +#define QAT_UTILS_HOST_TO_NW_16(uData) QAT_UTILS_OS_HOST_TO_NW_16(uData) +#define QAT_UTILS_HOST_TO_NW_32(uData) QAT_UTILS_OS_HOST_TO_NW_32(uData) +#define QAT_UTILS_HOST_TO_NW_64(uData) QAT_UTILS_OS_HOST_TO_NW_64(uData) + +#define QAT_UTILS_NW_TO_HOST_16(uData) QAT_UTILS_OS_NW_TO_HOST_16(uData) +#define QAT_UTILS_NW_TO_HOST_32(uData) QAT_UTILS_OS_NW_TO_HOST_32(uData) +#define QAT_UTILS_NW_TO_HOST_64(uData) QAT_UTILS_OS_NW_TO_HOST_64(uData) + +#define QAT_UTILS_UDIV64_32(dividend, divisor) \ + QAT_UTILS_OS_UDIV64_32(dividend, divisor) + +#define QAT_UTILS_UMOD64_32(dividend, divisor) \ + QAT_UTILS_OS_UMOD64_32(dividend, divisor) + +#define ICP_CHECK_FOR_NULL_PARAM(param) \ + do { \ + if (NULL == param) { \ + QAT_UTILS_LOG("%s(): invalid param: %s\n", \ + __FUNCTION__, \ + #param); \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +#define ICP_CHECK_FOR_NULL_PARAM_VOID(param) \ + do { \ + if (NULL == param) { \ + QAT_UTILS_LOG("%s(): invalid param: %s\n", \ + __FUNCTION__, \ + #param); \ + return; \ + } \ + } while (0) + +/*Macro for adding an element to the tail of a doubly linked list*/ +/*The currentptr tracks the tail, and the headptr tracks the head.*/ +#define ICP_ADD_ELEMENT_TO_END_OF_LIST(elementtoadd, currentptr, headptr) \ + do { \ + if (NULL == currentptr) { \ + currentptr = elementtoadd; \ + elementtoadd->pNext = NULL; \ + elementtoadd->pPrev = NULL; \ + headptr = currentptr; \ + } else { \ + elementtoadd->pPrev = currentptr; \ + currentptr->pNext = elementtoadd; \ + elementtoadd->pNext = NULL; \ + currentptr = elementtoadd; \ + } \ + } while (0) + +/*currentptr is not used in this case since we don't track the tail. */ +#define ICP_ADD_ELEMENT_TO_HEAD_OF_LIST(elementtoadd, currentptr, headptr) \ + do { \ + if (NULL == headptr) { \ + elementtoadd->pNext = NULL; \ + elementtoadd->pPrev = NULL; \ + headptr = elementtoadd; \ + } else { \ + elementtoadd->pPrev = NULL; \ + elementtoadd->pNext = headptr; \ + headptr->pPrev = elementtoadd; \ + headptr = elementtoadd; \ + } \ + } while (0) + +#define ICP_REMOVE_ELEMENT_FROM_LIST(elementtoremove, currentptr, headptr) \ + do { \ + /*If the previous pointer is not NULL*/ \ + if (NULL != elementtoremove->pPrev) { \ + elementtoremove->pPrev->pNext = \ + elementtoremove->pNext; \ + if (elementtoremove->pNext) { \ + elementtoremove->pNext->pPrev = \ + elementtoremove->pPrev; \ + } else { \ + /* Move the tail pointer backwards */ \ + currentptr = elementtoremove->pPrev; \ + } \ + } else if (NULL != elementtoremove->pNext) { \ + /*Remove the head pointer.*/ \ + elementtoremove->pNext->pPrev = NULL; \ + /*Hence move the head forward.*/ \ + headptr = elementtoremove->pNext; \ + } else { \ + /*Remove the final entry in the list. */ \ + currentptr = NULL; \ + headptr = NULL; \ + } \ + } while (0) + +MALLOC_DECLARE(M_QAT); + +#ifdef __x86_64__ +typedef atomic64_t QatUtilsAtomic; +#else +typedef atomic_t QatUtilsAtomic; +#endif + +#define QAT_UTILS_OS_NW_TO_HOST_16(uData) be16toh(uData) +#define QAT_UTILS_OS_NW_TO_HOST_32(uData) be32toh(uData) +#define QAT_UTILS_OS_NW_TO_HOST_64(uData) be64toh(uData) + +#define QAT_UTILS_OS_HOST_TO_NW_16(uData) htobe16(uData) +#define QAT_UTILS_OS_HOST_TO_NW_32(uData) htobe32(uData) +#define QAT_UTILS_OS_HOST_TO_NW_64(uData) htobe64(uData) + +/** + * @ingroup QatUtils + * + * @brief Atomically read the value of atomic variable + * + * @param pAtomicVar IN - atomic variable + * + * Atomically reads the value of pAtomicVar to the outValue + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return pAtomicVar value + */ +int64_t qatUtilsAtomicGet(QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief Atomically set the value of atomic variable + * + * @param inValue IN - atomic variable to be set equal to inValue + * + * @param pAtomicVar OUT - atomic variable + * + * Atomically sets the value of pAtomicVar to the value given + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return none + */ +void qatUtilsAtomicSet(int64_t inValue, QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief add the value to atomic variable + * + * @param inValue (in) - value to be added to the atomic variable + * + * @param pAtomicVar (in & out) - atomic variable + * + * Atomically adds the value of inValue to the pAtomicVar + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return pAtomicVar value after the addition + */ +int64_t qatUtilsAtomicAdd(int64_t inValue, QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief subtract the value from atomic variable + * + * @param inValue IN - atomic variable value to be subtracted by value + * + * @param pAtomicVar IN/OUT - atomic variable + * + * Atomically subtracts the value of pAtomicVar by inValue + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return pAtomicVar value after the subtraction + */ +int64_t qatUtilsAtomicSub(int64_t inValue, QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief increment value of atomic variable by 1 + * + * @param pAtomicVar IN/OUT - atomic variable + * + * Atomically increments the value of pAtomicVar by 1. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return pAtomicVar value after the increment + */ +int64_t qatUtilsAtomicInc(QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief decrement value of atomic variable by 1 + * + * @param pAtomicVar IN/OUT - atomic variable + * + * Atomically decrements the value of pAtomicVar by 1. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return pAtomic value after the decrement + */ +int64_t qatUtilsAtomicDec(QatUtilsAtomic *pAtomicVar); + +/** + * @ingroup QatUtils + * + * @brief NUMA aware memory allocation; available on Linux OS only. + * + * @param size - memory size to allocate, in bytes + * @param node - node + * @param alignment - memory boundary alignment (alignment can not be 0) + * + * Allocates a memory zone of a given size on the specified node + * The returned memory is guaraunteed to be physically contiguous if the + * given size is less than 128KB and belonging to the node specified + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return Pointer to the allocated zone or NULL if the allocation failed + */ +void *qatUtilsMemAllocContiguousNUMA(uint32_t size, + uint32_t node, + uint32_t alignment); + +/** + * @ingroup QatUtils + * + * @brief Frees memory allocated by qatUtilsMemAllocContigousNUMA. + * + * @param ptr - pointer to the memory zone + * @param size - size of the pointer previously allocated + * + * Frees a previously allocated memory zone + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - none + */ +void qatUtilsMemFreeNUMA(void *ptr); + +/** + * @ingroup QatUtils + * + * @brief virtual to physical address translation + * + * @param virtAddr - virtual address + * + * Converts a virtual address into its equivalent MMU-mapped physical address + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return Corresponding physical address + */ +#define QAT_UTILS_MMU_VIRT_TO_PHYS(virtAddr) \ + ((uint64_t)((virtAddr) ? vtophys(virtAddr) : 0)) + +/** + * @ingroup QatUtils + * + * @brief Initializes the SpinLock object + * + * @param pLock - Spinlock handle + * + * Initializes the SpinLock object. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsLockInit(struct mtx *pLock); + +/** + * @ingroup QatUtils + * + * @brief Acquires a spin lock + * + * @param pLock - Spinlock handle + * + * This routine acquires a spin lock so the + * caller can synchronize access to shared data in a + * multiprocessor-safe way by raising IRQL. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - Returns CPA_STATUS_SUCCESS if the spinlock is acquired. Returns + * CPA_STATUS_FAIL + * if + * spinlock handle is NULL. If spinlock is already acquired by any + * other thread of execution then it tries in busy loop/spins till it + * gets spinlock. + */ +CpaStatus qatUtilsLock(struct mtx *pLock); + +/** + * @ingroup QatUtils + * + * @brief Releases the spin lock + * + * @param pLock - Spinlock handle + * + * This routine releases the spin lock which the thread had acquired + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - return CPA_STATUS_SUCCESS if the spinlock is released. Returns + * CPA_STATUS_FAIL + * if + * spinlockhandle passed is NULL. + */ +CpaStatus qatUtilsUnlock(struct mtx *pLock); + +/** + * @ingroup QatUtils + * + * @brief Destroy the spin lock object + * + * @param pLock - Spinlock handle + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - returns CPA_STATUS_SUCCESS if plock is destroyed. + * returns CPA_STATUS_FAIL if plock is NULL. + */ +CpaStatus qatUtilsLockDestroy(struct mtx *pLock); + +/** + * @ingroup QatUtils + * + * @brief Initializes a semaphore + * + * @param pSid - semaphore handle + * @param start_value - initial semaphore value + * + * Initializes a semaphore object + * Note: Semaphore initialization qatUtilsSemaphoreInit API must be called + * first before using any QAT Utils Semaphore APIs + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSemaphoreInit(struct sema **pSid, uint32_t start_value); + +/** + * @ingroup QatUtils + * + * @brief Destroys a semaphore object + * + * @param pSid - semaphore handle + * + * Destroys a semaphore object; the caller should ensure that no thread is + * blocked on this semaphore. If call made when thread blocked on semaphore the + * behaviour is unpredictable + * + * @li Reentrant: yes +] * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSemaphoreDestroy(struct sema **pSid); + +/** + * @ingroup QatUtils + * + * @brief Waits on (decrements) a semaphore + * + * @param pSid - semaphore handle + * @param timeout - timeout, in ms; QAT_UTILS_WAIT_FOREVER (-1) if the thread + * is to block indefinitely or QAT_UTILS_WAIT_NONE (0) if the thread is to + * return immediately even if the call fails + * + * Decrements a semaphore, blocking if the semaphore is + * unavailable (value is 0). + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSemaphoreWait(struct sema **pSid, int32_t timeout); + +/** + * @ingroup QatUtils + * + * @brief Non-blocking wait on semaphore + * + * @param semaphore - semaphore handle + * + * Decrements a semaphore, not blocking the calling thread if the semaphore + * is unavailable + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSemaphoreTryWait(struct sema **semaphore); + +/** + * @ingroup QatUtils + * + * @brief Posts to (increments) a semaphore + * + * @param pSid - semaphore handle + * + * Increments a semaphore object + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSemaphorePost(struct sema **pSid); + +/** + * @ingroup QatUtils + * + * @brief initializes a pMutex + * + * @param pMutex - pMutex handle + * + * Initializes a pMutex object + * @note Mutex initialization qatUtilsMutexInit API must be called + * first before using any QAT Utils Mutex APIs + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsMutexInit(struct mtx **pMutex); + +/** + * @ingroup QatUtils + * + * @brief locks a pMutex + * + * @param pMutex - pMutex handle + * @param timeout - timeout in ms; QAT_UTILS_WAIT_FOREVER (-1) to wait forever + * or QAT_UTILS_WAIT_NONE to return immediately + * + * Locks a pMutex object + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsMutexLock(struct mtx **pMutex, int32_t timeout); + +/** + * @ingroup QatUtils + * + * @brief Unlocks a pMutex + * + * @param pMutex - pMutex handle + * + * Unlocks a pMutex object + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsMutexUnlock(struct mtx **pMutex); + +/** + * @ingroup QatUtils + * + * @brief Destroys a pMutex object + * + * @param pMutex - pMutex handle + * + * Destroys a pMutex object; the caller should ensure that no thread is + * blocked on this pMutex. If call made when thread blocked on pMutex the + * behaviour is unpredictable + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsMutexDestroy(struct mtx **pMutex); + +/** + * @ingroup QatUtils + * + * @brief Non-blocking attempt to lock a pMutex + * + * @param pMutex - pMutex handle + * + * Attempts to lock a pMutex object, returning immediately with + * CPA_STATUS_SUCCESS if + * the lock was successful or CPA_STATUS_FAIL if the lock failed + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsMutexTryLock(struct mtx **pMutex); + +/** + * @ingroup QatUtils + * + * @brief Yielding sleep for a number of milliseconds + * + * @param milliseconds - number of milliseconds to sleep + * + * The calling thread will sleep for the specified number of milliseconds. + * This sleep is yielding, hence other tasks will be scheduled by the + * operating system during the sleep period. Calling this function with an + * argument of 0 will place the thread at the end of the current scheduling + * loop. + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + */ +CpaStatus qatUtilsSleep(uint32_t milliseconds); + +/** + * @ingroup QatUtils + * + * @brief Yields execution of current thread + * + * Yields the execution of the current thread + * + * @li Reentrant: yes + * @li IRQ safe: no + * + * @return - none + */ +void qatUtilsYield(void); + +/** + * @ingroup QatUtils + * + * @brief Calculate MD5 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least md5 block size long as defined in + * rfc1321 (64 bytes) + * out - output pointer for state data after single md5 transform + * operation. + * The buffer needs to be at least md5 state size long as defined in + * rfc1321 (16 bytes) + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashMD5(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate MD5 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least md5 block size long as defined in + * rfc1321 (64 bytes) + * out - output pointer for state data after single md5 transform + * operation. + * The buffer needs to be at least md5 state size long as defined in + * rfc1321 (16 bytes) + * len - Length on the input to be processed. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashMD5Full(uint8_t *in, uint8_t *out, uint32_t len); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA1 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha1 block size long as defined in + * rfc3174 (64 bytes) + * out - output pointer for state data after single sha1 transform + * operation. + * The buffer needs to be at least sha1 state size long as defined in + * rfc3174 (20 bytes) + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA1(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA1 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha1 block size long as defined in + * rfc3174 (64 bytes) + * out - output pointer for state data after single sha1 transform + * operation. + * The buffer needs to be at least sha1 state size long as defined in + * rfc3174 (20 bytes) + * len - Length on the input to be processed. + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA1Full(uint8_t *in, uint8_t *out, uint32_t len); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA224 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha224 block size long as defined in + * rfc3874 and rfc4868 (64 bytes) + * out - output pointer for state data after single sha224 transform + * operation. + * The buffer needs to be at least sha224 state size long as defined in + * rfc3874 and rfc4868 (32 bytes) + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA224(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA256 transform operation + * + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha256 block size long as defined in + * rfc4868 (64 bytes) + * out - output pointer for state data after single sha256 transform + * operation. + * The buffer needs to be at least sha256 state size long as defined in + * rfc4868 (32 bytes) + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA256(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA256 transform operation + * + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha256 block size long as defined in + * rfc4868 (64 bytes) + * out - output pointer for state data after single sha256 transform + * operation. + * The buffer needs to be at least sha256 state size long as defined in + * rfc4868 (32 bytes) + * len - Length on the input to be processed. + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA256Full(uint8_t *in, uint8_t *out, uint32_t len); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA384 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha384 block size long as defined in + * rfc4868 (128 bytes) + * out - output pointer for state data after single sha384 transform + * operation. + * The buffer needs to be at least sha384 state size long as defined in + * rfc4868 (64 bytes) + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA384(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA384 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha384 block size long as defined in + * rfc4868 (128 bytes) + * out - output pointer for state data after single sha384 transform + * operation. + * The buffer needs to be at least sha384 state size long as defined in + * rfc4868 (64 bytes) + * len - Length on the input to be processed. + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA384Full(uint8_t *in, uint8_t *out, uint32_t len); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA512 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha512 block size long as defined in + * rfc4868 (128 bytes) + * out - output pointer for state data after single sha512 transform + * operation. + * The buffer needs to be at least sha512 state size long as defined in + * rfc4868 (64 bytes) + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA512(uint8_t *in, uint8_t *out); + +/** + * @ingroup QatUtils + * + * @brief Calculate SHA512 transform operation + * + * @param in - pointer to data to be processed. + * The buffer needs to be at least sha512 block size long as defined in + * rfc4868 (128 bytes) + * out - output pointer for state data after single sha512 transform + * operation. + * The buffer needs to be at least sha512 state size long as defined in + * rfc4868 (64 bytes) + * len - Length on the input to be processed. + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsHashSHA512Full(uint8_t *in, uint8_t *out, uint32_t len); + +/** + * @ingroup QatUtils + * + * @brief Single block AES encrypt + * + * @param key - pointer to symetric key. + * keyLenInBytes - key length + * in - pointer to data to encrypt + * out - pointer to output buffer for encrypted text + * The in and out buffers need to be at least AES block size long + * as defined in rfc3686 (16 bytes) + * + * @li Reentrant: yes + * @li IRQ safe: yes + * + * @return - CPA_STATUS_SUCCESS/CPA_STATUS_FAIL + * + */ +CpaStatus qatUtilsAESEncrypt(uint8_t *key, + uint32_t keyLenInBytes, + uint8_t *in, + uint8_t *out); +#endif diff --git a/sys/dev/qat/qat_api/qat_utils/src/QatUtilsAtomic.c b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsAtomic.c new file mode 100644 index 00000000000..5bee0e6543f --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsAtomic.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_utils.h" + +#ifdef __x86_64__ +__inline int64_t +qatUtilsAtomicGet(QatUtilsAtomic *pAtomicVar) +{ + return ((int64_t)atomic64_read((QatUtilsAtomic *)pAtomicVar)); +} + +__inline void +qatUtilsAtomicSet(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + atomic64_set((QatUtilsAtomic *)pAtomicVar, inValue); +} + +__inline int64_t +qatUtilsAtomicAdd(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + return atomic64_add_return((long)inValue, (QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicSub(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + return atomic64_sub_return((long)inValue, (QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicInc(QatUtilsAtomic *pAtomicVar) +{ + return atomic64_inc_return((QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicDec(QatUtilsAtomic *pAtomicVar) +{ + return atomic64_dec_return((QatUtilsAtomic *)pAtomicVar); +} +#else +__inline int64_t +qatUtilsAtomicGet(QatUtilsAtomic *pAtomicVar) +{ + return ((int64_t)atomic_read((QatUtilsAtomic *)pAtomicVar)); +} + +__inline void +qatUtilsAtomicSet(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + atomic_set((QatUtilsAtomic *)pAtomicVar, inValue); +} + +__inline int64_t +qatUtilsAtomicAdd(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + return atomic_add_return(inValue, (QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicSub(int64_t inValue, QatUtilsAtomic *pAtomicVar) +{ + return atomic_sub_return(inValue, (QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicInc(QatUtilsAtomic *pAtomicVar) +{ + return atomic_inc_return((QatUtilsAtomic *)pAtomicVar); +} + +__inline int64_t +qatUtilsAtomicDec(QatUtilsAtomic *pAtomicVar) +{ + return atomic_dec_return((QatUtilsAtomic *)pAtomicVar); +} +#endif diff --git a/sys/dev/qat/qat_api/qat_utils/src/QatUtilsCrypto.c b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsCrypto.c new file mode 100644 index 00000000000..3be2b8c362a --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsCrypto.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_utils.h" + +CpaStatus +qatUtilsHashMD5(uint8_t *in, uint8_t *out) +{ + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, in, MD5_BLOCK_LENGTH); + bcopy(&ctx, out, MD5_DIGEST_LENGTH); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA1(uint8_t *in, uint8_t *out) +{ + SHA1_CTX ctx; + + SHA1Init(&ctx); + SHA1Update(&ctx, in, SHA1_BLOCK_LEN); + bcopy(&ctx, out, SHA1_HASH_LEN); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA224(uint8_t *in, uint8_t *out) +{ + SHA224_CTX ctx; + + SHA224_Init(&ctx); + SHA224_Update(&ctx, in, SHA224_BLOCK_LENGTH); + bcopy(&ctx, out, SHA256_DIGEST_LENGTH); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA256(uint8_t *in, uint8_t *out) +{ + SHA256_CTX ctx; + + SHA256_Init(&ctx); + SHA256_Update(&ctx, in, SHA256_BLOCK_LENGTH); + bcopy(&ctx, out, SHA256_DIGEST_LENGTH); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA384(uint8_t *in, uint8_t *out) +{ + SHA384_CTX ctx; + + SHA384_Init(&ctx); + SHA384_Update(&ctx, in, SHA384_BLOCK_LENGTH); + bcopy(&ctx, out, SHA512_DIGEST_LENGTH); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA512(uint8_t *in, uint8_t *out) +{ + SHA512_CTX ctx; + + SHA512_Init(&ctx); + SHA512_Update(&ctx, in, SHA512_BLOCK_LENGTH); + bcopy(&ctx, out, SHA512_DIGEST_LENGTH); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashMD5Full(uint8_t *in, uint8_t *out, uint32_t len) +{ + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, in, len); + MD5Final(out, &ctx); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA1Full(uint8_t *in, uint8_t *out, uint32_t len) +{ + SHA1_CTX ctx; + + SHA1Init(&ctx); + SHA1Update(&ctx, in, len); + SHA1Final((caddr_t)out, &ctx); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA256Full(uint8_t *in, uint8_t *out, uint32_t len) +{ + SHA256_CTX ctx; + + SHA256_Init(&ctx); + SHA256_Update(&ctx, in, len); + SHA256_Final(out, &ctx); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA384Full(uint8_t *in, uint8_t *out, uint32_t len) +{ + SHA384_CTX ctx; + + SHA384_Init(&ctx); + SHA384_Update(&ctx, in, len); + SHA384_Final(out, &ctx); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsHashSHA512Full(uint8_t *in, uint8_t *out, uint32_t len) +{ + SHA512_CTX ctx; + + SHA512_Init(&ctx); + SHA512_Update(&ctx, in, len); + SHA512_Final(out, &ctx); + + return CPA_STATUS_SUCCESS; +} + +#define BYTE_TO_BITS_SHIFT 3 + +CpaStatus +qatUtilsAESEncrypt(uint8_t *key, + uint32_t keyLenInBytes, + uint8_t *in, + uint8_t *out) +{ + rijndael_ctx ctx; + + rijndael_set_key(&ctx, key, keyLenInBytes << BYTE_TO_BITS_SHIFT); + rijndael_encrypt(&ctx, in, out); + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSemaphore.c b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSemaphore.c new file mode 100644 index 00000000000..5de928c2f05 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSemaphore.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_utils.h" + +#include +#include +#include +#include + +/* Define a 64 bit number */ +#define QAT_UTILS_MAX_LONG (0x7FFFFFFF) + +/* Max timeout in MS, used to guard against possible overflow */ +#define QAT_UTILS_MAX_TIMEOUT_MS (QAT_UTILS_MAX_LONG / hz) + +CpaStatus +qatUtilsSemaphoreInit(struct sema **pSid, uint32_t start_value) +{ + if (!pSid) + return CPA_STATUS_FAIL; + + *pSid = malloc(sizeof(struct sema), M_QAT, M_WAITOK); + + sema_init(*pSid, start_value, "qat sema"); + + return CPA_STATUS_SUCCESS; +} + +/** + * DESCRIPTION: If the semaphore is unset, the calling thread is blocked. + * If the semaphore is set, it is taken and control is returned + * to the caller. If the time indicated in 'timeout' is reached, + * the thread will unblock and return an error indication. If the + * timeout is set to 'QAT_UTILS_WAIT_NONE', the thread will never block; + * if it is set to 'QAT_UTILS_WAIT_FOREVER', the thread will block until + * the semaphore is available. + * + * + */ + +CpaStatus +qatUtilsSemaphoreWait(struct sema **pSid, int32_t timeout) +{ + + CpaStatus Status = CPA_STATUS_SUCCESS; + unsigned long timeoutTime; + + if (!pSid) + return CPA_STATUS_FAIL; + /* + * Guard against illegal timeout values + */ + if ((timeout < 0) && (timeout != QAT_UTILS_WAIT_FOREVER)) { + QAT_UTILS_LOG( + "QatUtilsSemaphoreWait(): illegal timeout value\n"); + return CPA_STATUS_FAIL; + } else if (timeout > QAT_UTILS_MAX_TIMEOUT_MS) { + QAT_UTILS_LOG( + "QatUtilsSemaphoreWait(): use a smaller timeout value to avoid overflow.\n"); + return CPA_STATUS_FAIL; + } + + if (timeout == QAT_UTILS_WAIT_FOREVER) { + sema_wait(*pSid); + } else if (timeout == QAT_UTILS_WAIT_NONE) { + if (sema_trywait(*pSid)) { + Status = CPA_STATUS_FAIL; + } + } else { + /* Convert timeout in milliseconds to HZ */ + timeoutTime = timeout * hz / 1000; + if (sema_timedwait(*pSid, timeoutTime)) { + Status = CPA_STATUS_FAIL; + } + } /* End of if */ + + return Status; +} + +CpaStatus +qatUtilsSemaphoreTryWait(struct sema **pSid) +{ + if (!pSid) + return CPA_STATUS_FAIL; + if (sema_trywait(*pSid)) { + return CPA_STATUS_FAIL; + } + return CPA_STATUS_SUCCESS; +} + +/** + * + * DESCRIPTION: This function causes the next available thread in the pend queue + * to be unblocked. If no thread is pending on this semaphore, the + * semaphore becomes 'full'. + */ +CpaStatus +qatUtilsSemaphorePost(struct sema **pSid) +{ + if (!pSid) + return CPA_STATUS_FAIL; + sema_post(*pSid); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsSemaphoreDestroy(struct sema **pSid) +{ + if (!pSid) + return CPA_STATUS_FAIL; + + sema_destroy(*pSid); + free(*pSid, M_QAT); + + return CPA_STATUS_SUCCESS; +} + +/**************************** + * Mutex + ****************************/ + +CpaStatus +qatUtilsMutexInit(struct mtx **pMutex) +{ + if (!pMutex) + return CPA_STATUS_FAIL; + *pMutex = malloc(sizeof(struct mtx), M_QAT, M_WAITOK); + + memset(*pMutex, 0, sizeof(struct mtx)); + + mtx_init(*pMutex, "qat mtx", NULL, MTX_DEF); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsMutexLock(struct mtx **pMutex, int32_t timeout) +{ + if (!pMutex) + return CPA_STATUS_FAIL; + if (timeout != QAT_UTILS_WAIT_FOREVER) { + QAT_UTILS_LOG("QatUtilsMutexLock(): Illegal timeout value\n"); + return CPA_STATUS_FAIL; + } + + mtx_lock(*pMutex); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsMutexUnlock(struct mtx **pMutex) +{ + if (!pMutex || !(*pMutex)) + return CPA_STATUS_FAIL; + mtx_unlock(*pMutex); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsMutexDestroy(struct mtx **pMutex) +{ + if (!pMutex || !(*pMutex)) + return CPA_STATUS_FAIL; + mtx_destroy(*pMutex); + free(*pMutex, M_QAT); + *pMutex = NULL; + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/qat_utils/src/QatUtilsServices.c b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsServices.c new file mode 100644 index 00000000000..bc2806e57df --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsServices.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Private data structure + * + * Data struct to store the information on the + * memory allocated. This structure is stored at the beginning of + * the allocated chunck of memory + * size is the no of byte passed to the memory allocation functions + * mSize is the real size of the memory required to the OS + * + * +----------------------------+--------------------------------+ + * | QatUtilsMemAllocInfoStruct | memory returned to user (size) | + * +----------------------------+--------------------------------+ + * ^ ^ + * mAllocMemPtr Ptr returned to the caller of MemAlloc* + * + */ + +typedef struct _QatUtilsMemAllocInfoStruct { + void *mAllocMemPtr; /* memory addr returned by the kernel */ + uint32_t mSize; /* allocated size */ +} QatUtilsMemAllocInfoStruct; + +/************************************** + * Memory functions + *************************************/ +void * +qatUtilsMemAllocContiguousNUMA(uint32_t size, uint32_t node, uint32_t alignment) +{ + void *ptr = NULL; + void *pRet = NULL; + uint32_t alignment_offset = 0; + + QatUtilsMemAllocInfoStruct memInfo = { 0 }; + if (size == 0 || alignment < 1) { + QAT_UTILS_LOG( + "QatUtilsMemAllocNUMA: size or alignment are zero.\n"); + return NULL; + } + if (alignment & (alignment - 1)) { + QAT_UTILS_LOG( + "QatUtilsMemAllocNUMA: Expecting alignment of a power.\n"); + return NULL; + } + + memInfo.mSize = size + alignment + sizeof(QatUtilsMemAllocInfoStruct); + ptr = contigmalloc(memInfo.mSize, M_QAT, M_WAITOK, 0, ~1UL, 64, 0); + + memInfo.mAllocMemPtr = ptr; + pRet = + (char *)memInfo.mAllocMemPtr + sizeof(QatUtilsMemAllocInfoStruct); +#ifdef __x86_64__ + alignment_offset = (uint64_t)pRet % alignment; +#else + alignment_offset = (uint32_t)pRet % alignment; +#endif + pRet = (char *)pRet + (alignment - alignment_offset); + memcpy(((char *)pRet) - sizeof(QatUtilsMemAllocInfoStruct), + &memInfo, + sizeof(QatUtilsMemAllocInfoStruct)); + + return pRet; +} + +void +qatUtilsMemFreeNUMA(void *ptr) +{ + QatUtilsMemAllocInfoStruct *memInfo = NULL; + + memInfo = + (QatUtilsMemAllocInfoStruct *)((int8_t *)ptr - + sizeof(QatUtilsMemAllocInfoStruct)); + if (memInfo->mSize == 0 || memInfo->mAllocMemPtr == NULL) { + QAT_UTILS_LOG( + "QatUtilsMemAlignedFree: Detected corrupted data: memory leak!\n"); + return; + } + contigfree(memInfo->mAllocMemPtr, memInfo->mSize, M_QAT); +} + +CpaStatus +qatUtilsSleep(uint32_t milliseconds) +{ + if (milliseconds != 0) { + pause("qatUtils sleep", milliseconds * hz / (1000)); + } else { + sched_relinquish(curthread); + } + return CPA_STATUS_SUCCESS; +} + +void +qatUtilsYield(void) +{ + sched_relinquish(curthread); +} diff --git a/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSpinLock.c b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSpinLock.c new file mode 100644 index 00000000000..575415a74e3 --- /dev/null +++ b/sys/dev/qat/qat_api/qat_utils/src/QatUtilsSpinLock.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_utils.h" +#include + +CpaStatus +qatUtilsLockInit(struct mtx *pLock) +{ + if (!pLock) + return CPA_STATUS_FAIL; + memset(pLock, 0, sizeof(*pLock)); + mtx_init(pLock, "qat spin", NULL, MTX_DEF | MTX_DUPOK); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsLock(struct mtx *pLock) +{ + if (!pLock) + return CPA_STATUS_FAIL; + mtx_lock(pLock); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsUnlock(struct mtx *pLock) +{ + if (!pLock) + return CPA_STATUS_FAIL; + mtx_unlock(pLock); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +qatUtilsLockDestroy(struct mtx *pLock) +{ + if (!pLock) + return CPA_STATUS_FAIL; + mtx_destroy(pLock); + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_common/adf_accel_engine.c b/sys/dev/qat/qat_common/adf_accel_engine.c new file mode 100644 index 00000000000..3b41ab5764e --- /dev/null +++ b/sys/dev/qat/qat_common/adf_accel_engine.c @@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include "adf_cfg.h" +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "icp_qat_uclo.h" +#include "icp_qat_hw.h" + +#define MMP_VERSION_LEN 4 + +struct adf_mmp_version_s { + u8 ver_val[MMP_VERSION_LEN]; +}; + +static int +request_firmware(const struct firmware **firmware_p, const char *name) +{ + int retval = 0; + if (NULL == firmware_p) { + return -1; + } + *firmware_p = firmware_get(name); + if (NULL == *firmware_p) { + retval = -1; + } + return retval; +} + +int +adf_ae_fw_load(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + const void *fw_addr, *mmp_addr; + u32 fw_size, mmp_size; + s32 i = 0; + u32 max_objs = 1; + const char *obj_name = NULL; + struct adf_mmp_version_s mmp_ver = { { 0 } }; + unsigned int cfg_ae_mask = 0; + + if (!hw_device->fw_name) + return 0; + + if (request_firmware(&loader_data->uof_fw, hw_device->fw_name)) { + device_printf(GET_DEV(accel_dev), + "Failed to load UOF FW %s\n", + hw_device->fw_name); + goto out_err; + } + + if (request_firmware(&loader_data->mmp_fw, hw_device->fw_mmp_name)) { + device_printf(GET_DEV(accel_dev), + "Failed to load MMP FW %s\n", + hw_device->fw_mmp_name); + goto out_err; + } + + fw_size = loader_data->uof_fw->datasize; + fw_addr = loader_data->uof_fw->data; + mmp_size = loader_data->mmp_fw->datasize; + mmp_addr = loader_data->mmp_fw->data; + + memcpy(&mmp_ver, mmp_addr, MMP_VERSION_LEN); + + accel_dev->fw_versions.mmp_version_major = mmp_ver.ver_val[0]; + accel_dev->fw_versions.mmp_version_minor = mmp_ver.ver_val[1]; + accel_dev->fw_versions.mmp_version_patch = mmp_ver.ver_val[2]; + + if (hw_device->accel_capabilities_mask & + ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) + if (qat_uclo_wr_mimage(loader_data->fw_loader, + mmp_addr, + mmp_size)) { + device_printf(GET_DEV(accel_dev), + "Failed to load MMP\n"); + goto out_err; + } + + if (hw_device->get_objs_num) + max_objs = hw_device->get_objs_num(accel_dev); + + for (i = max_objs - 1; i >= 0; i--) { + /* obj_name is used to indicate the firmware name in MOF, + * config unit0 must be loaded at end for authentication + */ + if (hw_device->get_obj_name && hw_device->get_obj_cfg_ae_mask) { + unsigned long service_mask = hw_device->service_mask; + + if (hw_device->service_mask && + !(test_bit(i, &service_mask))) + continue; + obj_name = hw_device->get_obj_name(accel_dev, BIT(i)); + if (!obj_name) { + device_printf( + GET_DEV(accel_dev), + "Invalid object (service = %lx)\n", + BIT(i)); + goto out_err; + } + if (!hw_device->get_obj_cfg_ae_mask(accel_dev, BIT(i))) + continue; + cfg_ae_mask = + hw_device->get_obj_cfg_ae_mask(accel_dev, BIT(i)); + if (qat_uclo_set_cfg_ae_mask(loader_data->fw_loader, + cfg_ae_mask)) { + device_printf(GET_DEV(accel_dev), + "Invalid config AE mask\n"); + goto out_err; + } + } + + if (qat_uclo_map_obj( + loader_data->fw_loader, fw_addr, fw_size, obj_name)) { + device_printf(GET_DEV(accel_dev), + "Failed to map UOF firmware\n"); + goto out_err; + } + if (qat_uclo_wr_all_uimage(loader_data->fw_loader)) { + device_printf(GET_DEV(accel_dev), + "Failed to load UOF firmware\n"); + goto out_err; + } + qat_uclo_del_obj(loader_data->fw_loader); + obj_name = NULL; + } + + return 0; + +out_err: + adf_ae_fw_release(accel_dev); + return EFAULT; +} + +void +adf_ae_fw_release(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + if (!hw_device->fw_name) + return; + if (loader_data->fw_loader) + qat_uclo_del_obj(loader_data->fw_loader); + if (loader_data->fw_loader && loader_data->fw_loader->mobj_handle) + qat_uclo_del_mof(loader_data->fw_loader); + qat_hal_deinit(loader_data->fw_loader); + if (loader_data->uof_fw) + firmware_put(loader_data->uof_fw, FIRMWARE_UNLOAD); + if (loader_data->mmp_fw) + firmware_put(loader_data->mmp_fw, FIRMWARE_UNLOAD); + loader_data->uof_fw = NULL; + loader_data->mmp_fw = NULL; + loader_data->fw_loader = NULL; +} + +int +adf_ae_start(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev); + + if (!hw_data->fw_name) + return 0; + + for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) { + if (hw_data->ae_mask & (1 << ae)) { + qat_hal_start(loader_data->fw_loader, ae, 0xFF); + ae_ctr++; + } + } + device_printf(GET_DEV(accel_dev), + "qat_dev%d started %d acceleration engines\n", + accel_dev->accel_id, + ae_ctr); + return 0; +} + +int +adf_ae_stop(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev); + + if (!hw_data->fw_name) + return 0; + + for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) { + if (hw_data->ae_mask & (1 << ae)) { + qat_hal_stop(loader_data->fw_loader, ae, 0xFF); + ae_ctr++; + } + } + device_printf(GET_DEV(accel_dev), + "qat_dev%d stopped %d acceleration engines\n", + accel_dev->accel_id, + ae_ctr); + return 0; +} + +static int +adf_ae_reset(struct adf_accel_dev *accel_dev, int ae) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + + qat_hal_reset(loader_data->fw_loader); + if (qat_hal_clr_reset(loader_data->fw_loader)) + return EFAULT; + + return 0; +} + +int +adf_ae_init(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + if (!hw_device->fw_name) + return 0; + + loader_data = malloc(sizeof(*loader_data), M_QAT, M_WAITOK | M_ZERO); + + accel_dev->fw_loader = loader_data; + if (qat_hal_init(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Failed to init the AEs\n"); + free(loader_data, M_QAT); + return EFAULT; + } + if (adf_ae_reset(accel_dev, 0)) { + device_printf(GET_DEV(accel_dev), "Failed to reset the AEs\n"); + qat_hal_deinit(loader_data->fw_loader); + free(loader_data, M_QAT); + return EFAULT; + } + return 0; +} + +int +adf_ae_shutdown(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_loader_data *loader_data = accel_dev->fw_loader; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + if (!hw_device->fw_name) + return 0; + + qat_hal_deinit(loader_data->fw_loader); + free(accel_dev->fw_loader, M_QAT); + accel_dev->fw_loader = NULL; + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_aer.c b/sys/dev/qat/qat_common/adf_aer.c new file mode 100644 index 00000000000..9ac7c8edd72 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_aer.c @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include +#include + +#define ADF_PPAERUCM_MASK (BIT(14) | BIT(20) | BIT(22)) + +static struct workqueue_struct *fatal_error_wq; +struct adf_fatal_error_data { + struct adf_accel_dev *accel_dev; + struct work_struct work; +}; + +static struct workqueue_struct *device_reset_wq; + +void +linux_complete_common(struct completion *c, int all) +{ + int wakeup_swapper; + + sleepq_lock(c); + c->done++; + if (all) + wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0); + else + wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0); + sleepq_release(c); + if (wakeup_swapper) + kick_proc0(); +} + +/* reset dev data */ +struct adf_reset_dev_data { + int mode; + struct adf_accel_dev *accel_dev; + struct completion compl; + struct work_struct reset_work; +}; + +int +adf_aer_store_ppaerucm_reg(device_t dev, struct adf_hw_device_data *hw_data) +{ + unsigned int aer_offset, reg_val = 0; + + if (!hw_data) + return -EINVAL; + + if (pci_find_extcap(dev, PCIZ_AER, &aer_offset) == 0) { + reg_val = + pci_read_config(dev, aer_offset + PCIR_AER_UC_MASK, 4); + + hw_data->aerucm_mask = reg_val; + } else { + device_printf(dev, + "Unable to find AER capability of the device\n"); + return -ENODEV; + } + + return 0; +} + +void +adf_reset_sbr(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_to_pci_dev(accel_dev); + device_t parent = device_get_parent(device_get_parent(pdev)); + uint16_t bridge_ctl = 0; + + if (accel_dev->is_vf) + return; + + if (!parent) + parent = pdev; + + if (!pcie_wait_for_pending_transactions(pdev, 0)) + device_printf(GET_DEV(accel_dev), + "Transaction still in progress. Proceeding\n"); + + device_printf(GET_DEV(accel_dev), "Secondary bus reset\n"); + + pci_save_state(pdev); + bridge_ctl = pci_read_config(parent, PCIR_BRIDGECTL_1, 2); + bridge_ctl |= PCIB_BCR_SECBUS_RESET; + pci_write_config(parent, PCIR_BRIDGECTL_1, bridge_ctl, 2); + pause_ms("adfrst", 100); + bridge_ctl &= ~PCIB_BCR_SECBUS_RESET; + pci_write_config(parent, PCIR_BRIDGECTL_1, bridge_ctl, 2); + pause_ms("adfrst", 100); + pci_restore_state(pdev); +} + +void +adf_reset_flr(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_to_pci_dev(accel_dev); + + pci_save_state(pdev); + if (pcie_flr(pdev, + max(pcie_get_max_completion_timeout(pdev) / 1000, 10), + true)) { + pci_restore_state(pdev); + return; + } + pci_restore_state(pdev); + device_printf(GET_DEV(accel_dev), + "FLR qat_dev%d failed trying secondary bus reset\n", + accel_dev->accel_id); + adf_reset_sbr(accel_dev); +} + +void +adf_dev_pre_reset(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + device_t pdev = accel_to_pci_dev(accel_dev); + u32 aer_offset, reg_val = 0; + + if (pci_find_extcap(pdev, PCIZ_AER, &aer_offset) == 0) { + reg_val = + pci_read_config(pdev, aer_offset + PCIR_AER_UC_MASK, 4); + reg_val |= ADF_PPAERUCM_MASK; + pci_write_config(pdev, + aer_offset + PCIR_AER_UC_MASK, + reg_val, + 4); + } else { + device_printf(pdev, + "Unable to find AER capability of the device\n"); + } + + if (hw_device->disable_arb) { + device_printf(GET_DEV(accel_dev), "Disable arbiter.\n"); + hw_device->disable_arb(accel_dev); + } +} + +void +adf_dev_post_reset(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + device_t pdev = accel_to_pci_dev(accel_dev); + u32 aer_offset; + + if (pci_find_extcap(pdev, PCIZ_AER, &aer_offset) == 0) { + pci_write_config(pdev, + aer_offset + PCIR_AER_UC_MASK, + hw_device->aerucm_mask, + 4); + } else { + device_printf(pdev, + "Unable to find AER capability of the device\n"); + } +} + +void +adf_dev_restore(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + device_t pdev = accel_to_pci_dev(accel_dev); + + if (hw_device->pre_reset) { + dev_dbg(GET_DEV(accel_dev), "Performing pre reset save\n"); + hw_device->pre_reset(accel_dev); + } + + if (hw_device->reset_device) { + device_printf(GET_DEV(accel_dev), + "Resetting device qat_dev%d\n", + accel_dev->accel_id); + hw_device->reset_device(accel_dev); + pci_restore_state(pdev); + pci_save_state(pdev); + } + + if (hw_device->post_reset) { + dev_dbg(GET_DEV(accel_dev), "Performing post reset restore\n"); + hw_device->post_reset(accel_dev); + } +} + +static void +adf_device_reset_worker(struct work_struct *work) +{ + struct adf_reset_dev_data *reset_data = + container_of(work, struct adf_reset_dev_data, reset_work); + struct adf_accel_dev *accel_dev = reset_data->accel_dev; + + if (adf_dev_restarting_notify(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Unable to send RESTARTING notification.\n"); + return; + } + + if (adf_dev_stop(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Stopping device failed.\n"); + return; + } + + adf_dev_shutdown(accel_dev); + + if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) { + /* The device hanged and we can't restart it */ + /* so stop here */ + device_printf(GET_DEV(accel_dev), "Restart device failed\n"); + if (reset_data->mode == ADF_DEV_RESET_ASYNC) + kfree(reset_data); + WARN(1, "QAT: device restart failed. Device is unusable\n"); + return; + } + + adf_dev_restarted_notify(accel_dev); + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + + /* The dev is back alive. Notify the caller if in sync mode */ + if (reset_data->mode == ADF_DEV_RESET_SYNC) + complete(&reset_data->compl); + else + kfree(reset_data); +} + +int +adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev, + enum adf_dev_reset_mode mode) +{ + struct adf_reset_dev_data *reset_data; + if (!adf_dev_started(accel_dev) || + test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) + return 0; + set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + reset_data = kzalloc(sizeof(*reset_data), GFP_ATOMIC); + if (!reset_data) + return -ENOMEM; + reset_data->accel_dev = accel_dev; + init_completion(&reset_data->compl); + reset_data->mode = mode; + INIT_WORK(&reset_data->reset_work, adf_device_reset_worker); + queue_work(device_reset_wq, &reset_data->reset_work); + /* If in sync mode wait for the result */ + if (mode == ADF_DEV_RESET_SYNC) { + int ret = 0; + /* Maximum device reset time is 10 seconds */ + unsigned long wait_jiffies = msecs_to_jiffies(10000); + unsigned long timeout = + wait_for_completion_timeout(&reset_data->compl, + wait_jiffies); + if (!timeout) { + device_printf(GET_DEV(accel_dev), + "Reset device timeout expired\n"); + ret = -EFAULT; + } + kfree(reset_data); + return ret; + } + return 0; +} + +int +adf_dev_autoreset(struct adf_accel_dev *accel_dev) +{ + if (accel_dev->autoreset_on_error) + return adf_dev_reset(accel_dev, ADF_DEV_RESET_ASYNC); + return 0; +} + +static void +adf_notify_fatal_error_work(struct work_struct *work) +{ + struct adf_fatal_error_data *wq_data = + container_of(work, struct adf_fatal_error_data, work); + struct adf_accel_dev *accel_dev = wq_data->accel_dev; + + adf_error_notifier((uintptr_t)accel_dev); + if (!accel_dev->is_vf) { + if (accel_dev->u1.pf.vf_info) + adf_pf2vf_notify_fatal_error(accel_dev); + adf_dev_autoreset(accel_dev); + } + + kfree(wq_data); +} + +int +adf_notify_fatal_error(struct adf_accel_dev *accel_dev) +{ + struct adf_fatal_error_data *wq_data; + + wq_data = kzalloc(sizeof(*wq_data), GFP_ATOMIC); + if (!wq_data) { + device_printf(GET_DEV(accel_dev), + "Failed to allocate memory\n"); + return ENOMEM; + } + wq_data->accel_dev = accel_dev; + + INIT_WORK(&wq_data->work, adf_notify_fatal_error_work); + queue_work(fatal_error_wq, &wq_data->work); + + return 0; +} + +int __init +adf_init_fatal_error_wq(void) +{ + fatal_error_wq = create_workqueue("qat_fatal_error_wq"); + return !fatal_error_wq ? EFAULT : 0; +} + +void +adf_exit_fatal_error_wq(void) +{ + if (fatal_error_wq) + destroy_workqueue(fatal_error_wq); + fatal_error_wq = NULL; +} + +int +adf_init_aer(void) +{ + device_reset_wq = create_workqueue("qat_device_reset_wq"); + return !device_reset_wq ? -EFAULT : 0; +} + +void +adf_exit_aer(void) +{ + if (device_reset_wq) + destroy_workqueue(device_reset_wq); + device_reset_wq = NULL; +} diff --git a/sys/dev/qat/qat_common/adf_cfg.c b/sys/dev/qat/qat_common/adf_cfg.c new file mode 100644 index 00000000000..1f6cf6c1732 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg.c @@ -0,0 +1,574 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_accel_devices.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_cfg_dev_dbg.h" +#include "adf_heartbeat_dbg.h" +#include "adf_ver_dbg.h" +#include "adf_fw_counters.h" +#include "adf_cnvnr_freq_counters.h" + +/** + * adf_cfg_dev_add() - Create an acceleration device configuration table. + * @accel_dev: Pointer to acceleration device. + * + * Function creates a configuration table for the given acceleration device. + * The table stores device specific config values. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_cfg_dev_add(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data; + + dev_cfg_data = malloc(sizeof(*dev_cfg_data), M_QAT, M_WAITOK | M_ZERO); + INIT_LIST_HEAD(&dev_cfg_data->sec_list); + sx_init(&dev_cfg_data->lock, "qat cfg data"); + accel_dev->cfg = dev_cfg_data; + + if (adf_cfg_dev_dbg_add(accel_dev)) + goto err; + if (!accel_dev->is_vf) { + if (adf_heartbeat_dbg_add(accel_dev)) + goto err; + + if (adf_ver_dbg_add(accel_dev)) + goto err; + + if (adf_fw_counters_add(accel_dev)) + goto err; + + if (adf_cnvnr_freq_counters_add(accel_dev)) + goto err; + } + return 0; + +err: + free(dev_cfg_data, M_QAT); + accel_dev->cfg = NULL; + return EFAULT; +} + +static void adf_cfg_section_del_all(struct list_head *head); + +void +adf_cfg_del_all(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + sx_xlock(&dev_cfg_data->lock); + adf_cfg_section_del_all(&dev_cfg_data->sec_list); + sx_xunlock(&dev_cfg_data->lock); + clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); +} + +void +adf_cfg_depot_del_all(struct list_head *head) +{ + adf_cfg_section_del_all(head); +} + +/** + * adf_cfg_dev_remove() - Clears acceleration device configuration table. + * @accel_dev: Pointer to acceleration device. + * + * Function removes configuration table from the given acceleration device + * and frees all allocated memory. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_cfg_dev_remove(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + if (!dev_cfg_data) + return; + + sx_xlock(&dev_cfg_data->lock); + adf_cfg_section_del_all(&dev_cfg_data->sec_list); + sx_xunlock(&dev_cfg_data->lock); + + adf_cfg_dev_dbg_remove(accel_dev); + if (!accel_dev->is_vf) { + adf_ver_dbg_del(accel_dev); + adf_heartbeat_dbg_del(accel_dev); + adf_fw_counters_remove(accel_dev); + adf_cnvnr_freq_counters_remove(accel_dev); + } + + free(dev_cfg_data, M_QAT); + accel_dev->cfg = NULL; +} + +static void +adf_cfg_keyval_add(struct adf_cfg_key_val *new, struct adf_cfg_section *sec) +{ + list_add_tail(&new->list, &sec->param_head); +} + +static void +adf_cfg_keyval_remove(const char *key, struct adf_cfg_section *sec) +{ + struct list_head *list_ptr, *tmp; + struct list_head *head = &sec->param_head; + + list_for_each_prev_safe(list_ptr, tmp, head) + { + struct adf_cfg_key_val *ptr = + list_entry(list_ptr, struct adf_cfg_key_val, list); + + if (strncmp(ptr->key, key, sizeof(ptr->key)) != 0) + continue; + + list_del(list_ptr); + free(ptr, M_QAT); + break; + } +} + +static int +adf_cfg_section_restore_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *cfg_depot_list) +{ + struct adf_cfg_section *ptr_sec, *iter_sec; + struct adf_cfg_key_val *ptr_key; + struct list_head *list, *tmp; + struct list_head *restore_list = &accel_dev->cfg->sec_list; + struct list_head *head = &cfg_depot_list[accel_dev->accel_id].sec_list; + + INIT_LIST_HEAD(restore_list); + + list_for_each_prev_safe(list, tmp, head) + { + ptr_sec = list_entry(list, struct adf_cfg_section, list); + iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO); + + strlcpy(iter_sec->name, ptr_sec->name, sizeof(iter_sec->name)); + + INIT_LIST_HEAD(&iter_sec->param_head); + + /* now we restore all the parameters */ + list_for_each_entry(ptr_key, &ptr_sec->param_head, list) + { + struct adf_cfg_key_val *key_val; + + key_val = + malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); + + memcpy(key_val, ptr_key, sizeof(*key_val)); + list_add_tail(&key_val->list, &iter_sec->param_head); + } + list_add_tail(&iter_sec->list, restore_list); + } + adf_cfg_section_del_all(head); + return 0; +} + +int +adf_cfg_depot_restore_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *cfg_depot_list) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + int ret = 0; + + sx_xlock(&dev_cfg_data->lock); + ret = adf_cfg_section_restore_all(accel_dev, cfg_depot_list); + sx_xunlock(&dev_cfg_data->lock); + + return ret; +} + +/** + * adf_cfg_section_del() - Delete config section entry to config table. + * @accel_dev: Pointer to acceleration device. + * @name: Name of the section + * + * Function deletes configuration section where key - value entries + * will be stored. + * To be used by QAT device specific drivers. + */ +static void +adf_cfg_section_del(struct adf_accel_dev *accel_dev, const char *name) +{ + struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); + + if (!sec) + return; + adf_cfg_keyval_del_all(&sec->param_head); + list_del(&sec->list); + free(sec, M_QAT); +} + +void +adf_cfg_keyval_del_all(struct list_head *head) +{ + struct list_head *list_ptr, *tmp; + + list_for_each_prev_safe(list_ptr, tmp, head) + { + struct adf_cfg_key_val *ptr = + list_entry(list_ptr, struct adf_cfg_key_val, list); + list_del(list_ptr); + free(ptr, M_QAT); + } +} + +static void +adf_cfg_section_del_all(struct list_head *head) +{ + struct adf_cfg_section *ptr; + struct list_head *list, *tmp; + + list_for_each_prev_safe(list, tmp, head) + { + ptr = list_entry(list, struct adf_cfg_section, list); + adf_cfg_keyval_del_all(&ptr->param_head); + list_del(list); + free(ptr, M_QAT); + } +} + +static struct adf_cfg_key_val * +adf_cfg_key_value_find(struct adf_cfg_section *s, const char *key) +{ + struct list_head *list; + + list_for_each(list, &s->param_head) + { + struct adf_cfg_key_val *ptr = + list_entry(list, struct adf_cfg_key_val, list); + if (!strncmp(ptr->key, key, sizeof(ptr->key))) + return ptr; + } + return NULL; +} + +struct adf_cfg_section * +adf_cfg_sec_find(struct adf_accel_dev *accel_dev, const char *sec_name) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct list_head *list; + + list_for_each(list, &cfg->sec_list) + { + struct adf_cfg_section *ptr = + list_entry(list, struct adf_cfg_section, list); + if (!strncmp(ptr->name, sec_name, sizeof(ptr->name))) + return ptr; + } + return NULL; +} + +static int +adf_cfg_key_val_get(struct adf_accel_dev *accel_dev, + const char *sec_name, + const char *key_name, + char *val) +{ + struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name); + struct adf_cfg_key_val *keyval = NULL; + + if (sec) + keyval = adf_cfg_key_value_find(sec, key_name); + if (keyval) { + memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + return 0; + } + return -1; +} + +/** + * adf_cfg_add_key_value_param() - Add key-value config entry to config table. + * @accel_dev: Pointer to acceleration device. + * @section_name: Name of the section where the param will be added + * @key: The key string + * @val: Value pain for the given @key + * @type: Type - string, int or address + * + * Function adds configuration key - value entry in the appropriate section + * in the given acceleration device + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const char *key, + const void *val, + enum adf_cfg_val_type type) +{ + char temp_val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_key_val *key_val; + struct adf_cfg_section *section = + adf_cfg_sec_find(accel_dev, section_name); + if (!section) + return EFAULT; + + key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); + + INIT_LIST_HEAD(&key_val->list); + strlcpy(key_val->key, key, sizeof(key_val->key)); + + if (type == ADF_DEC) { + snprintf(key_val->val, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%ld", + (*((const long *)val))); + } else if (type == ADF_STR) { + strlcpy(key_val->val, (const char *)val, sizeof(key_val->val)); + } else if (type == ADF_HEX) { + snprintf(key_val->val, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "0x%lx", + (unsigned long)val); + } else { + device_printf(GET_DEV(accel_dev), "Unknown type given.\n"); + free(key_val, M_QAT); + return -1; + } + key_val->type = type; + + /* Add the key-value pair as below policy: + * 1. If the key doesn't exist, add it, + * 2. If the key already exists with a different value + * then delete it, + * 3. If the key exists with the same value, then return + * without doing anything. + */ + if (adf_cfg_key_val_get(accel_dev, section_name, key, temp_val) == 0) { + if (strncmp(temp_val, key_val->val, sizeof(temp_val)) != 0) { + adf_cfg_keyval_remove(key, section); + } else { + free(key_val, M_QAT); + return 0; + } + } + + sx_xlock(&cfg->lock); + adf_cfg_keyval_add(key_val, section); + sx_xunlock(&cfg->lock); + return 0; +} + +int +adf_cfg_save_section(struct adf_accel_dev *accel_dev, + const char *name, + struct adf_cfg_section *section) +{ + struct adf_cfg_key_val *ptr; + struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); + + if (!sec) { + device_printf(GET_DEV(accel_dev), + "Couldn't find section %s\n", + name); + return EFAULT; + } + + strlcpy(section->name, name, sizeof(section->name)); + INIT_LIST_HEAD(§ion->param_head); + + /* now we save all the parameters */ + list_for_each_entry(ptr, &sec->param_head, list) + { + struct adf_cfg_key_val *key_val; + + key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); + + memcpy(key_val, ptr, sizeof(*key_val)); + list_add_tail(&key_val->list, §ion->param_head); + } + return 0; +} + +static int +adf_cfg_section_save_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *cfg_depot_list) +{ + struct adf_cfg_section *ptr_sec, *iter_sec; + struct list_head *list, *tmp, *save_list; + struct list_head *head = &accel_dev->cfg->sec_list; + + save_list = &cfg_depot_list[accel_dev->accel_id].sec_list; + + list_for_each_prev_safe(list, tmp, head) + { + ptr_sec = list_entry(list, struct adf_cfg_section, list); + iter_sec = malloc(sizeof(*iter_sec), M_QAT, M_WAITOK | M_ZERO); + + adf_cfg_save_section(accel_dev, ptr_sec->name, iter_sec); + list_add_tail(&iter_sec->list, save_list); + } + return 0; +} + +int +adf_cfg_depot_save_all(struct adf_accel_dev *accel_dev, + struct adf_cfg_depot_list *cfg_depot_list) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + int ret = 0; + + sx_xlock(&dev_cfg_data->lock); + ret = adf_cfg_section_save_all(accel_dev, cfg_depot_list); + sx_xunlock(&dev_cfg_data->lock); + + return ret; +} + +/** + * adf_cfg_remove_key_param() - remove config entry in config table. + * @accel_dev: Pointer to acceleration device. + * @section_name: Name of the section where the param will be added + * @key: The key string + * + * Function remove configuration key + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_cfg_remove_key_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const char *key) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_section *section = + adf_cfg_sec_find(accel_dev, section_name); + if (!section) + return EFAULT; + + sx_xlock(&cfg->lock); + adf_cfg_keyval_remove(key, section); + sx_xunlock(&cfg->lock); + return 0; +} + +/** + * adf_cfg_section_add() - Add config section entry to config table. + * @accel_dev: Pointer to acceleration device. + * @name: Name of the section + * + * Function adds configuration section where key - value entries + * will be stored. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name); + + if (sec) + return 0; + + sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO); + + strlcpy(sec->name, name, sizeof(sec->name)); + INIT_LIST_HEAD(&sec->param_head); + sx_xlock(&cfg->lock); + list_add_tail(&sec->list, &cfg->sec_list); + sx_xunlock(&cfg->lock); + return 0; +} + +/* need to differentiate derived section with the original section */ +int +adf_cfg_derived_section_add(struct adf_accel_dev *accel_dev, const char *name) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_section *sec = NULL; + + if (adf_cfg_section_add(accel_dev, name)) + return EFAULT; + + sec = adf_cfg_sec_find(accel_dev, name); + if (!sec) + return EFAULT; + + sx_xlock(&cfg->lock); + sec->is_derived = true; + sx_xunlock(&cfg->lock); + return 0; +} + +static int +adf_cfg_restore_key_value_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const char *key, + const char *val, + enum adf_cfg_val_type type) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + struct adf_cfg_key_val *key_val; + struct adf_cfg_section *section = + adf_cfg_sec_find(accel_dev, section_name); + if (!section) + return EFAULT; + + key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); + + INIT_LIST_HEAD(&key_val->list); + + strlcpy(key_val->key, key, sizeof(key_val->key)); + strlcpy(key_val->val, val, sizeof(key_val->val)); + key_val->type = type; + sx_xlock(&cfg->lock); + adf_cfg_keyval_add(key_val, section); + sx_xunlock(&cfg->lock); + return 0; +} + +int +adf_cfg_restore_section(struct adf_accel_dev *accel_dev, + struct adf_cfg_section *section) +{ + struct adf_cfg_key_val *ptr; + int ret = 0; + + ret = adf_cfg_section_add(accel_dev, section->name); + if (ret) + goto err; + + list_for_each_entry(ptr, §ion->param_head, list) + { + ret = adf_cfg_restore_key_value_param( + accel_dev, section->name, ptr->key, ptr->val, ptr->type); + if (ret) + goto err_remove_sec; + } + return 0; + +err_remove_sec: + adf_cfg_section_del(accel_dev, section->name); +err: + device_printf(GET_DEV(accel_dev), + "Failed to restore section %s\n", + section->name); + return ret; +} + +int +adf_cfg_get_param_value(struct adf_accel_dev *accel_dev, + const char *section, + const char *name, + char *value) +{ + struct adf_cfg_device_data *cfg = accel_dev->cfg; + int ret; + + sx_slock(&cfg->lock); + ret = adf_cfg_key_val_get(accel_dev, section, name, value); + sx_sunlock(&cfg->lock); + return ret; +} diff --git a/sys/dev/qat/qat_common/adf_cfg_bundle.c b/sys/dev/qat/qat_common/adf_cfg_bundle.c new file mode 100644 index 00000000000..edb2ef94241 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_bundle.c @@ -0,0 +1,377 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg_bundle.h" +#include "adf_cfg_strings.h" +#include "adf_cfg_instance.h" +#include + +static bool +adf_cfg_is_interrupt_mode(struct adf_cfg_bundle *bundle) +{ + return (bundle->polling_mode == ADF_CFG_RESP_EPOLL) || + (bundle->type == KERNEL && + (bundle->polling_mode != ADF_CFG_RESP_POLL)); +} + +static bool +adf_cfg_can_be_shared(struct adf_cfg_bundle *bundle, + const char *process_name, + int polling_mode) +{ + if (adf_cfg_is_free(bundle)) + return true; + + if (bundle->polling_mode != polling_mode) + return false; + + return !adf_cfg_is_interrupt_mode(bundle) || + !strncmp(process_name, + bundle->sections[0], + ADF_CFG_MAX_SECTION_LEN_IN_BYTES); +} + +bool +adf_cfg_is_free(struct adf_cfg_bundle *bundle) +{ + return bundle->type == FREE; +} + +struct adf_cfg_instance * +adf_cfg_get_free_instance(struct adf_cfg_device *device, + struct adf_cfg_bundle *bundle, + struct adf_cfg_instance *inst, + const char *process_name) +{ + int i = 0; + struct adf_cfg_instance *ret_instance = NULL; + + if (adf_cfg_can_be_shared(bundle, process_name, inst->polling_mode)) { + for (i = 0; i < device->instance_index; i++) { + /* + * the selected instance must match two criteria + * 1) instance is from the bundle + * 2) instance type is same + */ + if (bundle->number == device->instances[i]->bundle && + inst->stype == device->instances[i]->stype) { + ret_instance = device->instances[i]; + break; + } + /* + * no opportunity to match, + * quit the loop as early as possible + */ + if ((bundle->number + 1) == + device->instances[i]->bundle) + break; + } + } + + return ret_instance; +} + +int +adf_cfg_get_ring_pairs_from_bundle(struct adf_cfg_bundle *bundle, + struct adf_cfg_instance *inst, + const char *process_name, + struct adf_cfg_instance *bundle_inst) +{ + if (inst->polling_mode == ADF_CFG_RESP_POLL && + adf_cfg_is_interrupt_mode(bundle)) { + pr_err("Trying to get ring pairs for a non-interrupt"); + pr_err(" bundle from an interrupt bundle\n"); + return EFAULT; + } + + if (inst->stype != bundle_inst->stype) { + pr_err("Got an instance of different type (cy/dc) than the"); + pr_err(" one request\n"); + return EFAULT; + } + + if (strcmp(ADF_KERNEL_SEC, process_name) && + strcmp(ADF_KERNEL_SAL_SEC, process_name) && + inst->polling_mode != ADF_CFG_RESP_EPOLL && + inst->polling_mode != ADF_CFG_RESP_POLL) { + pr_err("User instance %s needs to be configured", inst->name); + pr_err(" with IsPolled 1 or 2 for poll and epoll mode,"); + pr_err(" respectively\n"); + return EFAULT; + } + + strlcpy(bundle->sections[bundle->section_index], + process_name, + ADF_CFG_MAX_STR_LEN); + bundle->section_index++; + + if (adf_cfg_is_free(bundle)) { + bundle->polling_mode = inst->polling_mode; + bundle->type = (!strcmp(ADF_KERNEL_SEC, process_name) || + !strcmp(ADF_KERNEL_SAL_SEC, process_name)) ? + KERNEL : + USER; + if (adf_cfg_is_interrupt_mode(bundle)) { + CPU_ZERO(&bundle->affinity_mask); + CPU_COPY(&inst->affinity_mask, &bundle->affinity_mask); + } + } + + switch (inst->stype) { + case CRYPTO: + inst->asym_tx = bundle_inst->asym_tx; + inst->asym_rx = bundle_inst->asym_rx; + inst->sym_tx = bundle_inst->sym_tx; + inst->sym_rx = bundle_inst->sym_rx; + break; + case COMP: + inst->dc_tx = bundle_inst->dc_tx; + inst->dc_rx = bundle_inst->dc_rx; + break; + case ASYM: + inst->asym_tx = bundle_inst->asym_tx; + inst->asym_rx = bundle_inst->asym_rx; + break; + case SYM: + inst->sym_tx = bundle_inst->sym_tx; + inst->sym_rx = bundle_inst->sym_rx; + break; + default: + /* unknown service type of instance */ + pr_err("1 Unknown service type %d of instance\n", inst->stype); + } + + /* mark it as used */ + bundle_inst->stype = USED; + + inst->bundle = bundle->number; + + return 0; +} + +static void +adf_cfg_init_and_insert_inst(struct adf_cfg_bundle *bundle, + struct adf_cfg_device *device, + int bank_num, + struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_instance *cfg_instance = NULL; + int ring_pair_index = 0; + int i = 0; + u8 serv_type; + int num_req_rings = bundle->num_of_rings / 2; + int num_rings_per_srv = num_req_rings / ADF_CFG_NUM_SERVICES; + u16 ring_to_svc_map = GET_HW_DATA(accel_dev)->ring_to_svc_map; + + /* init the bundle with instance information */ + for (ring_pair_index = 0; ring_pair_index < ADF_CFG_NUM_SERVICES; + ring_pair_index++) { + serv_type = GET_SRV_TYPE(ring_to_svc_map, ring_pair_index); + for (i = 0; i < num_rings_per_srv; i++) { + cfg_instance = malloc(sizeof(*cfg_instance), + M_QAT, + M_WAITOK | M_ZERO); + + switch (serv_type) { + case CRYPTO: + crypto_instance_init(cfg_instance, bundle); + break; + case COMP: + dc_instance_init(cfg_instance, bundle); + break; + case ASYM: + asym_instance_init(cfg_instance, bundle); + break; + case SYM: + sym_instance_init(cfg_instance, bundle); + break; + case NA: + break; + + default: + /* Unknown service type */ + device_printf( + GET_DEV(accel_dev), + "Unknown service type %d of instance, mask is 0x%x\n", + serv_type, + ring_to_svc_map); + } + cfg_instance->bundle = bank_num; + device->instances[device->instance_index++] = + cfg_instance; + cfg_instance = NULL; + } + if (serv_type == CRYPTO) { + ring_pair_index++; + serv_type = + GET_SRV_TYPE(ring_to_svc_map, ring_pair_index); + } + } + + return; +} + +int +adf_cfg_bundle_init(struct adf_cfg_bundle *bundle, + struct adf_cfg_device *device, + int bank_num, + struct adf_accel_dev *accel_dev) +{ + int i = 0; + + /* init ring to service mapping for this bundle */ + adf_cfg_init_ring2serv_mapping(accel_dev, bundle); + + /* init the bundle with instance information */ + adf_cfg_init_and_insert_inst(bundle, device, bank_num, accel_dev); + + CPU_FILL(&bundle->affinity_mask); + bundle->type = FREE; + bundle->polling_mode = -1; + bundle->section_index = 0; + bundle->number = bank_num; + + bundle->sections = malloc(sizeof(char *) * bundle->max_section, + M_QAT, + M_WAITOK | M_ZERO); + + for (i = 0; i < bundle->max_section; i++) { + bundle->sections[i] = + malloc(ADF_CFG_MAX_STR_LEN, M_QAT, M_WAITOK | M_ZERO); + } + return 0; +} + +void +adf_cfg_bundle_clear(struct adf_cfg_bundle *bundle, + struct adf_accel_dev *accel_dev) +{ + int i = 0; + + for (i = 0; i < bundle->max_section; i++) { + if (bundle->sections && bundle->sections[i]) { + free(bundle->sections[i], M_QAT); + bundle->sections[i] = NULL; + } + } + + free(bundle->sections, M_QAT); + bundle->sections = NULL; + + adf_cfg_rel_ring2serv_mapping(bundle); +} + +static void +adf_cfg_assign_serv_to_rings(struct adf_cfg_bundle *bundle, u16 ring_to_svc_map) +{ + int ring_pair_index = 0; + int ring_index = 0; + u8 serv_type = 0; + int num_req_rings = bundle->num_of_rings / 2; + int num_rings_per_srv = num_req_rings / ADF_CFG_NUM_SERVICES; + + for (ring_pair_index = 0; ring_pair_index < ADF_CFG_NUM_SERVICES; + ring_pair_index++) { + serv_type = GET_SRV_TYPE(ring_to_svc_map, ring_pair_index); + ring_index = num_rings_per_srv * ring_pair_index; + switch (serv_type) { + case CRYPTO: + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_ASYM, + num_rings_per_srv); + ring_pair_index++; + ring_index = num_rings_per_srv * ring_pair_index; + if (ring_pair_index == ADF_CFG_NUM_SERVICES) + break; + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_SYM, + num_rings_per_srv); + break; + case COMP: + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_DC, + num_rings_per_srv); + break; + case SYM: + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_SYM, + num_rings_per_srv); + break; + case ASYM: + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_ASYM, + num_rings_per_srv); + break; + case NA: + ASSIGN_SERV_TO_RINGS(bundle, + ring_index, + num_req_rings, + ADF_ACCEL_SERV_NA, + num_rings_per_srv); + break; + + default: + /* unknown service type */ + pr_err("Unknown service type %d, mask 0x%x.\n", + serv_type, + ring_to_svc_map); + } + } + + return; +} + +void +adf_cfg_init_ring2serv_mapping(struct adf_accel_dev *accel_dev, + struct adf_cfg_bundle *bundle) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_cfg_ring *ring_in_bundle; + int ring_num = 0; + + bundle->num_of_rings = hw_data->num_rings_per_bank; + + bundle->rings = + malloc(bundle->num_of_rings * sizeof(struct adf_cfg_ring *), + M_QAT, + M_WAITOK | M_ZERO); + + for (ring_num = 0; ring_num < bundle->num_of_rings; ring_num++) { + ring_in_bundle = malloc(sizeof(struct adf_cfg_ring), + M_QAT, + M_WAITOK | M_ZERO); + ring_in_bundle->mode = + (ring_num < bundle->num_of_rings / 2) ? TX : RX; + ring_in_bundle->number = ring_num; + bundle->rings[ring_num] = ring_in_bundle; + } + + adf_cfg_assign_serv_to_rings(bundle, hw_data->ring_to_svc_map); + + return; +} + +int +adf_cfg_rel_ring2serv_mapping(struct adf_cfg_bundle *bundle) +{ + int i = 0; + + if (bundle->rings) { + for (i = 0; i < bundle->num_of_rings; i++) + free(bundle->rings[i], M_QAT); + + free(bundle->rings, M_QAT); + } + + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_cfg_bundle.h b/sys/dev/qat/qat_common/adf_cfg_bundle.h new file mode 100644 index 00000000000..50ad7b007ef --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_bundle.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_BUNDLE_H_ +#define ADF_CFG_BUNDLE_H_ + +#include "adf_accel_devices.h" +#include "adf_cfg_common.h" + +#define MAX_SECTIONS_PER_BUNDLE 8 +#define MAX_SECTION_NAME_LEN 64 + +#define TX 0x0 +#define RX 0x1 + +#define ASSIGN_SERV_TO_RINGS(bund, index, base, stype, rng_per_srv) \ + do { \ + int j = 0; \ + typeof(bund) b = (bund); \ + typeof(index) i = (index); \ + typeof(base) s = (base); \ + typeof(stype) t = (stype); \ + typeof(rng_per_srv) rps = (rng_per_srv); \ + for (j = 0; j < rps; j++) { \ + b->rings[i + j]->serv_type = t; \ + b->rings[i + j + s]->serv_type = t; \ + } \ + } while (0) + +bool adf_cfg_is_free(struct adf_cfg_bundle *bundle); + +int adf_cfg_get_ring_pairs_from_bundle(struct adf_cfg_bundle *bundle, + struct adf_cfg_instance *inst, + const char *process_name, + struct adf_cfg_instance *bundle_inst); + +struct adf_cfg_instance * +adf_cfg_get_free_instance(struct adf_cfg_device *device, + struct adf_cfg_bundle *bundle, + struct adf_cfg_instance *inst, + const char *process_name); + +int adf_cfg_bundle_init(struct adf_cfg_bundle *bundle, + struct adf_cfg_device *device, + int bank_num, + struct adf_accel_dev *accel_dev); + +void adf_cfg_bundle_clear(struct adf_cfg_bundle *bundle, + struct adf_accel_dev *accel_dev); + +void adf_cfg_init_ring2serv_mapping(struct adf_accel_dev *accel_dev, + struct adf_cfg_bundle *bundle); + +int adf_cfg_rel_ring2serv_mapping(struct adf_cfg_bundle *bundle); +#endif diff --git a/sys/dev/qat/qat_common/adf_cfg_device.c b/sys/dev/qat/qat_common/adf_cfg_device.c new file mode 100644 index 00000000000..ecd8e1599ee --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_device.c @@ -0,0 +1,1102 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg_instance.h" +#include "adf_cfg_section.h" +#include "adf_cfg_device.h" +#include "icp_qat_hw.h" +#include "adf_common_drv.h" + +#define ADF_CFG_SVCS_MAX (25) +#define ADF_CFG_DEPRE_PARAMS_NUM (4) + +#define ADF_CFG_CAP_DC ADF_ACCEL_CAPABILITIES_COMPRESSION +#define ADF_CFG_CAP_ASYM ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC +#define ADF_CFG_CAP_SYM \ + (ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | \ + ADF_ACCEL_CAPABILITIES_CIPHER | \ + ADF_ACCEL_CAPABILITIES_AUTHENTICATION) +#define ADF_CFG_CAP_CY (ADF_CFG_CAP_ASYM | ADF_CFG_CAP_SYM) + +#define ADF_CFG_FW_CAP_RL ICP_ACCEL_CAPABILITIES_RL +#define ADF_CFG_FW_CAP_HKDF ICP_ACCEL_CAPABILITIES_HKDF +#define ADF_CFG_FW_CAP_ECEDMONT ICP_ACCEL_CAPABILITIES_ECEDMONT +#define ADF_CFG_FW_CAP_EXT_ALGCHAIN ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN + +#define ADF_CFG_CY_RINGS \ + (CRYPTO | CRYPTO << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + CRYPTO << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + CRYPTO << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_SYM_RINGS \ + (SYM | SYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + SYM << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + SYM << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_ASYM_RINGS \ + (ASYM | ASYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + ASYM << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + ASYM << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_CY_DC_RINGS \ + (CRYPTO | CRYPTO << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + NA << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_ASYM_DC_RINGS \ + (ASYM | ASYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_SYM_DC_RINGS \ + (SYM | SYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +#define ADF_CFG_DC_RINGS \ + (COMP | COMP << ADF_CFG_SERV_RING_PAIR_1_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT | \ + COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT) + +static char adf_cfg_deprecated_params[][ADF_CFG_MAX_KEY_LEN_IN_BYTES] = + { ADF_DEV_KPT_ENABLE, + ADF_STORAGE_FIRMWARE_ENABLED, + ADF_RL_FIRMWARE_ENABLED, + ADF_PKE_DISABLED }; + +struct adf_cfg_enabled_services { + const char svcs_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u16 rng_to_svc_msk; + u32 enabled_svc_cap; + u32 enabled_fw_cap; +}; + +struct adf_cfg_profile { + enum adf_cfg_fw_image_type fw_image_type; + struct adf_cfg_enabled_services supported_svcs[ADF_CFG_SVCS_MAX]; +}; + +static struct adf_cfg_profile adf_profiles[] = + { { ADF_FW_IMAGE_DEFAULT, + { + { "cy", + ADF_CFG_CY_RINGS, + ADF_CFG_CAP_CY, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 }, + { "sym", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym", + ADF_CFG_ASYM_RINGS, + ADF_CFG_CAP_ASYM, + ADF_CFG_FW_CAP_ECEDMONT }, + { "cy;dc", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;cy", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym;dc", + ADF_CFG_ASYM_DC_RINGS, + ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT }, + { "dc;asym", + ADF_CFG_ASYM_DC_RINGS, + ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT }, + { "sym;dc", + ADF_CFG_SYM_DC_RINGS, + ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;sym", + ADF_CFG_SYM_DC_RINGS, + ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "inline;sym", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "sym;inline", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "inline;asym", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym;inline", + ADF_CFG_ASYM_RINGS, + ADF_CFG_CAP_ASYM, + ADF_CFG_FW_CAP_ECEDMONT }, + { "inline", 0, 0, 0 }, + { "inline;cy", + ADF_CFG_CY_RINGS, + ADF_CFG_CAP_CY, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "cy;inline", + ADF_CFG_CY_RINGS, + ADF_CFG_CAP_CY, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;inline", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 }, + { "inline;dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 }, + { "cy;dc;inline", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "cy;inline;dc", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;inline;cy", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;cy;inline", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "inline;cy;dc", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "inline;dc;cy", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + } }, + { ADF_FW_IMAGE_CRYPTO, + { + { "cy", + ADF_CFG_CY_RINGS, + ADF_CFG_CAP_CY, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_ECEDMONT | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "sym", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym", + ADF_CFG_ASYM_RINGS, + ADF_CFG_CAP_ASYM, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT }, + } }, + { ADF_FW_IMAGE_COMPRESSION, + { + { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 }, + } }, + { ADF_FW_IMAGE_CUSTOM1, + { + { "cy", + ADF_CFG_CY_RINGS, + ADF_CFG_CAP_CY, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_ECEDMONT | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 }, + { "sym", + ADF_CFG_SYM_RINGS, + ADF_CFG_CAP_SYM, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym", + ADF_CFG_ASYM_RINGS, + ADF_CFG_CAP_ASYM, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT }, + { "cy;dc", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_ECEDMONT | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;cy", + ADF_CFG_CY_DC_RINGS, + ADF_CFG_CAP_CY | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_ECEDMONT | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "asym;dc", + ADF_CFG_ASYM_DC_RINGS, + ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT }, + { "dc;asym", + ADF_CFG_ASYM_DC_RINGS, + ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT }, + { "sym;dc", + ADF_CFG_SYM_DC_RINGS, + ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + { "dc;sym", + ADF_CFG_SYM_DC_RINGS, + ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC, + ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF | + ADF_CFG_FW_CAP_EXT_ALGCHAIN }, + } } }; + +int +adf_cfg_get_ring_pairs(struct adf_cfg_device *device, + struct adf_cfg_instance *inst, + const char *process_name, + struct adf_accel_dev *accel_dev) +{ + int i = 0; + int ret = EFAULT; + struct adf_cfg_instance *free_inst = NULL; + struct adf_cfg_bundle *first_free_bundle = NULL; + enum adf_cfg_bundle_type free_bundle_type; + int first_user_bundle = 0; + + /* Section of user process with poll mode */ + if (strcmp(ADF_KERNEL_SEC, process_name) && + strcmp(ADF_KERNEL_SAL_SEC, process_name) && + inst->polling_mode == ADF_CFG_RESP_POLL) { + first_user_bundle = device->max_kernel_bundle_nr + 1; + for (i = first_user_bundle; i < device->bundle_num; i++) { + free_inst = adf_cfg_get_free_instance( + device, device->bundles[i], inst, process_name); + + if (!free_inst) + continue; + + ret = adf_cfg_get_ring_pairs_from_bundle( + device->bundles[i], inst, process_name, free_inst); + return ret; + } + } else { + /* Section of in-tree, or kernel API or user process + * with epoll mode + */ + if (!strcmp(ADF_KERNEL_SEC, process_name) || + !strcmp(ADF_KERNEL_SAL_SEC, process_name)) + free_bundle_type = KERNEL; + else + free_bundle_type = USER; + + for (i = 0; i < device->bundle_num; i++) { + /* Since both in-tree and kernel API's bundle type + * are kernel, use cpumask_subset to check if the + * ring's affinity mask is a subset of a bundle's + * one. + */ + if (free_bundle_type == device->bundles[i]->type && + CPU_SUBSET(&device->bundles[i]->affinity_mask, + &inst->affinity_mask)) { + free_inst = adf_cfg_get_free_instance( + device, + device->bundles[i], + inst, + process_name); + + if (!free_inst) + continue; + ret = adf_cfg_get_ring_pairs_from_bundle( + device->bundles[i], + inst, + process_name, + free_inst); + + return ret; + + } else if (!first_free_bundle && + adf_cfg_is_free(device->bundles[i])) { + first_free_bundle = device->bundles[i]; + } + } + + if (first_free_bundle) { + free_inst = adf_cfg_get_free_instance(device, + first_free_bundle, + inst, + process_name); + + if (!free_inst) + return ret; + + ret = adf_cfg_get_ring_pairs_from_bundle( + first_free_bundle, inst, process_name, free_inst); + + if (free_bundle_type == KERNEL) { + device->max_kernel_bundle_nr = + first_free_bundle->number; + } + return ret; + } + } + pr_err("Don't have enough rings for instance %s in process %s\n", + inst->name, + process_name); + + return ret; +} + +int +adf_cfg_get_services_enabled(struct adf_accel_dev *accel_dev, + u16 *ring_to_svc_map) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u32 i = 0; + struct adf_cfg_enabled_services *svcs = NULL; + enum adf_cfg_fw_image_type fw_image_type = ADF_FW_IMAGE_DEFAULT; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + *ring_to_svc_map = 0; + + /* Get the services enabled by user */ + snprintf(key, sizeof(key), ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + + if (hw_data->get_fw_image_type) { + if (hw_data->get_fw_image_type(accel_dev, &fw_image_type)) + return EFAULT; + } + + for (i = 0; i < ADF_CFG_SVCS_MAX; i++) { + svcs = &adf_profiles[fw_image_type].supported_svcs[i]; + + if (!strncmp(svcs->svcs_enabled, + "", + ADF_CFG_MAX_VAL_LEN_IN_BYTES)) + break; + + if (!strncmp(val, + svcs->svcs_enabled, + ADF_CFG_MAX_VAL_LEN_IN_BYTES)) { + *ring_to_svc_map = svcs->rng_to_svc_msk; + return 0; + } + } + + device_printf(GET_DEV(accel_dev), + "Invalid ServicesEnabled %s for ServicesProfile: %d\n", + val, + fw_image_type); + + return EFAULT; +} + +void +adf_cfg_set_asym_rings_mask(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + + hw_data->asym_rings_mask = 0; +} + +void +adf_cfg_gen_dispatch_arbiter(struct adf_accel_dev *accel_dev, + const u32 *thrd_to_arb_map, + u32 *thrd_to_arb_map_gen, + u32 total_engines) +{ + int engine, thread, service, bits; + u32 thread_ability, ability_map, service_mask, service_type; + u16 ena_srv_mask = GET_HW_DATA(accel_dev)->ring_to_svc_map; + + for (engine = 0; engine < total_engines; engine++) { + if (!(GET_HW_DATA(accel_dev)->ae_mask & (1 << engine))) + continue; + bits = 0; + /* ability_map is used to indicate the threads ability */ + ability_map = thrd_to_arb_map[engine]; + thrd_to_arb_map_gen[engine] = 0; + /* parse each thread on the engine */ + for (thread = 0; thread < ADF_NUM_THREADS_PER_AE; thread++) { + /* get the ability of this thread */ + thread_ability = ability_map & ADF_THRD_ABILITY_MASK; + ability_map >>= ADF_THRD_ABILITY_BIT_LEN; + /* parse each service */ + for (service = 0; service < ADF_CFG_MAX_SERVICES; + service++) { + service_type = + GET_SRV_TYPE(ena_srv_mask, service); + switch (service_type) { + case CRYPTO: + service_mask = ADF_CFG_ASYM_SRV_MASK; + if (thread_ability & service_mask) + thrd_to_arb_map_gen[engine] |= + (1 << bits); + bits++; + service++; + service_mask = ADF_CFG_SYM_SRV_MASK; + break; + case COMP: + service_mask = ADF_CFG_DC_SRV_MASK; + break; + case SYM: + service_mask = ADF_CFG_SYM_SRV_MASK; + break; + case ASYM: + service_mask = ADF_CFG_ASYM_SRV_MASK; + break; + default: + service_mask = ADF_CFG_UNKNOWN_SRV_MASK; + } + if (thread_ability & service_mask) + thrd_to_arb_map_gen[engine] |= + (1 << bits); + bits++; + } + } + } +} + +int +adf_cfg_get_fw_image_type(struct adf_accel_dev *accel_dev, + enum adf_cfg_fw_image_type *fw_image_type) +{ + *fw_image_type = ADF_FW_IMAGE_CUSTOM1; + + return 0; +} + +static int +adf_cfg_get_caps_enabled(struct adf_accel_dev *accel_dev, + u32 *enabled_svc_caps, + u32 *enabled_fw_caps) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u8 i = 0; + struct adf_cfg_enabled_services *svcs = NULL; + enum adf_cfg_fw_image_type fw_image_type = ADF_FW_IMAGE_DEFAULT; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + + *enabled_svc_caps = 0; + *enabled_fw_caps = 0; + + /* Get the services enabled by user */ + snprintf(key, sizeof(key), ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + + /* + * Only the PF driver has the hook for get_fw_image_type as the VF's + * enabled service is from PFVF communication. The fw_image_type for + * the VF is set to DEFAULT since this type contains all kinds of + * enabled service. + */ + if (hw_data->get_fw_image_type) { + if (hw_data->get_fw_image_type(accel_dev, &fw_image_type)) + return EFAULT; + } + + for (i = 0; i < ADF_CFG_SVCS_MAX; i++) { + svcs = &adf_profiles[fw_image_type].supported_svcs[i]; + + if (!strncmp(svcs->svcs_enabled, + "", + ADF_CFG_MAX_VAL_LEN_IN_BYTES)) + break; + + if (!strncmp(val, + svcs->svcs_enabled, + ADF_CFG_MAX_VAL_LEN_IN_BYTES)) { + *enabled_svc_caps = svcs->enabled_svc_cap; + *enabled_fw_caps = svcs->enabled_fw_cap; + return 0; + } + } + device_printf(GET_DEV(accel_dev), + "Invalid ServicesEnabled %s for ServicesProfile: %d\n", + val, + fw_image_type); + + return EFAULT; +} + +static void +adf_cfg_check_deprecated_params(struct adf_accel_dev *accel_dev) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u8 i = 0; + + for (i = 0; i < ADF_CFG_DEPRE_PARAMS_NUM; i++) { + /* give a warning if the deprecated params are set by user */ + snprintf(key, sizeof(key), "%s", adf_cfg_deprecated_params[i]); + if (!adf_cfg_get_param_value( + accel_dev, ADF_GENERAL_SEC, key, val)) { + device_printf(GET_DEV(accel_dev), + "Parameter '%s' has been deprecated\n", + key); + } + } +} + +static int +adf_cfg_check_enabled_services(struct adf_accel_dev *accel_dev, + u32 enabled_svc_caps) +{ + u32 hw_caps = GET_HW_DATA(accel_dev)->accel_capabilities_mask; + + if ((enabled_svc_caps & hw_caps) == enabled_svc_caps) + return 0; + + device_printf(GET_DEV(accel_dev), "Unsupported device configuration\n"); + + return EFAULT; +} + +static int +adf_cfg_update_pf_accel_cap_mask(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 enabled_svc_caps = 0; + u32 enabled_fw_caps = 0; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + if (adf_cfg_get_caps_enabled(accel_dev, + &enabled_svc_caps, + &enabled_fw_caps)) + return EFAULT; + + if (adf_cfg_check_enabled_services(accel_dev, enabled_svc_caps)) + return EFAULT; + + if (!(enabled_svc_caps & ADF_CFG_CAP_ASYM)) + hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_ASYM; + if (!(enabled_svc_caps & ADF_CFG_CAP_SYM)) + hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_SYM; + if (!(enabled_svc_caps & ADF_CFG_CAP_DC)) + hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_DC; + + /* Enable FW defined capabilities*/ + if (enabled_fw_caps) + hw_data->accel_capabilities_mask |= enabled_fw_caps; + + return 0; +} + +static int +adf_cfg_update_vf_accel_cap_mask(struct adf_accel_dev *accel_dev) +{ + u32 enabled_svc_caps = 0; + u32 enabled_fw_caps = 0; + + if (adf_cfg_get_caps_enabled(accel_dev, + &enabled_svc_caps, + &enabled_fw_caps)) + return EFAULT; + + if (adf_cfg_check_enabled_services(accel_dev, enabled_svc_caps)) + return EFAULT; + + return 0; +} + +int +adf_cfg_device_init(struct adf_cfg_device *device, + struct adf_accel_dev *accel_dev) +{ + int i = 0; + /* max_inst indicates the max instance number one bank can hold */ + int max_inst = accel_dev->hw_device->tx_rx_gap; + int ret = ENOMEM; + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + + adf_cfg_check_deprecated_params(accel_dev); + + device->bundle_num = 0; + device->bundles = (struct adf_cfg_bundle **)malloc( + sizeof(struct adf_cfg_bundle *) * accel_dev->hw_device->num_banks, + M_QAT, + M_WAITOK | M_ZERO); + + device->bundle_num = accel_dev->hw_device->num_banks; + + device->instances = (struct adf_cfg_instance **)malloc( + sizeof(struct adf_cfg_instance *) * device->bundle_num * max_inst, + M_QAT, + M_WAITOK | M_ZERO); + + device->instance_index = 0; + + device->max_kernel_bundle_nr = -1; + + ret = EFAULT; + + /* Update the acceleration capability mask based on User capability */ + if (!accel_dev->is_vf) { + if (adf_cfg_update_pf_accel_cap_mask(accel_dev)) + goto failed; + } else { + if (adf_cfg_update_vf_accel_cap_mask(accel_dev)) + goto failed; + } + + /* Based on the svc configured, get ring_to_svc_map */ + if (hw_data->get_ring_to_svc_map) { + if (hw_data->get_ring_to_svc_map(accel_dev, + &hw_data->ring_to_svc_map)) + goto failed; + } + + ret = ENOMEM; + /* + * 1) get the config information to generate the ring to service + * mapping table + * 2) init each bundle of this device + */ + for (i = 0; i < device->bundle_num; i++) { + device->bundles[i] = malloc(sizeof(struct adf_cfg_bundle), + M_QAT, + M_WAITOK | M_ZERO); + + device->bundles[i]->max_section = max_inst; + adf_cfg_bundle_init(device->bundles[i], device, i, accel_dev); + } + + return 0; + +failed: + for (i = 0; i < device->bundle_num; i++) { + if (device->bundles[i]) + adf_cfg_bundle_clear(device->bundles[i], accel_dev); + } + + for (i = 0; i < (device->bundle_num * max_inst); i++) { + if (device->instances && device->instances[i]) + free(device->instances[i], M_QAT); + } + + free(device->instances, M_QAT); + device->instances = NULL; + + device_printf(GET_DEV(accel_dev), "Failed to do device init\n"); + return ret; +} + +void +adf_cfg_device_clear(struct adf_cfg_device *device, + struct adf_accel_dev *accel_dev) +{ + int i = 0; + + for (i = 0; i < device->bundle_num; i++) { + if (device->bundles && device->bundles[i]) { + adf_cfg_bundle_clear(device->bundles[i], accel_dev); + free(device->bundles[i], M_QAT); + device->bundles[i] = NULL; + } + } + + free(device->bundles, M_QAT); + device->bundles = NULL; + + for (i = 0; i < device->instance_index; i++) { + if (device->instances && device->instances[i]) { + free(device->instances[i], M_QAT); + device->instances[i] = NULL; + } + } + + free(device->instances, M_QAT); + device->instances = NULL; +} + +static int +adf_cfg_static_conf(struct adf_accel_dev *accel_dev) +{ + int ret = 0; + unsigned long val = 0; + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char value[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + int cpus; + int instances = 0; + int cy_poll_instances; + int cy_irq_instances; + int dc_instances; + int i = 0; + + cpus = num_online_cpus(); + instances = + GET_MAX_BANKS(accel_dev) > cpus ? GET_MAX_BANKS(accel_dev) : cpus; + if (!instances) + return EFAULT; + + if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_DC) + dc_instances = ADF_CFG_STATIC_CONF_INST_NUM_DC; + else + return EFAULT; + instances -= dc_instances; + + if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_CY_POLL) + cy_poll_instances = ADF_CFG_STATIC_CONF_INST_NUM_CY_POLL; + else + return EFAULT; + instances -= cy_poll_instances; + + if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_CY_IRQ) + cy_irq_instances = ADF_CFG_STATIC_CONF_INST_NUM_CY_IRQ; + else + return EFAULT; + instances -= cy_irq_instances; + + ret |= adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC); + + ret |= adf_cfg_section_add(accel_dev, ADF_KERNEL_SAL_SEC); + + val = ADF_CFG_STATIC_CONF_VER; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CONFIG_VERSION); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_AUTO_RESET; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_AUTO_RESET_ON_ERROR); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + if (accel_dev->hw_device->get_num_accel_units) { + int cy_au = 0; + int dc_au = 0; + int num_au = accel_dev->hw_device->get_num_accel_units( + accel_dev->hw_device); + + if (num_au > ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS) { + cy_au = num_au - ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS; + dc_au = ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS; + } else if (num_au == ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS) { + cy_au = 1; + dc_au = 1; + } else { + return EFAULT; + } + + val = cy_au; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_NUM_CY_ACCEL_UNITS); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = dc_au; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_NUM_DC_ACCEL_UNITS); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_NUM_INLINE_ACCEL_UNITS; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_NUM_INLINE_ACCEL_UNITS); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + } + + val = ADF_CFG_STATIC_CONF_CY_ASYM_RING_SIZE; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CY ADF_RING_ASYM_SIZE); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_CY_SYM_RING_SIZE; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CY ADF_RING_SYM_SIZE); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_DC_INTER_BUF_SIZE; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_INTER_BUF_SIZE); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_SERVICES_ENABLED); + if ((cy_poll_instances + cy_irq_instances) == 0 && dc_instances > 0) { + snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CFG_DC); + } else if (((cy_poll_instances + cy_irq_instances)) > 0 && + dc_instances == 0) { + snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CFG_SYM); + } else { + snprintf(value, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%s;%s", + ADF_CFG_SYM, + ADF_CFG_DC); + } + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)value, ADF_STR); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DC; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DC); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DH; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DH); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DRBG; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DRBG); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DSA; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DSA); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_ECC; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_ECC); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_ENABLED; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_ENABLED); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_KEYGEN; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_KEYGEN); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_LN; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_LN); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_PRIME; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_PRIME); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_RSA; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_RSA); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_SYM; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_SYM); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC); + + val = (cy_poll_instances + cy_irq_instances); + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_NUM_CY); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + val = dc_instances; + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_NUM_DC); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + for (i = 0; i < (cy_irq_instances); i++) { + val = i; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_IRQ; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY "%d" ADF_POLL_MODE, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CY "%d", i); + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_NAME_FORMAT, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR); + } + + for (i = cy_irq_instances; i < (cy_poll_instances + cy_irq_instances); + i++) { + val = i; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_POLL; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY "%d" ADF_POLL_MODE, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CY "%d", i); + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_NAME_FORMAT, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR); + } + + for (i = 0; i < dc_instances; i++) { + val = i; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_DC "%d" ADF_ETRMGR_CORE_AFFINITY, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + val = ADF_CFG_STATIC_CONF_POLL; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_DC "%d" ADF_POLL_MODE, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC); + + snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_DC "%d", i); + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_DC_NAME_FORMAT, + i); + ret |= adf_cfg_add_key_value_param( + accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR); + } + + if (ret) + ret = EFAULT; + return ret; +} + +int +adf_config_device(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *cfg = NULL; + struct adf_cfg_device *cfg_device = NULL; + struct adf_cfg_section *sec; + struct list_head *list; + int ret = ENOMEM; + + if (!accel_dev) + return ret; + + ret = adf_cfg_static_conf(accel_dev); + if (ret) + goto failed; + + cfg = accel_dev->cfg; + cfg->dev = NULL; + cfg_device = (struct adf_cfg_device *)malloc(sizeof(*cfg_device), + M_QAT, + M_WAITOK | M_ZERO); + + ret = EFAULT; + + if (adf_cfg_device_init(cfg_device, accel_dev)) + goto failed; + + cfg->dev = cfg_device; + + /* GENERAL and KERNEL section must be processed before others */ + list_for_each(list, &cfg->sec_list) + { + sec = list_entry(list, struct adf_cfg_section, list); + if (!strcmp(sec->name, ADF_GENERAL_SEC)) { + ret = adf_cfg_process_section(accel_dev, + sec->name, + accel_dev->accel_id); + if (ret) + goto failed; + sec->processed = true; + break; + } + } + + list_for_each(list, &cfg->sec_list) + { + sec = list_entry(list, struct adf_cfg_section, list); + if (!strcmp(sec->name, ADF_KERNEL_SEC)) { + ret = adf_cfg_process_section(accel_dev, + sec->name, + accel_dev->accel_id); + if (ret) + goto failed; + sec->processed = true; + break; + } + } + + list_for_each(list, &cfg->sec_list) + { + sec = list_entry(list, struct adf_cfg_section, list); + if (!strcmp(sec->name, ADF_KERNEL_SAL_SEC)) { + ret = adf_cfg_process_section(accel_dev, + sec->name, + accel_dev->accel_id); + if (ret) + goto failed; + sec->processed = true; + break; + } + } + + list_for_each(list, &cfg->sec_list) + { + sec = list_entry(list, struct adf_cfg_section, list); + /* avoid reprocessing one section */ + if (!sec->processed && !sec->is_derived) { + ret = adf_cfg_process_section(accel_dev, + sec->name, + accel_dev->accel_id); + if (ret) + goto failed; + sec->processed = true; + } + } + + /* newly added accel section */ + ret = adf_cfg_process_section(accel_dev, + ADF_ACCEL_SEC, + accel_dev->accel_id); + if (ret) + goto failed; + + /* + * put item-remove task after item-process + * because during process we may fetch values from those items + */ + list_for_each(list, &cfg->sec_list) + { + sec = list_entry(list, struct adf_cfg_section, list); + if (!sec->is_derived) { + ret = adf_cfg_cleanup_section(accel_dev, + sec->name, + accel_dev->accel_id); + if (ret) + goto failed; + } + } + + ret = 0; + set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); +failed: + if (ret) { + if (cfg_device) { + adf_cfg_device_clear(cfg_device, accel_dev); + free(cfg_device, M_QAT); + cfg->dev = NULL; + } + adf_cfg_del_all(accel_dev); + device_printf(GET_DEV(accel_dev), "Failed to config device\n"); + } + + return ret; +} diff --git a/sys/dev/qat/qat_common/adf_cfg_instance.c b/sys/dev/qat/qat_common/adf_cfg_instance.c new file mode 100644 index 00000000000..bf8a7d239d6 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_instance.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg_instance.h" + +void +crypto_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle) +{ + int i = 0; + + instance->stype = CRYPTO; + for (i = 0; i < bundle->num_of_rings / 2; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_ASYM && + bundle->rings[i]->mode == TX) { + instance->asym_tx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = 0; i < bundle->num_of_rings / 2; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_SYM && + bundle->rings[i]->mode == TX) { + instance->sym_tx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = bundle->num_of_rings / 2; i < bundle->num_of_rings; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_ASYM && + bundle->rings[i]->mode == RX) { + instance->asym_rx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = bundle->num_of_rings / 2; i < bundle->num_of_rings; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_SYM && + bundle->rings[i]->mode == RX) { + instance->sym_rx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } +} + +void +dc_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle) +{ + int i = 0; + + instance->stype = COMP; + for (i = 0; i < bundle->num_of_rings / 2; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_DC && + bundle->rings[i]->mode == TX) { + instance->dc_tx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = bundle->num_of_rings / 2; i < bundle->num_of_rings; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_DC && + bundle->rings[i]->mode == RX) { + instance->dc_rx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } +} + +void +asym_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle) +{ + int i = 0; + + instance->stype = ASYM; + for (i = 0; i < bundle->num_of_rings / 2; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_ASYM && + bundle->rings[i]->mode == TX) { + instance->asym_tx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = bundle->num_of_rings / 2; i < bundle->num_of_rings; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_ASYM && + bundle->rings[i]->mode == RX) { + instance->asym_rx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } +} + +void +sym_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle) +{ + int i = 0; + + instance->stype = SYM; + for (i = 0; i < bundle->num_of_rings / 2; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_SYM && + bundle->rings[i]->mode == TX) { + instance->sym_tx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } + + for (i = 0 + bundle->num_of_rings / 2; i < bundle->num_of_rings; i++) { + if ((bundle->in_use >> bundle->rings[i]->number) & 0x1) + continue; + + if (bundle->rings[i]->serv_type == ADF_ACCEL_SERV_SYM && + bundle->rings[i]->mode == RX) { + instance->sym_rx = bundle->rings[i]->number; + bundle->in_use |= 1 << bundle->rings[i]->number; + break; + } + } +} diff --git a/sys/dev/qat/qat_common/adf_cfg_instance.h b/sys/dev/qat/qat_common/adf_cfg_instance.h new file mode 100644 index 00000000000..29427343d02 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_instance.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_INSTANCE_H_ +#define ADF_CFG_INSTANCE_H_ + +#include "adf_accel_devices.h" +#include "adf_cfg_common.h" +#include "adf_cfg_bundle.h" + +void crypto_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle); +void dc_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle); +void asym_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle); +void sym_instance_init(struct adf_cfg_instance *instance, + struct adf_cfg_bundle *bundle); +#endif diff --git a/sys/dev/qat/qat_common/adf_cfg_section.c b/sys/dev/qat/qat_common/adf_cfg_section.c new file mode 100644 index 00000000000..efb07784c57 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_section.c @@ -0,0 +1,1144 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_cfg_instance.h" +#include "adf_cfg_device.h" +#include "adf_cfg_section.h" + +static bool +adf_cfg_is_svc_enabled(struct adf_accel_dev *accel_dev, const u8 svc) +{ + int ring_pair_index = 0; + u8 serv_type = NA; + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + + for (ring_pair_index = 0; ring_pair_index < ADF_CFG_NUM_SERVICES; + ring_pair_index++) { + serv_type = + GET_SRV_TYPE(hw_data->ring_to_svc_map, ring_pair_index); + if (serv_type == svc) + return true; + } + return false; +} + +static int +adf_cfg_set_core_number_for_instance(struct adf_accel_dev *accel_dev, + const char *sec_name, + const char *inst_name, + int process_num, + unsigned long *core_number) +{ + char *core_val = NULL; + char *pos = NULL; + char **tokens = NULL; + int token_index = 0; + int core_arr_index = 0; + int i = 0; + int ret = EFAULT; + unsigned long *core_num_arr = NULL; + unsigned long core_num; + unsigned long start, end; + + /* do memory allocation */ + core_val = + malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + tokens = malloc(sizeof(char *) * ADF_CFG_MAX_TOKENS, + M_QAT, + M_WAITOK | M_ZERO); + + for (i = 0; i < ADF_CFG_MAX_TOKENS; i++) { + tokens[i] = + malloc(ADF_CFG_MAX_TOKEN_LEN, M_QAT, M_WAITOK | M_ZERO); + } + + core_num_arr = malloc(sizeof(unsigned long) * ADF_CFG_MAX_CORE_NUM, + M_QAT, + M_WAITOK | M_ZERO); + + /* parse the core_val */ + ret = EFAULT; + if (adf_cfg_get_param_value(accel_dev, sec_name, inst_name, core_val)) + goto failed; + + pos = strchr(core_val, ','); + while (pos) { + pos[0] = '\0'; + strlcpy(tokens[token_index++], core_val, ADF_CFG_MAX_TOKEN_LEN); + strlcpy(core_val, pos + 1, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + pos = strchr(core_val, ','); + if (!pos) + strlcpy(tokens[token_index++], + core_val, + ADF_CFG_MAX_VAL_LEN_IN_BYTES); + } + + /* in case there is only N-M */ + if (token_index == 0) + strlcpy(tokens[token_index++], + core_val, + ADF_CFG_MAX_VAL_LEN_IN_BYTES); + + /* parse the tokens such as N-M */ + for (i = 0; i < token_index; i++) { + pos = strchr(tokens[i], '-'); + if (pos) { + pos[0] = '\0'; + ret = compat_strtoul(tokens[i], 10, &start); + if (ret) + goto failed; + ret = compat_strtoul(pos + 1, 10, &end); + if (ret) + goto failed; + if (start > end) { + ret = EFAULT; + goto failed; + } + for (core_num = start; core_num < end + 1; core_num++) + core_num_arr[core_arr_index++] = core_num; + } else { + ret = compat_strtoul(tokens[i], 10, &core_num); + if (ret) + goto failed; + core_num_arr[core_arr_index++] = core_num; + } + } + + if (core_arr_index == 0) { + ret = compat_strtoul(core_val, 10, &core_num); + if (ret) + goto failed; + else + core_num_arr[core_arr_index++] = core_num; + } + + *core_number = core_num_arr[process_num % core_arr_index]; + ret = 0; +failed: + free(core_val, M_QAT); + if (tokens) { + for (i = 0; i < ADF_CFG_MAX_TOKENS; i++) + free(tokens[i], M_QAT); + free(tokens, M_QAT); + } + free(core_num_arr, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Get core number failed with error %d\n", + ret); + return ret; +} + +static int +adf_cfg_set_value(struct adf_accel_dev *accel_dev, + const char *sec, + const char *key, + unsigned long *value) +{ + char *val = NULL; + int ret = EFAULT; + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + if (adf_cfg_get_param_value(accel_dev, sec, key, val)) + goto out; + + /* as the key type can be either ADF_DEC or ADF_HEX */ + if (compat_strtoul(val, 10, value) && compat_strtoul(val, 16, value)) + goto out; + + ret = 0; +out: + free(val, M_QAT); + return ret; +} + +static void +adf_cfg_add_cy_inst_info(struct adf_accel_dev *accel_dev, + struct adf_cfg_instance *crypto_inst, + const char *derived_sec, + int inst_index) +{ + char *key = NULL; + unsigned long bank_number = 0; + unsigned long ring_number = 0; + unsigned long asym_req = 0; + unsigned long sym_req = 0; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_BANK_NUM_FORMAT, + inst_index); + bank_number = crypto_inst->bundle; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&bank_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_ASYM_TX_FORMAT, + inst_index); + ring_number = crypto_inst->asym_tx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_SYM_TX_FORMAT, + inst_index); + ring_number = crypto_inst->sym_tx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_ASYM_RX_FORMAT, + inst_index); + ring_number = crypto_inst->asym_rx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_SYM_RX_FORMAT, + inst_index); + ring_number = crypto_inst->sym_rx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + strlcpy(key, ADF_CY_RING_ASYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &asym_req)) + asym_req = ADF_CFG_DEF_CY_RING_ASYM_SIZE; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_RING_ASYM_SIZE_FORMAT, + inst_index); + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&asym_req, ADF_DEC); + + strlcpy(key, ADF_CY_RING_SYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &sym_req)) + sym_req = ADF_CFG_DEF_CY_RING_SYM_SIZE; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_RING_SYM_SIZE_FORMAT, + inst_index); + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&sym_req, ADF_DEC); + + free(key, M_QAT); +} + +static void +adf_cfg_add_dc_inst_info(struct adf_accel_dev *accel_dev, + struct adf_cfg_instance *dc_inst, + const char *derived_sec, + int inst_index) +{ + char *key = NULL; + unsigned long bank_number = 0; + unsigned long ring_number = 0; + unsigned long dc_req = 0; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + snprintf(key, ADF_CFG_MAX_STR_LEN, ADF_DC_BANK_NUM_FORMAT, inst_index); + bank_number = dc_inst->bundle; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&bank_number, ADF_DEC); + + snprintf(key, ADF_CFG_MAX_STR_LEN, ADF_DC_TX_FORMAT, inst_index); + ring_number = dc_inst->dc_tx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, ADF_CFG_MAX_STR_LEN, ADF_DC_RX_FORMAT, inst_index); + ring_number = dc_inst->dc_rx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + strlcpy(key, ADF_DC_RING_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &dc_req)) + dc_req = ADF_CFG_DEF_DC_RING_SIZE; + + snprintf(key, ADF_CFG_MAX_STR_LEN, ADF_DC_RING_SIZE_FORMAT, inst_index); + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&dc_req, ADF_DEC); + + free(key, M_QAT); +} + +static void +adf_cfg_add_asym_inst_info(struct adf_accel_dev *accel_dev, + struct adf_cfg_instance *asym_inst, + const char *derived_sec, + int inst_index) +{ + char *key = NULL; + unsigned long bank_number = 0; + unsigned long ring_number = 0; + unsigned long asym_req = 0; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_BANK_NUM_FORMAT, + inst_index); + bank_number = asym_inst->bundle; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&bank_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_ASYM_TX_FORMAT, + inst_index); + ring_number = asym_inst->asym_tx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_ASYM_RX_FORMAT, + inst_index); + ring_number = asym_inst->asym_rx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + strlcpy(key, ADF_CY_RING_ASYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &asym_req)) + asym_req = ADF_CFG_DEF_CY_RING_ASYM_SIZE; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_RING_ASYM_SIZE_FORMAT, + inst_index); + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&asym_req, ADF_DEC); + + free(key, M_QAT); +} + +static void +adf_cfg_add_sym_inst_info(struct adf_accel_dev *accel_dev, + struct adf_cfg_instance *sym_inst, + const char *derived_sec, + int inst_index) +{ + char *key = NULL; + unsigned long bank_number = 0; + unsigned long ring_number = 0; + unsigned long sym_req = 0; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_BANK_NUM_FORMAT, + inst_index); + bank_number = sym_inst->bundle; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&bank_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_SYM_TX_FORMAT, + inst_index); + ring_number = sym_inst->sym_tx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_SYM_RX_FORMAT, + inst_index); + ring_number = sym_inst->sym_rx; + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&ring_number, ADF_DEC); + + strlcpy(key, ADF_CY_RING_SYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &sym_req)) + sym_req = ADF_CFG_DEF_CY_RING_SYM_SIZE; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_RING_SYM_SIZE_FORMAT, + inst_index); + adf_cfg_add_key_value_param( + accel_dev, derived_sec, key, (void *)&sym_req, ADF_DEC); + + free(key, M_QAT); +} + +static int +adf_cfg_section_copy(struct adf_accel_dev *accel_dev, + const char *processed_sec, + const char *derived_sec) +{ + unsigned long val = 0; + struct list_head *list; + struct adf_cfg_section *sec_process = + adf_cfg_sec_find(accel_dev, processed_sec); + if (!sec_process) + return EFAULT; + + list_for_each(list, &sec_process->param_head) + { + struct adf_cfg_key_val *ptr = + list_entry(list, struct adf_cfg_key_val, list); + + /* + * ignore CoreAffinity since it will be generated later, and + * there is no need to keep NumProcesses and LimitDevAccess. + */ + if (strstr(ptr->key, ADF_ETRMGR_CORE_AFFINITY) || + strstr(ptr->key, ADF_NUM_PROCESSES) || + strstr(ptr->key, ADF_LIMIT_DEV_ACCESS)) + continue; + + if (ptr->type == ADF_DEC) { + if (!compat_strtoul(ptr->val, 10, &val)) + adf_cfg_add_key_value_param(accel_dev, + derived_sec, + ptr->key, + (void *)&val, + ptr->type); + } else if (ptr->type == ADF_STR) { + adf_cfg_add_key_value_param(accel_dev, + derived_sec, + ptr->key, + (void *)ptr->val, + ptr->type); + } else if (ptr->type == ADF_HEX) { + if (!compat_strtoul(ptr->val, 16, &val)) + adf_cfg_add_key_value_param(accel_dev, + derived_sec, + ptr->key, + (void *)val, + ptr->type); + } + } + return 0; +} + +static int +adf_cfg_create_rings_entries_for_cy_inst(struct adf_accel_dev *accel_dev, + const char *processed_sec, + const char *derived_sec, + int process_num, + enum adf_cfg_service_type serv_type) +{ + int i = 0; + int ret = EFAULT; + unsigned long num_inst = 0, num_dc_inst = 0; + unsigned long core_number = 0; + unsigned long polling_mode = 0; + struct adf_cfg_instance *crypto_inst = NULL; + + char *key = NULL; + char *val = NULL; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + goto failed; + if ((!strncmp(val, ADF_CFG_CY, ADF_CFG_MAX_VAL_LEN_IN_BYTES)) || + (!strncmp(val, ADF_CFG_ASYM, ADF_CFG_MAX_VAL_LEN_IN_BYTES)) || + (!strncmp(val, ADF_CFG_SYM, ADF_CFG_MAX_VAL_LEN_IN_BYTES))) { + strlcpy(key, ADF_NUM_DC, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value( + accel_dev, processed_sec, key, &num_dc_inst)) + goto failed; + if (num_dc_inst > 0) { + device_printf( + GET_DEV(accel_dev), + "NumDcInstances > 0,when CY only is enabled\n"); + goto failed; + } + } + ret = EFAULT; + + strlcpy(key, ADF_NUM_CY, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, processed_sec, key, &num_inst)) + goto failed; + + crypto_inst = malloc(sizeof(*crypto_inst), M_QAT, M_WAITOK | M_ZERO); + + for (i = 0; i < num_inst; i++) { + memset(crypto_inst, 0, sizeof(*crypto_inst)); + crypto_inst->stype = serv_type; + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_CORE_AFFINITY_FORMAT, + i); + if (adf_cfg_set_core_number_for_instance(accel_dev, + processed_sec, + key, + process_num, + &core_number)) + goto failed; + + if (strcmp(processed_sec, ADF_KERNEL_SEC) && + strcmp(processed_sec, ADF_KERNEL_SAL_SEC)) + adf_cfg_add_key_value_param(accel_dev, + derived_sec, + key, + (void *)&core_number, + ADF_DEC); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_NAME_FORMAT, + i); + if (adf_cfg_get_param_value(accel_dev, processed_sec, key, val)) + goto failed; + + strlcpy(crypto_inst->name, val, sizeof(crypto_inst->name)); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_CY_POLL_MODE_FORMAT, + i); + if (adf_cfg_set_value( + accel_dev, processed_sec, key, &polling_mode)) + goto failed; + + crypto_inst->polling_mode = polling_mode; + CPU_ZERO(&crypto_inst->affinity_mask); + CPU_SET(core_number, &crypto_inst->affinity_mask); + + if (adf_cfg_get_ring_pairs(accel_dev->cfg->dev, + crypto_inst, + derived_sec, + accel_dev)) + goto failed; + + switch (serv_type) { + case CRYPTO: + adf_cfg_add_cy_inst_info(accel_dev, + crypto_inst, + derived_sec, + i); + break; + case ASYM: + adf_cfg_add_asym_inst_info(accel_dev, + crypto_inst, + derived_sec, + i); + break; + case SYM: + adf_cfg_add_sym_inst_info(accel_dev, + crypto_inst, + derived_sec, + i); + break; + default: + pr_err("unknown crypto instance type %d.\n", serv_type); + goto failed; + } + } + + ret = 0; +failed: + free(crypto_inst, M_QAT); + free(val, M_QAT); + free(key, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to create rings for cy\n"); + + return ret; +} + +static int +adf_cfg_create_rings_entries_for_dc_inst(struct adf_accel_dev *accel_dev, + const char *processed_sec, + const char *derived_sec, + int process_num) +{ + int i = 0; + int ret = EFAULT; + unsigned long num_inst = 0, num_cy_inst = 0; + unsigned long core_number = 0; + unsigned long polling_mode = 0; + struct adf_cfg_instance *dc_inst = NULL; + + char *key = NULL; + char *val = NULL; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + ret = EFAULT; + + snprintf(key, ADF_CFG_MAX_STR_LEN, ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + goto failed; + + if (!strncmp(val, ADF_CFG_DC, ADF_CFG_MAX_VAL_LEN_IN_BYTES)) { + strlcpy(key, ADF_NUM_CY, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value( + accel_dev, processed_sec, key, &num_cy_inst)) + goto failed; + if (num_cy_inst > 0) { + device_printf( + GET_DEV(accel_dev), + "NumCyInstances > 0,when DC only is enabled\n"); + goto failed; + } + } + + strlcpy(key, ADF_NUM_DC, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, processed_sec, key, &num_inst)) + goto failed; + + dc_inst = malloc(sizeof(*dc_inst), M_QAT, M_WAITOK | M_ZERO); + + for (i = 0; i < num_inst; i++) { + memset(dc_inst, 0, sizeof(*dc_inst)); + dc_inst->stype = COMP; + snprintf(key, + ADF_CFG_MAX_STR_LEN, + ADF_DC_CORE_AFFINITY_FORMAT, + i); + + if (adf_cfg_set_core_number_for_instance(accel_dev, + processed_sec, + key, + process_num, + &core_number)) + goto failed; + + if (strcmp(processed_sec, ADF_KERNEL_SEC) && + strcmp(processed_sec, ADF_KERNEL_SAL_SEC)) { + adf_cfg_add_key_value_param(accel_dev, + derived_sec, + key, + (void *)&core_number, + ADF_DEC); + } + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_DC_NAME_FORMAT, + i); + if (adf_cfg_get_param_value(accel_dev, processed_sec, key, val)) + goto failed; + + strlcpy(dc_inst->name, val, sizeof(dc_inst->name)); + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_DC_POLL_MODE_FORMAT, + i); + if (adf_cfg_set_value( + accel_dev, processed_sec, key, &polling_mode)) + goto failed; + + dc_inst->polling_mode = polling_mode; + CPU_ZERO(&dc_inst->affinity_mask); + CPU_SET(core_number, &dc_inst->affinity_mask); + + if (adf_cfg_get_ring_pairs( + accel_dev->cfg->dev, dc_inst, derived_sec, accel_dev)) + goto failed; + + adf_cfg_add_dc_inst_info(accel_dev, dc_inst, derived_sec, i); + } + + ret = 0; +failed: + free(dc_inst, M_QAT); + free(val, M_QAT); + free(key, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to create rings for dc\n"); + + return ret; +} + +static int +adf_cfg_process_user_section(struct adf_accel_dev *accel_dev, + const char *sec_name, + int dev) +{ + int i = 0; + int ret = EFAULT; + unsigned long num_processes = 0; + unsigned long limit_dev_acc = 0; + u8 serv_type = 0; + + char *key = NULL; + char *val = NULL; + char *derived_sec_name = NULL; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + derived_sec_name = + malloc(ADF_CFG_MAX_STR_LEN, M_QAT, M_WAITOK | M_ZERO); + + strlcpy(key, ADF_NUM_PROCESSES, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, sec_name, key, &num_processes)) + num_processes = 0; + + strlcpy(key, ADF_LIMIT_DEV_ACCESS, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, sec_name, key, &limit_dev_acc)) + limit_dev_acc = 0; + + for (i = 0; i < num_processes; i++) { + if (limit_dev_acc) + snprintf(derived_sec_name, + ADF_CFG_MAX_STR_LEN, + ADF_LIMITED_USER_SECTION_NAME_FORMAT, + sec_name, + dev, + i); + else + snprintf(derived_sec_name, + ADF_CFG_MAX_STR_LEN, + ADF_USER_SECTION_NAME_FORMAT, + sec_name, + i); + + if (adf_cfg_derived_section_add(accel_dev, derived_sec_name)) + goto failed; + + /* copy items to the derived section */ + adf_cfg_section_copy(accel_dev, sec_name, derived_sec_name); + + for (serv_type = NA; serv_type <= USED; serv_type++) { + switch (serv_type) { + case NA: + break; + case CRYPTO: + case ASYM: + case SYM: + if (adf_cfg_is_svc_enabled(accel_dev, + serv_type)) + if (adf_cfg_create_rings_entries_for_cy_inst( + accel_dev, + sec_name, + derived_sec_name, + i, + (enum adf_cfg_service_type) + serv_type)) + goto failed; + break; + case COMP: + if (adf_cfg_is_svc_enabled(accel_dev, + serv_type)) + if (adf_cfg_create_rings_entries_for_dc_inst( + accel_dev, + sec_name, + derived_sec_name, + i)) + goto failed; + break; + case USED: + break; + default: + pr_err("Unknown service type %d.\n", serv_type); + } + } + } + + ret = 0; +failed: + + free(val, M_QAT); + free(key, M_QAT); + free(derived_sec_name, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to process user section %s\n", + sec_name); + + return ret; +} + +static int +adf_cfg_cleanup_user_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name); + struct list_head *head; + struct list_head *list_ptr, *tmp; + + if (!sec) + return EFAULT; + + if (sec->is_derived) + return 0; + + head = &sec->param_head; + list_for_each_prev_safe(list_ptr, tmp, head) + { + struct adf_cfg_key_val *ptr = + list_entry(list_ptr, struct adf_cfg_key_val, list); + + if (!strcmp(ptr->key, ADF_LIMIT_DEV_ACCESS)) + continue; + + list_del(list_ptr); + free(ptr, M_QAT); + } + return 0; +} + +static int +adf_cfg_process_section_no_op(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + return 0; +} + +static int +adf_cfg_cleanup_general_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + unsigned long first_used_bundle = 0; + int ret = EFAULT; + char *key = NULL; + char *val = NULL; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + /* Remove sections that not needed after processing */ + strlcpy(key, ADF_CONFIG_VERSION, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_remove_key_param(accel_dev, sec_name, key)) + goto failed; + + strlcpy(key, ADF_CY ADF_RING_ASYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_remove_key_param(accel_dev, sec_name, key)) + goto failed; + + strlcpy(key, ADF_CY ADF_RING_SYM_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_remove_key_param(accel_dev, sec_name, key)) + goto failed; + + strlcpy(key, ADF_DC ADF_RING_DC_SIZE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_remove_key_param(accel_dev, sec_name, key)) + goto failed; + + /* After all processing done, set the "FirstUserBundle" value */ + first_used_bundle = accel_dev->cfg->dev->max_kernel_bundle_nr + 1; + strlcpy(key, ADF_FIRST_USER_BUNDLE, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_add_key_value_param( + accel_dev, sec_name, key, (void *)&first_used_bundle, ADF_DEC)) + goto failed; + + ret = 0; +failed: + free(key, M_QAT); + free(val, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to clean up general section\n"); + + return ret; +} + +static int +adf_cfg_process_kernel_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + u8 serv_type = 0; + + for (serv_type = NA; serv_type <= USED; serv_type++) { + switch (serv_type) { + case NA: + break; + case CRYPTO: + case ASYM: + case SYM: + if (adf_cfg_is_svc_enabled(accel_dev, serv_type)) + if (adf_cfg_create_rings_entries_for_cy_inst( + accel_dev, + sec_name, + sec_name, + 0, + (enum adf_cfg_service_type)serv_type)) + goto failed; + break; + case COMP: + if (adf_cfg_is_svc_enabled(accel_dev, serv_type)) + if (adf_cfg_create_rings_entries_for_dc_inst( + accel_dev, sec_name, sec_name, 0)) + goto failed; + break; + case USED: + break; + default: + pr_err("Unknown service type of instance %d.\n", + serv_type); + } + } + + return 0; + +failed: + return EFAULT; +} + +static int +adf_cfg_cleanup_kernel_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + return 0; +} + +static int +adf_cfg_create_accel_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + /* Find global settings for coalescing. Use defaults if not found */ + unsigned long accel_coales = 0; + unsigned long accel_coales_timer = 0; + unsigned long accel_coales_num_msg = 0; + unsigned long cpu; + char *key = NULL; + char *val = NULL; + int ret = EFAULT; + int index = 0; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + if (!hw_device) + goto failed; + + key = malloc(ADF_CFG_MAX_KEY_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + val = malloc(ADF_CFG_MAX_VAL_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + strlcpy(key, + ADF_ETRMGR_COALESCING_ENABLED, + ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value(accel_dev, ADF_GENERAL_SEC, key, &accel_coales)) + accel_coales = ADF_CFG_ACCEL_DEF_COALES; + + strlcpy(key, ADF_ETRMGR_COALESCE_TIMER, ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value( + accel_dev, ADF_GENERAL_SEC, key, &accel_coales_timer)) + accel_coales_timer = ADF_CFG_ACCEL_DEF_COALES_TIMER; + + strlcpy(key, + ADF_ETRMGR_COALESCING_MSG_ENABLED, + ADF_CFG_MAX_KEY_LEN_IN_BYTES); + if (adf_cfg_set_value( + accel_dev, ADF_GENERAL_SEC, key, &accel_coales_num_msg)) + accel_coales_num_msg = ADF_CFG_ACCEL_DEF_COALES_NUM_MSG; + + for (index = 0; index < hw_device->num_banks; index++) { + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_ETRMGR_COALESCING_ENABLED_FORMAT, + index); + ret = adf_cfg_add_key_value_param( + accel_dev, sec_name, key, &accel_coales, ADF_DEC); + if (ret != 0) + goto failed; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_ETRMGR_COALESCE_TIMER_FORMAT, + index); + ret = adf_cfg_add_key_value_param( + accel_dev, sec_name, key, &accel_coales_timer, ADF_DEC); + if (ret != 0) + goto failed; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_ETRMGR_COALESCING_MSG_ENABLED_FORMAT, + index); + ret = adf_cfg_add_key_value_param( + accel_dev, sec_name, key, &accel_coales_num_msg, ADF_DEC); + if (ret != 0) + goto failed; + + cpu = ADF_CFG_AFFINITY_WHATEVER; + + snprintf(key, + ADF_CFG_MAX_KEY_LEN_IN_BYTES, + ADF_ETRMGR_CORE_AFFINITY_FORMAT, + index); + ret = adf_cfg_add_key_value_param( + accel_dev, sec_name, key, &cpu, ADF_DEC); + if (ret != 0) + goto failed; + } + + ret = 0; + +failed: + free(key, M_QAT); + free(val, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to create accel section\n"); + + return ret; +} + +static int +adf_cfg_cleanup_accel_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + return 0; +} + +static int +adf_cfg_process_accel_section(struct adf_accel_dev *accel_dev, + const char *sec_name) +{ + int accel_num = 0; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + char *derived_name = NULL; + int ret = EFAULT; + + if (!hw_device) + goto failed; + + if (hw_device->num_logical_accel == 0) + goto failed; + + derived_name = + malloc(ADF_CFG_MAX_SECTION_LEN_IN_BYTES, M_QAT, M_WAITOK | M_ZERO); + + for (accel_num = 0; accel_num < hw_device->num_logical_accel; + accel_num++) { + snprintf(derived_name, + ADF_CFG_MAX_SECTION_LEN_IN_BYTES, + ADF_ACCEL_STR, + accel_num); + ret = adf_cfg_section_add(accel_dev, derived_name); + if (ret != 0) + goto failed; + + ret = adf_cfg_create_accel_section(accel_dev, derived_name); + if (ret != 0) + goto failed; + } + + ret = 0; +failed: + free(derived_name, M_QAT); + + if (ret) + device_printf(GET_DEV(accel_dev), + "Failed to process accel section\n"); + + return ret; +} + +int +adf_cfg_process_section(struct adf_accel_dev *accel_dev, + const char *sec_name, + int dev) +{ + if (!strcmp(sec_name, ADF_GENERAL_SEC) || + !strcmp(sec_name, ADF_INLINE_SEC)) + return adf_cfg_process_section_no_op(accel_dev, sec_name); + else if (!strcmp(sec_name, ADF_KERNEL_SEC) || + !strcmp(sec_name, ADF_KERNEL_SAL_SEC)) + return adf_cfg_process_kernel_section(accel_dev, sec_name); + else if (!strcmp(sec_name, ADF_ACCEL_SEC)) + return adf_cfg_process_accel_section(accel_dev, sec_name); + else + return adf_cfg_process_user_section(accel_dev, sec_name, dev); +} + +int +adf_cfg_cleanup_section(struct adf_accel_dev *accel_dev, + const char *sec_name, + int dev) +{ + if (!strcmp(sec_name, ADF_GENERAL_SEC)) + return adf_cfg_cleanup_general_section(accel_dev, sec_name); + else if (!strcmp(sec_name, ADF_INLINE_SEC)) + return adf_cfg_process_section_no_op(accel_dev, sec_name); + else if (!strcmp(sec_name, ADF_KERNEL_SEC) || + !strcmp(sec_name, ADF_KERNEL_SAL_SEC)) + return adf_cfg_cleanup_kernel_section(accel_dev, sec_name); + else if (strstr(sec_name, ADF_ACCEL_SEC)) + return adf_cfg_cleanup_accel_section(accel_dev, sec_name); + else + return adf_cfg_cleanup_user_section(accel_dev, sec_name); +} + +int +adf_cfg_setup_irq(struct adf_accel_dev *accel_dev) +{ + int ret = EFAULT; + struct adf_accel_pci *info_pci_dev = &accel_dev->accel_pci_dev; + struct adf_cfg_device *cfg_dev = NULL; + struct msix_entry *msixe = NULL; + u32 num_msix = 0; + int index = 0; + int computed_core = 0; + + if (!accel_dev || !accel_dev->cfg || !accel_dev->hw_device) + goto failed; + + cfg_dev = accel_dev->cfg->dev; + if (!cfg_dev) + goto failed; + + msixe = + (struct msix_entry *)accel_dev->accel_pci_dev.msix_entries.entries; + num_msix = accel_dev->accel_pci_dev.msix_entries.num_entries; + if (!msixe) + goto cleanup_and_fail; + + /* + * Here we want to set the affinity of kernel and epoll mode + * bundle into user defined value. + * Because in adf_isr.c we setup core affinity by round-robin + * we need to reset it after device up done. + */ + for (index = 0; index < accel_dev->hw_device->num_banks; index++) { + struct adf_cfg_bundle *bundle = cfg_dev->bundles[index]; + + if (!bundle) + continue; + + if (bundle->type != KERNEL && + bundle->polling_mode != ADF_CFG_RESP_EPOLL) + continue; + + if (bundle->number >= num_msix) + goto cleanup_and_fail; + + computed_core = CPU_FFS(&bundle->affinity_mask) - 1; + bus_bind_intr(info_pci_dev->pci_dev, + msixe[index].irq, + computed_core); + } + ret = 0; + +cleanup_and_fail: + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + +failed: + return ret; +} diff --git a/sys/dev/qat/qat_common/adf_cfg_section.h b/sys/dev/qat/qat_common/adf_cfg_section.h new file mode 100644 index 00000000000..20432cb2fc2 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_cfg_section.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_CFG_SECTION_H_ +#define ADF_CFG_SECTION_H_ + +#include +#include "adf_accel_devices.h" +#include "adf_cfg_common.h" +#include "adf_cfg_strings.h" + +int adf_cfg_process_section(struct adf_accel_dev *accel_dev, + const char *section_name, + int dev); + +int adf_cfg_cleanup_section(struct adf_accel_dev *accel_dev, + const char *section_name, + int dev); +#endif diff --git a/sys/dev/qat/qat_common/adf_clock.c b/sys/dev/qat/qat_common/adf_clock.c new file mode 100644 index 00000000000..1a44b87cab5 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_clock.c @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_accel_devices.h" +#include "adf_common_drv.h" + +#include + +#define MEASURE_CLOCK_RETRIES 10 +#define MEASURE_CLOCK_DELTA_THRESHOLD 100 +#define MEASURE_CLOCK_DELAY 10000 +#define ME_CLK_DIVIDER 16 + +#define CLK_DBGFS_FILE "frequency" +#define HB_SYSCTL_ERR(RC) \ + do { \ + if (!RC) { \ + device_printf(GET_DEV(accel_dev), \ + "Memory allocation failed in \ + adf_heartbeat_dbg_add\n"); \ + return ENOMEM; \ + } \ + } while (0) + +int +adf_clock_debugfs_add(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_sysctl_tree; + struct sysctl_oid *rc = 0; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + rc = SYSCTL_ADD_UINT(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + CLK_DBGFS_FILE, + CTLFLAG_RD, + &hw_data->clock_frequency, + 0, + "clock frequency"); + HB_SYSCTL_ERR(rc); + return 0; +} + +/** + * adf_dev_measure_clock() -- Measure the CPM clock frequency + * @accel_dev: Pointer to acceleration device. + * @frequency: Pointer to returned frequency in Hz. + * + * Return: 0 on success, error code otherwise. + */ +static int +measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency) +{ + struct timespec ts1; + struct timespec ts2; + struct timespec ts3; + struct timespec ts4; + struct timespec delta; + u64 delta_us = 0; + u64 timestamp1 = 0; + u64 timestamp2 = 0; + u64 temp = 0; + int tries = 0; + + if (!accel_dev || !frequency) + return EIO; + do { + nanotime(&ts1); + if (adf_get_fw_timestamp(accel_dev, ×tamp1)) { + device_printf(GET_DEV(accel_dev), + "Failed to get fw timestamp\n"); + return EIO; + } + nanotime(&ts2); + + delta = timespec_sub(ts2, ts1); + temp = delta.tv_nsec; + do_div(temp, NSEC_PER_USEC); + + delta_us = delta.tv_sec * USEC_PER_SEC + temp; + } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD && + ++tries < MEASURE_CLOCK_RETRIES); + + if (tries >= MEASURE_CLOCK_RETRIES) { + device_printf(GET_DEV(accel_dev), + "Excessive clock measure delay\n"); + return EIO; + } + + usleep_range(MEASURE_CLOCK_DELAY, MEASURE_CLOCK_DELAY * 2); + tries = 0; + do { + nanotime(&ts3); + if (adf_get_fw_timestamp(accel_dev, ×tamp2)) { + device_printf(GET_DEV(accel_dev), + "Failed to get fw timestamp\n"); + return EIO; + } + nanotime(&ts4); + + delta = timespec_sub(ts4, ts3); + temp = delta.tv_nsec; + do_div(temp, NSEC_PER_USEC); + + delta_us = delta.tv_sec * USEC_PER_SEC + temp; + } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD && + ++tries < MEASURE_CLOCK_RETRIES); + + if (tries >= MEASURE_CLOCK_RETRIES) { + device_printf(GET_DEV(accel_dev), + "Excessive clock measure delay\n"); + return EIO; + } + + delta = timespec_sub(ts3, ts1); + temp = + delta.tv_sec * NSEC_PER_SEC + delta.tv_nsec + (NSEC_PER_USEC / 2); + do_div(temp, NSEC_PER_USEC); + delta_us = temp; + /* Don't pretend that this gives better than 100KHz resolution */ + temp = (timestamp2 - timestamp1) * ME_CLK_DIVIDER * 10 + (delta_us / 2); + do_div(temp, delta_us); + *frequency = temp * 100000; + + return 0; +} + +/** + * adf_dev_measure_clock() -- Measure the CPM clock frequency + * @accel_dev: Pointer to acceleration device. + * @frequency: Pointer to returned frequency in Hz. + * @min: Minimum expected frequency + * @max: Maximum expected frequency + * + * Return: 0 on success, error code otherwise. + */ +int +adf_dev_measure_clock(struct adf_accel_dev *accel_dev, + u32 *frequency, + u32 min, + u32 max) +{ + int ret; + u32 freq; + + ret = measure_clock(accel_dev, &freq); + if (ret) + return ret; + + if (freq < min) { + device_printf(GET_DEV(accel_dev), + "Slow clock %d MHz measured, assuming %d\n", + freq, + min); + freq = min; + } else if (freq > max) { + device_printf(GET_DEV(accel_dev), + "Fast clock %d MHz measured, assuming %d\n", + freq, + max); + freq = max; + } + *frequency = freq; + return 0; +} + +static inline u64 +timespec_to_ms(const struct timespec *ts) +{ + return (uint64_t)(ts->tv_sec * (1000)) + (ts->tv_nsec / NSEC_PER_MSEC); +} + +u64 +adf_clock_get_current_time(void) +{ + struct timespec ts; + + getnanotime(&ts); + return timespec_to_ms(&ts); +} diff --git a/sys/dev/qat/qat_common/adf_dev_err.c b/sys/dev/qat/qat_common/adf_dev_err.c new file mode 100644 index 00000000000..a315a7cd99d --- /dev/null +++ b/sys/dev/qat/qat_common/adf_dev_err.c @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_dev_err.h" + +struct reg_info { + size_t offs; + char *name; +}; + +static struct reg_info adf_err_regs[] = { + { ADF_ERRSOU0, "ERRSOU0" }, + { ADF_ERRSOU1, "ERRSOU1" }, + { ADF_ERRSOU3, "ERRSOU3" }, + { ADF_ERRSOU4, "ERRSOU4" }, + { ADF_ERRSOU5, "ERRSOU5" }, + { ADF_RICPPINTSTS, "RICPPINTSTS" }, + { ADF_RIERRPUSHID, "RIERRPUSHID" }, + { ADF_RIERRPULLID, "RIERRPULLID" }, + { ADF_CPP_CFC_ERR_STATUS, "CPP_CFC_ERR_STATUS" }, + { ADF_CPP_CFC_ERR_PPID, "CPP_CFC_ERR_PPID" }, + { ADF_TICPPINTSTS, "TICPPINTSTS" }, + { ADF_TIERRPUSHID, "TIERRPUSHID" }, + { ADF_TIERRPULLID, "TIERRPULLID" }, + { ADF_SECRAMUERR, "SECRAMUERR" }, + { ADF_SECRAMUERRAD, "SECRAMUERRAD" }, + { ADF_CPPMEMTGTERR, "CPPMEMTGTERR" }, + { ADF_ERRPPID, "ERRPPID" }, +}; + +static u32 +adf_get_intstatsssm(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_INTSTATSSM(dev)); +} + +static u32 +adf_get_pperr(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERR(dev)); +} + +static u32 +adf_get_pperrid(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERRID(dev)); +} + +static u32 +adf_get_uerrssmsh(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSH(dev)); +} + +static u32 +adf_get_uerrssmshad(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSHAD(dev)); +} + +static u32 +adf_get_uerrssmmmp0(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 0)); +} + +static u32 +adf_get_uerrssmmmp1(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 1)); +} + +static u32 +adf_get_uerrssmmmp2(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 2)); +} + +static u32 +adf_get_uerrssmmmp3(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 3)); +} + +static u32 +adf_get_uerrssmmmp4(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 4)); +} + +static u32 +adf_get_uerrssmmmpad0(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 0)); +} + +static u32 +adf_get_uerrssmmmpad1(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 1)); +} + +static u32 +adf_get_uerrssmmmpad2(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 2)); +} + +static u32 +adf_get_uerrssmmmpad3(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 3)); +} + +static u32 +adf_get_uerrssmmmpad4(struct resource *pmisc_bar_addr, size_t dev) +{ + return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 4)); +} + +struct reg_array_info { + u32 (*read)(struct resource *pmisc_bar_addr, size_t dev); + char *name; +}; + +static struct reg_array_info adf_accel_err_regs[] = { + { adf_get_intstatsssm, "INTSTATSSM" }, + { adf_get_pperr, "PPERR" }, + { adf_get_pperrid, "PPERRID" }, + { adf_get_uerrssmsh, "UERRSSMSH" }, + { adf_get_uerrssmshad, "UERRSSMSHAD" }, + { adf_get_uerrssmmmp0, "UERRSSMMMP0" }, + { adf_get_uerrssmmmp1, "UERRSSMMMP1" }, + { adf_get_uerrssmmmp2, "UERRSSMMMP2" }, + { adf_get_uerrssmmmp3, "UERRSSMMMP3" }, + { adf_get_uerrssmmmp4, "UERRSSMMMP4" }, + { adf_get_uerrssmmmpad0, "UERRSSMMMPAD0" }, + { adf_get_uerrssmmmpad1, "UERRSSMMMPAD1" }, + { adf_get_uerrssmmmpad2, "UERRSSMMMPAD2" }, + { adf_get_uerrssmmmpad3, "UERRSSMMMPAD3" }, + { adf_get_uerrssmmmpad4, "UERRSSMMMPAD4" }, +}; + +static char adf_printf_buf[128] = { 0 }; +static size_t adf_printf_len; + +static void +adf_print_flush(struct adf_accel_dev *accel_dev) +{ + if (adf_printf_len > 0) { + device_printf(GET_DEV(accel_dev), "%.128s\n", adf_printf_buf); + adf_printf_len = 0; + } +} + +static void +adf_print_reg(struct adf_accel_dev *accel_dev, + const char *name, + size_t idx, + u32 val) +{ + adf_printf_len += snprintf(&adf_printf_buf[adf_printf_len], + sizeof(adf_printf_buf) - adf_printf_len, + "%s[%zu],%.8x,", + name, + idx, + val); + + if (adf_printf_len >= 80) + adf_print_flush(accel_dev); +} + +void +adf_print_err_registers(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *misc_bar = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *csr = misc_bar->virt_addr; + size_t i; + unsigned int mask; + u32 val; + + for (i = 0; i < ARRAY_SIZE(adf_err_regs); ++i) { + val = ADF_CSR_RD(csr, adf_err_regs[i].offs); + + adf_print_reg(accel_dev, adf_err_regs[i].name, 0, val); + } + + for (i = 0; i < ARRAY_SIZE(adf_accel_err_regs); ++i) { + size_t accel; + + for (accel = 0, mask = hw_data->accel_mask; mask; + accel++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = adf_accel_err_regs[i].read(csr, accel); + + adf_print_reg(accel_dev, + adf_accel_err_regs[i].name, + accel, + val); + } + } + + adf_print_flush(accel_dev); +} + +static void +adf_log_slice_hang(struct adf_accel_dev *accel_dev, + u8 accel_num, + char *unit_name, + u8 unit_number) +{ + device_printf(GET_DEV(accel_dev), + "CPM #%x Slice Hang Detected unit: %s%d.\n", + accel_num, + unit_name, + unit_number); +} + +bool +adf_handle_slice_hang(struct adf_accel_dev *accel_dev, + u8 accel_num, + struct resource *csr, + u32 slice_hang_offset) +{ + u32 slice_hang = ADF_CSR_RD(csr, slice_hang_offset); + + if (!slice_hang) + return false; + + if (slice_hang & ADF_SLICE_HANG_AUTH0_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Auth", 0); + if (slice_hang & ADF_SLICE_HANG_AUTH1_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Auth", 1); + if (slice_hang & ADF_SLICE_HANG_AUTH2_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Auth", 2); + if (slice_hang & ADF_SLICE_HANG_CPHR0_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Cipher", 0); + if (slice_hang & ADF_SLICE_HANG_CPHR1_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Cipher", 1); + if (slice_hang & ADF_SLICE_HANG_CPHR2_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Cipher", 2); + if (slice_hang & ADF_SLICE_HANG_CMP0_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Comp", 0); + if (slice_hang & ADF_SLICE_HANG_CMP1_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Comp", 1); + if (slice_hang & ADF_SLICE_HANG_XLT0_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Xlator", 0); + if (slice_hang & ADF_SLICE_HANG_XLT1_MASK) + adf_log_slice_hang(accel_dev, accel_num, "Xlator", 1); + if (slice_hang & ADF_SLICE_HANG_MMP0_MASK) + adf_log_slice_hang(accel_dev, accel_num, "MMP", 0); + if (slice_hang & ADF_SLICE_HANG_MMP1_MASK) + adf_log_slice_hang(accel_dev, accel_num, "MMP", 1); + if (slice_hang & ADF_SLICE_HANG_MMP2_MASK) + adf_log_slice_hang(accel_dev, accel_num, "MMP", 2); + if (slice_hang & ADF_SLICE_HANG_MMP3_MASK) + adf_log_slice_hang(accel_dev, accel_num, "MMP", 3); + if (slice_hang & ADF_SLICE_HANG_MMP4_MASK) + adf_log_slice_hang(accel_dev, accel_num, "MMP", 4); + + /* Clear the associated interrupt */ + ADF_CSR_WR(csr, slice_hang_offset, slice_hang); + + return true; +} + +/** + * adf_check_slice_hang() - Check slice hang status + * + * Return: true if a slice hange interrupt is serviced.. + */ +bool +adf_check_slice_hang(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *misc_bar = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *csr = misc_bar->virt_addr; + u32 errsou3 = ADF_CSR_RD(csr, ADF_ERRSOU3); + u32 errsou5 = ADF_CSR_RD(csr, ADF_ERRSOU5); + u32 offset; + u32 accel_num; + bool handled = false; + u32 errsou[] = { errsou3, errsou3, errsou5, errsou5, errsou5 }; + u32 mask[] = { ADF_EMSK3_CPM0_MASK, + ADF_EMSK3_CPM1_MASK, + ADF_EMSK5_CPM2_MASK, + ADF_EMSK5_CPM3_MASK, + ADF_EMSK5_CPM4_MASK }; + unsigned int accel_mask; + + for (accel_num = 0, accel_mask = hw_data->accel_mask; accel_mask; + accel_num++, accel_mask >>= 1) { + if (!(accel_mask & 1)) + continue; + if (accel_num >= ARRAY_SIZE(errsou)) { + device_printf(GET_DEV(accel_dev), + "Invalid accel_num %d.\n", + accel_num); + break; + } + + if (errsou[accel_num] & mask[accel_num]) { + if (ADF_CSR_RD(csr, ADF_INTSTATSSM(accel_num)) & + ADF_INTSTATSSM_SHANGERR) { + offset = ADF_SLICEHANGSTATUS(accel_num); + handled |= adf_handle_slice_hang(accel_dev, + accel_num, + csr, + offset); + } + } + } + + return handled; +} diff --git a/sys/dev/qat/qat_common/adf_dev_mgr.c b/sys/dev/qat/qat_common/adf_dev_mgr.c new file mode 100644 index 00000000000..87a0744fa85 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_dev_mgr.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include "adf_cfg.h" +#include "adf_common_drv.h" + +#define ADF_AE_PAIR 2 +#define PKE_SLICES_PER_AE_PAIR 5 + +static LIST_HEAD(accel_table); +static LIST_HEAD(vfs_table); +static DEFINE_MUTEX(table_lock); +static uint32_t num_devices; +static u8 id_map[ADF_MAX_DEVICES]; + +struct vf_id_map { + u32 bdf; + u32 id; + u32 fake_id; + bool attached; + struct list_head list; +}; + +/** + * adf_get_vf_real_id() - Translate fake to real device id + * + * The "real" id is assigned to a device when it is initially + * bound to the driver. + * The "fake" id is usually the same as the real id, but + * can change when devices are unbound from the qat driver, + * perhaps to assign the device to a guest. + */ +static int +adf_get_vf_real_id(u32 fake) +{ + struct list_head *itr; + + list_for_each(itr, &vfs_table) + { + struct vf_id_map *ptr = list_entry(itr, struct vf_id_map, list); + if (ptr->fake_id == fake) + return ptr->id; + } + return -1; +} + +/** + * adf_clean_vf_map() - Cleans VF id mapings + * + * Function cleans internal ids for virtual functions. + * @vf: flag indicating whether mappings is cleaned + * for vfs only or for vfs and pfs + */ +void +adf_clean_vf_map(bool vf) +{ + struct vf_id_map *map; + struct list_head *ptr, *tmp; + + mutex_lock(&table_lock); + list_for_each_safe(ptr, tmp, &vfs_table) + { + map = list_entry(ptr, struct vf_id_map, list); + if (map->bdf != -1) { + id_map[map->id] = 0; + num_devices--; + } + + if (vf && map->bdf == -1) + continue; + + list_del(ptr); + free(map, M_QAT); + } + mutex_unlock(&table_lock); +} + +/** + * adf_devmgr_update_class_index() - Update internal index + * @hw_data: Pointer to internal device data. + * + * Function updates internal dev index for VFs + */ +void +adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data) +{ + struct adf_hw_device_class *class = hw_data->dev_class; + struct list_head *itr; + int i = 0; + + list_for_each(itr, &accel_table) + { + struct adf_accel_dev *ptr = + list_entry(itr, struct adf_accel_dev, list); + + if (ptr->hw_device->dev_class == class) + ptr->hw_device->instance_id = i++; + + if (i == class->instances) + break; + } +} + +static unsigned int +adf_find_free_id(void) +{ + unsigned int i; + + for (i = 0; i < ADF_MAX_DEVICES; i++) { + if (!id_map[i]) { + id_map[i] = 1; + return i; + } + } + return ADF_MAX_DEVICES + 1; +} + +/** + * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework + * @accel_dev: Pointer to acceleration device. + * @pf: Corresponding PF if the accel_dev is a VF + * + * Function adds acceleration device to the acceleration framework. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf) +{ + struct list_head *itr; + int ret = 0; + + if (num_devices == ADF_MAX_DEVICES) { + device_printf(GET_DEV(accel_dev), + "Only support up to %d devices\n", + ADF_MAX_DEVICES); + return EFAULT; + } + + mutex_lock(&table_lock); + + /* PF on host or VF on guest */ + if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) { + struct vf_id_map *map; + + list_for_each(itr, &accel_table) + { + struct adf_accel_dev *ptr = + list_entry(itr, struct adf_accel_dev, list); + + if (ptr == accel_dev) { + ret = EEXIST; + goto unlock; + } + } + + list_add_tail(&accel_dev->list, &accel_table); + accel_dev->accel_id = adf_find_free_id(); + if (accel_dev->accel_id > ADF_MAX_DEVICES) { + ret = EFAULT; + goto unlock; + } + num_devices++; + map = malloc(sizeof(*map), M_QAT, GFP_KERNEL); + if (!map) { + ret = ENOMEM; + goto unlock; + } + map->bdf = ~0; + map->id = accel_dev->accel_id; + map->fake_id = map->id; + map->attached = true; + list_add_tail(&map->list, &vfs_table); + } else if (accel_dev->is_vf && pf) { + ret = ENOTSUP; + goto unlock; + } +unlock: + mutex_unlock(&table_lock); + return ret; +} + +struct list_head * +adf_devmgr_get_head(void) +{ + return &accel_table; +} + +/** + * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework. + * @accel_dev: Pointer to acceleration device. + * @pf: Corresponding PF if the accel_dev is a VF + * + * Function removes acceleration device from the acceleration framework. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf) +{ + mutex_lock(&table_lock); + if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) { + id_map[accel_dev->accel_id] = 0; + num_devices--; + } + list_del(&accel_dev->list); + mutex_unlock(&table_lock); +} + +struct adf_accel_dev * +adf_devmgr_get_first(void) +{ + struct adf_accel_dev *dev = NULL; + + if (!list_empty(&accel_table)) + dev = + list_first_entry(&accel_table, struct adf_accel_dev, list); + return dev; +} + +/** + * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev. + * @accel_dev: Pointer to pci device. + * + * Function returns acceleration device associated with the given pci device. + * To be used by QAT device specific drivers. + * + * Return: pointer to accel_dev or NULL if not found. + */ +struct adf_accel_dev * +adf_devmgr_pci_to_accel_dev(device_t pci_dev) +{ + struct list_head *itr; + + mutex_lock(&table_lock); + list_for_each(itr, &accel_table) + { + struct adf_accel_dev *ptr = + list_entry(itr, struct adf_accel_dev, list); + + if (ptr->accel_pci_dev.pci_dev == pci_dev) { + mutex_unlock(&table_lock); + return ptr; + } + } + mutex_unlock(&table_lock); + return NULL; +} + +struct adf_accel_dev * +adf_devmgr_get_dev_by_id(uint32_t id) +{ + struct list_head *itr; + int real_id; + + mutex_lock(&table_lock); + real_id = adf_get_vf_real_id(id); + if (real_id < 0) + goto unlock; + + id = real_id; + + list_for_each(itr, &accel_table) + { + struct adf_accel_dev *ptr = + list_entry(itr, struct adf_accel_dev, list); + if (ptr->accel_id == id) { + mutex_unlock(&table_lock); + return ptr; + } + } +unlock: + mutex_unlock(&table_lock); + return NULL; +} + +int +adf_devmgr_verify_id(uint32_t *id) +{ + struct adf_accel_dev *accel_dev; + + if (*id == ADF_CFG_ALL_DEVICES) + return 0; + + accel_dev = adf_devmgr_get_dev_by_id(*id); + if (!accel_dev) + return ENODEV; + + /* Correct the id if real and fake differ */ + *id = accel_dev->accel_id; + return 0; +} + +static int +adf_get_num_dettached_vfs(void) +{ + struct list_head *itr; + int vfs = 0; + + mutex_lock(&table_lock); + list_for_each(itr, &vfs_table) + { + struct vf_id_map *ptr = list_entry(itr, struct vf_id_map, list); + if (ptr->bdf != ~0 && !ptr->attached) + vfs++; + } + mutex_unlock(&table_lock); + return vfs; +} + +void +adf_devmgr_get_num_dev(uint32_t *num) +{ + *num = num_devices - adf_get_num_dettached_vfs(); +} + +/** + * adf_dev_in_use() - Check whether accel_dev is currently in use + * @accel_dev: Pointer to acceleration device. + * + * To be used by QAT device specific drivers. + * + * Return: 1 when device is in use, 0 otherwise. + */ +int +adf_dev_in_use(struct adf_accel_dev *accel_dev) +{ + return atomic_read(&accel_dev->ref_count) != 0; +} + +/** + * adf_dev_get() - Increment accel_dev reference count + * @accel_dev: Pointer to acceleration device. + * + * Increment the accel_dev refcount and if this is the first time + * incrementing it during this period the accel_dev is in use, + * increment the module refcount too. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_dev_get(struct adf_accel_dev *accel_dev) +{ + if (atomic_add_return(1, &accel_dev->ref_count) == 1) + device_busy(GET_DEV(accel_dev)); +} + +/** + * adf_dev_put() - Decrement accel_dev reference count + * @accel_dev: Pointer to acceleration device. + * + * Decrement the accel_dev refcount and if this is the last time + * decrementing it during this period the accel_dev is in use, + * decrement the module refcount too. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_dev_put(struct adf_accel_dev *accel_dev) +{ + if (atomic_sub_return(1, &accel_dev->ref_count) == 0) + device_unbusy(GET_DEV(accel_dev)); +} + +/** + * adf_devmgr_in_reset() - Check whether device is in reset + * @accel_dev: Pointer to acceleration device. + * + * To be used by QAT device specific drivers. + * + * Return: 1 when the device is being reset, 0 otherwise. + */ +int +adf_devmgr_in_reset(struct adf_accel_dev *accel_dev) +{ + return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status); +} + +/** + * adf_dev_started() - Check whether device has started + * @accel_dev: Pointer to acceleration device. + * + * To be used by QAT device specific drivers. + * + * Return: 1 when the device has started, 0 otherwise + */ +int +adf_dev_started(struct adf_accel_dev *accel_dev) +{ + return test_bit(ADF_STATUS_STARTED, &accel_dev->status); +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_admin.c b/sys/dev/qat/qat_common/adf_freebsd_admin.c new file mode 100644 index 00000000000..2ad91988794 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_admin.c @@ -0,0 +1,602 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include "adf_heartbeat.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ADF_CONST_TABLE_VERSION_BYTE (0) +/* Keep version number in range 0-255 */ +#define ADF_CONST_TABLE_VERSION (1) + +/* Admin Messages Registers */ +#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574) +#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578) +#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970 +#define ADF_DH895XCC_MAILBOX_STRIDE 0x1000 +#define ADF_ADMINMSG_LEN 32 +#define FREEBSD_ALLIGNMENT_SIZE 64 +#define ADF_INIT_CONFIG_SIZE 1024 + +static u8 const_tab[1024] __aligned(1024) = { +ADF_CONST_TABLE_VERSION, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, +0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, +0x54, 0x32, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, +0x89, 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x05, 0x9e, +0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd, 0x17, 0xf7, 0x0e, 0x59, 0x39, +0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58, 0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe, +0xfa, 0x4f, 0xa4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, +0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, +0x9b, 0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19, 0x05, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29, +0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, 0xdd, 0x17, +0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67, 0x33, 0x26, 0x67, 0xff, +0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87, 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, +0x2e, 0x0d, 0x64, 0xf9, 0x8f, 0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, +0xa4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, +0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, +0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, 0x0e, 0x52, +0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f, +0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, +0x7e, 0x21, 0x79, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x02, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, +0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x2B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define ADF_ADMIN_POLL_INTERVAL_US 20 +#define ADF_ADMIN_POLL_RETRIES 5000 + +static void +dma_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + bus_addr_t *addr; + + addr = arg; + if (error == 0 && nseg == 1) + *addr = segs[0].ds_addr; + else + *addr = 0; +} + +int +adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev, + u32 ae, + void *in, + void *out) +{ + struct adf_admin_comms *admin = accel_dev->admin; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *mailbox = admin->mailbox_addr; + struct admin_info admin_csrs_info; + + hw_data->get_admin_info(&admin_csrs_info); + int offset = ae * ADF_ADMINMSG_LEN * 2; + int mb_offset = + ae * ADF_DH895XCC_MAILBOX_STRIDE + admin_csrs_info.mailbox_offset; + + int times, received; + struct icp_qat_fw_init_admin_req *request = in; + + sx_xlock(&admin->lock); + + if (ADF_CSR_RD(mailbox, mb_offset) == 1) { + sx_xunlock(&admin->lock); + return EAGAIN; + } + + memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN); + ADF_CSR_WR(mailbox, mb_offset, 1); + received = 0; + for (times = 0; times < ADF_ADMIN_POLL_RETRIES; times++) { + usleep_range(ADF_ADMIN_POLL_INTERVAL_US, + ADF_ADMIN_POLL_INTERVAL_US * 2); + if (ADF_CSR_RD(mailbox, mb_offset) == 0) { + received = 1; + break; + } + } + if (received) + memcpy(out, + admin->virt_addr + offset + ADF_ADMINMSG_LEN, + ADF_ADMINMSG_LEN); + else + device_printf(GET_DEV(accel_dev), + "Failed to send admin msg %d to accelerator %d\n", + request->cmd_id, + ae); + + sx_xunlock(&admin->lock); + return received ? 0 : EFAULT; +} + +static inline int +adf_set_dc_ibuf(struct adf_accel_dev *accel_dev, + struct icp_qat_fw_init_admin_req *req) +{ + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + unsigned long ibuf_size = 0; + + if (!adf_cfg_get_param_value( + accel_dev, ADF_GENERAL_SEC, ADF_INTER_BUF_SIZE, val)) { + if (compat_strtoul(val, 0, &ibuf_size)) + return EFAULT; + } + + if (ibuf_size != 32 && ibuf_size != 64) + ibuf_size = 64; + + req->ibuf_size_in_kb = ibuf_size; + + return 0; +} + +int +adf_send_admin(struct adf_accel_dev *accel_dev, + struct icp_qat_fw_init_admin_req *req, + struct icp_qat_fw_init_admin_resp *resp, + u32 ae_mask) +{ + int i; + unsigned int mask; + + for (i = 0, mask = ae_mask; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + if (adf_put_admin_msg_sync(accel_dev, i, req, resp) || + resp->status) + return EFAULT; + } + + return 0; +} + +static int +adf_init_me(struct adf_accel_dev *accel_dev) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 ae_mask = hw_device->ae_mask; + + explicit_bzero(&req, sizeof(req)); + explicit_bzero(&resp, sizeof(resp)); + req.cmd_id = ICP_QAT_FW_INIT_ME; + + if (adf_set_dc_ibuf(accel_dev, &req)) + return EFAULT; + if (accel_dev->aram_info) { + req.init_cfg_sz = sizeof(*accel_dev->aram_info); + req.init_cfg_ptr = (u64)accel_dev->admin->aram_map_phys_addr; + } + if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) + return EFAULT; + + return 0; +} + +static int +adf_set_heartbeat_timer(struct adf_accel_dev *accel_dev) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 ae_mask = hw_device->ae_mask; + u32 heartbeat_ticks; + + explicit_bzero(&req, sizeof(req)); + req.cmd_id = ICP_QAT_FW_HEARTBEAT_TIMER_SET; + req.hb_cfg_ptr = accel_dev->admin->phy_hb_addr; + if (adf_get_hb_timer(accel_dev, &heartbeat_ticks)) + return EINVAL; + req.heartbeat_ticks = heartbeat_ticks; + + if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) + return EFAULT; + + return 0; +} + +static int +adf_get_dc_capabilities(struct adf_accel_dev *accel_dev, u32 *capabilities) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + u32 ae_mask = 1; + + explicit_bzero(&req, sizeof(req)); + req.cmd_id = ICP_QAT_FW_COMP_CAPABILITY_GET; + + if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) + return EFAULT; + + *capabilities = resp.extended_features; + + return 0; +} + +static int +adf_set_fw_constants(struct adf_accel_dev *accel_dev) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 ae_mask = hw_device->ae_mask; + + explicit_bzero(&req, sizeof(req)); + req.cmd_id = ICP_QAT_FW_CONSTANTS_CFG; + + req.init_cfg_sz = sizeof(const_tab); + req.init_cfg_ptr = accel_dev->admin->const_tbl_addr; + + if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) + return EFAULT; + + return 0; +} + +static int +adf_get_fw_status(struct adf_accel_dev *accel_dev, + u8 *major, + u8 *minor, + u8 *patch) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + u32 ae_mask = 1; + + explicit_bzero(&req, sizeof(req)); + req.cmd_id = ICP_QAT_FW_STATUS_GET; + + if (adf_send_admin(accel_dev, &req, &resp, ae_mask)) + return EFAULT; + + *major = resp.version_major_num; + *minor = resp.version_minor_num; + *patch = resp.version_patch_num; + + return 0; +} + +int +adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp rsp; + unsigned int ae_mask = 1; + + if (!accel_dev || !timestamp) + return EFAULT; + + explicit_bzero(&req, sizeof(req)); + req.cmd_id = ICP_QAT_FW_TIMER_GET; + + if (adf_send_admin(accel_dev, &req, &rsp, ae_mask)) + return EFAULT; + + *timestamp = rsp.timestamp; + return 0; +} + +int +adf_get_fw_pke_stats(struct adf_accel_dev *accel_dev, + u64 *suc_count, + u64 *unsuc_count) +{ + struct icp_qat_fw_init_admin_req req = { 0 }; + struct icp_qat_fw_init_admin_resp resp = { 0 }; + unsigned long sym_ae_msk = 0; + u8 sym_ae_msk_size = 0; + u8 i = 0; + + if (!suc_count || !unsuc_count) + return EFAULT; + + sym_ae_msk = accel_dev->au_info->sym_ae_msk; + sym_ae_msk_size = + sizeof(accel_dev->au_info->sym_ae_msk) * BITS_PER_BYTE; + + req.cmd_id = ICP_QAT_FW_PKE_REPLAY_STATS_GET; + for_each_set_bit(i, &sym_ae_msk, sym_ae_msk_size) + { + memset(&resp, 0, sizeof(struct icp_qat_fw_init_admin_resp)); + if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) || + resp.status) { + return EFAULT; + } + *suc_count += resp.successful_count; + *unsuc_count += resp.unsuccessful_count; + } + return 0; +} + +/** + * adf_send_admin_init() - Function sends init message to FW + * @accel_dev: Pointer to acceleration device. + * + * Function sends admin init message to the FW + * + * Return: 0 on success, error code otherwise. + */ +int +adf_send_admin_init(struct adf_accel_dev *accel_dev) +{ + int ret; + u32 dc_capabilities = 0; + unsigned int storage_enabled = 0; + + if (GET_HW_DATA(accel_dev)->query_storage_cap) { + ret = adf_get_dc_capabilities(accel_dev, &dc_capabilities); + if (ret) { + device_printf(GET_DEV(accel_dev), + "Cannot get dc capabilities\n"); + return ret; + } + accel_dev->hw_device->extended_dc_capabilities = + dc_capabilities; + } else { + ret = GET_HW_DATA(accel_dev)->get_storage_enabled( + accel_dev, &storage_enabled); + if (ret) { + device_printf(GET_DEV(accel_dev), + "Cannot get storage enabled\n"); + return ret; + } + } + + ret = adf_set_heartbeat_timer(accel_dev); + if (ret) { + if (ret == EINVAL) { + device_printf(GET_DEV(accel_dev), + "Cannot set heartbeat timer\n"); + return ret; + } + device_printf(GET_DEV(accel_dev), + "Heartbeat is not supported\n"); + } + + ret = adf_get_fw_status(accel_dev, + &accel_dev->fw_versions.fw_version_major, + &accel_dev->fw_versions.fw_version_minor, + &accel_dev->fw_versions.fw_version_patch); + if (ret) { + device_printf(GET_DEV(accel_dev), "Cannot get fw version\n"); + return ret; + } + + device_printf(GET_DEV(accel_dev), + "FW version: %d.%d.%d\n", + accel_dev->fw_versions.fw_version_major, + accel_dev->fw_versions.fw_version_minor, + accel_dev->fw_versions.fw_version_patch); + + ret = adf_set_fw_constants(accel_dev); + if (ret) { + device_printf(GET_DEV(accel_dev), "Cannot set fw constants\n"); + return ret; + } + + ret = adf_init_me(accel_dev); + if (ret) + device_printf(GET_DEV(accel_dev), "Cannot init AE\n"); + + return ret; +} + +int +adf_init_admin_comms(struct adf_accel_dev *accel_dev) +{ + struct adf_admin_comms *admin = NULL; + struct adf_hw_device_data *hw_data = NULL; + struct adf_bar *pmisc = NULL; + struct resource *csr = NULL; + struct admin_info admin_csrs_info; + unsigned int adminmsg_u, adminmsg_l; + u64 reg_val = 0; + int ret = 0; + + admin = kzalloc_node(sizeof(*accel_dev->admin), + M_WAITOK | M_ZERO, + dev_to_node(GET_DEV(accel_dev))); + hw_data = accel_dev->hw_device; + pmisc = &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + csr = pmisc->virt_addr; + ret = bus_dma_mem_create(&admin->dma_mem, + accel_dev->dma_tag, + FREEBSD_ALLIGNMENT_SIZE, + BUS_SPACE_MAXADDR, + PAGE_SIZE, + 0); + if (ret != 0) { + device_printf(GET_DEV(accel_dev), + "Failed to allocate dma buff\n"); + kfree(admin); + return ret; + } + admin->virt_addr = admin->dma_mem.dma_vaddr; + admin->phy_addr = admin->dma_mem.dma_baddr; + bzero(admin->virt_addr, PAGE_SIZE); + + ret = bus_dmamap_create(accel_dev->dma_tag, 0, &admin->const_tbl_map); + if (ret != 0) { + device_printf(GET_DEV(accel_dev), "Failed to create DMA map\n"); + bus_dma_mem_free(&admin->dma_mem); + kfree(admin); + return ret; + } + + ret = bus_dmamap_load(accel_dev->dma_tag, + admin->const_tbl_map, + (void *)const_tab, + 1024, + dma_callback, + &admin->const_tbl_addr, + BUS_DMA_NOWAIT); + if (ret == 0 && admin->const_tbl_addr == 0) + ret = EFBIG; + if (ret != 0) { + device_printf(GET_DEV(accel_dev), + "Failed to map const table for DMA\n"); + bus_dmamap_destroy(accel_dev->dma_tag, admin->const_tbl_map); + bus_dma_mem_free(&admin->dma_mem); + kfree(admin); + return ret; + } + + /* DMA ARAM address map */ + if (accel_dev->aram_info) { + ret = + bus_dmamap_create(accel_dev->dma_tag, 0, &admin->aram_map); + if (ret != 0) { + device_printf(GET_DEV(accel_dev), + "Failed to create DMA map\n"); + bus_dma_mem_free(&admin->dma_mem); + kfree(admin); + return ret; + } + ret = bus_dmamap_load(accel_dev->dma_tag, + admin->aram_map, + (void *)accel_dev->aram_info, + sizeof(*accel_dev->aram_info), + dma_callback, + &admin->aram_map_phys_addr, + BUS_DMA_NOWAIT); + + if (ret == 0 && admin->aram_map_phys_addr == 0) + ret = EFBIG; + if (ret != 0) { + device_printf(GET_DEV(accel_dev), + "Failed to map aram phys addr for DMA\n"); + bus_dmamap_destroy(accel_dev->dma_tag, admin->aram_map); + bus_dma_mem_free(&admin->dma_mem); + kfree(admin); + return ret; + } + } + + ret = bus_dma_mem_create(&admin->dma_hb, + accel_dev->dma_tag, + FREEBSD_ALLIGNMENT_SIZE, + BUS_SPACE_MAXADDR, + PAGE_SIZE, + 0); + if (ret != 0) { + device_printf(GET_DEV(accel_dev), + "Failed to allocate dma buff\n"); + bus_dmamap_unload(accel_dev->dma_tag, admin->const_tbl_map); + bus_dmamap_destroy(accel_dev->dma_tag, admin->const_tbl_map); + bus_dma_mem_free(&admin->dma_mem); + kfree(admin); + return ret; + } + + admin->virt_hb_addr = admin->dma_hb.dma_vaddr; + admin->phy_hb_addr = admin->dma_hb.dma_baddr; + bzero(admin->virt_hb_addr, PAGE_SIZE); + + hw_data->get_admin_info(&admin_csrs_info); + + adminmsg_u = admin_csrs_info.admin_msg_ur; + adminmsg_l = admin_csrs_info.admin_msg_lr; + reg_val = (u64)admin->phy_addr; + ADF_CSR_WR(csr, adminmsg_u, reg_val >> 32); + ADF_CSR_WR(csr, adminmsg_l, reg_val); + sx_init(&admin->lock, "qat admin"); + admin->mailbox_addr = csr; + accel_dev->admin = admin; + return 0; +} + +void +adf_exit_admin_comms(struct adf_accel_dev *accel_dev) +{ + struct adf_admin_comms *admin = accel_dev->admin; + + if (!admin) + return; + + if (admin->virt_addr) + bus_dma_mem_free(&admin->dma_mem); + + if (admin->virt_hb_addr) + bus_dma_mem_free(&admin->dma_hb); + + bus_dmamap_unload(accel_dev->dma_tag, admin->const_tbl_map); + bus_dmamap_destroy(accel_dev->dma_tag, admin->const_tbl_map); + sx_destroy(&admin->lock); + kfree(admin); + accel_dev->admin = NULL; +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_cfg_dev_dbg.c b/sys/dev/qat/qat_common/adf_freebsd_cfg_dev_dbg.c new file mode 100644 index 00000000000..98c6206a1b0 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_cfg_dev_dbg.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_common_drv.h" +#include "adf_cfg_device.h" +#include "adf_cfg_dev_dbg.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static int qat_dev_cfg_show(SYSCTL_HANDLER_ARGS) +{ + struct adf_cfg_device_data *dev_cfg; + struct adf_cfg_section *sec; + struct adf_cfg_key_val *ptr; + struct sbuf sb; + int error; + + sbuf_new_for_sysctl(&sb, NULL, 128, req); + dev_cfg = arg1; + sx_slock(&dev_cfg->lock); + list_for_each_entry(sec, &dev_cfg->sec_list, list) + { + sbuf_printf(&sb, "[%s]\n", sec->name); + list_for_each_entry(ptr, &sec->param_head, list) + { + sbuf_printf(&sb, "%s = %s\n", ptr->key, ptr->val); + } + } + sx_sunlock(&dev_cfg->lock); + error = sbuf_finish(&sb); + sbuf_delete(&sb); + return error; +} + +int +adf_cfg_dev_dbg_add(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + device_t dev; + + dev = GET_DEV(accel_dev); + dev_cfg_data->debug = + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, + "dev_cfg", + CTLFLAG_RD | CTLTYPE_STRING, + dev_cfg_data, + 0, + qat_dev_cfg_show, + "A", + "Device configuration"); + + if (!dev_cfg_data->debug) { + device_printf(dev, "Failed to create qat cfg sysctl.\n"); + return ENXIO; + } + return 0; +} + +void +adf_cfg_dev_dbg_remove(struct adf_accel_dev *accel_dev) +{ + struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg; + + if (dev_cfg_data->dev) { + adf_cfg_device_clear(dev_cfg_data->dev, accel_dev); + free(dev_cfg_data->dev, M_QAT); + dev_cfg_data->dev = NULL; + } +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_cnvnr_ctrs_dbg.c b/sys/dev/qat/qat_common/adf_freebsd_cnvnr_ctrs_dbg.c new file mode 100644 index 00000000000..51fc40ecab2 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_cnvnr_ctrs_dbg.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include "adf_cnvnr_freq_counters.h" +#include "adf_common_drv.h" +#include "adf_cfg.h" +#include "icp_qat_fw_init_admin.h" + +#define ADF_CNVNR_ERR_MASK 0xFFF + +#define LINE \ + "+-----------------------------------------------------------------+\n" +#define BANNER \ + "| CNV Error Freq Statistics for Qat Device |\n" +#define NEW_LINE "\n" +#define REPORT_ENTRY_FORMAT \ + "|[AE %2d]: TotalErrors: %5d : LastError: %s [%5d] |\n" +#define MAX_LINE_LENGTH 128 +#define MAX_REPORT_SIZE ((ADF_MAX_ACCELENGINES + 3) * MAX_LINE_LENGTH) + +#define PRINT_LINE(line) \ + (snprintf( \ + report_ptr, MAX_REPORT_SIZE - (report_ptr - report), "%s", line)) + +const char *cnvnr_err_str[] = {"No Error ", + "Checksum Error", + "Length Error-P", + "Decomp Error ", + "Xlat Error ", + "Length Error-C", + "Unknown Error "}; + +/* Handler for HB status check */ +static int qat_cnvnr_ctrs_dbg_read(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + struct adf_hw_device_data *hw_device; + struct icp_qat_fw_init_admin_req request; + struct icp_qat_fw_init_admin_resp response; + unsigned long dc_ae_msk = 0; + u8 num_aes = 0, ae = 0, error_type = 0, bytes_written = 0; + s16 latest_error = 0; + char report[MAX_REPORT_SIZE]; + char *report_ptr = report; + + /* Defensive check */ + if (!accel_dev || accel_dev->accel_id > ADF_MAX_DEVICES) + return EINVAL; + + if (!adf_dev_started(accel_dev)) { + device_printf(GET_DEV(accel_dev), "QAT Device not started\n"); + return EINVAL; + } + + hw_device = accel_dev->hw_device; + if (!hw_device) { + device_printf(GET_DEV(accel_dev), "Failed to get hw_device.\n"); + return EFAULT; + } + + /* Clean report memory */ + explicit_bzero(report, sizeof(report)); + + /* Adding banner to report */ + bytes_written = PRINT_LINE(NEW_LINE); + if (bytes_written <= 0) + return EINVAL; + report_ptr += bytes_written; + + bytes_written = PRINT_LINE(LINE); + if (bytes_written <= 0) + return EINVAL; + report_ptr += bytes_written; + + bytes_written = PRINT_LINE(BANNER); + if (bytes_written <= 0) + return EINVAL; + report_ptr += bytes_written; + + bytes_written = PRINT_LINE(LINE); + if (bytes_written <= 0) + return EINVAL; + report_ptr += bytes_written; + + if (accel_dev->au_info) + dc_ae_msk = accel_dev->au_info->dc_ae_msk; + + /* Extracting number of Acceleration Engines */ + num_aes = hw_device->get_num_aes(hw_device); + for (ae = 0; ae < num_aes; ae++) { + if (accel_dev->au_info && !test_bit(ae, &dc_ae_msk)) + continue; + explicit_bzero(&response, + sizeof(struct icp_qat_fw_init_admin_resp)); + request.cmd_id = ICP_QAT_FW_CNV_STATS_GET; + if (adf_put_admin_msg_sync( + accel_dev, ae, &request, &response) || + response.status) { + return EFAULT; + } + error_type = CNV_ERROR_TYPE_GET(response.latest_error); + if (error_type == CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH_ERROR || + error_type == CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH_ERROR) { + latest_error = + CNV_ERROR_LENGTH_DELTA_GET(response.latest_error); + } else if (error_type == CNV_ERR_TYPE_DECOMPRESSION_ERROR || + error_type == CNV_ERR_TYPE_TRANSLATION_ERROR) { + latest_error = + CNV_ERROR_DECOMP_STATUS_GET(response.latest_error); + } else { + latest_error = + response.latest_error & ADF_CNVNR_ERR_MASK; + } + + bytes_written = + snprintf(report_ptr, + MAX_REPORT_SIZE - (report_ptr - report), + REPORT_ENTRY_FORMAT, + ae, + response.error_count, + cnvnr_err_str[error_type], + latest_error); + if (bytes_written <= 0) { + printf("ERROR: No space left in CnV ctrs line buffer\n" + "\tAcceleration ID: %d, Engine: %d\n", + accel_dev->accel_id, + ae); + break; + } + report_ptr += bytes_written; + } + + sysctl_handle_string(oidp, report, sizeof(report), req); + return 0; +} + +int +adf_cnvnr_freq_counters_add(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_cnvnr_ctrs_sysctl_tree; + struct sysctl_oid *oid_rc; + + /* Defensive checks */ + if (!accel_dev) + return EINVAL; + + /* Creating context and tree */ + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_cnvnr_ctrs_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + /* Create "cnv_error" string type leaf - with callback */ + oid_rc = SYSCTL_ADD_PROC(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_cnvnr_ctrs_sysctl_tree), + OID_AUTO, + "cnv_error", + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + qat_cnvnr_ctrs_dbg_read, + "IU", + "QAT CnVnR status"); + + if (!oid_rc) { + printf("ERROR: Memory allocation failed\n"); + return ENOMEM; + } + return 0; +} + +void +adf_cnvnr_freq_counters_remove(struct adf_accel_dev *accel_dev) +{ +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_heartbeat_dbg.c b/sys/dev/qat/qat_common/adf_freebsd_heartbeat_dbg.c new file mode 100644 index 00000000000..47f43218f4d --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_heartbeat_dbg.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_common_drv.h" +#include "adf_cfg.h" +#include "adf_heartbeat.h" + +#define HB_SYSCTL_ERR(RC) \ + do { \ + if (RC == NULL) { \ + printf( \ + "Memory allocation failed in adf_heartbeat_dbg_add\n"); \ + return ENOMEM; \ + } \ + } while (0) + +/* Handler for HB status check */ +static int qat_dev_hb_read(SYSCTL_HANDLER_ARGS) +{ + enum adf_device_heartbeat_status hb_status = DEV_HB_UNRESPONSIVE; + struct adf_accel_dev *accel_dev = arg1; + struct adf_heartbeat *hb; + int ret = 0; + if (accel_dev == NULL) { + return EINVAL; + } + hb = accel_dev->heartbeat; + + /* if FW is loaded, proceed else set heartbeat down */ + if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) { + adf_heartbeat_status(accel_dev, &hb_status); + } + if (hb_status == DEV_HB_ALIVE) { + hb->heartbeat.hb_sysctlvar = 1; + } else { + hb->heartbeat.hb_sysctlvar = 0; + } + ret = sysctl_handle_int(oidp, &hb->heartbeat.hb_sysctlvar, 0, req); + return ret; +} + +int +adf_heartbeat_dbg_add(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_hb_sysctl_ctx; + struct sysctl_oid *qat_hb_sysctl_tree; + struct adf_heartbeat *hb; + struct sysctl_oid *rc = 0; + + if (accel_dev == NULL) { + return EINVAL; + } + + if (adf_heartbeat_init(accel_dev)) + return EINVAL; + + hb = accel_dev->heartbeat; + qat_hb_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_hb_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + rc = SYSCTL_ADD_UINT(qat_hb_sysctl_ctx, + SYSCTL_CHILDREN(qat_hb_sysctl_tree), + OID_AUTO, + "heartbeat_sent", + CTLFLAG_RD, + &hb->hb_sent_counter, + 0, + "HB sent count"); + HB_SYSCTL_ERR(rc); + + rc = SYSCTL_ADD_UINT(qat_hb_sysctl_ctx, + SYSCTL_CHILDREN(qat_hb_sysctl_tree), + OID_AUTO, + "heartbeat_failed", + CTLFLAG_RD, + &hb->hb_failed_counter, + 0, + "HB failed count"); + HB_SYSCTL_ERR(rc); + + rc = SYSCTL_ADD_PROC(qat_hb_sysctl_ctx, + SYSCTL_CHILDREN(qat_hb_sysctl_tree), + OID_AUTO, + "heartbeat", + CTLTYPE_INT | CTLFLAG_RD, + accel_dev, + 0, + qat_dev_hb_read, + "IU", + "QAT device status"); + HB_SYSCTL_ERR(rc); + return 0; +} + +int +adf_heartbeat_dbg_del(struct adf_accel_dev *accel_dev) +{ + adf_heartbeat_clean(accel_dev); + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_pfvf_ctrs_dbg.c b/sys/dev/qat/qat_common/adf_freebsd_pfvf_ctrs_dbg.c new file mode 100644 index 00000000000..3dc6a10f50d --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_pfvf_ctrs_dbg.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_dev_err.h" +#include "adf_freebsd_pfvf_ctrs_dbg.h" + +#define MAX_REPORT_LINES (14) +#define MAX_REPORT_LINE_LEN (64) +#define MAX_REPORT_SIZE (MAX_REPORT_LINES * MAX_REPORT_LINE_LEN) + +static void +adf_pfvf_ctrs_prepare_report(char *rep, struct pfvf_stats *pfvf_counters) +{ + unsigned int value = 0; + char *string = "unknown"; + unsigned int pos = 0; + char *ptr = rep; + + for (pos = 0; pos < MAX_REPORT_LINES; pos++) { + switch (pos) { + case 0: + string = "Messages written to CSR"; + value = pfvf_counters->tx; + break; + case 1: + string = "Messages read from CSR"; + value = pfvf_counters->rx; + break; + case 2: + string = "Spurious Interrupt"; + value = pfvf_counters->spurious; + break; + case 3: + string = "Block messages sent"; + value = pfvf_counters->blk_tx; + break; + case 4: + string = "Block messages received"; + value = pfvf_counters->blk_rx; + break; + case 5: + string = "Blocks received with CRC errors"; + value = pfvf_counters->crc_err; + break; + case 6: + string = "CSR in use"; + value = pfvf_counters->busy; + break; + case 7: + string = "No acknowledgment"; + value = pfvf_counters->no_ack; + break; + case 8: + string = "Collisions"; + value = pfvf_counters->collision; + break; + case 9: + string = "Put msg timeout"; + value = pfvf_counters->tx_timeout; + break; + case 10: + string = "No response received"; + value = pfvf_counters->rx_timeout; + break; + case 11: + string = "Responses received"; + value = pfvf_counters->rx_rsp; + break; + case 12: + string = "Messages re-transmitted"; + value = pfvf_counters->retry; + break; + case 13: + string = "Put event timeout"; + value = pfvf_counters->event_timeout; + break; + default: + value = 0; + } + if (value) + ptr += snprintf(ptr, + (MAX_REPORT_SIZE - (ptr - rep)), + "%s %u\n", + string, + value); + } +} + +static int adf_pfvf_ctrs_show(SYSCTL_HANDLER_ARGS) +{ + struct pfvf_stats *pfvf_counters = arg1; + char report[MAX_REPORT_SIZE]; + + if (!pfvf_counters) + return EINVAL; + + explicit_bzero(report, sizeof(report)); + adf_pfvf_ctrs_prepare_report(report, pfvf_counters); + sysctl_handle_string(oidp, report, sizeof(report), req); + return 0; +} + +int +adf_pfvf_ctrs_dbg_add(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_pfvf_ctrs_sysctl_tree; + struct sysctl_oid *oid_pfvf; + device_t dev; + + if (!accel_dev || accel_dev->accel_id > ADF_MAX_DEVICES) + return EINVAL; + + dev = GET_DEV(accel_dev); + + qat_sysctl_ctx = device_get_sysctl_ctx(dev); + qat_pfvf_ctrs_sysctl_tree = device_get_sysctl_tree(dev); + + oid_pfvf = SYSCTL_ADD_PROC(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_pfvf_ctrs_sysctl_tree), + OID_AUTO, + "pfvf_counters", + CTLTYPE_STRING | CTLFLAG_RD, + &accel_dev->u1.vf.pfvf_counters, + 0, + adf_pfvf_ctrs_show, + "A", + "QAT PFVF counters"); + + if (!oid_pfvf) { + device_printf(dev, "Failure creating PFVF counters sysctl\n"); + return ENOMEM; + } + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_transport_debug.c b/sys/dev/qat/qat_common/adf_freebsd_transport_debug.c new file mode 100644 index 00000000000..b8e2bf2ca33 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_transport_debug.c @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include +#include + +static int adf_ring_show(SYSCTL_HANDLER_ARGS) +{ + struct adf_etr_ring_data *ring = arg1; + struct adf_etr_bank_data *bank = ring->bank; + struct resource *csr = ring->bank->csr_addr; + struct sbuf sb; + int error, word; + uint32_t *wp, *end; + + sbuf_new_for_sysctl(&sb, NULL, 128, req); + { + int head, tail, empty; + + head = READ_CSR_RING_HEAD(csr, + bank->bank_number, + ring->ring_number); + tail = READ_CSR_RING_TAIL(csr, + bank->bank_number, + ring->ring_number); + empty = READ_CSR_E_STAT(csr, bank->bank_number); + + sbuf_cat(&sb, "\n------- Ring configuration -------\n"); + sbuf_printf(&sb, + "ring name: %s\n", + ring->ring_debug->ring_name); + sbuf_printf(&sb, + "ring num %d, bank num %d\n", + ring->ring_number, + ring->bank->bank_number); + sbuf_printf(&sb, + "head %x, tail %x, empty: %d\n", + head, + tail, + (empty & 1 << ring->ring_number) >> + ring->ring_number); + sbuf_printf(&sb, + "ring size %d, msg size %d\n", + ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size), + ADF_MSG_SIZE_TO_BYTES(ring->msg_size)); + sbuf_cat(&sb, "----------- Ring data ------------\n"); + } + wp = ring->base_addr; + end = (uint32_t *)((char *)ring->base_addr + + ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size)); + while (wp < end) { + sbuf_printf(&sb, "%p:", wp); + for (word = 0; word < 32 / 4; word++, wp++) + sbuf_printf(&sb, " %08x", *wp); + sbuf_printf(&sb, "\n"); + } + error = sbuf_finish(&sb); + sbuf_delete(&sb); + return (error); +} + +int +adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name) +{ + struct adf_etr_ring_debug_entry *ring_debug; + char entry_name[8]; + + ring_debug = malloc(sizeof(*ring_debug), M_QAT, M_WAITOK | M_ZERO); + + strlcpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name)); + snprintf(entry_name, + sizeof(entry_name), + "ring_%02d", + ring->ring_number); + + ring_debug->debug = + SYSCTL_ADD_PROC(&ring->bank->accel_dev->sysctl_ctx, + SYSCTL_CHILDREN(ring->bank->bank_debug_dir), + OID_AUTO, + entry_name, + CTLFLAG_RD | CTLTYPE_STRING, + ring, + 0, + adf_ring_show, + "A", + "Ring configuration"); + + if (!ring_debug->debug) { + printf("QAT: Failed to create ring debug entry.\n"); + free(ring_debug, M_QAT); + return EFAULT; + } + ring->ring_debug = ring_debug; + return 0; +} + +void +adf_ring_debugfs_rm(struct adf_etr_ring_data *ring) +{ + if (ring->ring_debug) { + free(ring->ring_debug, M_QAT); + ring->ring_debug = NULL; + } +} + +static int adf_bank_show(SYSCTL_HANDLER_ARGS) +{ + struct adf_etr_bank_data *bank; + struct adf_accel_dev *accel_dev = NULL; + struct adf_hw_device_data *hw_data = NULL; + u8 num_rings_per_bank = 0; + struct sbuf sb; + int error, ring_id; + + sbuf_new_for_sysctl(&sb, NULL, 128, req); + bank = arg1; + accel_dev = bank->accel_dev; + hw_data = accel_dev->hw_device; + num_rings_per_bank = hw_data->num_rings_per_bank; + sbuf_printf(&sb, + "\n------- Bank %d configuration -------\n", + bank->bank_number); + for (ring_id = 0; ring_id < num_rings_per_bank; ring_id++) { + struct adf_etr_ring_data *ring = &bank->rings[ring_id]; + struct resource *csr = bank->csr_addr; + int head, tail, empty; + + if (!(bank->ring_mask & 1 << ring_id)) + continue; + + head = READ_CSR_RING_HEAD(csr, + bank->bank_number, + ring->ring_number); + tail = READ_CSR_RING_TAIL(csr, + bank->bank_number, + ring->ring_number); + empty = READ_CSR_E_STAT(csr, bank->bank_number); + + sbuf_printf(&sb, + "ring num %02d, head %04x, tail %04x, empty: %d\n", + ring->ring_number, + head, + tail, + (empty & 1 << ring->ring_number) >> + ring->ring_number); + } + error = sbuf_finish(&sb); + sbuf_delete(&sb); + return (error); +} + +int +adf_bank_debugfs_add(struct adf_etr_bank_data *bank) +{ + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct sysctl_oid *parent = accel_dev->transport->debug; + char name[9]; + + snprintf(name, sizeof(name), "bank_%03d", bank->bank_number); + + bank->bank_debug_dir = SYSCTL_ADD_NODE(&accel_dev->sysctl_ctx, + SYSCTL_CHILDREN(parent), + OID_AUTO, + name, + CTLFLAG_RD | CTLFLAG_SKIP, + NULL, + ""); + + if (!bank->bank_debug_dir) { + printf("QAT: Failed to create bank debug dir.\n"); + return EFAULT; + } + + bank->bank_debug_cfg = + SYSCTL_ADD_PROC(&accel_dev->sysctl_ctx, + SYSCTL_CHILDREN(bank->bank_debug_dir), + OID_AUTO, + "config", + CTLFLAG_RD | CTLTYPE_STRING, + bank, + 0, + adf_bank_show, + "A", + "Bank configuration"); + + if (!bank->bank_debug_cfg) { + printf("QAT: Failed to create bank debug entry.\n"); + return EFAULT; + } + + return 0; +} + +void +adf_bank_debugfs_rm(struct adf_etr_bank_data *bank) +{ +} diff --git a/sys/dev/qat/qat_common/adf_freebsd_ver_dbg.c b/sys/dev/qat/qat_common/adf_freebsd_ver_dbg.c new file mode 100644 index 00000000000..697686ce3af --- /dev/null +++ b/sys/dev/qat/qat_common/adf_freebsd_ver_dbg.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_ver_dbg.h" + +static int adf_sysctl_read_fw_versions(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + char fw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) + snprintf(fw_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d.%d.%d", + accel_dev->fw_versions.fw_version_major, + accel_dev->fw_versions.fw_version_minor, + accel_dev->fw_versions.fw_version_patch); + else + snprintf(fw_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ""); + + return SYSCTL_OUT(req, + fw_version, + strnlen(fw_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES)); +} + +static int adf_sysctl_read_hw_versions(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + char hw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) + snprintf(hw_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d", + accel_dev->accel_pci_dev.revid); + else + snprintf(hw_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ""); + + return SYSCTL_OUT(req, + hw_version, + strnlen(hw_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES)); +} + +static int adf_sysctl_read_mmp_versions(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + char mmp_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + if (!accel_dev) + return -EINVAL; + + if (adf_dev_started(accel_dev)) + snprintf(mmp_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d.%d.%d", + accel_dev->fw_versions.mmp_version_major, + accel_dev->fw_versions.mmp_version_minor, + accel_dev->fw_versions.mmp_version_patch); + + if (adf_dev_started(accel_dev)) + snprintf(mmp_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d.%d.%d", + accel_dev->fw_versions.mmp_version_major, + accel_dev->fw_versions.mmp_version_minor, + accel_dev->fw_versions.mmp_version_patch); + else + snprintf(mmp_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ""); + + return SYSCTL_OUT(req, + mmp_version, + strnlen(mmp_version, ADF_CFG_MAX_VAL_LEN_IN_BYTES)); +} + +int +adf_ver_dbg_add(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_sysctl_tree; + struct sysctl_oid *rc = 0; + + if (!accel_dev) + return -EINVAL; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + rc = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "fw_version", + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + adf_sysctl_read_fw_versions, + "A", + "QAT FW version"); + if (!rc) + goto err; + + rc = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "hw_version", + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + adf_sysctl_read_hw_versions, + "A", + "QAT HW version"); + if (!rc) + goto err; + + rc = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "mmp_version", + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + adf_sysctl_read_mmp_versions, + "A", + "QAT MMP version"); + if (!rc) + goto err; + + return 0; +err: + device_printf(GET_DEV(accel_dev), + "Failed to add firmware versions to sysctl\n"); + return -EINVAL; +} + +void +adf_ver_dbg_del(struct adf_accel_dev *accel_dev) +{ +} diff --git a/sys/dev/qat/qat_common/adf_fw_counters.c b/sys/dev/qat/qat_common/adf_fw_counters.c new file mode 100644 index 00000000000..7c483168b71 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_fw_counters.c @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include "adf_accel_devices.h" +#include "adf_fw_counters.h" +#include "adf_common_drv.h" +#include "icp_qat_fw_init_admin.h" +#include +#include +#define ADF_FW_COUNTERS_BUF_SZ 4096 + +#define ADF_RAS_EVENT_STR "RAS events" +#define ADF_FW_REQ_STR "Firmware Requests" +#define ADF_FW_RESP_STR "Firmware Responses" + +static void adf_fw_counters_section_del_all(struct list_head *head); +static void adf_fw_counters_del_all(struct adf_accel_dev *accel_dev); +static int +adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const unsigned long sec_name_max_size, + const char *key, + const void *val); +static int adf_fw_counters_section_add(struct adf_accel_dev *accel_dev, + const char *name, + const unsigned long name_max_size); +int adf_get_fw_counters(struct adf_accel_dev *accel_dev); +int adf_read_fw_counters(SYSCTL_HANDLER_ARGS); + +int +adf_get_fw_counters(struct adf_accel_dev *accel_dev) +{ + struct icp_qat_fw_init_admin_req req; + struct icp_qat_fw_init_admin_resp resp; + unsigned long ae_mask; + int i; + int ret = 0; + char aeidstr[16] = { 0 }; + struct adf_hw_device_data *hw_device; + + if (!accel_dev) { + ret = EFAULT; + goto fail_clean; + } + if (!adf_dev_started(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Qat Device not started\n"); + ret = EFAULT; + goto fail_clean; + } + + hw_device = accel_dev->hw_device; + if (!hw_device) { + ret = EFAULT; + goto fail_clean; + } + + adf_fw_counters_del_all(accel_dev); + explicit_bzero(&req, sizeof(struct icp_qat_fw_init_admin_req)); + req.cmd_id = ICP_QAT_FW_COUNTERS_GET; + ae_mask = hw_device->ae_mask; + for_each_set_bit(i, &ae_mask, GET_MAX_ACCELENGINES(accel_dev)) + { + explicit_bzero(&resp, + sizeof(struct icp_qat_fw_init_admin_resp)); + if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) || + resp.status) { + resp.req_rec_count = ADF_FW_COUNTERS_NO_RESPONSE; + resp.resp_sent_count = ADF_FW_COUNTERS_NO_RESPONSE; + resp.ras_event_count = ADF_FW_COUNTERS_NO_RESPONSE; + } + explicit_bzero(aeidstr, sizeof(aeidstr)); + snprintf(aeidstr, sizeof(aeidstr), "AE %2d", i); + + if (adf_fw_counters_section_add(accel_dev, + aeidstr, + sizeof(aeidstr))) { + ret = ENOMEM; + goto fail_clean; + } + + if (adf_fw_counters_add_key_value_param( + accel_dev, + aeidstr, + sizeof(aeidstr), + ADF_FW_REQ_STR, + (void *)&resp.req_rec_count)) { + adf_fw_counters_del_all(accel_dev); + ret = ENOMEM; + goto fail_clean; + } + + if (adf_fw_counters_add_key_value_param( + accel_dev, + aeidstr, + sizeof(aeidstr), + ADF_FW_RESP_STR, + (void *)&resp.resp_sent_count)) { + adf_fw_counters_del_all(accel_dev); + ret = ENOMEM; + goto fail_clean; + } + + if (hw_device->count_ras_event && + hw_device->count_ras_event(accel_dev, + (void *)&resp.ras_event_count, + aeidstr)) { + adf_fw_counters_del_all(accel_dev); + ret = ENOMEM; + goto fail_clean; + } + } + +fail_clean: + return ret; +} + +int adf_read_fw_counters(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + struct adf_fw_counters_section *ptr = NULL; + struct list_head *list = NULL, *list_ptr = NULL; + struct list_head *tmp = NULL, *tmp_val = NULL; + int ret = 0; + struct sbuf *sbuf = NULL; + char *cbuf = NULL; + + if (accel_dev == NULL) { + return EINVAL; + } + cbuf = malloc(ADF_FW_COUNTERS_BUF_SZ, M_QAT, M_WAITOK | M_ZERO); + + sbuf = sbuf_new(NULL, cbuf, ADF_FW_COUNTERS_BUF_SZ, SBUF_FIXEDLEN); + if (sbuf == NULL) { + free(cbuf, M_QAT); + return ENOMEM; + } + ret = adf_get_fw_counters(accel_dev); + + if (ret) { + sbuf_delete(sbuf); + free(cbuf, M_QAT); + return ret; + } + + sbuf_printf(sbuf, + "\n+------------------------------------------------+\n"); + sbuf_printf( + sbuf, + "| FW Statistics for Qat Device |\n"); + sbuf_printf(sbuf, + "+------------------------------------------------+\n"); + + list_for_each_prev_safe(list, + tmp, + &accel_dev->fw_counters_data->ae_sec_list) + { + ptr = list_entry(list, struct adf_fw_counters_section, list); + sbuf_printf(sbuf, "%s\n", ptr->name); + list_for_each_prev_safe(list_ptr, tmp_val, &ptr->param_head) + { + struct adf_fw_counters_val *count = + list_entry(list_ptr, + struct adf_fw_counters_val, + list); + sbuf_printf(sbuf, "%s:%s\n", count->key, count->val); + } + } + + sbuf_finish(sbuf); + ret = SYSCTL_OUT(req, sbuf_data(sbuf), sbuf_len(sbuf)); + sbuf_delete(sbuf); + free(cbuf, M_QAT); + return ret; +} + +int +adf_fw_count_ras_event(struct adf_accel_dev *accel_dev, + u32 *ras_event, + char *aeidstr) +{ + unsigned long count = 0; + + if (!accel_dev || !ras_event || !aeidstr) + return EINVAL; + + count = (*ras_event == ADF_FW_COUNTERS_NO_RESPONSE ? + ADF_FW_COUNTERS_NO_RESPONSE : + (unsigned long)*ras_event); + + return adf_fw_counters_add_key_value_param( + accel_dev, aeidstr, 16, ADF_RAS_EVENT_STR, (void *)&count); +} + +/** + * adf_fw_counters_add() - Create an acceleration device FW counters table. + * @accel_dev: Pointer to acceleration device. + * + * Function creates a FW counters statistics table for the given + * acceleration device. + * The table stores device specific values of FW Requests sent to the FW and + * FW Responses received from the FW. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_fw_counters_add(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_counters_data *fw_counters_data; + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_sysctl_tree; + struct sysctl_oid *rc = 0; + + fw_counters_data = + malloc(sizeof(*fw_counters_data), M_QAT, M_WAITOK | M_ZERO); + + INIT_LIST_HEAD(&fw_counters_data->ae_sec_list); + + init_rwsem(&fw_counters_data->lock); + accel_dev->fw_counters_data = fw_counters_data; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + rc = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "fw_counters", + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + adf_read_fw_counters, + "A", + "QAT FW counters"); + if (!rc) + return ENOMEM; + else + return 0; +} + +static void +adf_fw_counters_del_all(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_counters_data *fw_counters_data = + accel_dev->fw_counters_data; + + down_write(&fw_counters_data->lock); + adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list); + up_write(&fw_counters_data->lock); +} + +static void +adf_fw_counters_keyval_add(struct adf_fw_counters_val *new, + struct adf_fw_counters_section *sec) +{ + list_add_tail(&new->list, &sec->param_head); +} + +static void +adf_fw_counters_keyval_del_all(struct list_head *head) +{ + struct list_head *list_ptr = NULL, *tmp = NULL; + + list_for_each_prev_safe(list_ptr, tmp, head) + { + struct adf_fw_counters_val *ptr = + list_entry(list_ptr, struct adf_fw_counters_val, list); + list_del(list_ptr); + free(ptr, M_QAT); + } +} + +static void +adf_fw_counters_section_del_all(struct list_head *head) +{ + struct adf_fw_counters_section *ptr = NULL; + struct list_head *list = NULL, *tmp = NULL; + + list_for_each_prev_safe(list, tmp, head) + { + ptr = list_entry(list, struct adf_fw_counters_section, list); + adf_fw_counters_keyval_del_all(&ptr->param_head); + list_del(list); + free(ptr, M_QAT); + } +} + +static struct adf_fw_counters_section * +adf_fw_counters_sec_find(struct adf_accel_dev *accel_dev, + const char *sec_name, + const unsigned long sec_name_max_size) +{ + struct adf_fw_counters_data *fw_counters_data = + accel_dev->fw_counters_data; + struct list_head *list = NULL; + + list_for_each(list, &fw_counters_data->ae_sec_list) + { + struct adf_fw_counters_section *ptr = + list_entry(list, struct adf_fw_counters_section, list); + if (!strncmp(ptr->name, sec_name, sec_name_max_size)) + return ptr; + } + return NULL; +} + +static int +adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev, + const char *section_name, + const unsigned long sec_name_max_size, + const char *key, + const void *val) +{ + struct adf_fw_counters_data *fw_counters_data = + accel_dev->fw_counters_data; + struct adf_fw_counters_val *key_val; + struct adf_fw_counters_section *section = + adf_fw_counters_sec_find(accel_dev, + section_name, + sec_name_max_size); + long tmp = *((const long *)val); + + if (!section) + return EFAULT; + key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO); + + INIT_LIST_HEAD(&key_val->list); + + if (tmp == ADF_FW_COUNTERS_NO_RESPONSE) { + snprintf(key_val->val, + FW_COUNTERS_MAX_VAL_LEN_IN_BYTES, + "No Response"); + } else { + snprintf(key_val->val, + FW_COUNTERS_MAX_VAL_LEN_IN_BYTES, + "%ld", + tmp); + } + + strlcpy(key_val->key, key, sizeof(key_val->key)); + down_write(&fw_counters_data->lock); + adf_fw_counters_keyval_add(key_val, section); + up_write(&fw_counters_data->lock); + return 0; +} + +/** + * adf_fw_counters_section_add() - Add AE section entry to FW counters table. + * @accel_dev: Pointer to acceleration device. + * @name: Name of the section + * + * Function adds a section for each AE where FW Requests/Responses and their + * values will be stored. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +static int +adf_fw_counters_section_add(struct adf_accel_dev *accel_dev, + const char *name, + const unsigned long name_max_size) +{ + struct adf_fw_counters_data *fw_counters_data = + accel_dev->fw_counters_data; + struct adf_fw_counters_section *sec = + adf_fw_counters_sec_find(accel_dev, name, name_max_size); + + if (sec) + return 0; + + sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO); + + strlcpy(sec->name, name, sizeof(sec->name)); + INIT_LIST_HEAD(&sec->param_head); + + down_write(&fw_counters_data->lock); + + list_add_tail(&sec->list, &fw_counters_data->ae_sec_list); + up_write(&fw_counters_data->lock); + return 0; +} + +/** + * adf_fw_counters_remove() - Clears acceleration device FW counters table. + * @accel_dev: Pointer to acceleration device. + * + * Function removes FW counters table from the given acceleration device + * and frees all allocated memory. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_fw_counters_remove(struct adf_accel_dev *accel_dev) +{ + struct adf_fw_counters_data *fw_counters_data = + accel_dev->fw_counters_data; + + if (!fw_counters_data) + return; + + down_write(&fw_counters_data->lock); + adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list); + up_write(&fw_counters_data->lock); + free(fw_counters_data, M_QAT); + accel_dev->fw_counters_data = NULL; +} diff --git a/sys/dev/qat/qat_common/adf_heartbeat.c b/sys/dev/qat/qat_common/adf_heartbeat.c new file mode 100644 index 00000000000..cf56ca98af3 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_heartbeat.c @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include "qat_freebsd.h" + +#include "adf_heartbeat.h" +#include "adf_common_drv.h" +#include "adf_cfg.h" +#include "adf_cfg_strings.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_transport_internal.h" + +#define MAX_HB_TICKS 0xFFFFFFFF + +static int +adf_check_hb_poll_freq(struct adf_accel_dev *accel_dev) +{ + u64 curr_hb_check_time = 0; + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + unsigned int timer_val = ADF_CFG_HB_DEFAULT_VALUE; + + curr_hb_check_time = adf_clock_get_current_time(); + + if (!adf_cfg_get_param_value(accel_dev, + ADF_GENERAL_SEC, + ADF_HEARTBEAT_TIMER, + (char *)timer_str)) { + if (compat_strtouint((char *)timer_str, + ADF_CFG_BASE_DEC, + &timer_val)) + timer_val = ADF_CFG_HB_DEFAULT_VALUE; + } + if ((curr_hb_check_time - accel_dev->heartbeat->last_hb_check_time) < + timer_val) { + return EINVAL; + } + accel_dev->heartbeat->last_hb_check_time = curr_hb_check_time; + + return 0; +} + +int +adf_heartbeat_init(struct adf_accel_dev *accel_dev) +{ + if (accel_dev->heartbeat) + adf_heartbeat_clean(accel_dev); + + accel_dev->heartbeat = + malloc(sizeof(*accel_dev->heartbeat), M_QAT, M_WAITOK | M_ZERO); + + return 0; +} + +void +adf_heartbeat_clean(struct adf_accel_dev *accel_dev) +{ + free(accel_dev->heartbeat, M_QAT); + accel_dev->heartbeat = NULL; +} + +int +adf_get_hb_timer(struct adf_accel_dev *accel_dev, unsigned int *value) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + unsigned int timer_val = ADF_CFG_HB_DEFAULT_VALUE; + u32 clk_per_sec = 0; + + if (!hw_data->get_ae_clock) + return EINVAL; + + clk_per_sec = (u32)hw_data->get_ae_clock(hw_data); + + /* Get Heartbeat Timer value from the configuration */ + if (!adf_cfg_get_param_value(accel_dev, + ADF_GENERAL_SEC, + ADF_HEARTBEAT_TIMER, + (char *)timer_str)) { + if (compat_strtouint((char *)timer_str, + ADF_CFG_BASE_DEC, + &timer_val)) + timer_val = ADF_CFG_HB_DEFAULT_VALUE; + } + + if (timer_val < ADF_MIN_HB_TIMER_MS) { + device_printf(GET_DEV(accel_dev), + "%s value cannot be lesser than %u\n", + ADF_HEARTBEAT_TIMER, + ADF_MIN_HB_TIMER_MS); + return EINVAL; + } + + /* Convert msec to clocks */ + clk_per_sec = clk_per_sec / 1000; + *value = timer_val * clk_per_sec; + + return 0; +} + +struct adf_hb_count { + u16 ae_thread[ADF_NUM_HB_CNT_PER_AE]; +}; + +int +adf_get_heartbeat_status(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct icp_qat_fw_init_admin_hb_stats *live_s = + (struct icp_qat_fw_init_admin_hb_stats *) + accel_dev->admin->virt_hb_addr; + const size_t max_aes = hw_device->get_num_aes(hw_device); + const size_t stats_size = + max_aes * sizeof(struct icp_qat_fw_init_admin_hb_stats); + int ret = 0; + size_t ae, thr; + unsigned long ae_mask = 0; + int num_threads_per_ae = ADF_NUM_HB_CNT_PER_AE; + + /* + * Memory layout of Heartbeat + * + * +----------------+----------------+---------+ + * | Live value | Last value | Count | + * +----------------+----------------+---------+ + * \_______________/\_______________/\________/ + * ^ ^ ^ + * | | | + * | | max_aes * sizeof(adf_hb_count) + * | max_aes * sizeof(icp_qat_fw_init_admin_hb_stats) + * max_aes * sizeof(icp_qat_fw_init_admin_hb_stats) + */ + struct icp_qat_fw_init_admin_hb_stats *curr_s; + struct icp_qat_fw_init_admin_hb_stats *last_s = live_s + max_aes; + struct adf_hb_count *count = (struct adf_hb_count *)(last_s + max_aes); + + curr_s = malloc(stats_size, M_QAT, M_WAITOK | M_ZERO); + + memcpy(curr_s, live_s, stats_size); + ae_mask = hw_device->ae_mask; + + for_each_set_bit(ae, &ae_mask, max_aes) + { + for (thr = 0; thr < num_threads_per_ae; ++thr) { + struct icp_qat_fw_init_admin_hb_cnt *curr = + &curr_s[ae].stats[thr]; + struct icp_qat_fw_init_admin_hb_cnt *prev = + &last_s[ae].stats[thr]; + u16 req = curr->req_heartbeat_cnt; + u16 resp = curr->resp_heartbeat_cnt; + u16 last = prev->resp_heartbeat_cnt; + + if ((thr == ADF_AE_ADMIN_THREAD || req != resp) && + resp == last) { + u16 retry = ++count[ae].ae_thread[thr]; + + if (retry >= ADF_CFG_HB_COUNT_THRESHOLD) + ret = EIO; + } else { + count[ae].ae_thread[thr] = 0; + } + } + } + + /* Copy current stats for the next iteration */ + memcpy(last_s, curr_s, stats_size); + free(curr_s, M_QAT); + + return ret; +} + +int +adf_heartbeat_status(struct adf_accel_dev *accel_dev, + enum adf_device_heartbeat_status *hb_status) +{ + /* Heartbeat is not implemented in VFs at the moment so they do not + * set get_heartbeat_status. Also, in case the device is not up, + * unsupported should be returned */ + if (!accel_dev || !accel_dev->hw_device || + !accel_dev->hw_device->get_heartbeat_status || + !accel_dev->heartbeat) { + *hb_status = DEV_HB_UNSUPPORTED; + return 0; + } + + if (!adf_dev_started(accel_dev) || + test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) { + *hb_status = DEV_HB_UNRESPONSIVE; + accel_dev->heartbeat->last_hb_status = DEV_HB_UNRESPONSIVE; + return 0; + } + + if (adf_check_hb_poll_freq(accel_dev) == EINVAL) { + *hb_status = accel_dev->heartbeat->last_hb_status; + return 0; + } + + accel_dev->heartbeat->hb_sent_counter++; + if (unlikely(accel_dev->hw_device->get_heartbeat_status(accel_dev))) { + device_printf(GET_DEV(accel_dev), + "ERROR: QAT is not responding.\n"); + *hb_status = DEV_HB_UNRESPONSIVE; + accel_dev->heartbeat->last_hb_status = DEV_HB_UNRESPONSIVE; + accel_dev->heartbeat->hb_failed_counter++; + return adf_notify_fatal_error(accel_dev); + } + + *hb_status = DEV_HB_ALIVE; + accel_dev->heartbeat->last_hb_status = DEV_HB_ALIVE; + + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_hw_arbiter.c b/sys/dev/qat/qat_common/adf_hw_arbiter.c new file mode 100644 index 00000000000..586b871f2df --- /dev/null +++ b/sys/dev/qat/qat_common/adf_hw_arbiter.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_transport_internal.h" + +#define ADF_ARB_NUM 4 +#define ADF_ARB_REG_SIZE 0x4 +#define ADF_ARB_WTR_SIZE 0x20 +#define ADF_ARB_OFFSET 0x30000 +#define ADF_ARB_REG_SLOT 0x1000 +#define ADF_ARB_WTR_OFFSET 0x010 +#define ADF_ARB_RO_EN_OFFSET 0x090 +#define ADF_ARB_WQCFG_OFFSET 0x100 +#define ADF_ARB_WRK_2_SER_MAP_OFFSET 0x180 +#define ADF_ARB_RINGSRVARBEN_OFFSET 0x19C + +#define WRITE_CSR_ARB_RINGSRVARBEN(csr_addr, index, value) \ + ADF_CSR_WR(csr_addr, \ + ADF_ARB_RINGSRVARBEN_OFFSET + (ADF_ARB_REG_SLOT * (index)), \ + value) + +#define WRITE_CSR_ARB_SARCONFIG(csr_addr, csr_offset, index, value) \ + ADF_CSR_WR(csr_addr, (csr_offset) + (ADF_ARB_REG_SIZE * (index)), value) +#define READ_CSR_ARB_RINGSRVARBEN(csr_addr, index) \ + ADF_CSR_RD(csr_addr, \ + ADF_ARB_RINGSRVARBEN_OFFSET + (ADF_ARB_REG_SLOT * (index))) + +static DEFINE_MUTEX(csr_arb_lock); + +#define WRITE_CSR_ARB_WRK_2_SER_MAP( \ + csr_addr, csr_offset, wrk_to_ser_map_offset, index, value) \ + ADF_CSR_WR(csr_addr, \ + ((csr_offset) + (wrk_to_ser_map_offset)) + \ + (ADF_ARB_REG_SIZE * (index)), \ + value) + +int +adf_init_arb(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct arb_info info; + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + u32 arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1; + u32 arb; + + hw_data->get_arb_info(&info); + + /* Service arb configured for 32 bytes responses and + * ring flow control check enabled. + */ + for (arb = 0; arb < ADF_ARB_NUM; arb++) + WRITE_CSR_ARB_SARCONFIG(csr, info.arbiter_offset, arb, arb_cfg); + + return 0; +} + +int +adf_init_gen2_arb(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct arb_info info; + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + u32 i; + const u32 *thd_2_arb_cfg; + + /* invoke common adf_init_arb */ + adf_init_arb(accel_dev); + + hw_data->get_arb_info(&info); + + /* Map worker threads to service arbiters */ + hw_data->get_arb_mapping(accel_dev, &thd_2_arb_cfg); + if (!thd_2_arb_cfg) + return EFAULT; + + for (i = 0; i < hw_data->num_engines; i++) + WRITE_CSR_ARB_WRK_2_SER_MAP(csr, + info.arbiter_offset, + info.wrk_thd_2_srv_arb_map, + i, + *(thd_2_arb_cfg + i)); + return 0; +} + +void +adf_update_ring_arb(struct adf_etr_ring_data *ring) +{ + WRITE_CSR_ARB_RINGSRVARBEN(ring->bank->csr_addr, + ring->bank->bank_number, + ring->bank->ring_mask & 0xFF); +} + +void +adf_enable_ring_arb(void *csr_addr, unsigned int bank_nr, unsigned int mask) +{ + struct resource *csr = csr_addr; + u32 arbenable; + + if (!csr) + return; + + mutex_lock(&csr_arb_lock); + arbenable = READ_CSR_ARB_RINGSRVARBEN(csr, bank_nr); + arbenable |= mask & 0xFF; + WRITE_CSR_ARB_RINGSRVARBEN(csr, bank_nr, arbenable); + + mutex_unlock(&csr_arb_lock); +} + +void +adf_disable_ring_arb(void *csr_addr, unsigned int bank_nr, unsigned int mask) +{ + struct resource *csr = csr_addr; + u32 arbenable; + + if (!csr_addr) + return; + + mutex_lock(&csr_arb_lock); + arbenable = READ_CSR_ARB_RINGSRVARBEN(csr, bank_nr); + arbenable &= ~mask & 0xFF; + WRITE_CSR_ARB_RINGSRVARBEN(csr, bank_nr, arbenable); + mutex_unlock(&csr_arb_lock); +} + +void +adf_exit_arb(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct arb_info info; + struct resource *csr; + unsigned int i; + + if (!accel_dev->transport) + return; + + csr = accel_dev->transport->banks[0].csr_addr; + + hw_data->get_arb_info(&info); + + /* Reset arbiter configuration */ + for (i = 0; i < ADF_ARB_NUM; i++) + WRITE_CSR_ARB_SARCONFIG(csr, info.arbiter_offset, i, 0); + + /* Unmap worker threads to service arbiters */ + if (hw_data->get_arb_mapping) { + for (i = 0; i < hw_data->num_engines; i++) + WRITE_CSR_ARB_WRK_2_SER_MAP(csr, + info.arbiter_offset, + info.wrk_thd_2_srv_arb_map, + i, + 0); + } + + /* Disable arbitration on all rings */ + for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) + WRITE_CSR_ARB_RINGSRVARBEN(csr, i, 0); +} + +void +adf_disable_arb(struct adf_accel_dev *accel_dev) +{ + struct resource *csr; + unsigned int i; + + if (!accel_dev || !accel_dev->transport) + return; + + csr = accel_dev->transport->banks[0].csr_addr; + + /* Disable arbitration on all rings */ + for (i = 0; i < GET_MAX_BANKS(accel_dev); i++) + WRITE_CSR_ARB_RINGSRVARBEN(csr, i, 0); +} diff --git a/sys/dev/qat/qat_common/adf_init.c b/sys/dev/qat/qat_common/adf_init.c new file mode 100644 index 00000000000..2e5f77d22ea --- /dev/null +++ b/sys/dev/qat/qat_common/adf_init.c @@ -0,0 +1,730 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_dev_err.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include "adf_accel_devices.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "icp_qat_fw.h" + +/* Mask used to check the CompressAndVerify capability bit */ +#define DC_CNV_EXTENDED_CAPABILITY (0x01) + +/* Mask used to check the CompressAndVerifyAndRecover capability bit */ +#define DC_CNVNR_EXTENDED_CAPABILITY (0x100) + +static LIST_HEAD(service_table); +static DEFINE_MUTEX(service_lock); + +static void +adf_service_add(struct service_hndl *service) +{ + mutex_lock(&service_lock); + list_add(&service->list, &service_table); + mutex_unlock(&service_lock); +} + +int +adf_service_register(struct service_hndl *service) +{ + memset(service->init_status, 0, sizeof(service->init_status)); + memset(service->start_status, 0, sizeof(service->start_status)); + adf_service_add(service); + return 0; +} + +static void +adf_service_remove(struct service_hndl *service) +{ + mutex_lock(&service_lock); + list_del(&service->list); + mutex_unlock(&service_lock); +} + +int +adf_service_unregister(struct service_hndl *service) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(service->init_status); i++) { + if (service->init_status[i] || service->start_status[i]) { + pr_err("QAT: Could not remove active service [%d]\n", + i); + return EFAULT; + } + } + adf_service_remove(service); + return 0; +} + +static int +adf_cfg_add_device_params(struct adf_accel_dev *accel_dev) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char hw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + char mmp_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + struct adf_hw_device_data *hw_data = NULL; + unsigned long val; + + if (!accel_dev) + return -EINVAL; + + hw_data = accel_dev->hw_device; + + if (adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC)) + goto err; + + snprintf(key, sizeof(key), ADF_DEV_MAX_BANKS); + val = GET_MAX_BANKS(accel_dev); + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_DEV_CAPABILITIES_MASK); + val = hw_data->accel_capabilities_mask; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX)) + goto err; + + snprintf(key, sizeof(key), ADF_DEV_PKG_ID); + val = accel_dev->accel_id; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_DEV_NODE_ID); + val = dev_to_node(GET_DEV(accel_dev)); + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_DEV_MAX_RINGS_PER_BANK); + val = hw_data->num_rings_per_bank; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_HW_REV_ID_KEY); + snprintf(hw_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d", + accel_dev->accel_pci_dev.revid); + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)hw_version, ADF_STR)) + goto err; + + snprintf(key, sizeof(key), ADF_MMP_VER_KEY); + snprintf(mmp_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d.%d.%d", + accel_dev->fw_versions.mmp_version_major, + accel_dev->fw_versions.mmp_version_minor, + accel_dev->fw_versions.mmp_version_patch); + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)mmp_version, ADF_STR)) + goto err; + + return 0; +err: + device_printf(GET_DEV(accel_dev), + "Failed to add internal values to accel_dev cfg\n"); + return -EINVAL; +} + +static int +adf_cfg_add_fw_version(struct adf_accel_dev *accel_dev) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char fw_version[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + snprintf(key, sizeof(key), ADF_UOF_VER_KEY); + snprintf(fw_version, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%d.%d.%d", + accel_dev->fw_versions.fw_version_major, + accel_dev->fw_versions.fw_version_minor, + accel_dev->fw_versions.fw_version_patch); + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)fw_version, ADF_STR)) + return EFAULT; + + return 0; +} + +static int +adf_cfg_add_ext_params(struct adf_accel_dev *accel_dev) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + unsigned long val; + + snprintf(key, sizeof(key), ADF_DC_EXTENDED_FEATURES); + + val = hw_data->extended_dc_capabilities; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)val, ADF_HEX)) + return -EINVAL; + + return 0; +} + +void +adf_error_notifier(uintptr_t arg) +{ + struct adf_accel_dev *accel_dev = (struct adf_accel_dev *)arg; + struct service_hndl *service; + struct list_head *list_itr; + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_ERROR)) + device_printf(GET_DEV(accel_dev), + "Failed to send error event to %s.\n", + service->name); + } +} + +/** + * adf_set_ssm_wdtimer() - Initialize the slice hang watchdog timer. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_set_ssm_wdtimer(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *misc_bar = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *csr = misc_bar->virt_addr; + u32 i; + unsigned int mask; + u32 clk_per_sec = hw_data->get_clock_speed(hw_data); + u32 timer_val = ADF_WDT_TIMER_SYM_COMP_MS * (clk_per_sec / 1000); + u32 timer_val_pke = ADF_SSM_WDT_PKE_DEFAULT_VALUE; + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + + /* Get Watch Dog Timer for CySym+Comp from the configuration */ + if (!adf_cfg_get_param_value(accel_dev, + ADF_GENERAL_SEC, + ADF_DEV_SSM_WDT_BULK, + (char *)timer_str)) { + if (!compat_strtouint((char *)timer_str, + ADF_CFG_BASE_DEC, + &timer_val)) + /* Convert msec to CPP clocks */ + timer_val = timer_val * (clk_per_sec / 1000); + } + /* Get Watch Dog Timer for CyAsym from the configuration */ + if (!adf_cfg_get_param_value(accel_dev, + ADF_GENERAL_SEC, + ADF_DEV_SSM_WDT_PKE, + (char *)timer_str)) { + if (!compat_strtouint((char *)timer_str, + ADF_CFG_BASE_DEC, + &timer_val_pke)) + /* Convert msec to CPP clocks */ + timer_val_pke = timer_val_pke * (clk_per_sec / 1000); + } + + for (i = 0, mask = hw_data->accel_mask; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + /* Enable Watch Dog Timer for CySym + Comp */ + ADF_CSR_WR(csr, ADF_SSMWDT(i), timer_val); + /* Enable Watch Dog Timer for CyAsym */ + ADF_CSR_WR(csr, ADF_SSMWDTPKE(i), timer_val_pke); + } + return 0; +} + +/** + * adf_dev_init() - Init data structures and services for the given accel device + * @accel_dev: Pointer to acceleration device. + * + * Initialize the ring data structures and the admin comms and arbitration + * services. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_dev_init(struct adf_accel_dev *accel_dev) +{ + struct service_hndl *service; + struct list_head *list_itr; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + char value[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + int ret = 0; + sysctl_ctx_init(&accel_dev->sysctl_ctx); + set_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status); + + if (!hw_data) { + device_printf(GET_DEV(accel_dev), + "Failed to init device - hw_data not set\n"); + return EFAULT; + } + if (hw_data->reset_hw_units) + hw_data->reset_hw_units(accel_dev); + + if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status) && + !accel_dev->is_vf) { + device_printf(GET_DEV(accel_dev), "Device not configured\n"); + return EFAULT; + } + + if (adf_init_etr_data(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Failed initialize etr\n"); + return EFAULT; + } + + if (hw_data->init_accel_units && hw_data->init_accel_units(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed initialize accel_units\n"); + return EFAULT; + } + + if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed initialize admin comms\n"); + return EFAULT; + } + + if (hw_data->init_arb && hw_data->init_arb(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed initialize hw arbiter\n"); + return EFAULT; + } + + if (hw_data->set_asym_rings_mask) + hw_data->set_asym_rings_mask(accel_dev); + + hw_data->enable_ints(accel_dev); + + if (adf_ae_init(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to initialise Acceleration Engine\n"); + return EFAULT; + } + + set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status); + + if (adf_ae_fw_load(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to load acceleration FW\n"); + return EFAULT; + } + set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status); + + if (hw_data->alloc_irq(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to allocate interrupts\n"); + return EFAULT; + } + set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status); + + if (hw_data->init_ras && hw_data->init_ras(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Failed to init RAS\n"); + return EFAULT; + } + + hw_data->enable_ints(accel_dev); + + hw_data->enable_error_correction(accel_dev); + + if (hw_data->enable_vf2pf_comms(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "QAT: Failed to enable vf2pf comms\n"); + return EFAULT; + } + + if (adf_pf_vf_capabilities_init(accel_dev)) + return EFAULT; + + if (adf_pf_vf_ring_to_svc_init(accel_dev)) + return EFAULT; + + if (adf_cfg_add_device_params(accel_dev)) + return EFAULT; + + if (hw_data->add_pke_stats && hw_data->add_pke_stats(accel_dev)) + return EFAULT; + + if (hw_data->add_misc_error && hw_data->add_misc_error(accel_dev)) + return EFAULT; + /* + * Subservice initialisation is divided into two stages: init and start. + * This is to facilitate any ordering dependencies between services + * prior to starting any of the accelerators. + */ + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_INIT)) { + device_printf(GET_DEV(accel_dev), + "Failed to initialise service %s\n", + service->name); + return EFAULT; + } + set_bit(accel_dev->accel_id, service->init_status); + } + + /* Read autoreset on error parameter */ + ret = adf_cfg_get_param_value(accel_dev, + ADF_GENERAL_SEC, + ADF_AUTO_RESET_ON_ERROR, + value); + if (!ret) { + if (compat_strtouint(value, + 10, + &accel_dev->autoreset_on_error)) { + device_printf( + GET_DEV(accel_dev), + "Failed converting %s to a decimal value\n", + ADF_AUTO_RESET_ON_ERROR); + return EFAULT; + } + } + + return 0; +} + +/** + * adf_dev_start() - Start acceleration service for the given accel device + * @accel_dev: Pointer to acceleration device. + * + * Function notifies all the registered services that the acceleration device + * is ready to be used. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_dev_start(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct service_hndl *service; + struct list_head *list_itr; + + set_bit(ADF_STATUS_STARTING, &accel_dev->status); + if (adf_devmgr_verify_id(&accel_dev->accel_id)) { + device_printf(GET_DEV(accel_dev), + "QAT: Device %d not found\n", + accel_dev->accel_id); + return ENODEV; + } + if (adf_ae_start(accel_dev)) { + device_printf(GET_DEV(accel_dev), "AE Start Failed\n"); + return EFAULT; + } + + set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status); + if (hw_data->send_admin_init(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to send init message\n"); + return EFAULT; + } + + if (adf_cfg_add_fw_version(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to update configuration FW version\n"); + return EFAULT; + } + + if (hw_data->measure_clock) + hw_data->measure_clock(accel_dev); + + /* + * Set ssm watch dog timer for slice hang detection + * Note! Not supported on devices older than C62x + */ + if (hw_data->set_ssm_wdtimer && hw_data->set_ssm_wdtimer(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "QAT: Failed to set ssm watch dog timer\n"); + return EFAULT; + } + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_START)) { + device_printf(GET_DEV(accel_dev), + "Failed to start service %s\n", + service->name); + return EFAULT; + } + set_bit(accel_dev->accel_id, service->start_status); + } + + if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status) && + adf_cfg_add_ext_params(accel_dev)) + return EFAULT; + + clear_bit(ADF_STATUS_STARTING, &accel_dev->status); + set_bit(ADF_STATUS_STARTED, &accel_dev->status); + + return 0; +} + +/** + * adf_dev_stop() - Stop acceleration service for the given accel device + * @accel_dev: Pointer to acceleration device. + * + * Function notifies all the registered services that the acceleration device + * is shuting down. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_dev_stop(struct adf_accel_dev *accel_dev) +{ + struct service_hndl *service; + struct list_head *list_itr; + + if (adf_devmgr_verify_id(&accel_dev->accel_id)) { + device_printf(GET_DEV(accel_dev), + "QAT: Device %d not found\n", + accel_dev->accel_id); + return ENODEV; + } + if (!adf_dev_started(accel_dev) && + !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) { + return 0; + } + + if (adf_dev_stop_notify_sync(accel_dev)) { + device_printf( + GET_DEV(accel_dev), + "Waiting for device un-busy failed. Retries limit reached\n"); + return EBUSY; + } + + clear_bit(ADF_STATUS_STARTING, &accel_dev->status); + clear_bit(ADF_STATUS_STARTED, &accel_dev->status); + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (!test_bit(accel_dev->accel_id, service->start_status)) + continue; + clear_bit(accel_dev->accel_id, service->start_status); + } + + if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) { + if (adf_ae_stop(accel_dev)) + device_printf(GET_DEV(accel_dev), + "failed to stop AE\n"); + else + clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status); + } + + return 0; +} + +/** + * adf_dev_shutdown() - shutdown acceleration services and data strucutures + * @accel_dev: Pointer to acceleration device + * + * Cleanup the ring data structures and the admin comms and arbitration + * services. + */ +void +adf_dev_shutdown(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct service_hndl *service; + struct list_head *list_itr; + + if (test_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, &accel_dev->status)) { + sysctl_ctx_free(&accel_dev->sysctl_ctx); + clear_bit(ADF_STATUS_SYSCTL_CTX_INITIALISED, + &accel_dev->status); + } + + if (!hw_data) { + device_printf( + GET_DEV(accel_dev), + "QAT: Failed to shutdown device - hw_data not set\n"); + return; + } + + if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) { + adf_ae_fw_release(accel_dev); + clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status); + } + + if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) { + if (adf_ae_shutdown(accel_dev)) + device_printf(GET_DEV(accel_dev), + "Failed to shutdown Accel Engine\n"); + else + clear_bit(ADF_STATUS_AE_INITIALISED, + &accel_dev->status); + } + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (!test_bit(accel_dev->accel_id, service->init_status)) + continue; + if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN)) + device_printf(GET_DEV(accel_dev), + "Failed to shutdown service %s\n", + service->name); + else + clear_bit(accel_dev->accel_id, service->init_status); + } + + hw_data->disable_iov(accel_dev); + + if (hw_data->disable_vf2pf_comms) + hw_data->disable_vf2pf_comms(accel_dev); + + if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) { + hw_data->free_irq(accel_dev); + clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status); + } + + /* Delete configuration only if not restarting */ + if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) + adf_cfg_del_all(accel_dev); + + if (hw_data->remove_pke_stats) + hw_data->remove_pke_stats(accel_dev); + + if (hw_data->remove_misc_error) + hw_data->remove_misc_error(accel_dev); + + if (hw_data->exit_ras) + hw_data->exit_ras(accel_dev); + + if (hw_data->exit_arb) + hw_data->exit_arb(accel_dev); + + if (hw_data->exit_admin_comms) + hw_data->exit_admin_comms(accel_dev); + + if (hw_data->exit_accel_units) + hw_data->exit_accel_units(accel_dev); + + adf_cleanup_etr_data(accel_dev); + if (hw_data->restore_device) + hw_data->restore_device(accel_dev); +} + +/** + * adf_dev_reset() - Reset acceleration service for the given accel device + * @accel_dev: Pointer to acceleration device. + * @mode: Specifies reset mode - synchronous or asynchronous. + * Function notifies all the registered services that the acceleration device + * is resetting. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_dev_reset(struct adf_accel_dev *accel_dev, enum adf_dev_reset_mode mode) +{ + return adf_dev_aer_schedule_reset(accel_dev, mode); +} + +int +adf_dev_restarting_notify(struct adf_accel_dev *accel_dev) +{ + struct service_hndl *service; + struct list_head *list_itr; + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING)) + device_printf(GET_DEV(accel_dev), + "Failed to restart service %s.\n", + service->name); + } + return 0; +} + +int +adf_dev_restarting_notify_sync(struct adf_accel_dev *accel_dev) +{ + int times; + + adf_dev_restarting_notify(accel_dev); + for (times = 0; times < ADF_STOP_RETRY; times++) { + if (!adf_dev_in_use(accel_dev)) + break; + dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times); + pause_ms("adfstop", 100); + } + if (adf_dev_in_use(accel_dev)) { + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + device_printf(GET_DEV(accel_dev), + "Device still in use during reset sequence.\n"); + return EBUSY; + } + + return 0; +} + +int +adf_dev_stop_notify_sync(struct adf_accel_dev *accel_dev) +{ + int times; + + struct service_hndl *service; + struct list_head *list_itr; + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_STOP)) + device_printf(GET_DEV(accel_dev), + "Failed to restart service %s.\n", + service->name); + } + + for (times = 0; times < ADF_STOP_RETRY; times++) { + if (!adf_dev_in_use(accel_dev)) + break; + dev_dbg(GET_DEV(accel_dev), "retry times=%d\n", times); + pause_ms("adfstop", 100); + } + if (adf_dev_in_use(accel_dev)) { + clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + device_printf(GET_DEV(accel_dev), + "Device still in use during stop sequence.\n"); + return EBUSY; + } + + return 0; +} + +int +adf_dev_restarted_notify(struct adf_accel_dev *accel_dev) +{ + struct service_hndl *service; + struct list_head *list_itr; + + list_for_each(list_itr, &service_table) + { + service = list_entry(list_itr, struct service_hndl, list); + if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED)) + device_printf(GET_DEV(accel_dev), + "Failed to restart service %s.\n", + service->name); + } + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_isr.c b/sys/dev/qat/qat_common/adf_isr.c new file mode 100644 index 00000000000..31e439ee60e --- /dev/null +++ b/sys/dev/qat/qat_common/adf_isr.c @@ -0,0 +1,345 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include +#include +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_cfg.h" +#include "adf_cfg_strings.h" +#include "adf_cfg_common.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include "adf_dev_err.h" + +TASKQUEUE_DEFINE_THREAD(qat_pf); + +static int +adf_enable_msix(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *info_pci_dev = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + int msix_num_entries = 1; + int count = 0; + int error = 0; + int num_vectors = 0; + u_int *vectors; + + /* If SR-IOV is disabled, add entries for each bank */ + if (!accel_dev->u1.pf.vf_info) { + msix_num_entries += hw_data->num_banks; + num_vectors = 0; + vectors = NULL; + } else { + num_vectors = hw_data->num_banks + 1; + vectors = malloc(num_vectors * sizeof(u_int), + M_QAT, + M_WAITOK | M_ZERO); + vectors[hw_data->num_banks] = 1; + } + + count = msix_num_entries; + error = pci_alloc_msix(info_pci_dev->pci_dev, &count); + if (error == 0 && count != msix_num_entries) { + pci_release_msi(info_pci_dev->pci_dev); + error = EFBIG; + } + if (error) { + device_printf(GET_DEV(accel_dev), + "Failed to enable MSI-X IRQ(s)\n"); + free(vectors, M_QAT); + return error; + } + + if (vectors != NULL) { + error = + pci_remap_msix(info_pci_dev->pci_dev, num_vectors, vectors); + free(vectors, M_QAT); + if (error) { + device_printf(GET_DEV(accel_dev), + "Failed to remap MSI-X IRQ(s)\n"); + pci_release_msi(info_pci_dev->pci_dev); + return error; + } + } + + return 0; +} + +static void +adf_disable_msix(struct adf_accel_pci *info_pci_dev) +{ + pci_release_msi(info_pci_dev->pci_dev); +} + +static void +adf_msix_isr_bundle(void *bank_ptr) +{ + struct adf_etr_bank_data *bank = bank_ptr; + struct adf_etr_data *priv_data = bank->accel_dev->transport; + + WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number, 0); + adf_response_handler((uintptr_t)&priv_data->banks[bank->bank_number]); + return; +} + +static void +adf_msix_isr_ae(void *dev_ptr) +{ + struct adf_accel_dev *accel_dev = dev_ptr; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *pmisc = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *pmisc_bar_addr = pmisc->virt_addr; + u32 errsou3; + u32 errsou5; + bool reset_required = false; + + if (hw_data->ras_interrupts && + hw_data->ras_interrupts(accel_dev, &reset_required)) + if (reset_required) { + adf_notify_fatal_error(accel_dev); + goto exit; + } + + if (hw_data->check_slice_hang && hw_data->check_slice_hang(accel_dev)) { + } + +exit: + errsou3 = ADF_CSR_RD(pmisc_bar_addr, ADF_ERRSOU3); + errsou5 = ADF_CSR_RD(pmisc_bar_addr, ADF_ERRSOU5); + if (errsou3 | errsou5) + adf_print_err_registers(accel_dev); + else + device_printf(GET_DEV(accel_dev), "spurious AE interrupt\n"); + + return; +} + +static int +adf_get_irq_affinity(struct adf_accel_dev *accel_dev, int bank) +{ + int core = CPU_FIRST(); + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + char bankName[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + + snprintf(bankName, + ADF_CFG_MAX_KEY_LEN_IN_BYTES - 1, + ADF_ETRMGR_CORE_AFFINITY_FORMAT, + bank); + bankName[ADF_CFG_MAX_KEY_LEN_IN_BYTES - 1] = '\0'; + + if (adf_cfg_get_param_value(accel_dev, "Accelerator0", bankName, val)) { + device_printf(GET_DEV(accel_dev), + "No CoreAffinity Set - using default core: %d\n", + core); + } else { + if (compat_strtouint(val, 10, &core)) { + device_printf(GET_DEV(accel_dev), + "Can't get cpu core ID\n"); + } + } + return (core); +} + +static int +adf_request_irqs(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *info_pci_dev = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct msix_entry *msixe = info_pci_dev->msix_entries.entries; + int ret = 0, rid = 0, i = 0; + struct adf_etr_data *etr_data = accel_dev->transport; + int computed_core = 0; + + /* Request msix irq for all banks unless SR-IOV enabled */ + if (!accel_dev->u1.pf.vf_info) { + for (i = 0; i < hw_data->num_banks; i++) { + struct adf_etr_bank_data *bank = &etr_data->banks[i]; + + rid = i + 1; + msixe[i].irq = + bus_alloc_resource_any(info_pci_dev->pci_dev, + SYS_RES_IRQ, + &rid, + RF_ACTIVE); + if (msixe[i].irq == NULL) { + device_printf( + GET_DEV(accel_dev), + "failed to allocate IRQ for bundle %d\n", + i); + return ENXIO; + } + + ret = bus_setup_intr(info_pci_dev->pci_dev, + msixe[i].irq, + INTR_TYPE_MISC | INTR_MPSAFE, + NULL, + adf_msix_isr_bundle, + bank, + &msixe[i].cookie); + if (ret) { + device_printf( + GET_DEV(accel_dev), + "failed to enable IRQ for bundle %d\n", + i); + bus_release_resource(info_pci_dev->pci_dev, + SYS_RES_IRQ, + rid, + msixe[i].irq); + msixe[i].irq = NULL; + return ret; + } + + computed_core = adf_get_irq_affinity(accel_dev, i); + bus_describe_intr(info_pci_dev->pci_dev, + msixe[i].irq, + msixe[i].cookie, + "b%d", + i); + bus_bind_intr(info_pci_dev->pci_dev, + msixe[i].irq, + computed_core); + } + } + + /* Request msix irq for AE */ + rid = hw_data->num_banks + 1; + msixe[i].irq = bus_alloc_resource_any(info_pci_dev->pci_dev, + SYS_RES_IRQ, + &rid, + RF_ACTIVE); + if (msixe[i].irq == NULL) { + device_printf(GET_DEV(accel_dev), + "failed to allocate IRQ for ae-cluster\n"); + return ENXIO; + } + + ret = bus_setup_intr(info_pci_dev->pci_dev, + msixe[i].irq, + INTR_TYPE_MISC | INTR_MPSAFE, + NULL, + adf_msix_isr_ae, + accel_dev, + &msixe[i].cookie); + if (ret) { + device_printf(GET_DEV(accel_dev), + "failed to enable IRQ for ae-cluster\n"); + bus_release_resource(info_pci_dev->pci_dev, + SYS_RES_IRQ, + rid, + msixe[i].irq); + msixe[i].irq = NULL; + return ret; + } + + bus_describe_intr(info_pci_dev->pci_dev, + msixe[i].irq, + msixe[i].cookie, + "ae"); + return ret; +} + +static void +adf_free_irqs(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *info_pci_dev = &accel_dev->accel_pci_dev; + struct msix_entry *msixe = info_pci_dev->msix_entries.entries; + int i = 0; + + if (info_pci_dev->msix_entries.num_entries > 0) { + for (i = 0; i < info_pci_dev->msix_entries.num_entries; i++) { + if (msixe[i].irq != NULL && msixe[i].cookie != NULL) { + bus_teardown_intr(info_pci_dev->pci_dev, + msixe[i].irq, + msixe[i].cookie); + bus_free_resource(info_pci_dev->pci_dev, + SYS_RES_IRQ, + msixe[i].irq); + } + } + } +} + +static int +adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev) +{ + struct msix_entry *entries; + u32 msix_num_entries = 1; + + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + /* If SR-IOV is disabled (vf_info is NULL), add entries for each bank */ + if (!accel_dev->u1.pf.vf_info) + msix_num_entries += hw_data->num_banks; + + entries = malloc(msix_num_entries * sizeof(struct msix_entry), + M_QAT, + M_WAITOK | M_ZERO); + + accel_dev->accel_pci_dev.msix_entries.num_entries = msix_num_entries; + accel_dev->accel_pci_dev.msix_entries.entries = entries; + return 0; +} + +static void +adf_isr_free_msix_entry_table(struct adf_accel_dev *accel_dev) +{ + + free(accel_dev->accel_pci_dev.msix_entries.entries, M_QAT); + accel_dev->accel_pci_dev.msix_entries.entries = NULL; +} + +/** + * adf_vf_isr_resource_free() - Free IRQ for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function frees interrupts for acceleration device. + */ +void +adf_isr_resource_free(struct adf_accel_dev *accel_dev) +{ + adf_free_irqs(accel_dev); + adf_disable_msix(&accel_dev->accel_pci_dev); + adf_isr_free_msix_entry_table(accel_dev); +} + +/** + * adf_vf_isr_resource_alloc() - Allocate IRQ for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function allocates interrupts for acceleration device. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_isr_resource_alloc(struct adf_accel_dev *accel_dev) +{ + int ret; + + ret = adf_isr_alloc_msix_entry_table(accel_dev); + if (ret) + return ret; + if (adf_enable_msix(accel_dev)) + goto err_out; + + if (adf_request_irqs(accel_dev)) + goto err_out; + + return 0; +err_out: + adf_isr_resource_free(accel_dev); + return EFAULT; +} diff --git a/sys/dev/qat/qat_common/adf_pf2vf_capabilities.c b/sys/dev/qat/qat_common/adf_pf2vf_capabilities.c new file mode 100644 index 00000000000..f4b4a3faf30 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_pf2vf_capabilities.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_pf2vf_msg.h" +#include "adf_cfg.h" + +#define ADF_VF2PF_CAPABILITIES_V1_VERSION 1 +#define ADF_VF2PF_CAPABILITIES_V1_LENGTH 4 +#define ADF_VF2PF_CAPABILITIES_V2_VERSION 2 +#define ADF_VF2PF_CAPABILITIES_CAP_OFFSET 4 +#define ADF_VF2PF_CAPABILITIES_V2_LENGTH 8 +#define ADF_VF2PF_CAPABILITIES_V3_VERSION 3 +#define ADF_VF2PF_CAPABILITIES_FREQ_OFFSET 8 +#define ADF_VF2PF_CAPABILITIES_V3_LENGTH 12 + +static int +adf_pf_capabilities_msg_provider(struct adf_accel_dev *accel_dev, + u8 **buffer, + u8 *length, + u8 *block_version, + u8 compatibility, + u8 byte_num) +{ + static u8 data[ADF_VF2PF_CAPABILITIES_V3_LENGTH] = { 0 }; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 ext_dc_caps = hw_data->extended_dc_capabilities; + u32 capabilities = hw_data->accel_capabilities_mask; + u32 frequency = hw_data->clock_frequency; + u16 byte = 0; + u16 index = 0; + + for (byte = 0; byte < sizeof(ext_dc_caps); byte++) { + data[byte] = (ext_dc_caps >> (byte * ADF_PFVF_DATA_SHIFT)) & + ADF_PFVF_DATA_MASK; + } + + for (byte = 0, index = ADF_VF2PF_CAPABILITIES_CAP_OFFSET; + byte < sizeof(capabilities); + byte++, index++) { + data[index] = (capabilities >> (byte * ADF_PFVF_DATA_SHIFT)) & + ADF_PFVF_DATA_MASK; + } + + if (frequency) { + for (byte = 0, index = ADF_VF2PF_CAPABILITIES_FREQ_OFFSET; + byte < sizeof(frequency); + byte++, index++) { + data[index] = + (frequency >> (byte * ADF_PFVF_DATA_SHIFT)) & + ADF_PFVF_DATA_MASK; + } + *length = ADF_VF2PF_CAPABILITIES_V3_LENGTH; + *block_version = ADF_VF2PF_CAPABILITIES_V3_VERSION; + } else { + *length = ADF_VF2PF_CAPABILITIES_V2_LENGTH; + *block_version = ADF_VF2PF_CAPABILITIES_V2_VERSION; + } + + *buffer = data; + return 0; +} + +int +adf_pf_vf_capabilities_init(struct adf_accel_dev *accel_dev) +{ + u8 data[ADF_VF2PF_CAPABILITIES_V3_LENGTH] = { 0 }; + u8 len = ADF_VF2PF_CAPABILITIES_V3_LENGTH; + u8 version = ADF_VF2PF_CAPABILITIES_V2_VERSION; + u32 ex_dc_cap = 0; + u32 capabilities = 0; + u32 frequency = 0; + u16 byte = 0; + u16 index = 0; + + if (!accel_dev->is_vf) { + /* on the pf */ + if (!adf_iov_is_block_provider_registered( + ADF_VF2PF_BLOCK_MSG_CAP_SUMMARY)) + adf_iov_block_provider_register( + ADF_VF2PF_BLOCK_MSG_CAP_SUMMARY, + adf_pf_capabilities_msg_provider); + } else if (accel_dev->u1.vf.pf_version >= + ADF_PFVF_COMPATIBILITY_CAPABILITIES) { + /* on the vf */ + if (adf_iov_block_get(accel_dev, + ADF_VF2PF_BLOCK_MSG_CAP_SUMMARY, + &version, + data, + &len)) { + device_printf(GET_DEV(accel_dev), + "QAT: Failed adf_iov_block_get\n"); + return EFAULT; + } + + if (len < ADF_VF2PF_CAPABILITIES_V1_LENGTH) { + device_printf( + GET_DEV(accel_dev), + "Capabilities message truncated to %d bytes\n", + len); + return EFAULT; + } + + for (byte = 0; byte < sizeof(ex_dc_cap); byte++) { + ex_dc_cap |= data[byte] << (byte * ADF_PFVF_DATA_SHIFT); + } + accel_dev->hw_device->extended_dc_capabilities = ex_dc_cap; + + /* Get capabilities if provided by PF */ + if (len >= ADF_VF2PF_CAPABILITIES_V2_LENGTH) { + for (byte = 0, + index = ADF_VF2PF_CAPABILITIES_CAP_OFFSET; + byte < sizeof(capabilities); + byte++, index++) { + capabilities |= data[index] + << (byte * ADF_PFVF_DATA_SHIFT); + } + accel_dev->hw_device->accel_capabilities_mask = + capabilities; + } else { + device_printf(GET_DEV(accel_dev), + "PF did not communicate capabilities\n"); + } + + /* Get frequency if provided by the PF */ + if (len >= ADF_VF2PF_CAPABILITIES_V3_LENGTH) { + for (byte = 0, + index = ADF_VF2PF_CAPABILITIES_FREQ_OFFSET; + byte < sizeof(frequency); + byte++, index++) { + frequency |= data[index] + << (byte * ADF_PFVF_DATA_SHIFT); + } + accel_dev->hw_device->clock_frequency = frequency; + } else { + device_printf(GET_DEV(accel_dev), + "PF did not communicate frequency\n"); + } + + } else { + /* The PF is too old to support the extended capabilities */ + accel_dev->hw_device->extended_dc_capabilities = 0; + } + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_pf2vf_msg.c b/sys/dev/qat/qat_common/adf_pf2vf_msg.c new file mode 100644 index 00000000000..60b1102f470 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_pf2vf_msg.c @@ -0,0 +1,896 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_pf2vf_msg.h" + +adf_iov_block_provider + pf2vf_message_providers[ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE + 1]; +unsigned char pfvf_crc8_table[] = + { 0x00, 0x97, 0xB9, 0x2E, 0xE5, 0x72, 0x5C, 0xCB, 0x5D, 0xCA, 0xE4, 0x73, + 0xB8, 0x2F, 0x01, 0x96, 0xBA, 0x2D, 0x03, 0x94, 0x5F, 0xC8, 0xE6, 0x71, + 0xE7, 0x70, 0x5E, 0xC9, 0x02, 0x95, 0xBB, 0x2C, 0xE3, 0x74, 0x5A, 0xCD, + 0x06, 0x91, 0xBF, 0x28, 0xBE, 0x29, 0x07, 0x90, 0x5B, 0xCC, 0xE2, 0x75, + 0x59, 0xCE, 0xE0, 0x77, 0xBC, 0x2B, 0x05, 0x92, 0x04, 0x93, 0xBD, 0x2A, + 0xE1, 0x76, 0x58, 0xCF, 0x51, 0xC6, 0xE8, 0x7F, 0xB4, 0x23, 0x0D, 0x9A, + 0x0C, 0x9B, 0xB5, 0x22, 0xE9, 0x7E, 0x50, 0xC7, 0xEB, 0x7C, 0x52, 0xC5, + 0x0E, 0x99, 0xB7, 0x20, 0xB6, 0x21, 0x0F, 0x98, 0x53, 0xC4, 0xEA, 0x7D, + 0xB2, 0x25, 0x0B, 0x9C, 0x57, 0xC0, 0xEE, 0x79, 0xEF, 0x78, 0x56, 0xC1, + 0x0A, 0x9D, 0xB3, 0x24, 0x08, 0x9F, 0xB1, 0x26, 0xED, 0x7A, 0x54, 0xC3, + 0x55, 0xC2, 0xEC, 0x7B, 0xB0, 0x27, 0x09, 0x9E, 0xA2, 0x35, 0x1B, 0x8C, + 0x47, 0xD0, 0xFE, 0x69, 0xFF, 0x68, 0x46, 0xD1, 0x1A, 0x8D, 0xA3, 0x34, + 0x18, 0x8F, 0xA1, 0x36, 0xFD, 0x6A, 0x44, 0xD3, 0x45, 0xD2, 0xFC, 0x6B, + 0xA0, 0x37, 0x19, 0x8E, 0x41, 0xD6, 0xF8, 0x6F, 0xA4, 0x33, 0x1D, 0x8A, + 0x1C, 0x8B, 0xA5, 0x32, 0xF9, 0x6E, 0x40, 0xD7, 0xFB, 0x6C, 0x42, 0xD5, + 0x1E, 0x89, 0xA7, 0x30, 0xA6, 0x31, 0x1F, 0x88, 0x43, 0xD4, 0xFA, 0x6D, + 0xF3, 0x64, 0x4A, 0xDD, 0x16, 0x81, 0xAF, 0x38, 0xAE, 0x39, 0x17, 0x80, + 0x4B, 0xDC, 0xF2, 0x65, 0x49, 0xDE, 0xF0, 0x67, 0xAC, 0x3B, 0x15, 0x82, + 0x14, 0x83, 0xAD, 0x3A, 0xF1, 0x66, 0x48, 0xDF, 0x10, 0x87, 0xA9, 0x3E, + 0xF5, 0x62, 0x4C, 0xDB, 0x4D, 0xDA, 0xF4, 0x63, 0xA8, 0x3F, 0x11, 0x86, + 0xAA, 0x3D, 0x13, 0x84, 0x4F, 0xD8, 0xF6, 0x61, 0xF7, 0x60, 0x4E, 0xD9, + 0x12, 0x85, 0xAB, 0x3C }; + +void +adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *pmisc_bar_addr = + pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr; + + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x0); +} + +void +adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *pmisc_bar_addr = + pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr; + + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x2); +} + +static int +__adf_iov_putmsg(struct adf_accel_dev *accel_dev, + u32 msg, + u8 vf_nr, + bool is_notification) +{ + struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *pmisc_bar_addr = + pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr; + u32 val, pf2vf_offset; + u32 total_delay = 0, mdelay = ADF_IOV_MSG_ACK_DELAY_MS, + udelay = ADF_IOV_MSG_ACK_DELAY_US; + u32 local_in_use_mask, local_in_use_pattern; + u32 remote_in_use_mask, remote_in_use_pattern; + struct mutex *lock; /* lock preventing concurrent acces of CSR */ + u32 int_bit; + int ret = 0; + struct pfvf_stats *pfvf_counters = NULL; + + if (accel_dev->is_vf) { + pf2vf_offset = hw_data->get_pf2vf_offset(0); + lock = &accel_dev->u1.vf.vf2pf_lock; + local_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK; + local_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF; + remote_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK; + remote_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF; + int_bit = ADF_VF2PF_INT; + pfvf_counters = &accel_dev->u1.vf.pfvf_counters; + } else { + pf2vf_offset = hw_data->get_pf2vf_offset(vf_nr); + lock = &accel_dev->u1.pf.vf_info[vf_nr].pf2vf_lock; + local_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK; + local_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF; + remote_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK; + remote_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF; + int_bit = ADF_PF2VF_INT; + pfvf_counters = &accel_dev->u1.pf.vf_info[vf_nr].pfvf_counters; + } + + mutex_lock(lock); + + /* Check if PF2VF CSR is in use by remote function */ + val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset); + if ((val & remote_in_use_mask) == remote_in_use_pattern) { + device_printf(GET_DEV(accel_dev), + "PF2VF CSR in use by remote function\n"); + ret = EAGAIN; + pfvf_counters->busy++; + goto out; + } + + /* Attempt to get ownership of PF2VF CSR */ + msg &= ~local_in_use_mask; + msg |= local_in_use_pattern; + ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg | int_bit); + pfvf_counters->tx++; + + /* Wait for confirmation from remote func it received the message */ + do { + if (udelay < ADF_IOV_MSG_ACK_EXP_MAX_DELAY_US) { + usleep_range(udelay, udelay * 2); + udelay = udelay * 2; + total_delay = total_delay + udelay; + } else { + pause_ms("adfstop", mdelay); + total_delay = total_delay + (mdelay * 1000); + } + val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset); + } while ((val & int_bit) && + (total_delay < ADF_IOV_MSG_ACK_LIN_MAX_DELAY_US)); + + if (val & int_bit) { + device_printf(GET_DEV(accel_dev), + "ACK not received from remote\n"); + pfvf_counters->no_ack++; + val &= ~int_bit; + ret = EIO; + } + + /* For fire-and-forget notifications, the receiver does not clear + * the in-use pattern. This is used to detect collisions. + */ + if (is_notification && (val & ~int_bit) != msg) { + /* Collision must have overwritten the message */ + device_printf(GET_DEV(accel_dev), + "Collision on notification\n"); + pfvf_counters->collision++; + ret = EAGAIN; + goto out; + } + + /* + * If the far side did not clear the in-use pattern it is either + * 1) Notification - message left intact to detect collision + * 2) Older protocol (compatibility version < 3) on the far side + * where the sender is responsible for clearing the in-use + * pattern after the received has acknowledged receipt. + * In either case, clear the in-use pattern now. + */ + if ((val & local_in_use_mask) == local_in_use_pattern) + ADF_CSR_WR(pmisc_bar_addr, + pf2vf_offset, + val & ~local_in_use_mask); + +out: + mutex_unlock(lock); + return ret; +} + +static int +adf_iov_put(struct adf_accel_dev *accel_dev, + u32 msg, + u8 vf_nr, + bool is_notification) +{ + u32 count = 0, delay = ADF_IOV_MSG_RETRY_DELAY; + int ret; + struct pfvf_stats *pfvf_counters = NULL; + + if (accel_dev->is_vf) + pfvf_counters = &accel_dev->u1.vf.pfvf_counters; + else + pfvf_counters = &accel_dev->u1.pf.vf_info[vf_nr].pfvf_counters; + + do { + ret = __adf_iov_putmsg(accel_dev, msg, vf_nr, is_notification); + if (ret == EAGAIN) + pause_ms("adfstop", delay); + delay = delay * 2; + } while (ret == EAGAIN && ++count < ADF_IOV_MSG_MAX_RETRIES); + if (ret == EAGAIN) { + if (is_notification) + pfvf_counters->event_timeout++; + else + pfvf_counters->tx_timeout++; + } + + return ret; +} + +/** + * adf_iov_putmsg() - send PF2VF message + * @accel_dev: Pointer to acceleration device. + * @msg: Message to send + * @vf_nr: VF number to which the message will be sent + * + * Function sends a messge from the PF to a VF + * + * Return: 0 on success, error code otherwise. + */ +int +adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) +{ + return adf_iov_put(accel_dev, msg, vf_nr, false); +} + +/** + * adf_iov_notify() - send PF2VF notification message + * @accel_dev: Pointer to acceleration device. + * @msg: Message to send + * @vf_nr: VF number to which the message will be sent + * + * Function sends a notification messge from the PF to a VF + * + * Return: 0 on success, error code otherwise. + */ +int +adf_iov_notify(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) +{ + return adf_iov_put(accel_dev, msg, vf_nr, true); +} + +u8 +adf_pfvf_crc(u8 start_crc, u8 *buf, u8 len) +{ + u8 crc = start_crc; + + while (len-- > 0) + crc = pfvf_crc8_table[(crc ^ *buf++) & 0xff]; + + return crc; +} + +int +adf_iov_block_provider_register(u8 msg_type, + const adf_iov_block_provider provider) +{ + if (msg_type >= ARRAY_SIZE(pf2vf_message_providers)) { + pr_err("QAT: invalid message type %d for PF2VF provider\n", + msg_type); + return -EINVAL; + } + if (pf2vf_message_providers[msg_type]) { + pr_err("QAT: Provider %ps already registered for message %d\n", + pf2vf_message_providers[msg_type], + msg_type); + return -EINVAL; + } + + pf2vf_message_providers[msg_type] = provider; + return 0; +} + +u8 +adf_iov_is_block_provider_registered(u8 msg_type) +{ + if (pf2vf_message_providers[msg_type]) + return 1; + else + return 0; +} + +int +adf_iov_block_provider_unregister(u8 msg_type, + const adf_iov_block_provider provider) +{ + if (msg_type >= ARRAY_SIZE(pf2vf_message_providers)) { + pr_err("QAT: invalid message type %d for PF2VF provider\n", + msg_type); + return -EINVAL; + } + if (pf2vf_message_providers[msg_type] != provider) { + pr_err("QAT: Provider %ps not registered for message %d\n", + provider, + msg_type); + return -EINVAL; + } + + pf2vf_message_providers[msg_type] = NULL; + return 0; +} + +static int +adf_iov_block_get_data(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 byte_num, + u8 *data, + u8 compatibility, + bool crc) +{ + u8 *buffer; + u8 size; + u8 msg_ver; + u8 crc8; + + if (msg_type >= ARRAY_SIZE(pf2vf_message_providers)) { + pr_err("QAT: invalid message type %d for PF2VF provider\n", + msg_type); + *data = ADF_PF2VF_INVALID_BLOCK_TYPE; + return -EINVAL; + } + + if (!pf2vf_message_providers[msg_type]) { + pr_err("QAT: No registered provider for message %d\n", + msg_type); + *data = ADF_PF2VF_INVALID_BLOCK_TYPE; + return -EINVAL; + } + + if ((*pf2vf_message_providers[msg_type])( + accel_dev, &buffer, &size, &msg_ver, compatibility, byte_num)) { + pr_err("QAT: unknown error from provider for message %d\n", + msg_type); + *data = ADF_PF2VF_UNSPECIFIED_ERROR; + return -EINVAL; + } + + if ((msg_type <= ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE && + size > ADF_VF2PF_SMALL_PAYLOAD_SIZE) || + (msg_type <= ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE && + size > ADF_VF2PF_MEDIUM_PAYLOAD_SIZE) || + size > ADF_VF2PF_LARGE_PAYLOAD_SIZE) { + pr_err("QAT: Invalid size %d provided for message type %d\n", + size, + msg_type); + *data = ADF_PF2VF_PAYLOAD_TRUNCATED; + return -EINVAL; + } + + if ((!byte_num && crc) || byte_num >= size + ADF_VF2PF_BLOCK_DATA) { + pr_err("QAT: Invalid byte number %d for message %d\n", + byte_num, + msg_type); + *data = ADF_PF2VF_INVALID_BYTE_NUM_REQ; + return -EINVAL; + } + + if (crc) { + crc8 = adf_pfvf_crc(ADF_CRC8_INIT_VALUE, &msg_ver, 1); + crc8 = adf_pfvf_crc(crc8, &size, 1); + *data = adf_pfvf_crc(crc8, buffer, byte_num - 1); + } else { + if (byte_num == 0) + *data = msg_ver; + else if (byte_num == 1) + *data = size; + else + *data = buffer[byte_num - 2]; + } + + return 0; +} + +static int +adf_iov_block_get_byte(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 byte_num, + u8 *data, + u8 compatibility) +{ + return adf_iov_block_get_data( + accel_dev, msg_type, byte_num, data, compatibility, false); +} + +static int +adf_iov_block_get_crc(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 byte_num, + u8 *data, + u8 compatibility) +{ + return adf_iov_block_get_data( + accel_dev, msg_type, byte_num, data, compatibility, true); +} + +int adf_iov_compatibility_check(struct adf_accel_dev *accel_dev, u8 compat_ver); + +void +adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info) +{ + struct adf_accel_dev *accel_dev = vf_info->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + int bar_id = hw_data->get_misc_bar_id(hw_data); + struct adf_bar *pmisc = &GET_BARS(accel_dev)[bar_id]; + struct resource *pmisc_addr = pmisc->virt_addr; + u32 msg, resp = 0, vf_nr = vf_info->vf_nr; + u8 byte_num = 0; + u8 msg_type = 0; + u8 resp_type; + int res; + u8 data; + u8 compat = 0x0; + int vf_compat_ver = 0; + bool is_notification = false; + + /* Read message from the VF */ + msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr)); + if (!(msg & ADF_VF2PF_INT)) { + device_printf(GET_DEV(accel_dev), + "Spurious VF2PF interrupt. msg %X. Ignored\n", + msg); + vf_info->pfvf_counters.spurious++; + goto out; + } + vf_info->pfvf_counters.rx++; + + if (!(msg & ADF_VF2PF_MSGORIGIN_SYSTEM)) { + /* Ignore legacy non-system (non-kernel) VF2PF messages */ + device_printf(GET_DEV(accel_dev), + "Ignored non-system message from VF%d (0x%x);\n", + vf_nr + 1, + msg); + /* + * To ack, clear the VF2PFINT bit. + * Because this must be a legacy message, the far side + * must clear the in-use pattern. + */ + msg &= ~(ADF_VF2PF_INT); + ADF_CSR_WR(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr), msg); + + goto out; + } + + switch ((msg & ADF_VF2PF_MSGTYPE_MASK) >> ADF_VF2PF_MSGTYPE_SHIFT) { + case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ: + + { + is_notification = false; + vf_compat_ver = msg >> ADF_VF2PF_COMPAT_VER_REQ_SHIFT; + vf_info->compat_ver = vf_compat_ver; + + resp = (ADF_PF2VF_MSGORIGIN_SYSTEM | + (ADF_PF2VF_MSGTYPE_VERSION_RESP + << ADF_PF2VF_MSGTYPE_SHIFT) | + (ADF_PFVF_COMPATIBILITY_VERSION + << ADF_PF2VF_VERSION_RESP_VERS_SHIFT)); + + device_printf( + GET_DEV(accel_dev), + "Compatibility Version Request from VF%d vers=%u\n", + vf_nr + 1, + vf_info->compat_ver); + + if (vf_compat_ver < ADF_PFVF_COMPATIBILITY_VERSION) + compat = adf_iov_compatibility_check(accel_dev, + vf_compat_ver); + else if (vf_compat_ver == ADF_PFVF_COMPATIBILITY_VERSION) + compat = ADF_PF2VF_VF_COMPATIBLE; + else + compat = ADF_PF2VF_VF_COMPAT_UNKNOWN; + + resp |= compat << ADF_PF2VF_VERSION_RESP_RESULT_SHIFT; + + if (compat == ADF_PF2VF_VF_INCOMPATIBLE) + device_printf(GET_DEV(accel_dev), + "VF%d and PF are incompatible.\n", + vf_nr + 1); + } break; + case ADF_VF2PF_MSGTYPE_VERSION_REQ: + device_printf(GET_DEV(accel_dev), + "Legacy VersionRequest received from VF%d 0x%x\n", + vf_nr + 1, + msg); + is_notification = false; + + /* legacy driver, VF compat_ver is 0 */ + vf_info->compat_ver = 0; + + resp = (ADF_PF2VF_MSGORIGIN_SYSTEM | + (ADF_PF2VF_MSGTYPE_VERSION_RESP + << ADF_PF2VF_MSGTYPE_SHIFT)); + + /* PF always newer than legacy VF */ + compat = + adf_iov_compatibility_check(accel_dev, vf_info->compat_ver); + resp |= compat << ADF_PF2VF_VERSION_RESP_RESULT_SHIFT; + + /* Set legacy major and minor version num */ + resp |= 1 << ADF_PF2VF_MAJORVERSION_SHIFT | + 1 << ADF_PF2VF_MINORVERSION_SHIFT; + + if (compat == ADF_PF2VF_VF_INCOMPATIBLE) + device_printf(GET_DEV(accel_dev), + "VF%d and PF are incompatible.\n", + vf_nr + 1); + break; + case ADF_VF2PF_MSGTYPE_INIT: { + device_printf(GET_DEV(accel_dev), + "Init message received from VF%d 0x%x\n", + vf_nr + 1, + msg); + is_notification = true; + vf_info->init = true; + } break; + case ADF_VF2PF_MSGTYPE_SHUTDOWN: { + device_printf(GET_DEV(accel_dev), + "Shutdown message received from VF%d 0x%x\n", + vf_nr + 1, + msg); + is_notification = true; + vf_info->init = false; + } break; + case ADF_VF2PF_MSGTYPE_GET_LARGE_BLOCK_REQ: + case ADF_VF2PF_MSGTYPE_GET_MEDIUM_BLOCK_REQ: + case ADF_VF2PF_MSGTYPE_GET_SMALL_BLOCK_REQ: { + is_notification = false; + switch ((msg & ADF_VF2PF_MSGTYPE_MASK) >> + ADF_VF2PF_MSGTYPE_SHIFT) { + case ADF_VF2PF_MSGTYPE_GET_LARGE_BLOCK_REQ: + byte_num = + ((msg & ADF_VF2PF_LARGE_BLOCK_BYTE_NUM_MASK) >> + ADF_VF2PF_LARGE_BLOCK_BYTE_NUM_SHIFT); + msg_type = + ((msg & ADF_VF2PF_LARGE_BLOCK_REQ_TYPE_MASK) >> + ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT); + msg_type += ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE; + break; + case ADF_VF2PF_MSGTYPE_GET_MEDIUM_BLOCK_REQ: + byte_num = + ((msg & ADF_VF2PF_MEDIUM_BLOCK_BYTE_NUM_MASK) >> + ADF_VF2PF_MEDIUM_BLOCK_BYTE_NUM_SHIFT); + msg_type = + ((msg & ADF_VF2PF_MEDIUM_BLOCK_REQ_TYPE_MASK) >> + ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT); + msg_type += ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE; + break; + case ADF_VF2PF_MSGTYPE_GET_SMALL_BLOCK_REQ: + byte_num = + ((msg & ADF_VF2PF_SMALL_BLOCK_BYTE_NUM_MASK) >> + ADF_VF2PF_SMALL_BLOCK_BYTE_NUM_SHIFT); + msg_type = + ((msg & ADF_VF2PF_SMALL_BLOCK_REQ_TYPE_MASK) >> + ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT); + msg_type += ADF_VF2PF_MIN_SMALL_MESSAGE_TYPE; + break; + } + + if (msg >> ADF_VF2PF_BLOCK_REQ_CRC_SHIFT) { + res = adf_iov_block_get_crc(accel_dev, + msg_type, + byte_num, + &data, + vf_info->compat_ver); + if (res) + resp_type = ADF_PF2VF_BLOCK_RESP_TYPE_ERROR; + else + resp_type = ADF_PF2VF_BLOCK_RESP_TYPE_CRC; + } else { + if (!byte_num) + vf_info->pfvf_counters.blk_tx++; + + res = adf_iov_block_get_byte(accel_dev, + msg_type, + byte_num, + &data, + vf_info->compat_ver); + if (res) + resp_type = ADF_PF2VF_BLOCK_RESP_TYPE_ERROR; + else + resp_type = ADF_PF2VF_BLOCK_RESP_TYPE_DATA; + } + resp = + (ADF_PF2VF_MSGORIGIN_SYSTEM | + (ADF_PF2VF_MSGTYPE_BLOCK_RESP << ADF_PF2VF_MSGTYPE_SHIFT) | + (resp_type << ADF_PF2VF_BLOCK_RESP_TYPE_SHIFT) | + (data << ADF_PF2VF_BLOCK_RESP_DATA_SHIFT)); + } break; + default: + device_printf(GET_DEV(accel_dev), + "Unknown message from VF%d (0x%x);\n", + vf_nr + 1, + msg); + } + + /* To ack, clear the VF2PFINT bit and the in-use-by */ + msg &= ~ADF_VF2PF_INT; + /* + * Clear the in-use pattern if the sender won't do it. + * Because the compatibility version must be the first message + * exchanged between the VF and PF, the vf_info->compat_ver must be + * set at this time. + * The in-use pattern is not cleared for notifications so that + * it can be used for collision detection. + */ + if (vf_info->compat_ver >= ADF_PFVF_COMPATIBILITY_FAST_ACK && + !is_notification) + msg &= ~ADF_VF2PF_IN_USE_BY_VF_MASK; + ADF_CSR_WR(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr), msg); + + if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr)) + device_printf(GET_DEV(accel_dev), + "Failed to send response to VF\n"); + +out: + return; +} + +void +adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_vf_info *vf; + u32 msg = (ADF_PF2VF_MSGORIGIN_SYSTEM | + (ADF_PF2VF_MSGTYPE_RESTARTING << ADF_PF2VF_MSGTYPE_SHIFT)); + + int i, num_vfs = accel_dev->u1.pf.num_vfs; + for (i = 0, vf = accel_dev->u1.pf.vf_info; i < num_vfs; i++, vf++) { + if (vf->init && adf_iov_notify(accel_dev, msg, i)) + device_printf(GET_DEV(accel_dev), + "Failed to send restarting msg to VF%d\n", + i); + } +} + +void +adf_pf2vf_notify_fatal_error(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_vf_info *vf; + int i, num_vfs = accel_dev->u1.pf.num_vfs; + u32 msg = (ADF_PF2VF_MSGORIGIN_SYSTEM | + (ADF_PF2VF_MSGTYPE_FATAL_ERROR << ADF_PF2VF_MSGTYPE_SHIFT)); + + for (i = 0, vf = accel_dev->u1.pf.vf_info; i < num_vfs; i++, vf++) { + if (vf->init && adf_iov_notify(accel_dev, msg, i)) + device_printf( + GET_DEV(accel_dev), + "Failed to send fatal error msg 0x%x to VF%d\n", + msg, + i); + } +} + +int +adf_iov_register_compat_checker(struct adf_accel_dev *accel_dev, + const adf_iov_compat_checker_t cc) +{ + struct adf_accel_compat_manager *cm = accel_dev->cm; + int num = 0; + + if (!cm) { + device_printf(GET_DEV(accel_dev), + "QAT: compatibility manager not initialized\n"); + return ENOMEM; + } + + for (num = 0; num < ADF_COMPAT_CHECKER_MAX; num++) { + if (cm->iov_compat_checkers[num]) { + if (cc == cm->iov_compat_checkers[num]) { + device_printf(GET_DEV(accel_dev), + "QAT: already registered\n"); + return EFAULT; + } + } else { + /* registering the new checker */ + cm->iov_compat_checkers[num] = cc; + break; + } + } + + if (num >= ADF_COMPAT_CHECKER_MAX) { + device_printf(GET_DEV(accel_dev), + "QAT: compatibility checkers are overflow.\n"); + return EFAULT; + } + + cm->num_chker = num; + return 0; +} + +int +adf_iov_unregister_compat_checker(struct adf_accel_dev *accel_dev, + const adf_iov_compat_checker_t cc) +{ + struct adf_accel_compat_manager *cm = accel_dev->cm; + int num = 0; + + if (!cm) { + device_printf(GET_DEV(accel_dev), + "QAT: compatibility manager not initialized\n"); + return ENOMEM; + } + num = cm->num_chker - 1; + + if (num < 0) { + device_printf( + GET_DEV(accel_dev), + "QAT: Array 'iov_compat_checkers' may use index value(s) -1\n"); + return EFAULT; + } + if (cc == cm->iov_compat_checkers[num]) { + /* unregistering the given checker */ + cm->iov_compat_checkers[num] = NULL; + } else { + device_printf( + GET_DEV(accel_dev), + "QAT: unregistering not in the registered order\n"); + return EFAULT; + } + + cm->num_chker--; + return 0; +} + +int +adf_iov_init_compat_manager(struct adf_accel_dev *accel_dev, + struct adf_accel_compat_manager **cm) +{ + if (!(*cm)) { + *cm = malloc(sizeof(**cm), M_QAT, M_WAITOK | M_ZERO); + } else { + /* zero the struct */ + explicit_bzero(*cm, sizeof(**cm)); + } + + return 0; +} + +int +adf_iov_shutdown_compat_manager(struct adf_accel_dev *accel_dev, + struct adf_accel_compat_manager **cm) +{ + if (*cm) { + free(*cm, M_QAT); + *cm = NULL; + } + return 0; +} + +int +adf_iov_compatibility_check(struct adf_accel_dev *accel_dev, u8 compat_ver) +{ + int compatible = ADF_PF2VF_VF_COMPATIBLE; + int i = 0; + struct adf_accel_compat_manager *cm = accel_dev->cm; + + if (!cm) { + device_printf(GET_DEV(accel_dev), + "QAT: compatibility manager not initialized\n"); + return ADF_PF2VF_VF_INCOMPATIBLE; + } + for (i = 0; i < cm->num_chker; i++) { + compatible = cm->iov_compat_checkers[i](accel_dev, compat_ver); + if (compatible == ADF_PF2VF_VF_INCOMPATIBLE) { + device_printf( + GET_DEV(accel_dev), + "QAT: PF and VF are incompatible [checker%d]\n", + i); + break; + } + } + return compatible; +} + +static int +adf_vf2pf_request_version(struct adf_accel_dev *accel_dev) +{ + unsigned long timeout = msecs_to_jiffies(ADF_IOV_MSG_RESP_TIMEOUT); + u32 msg = 0; + int ret = 0; + int comp = 0; + int response_received = 0; + int retry_count = 0; + struct pfvf_stats *pfvf_counters = NULL; + + pfvf_counters = &accel_dev->u1.vf.pfvf_counters; + + msg = ADF_VF2PF_MSGORIGIN_SYSTEM; + msg |= ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ << ADF_VF2PF_MSGTYPE_SHIFT; + msg |= ADF_PFVF_COMPATIBILITY_VERSION << ADF_VF2PF_COMPAT_VER_REQ_SHIFT; + BUILD_BUG_ON(ADF_PFVF_COMPATIBILITY_VERSION > 255); + /* Clear communication flag - without that VF will not be waiting for + * the response from host driver, and start sending init. + */ + accel_dev->u1.vf.iov_msg_completion = 0; + do { + /* Send request from VF to PF */ + if (retry_count) + pfvf_counters->retry++; + if (adf_iov_putmsg(accel_dev, msg, 0)) { + device_printf( + GET_DEV(accel_dev), + "Failed to send Compat Version Request.\n"); + return EIO; + } + mutex_lock(&accel_dev->u1.vf.vf2pf_lock); + if (accel_dev->u1.vf.iov_msg_completion == 0 && + sx_sleep(&accel_dev->u1.vf.iov_msg_completion, + &accel_dev->u1.vf.vf2pf_lock.sx, + 0, + "pfver", + timeout) == EWOULDBLOCK) { + /* It's possible that wakeup could be missed */ + if (accel_dev->u1.vf.iov_msg_completion) { + response_received = 1; + } else { + device_printf( + GET_DEV(accel_dev), + "IOV request/response message timeout expired\n"); + } + } else { + response_received = 1; + } + mutex_unlock(&accel_dev->u1.vf.vf2pf_lock); + } while (!response_received && + ++retry_count < ADF_IOV_MSG_RESP_RETRIES); + + if (!response_received) + pfvf_counters->rx_timeout++; + else + pfvf_counters->rx_rsp++; + if (!response_received) + return EIO; + + if (accel_dev->u1.vf.compatible == ADF_PF2VF_VF_COMPAT_UNKNOWN) + /* Response from PF received, check compatibility */ + comp = adf_iov_compatibility_check(accel_dev, + accel_dev->u1.vf.pf_version); + else + comp = accel_dev->u1.vf.compatible; + + ret = (comp == ADF_PF2VF_VF_COMPATIBLE) ? 0 : EFAULT; + if (ret) + device_printf( + GET_DEV(accel_dev), + "VF is not compatible with PF, due to the reason %d\n", + comp); + + return ret; +} + +/** + * adf_enable_vf2pf_comms() - Function enables communication from vf to pf + * + * @accel_dev: Pointer to acceleration device virtual function. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev) +{ + int ret = 0; + + /* init workqueue for VF */ + ret = adf_init_vf_wq(); + if (ret) + return ret; + + adf_enable_pf2vf_interrupts(accel_dev); + adf_iov_init_compat_manager(accel_dev, &accel_dev->cm); + return adf_vf2pf_request_version(accel_dev); +} +/** + * adf_disable_vf2pf_comms() - Function disables communication from vf to pf + * + * @accel_dev: Pointer to acceleration device virtual function. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_disable_vf2pf_comms(struct adf_accel_dev *accel_dev) +{ + return adf_iov_shutdown_compat_manager(accel_dev, &accel_dev->cm); +} + +/** + * adf_pf_enable_vf2pf_comms() - Function enables communication from pf + * + * @accel_dev: Pointer to acceleration device physical function. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_pf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev) +{ + adf_iov_init_compat_manager(accel_dev, &accel_dev->cm); + return 0; +} + +/** + * adf_pf_disable_vf2pf_comms() - Function disables communication from pf + * + * @accel_dev: Pointer to acceleration device physical function. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_pf_disable_vf2pf_comms(struct adf_accel_dev *accel_dev) +{ + return adf_iov_shutdown_compat_manager(accel_dev, &accel_dev->cm); +} diff --git a/sys/dev/qat/qat_common/adf_pf2vf_ring_to_svc_map.c b/sys/dev/qat/qat_common/adf_pf2vf_ring_to_svc_map.c new file mode 100644 index 00000000000..46c13068227 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_pf2vf_ring_to_svc_map.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_pf2vf_msg.h" +#include "adf_cfg.h" + +#define ADF_VF2PF_RING_TO_SVC_VERSION 1 +#define ADF_VF2PF_RING_TO_SVC_LENGTH 2 + +int +adf_pf_ring_to_svc_msg_provider(struct adf_accel_dev *accel_dev, + u8 **buffer, + u8 *length, + u8 *block_version, + u8 compatibility, + u8 byte_num) +{ + static u8 data[ADF_VF2PF_RING_TO_SVC_LENGTH] = { 0 }; + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + u16 ring_to_svc_map = hw_data->ring_to_svc_map; + u16 byte = 0; + + for (byte = 0; byte < ADF_VF2PF_RING_TO_SVC_LENGTH; byte++) { + data[byte] = (ring_to_svc_map >> (byte * ADF_PFVF_DATA_SHIFT)) & + ADF_PFVF_DATA_MASK; + } + + *length = ADF_VF2PF_RING_TO_SVC_LENGTH; + *block_version = ADF_VF2PF_RING_TO_SVC_VERSION; + *buffer = data; + + return 0; +} + +int +adf_pf_vf_ring_to_svc_init(struct adf_accel_dev *accel_dev) +{ + u8 data[ADF_VF2PF_RING_TO_SVC_LENGTH] = { 0 }; + u8 len = ADF_VF2PF_RING_TO_SVC_LENGTH; + u8 version = ADF_VF2PF_RING_TO_SVC_VERSION; + u16 ring_to_svc_map = 0; + u16 byte = 0; + + if (!accel_dev->is_vf) { + /* on the pf */ + if (!adf_iov_is_block_provider_registered( + ADF_VF2PF_BLOCK_MSG_GET_RING_TO_SVC_REQ)) + adf_iov_block_provider_register( + ADF_VF2PF_BLOCK_MSG_GET_RING_TO_SVC_REQ, + adf_pf_ring_to_svc_msg_provider); + } else if (accel_dev->u1.vf.pf_version >= + ADF_PFVF_COMPATIBILITY_RING_TO_SVC_MAP) { + /* on the vf */ + if (adf_iov_block_get(accel_dev, + ADF_VF2PF_BLOCK_MSG_GET_RING_TO_SVC_REQ, + &version, + data, + &len)) { + device_printf(GET_DEV(accel_dev), + "QAT: Failed adf_iov_block_get\n"); + return EFAULT; + } + for (byte = 0; byte < ADF_VF2PF_RING_TO_SVC_LENGTH; byte++) { + ring_to_svc_map |= data[byte] + << (byte * ADF_PFVF_DATA_SHIFT); + } + GET_HW_DATA(accel_dev)->ring_to_svc_map = ring_to_svc_map; + } + + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_transport.c b/sys/dev/qat/qat_common/adf_transport.c new file mode 100644 index 00000000000..e896f1d70e0 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_transport.c @@ -0,0 +1,747 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include "adf_accel_devices.h" +#include "adf_transport_internal.h" +#include "adf_transport_access_macros.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" + +#define QAT_RING_ALIGNMENT 64 + +static inline u32 +adf_modulo(u32 data, u32 shift) +{ + u32 div = data >> shift; + u32 mult = div << shift; + + return data - mult; +} + +static inline int +adf_check_ring_alignment(u64 addr, u64 size) +{ + if (((size - 1) & addr) != 0) + return EFAULT; + return 0; +} + +static int +adf_verify_ring_size(u32 msg_size, u32 msg_num) +{ + int i = ADF_MIN_RING_SIZE; + + for (; i <= ADF_MAX_RING_SIZE; i++) + if ((msg_size * msg_num) == ADF_SIZE_TO_RING_SIZE_IN_BYTES(i)) + return i; + + return ADF_DEFAULT_RING_SIZE; +} + +static int +adf_reserve_ring(struct adf_etr_bank_data *bank, u32 ring) +{ + mtx_lock(&bank->lock); + if (bank->ring_mask & (1 << ring)) { + mtx_unlock(&bank->lock); + return EFAULT; + } + bank->ring_mask |= (1 << ring); + mtx_unlock(&bank->lock); + return 0; +} + +static void +adf_unreserve_ring(struct adf_etr_bank_data *bank, u32 ring) +{ + mtx_lock(&bank->lock); + bank->ring_mask &= ~(1 << ring); + mtx_unlock(&bank->lock); +} + +static void +adf_enable_ring_irq(struct adf_etr_bank_data *bank, u32 ring) +{ + mtx_lock(&bank->lock); + bank->irq_mask |= (1 << ring); + mtx_unlock(&bank->lock); + WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask); + WRITE_CSR_INT_COL_CTL(bank->csr_addr, + bank->bank_number, + bank->irq_coalesc_timer); +} + +static void +adf_disable_ring_irq(struct adf_etr_bank_data *bank, u32 ring) +{ + mtx_lock(&bank->lock); + bank->irq_mask &= ~(1 << ring); + mtx_unlock(&bank->lock); + WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask); +} + +int +adf_send_message(struct adf_etr_ring_data *ring, u32 *msg) +{ + u32 msg_size = 0; + + if (atomic_add_return(1, ring->inflights) > ring->max_inflights) { + atomic_dec(ring->inflights); + return EAGAIN; + } + + msg_size = ADF_MSG_SIZE_TO_BYTES(ring->msg_size); + mtx_lock(&ring->lock); + memcpy((void *)((uintptr_t)ring->base_addr + ring->tail), + msg, + msg_size); + + ring->tail = adf_modulo(ring->tail + msg_size, + ADF_RING_SIZE_MODULO(ring->ring_size)); + + WRITE_CSR_RING_TAIL(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring->tail); + ring->csr_tail_offset = ring->tail; + mtx_unlock(&ring->lock); + return 0; +} + +int +adf_handle_response(struct adf_etr_ring_data *ring, u32 quota) +{ + u32 msg_counter = 0; + u32 *msg = (u32 *)((uintptr_t)ring->base_addr + ring->head); + + if (!quota) + quota = ADF_NO_RESPONSE_QUOTA; + + while ((*msg != ADF_RING_EMPTY_SIG) && (msg_counter < quota)) { + ring->callback((u32 *)msg); + atomic_dec(ring->inflights); + *msg = ADF_RING_EMPTY_SIG; + ring->head = adf_modulo(ring->head + ADF_MSG_SIZE_TO_BYTES( + ring->msg_size), + ADF_RING_SIZE_MODULO(ring->ring_size)); + msg_counter++; + msg = (u32 *)((uintptr_t)ring->base_addr + ring->head); + } + if (msg_counter > 0) + WRITE_CSR_RING_HEAD(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring->head); + return msg_counter; +} + +int +adf_poll_bank(u32 accel_id, u32 bank_num, u32 quota) +{ + int num_resp; + struct adf_accel_dev *accel_dev; + struct adf_etr_data *trans_data; + struct adf_etr_bank_data *bank; + struct adf_etr_ring_data *ring; + u32 rings_not_empty; + u32 ring_num; + u32 resp_total = 0; + u32 num_rings_per_bank; + + /* Find the accel device associated with the accelId + * passed in. + */ + accel_dev = adf_devmgr_get_dev_by_id(accel_id); + if (!accel_dev) { + pr_err("There is no device with id: %d\n", accel_id); + return EINVAL; + } + + trans_data = accel_dev->transport; + bank = &trans_data->banks[bank_num]; + mtx_lock(&bank->lock); + + /* Read the ring status CSR to determine which rings are empty. */ + rings_not_empty = READ_CSR_E_STAT(bank->csr_addr, bank->bank_number); + /* Complement to find which rings have data to be processed. */ + rings_not_empty = (~rings_not_empty) & bank->ring_mask; + + /* Return RETRY if the bank polling rings + * are all empty. + */ + if (!(rings_not_empty & bank->ring_mask)) { + mtx_unlock(&bank->lock); + return EAGAIN; + } + + /* + * Loop over all rings within this bank. + * The ring structure is global to all + * rings hence while we loop over all rings in the + * bank we use ring_number to get the global ring. + */ + num_rings_per_bank = accel_dev->hw_device->num_rings_per_bank; + for (ring_num = 0; ring_num < num_rings_per_bank; ring_num++) { + ring = &bank->rings[ring_num]; + + /* And with polling ring mask. + * If the there is no data on this ring + * move to the next one. + */ + if (!(rings_not_empty & (1 << ring->ring_number))) + continue; + + /* Poll the ring. */ + num_resp = adf_handle_response(ring, quota); + resp_total += num_resp; + } + + mtx_unlock(&bank->lock); + /* Return SUCCESS if there's any response message + * returned. + */ + if (resp_total) + return 0; + return EAGAIN; +} + +int +adf_poll_all_banks(u32 accel_id, u32 quota) +{ + int status = EAGAIN; + struct adf_accel_dev *accel_dev; + struct adf_etr_data *trans_data; + struct adf_etr_bank_data *bank; + u32 bank_num; + u32 stat_total = 0; + + /* Find the accel device associated with the accelId + * passed in. + */ + accel_dev = adf_devmgr_get_dev_by_id(accel_id); + if (!accel_dev) { + pr_err("There is no device with id: %d\n", accel_id); + return EINVAL; + } + + /* Loop over banks and call adf_poll_bank */ + trans_data = accel_dev->transport; + for (bank_num = 0; bank_num < GET_MAX_BANKS(accel_dev); bank_num++) { + bank = &trans_data->banks[bank_num]; + /* if there are no polling rings on this bank + * continue to the next bank number. + */ + if (bank->ring_mask == 0) + continue; + status = adf_poll_bank(accel_id, bank_num, quota); + /* The successful status should be AGAIN or 0 */ + if (status == 0) + stat_total++; + else if (status != EAGAIN) + return status; + } + + /* Return SUCCESS if adf_poll_bank returned SUCCESS + * at any stage. adf_poll_bank cannot + * return fail in the above case. + */ + if (stat_total) + return 0; + + return EAGAIN; +} + +static void +adf_configure_tx_ring(struct adf_etr_ring_data *ring) +{ + u32 ring_config = BUILD_RING_CONFIG(ring->ring_size); + + WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring_config); +} + +static void +adf_configure_rx_ring(struct adf_etr_ring_data *ring) +{ + u32 ring_config = BUILD_RESP_RING_CONFIG(ring->ring_size, + ADF_RING_NEAR_WATERMARK_512, + ADF_RING_NEAR_WATERMARK_0); + + WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring_config); +} + +static int +adf_init_ring(struct adf_etr_ring_data *ring) +{ + struct adf_etr_bank_data *bank = ring->bank; + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u64 ring_base; + u32 ring_size_bytes = ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size); + + ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes); + int ret; + + ret = bus_dma_mem_create(&ring->dma_mem, + accel_dev->dma_tag, + ring_size_bytes, + BUS_SPACE_MAXADDR, + ring_size_bytes, + M_WAITOK | M_ZERO); + if (ret) + return ret; + ring->base_addr = ring->dma_mem.dma_vaddr; + ring->dma_addr = ring->dma_mem.dma_baddr; + + memset(ring->base_addr, 0x7F, ring_size_bytes); + /* The base_addr has to be aligned to the size of the buffer */ + if (adf_check_ring_alignment(ring->dma_addr, ring_size_bytes)) { + device_printf(GET_DEV(accel_dev), "Ring address not aligned\n"); + bus_dma_mem_free(&ring->dma_mem); + ring->base_addr = NULL; + return EFAULT; + } + + if (hw_data->tx_rings_mask & (1 << ring->ring_number)) + adf_configure_tx_ring(ring); + else + adf_configure_rx_ring(ring); + + ring_base = BUILD_RING_BASE_ADDR(ring->dma_addr, ring->ring_size); + WRITE_CSR_RING_BASE(ring->bank->csr_addr, + ring->bank->bank_number, + ring->ring_number, + ring_base); + mtx_init(&ring->lock, "adf bank", NULL, MTX_DEF); + return 0; +} + +static void +adf_cleanup_ring(struct adf_etr_ring_data *ring) +{ + u32 ring_size_bytes = ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size); + ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes); + + if (ring->base_addr) { + explicit_bzero(ring->base_addr, ring_size_bytes); + bus_dma_mem_free(&ring->dma_mem); + } + mtx_destroy(&ring->lock); +} + +int +adf_create_ring(struct adf_accel_dev *accel_dev, + const char *section, + u32 bank_num, + u32 num_msgs, + u32 msg_size, + const char *ring_name, + adf_callback_fn callback, + int poll_mode, + struct adf_etr_ring_data **ring_ptr) +{ + struct adf_etr_data *transport_data = accel_dev->transport; + struct adf_etr_bank_data *bank; + struct adf_etr_ring_data *ring; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u32 ring_num; + int ret; + u8 num_rings_per_bank = accel_dev->hw_device->num_rings_per_bank; + + if (bank_num >= GET_MAX_BANKS(accel_dev)) { + device_printf(GET_DEV(accel_dev), "Invalid bank number\n"); + return EFAULT; + } + if (msg_size > ADF_MSG_SIZE_TO_BYTES(ADF_MAX_MSG_SIZE)) { + device_printf(GET_DEV(accel_dev), "Invalid msg size\n"); + return EFAULT; + } + if (ADF_MAX_INFLIGHTS(adf_verify_ring_size(msg_size, num_msgs), + ADF_BYTES_TO_MSG_SIZE(msg_size)) < 2) { + device_printf(GET_DEV(accel_dev), + "Invalid ring size for given msg size\n"); + return EFAULT; + } + if (adf_cfg_get_param_value(accel_dev, section, ring_name, val)) { + device_printf(GET_DEV(accel_dev), + "Section %s, no such entry : %s\n", + section, + ring_name); + return EFAULT; + } + if (compat_strtouint(val, 10, &ring_num)) { + device_printf(GET_DEV(accel_dev), "Can't get ring number\n"); + return EFAULT; + } + if (ring_num >= num_rings_per_bank) { + device_printf(GET_DEV(accel_dev), "Invalid ring number\n"); + return EFAULT; + } + + bank = &transport_data->banks[bank_num]; + if (adf_reserve_ring(bank, ring_num)) { + device_printf(GET_DEV(accel_dev), + "Ring %d, %s already exists.\n", + ring_num, + ring_name); + return EFAULT; + } + ring = &bank->rings[ring_num]; + ring->ring_number = ring_num; + ring->bank = bank; + ring->callback = callback; + ring->msg_size = ADF_BYTES_TO_MSG_SIZE(msg_size); + ring->ring_size = adf_verify_ring_size(msg_size, num_msgs); + ring->max_inflights = + ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size); + ring->head = 0; + ring->tail = 0; + ring->csr_tail_offset = 0; + ret = adf_init_ring(ring); + if (ret) + goto err; + + /* Enable HW arbitration for the given ring */ + adf_update_ring_arb(ring); + + if (adf_ring_debugfs_add(ring, ring_name)) { + device_printf(GET_DEV(accel_dev), + "Couldn't add ring debugfs entry\n"); + ret = EFAULT; + goto err; + } + + /* Enable interrupts if needed */ + if (callback && !poll_mode) + adf_enable_ring_irq(bank, ring->ring_number); + *ring_ptr = ring; + return 0; +err: + adf_cleanup_ring(ring); + adf_unreserve_ring(bank, ring_num); + adf_update_ring_arb(ring); + return ret; +} + +void +adf_remove_ring(struct adf_etr_ring_data *ring) +{ + struct adf_etr_bank_data *bank = ring->bank; + + /* Disable interrupts for the given ring */ + adf_disable_ring_irq(bank, ring->ring_number); + + /* Clear PCI config space */ + WRITE_CSR_RING_CONFIG(bank->csr_addr, + bank->bank_number, + ring->ring_number, + 0); + WRITE_CSR_RING_BASE(bank->csr_addr, + bank->bank_number, + ring->ring_number, + 0); + adf_ring_debugfs_rm(ring); + adf_unreserve_ring(bank, ring->ring_number); + /* Disable HW arbitration for the given ring */ + adf_update_ring_arb(ring); + adf_cleanup_ring(ring); +} + +static void +adf_ring_response_handler(struct adf_etr_bank_data *bank) +{ + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u8 num_rings_per_bank = hw_data->num_rings_per_bank; + u32 empty_rings, i; + + empty_rings = READ_CSR_E_STAT(bank->csr_addr, bank->bank_number); + empty_rings = ~empty_rings & bank->irq_mask; + + for (i = 0; i < num_rings_per_bank; ++i) { + if (empty_rings & (1 << i)) + adf_handle_response(&bank->rings[i], 0); + } +} + +void +adf_response_handler(uintptr_t bank_addr) +{ + struct adf_etr_bank_data *bank = (void *)bank_addr; + + /* Handle all the responses and re-enable IRQs */ + adf_ring_response_handler(bank); + WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, + bank->bank_number, + bank->irq_mask); +} + +static inline int +adf_get_cfg_int(struct adf_accel_dev *accel_dev, + const char *section, + const char *format, + u32 key, + u32 *value) +{ + char key_buf[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val_buf[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + snprintf(key_buf, ADF_CFG_MAX_KEY_LEN_IN_BYTES, format, key); + + if (adf_cfg_get_param_value(accel_dev, section, key_buf, val_buf)) + return EFAULT; + + if (compat_strtouint(val_buf, 10, value)) + return EFAULT; + return 0; +} + +static void +adf_get_coalesc_timer(struct adf_etr_bank_data *bank, + const char *section, + u32 bank_num_in_accel) +{ + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 coalesc_timer = ADF_COALESCING_DEF_TIME; + + adf_get_cfg_int(accel_dev, + section, + ADF_ETRMGR_COALESCE_TIMER_FORMAT, + bank_num_in_accel, + &coalesc_timer); + + if (hw_data->get_clock_speed) + bank->irq_coalesc_timer = + (coalesc_timer * + (hw_data->get_clock_speed(hw_data) / USEC_PER_SEC)) / + NSEC_PER_USEC; + else + bank->irq_coalesc_timer = coalesc_timer; + + if (bank->irq_coalesc_timer > ADF_COALESCING_MAX_TIME) + bank->irq_coalesc_timer = ADF_COALESCING_MAX_TIME; + else if (bank->irq_coalesc_timer < ADF_COALESCING_MIN_TIME) + bank->irq_coalesc_timer = ADF_COALESCING_MIN_TIME; +} + +static int +adf_init_bank(struct adf_accel_dev *accel_dev, + struct adf_etr_bank_data *bank, + u32 bank_num, + struct resource *csr_addr) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_etr_ring_data *ring; + struct adf_etr_ring_data *tx_ring; + u32 i, coalesc_enabled = 0; + u8 num_rings_per_bank = hw_data->num_rings_per_bank; + u32 size = 0; + + explicit_bzero(bank, sizeof(*bank)); + bank->bank_number = bank_num; + bank->csr_addr = csr_addr; + bank->accel_dev = accel_dev; + mtx_init(&bank->lock, "adf bank", NULL, MTX_DEF); + + /* Allocate the rings in the bank */ + size = num_rings_per_bank * sizeof(struct adf_etr_ring_data); + bank->rings = kzalloc_node(size, + M_WAITOK | M_ZERO, + dev_to_node(GET_DEV(accel_dev))); + + /* Enable IRQ coalescing always. This will allow to use + * the optimised flag and coalesc register. + * If it is disabled in the config file just use min time value */ + if ((adf_get_cfg_int(accel_dev, + "Accelerator0", + ADF_ETRMGR_COALESCING_ENABLED_FORMAT, + bank_num, + &coalesc_enabled) == 0) && + coalesc_enabled) + adf_get_coalesc_timer(bank, "Accelerator0", bank_num); + else + bank->irq_coalesc_timer = ADF_COALESCING_MIN_TIME; + + for (i = 0; i < num_rings_per_bank; i++) { + WRITE_CSR_RING_CONFIG(csr_addr, bank_num, i, 0); + WRITE_CSR_RING_BASE(csr_addr, bank_num, i, 0); + ring = &bank->rings[i]; + if (hw_data->tx_rings_mask & (1 << i)) { + ring->inflights = + kzalloc_node(sizeof(atomic_t), + M_WAITOK | M_ZERO, + dev_to_node(GET_DEV(accel_dev))); + } else { + if (i < hw_data->tx_rx_gap) { + device_printf(GET_DEV(accel_dev), + "Invalid tx rings mask config\n"); + goto err; + } + tx_ring = &bank->rings[i - hw_data->tx_rx_gap]; + ring->inflights = tx_ring->inflights; + } + } + + if (adf_bank_debugfs_add(bank)) { + device_printf(GET_DEV(accel_dev), + "Failed to add bank debugfs entry\n"); + goto err; + } + + WRITE_CSR_INT_FLAG(csr_addr, bank_num, ADF_BANK_INT_FLAG_CLEAR_MASK); + WRITE_CSR_INT_SRCSEL(csr_addr, bank_num); + return 0; +err: + for (i = 0; i < num_rings_per_bank; i++) { + ring = &bank->rings[i]; + if (hw_data->tx_rings_mask & (1 << i)) { + kfree(ring->inflights); + ring->inflights = NULL; + } + } + kfree(bank->rings); + return ENOMEM; +} + +/** + * adf_init_etr_data() - Initialize transport rings for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function initializes the communications channels (rings) to the + * acceleration device accel_dev. + * To be used by QAT device specific drivers. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_init_etr_data(struct adf_accel_dev *accel_dev) +{ + struct adf_etr_data *etr_data; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *csr_addr; + u32 size; + u32 num_banks = 0; + int i, ret; + + etr_data = kzalloc_node(sizeof(*etr_data), + M_WAITOK | M_ZERO, + dev_to_node(GET_DEV(accel_dev))); + + num_banks = GET_MAX_BANKS(accel_dev); + size = num_banks * sizeof(struct adf_etr_bank_data); + etr_data->banks = kzalloc_node(size, + M_WAITOK | M_ZERO, + dev_to_node(GET_DEV(accel_dev))); + + accel_dev->transport = etr_data; + i = hw_data->get_etr_bar_id(hw_data); + csr_addr = accel_dev->accel_pci_dev.pci_bars[i].virt_addr; + + etr_data->debug = + SYSCTL_ADD_NODE(&accel_dev->sysctl_ctx, + SYSCTL_CHILDREN( + device_get_sysctl_tree(GET_DEV(accel_dev))), + OID_AUTO, + "transport", + CTLFLAG_RD, + NULL, + "Transport parameters"); + if (!etr_data->debug) { + device_printf(GET_DEV(accel_dev), + "Unable to create transport debugfs entry\n"); + ret = ENOENT; + goto err_bank_all; + } + + for (i = 0; i < num_banks; i++) { + ret = + adf_init_bank(accel_dev, &etr_data->banks[i], i, csr_addr); + if (ret) + goto err_bank_all; + } + + return 0; + +err_bank_all: + kfree(etr_data->banks); + kfree(etr_data); + accel_dev->transport = NULL; + return ret; +} + +static void +cleanup_bank(struct adf_etr_bank_data *bank) +{ + u32 i; + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u8 num_rings_per_bank = hw_data->num_rings_per_bank; + + for (i = 0; i < num_rings_per_bank; i++) { + struct adf_accel_dev *accel_dev = bank->accel_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_etr_ring_data *ring = &bank->rings[i]; + + if (bank->ring_mask & (1 << i)) + adf_cleanup_ring(ring); + + if (hw_data->tx_rings_mask & (1 << i)) { + kfree(ring->inflights); + ring->inflights = NULL; + } + } + kfree(bank->rings); + adf_bank_debugfs_rm(bank); + mtx_destroy(&bank->lock); + explicit_bzero(bank, sizeof(*bank)); +} + +static void +adf_cleanup_etr_handles(struct adf_accel_dev *accel_dev) +{ + struct adf_etr_data *etr_data = accel_dev->transport; + u32 i, num_banks = GET_MAX_BANKS(accel_dev); + + for (i = 0; i < num_banks; i++) + cleanup_bank(&etr_data->banks[i]); +} + +/** + * adf_cleanup_etr_data() - Clear transport rings for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function is the clears the communications channels (rings) of the + * acceleration device accel_dev. + * To be used by QAT device specific drivers. + * + * Return: void + */ +void +adf_cleanup_etr_data(struct adf_accel_dev *accel_dev) +{ + struct adf_etr_data *etr_data = accel_dev->transport; + + if (etr_data) { + adf_cleanup_etr_handles(accel_dev); + kfree(etr_data->banks); + kfree(etr_data); + accel_dev->transport = NULL; + } +} diff --git a/sys/dev/qat/qat_common/adf_vf2pf_msg.c b/sys/dev/qat/qat_common/adf_vf2pf_msg.c new file mode 100644 index 00000000000..bd041c7946a --- /dev/null +++ b/sys/dev/qat/qat_common/adf_vf2pf_msg.c @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_pf2vf_msg.h" + +/** + * adf_vf2pf_init() - send init msg to PF + * @accel_dev: Pointer to acceleration VF device. + * + * Function sends an init messge from the VF to a PF + * + * Return: 0 on success, error code otherwise. + */ +int +adf_vf2pf_init(struct adf_accel_dev *accel_dev) +{ + u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | + (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT)); + if (adf_iov_notify(accel_dev, msg, 0)) { + device_printf(GET_DEV(accel_dev), + "Failed to send Init event to PF\n"); + return -EFAULT; + } + set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + return 0; +} + +/** + * adf_vf2pf_shutdown() - send shutdown msg to PF + * @accel_dev: Pointer to acceleration VF device. + * + * Function sends a shutdown messge from the VF to a PF + * + * Return: void + */ +void +adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev) +{ + u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM | + (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT)); + mutex_init(&accel_dev->u1.vf.vf2pf_lock); + if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status)) + if (adf_iov_notify(accel_dev, msg, 0)) + device_printf(GET_DEV(accel_dev), + "Failed to send Shutdown event to PF\n"); + mutex_destroy(&accel_dev->u1.vf.vf2pf_lock); +} + +static int +adf_iov_block_get_bc(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 msg_index, + u8 *data, + int get_crc) +{ + u8 blk_type; + u32 msg; + unsigned long timeout = msecs_to_jiffies(ADF_IOV_MSG_RESP_TIMEOUT); + int response_received = 0; + int retry_count = 0; + + msg = ADF_VF2PF_MSGORIGIN_SYSTEM; + if (get_crc) + msg |= 1 << ADF_VF2PF_BLOCK_REQ_CRC_SHIFT; + + if (msg_type <= ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE) { + if (msg_index >= + ADF_VF2PF_SMALL_PAYLOAD_SIZE + ADF_VF2PF_BLOCK_DATA) { + device_printf( + GET_DEV(accel_dev), + "Invalid byte index %d for message type %d\n", + msg_index, + msg_type); + return -EINVAL; + } + msg |= ADF_VF2PF_MSGTYPE_GET_SMALL_BLOCK_REQ + << ADF_VF2PF_MSGTYPE_SHIFT; + blk_type = msg_type; + msg |= blk_type << ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT; + msg |= msg_index << ADF_VF2PF_SMALL_BLOCK_BYTE_NUM_SHIFT; + } else if (msg_type <= ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE) { + if (msg_index >= + ADF_VF2PF_MEDIUM_PAYLOAD_SIZE + ADF_VF2PF_BLOCK_DATA) { + device_printf( + GET_DEV(accel_dev), + "Invalid byte index %d for message type %d\n", + msg_index, + msg_type); + return -EINVAL; + } + msg |= ADF_VF2PF_MSGTYPE_GET_MEDIUM_BLOCK_REQ + << ADF_VF2PF_MSGTYPE_SHIFT; + blk_type = msg_type - ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE; + msg |= blk_type << ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT; + msg |= msg_index << ADF_VF2PF_MEDIUM_BLOCK_BYTE_NUM_SHIFT; + } else if (msg_type <= ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE) { + if (msg_index >= + ADF_VF2PF_LARGE_PAYLOAD_SIZE + ADF_VF2PF_BLOCK_DATA) { + device_printf( + GET_DEV(accel_dev), + "Invalid byte index %d for message type %d\n", + msg_index, + msg_type); + return -EINVAL; + } + msg |= ADF_VF2PF_MSGTYPE_GET_LARGE_BLOCK_REQ + << ADF_VF2PF_MSGTYPE_SHIFT; + blk_type = msg_type - ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE; + msg |= blk_type << ADF_VF2PF_BLOCK_REQ_TYPE_SHIFT; + msg |= msg_index << ADF_VF2PF_LARGE_BLOCK_BYTE_NUM_SHIFT; + } else { + device_printf(GET_DEV(accel_dev), + "Invalid message type %d\n", + msg_type); + } + accel_dev->u1.vf.iov_msg_completion = 0; + do { + /* Send request from VF to PF */ + if (retry_count) + accel_dev->u1.vf.pfvf_counters.retry++; + if (adf_iov_putmsg(accel_dev, msg, 0)) { + device_printf(GET_DEV(accel_dev), + "Failed to send block request to PF\n"); + return EIO; + } + + /* Wait for response */ + mutex_lock(&accel_dev->u1.vf.vf2pf_lock); + if (accel_dev->u1.vf.iov_msg_completion == 0 && + sx_sleep(&accel_dev->u1.vf.iov_msg_completion, + &accel_dev->u1.vf.vf2pf_lock.sx, + 0, + "pfver", + timeout) == EWOULDBLOCK) { + /* It's possible that wakeup could be missed */ + if (accel_dev->u1.vf.iov_msg_completion) { + response_received = 1; + } else { + device_printf( + GET_DEV(accel_dev), + "IOV request/response message timeout expired\n"); + } + } else { + response_received = 1; + } + mutex_unlock(&accel_dev->u1.vf.vf2pf_lock); + } while (!response_received && + ++retry_count < ADF_IOV_MSG_RESP_RETRIES); + + if (!response_received) + accel_dev->u1.vf.pfvf_counters.rx_timeout++; + else + accel_dev->u1.vf.pfvf_counters.rx_rsp++; + + if (!response_received) + return EIO; + + if (accel_dev->u1.vf.pf2vf_block_resp_type != + (get_crc ? ADF_PF2VF_BLOCK_RESP_TYPE_CRC : + ADF_PF2VF_BLOCK_RESP_TYPE_DATA)) { + device_printf( + GET_DEV(accel_dev), + "%sBlock response type %d, data %d, msg %d, index %d\n", + get_crc ? "CRC " : "", + accel_dev->u1.vf.pf2vf_block_resp_type, + accel_dev->u1.vf.pf2vf_block_byte, + msg_type, + msg_index); + return -EIO; + } + *data = accel_dev->u1.vf.pf2vf_block_byte; + return 0; +} + +static int +adf_iov_block_get_byte(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 msg_index, + u8 *data) +{ + return adf_iov_block_get_bc(accel_dev, msg_type, msg_index, data, 0); +} + +static int +adf_iov_block_get_crc(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 msg_index, + u8 *crc) +{ + return adf_iov_block_get_bc(accel_dev, msg_type, msg_index - 1, crc, 1); +} + +int +adf_iov_block_get(struct adf_accel_dev *accel_dev, + u8 msg_type, + u8 *block_version, + u8 *buffer, + u8 *length) +{ + u8 buf_size = *length; + u8 payload_len; + u8 remote_crc; + u8 local_crc; + u8 buf_index; + int ret; + + if (msg_type > ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE) { + device_printf(GET_DEV(accel_dev), + "Invalid message type %d\n", + msg_type); + return -EINVAL; + } + + ret = adf_iov_block_get_byte(accel_dev, + msg_type, + ADF_VF2PF_BLOCK_VERSION_BYTE, + block_version); + if (ret) + return ret; + ret = adf_iov_block_get_byte(accel_dev, + msg_type, + ADF_VF2PF_BLOCK_LEN_BYTE, + length); + + if (ret) + return ret; + + payload_len = *length; + + if (buf_size < payload_len) { + device_printf( + GET_DEV(accel_dev), + "Truncating block type %d response from %d to %d bytes\n", + msg_type, + payload_len, + buf_size); + payload_len = buf_size; + } + + /* Get the data */ + for (buf_index = 0; buf_index < payload_len; buf_index++) { + ret = adf_iov_block_get_byte(accel_dev, + msg_type, + buf_index + ADF_VF2PF_BLOCK_DATA, + buffer + buf_index); + if (ret) + return ret; + } + + ret = adf_iov_block_get_crc(accel_dev, + msg_type, + payload_len + ADF_VF2PF_BLOCK_DATA, + &remote_crc); + if (ret) + return ret; + local_crc = adf_pfvf_crc(ADF_CRC8_INIT_VALUE, block_version, 1); + local_crc = adf_pfvf_crc(local_crc, length, 1); + local_crc = adf_pfvf_crc(local_crc, buffer, payload_len); + if (local_crc != remote_crc) { + device_printf( + GET_DEV(accel_dev), + "CRC error on msg type %d. Local %02X, remote %02X\n", + msg_type, + local_crc, + remote_crc); + accel_dev->u1.vf.pfvf_counters.crc_err++; + return EIO; + } + + accel_dev->u1.vf.pfvf_counters.blk_rx++; + *length = payload_len; + return 0; +} diff --git a/sys/dev/qat/qat_common/adf_vf_isr.c b/sys/dev/qat/qat_common/adf_vf_isr.c new file mode 100644 index 00000000000..2e92133a0b5 --- /dev/null +++ b/sys/dev/qat/qat_common/adf_vf_isr.c @@ -0,0 +1,393 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include +#include +#include +#include +#include +#include +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_cfg.h" +#include "adf_cfg_strings.h" +#include "adf_cfg_common.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include "adf_pf2vf_msg.h" + +#define ADF_VINTSOU_BUN BIT(0) +#define ADF_VINTSOU_PF2VF BIT(1) + +static TASKQUEUE_DEFINE_THREAD(qat_vf); + +static struct workqueue_struct *adf_vf_stop_wq; +static DEFINE_MUTEX(vf_stop_wq_lock); + +struct adf_vf_stop_data { + struct adf_accel_dev *accel_dev; + struct work_struct vf_stop_work; +}; + +static int +adf_enable_msi(struct adf_accel_dev *accel_dev) +{ + int stat; + int count = 1; + stat = pci_alloc_msi(accel_to_pci_dev(accel_dev), &count); + if (stat) { + device_printf(GET_DEV(accel_dev), + "Failed to enable MSI interrupts\n"); + return stat; + } + + return stat; +} + +static void +adf_disable_msi(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_to_pci_dev(accel_dev); + pci_release_msi(pdev); +} + +static void +adf_dev_stop_async(struct work_struct *work) +{ + struct adf_vf_stop_data *stop_data = + container_of(work, struct adf_vf_stop_data, vf_stop_work); + struct adf_accel_dev *accel_dev = stop_data->accel_dev; + + adf_dev_restarting_notify(accel_dev); + adf_dev_stop(accel_dev); + adf_dev_shutdown(accel_dev); + + /* Re-enable PF2VF interrupts */ + adf_enable_pf2vf_interrupts(accel_dev); + kfree(stop_data); +} + +static void +adf_pf2vf_bh_handler(void *data, int pending) +{ + struct adf_accel_dev *accel_dev = data; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *pmisc = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *pmisc_bar_addr = pmisc->virt_addr; + u32 msg; + bool is_notification = false; + + /* Read the message from PF */ + msg = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_pf2vf_offset(0)); + if (!(msg & ADF_PF2VF_INT)) { + device_printf(GET_DEV(accel_dev), + "Spurious PF2VF interrupt. msg %X. Ignored\n", + msg); + accel_dev->u1.vf.pfvf_counters.spurious++; + goto out; + } + accel_dev->u1.vf.pfvf_counters.rx++; + + if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM)) { + device_printf(GET_DEV(accel_dev), + "Ignore non-system PF2VF message(0x%x)\n", + msg); + /* + * To ack, clear the VF2PFINT bit. + * Because this must be a legacy message, the far side + * must clear the in-use pattern. + */ + msg &= ~ADF_PF2VF_INT; + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg); + goto out; + } + + switch ((msg & ADF_PF2VF_MSGTYPE_MASK) >> ADF_PF2VF_MSGTYPE_SHIFT) { + case ADF_PF2VF_MSGTYPE_RESTARTING: { + struct adf_vf_stop_data *stop_data; + + is_notification = true; + + device_printf(GET_DEV(accel_dev), + "Restarting msg received from PF 0x%x\n", + msg); + + clear_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status); + stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC); + if (!stop_data) { + device_printf(GET_DEV(accel_dev), + "Couldn't schedule stop for vf_%d\n", + accel_dev->accel_id); + goto out; + } + stop_data->accel_dev = accel_dev; + INIT_WORK(&stop_data->vf_stop_work, adf_dev_stop_async); + queue_work(adf_vf_stop_wq, &stop_data->vf_stop_work); + break; + } + case ADF_PF2VF_MSGTYPE_VERSION_RESP: + device_printf(GET_DEV(accel_dev), + "Version resp received from PF 0x%x\n", + msg); + is_notification = false; + accel_dev->u1.vf.pf_version = + (msg & ADF_PF2VF_VERSION_RESP_VERS_MASK) >> + ADF_PF2VF_VERSION_RESP_VERS_SHIFT; + accel_dev->u1.vf.compatible = + (msg & ADF_PF2VF_VERSION_RESP_RESULT_MASK) >> + ADF_PF2VF_VERSION_RESP_RESULT_SHIFT; + accel_dev->u1.vf.iov_msg_completion = 1; + wakeup(&accel_dev->u1.vf.iov_msg_completion); + break; + case ADF_PF2VF_MSGTYPE_BLOCK_RESP: + is_notification = false; + accel_dev->u1.vf.pf2vf_block_byte = + (msg & ADF_PF2VF_BLOCK_RESP_DATA_MASK) >> + ADF_PF2VF_BLOCK_RESP_DATA_SHIFT; + accel_dev->u1.vf.pf2vf_block_resp_type = + (msg & ADF_PF2VF_BLOCK_RESP_TYPE_MASK) >> + ADF_PF2VF_BLOCK_RESP_TYPE_SHIFT; + accel_dev->u1.vf.iov_msg_completion = 1; + wakeup(&accel_dev->u1.vf.iov_msg_completion); + break; + case ADF_PF2VF_MSGTYPE_FATAL_ERROR: + device_printf(GET_DEV(accel_dev), + "Fatal error received from PF 0x%x\n", + msg); + is_notification = true; + if (adf_notify_fatal_error(accel_dev)) + device_printf(GET_DEV(accel_dev), + "Couldn't notify fatal error\n"); + break; + default: + device_printf(GET_DEV(accel_dev), + "Unknown PF2VF message(0x%x)\n", + msg); + } + + /* To ack, clear the PF2VFINT bit */ + msg &= ~ADF_PF2VF_INT; + /* + * Clear the in-use pattern if the sender won't do it. + * Because the compatibility version must be the first message + * exchanged between the VF and PF, the pf.version must be + * set at this time. + * The in-use pattern is not cleared for notifications so that + * it can be used for collision detection. + */ + if (accel_dev->u1.vf.pf_version >= ADF_PFVF_COMPATIBILITY_FAST_ACK && + !is_notification) + msg &= ~ADF_PF2VF_IN_USE_BY_PF_MASK; + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg); + +out: + /* Re-enable PF2VF interrupts */ + adf_enable_pf2vf_interrupts(accel_dev); + return; +} + +static int +adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev) +{ + TASK_INIT(&accel_dev->u1.vf.pf2vf_bh_tasklet, + 0, + adf_pf2vf_bh_handler, + accel_dev); + mutex_init(&accel_dev->u1.vf.vf2pf_lock); + + return 0; +} + +static void +adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev) +{ + taskqueue_cancel(taskqueue_qat_vf, + &accel_dev->u1.vf.pf2vf_bh_tasklet, + NULL); + taskqueue_drain(taskqueue_qat_vf, &accel_dev->u1.vf.pf2vf_bh_tasklet); + mutex_destroy(&accel_dev->u1.vf.vf2pf_lock); +} + +static void +adf_isr(void *privdata) +{ + struct adf_accel_dev *accel_dev = privdata; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *pmisc = + &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; + struct resource *pmisc_bar_addr = pmisc->virt_addr; + u32 v_int, v_mask; + int handled = 0; + + /* Read VF INT source CSR to determine the source of VF interrupt */ + v_int = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_vintsou_offset()); + v_mask = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_vintmsk_offset(0)); + + /* Check for PF2VF interrupt */ + if ((v_int & ~v_mask) & ADF_VINTSOU_PF2VF) { + /* Disable PF to VF interrupt */ + adf_disable_pf2vf_interrupts(accel_dev); + + /* Schedule tasklet to handle interrupt BH */ + taskqueue_enqueue(taskqueue_qat_vf, + &accel_dev->u1.vf.pf2vf_bh_tasklet); + handled = 1; + } + + if ((v_int & ~v_mask) & ADF_VINTSOU_BUN) { + struct adf_etr_data *etr_data = accel_dev->transport; + struct adf_etr_bank_data *bank = &etr_data->banks[0]; + + /* Disable Flag and Coalesce Ring Interrupts */ + WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, + bank->bank_number, + 0); + adf_response_handler((uintptr_t)&etr_data->banks[0]); + handled = 1; + } + + if (handled) + return; +} + +static int +adf_request_msi_irq(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_to_pci_dev(accel_dev); + int ret; + int rid = 1; + accel_dev->u1.vf.irq = + bus_alloc_resource_any(pdev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (accel_dev->u1.vf.irq == NULL) { + device_printf(GET_DEV(accel_dev), "failed to allocate IRQ\n"); + return ENXIO; + } + ret = bus_setup_intr(pdev, + accel_dev->u1.vf.irq, + INTR_TYPE_MISC | INTR_MPSAFE, + NULL, + adf_isr, + accel_dev, + &accel_dev->u1.vf.cookie); + if (ret) { + device_printf(GET_DEV(accel_dev), + "failed to enable irq for %s\n", + accel_dev->u1.vf.irq_name); + return ret; + } + return ret; +} + +static int +adf_setup_bh(struct adf_accel_dev *accel_dev) +{ + return 0; +} + +static void +adf_cleanup_bh(struct adf_accel_dev *accel_dev) +{ +} + +/** + * adf_vf_isr_resource_free() - Free IRQ for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function frees interrupts for acceleration device virtual function. + */ +void +adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_to_pci_dev(accel_dev); + bus_teardown_intr(pdev, accel_dev->u1.vf.irq, accel_dev->u1.vf.cookie); + bus_free_resource(pdev, SYS_RES_IRQ, accel_dev->u1.vf.irq); + adf_cleanup_bh(accel_dev); + adf_cleanup_pf2vf_bh(accel_dev); + adf_disable_msi(accel_dev); +} + +/** + * adf_vf_isr_resource_alloc() - Allocate IRQ for acceleration device + * @accel_dev: Pointer to acceleration device. + * + * Function allocates interrupts for acceleration device virtual function. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev) +{ + if (adf_enable_msi(accel_dev)) + goto err_out; + + if (adf_setup_pf2vf_bh(accel_dev)) + goto err_out; + + if (adf_setup_bh(accel_dev)) + goto err_out; + + if (adf_request_msi_irq(accel_dev)) + goto err_out; + + return 0; +err_out: + adf_vf_isr_resource_free(accel_dev); + return EFAULT; +} + +/** + * adf_flush_vf_wq() - Flush workqueue for VF + * + * Function flushes workqueue 'adf_vf_stop_wq' for VF. + * + * Return: void. + */ +void +adf_flush_vf_wq(void) +{ + if (adf_vf_stop_wq) + flush_workqueue(adf_vf_stop_wq); +} + +/** + * adf_init_vf_wq() - Init workqueue for VF + * + * Function init workqueue 'adf_vf_stop_wq' for VF. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_init_vf_wq(void) +{ + int ret = 0; + + mutex_lock(&vf_stop_wq_lock); + if (!adf_vf_stop_wq) + adf_vf_stop_wq = + alloc_workqueue("adf_vf_stop_wq", WQ_MEM_RECLAIM, 0); + + if (!adf_vf_stop_wq) + ret = ENOMEM; + + mutex_unlock(&vf_stop_wq_lock); + return ret; +} + +/** + * adf_exit_vf_wq() - Destroy workqueue for VF + * + * Function destroy workqueue 'adf_vf_stop_wq' for VF. + * + * Return: void. + */ +void +adf_exit_vf_wq(void) +{ + if (adf_vf_stop_wq) { + destroy_workqueue(adf_vf_stop_wq); + adf_vf_stop_wq = NULL; + } +} diff --git a/sys/dev/qat/qat_common/qat_common_module.c b/sys/dev/qat/qat_common/qat_common_module.c new file mode 100644 index 00000000000..fca9997f750 --- /dev/null +++ b/sys/dev/qat/qat_common/qat_common_module.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_common_drv.h" + +static int __init +qat_common_register(void) +{ + if (adf_init_aer()) + return EFAULT; + + if (adf_init_fatal_error_wq()) + return EFAULT; + + return 0; +} + +static void __exit +qat_common_unregister(void) +{ + adf_exit_vf_wq(); + adf_exit_aer(); + adf_exit_fatal_error_wq(); + adf_clean_vf_map(false); +} + +static int +qat_common_modevent(module_t mod, int type, void *data) +{ + switch (type) { + case MOD_LOAD: + return qat_common_register(); + case MOD_UNLOAD: + qat_common_unregister(); + return 0; + default: + return EOPNOTSUPP; + } +} + +static moduledata_t qat_common_mod = { "qat_common", qat_common_modevent, 0 }; + +DECLARE_MODULE(qat_common, qat_common_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); +MODULE_VERSION(qat_common, 1); +MODULE_DEPEND(qat_common, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_common/qat_freebsd.c b/sys/dev/qat/qat_common/qat_freebsd.c new file mode 100644 index 00000000000..b5deb7cc22d --- /dev/null +++ b/sys/dev/qat/qat_common/qat_freebsd.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include +#include +#include +#include + +MALLOC_DEFINE(M_QAT, "qat", "qat"); + +struct bus_dma_mem_cb_data { + struct bus_dmamem *mem; + int error; +}; + +static void +bus_dma_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + struct bus_dma_mem_cb_data *d; + + d = arg; + d->error = error; + if (error) + return; + d->mem->dma_baddr = segs[0].ds_addr; +} + +int +bus_dma_mem_create(struct bus_dmamem *mem, + bus_dma_tag_t parent, + bus_size_t alignment, + bus_addr_t lowaddr, + bus_size_t len, + int flags) +{ + struct bus_dma_mem_cb_data d; + int error; + + bzero(mem, sizeof(*mem)); + error = bus_dma_tag_create(parent, + alignment, + 0, + lowaddr, + BUS_SPACE_MAXADDR, + NULL, + NULL, + len, + 1, + len, + 0, + NULL, + NULL, + &mem->dma_tag); + if (error) { + bus_dma_mem_free(mem); + return (error); + } + error = bus_dmamem_alloc(mem->dma_tag, + &mem->dma_vaddr, + flags, + &mem->dma_map); + if (error) { + bus_dma_mem_free(mem); + return (error); + } + d.mem = mem; + error = bus_dmamap_load(mem->dma_tag, + mem->dma_map, + mem->dma_vaddr, + len, + bus_dma_mem_cb, + &d, + BUS_DMA_NOWAIT); + if (error == 0) + error = d.error; + if (error) { + bus_dma_mem_free(mem); + return (error); + } + return (0); +} + +void +bus_dma_mem_free(struct bus_dmamem *mem) +{ + + if (mem->dma_baddr != 0) + bus_dmamap_unload(mem->dma_tag, mem->dma_map); + if (mem->dma_vaddr != NULL) + bus_dmamem_free(mem->dma_tag, mem->dma_vaddr, mem->dma_map); + if (mem->dma_tag != NULL) + bus_dma_tag_destroy(mem->dma_tag); + bzero(mem, sizeof(*mem)); +} + +device_t +pci_find_pf(device_t vf) +{ + return (NULL); +} + +int +pci_set_max_payload(device_t dev, int payload_size) +{ + const int packet_sizes[6] = { 128, 256, 512, 1024, 2048, 4096 }; + int cap_reg = 0, reg_value = 0, mask = 0; + + for (mask = 0; mask < 6; mask++) { + if (payload_size == packet_sizes[mask]) + break; + } + if (mask == 6) + return -1; + + if (pci_find_cap(dev, PCIY_EXPRESS, &cap_reg) != 0) + return -1; + + cap_reg += PCIER_DEVICE_CTL; /* Offset for Device Control Register. */ + reg_value = pci_read_config(dev, cap_reg, 1); + reg_value = (reg_value & 0x1f) | (mask << 5); + pci_write_config(dev, cap_reg, reg_value, 1); + return 0; +} diff --git a/sys/dev/qat/qat_common/qat_hal.c b/sys/dev/qat/qat_common/qat_hal.c new file mode 100644 index 00000000000..0d711f5997f --- /dev/null +++ b/sys/dev/qat/qat_common/qat_hal.c @@ -0,0 +1,1848 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "icp_qat_hal.h" +#include "icp_qat_uclo.h" + +#define BAD_REGADDR 0xffff +#define MAX_RETRY_TIMES 1000000 +#define INIT_CTX_ARB_VALUE 0x0 +#define INIT_CTX_ENABLE_VALUE 0x0 +#define INIT_PC_VALUE 0x0 +#define INIT_WAKEUP_EVENTS_VALUE 0x1 +#define INIT_SIG_EVENTS_VALUE 0x1 +#define INIT_CCENABLE_VALUE 0x2000 +#define RST_CSR_QAT_LSB 20 +#define RST_CSR_AE_LSB 0 +#define MC_TIMESTAMP_ENABLE (0x1 << 7) + +#define IGNORE_W1C_MASK \ + ((~(1 << CE_BREAKPOINT_BITPOS)) & \ + (~(1 << CE_CNTL_STORE_PARITY_ERROR_BITPOS)) & \ + (~(1 << CE_REG_PAR_ERR_BITPOS))) +#define INSERT_IMMED_GPRA_CONST(inst, const_val) \ + (inst = ((inst & 0xFFFF00C03FFull) | \ + ((((const_val) << 12) & 0x0FF00000ull) | \ + (((const_val) << 10) & 0x0003FC00ull)))) +#define INSERT_IMMED_GPRB_CONST(inst, const_val) \ + (inst = ((inst & 0xFFFF00FFF00ull) | \ + ((((const_val) << 12) & 0x0FF00000ull) | \ + (((const_val) << 0) & 0x000000FFull)))) + +#define AE(handle, ae) ((handle)->hal_handle->aes[ae]) + +static const uint64_t inst_4b[] = { 0x0F0400C0000ull, 0x0F4400C0000ull, + 0x0F040000300ull, 0x0F440000300ull, + 0x0FC066C0000ull, 0x0F0000C0300ull, + 0x0F0000C0300ull, 0x0F0000C0300ull, + 0x0A021000000ull }; + +static const uint64_t inst[] = { + 0x0F0000C0000ull, 0x0F000000380ull, 0x0D805000011ull, 0x0FC082C0300ull, + 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull, + 0x0A0643C0000ull, 0x0BAC0000301ull, 0x0D802000101ull, 0x0F0000C0001ull, + 0x0FC066C0001ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull, + 0x0F000400300ull, 0x0A0610C0000ull, 0x0BAC0000301ull, 0x0D804400101ull, + 0x0A0580C0000ull, 0x0A0581C0000ull, 0x0A0582C0000ull, 0x0A0583C0000ull, + 0x0A0584C0000ull, 0x0A0585C0000ull, 0x0A0586C0000ull, 0x0A0587C0000ull, + 0x0A0588C0000ull, 0x0A0589C0000ull, 0x0A058AC0000ull, 0x0A058BC0000ull, + 0x0A058CC0000ull, 0x0A058DC0000ull, 0x0A058EC0000ull, 0x0A058FC0000ull, + 0x0A05C0C0000ull, 0x0A05C1C0000ull, 0x0A05C2C0000ull, 0x0A05C3C0000ull, + 0x0A05C4C0000ull, 0x0A05C5C0000ull, 0x0A05C6C0000ull, 0x0A05C7C0000ull, + 0x0A05C8C0000ull, 0x0A05C9C0000ull, 0x0A05CAC0000ull, 0x0A05CBC0000ull, + 0x0A05CCC0000ull, 0x0A05CDC0000ull, 0x0A05CEC0000ull, 0x0A05CFC0000ull, + 0x0A0400C0000ull, 0x0B0400C0000ull, 0x0A0401C0000ull, 0x0B0401C0000ull, + 0x0A0402C0000ull, 0x0B0402C0000ull, 0x0A0403C0000ull, 0x0B0403C0000ull, + 0x0A0404C0000ull, 0x0B0404C0000ull, 0x0A0405C0000ull, 0x0B0405C0000ull, + 0x0A0406C0000ull, 0x0B0406C0000ull, 0x0A0407C0000ull, 0x0B0407C0000ull, + 0x0A0408C0000ull, 0x0B0408C0000ull, 0x0A0409C0000ull, 0x0B0409C0000ull, + 0x0A040AC0000ull, 0x0B040AC0000ull, 0x0A040BC0000ull, 0x0B040BC0000ull, + 0x0A040CC0000ull, 0x0B040CC0000ull, 0x0A040DC0000ull, 0x0B040DC0000ull, + 0x0A040EC0000ull, 0x0B040EC0000ull, 0x0A040FC0000ull, 0x0B040FC0000ull, + 0x0D81581C010ull, 0x0E000010000ull, 0x0E000010000ull, +}; + +void +qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask) +{ + AE(handle, ae).live_ctx_mask = ctx_mask; +} + +#define CSR_RETRY_TIMES 500 +static int +qat_hal_rd_ae_csr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int csr, + unsigned int *value) +{ + unsigned int iterations = CSR_RETRY_TIMES; + + do { + *value = GET_AE_CSR(handle, ae, csr); + if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS)) + return 0; + } while (iterations--); + + pr_err("QAT: Read CSR timeout\n"); + return EFAULT; +} + +static int +qat_hal_wr_ae_csr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int csr, + unsigned int value) +{ + unsigned int iterations = CSR_RETRY_TIMES; + + do { + SET_AE_CSR(handle, ae, csr, value); + if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS)) + return 0; + } while (iterations--); + + pr_err("QAT: Write CSR Timeout\n"); + return EFAULT; +} + +static void +qat_hal_get_wakeup_event(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + unsigned int *events) +{ + unsigned int cur_ctx; + + qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx); + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx); + qat_hal_rd_ae_csr(handle, ae, CTX_WAKEUP_EVENTS_INDIRECT, events); + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx); +} + +static int +qat_hal_wait_cycles(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int cycles, + int chk_inactive) +{ + unsigned int base_cnt = 0, cur_cnt = 0; + unsigned int csr = (1 << ACS_ABO_BITPOS); + int times = MAX_RETRY_TIMES; + int elapsed_cycles = 0; + + qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &base_cnt); + base_cnt &= 0xffff; + while ((int)cycles > elapsed_cycles && times--) { + if (chk_inactive) + qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &csr); + + qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &cur_cnt); + cur_cnt &= 0xffff; + elapsed_cycles = cur_cnt - base_cnt; + + if (elapsed_cycles < 0) + elapsed_cycles += 0x10000; + + /* ensure at least 8 time cycles elapsed in wait_cycles */ + if (elapsed_cycles >= 8 && !(csr & (1 << ACS_ABO_BITPOS))) + return 0; + } + if (times < 0) { + pr_err("QAT: wait_num_cycles time out\n"); + return EFAULT; + } + return 0; +} + +void +qat_hal_get_scs_neigh_ae(unsigned char ae, unsigned char *ae_neigh) +{ + *ae_neigh = (ae & 0x1) ? (ae - 1) : (ae + 1); +} + +#define CLR_BIT(wrd, bit) ((wrd) & ~(1 << (bit))) +#define SET_BIT(wrd, bit) ((wrd) | 1 << (bit)) + +int +qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode) +{ + unsigned int csr, new_csr; + + if (mode != 4 && mode != 8) { + pr_err("QAT: bad ctx mode=%d\n", mode); + return EINVAL; + } + + /* Sets the accelaration engine context mode to either four or eight */ + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr); + csr = IGNORE_W1C_MASK & csr; + new_csr = (mode == 4) ? SET_BIT(csr, CE_INUSE_CONTEXTS_BITPOS) : + CLR_BIT(csr, CE_INUSE_CONTEXTS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr); + return 0; +} + +int +qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode) +{ + unsigned int csr, new_csr; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr); + csr &= IGNORE_W1C_MASK; + + new_csr = (mode) ? SET_BIT(csr, CE_NN_MODE_BITPOS) : + CLR_BIT(csr, CE_NN_MODE_BITPOS); + + if (new_csr != csr) + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr); + + return 0; +} + +int +qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + enum icp_qat_uof_regtype lm_type, + unsigned char mode) +{ + unsigned int csr, new_csr; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr); + csr &= IGNORE_W1C_MASK; + switch (lm_type) { + case ICP_LMEM0: + new_csr = (mode) ? SET_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS) : + CLR_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS); + break; + case ICP_LMEM1: + new_csr = (mode) ? SET_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS) : + CLR_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS); + break; + case ICP_LMEM2: + new_csr = (mode) ? SET_BIT(csr, CE_LMADDR_2_GLOBAL_BITPOS) : + CLR_BIT(csr, CE_LMADDR_2_GLOBAL_BITPOS); + break; + case ICP_LMEM3: + new_csr = (mode) ? SET_BIT(csr, CE_LMADDR_3_GLOBAL_BITPOS) : + CLR_BIT(csr, CE_LMADDR_3_GLOBAL_BITPOS); + break; + default: + pr_err("QAT: lmType = 0x%x\n", lm_type); + return EINVAL; + } + + if (new_csr != csr) + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr); + return 0; +} + +void +qat_hal_set_ae_tindex_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode) +{ + unsigned int csr, new_csr; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr); + csr &= IGNORE_W1C_MASK; + new_csr = (mode) ? SET_BIT(csr, CE_T_INDEX_GLOBAL_BITPOS) : + CLR_BIT(csr, CE_T_INDEX_GLOBAL_BITPOS); + if (new_csr != csr) + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr); +} + +void +qat_hal_set_ae_scs_mode(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char mode) +{ + unsigned int csr, new_csr; + + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr); + new_csr = (mode) ? SET_BIT(csr, MMC_SHARE_CS_BITPOS) : + CLR_BIT(csr, MMC_SHARE_CS_BITPOS); + if (new_csr != csr) + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, new_csr); +} + +static unsigned short +qat_hal_get_reg_addr(unsigned int type, unsigned short reg_num) +{ + unsigned short reg_addr; + + switch (type) { + case ICP_GPA_ABS: + case ICP_GPB_ABS: + reg_addr = 0x80 | (reg_num & 0x7f); + break; + case ICP_GPA_REL: + case ICP_GPB_REL: + reg_addr = reg_num & 0x1f; + break; + case ICP_SR_RD_REL: + case ICP_SR_WR_REL: + case ICP_SR_REL: + reg_addr = 0x180 | (reg_num & 0x1f); + break; + case ICP_SR_ABS: + reg_addr = 0x140 | ((reg_num & 0x3) << 1); + break; + case ICP_DR_RD_REL: + case ICP_DR_WR_REL: + case ICP_DR_REL: + reg_addr = 0x1c0 | (reg_num & 0x1f); + break; + case ICP_DR_ABS: + reg_addr = 0x100 | ((reg_num & 0x3) << 1); + break; + case ICP_NEIGH_REL: + reg_addr = 0x280 | (reg_num & 0x1f); + break; + case ICP_LMEM0: + reg_addr = 0x200; + break; + case ICP_LMEM1: + reg_addr = 0x220; + break; + case ICP_LMEM2: + reg_addr = 0x2c0; + break; + case ICP_LMEM3: + reg_addr = 0x2e0; + break; + case ICP_NO_DEST: + reg_addr = 0x300 | (reg_num & 0xff); + break; + default: + reg_addr = BAD_REGADDR; + break; + } + return reg_addr; +} + +void +qat_hal_reset(struct icp_qat_fw_loader_handle *handle) +{ + unsigned int ae_reset_csr[MAX_CPP_NUM]; + unsigned int ae_reset_val[MAX_CPP_NUM]; + unsigned int valid_ae_mask, valid_slice_mask; + unsigned int cpp_num = 1; + unsigned int i; + + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + ae_reset_csr[0] = ICP_RESET_CPP0; + ae_reset_csr[1] = ICP_RESET_CPP1; + if (handle->hal_handle->ae_mask > 0xffff) + ++cpp_num; + } else { + ae_reset_csr[0] = ICP_RESET; + } + + for (i = 0; i < cpp_num; i++) { + if (i == 0) { + valid_ae_mask = handle->hal_handle->ae_mask & 0xFFFF; + valid_slice_mask = + handle->hal_handle->slice_mask & 0x3F; + } else { + valid_ae_mask = + (handle->hal_handle->ae_mask >> AES_PER_CPP) & + 0xFFFF; + valid_slice_mask = + (handle->hal_handle->slice_mask >> SLICES_PER_CPP) & + 0x3F; + } + + ae_reset_val[i] = GET_GLB_CSR(handle, ae_reset_csr[i]); + ae_reset_val[i] |= valid_ae_mask << RST_CSR_AE_LSB; + ae_reset_val[i] |= valid_slice_mask << RST_CSR_QAT_LSB; + SET_GLB_CSR(handle, ae_reset_csr[i], ae_reset_val[i]); + } +} + +static void +qat_hal_wr_indr_csr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask, + unsigned int ae_csr, + unsigned int csr_val) +{ + unsigned int ctx, cur_ctx; + + qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx); + + for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) { + if (!(ctx_mask & (1 << ctx))) + continue; + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx); + qat_hal_wr_ae_csr(handle, ae, ae_csr, csr_val); + } + + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx); +} + +static void +qat_hal_rd_indr_csr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + unsigned int ae_csr, + unsigned int *csr_val) +{ + unsigned int cur_ctx; + + qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx); + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx); + qat_hal_rd_ae_csr(handle, ae, ae_csr, csr_val); + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx); +} + +static void +qat_hal_put_sig_event(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask, + unsigned int events) +{ + unsigned int ctx, cur_ctx; + + qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx); + for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) { + if (!(ctx_mask & (1 << ctx))) + continue; + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx); + qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_INDIRECT, events); + } + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx); +} + +static void +qat_hal_put_wakeup_event(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask, + unsigned int events) +{ + unsigned int ctx, cur_ctx; + + qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx); + for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) { + if (!(ctx_mask & (1 << ctx))) + continue; + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx); + qat_hal_wr_ae_csr(handle, + ae, + CTX_WAKEUP_EVENTS_INDIRECT, + events); + } + qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx); +} + +static int +qat_hal_check_ae_alive(struct icp_qat_fw_loader_handle *handle) +{ + unsigned int base_cnt, cur_cnt; + unsigned char ae; + unsigned long ae_mask = handle->hal_handle->ae_mask; + int times = MAX_RETRY_TIMES; + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + qat_hal_rd_ae_csr(handle, + ae, + PROFILE_COUNT, + (unsigned int *)&base_cnt); + base_cnt &= 0xffff; + + do { + qat_hal_rd_ae_csr(handle, + ae, + PROFILE_COUNT, + (unsigned int *)&cur_cnt); + cur_cnt &= 0xffff; + } while (times-- && (cur_cnt == base_cnt)); + + if (times < 0) { + pr_err("QAT: AE%d is inactive!!\n", ae); + return EFAULT; + } + } + + return 0; +} + +int +qat_hal_check_ae_active(struct icp_qat_fw_loader_handle *handle, + unsigned int ae) +{ + unsigned int enable = 0, active = 0; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &enable); + qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &active); + if ((enable & (0xff << CE_ENABLE_BITPOS)) || + (active & (1 << ACS_ABO_BITPOS))) + return 1; + else + return 0; +} + +static void +qat_hal_reset_timestamp(struct icp_qat_fw_loader_handle *handle) +{ + unsigned int misc_ctl_csr, misc_ctl; + unsigned char ae; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + misc_ctl_csr = + (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) ? + MISC_CONTROL_C4XXX : + MISC_CONTROL; + /* stop the timestamp timers */ + misc_ctl = GET_GLB_CSR(handle, misc_ctl_csr); + if (misc_ctl & MC_TIMESTAMP_ENABLE) + SET_GLB_CSR(handle, + misc_ctl_csr, + misc_ctl & (~MC_TIMESTAMP_ENABLE)); + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_LOW, 0); + qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_HIGH, 0); + } + /* start timestamp timers */ + SET_GLB_CSR(handle, misc_ctl_csr, misc_ctl | MC_TIMESTAMP_ENABLE); +} + +#define ESRAM_AUTO_TINIT BIT(2) +#define ESRAM_AUTO_TINIT_DONE BIT(3) +#define ESRAM_AUTO_INIT_USED_CYCLES (1640) +#define ESRAM_AUTO_INIT_CSR_OFFSET 0xC1C + +static int +qat_hal_init_esram(struct icp_qat_fw_loader_handle *handle) +{ + uintptr_t csr_addr = + ((uintptr_t)handle->hal_ep_csr_addr_v + ESRAM_AUTO_INIT_CSR_OFFSET); + unsigned int csr_val; + int times = 30; + + if (pci_get_device(GET_DEV(handle->accel_dev)) != + ADF_DH895XCC_PCI_DEVICE_ID) + return 0; + + csr_val = ADF_CSR_RD(handle->hal_misc_addr_v, csr_addr); + if ((csr_val & ESRAM_AUTO_TINIT) && (csr_val & ESRAM_AUTO_TINIT_DONE)) + return 0; + csr_val = ADF_CSR_RD(handle->hal_misc_addr_v, csr_addr); + csr_val |= ESRAM_AUTO_TINIT; + + ADF_CSR_WR(handle->hal_misc_addr_v, csr_addr, csr_val); + do { + qat_hal_wait_cycles(handle, 0, ESRAM_AUTO_INIT_USED_CYCLES, 0); + csr_val = ADF_CSR_RD(handle->hal_misc_addr_v, csr_addr); + + } while (!(csr_val & ESRAM_AUTO_TINIT_DONE) && times--); + if (times < 0) { + pr_err("QAT: Fail to init eSram!\n"); + return EFAULT; + } + return 0; +} + +#define SHRAM_INIT_CYCLES 2060 +int +qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle) +{ + unsigned int ae_reset_csr[MAX_CPP_NUM]; + unsigned int ae_reset_val[MAX_CPP_NUM]; + unsigned int cpp_num = 1; + unsigned int valid_ae_mask, valid_slice_mask; + unsigned char ae; + unsigned int i; + unsigned int clk_csr[MAX_CPP_NUM]; + unsigned int clk_val[MAX_CPP_NUM]; + unsigned int times = 100; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + ae_reset_csr[0] = ICP_RESET_CPP0; + ae_reset_csr[1] = ICP_RESET_CPP1; + clk_csr[0] = ICP_GLOBAL_CLK_ENABLE_CPP0; + clk_csr[1] = ICP_GLOBAL_CLK_ENABLE_CPP1; + if (handle->hal_handle->ae_mask > 0xffff) + ++cpp_num; + } else { + ae_reset_csr[0] = ICP_RESET; + clk_csr[0] = ICP_GLOBAL_CLK_ENABLE; + } + + for (i = 0; i < cpp_num; i++) { + if (i == 0) { + valid_ae_mask = handle->hal_handle->ae_mask & 0xFFFF; + valid_slice_mask = + handle->hal_handle->slice_mask & 0x3F; + } else { + valid_ae_mask = + (handle->hal_handle->ae_mask >> AES_PER_CPP) & + 0xFFFF; + valid_slice_mask = + (handle->hal_handle->slice_mask >> SLICES_PER_CPP) & + 0x3F; + } + /* write to the reset csr */ + ae_reset_val[i] = GET_GLB_CSR(handle, ae_reset_csr[i]); + ae_reset_val[i] &= ~(valid_ae_mask << RST_CSR_AE_LSB); + ae_reset_val[i] &= ~(valid_slice_mask << RST_CSR_QAT_LSB); + do { + SET_GLB_CSR(handle, ae_reset_csr[i], ae_reset_val[i]); + if (!(times--)) + goto out_err; + ae_reset_val[i] = GET_GLB_CSR(handle, ae_reset_csr[i]); + } while ( + (valid_ae_mask | (valid_slice_mask << RST_CSR_QAT_LSB)) & + ae_reset_val[i]); + /* enable clock */ + clk_val[i] = GET_GLB_CSR(handle, clk_csr[i]); + clk_val[i] |= valid_ae_mask << 0; + clk_val[i] |= valid_slice_mask << 20; + SET_GLB_CSR(handle, clk_csr[i], clk_val[i]); + } + if (qat_hal_check_ae_alive(handle)) + goto out_err; + + /* Set undefined power-up/reset states to reasonable default values */ + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + qat_hal_wr_ae_csr(handle, + ae, + CTX_ENABLES, + INIT_CTX_ENABLE_VALUE); + qat_hal_wr_indr_csr(handle, + ae, + ICP_QAT_UCLO_AE_ALL_CTX, + CTX_STS_INDIRECT, + handle->hal_handle->upc_mask & + INIT_PC_VALUE); + qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE); + qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE); + qat_hal_put_wakeup_event(handle, + ae, + ICP_QAT_UCLO_AE_ALL_CTX, + INIT_WAKEUP_EVENTS_VALUE); + qat_hal_put_sig_event(handle, + ae, + ICP_QAT_UCLO_AE_ALL_CTX, + INIT_SIG_EVENTS_VALUE); + } + if (qat_hal_init_esram(handle)) + goto out_err; + if (qat_hal_wait_cycles(handle, 0, SHRAM_INIT_CYCLES, 0)) + goto out_err; + qat_hal_reset_timestamp(handle); + + return 0; +out_err: + pr_err("QAT: failed to get device out of reset\n"); + return EFAULT; +} + +static void +qat_hal_disable_ctx(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask) +{ + unsigned int ctx; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx); + ctx &= IGNORE_W1C_MASK & + (~((ctx_mask & ICP_QAT_UCLO_AE_ALL_CTX) << CE_ENABLE_BITPOS)); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx); +} + +static uint64_t +qat_hal_parity_64bit(uint64_t word) +{ + word ^= word >> 1; + word ^= word >> 2; + word ^= word >> 4; + word ^= word >> 8; + word ^= word >> 16; + word ^= word >> 32; + return word & 1; +} + +static uint64_t +qat_hal_set_uword_ecc(uint64_t uword) +{ + uint64_t bit0_mask = 0xff800007fffULL, bit1_mask = 0x1f801ff801fULL, + bit2_mask = 0xe387e0781e1ULL, bit3_mask = 0x7cb8e388e22ULL, + bit4_mask = 0xaf5b2c93244ULL, bit5_mask = 0xf56d5525488ULL, + bit6_mask = 0xdaf69a46910ULL; + + /* clear the ecc bits */ + uword &= ~(0x7fULL << 0x2C); + uword |= qat_hal_parity_64bit(bit0_mask & uword) << 0x2C; + uword |= qat_hal_parity_64bit(bit1_mask & uword) << 0x2D; + uword |= qat_hal_parity_64bit(bit2_mask & uword) << 0x2E; + uword |= qat_hal_parity_64bit(bit3_mask & uword) << 0x2F; + uword |= qat_hal_parity_64bit(bit4_mask & uword) << 0x30; + uword |= qat_hal_parity_64bit(bit5_mask & uword) << 0x31; + uword |= qat_hal_parity_64bit(bit6_mask & uword) << 0x32; + return uword; +} + +void +qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + const uint64_t *uword) +{ + unsigned int ustore_addr; + unsigned int i; + + qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr); + uaddr |= UA_ECS; + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr); + for (i = 0; i < words_num; i++) { + unsigned int uwrd_lo, uwrd_hi; + uint64_t tmp; + + tmp = qat_hal_set_uword_ecc(uword[i]); + uwrd_lo = (unsigned int)(tmp & 0xffffffff); + uwrd_hi = (unsigned int)(tmp >> 0x20); + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo); + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi); + } + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr); +} + +void +qat_hal_wr_coalesce_uwords(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + u64 *uword) +{ + u64 *even_uwrods, *odd_uwords; + unsigned char neigh_ae, odd_ae, even_ae; + int i, even_cpy_cnt = 0, odd_cpy_cnt = 0; + + even_uwrods = + malloc(16 * 1024 * sizeof(*uword), M_QAT, M_WAITOK | M_ZERO); + odd_uwords = + malloc(16 * 1024 * sizeof(*uword), M_QAT, M_WAITOK | M_ZERO); + qat_hal_get_scs_neigh_ae(ae, &neigh_ae); + if (ae & 1) { + odd_ae = ae; + even_ae = neigh_ae; + } else { + odd_ae = neigh_ae; + even_ae = ae; + } + for (i = 0; i < words_num; i++) { + if ((uaddr + i) & 1) + odd_uwords[odd_cpy_cnt++] = uword[i]; + else + even_uwrods[even_cpy_cnt++] = uword[i]; + } + if (even_cpy_cnt) + qat_hal_wr_uwords(handle, + even_ae, + (uaddr + 1) / 2, + even_cpy_cnt, + even_uwrods); + if (odd_cpy_cnt) + qat_hal_wr_uwords( + handle, odd_ae, uaddr / 2, odd_cpy_cnt, odd_uwords); + free(even_uwrods, M_QAT); + free(odd_uwords, M_QAT); +} + +static void +qat_hal_enable_ctx(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask) +{ + unsigned int ctx; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx); + ctx &= IGNORE_W1C_MASK; + ctx_mask &= (ctx & CE_INUSE_CONTEXTS) ? 0x55 : 0xFF; + ctx |= (ctx_mask << CE_ENABLE_BITPOS); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx); +} + +static void +qat_hal_clear_xfer(struct icp_qat_fw_loader_handle *handle) +{ + unsigned char ae; + unsigned short reg; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + for (reg = 0; reg < ICP_QAT_UCLO_MAX_GPR_REG; reg++) { + qat_hal_init_rd_xfer( + handle, ae, 0, ICP_SR_RD_ABS, reg, 0); + qat_hal_init_rd_xfer( + handle, ae, 0, ICP_DR_RD_ABS, reg, 0); + } + } +} + +static int +qat_hal_clear_gpr(struct icp_qat_fw_loader_handle *handle) +{ + unsigned char ae; + unsigned int ctx_mask = ICP_QAT_UCLO_AE_ALL_CTX; + int times = MAX_RETRY_TIMES; + unsigned int csr_val = 0; + unsigned int savctx = 0; + unsigned int scs_flag = 0; + unsigned long ae_mask = handle->hal_handle->ae_mask; + int ret = 0; + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + scs_flag = csr_val & (1 << MMC_SHARE_CS_BITPOS); + csr_val &= ~(1 << MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, csr_val); + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr_val); + csr_val &= IGNORE_W1C_MASK; + csr_val |= CE_NN_MODE; + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, csr_val); + qat_hal_wr_uwords( + handle, ae, 0, ARRAY_SIZE(inst), (const uint64_t *)inst); + qat_hal_wr_indr_csr(handle, + ae, + ctx_mask, + CTX_STS_INDIRECT, + handle->hal_handle->upc_mask & + INIT_PC_VALUE); + qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx); + qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, 0); + qat_hal_put_wakeup_event(handle, ae, ctx_mask, XCWE_VOLUNTARY); + qat_hal_wr_indr_csr( + handle, ae, ctx_mask, CTX_SIG_EVENTS_INDIRECT, 0); + qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0); + qat_hal_enable_ctx(handle, ae, ctx_mask); + } + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + /* wait for AE to finish */ + do { + ret = qat_hal_wait_cycles(handle, ae, 20, 1); + } while (ret && times--); + + if (times < 0) { + pr_err("QAT: clear GPR of AE %d failed", ae); + return EINVAL; + } + qat_hal_disable_ctx(handle, ae, ctx_mask); + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + if (scs_flag) + csr_val |= (1 << MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, csr_val); + qat_hal_wr_ae_csr(handle, + ae, + ACTIVE_CTX_STATUS, + savctx & ACS_ACNO); + qat_hal_wr_ae_csr(handle, + ae, + CTX_ENABLES, + INIT_CTX_ENABLE_VALUE); + qat_hal_wr_indr_csr(handle, + ae, + ctx_mask, + CTX_STS_INDIRECT, + handle->hal_handle->upc_mask & + INIT_PC_VALUE); + qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE); + qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE); + qat_hal_put_wakeup_event(handle, + ae, + ctx_mask, + INIT_WAKEUP_EVENTS_VALUE); + qat_hal_put_sig_event(handle, + ae, + ctx_mask, + INIT_SIG_EVENTS_VALUE); + } + return 0; +} + +static int +qat_hal_check_imr(struct icp_qat_fw_loader_handle *handle) +{ + device_t dev = accel_to_pci_dev(handle->accel_dev); + u8 reg_val = 0; + + if (pci_get_device(GET_DEV(handle->accel_dev)) != + ADF_C3XXX_PCI_DEVICE_ID && + pci_get_device(GET_DEV(handle->accel_dev)) != + ADF_200XX_PCI_DEVICE_ID) + return 0; + + reg_val = pci_read_config(dev, 0x04, 1); + /* + * PCI command register memory bit and rambaseaddr_lo address + * are checked to confirm IMR2 is enabled in BIOS settings + */ + if ((reg_val & 0x2) && GET_FCU_CSR(handle, FCU_RAMBASE_ADDR_LO)) + return 0; + + return EINVAL; +} + +int +qat_hal_init(struct adf_accel_dev *accel_dev) +{ + unsigned char ae; + unsigned int cap_offset, ae_offset, ep_offset; + unsigned int sram_offset = 0; + unsigned int max_en_ae_id = 0; + int ret = 0; + unsigned long ae_mask; + struct icp_qat_fw_loader_handle *handle; + if (!accel_dev) { + return EFAULT; + } + struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_bar *misc_bar = + &pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)]; + struct adf_bar *sram_bar; + + handle = malloc(sizeof(*handle), M_QAT, M_WAITOK | M_ZERO); + + handle->hal_misc_addr_v = misc_bar->virt_addr; + handle->accel_dev = accel_dev; + if (pci_get_device(GET_DEV(handle->accel_dev)) == + ADF_DH895XCC_PCI_DEVICE_ID || + IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + sram_bar = + &pci_info->pci_bars[hw_data->get_sram_bar_id(hw_data)]; + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) + sram_offset = + 0x400000 + accel_dev->aram_info->mmp_region_offset; + handle->hal_sram_addr_v = sram_bar->virt_addr; + handle->hal_sram_offset = sram_offset; + handle->hal_sram_size = sram_bar->size; + } + GET_CSR_OFFSET(pci_get_device(GET_DEV(handle->accel_dev)), + cap_offset, + ae_offset, + ep_offset); + handle->hal_cap_g_ctl_csr_addr_v = cap_offset; + handle->hal_cap_ae_xfer_csr_addr_v = ae_offset; + handle->hal_ep_csr_addr_v = ep_offset; + handle->hal_cap_ae_local_csr_addr_v = + ((uintptr_t)handle->hal_cap_ae_xfer_csr_addr_v + + LOCAL_TO_XFER_REG_OFFSET); + handle->fw_auth = (pci_get_device(GET_DEV(handle->accel_dev)) == + ADF_DH895XCC_PCI_DEVICE_ID) ? + false : + true; + if (handle->fw_auth && qat_hal_check_imr(handle)) { + device_printf(GET_DEV(accel_dev), "IMR2 not enabled in BIOS\n"); + ret = EINVAL; + goto out_hal_handle; + } + + handle->hal_handle = + malloc(sizeof(*handle->hal_handle), M_QAT, M_WAITOK | M_ZERO); + handle->hal_handle->revision_id = accel_dev->accel_pci_dev.revid; + handle->hal_handle->ae_mask = hw_data->ae_mask; + handle->hal_handle->slice_mask = hw_data->accel_mask; + handle->cfg_ae_mask = 0xFFFFFFFF; + /* create AE objects */ + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + handle->hal_handle->upc_mask = 0xffff; + handle->hal_handle->max_ustore = 0x2000; + } else { + handle->hal_handle->upc_mask = 0x1ffff; + handle->hal_handle->max_ustore = 0x4000; + } + + ae_mask = hw_data->ae_mask; + + for_each_set_bit(ae, &ae_mask, ICP_QAT_UCLO_MAX_AE) + { + handle->hal_handle->aes[ae].free_addr = 0; + handle->hal_handle->aes[ae].free_size = + handle->hal_handle->max_ustore; + handle->hal_handle->aes[ae].ustore_size = + handle->hal_handle->max_ustore; + handle->hal_handle->aes[ae].live_ctx_mask = + ICP_QAT_UCLO_AE_ALL_CTX; + max_en_ae_id = ae; + } + handle->hal_handle->ae_max_num = max_en_ae_id + 1; + /* take all AEs out of reset */ + if (qat_hal_clr_reset(handle)) { + device_printf(GET_DEV(accel_dev), "qat_hal_clr_reset error\n"); + ret = EIO; + goto out_err; + } + qat_hal_clear_xfer(handle); + if (!handle->fw_auth) { + if (qat_hal_clear_gpr(handle)) { + ret = EIO; + goto out_err; + } + } + + /* Set SIGNATURE_ENABLE[0] to 0x1 in order to enable ALU_OUT csr */ + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + unsigned int csr_val = 0; + + qat_hal_rd_ae_csr(handle, ae, SIGNATURE_ENABLE, &csr_val); + csr_val |= 0x1; + qat_hal_wr_ae_csr(handle, ae, SIGNATURE_ENABLE, csr_val); + } + accel_dev->fw_loader->fw_loader = handle; + return 0; + +out_err: + free(handle->hal_handle, M_QAT); +out_hal_handle: + free(handle, M_QAT); + return ret; +} + +void +qat_hal_deinit(struct icp_qat_fw_loader_handle *handle) +{ + if (!handle) + return; + free(handle->hal_handle, M_QAT); + free(handle, M_QAT); +} + +void +qat_hal_start(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask) +{ + int retry = 0; + unsigned int fcu_sts = 0; + unsigned int fcu_ctl_csr, fcu_sts_csr; + + if (handle->fw_auth) { + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + fcu_ctl_csr = FCU_CONTROL_C4XXX; + fcu_sts_csr = FCU_STATUS_C4XXX; + + } else { + fcu_ctl_csr = FCU_CONTROL; + fcu_sts_csr = FCU_STATUS; + } + SET_FCU_CSR(handle, fcu_ctl_csr, FCU_CTRL_CMD_START); + do { + pause_ms("adfstop", FW_AUTH_WAIT_PERIOD); + fcu_sts = GET_FCU_CSR(handle, fcu_sts_csr); + if (((fcu_sts >> FCU_STS_DONE_POS) & 0x1)) + return; + } while (retry++ < FW_AUTH_MAX_RETRY); + pr_err("QAT: start error (AE 0x%x FCU_STS = 0x%x)\n", + ae, + fcu_sts); + } else { + qat_hal_put_wakeup_event(handle, + ae, + (~ctx_mask) & ICP_QAT_UCLO_AE_ALL_CTX, + 0x10000); + qat_hal_enable_ctx(handle, ae, ctx_mask); + } +} + +void +qat_hal_stop(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask) +{ + if (!handle->fw_auth) + qat_hal_disable_ctx(handle, ae, ctx_mask); +} + +void +qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int ctx_mask, + unsigned int upc) +{ + qat_hal_wr_indr_csr(handle, + ae, + ctx_mask, + CTX_STS_INDIRECT, + handle->hal_handle->upc_mask & upc); +} + +static void +qat_hal_get_uwords(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + uint64_t *uword) +{ + unsigned int i, uwrd_lo, uwrd_hi; + unsigned int ustore_addr, misc_control; + unsigned int scs_flag = 0; + + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &misc_control); + scs_flag = misc_control & (0x1 << MMC_SHARE_CS_BITPOS); + /*disable scs*/ + qat_hal_wr_ae_csr(handle, + ae, + AE_MISC_CONTROL, + misc_control & 0xfffffffb); + qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr); + uaddr |= UA_ECS; + for (i = 0; i < words_num; i++) { + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr); + uaddr++; + qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_LOWER, &uwrd_lo); + qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_UPPER, &uwrd_hi); + uword[i] = uwrd_hi; + uword[i] = (uword[i] << 0x20) | uwrd_lo; + } + if (scs_flag) + misc_control |= (0x1 << MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, misc_control); + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr); +} + +void +qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int uaddr, + unsigned int words_num, + unsigned int *data) +{ + unsigned int i, ustore_addr; + + qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr); + uaddr |= UA_ECS; + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr); + for (i = 0; i < words_num; i++) { + unsigned int uwrd_lo, uwrd_hi, tmp; + + uwrd_lo = ((data[i] & 0xfff0000) << 4) | (0x3 << 18) | + ((data[i] & 0xff00) << 2) | (0x3 << 8) | (data[i] & 0xff); + uwrd_hi = (0xf << 4) | ((data[i] & 0xf0000000) >> 28); + uwrd_hi |= (bitcount32(data[i] & 0xffff) & 0x1) << 8; + tmp = ((data[i] >> 0x10) & 0xffff); + uwrd_hi |= (bitcount32(tmp) & 0x1) << 9; + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo); + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi); + } + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr); +} + +#define MAX_EXEC_INST 100 +static int +qat_hal_exec_micro_inst(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + uint64_t *micro_inst, + unsigned int inst_num, + int code_off, + unsigned int max_cycle, + unsigned int *endpc) +{ + uint64_t savuwords[MAX_EXEC_INST]; + unsigned int ind_lm_addr0, ind_lm_addr1; + unsigned int ind_lm_addr2, ind_lm_addr3; + unsigned int ind_lm_addr_byte0, ind_lm_addr_byte1; + unsigned int ind_lm_addr_byte2, ind_lm_addr_byte3; + unsigned int ind_t_index, ind_t_index_byte; + unsigned int ind_cnt_sig; + unsigned int ind_sig, act_sig; + unsigned int csr_val = 0, newcsr_val; + unsigned int savctx, scs_flag; + unsigned int savcc, wakeup_events, savpc; + unsigned int ctxarb_ctl, ctx_enables; + + if (inst_num > handle->hal_handle->max_ustore || !micro_inst) { + pr_err("QAT: invalid instruction num %d\n", inst_num); + return EINVAL; + } + /* save current context */ + qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_0_INDIRECT, &ind_lm_addr0); + qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_1_INDIRECT, &ind_lm_addr1); + qat_hal_rd_indr_csr( + handle, ae, ctx, INDIRECT_LM_ADDR_0_BYTE_INDEX, &ind_lm_addr_byte0); + qat_hal_rd_indr_csr( + handle, ae, ctx, INDIRECT_LM_ADDR_1_BYTE_INDEX, &ind_lm_addr_byte1); + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + qat_hal_rd_indr_csr( + handle, ae, ctx, LM_ADDR_2_INDIRECT, &ind_lm_addr2); + qat_hal_rd_indr_csr( + handle, ae, ctx, LM_ADDR_3_INDIRECT, &ind_lm_addr3); + qat_hal_rd_indr_csr(handle, + ae, + ctx, + INDIRECT_LM_ADDR_2_BYTE_INDEX, + &ind_lm_addr_byte2); + qat_hal_rd_indr_csr(handle, + ae, + ctx, + INDIRECT_LM_ADDR_3_BYTE_INDEX, + &ind_lm_addr_byte3); + qat_hal_rd_indr_csr( + handle, ae, ctx, INDIRECT_T_INDEX, &ind_t_index); + qat_hal_rd_indr_csr(handle, + ae, + ctx, + INDIRECT_T_INDEX_BYTE_INDEX, + &ind_t_index_byte); + } + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + scs_flag = csr_val & (1 << MMC_SHARE_CS_BITPOS); + newcsr_val = CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val); + if (inst_num <= MAX_EXEC_INST) + qat_hal_get_uwords(handle, ae, 0, inst_num, savuwords); + qat_hal_get_wakeup_event(handle, ae, ctx, &wakeup_events); + qat_hal_rd_indr_csr(handle, ae, ctx, CTX_STS_INDIRECT, &savpc); + savpc = (savpc & handle->hal_handle->upc_mask) >> 0; + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + ctx_enables &= IGNORE_W1C_MASK; + qat_hal_rd_ae_csr(handle, ae, CC_ENABLE, &savcc); + qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx); + qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_ctl); + qat_hal_rd_indr_csr( + handle, ae, ctx, FUTURE_COUNT_SIGNAL_INDIRECT, &ind_cnt_sig); + qat_hal_rd_indr_csr(handle, ae, ctx, CTX_SIG_EVENTS_INDIRECT, &ind_sig); + qat_hal_rd_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, &act_sig); + /* execute micro codes */ + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables); + qat_hal_wr_uwords(handle, ae, 0, inst_num, micro_inst); + qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_STS_INDIRECT, 0); + qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, ctx & ACS_ACNO); + if (code_off) + qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc & 0xffffdfff); + qat_hal_put_wakeup_event(handle, ae, (1 << ctx), XCWE_VOLUNTARY); + qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_SIG_EVENTS_INDIRECT, 0); + qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0); + qat_hal_enable_ctx(handle, ae, (1 << ctx)); + /* wait for micro codes to finish */ + if (qat_hal_wait_cycles(handle, ae, max_cycle, 1) != 0) + return EFAULT; + if (endpc) { + unsigned int ctx_status; + + qat_hal_rd_indr_csr( + handle, ae, ctx, CTX_STS_INDIRECT, &ctx_status); + *endpc = ctx_status & handle->hal_handle->upc_mask; + } + /* retore to saved context */ + qat_hal_disable_ctx(handle, ae, (1 << ctx)); + if (inst_num <= MAX_EXEC_INST) + qat_hal_wr_uwords(handle, ae, 0, inst_num, savuwords); + qat_hal_put_wakeup_event(handle, ae, (1 << ctx), wakeup_events); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + CTX_STS_INDIRECT, + handle->hal_handle->upc_mask & savpc); + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + newcsr_val = scs_flag ? SET_BIT(csr_val, MMC_SHARE_CS_BITPOS) : + CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val); + qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc); + qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, savctx & ACS_ACNO); + qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_ctl); + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), LM_ADDR_0_INDIRECT, ind_lm_addr0); + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), LM_ADDR_1_INDIRECT, ind_lm_addr1); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + INDIRECT_LM_ADDR_0_BYTE_INDEX, + ind_lm_addr_byte0); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + INDIRECT_LM_ADDR_1_BYTE_INDEX, + ind_lm_addr_byte1); + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), LM_ADDR_2_INDIRECT, ind_lm_addr2); + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), LM_ADDR_3_INDIRECT, ind_lm_addr3); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + INDIRECT_LM_ADDR_2_BYTE_INDEX, + ind_lm_addr_byte2); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + INDIRECT_LM_ADDR_3_BYTE_INDEX, + ind_lm_addr_byte3); + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), INDIRECT_T_INDEX, ind_t_index); + qat_hal_wr_indr_csr(handle, + ae, + (1 << ctx), + INDIRECT_T_INDEX_BYTE_INDEX, + ind_t_index_byte); + } + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), FUTURE_COUNT_SIGNAL_INDIRECT, ind_cnt_sig); + qat_hal_wr_indr_csr( + handle, ae, (1 << ctx), CTX_SIG_EVENTS_INDIRECT, ind_sig); + qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, act_sig); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables); + + return 0; +} + +static int +qat_hal_rd_rel_reg(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int *data) +{ + unsigned int savctx, uaddr, uwrd_lo, uwrd_hi; + unsigned int ctxarb_cntl, ustore_addr, ctx_enables; + unsigned short reg_addr; + int status = 0; + unsigned int scs_flag = 0; + unsigned int csr_val = 0, newcsr_val = 0; + u64 insts, savuword; + + reg_addr = qat_hal_get_reg_addr(reg_type, reg_num); + if (reg_addr == BAD_REGADDR) { + pr_err("QAT: bad regaddr=0x%x\n", reg_addr); + return EINVAL; + } + switch (reg_type) { + case ICP_GPA_REL: + insts = 0xA070000000ull | (reg_addr & 0x3ff); + break; + default: + insts = (uint64_t)0xA030000000ull | ((reg_addr & 0x3ff) << 10); + break; + } + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + scs_flag = csr_val & (1 << MMC_SHARE_CS_BITPOS); + newcsr_val = CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val); + qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx); + qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_cntl); + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + ctx_enables &= IGNORE_W1C_MASK; + if (ctx != (savctx & ACS_ACNO)) + qat_hal_wr_ae_csr(handle, + ae, + ACTIVE_CTX_STATUS, + ctx & ACS_ACNO); + qat_hal_get_uwords(handle, ae, 0, 1, &savuword); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables); + qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr); + uaddr = UA_ECS; + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr); + insts = qat_hal_set_uword_ecc(insts); + uwrd_lo = (unsigned int)(insts & 0xffffffff); + uwrd_hi = (unsigned int)(insts >> 0x20); + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo); + qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi); + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr); + /* delay for at least 8 cycles */ + qat_hal_wait_cycles(handle, ae, 0x8, 0); + /* + * read ALU output + * the instruction should have been executed + * prior to clearing the ECS in putUwords + */ + qat_hal_rd_ae_csr(handle, ae, ALU_OUT, data); + qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr); + qat_hal_wr_uwords(handle, ae, 0, 1, &savuword); + if (ctx != (savctx & ACS_ACNO)) + qat_hal_wr_ae_csr(handle, + ae, + ACTIVE_CTX_STATUS, + savctx & ACS_ACNO); + qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_cntl); + qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val); + newcsr_val = scs_flag ? SET_BIT(csr_val, MMC_SHARE_CS_BITPOS) : + CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS); + qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables); + + return status; +} + +static int +qat_hal_wr_rel_reg(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int data) +{ + unsigned short src_hiaddr, src_lowaddr, dest_addr, data16hi, data16lo; + uint64_t insts[] = { 0x0F440000000ull, + 0x0F040000000ull, + 0x0F0000C0300ull, + 0x0E000010000ull }; + const int num_inst = ARRAY_SIZE(insts), code_off = 1; + const int imm_w1 = 0, imm_w0 = 1; + + dest_addr = qat_hal_get_reg_addr(reg_type, reg_num); + if (dest_addr == BAD_REGADDR) { + pr_err("QAT: bad destAddr=0x%x\n", dest_addr); + return EINVAL; + } + + data16lo = 0xffff & data; + data16hi = 0xffff & (data >> 0x10); + src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST, + (unsigned short)(0xff & data16hi)); + src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST, + (unsigned short)(0xff & data16lo)); + switch (reg_type) { + case ICP_GPA_REL: + insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) | + ((src_hiaddr & 0x3ff) << 10) | (dest_addr & 0x3ff); + insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) | + ((src_lowaddr & 0x3ff) << 10) | (dest_addr & 0x3ff); + break; + default: + insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) | + ((dest_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff); + + insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) | + ((dest_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff); + break; + } + + return qat_hal_exec_micro_inst( + handle, ae, ctx, insts, num_inst, code_off, num_inst * 0x5, NULL); +} + +int +qat_hal_get_ins_num(void) +{ + return ARRAY_SIZE(inst_4b); +} + +static int +qat_hal_concat_micro_code(uint64_t *micro_inst, + unsigned int inst_num, + unsigned int size, + unsigned int addr, + unsigned int *value) +{ + int i; + unsigned int cur_value; + const uint64_t *inst_arr; + unsigned int fixup_offset; + int usize = 0; + unsigned int orig_num; + unsigned int delta; + + orig_num = inst_num; + fixup_offset = inst_num; + cur_value = value[0]; + inst_arr = inst_4b; + usize = ARRAY_SIZE(inst_4b); + for (i = 0; i < usize; i++) + micro_inst[inst_num++] = inst_arr[i]; + INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], (addr)); + fixup_offset++; + INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], 0); + fixup_offset++; + INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0)); + fixup_offset++; + INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0x10)); + + delta = inst_num - orig_num; + + return (int)delta; +} + +static int +qat_hal_exec_micro_init_lm(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + int *pfirst_exec, + uint64_t *micro_inst, + unsigned int inst_num) +{ + int stat = 0; + unsigned int gpra0 = 0, gpra1 = 0, gpra2 = 0; + unsigned int gprb0 = 0, gprb1 = 0; + + if (*pfirst_exec) { + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, &gpra0); + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, &gpra1); + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, &gpra2); + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, &gprb0); + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, &gprb1); + *pfirst_exec = 0; + } + stat = qat_hal_exec_micro_inst( + handle, ae, ctx, micro_inst, inst_num, 1, inst_num * 0x5, NULL); + if (stat != 0) + return EFAULT; + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, gpra0); + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, gpra1); + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, gpra2); + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, gprb0); + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, gprb1); + + return 0; +} + +int +qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + struct icp_qat_uof_batch_init *lm_init_header) +{ + struct icp_qat_uof_batch_init *plm_init; + uint64_t *micro_inst_arry; + int micro_inst_num; + int alloc_inst_size; + int first_exec = 1; + int stat = 0; + + if (!lm_init_header) + return 0; + plm_init = lm_init_header->next; + alloc_inst_size = lm_init_header->size; + if ((unsigned int)alloc_inst_size > handle->hal_handle->max_ustore) + alloc_inst_size = handle->hal_handle->max_ustore; + micro_inst_arry = malloc(alloc_inst_size * sizeof(uint64_t), + M_QAT, + M_WAITOK | M_ZERO); + micro_inst_num = 0; + while (plm_init) { + unsigned int addr, *value, size; + + ae = plm_init->ae; + addr = plm_init->addr; + value = plm_init->value; + size = plm_init->size; + micro_inst_num += qat_hal_concat_micro_code( + micro_inst_arry, micro_inst_num, size, addr, value); + plm_init = plm_init->next; + } + /* exec micro codes */ + if (micro_inst_arry && micro_inst_num > 0) { + micro_inst_arry[micro_inst_num++] = 0x0E000010000ull; + stat = qat_hal_exec_micro_init_lm(handle, + ae, + 0, + &first_exec, + micro_inst_arry, + micro_inst_num); + } + free(micro_inst_arry, M_QAT); + return stat; +} + +static int +qat_hal_put_rel_rd_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int val) +{ + int status = 0; + unsigned int reg_addr; + unsigned int ctx_enables; + unsigned short mask; + unsigned short dr_offset = 0x10; + + status = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + if (CE_INUSE_CONTEXTS & ctx_enables) { + if (ctx & 0x1) { + pr_err("QAT: bad 4-ctx mode,ctx=0x%x\n", ctx); + return EINVAL; + } + mask = 0x1f; + dr_offset = 0x20; + } else { + mask = 0x0f; + } + if (reg_num & ~mask) + return EINVAL; + reg_addr = reg_num + (ctx << 0x5); + switch (reg_type) { + case ICP_SR_RD_REL: + case ICP_SR_REL: + SET_AE_XFER(handle, ae, reg_addr, val); + break; + case ICP_DR_RD_REL: + case ICP_DR_REL: + SET_AE_XFER(handle, ae, (reg_addr + dr_offset), val); + break; + default: + status = EINVAL; + break; + } + return status; +} + +static int +qat_hal_put_rel_wr_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int data) +{ + unsigned int gprval, ctx_enables; + unsigned short src_hiaddr, src_lowaddr, gpr_addr, xfr_addr, data16hi, + data16low; + unsigned short reg_mask; + int status = 0; + uint64_t micro_inst[] = { 0x0F440000000ull, + 0x0F040000000ull, + 0x0A000000000ull, + 0x0F0000C0300ull, + 0x0E000010000ull }; + const int num_inst = ARRAY_SIZE(micro_inst), code_off = 1; + const unsigned short gprnum = 0, dly = num_inst * 0x5; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + if (CE_INUSE_CONTEXTS & ctx_enables) { + if (ctx & 0x1) { + pr_err("QAT: 4-ctx mode,ctx=0x%x\n", ctx); + return EINVAL; + } + reg_mask = (unsigned short)~0x1f; + } else { + reg_mask = (unsigned short)~0xf; + } + if (reg_num & reg_mask) + return EINVAL; + xfr_addr = qat_hal_get_reg_addr(reg_type, reg_num); + if (xfr_addr == BAD_REGADDR) { + pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr); + return EINVAL; + } + qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval); + gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum); + data16low = 0xffff & data; + data16hi = 0xffff & (data >> 0x10); + src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST, + (unsigned short)(0xff & data16hi)); + src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST, + (unsigned short)(0xff & data16low)); + micro_inst[0] = micro_inst[0x0] | ((data16hi >> 8) << 20) | + ((gpr_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff); + micro_inst[1] = micro_inst[0x1] | ((data16low >> 8) << 20) | + ((gpr_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff); + micro_inst[0x2] = micro_inst[0x2] | ((xfr_addr & 0x3ff) << 20) | + ((gpr_addr & 0x3ff) << 10); + status = qat_hal_exec_micro_inst( + handle, ae, ctx, micro_inst, num_inst, code_off, dly, NULL); + qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, gprval); + return status; +} + +static int +qat_hal_put_rel_nn(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx, + unsigned short nn, + unsigned int val) +{ + unsigned int ctx_enables; + int stat = 0; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + ctx_enables &= IGNORE_W1C_MASK; + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables | CE_NN_MODE); + + stat = qat_hal_put_rel_wr_xfer(handle, ae, ctx, ICP_NEIGH_REL, nn, val); + qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables); + return stat; +} + +static int +qat_hal_convert_abs_to_rel(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned short absreg_num, + unsigned short *relreg, + unsigned char *ctx) +{ + unsigned int ctx_enables; + + qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables); + if (ctx_enables & CE_INUSE_CONTEXTS) { + /* 4-ctx mode */ + *relreg = absreg_num & 0x1F; + *ctx = (absreg_num >> 0x4) & 0x6; + } else { + /* 8-ctx mode */ + *relreg = absreg_num & 0x0F; + *ctx = (absreg_num >> 0x4) & 0x7; + } + return 0; +} + +int +qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata) +{ + int stat = 0; + unsigned short reg; + unsigned char ctx = 0; + enum icp_qat_uof_regtype type; + + if (reg_num >= ICP_QAT_UCLO_MAX_GPR_REG) + return EINVAL; + + do { + if (ctx_mask == 0) { + qat_hal_convert_abs_to_rel( + handle, ae, reg_num, ®, &ctx); + type = reg_type - 1; + } else { + reg = reg_num; + type = reg_type; + if (!test_bit(ctx, &ctx_mask)) + continue; + } + stat = qat_hal_wr_rel_reg(handle, ae, ctx, type, reg, regdata); + if (stat) { + pr_err("QAT: write gpr fail\n"); + return EINVAL; + } + } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX)); + + return 0; +} + +int +qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata) +{ + int stat = 0; + unsigned short reg; + unsigned char ctx = 0; + enum icp_qat_uof_regtype type; + + if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG) + return EINVAL; + + do { + if (ctx_mask == 0) { + qat_hal_convert_abs_to_rel( + handle, ae, reg_num, ®, &ctx); + type = reg_type - 3; + } else { + reg = reg_num; + type = reg_type; + if (!test_bit(ctx, &ctx_mask)) + continue; + } + stat = qat_hal_put_rel_wr_xfer( + handle, ae, ctx, type, reg, regdata); + if (stat) { + pr_err("QAT: write wr xfer fail\n"); + return EINVAL; + } + } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX)); + + return 0; +} + +int +qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_num, + unsigned int regdata) +{ + int stat = 0; + unsigned short reg; + unsigned char ctx = 0; + enum icp_qat_uof_regtype type; + + if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG) + return EINVAL; + + do { + if (ctx_mask == 0) { + qat_hal_convert_abs_to_rel( + handle, ae, reg_num, ®, &ctx); + type = reg_type - 3; + } else { + reg = reg_num; + type = reg_type; + if (!test_bit(ctx, &ctx_mask)) + continue; + } + stat = qat_hal_put_rel_rd_xfer( + handle, ae, ctx, type, reg, regdata); + if (stat) { + pr_err("QAT: write rd xfer fail\n"); + return EINVAL; + } + } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX)); + + return 0; +} + +int +qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned long ctx_mask, + unsigned short reg_num, + unsigned int regdata) +{ + int stat = 0; + unsigned char ctx; + + if (ctx_mask == 0) + return EINVAL; + + for_each_set_bit(ctx, &ctx_mask, ICP_QAT_UCLO_MAX_CTX) + { + stat = qat_hal_put_rel_nn(handle, ae, ctx, reg_num, regdata); + if (stat) { + pr_err("QAT: write neigh error\n"); + return EINVAL; + } + } + + return 0; +} diff --git a/sys/dev/qat/qat_common/qat_uclo.c b/sys/dev/qat/qat_common/qat_uclo.c new file mode 100644 index 00000000000..4232fb0ad09 --- /dev/null +++ b/sys/dev/qat/qat_common/qat_uclo.c @@ -0,0 +1,2188 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "icp_qat_uclo.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_init_admin.h" +#include "adf_cfg_strings.h" +#include "adf_transport_access_macros.h" +#include "adf_transport_internal.h" +#include +#include +#include +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "icp_qat_uclo.h" +#include "icp_qat_hal.h" +#include "icp_qat_fw_loader_handle.h" + +#define UWORD_CPYBUF_SIZE 1024 +#define INVLD_UWORD 0xffffffffffull +#define PID_MINOR_REV 0xf +#define PID_MAJOR_REV (0xf << 4) +#define MAX_UINT32_VAL 0xfffffffful + +static int +qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle, + unsigned int ae, + unsigned int image_num) +{ + struct icp_qat_uclo_aedata *ae_data; + struct icp_qat_uclo_encapme *encap_image; + struct icp_qat_uclo_page *page = NULL; + struct icp_qat_uclo_aeslice *ae_slice = NULL; + + ae_data = &obj_handle->ae_data[ae]; + encap_image = &obj_handle->ae_uimage[image_num]; + ae_slice = &ae_data->ae_slices[ae_data->slice_num]; + ae_slice->encap_image = encap_image; + + if (encap_image->img_ptr) { + ae_slice->ctx_mask_assigned = + encap_image->img_ptr->ctx_assigned; + ae_data->shareable_ustore = + ICP_QAT_SHARED_USTORE_MODE(encap_image->img_ptr->ae_mode); + ae_data->eff_ustore_size = ae_data->shareable_ustore ? + (obj_handle->ustore_phy_size << 1) : + obj_handle->ustore_phy_size; + } else { + ae_slice->ctx_mask_assigned = 0; + } + ae_slice->region = + malloc(sizeof(*ae_slice->region), M_QAT, M_WAITOK | M_ZERO); + ae_slice->page = + malloc(sizeof(*ae_slice->page), M_QAT, M_WAITOK | M_ZERO); + page = ae_slice->page; + page->encap_page = encap_image->page; + ae_slice->page->region = ae_slice->region; + ae_data->slice_num++; + return 0; +} + +static int +qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data) +{ + unsigned int i; + + if (!ae_data) { + pr_err("QAT: bad argument, ae_data is NULL\n "); + return EINVAL; + } + + for (i = 0; i < ae_data->slice_num; i++) { + free(ae_data->ae_slices[i].region, M_QAT); + ae_data->ae_slices[i].region = NULL; + free(ae_data->ae_slices[i].page, M_QAT); + ae_data->ae_slices[i].page = NULL; + } + return 0; +} + +static char * +qat_uclo_get_string(struct icp_qat_uof_strtable *str_table, + unsigned int str_offset) +{ + if (!str_table->table_len || str_offset > str_table->table_len) + return NULL; + return (char *)(((uintptr_t)(str_table->strings)) + str_offset); +} + +static int +qat_uclo_check_uof_format(struct icp_qat_uof_filehdr *hdr) +{ + int maj = hdr->maj_ver & 0xff; + int min = hdr->min_ver & 0xff; + + if (hdr->file_id != ICP_QAT_UOF_FID) { + pr_err("QAT: Invalid header 0x%x\n", hdr->file_id); + return EINVAL; + } + if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) { + pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n", + maj, + min); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_check_suof_format(const struct icp_qat_suof_filehdr *suof_hdr) +{ + int maj = suof_hdr->maj_ver & 0xff; + int min = suof_hdr->min_ver & 0xff; + + if (suof_hdr->file_id != ICP_QAT_SUOF_FID) { + pr_err("QAT: invalid header 0x%x\n", suof_hdr->file_id); + return EINVAL; + } + if (suof_hdr->fw_type != 0) { + pr_err("QAT: unsupported firmware type\n"); + return EINVAL; + } + if (suof_hdr->num_chunks <= 0x1) { + pr_err("QAT: SUOF chunk amount is incorrect\n"); + return EINVAL; + } + if (maj != ICP_QAT_SUOF_MAJVER || min != ICP_QAT_SUOF_MINVER) { + pr_err("QAT: bad SUOF version, major 0x%x, minor 0x%x\n", + maj, + min); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle, + unsigned int addr, + const unsigned int *val, + unsigned int num_in_bytes) +{ + unsigned int outval; + const unsigned char *ptr = (const unsigned char *)val; + + if (num_in_bytes > handle->hal_sram_size) { + pr_err("QAT: error, mmp size overflow %d\n", num_in_bytes); + return EINVAL; + } + while (num_in_bytes) { + memcpy(&outval, ptr, 4); + SRAM_WRITE(handle, addr, outval); + num_in_bytes -= 4; + ptr += 4; + addr += 4; + } + return 0; +} + +static void +qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned int addr, + unsigned int *val, + unsigned int num_in_bytes) +{ + unsigned int outval; + unsigned char *ptr = (unsigned char *)val; + + addr >>= 0x2; /* convert to uword address */ + + while (num_in_bytes) { + memcpy(&outval, ptr, 4); + qat_hal_wr_umem(handle, ae, addr++, 1, &outval); + num_in_bytes -= 4; + ptr += 4; + } +} + +static void +qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + struct icp_qat_uof_batch_init *umem_init_header) +{ + struct icp_qat_uof_batch_init *umem_init; + + if (!umem_init_header) + return; + umem_init = umem_init_header->next; + while (umem_init) { + unsigned int addr, *value, size; + + ae = umem_init->ae; + addr = umem_init->addr; + value = umem_init->value; + size = umem_init->size; + qat_uclo_wr_umem_by_words(handle, ae, addr, value, size); + umem_init = umem_init->next; + } +} + +static void +qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_batch_init **base) +{ + struct icp_qat_uof_batch_init *umem_init; + + umem_init = *base; + while (umem_init) { + struct icp_qat_uof_batch_init *pre; + + pre = umem_init; + umem_init = umem_init->next; + free(pre, M_QAT); + } + *base = NULL; +} + +static int +qat_uclo_parse_num(char *str, unsigned int *num) +{ + char buf[16] = { 0 }; + unsigned long ae = 0; + int i; + + strncpy(buf, str, 15); + for (i = 0; i < 16; i++) { + if (!isdigit(buf[i])) { + buf[i] = '\0'; + break; + } + } + if ((compat_strtoul(buf, 10, &ae))) + return EFAULT; + + if (ae > MAX_UINT32_VAL) + return EFAULT; + + *num = (unsigned int)ae; + return 0; +} + +static int +qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_initmem *init_mem, + unsigned int size_range, + unsigned int *ae) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + char *str; + + if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) { + pr_err("QAT: initmem is out of range"); + return EINVAL; + } + if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) { + pr_err("QAT: Memory scope for init_mem error\n"); + return EINVAL; + } + str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name); + if (!str) { + pr_err("QAT: AE name assigned in UOF init table is NULL\n"); + return EINVAL; + } + if (qat_uclo_parse_num(str, ae)) { + pr_err("QAT: Parse num for AE number failed\n"); + return EINVAL; + } + if (*ae >= ICP_QAT_UCLO_MAX_AE) { + pr_err("QAT: ae %d out of range\n", *ae); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_initmem *init_mem, + unsigned int ae, + struct icp_qat_uof_batch_init **init_tab_base) +{ + struct icp_qat_uof_batch_init *init_header, *tail; + struct icp_qat_uof_batch_init *mem_init, *tail_old; + struct icp_qat_uof_memvar_attr *mem_val_attr; + unsigned int i = 0; + + mem_val_attr = + (struct icp_qat_uof_memvar_attr *)((uintptr_t)init_mem + + sizeof( + struct icp_qat_uof_initmem)); + + init_header = *init_tab_base; + if (!init_header) { + init_header = + malloc(sizeof(*init_header), M_QAT, M_WAITOK | M_ZERO); + init_header->size = 1; + *init_tab_base = init_header; + } + tail_old = init_header; + while (tail_old->next) + tail_old = tail_old->next; + tail = tail_old; + for (i = 0; i < init_mem->val_attr_num; i++) { + mem_init = malloc(sizeof(*mem_init), M_QAT, M_WAITOK | M_ZERO); + mem_init->ae = ae; + mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte; + mem_init->value = &mem_val_attr->value; + mem_init->size = 4; + mem_init->next = NULL; + tail->next = mem_init; + tail = mem_init; + init_header->size += qat_hal_get_ins_num(); + mem_val_attr++; + } + return 0; +} + +static int +qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_initmem *init_mem) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int ae; + + if (qat_uclo_fetch_initmem_ae( + handle, init_mem, ICP_QAT_UCLO_MAX_LMEM_REG, &ae)) + return EINVAL; + if (qat_uclo_create_batch_init_list( + handle, init_mem, ae, &obj_handle->lm_init_tab[ae])) + return EINVAL; + return 0; +} + +static int +qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_initmem *init_mem) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int ae, ustore_size, uaddr, i; + struct icp_qat_uclo_aedata *aed; + + ustore_size = obj_handle->ustore_phy_size; + if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae)) + return EINVAL; + if (qat_uclo_create_batch_init_list( + handle, init_mem, ae, &obj_handle->umem_init_tab[ae])) + return EINVAL; + /* set the highest ustore address referenced */ + uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2; + aed = &obj_handle->ae_data[ae]; + for (i = 0; i < aed->slice_num; i++) { + if (aed->ae_slices[i].encap_image->uwords_num < uaddr) + aed->ae_slices[i].encap_image->uwords_num = uaddr; + } + return 0; +} + +#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000 +static int +qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_initmem *init_mem) +{ + switch (init_mem->region) { + case ICP_QAT_UOF_LMEM_REGION: + if (qat_uclo_init_lmem_seg(handle, init_mem)) + return EINVAL; + break; + case ICP_QAT_UOF_UMEM_REGION: + if (qat_uclo_init_umem_seg(handle, init_mem)) + return EINVAL; + break; + default: + pr_err("QAT: initmem region error. region type=0x%x\n", + init_mem->region); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uclo_encapme *image) +{ + unsigned int i; + struct icp_qat_uclo_encap_page *page; + struct icp_qat_uof_image *uof_image; + unsigned char ae = 0; + unsigned char neigh_ae; + unsigned int ustore_size; + unsigned int patt_pos; + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + uint64_t *fill_data; + static unsigned int init[32] = { 0 }; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + uof_image = image->img_ptr; + /*if shared CS mode, the ustore size should be 2*ustore_phy_size*/ + fill_data = malloc(obj_handle->ustore_phy_size * 2 * sizeof(uint64_t), + M_QAT, + M_WAITOK | M_ZERO); + for (i = 0; i < obj_handle->ustore_phy_size * 2; i++) + memcpy(&fill_data[i], + &uof_image->fill_pattern, + sizeof(uint64_t)); + page = image->page; + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + unsigned long cfg_ae_mask = handle->cfg_ae_mask; + unsigned long ae_assigned = uof_image->ae_assigned; + + if (!test_bit(ae, &cfg_ae_mask)) + continue; + + if (!test_bit(ae, &ae_assigned)) + continue; + + if (obj_handle->ae_data[ae].shareable_ustore && (ae & 1)) { + qat_hal_get_scs_neigh_ae(ae, &neigh_ae); + + if (test_bit(neigh_ae, &ae_assigned)) + continue; + } + + ustore_size = obj_handle->ae_data[ae].eff_ustore_size; + patt_pos = page->beg_addr_p + page->micro_words_num; + if (obj_handle->ae_data[ae].shareable_ustore) { + qat_hal_get_scs_neigh_ae(ae, &neigh_ae); + if (init[ae] == 0 && page->beg_addr_p != 0) { + qat_hal_wr_coalesce_uwords(handle, + (unsigned char)ae, + 0, + page->beg_addr_p, + &fill_data[0]); + } + qat_hal_wr_coalesce_uwords( + handle, + (unsigned char)ae, + patt_pos, + ustore_size - patt_pos, + &fill_data[page->beg_addr_p]); + init[ae] = 1; + init[neigh_ae] = 1; + } else { + qat_hal_wr_uwords(handle, + (unsigned char)ae, + 0, + page->beg_addr_p, + &fill_data[0]); + qat_hal_wr_uwords(handle, + (unsigned char)ae, + patt_pos, + ustore_size - patt_pos + 1, + &fill_data[page->beg_addr_p]); + } + } + free(fill_data, M_QAT); + return 0; +} + +static int +qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle) +{ + int i; + int ae = 0; + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) { + if (initmem->num_in_bytes) { + if (qat_uclo_init_ae_memory(handle, initmem)) + return EINVAL; + } + initmem = + (struct icp_qat_uof_initmem + *)((uintptr_t)((uintptr_t)initmem + + sizeof(struct icp_qat_uof_initmem)) + + (sizeof(struct icp_qat_uof_memvar_attr) * + initmem->val_attr_num)); + } + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + if (qat_hal_batch_wr_lm(handle, + ae, + obj_handle->lm_init_tab[ae])) { + pr_err("QAT: fail to batch init lmem for AE %d\n", ae); + return EINVAL; + } + qat_uclo_cleanup_batch_init_list(handle, + &obj_handle->lm_init_tab[ae]); + qat_uclo_batch_wr_umem(handle, + ae, + obj_handle->umem_init_tab[ae]); + qat_uclo_cleanup_batch_init_list( + handle, &obj_handle->umem_init_tab[ae]); + } + return 0; +} + +static void * +qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr, + char *chunk_id, + void *cur) +{ + int i; + struct icp_qat_uof_chunkhdr *chunk_hdr = + (struct icp_qat_uof_chunkhdr *)((uintptr_t)obj_hdr + + sizeof(struct icp_qat_uof_objhdr)); + + for (i = 0; i < obj_hdr->num_chunks; i++) { + if ((cur < (void *)&chunk_hdr[i]) && + !strncmp(chunk_hdr[i].chunk_id, + chunk_id, + ICP_QAT_UOF_OBJID_LEN)) { + return &chunk_hdr[i]; + } + } + return NULL; +} + +static unsigned int +qat_uclo_calc_checksum(unsigned int reg, int ch) +{ + int i; + unsigned int topbit = 1 << 0xF; + unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch); + + reg ^= inbyte << 0x8; + for (i = 0; i < 0x8; i++) { + if (reg & topbit) + reg = (reg << 1) ^ 0x1021; + else + reg <<= 1; + } + return reg & 0xFFFF; +} + +static unsigned int +qat_uclo_calc_str_checksum(const char *ptr, int num) +{ + unsigned int chksum = 0; + + if (ptr) + while (num--) + chksum = qat_uclo_calc_checksum(chksum, *ptr++); + return chksum; +} + +static struct icp_qat_uclo_objhdr * +qat_uclo_map_chunk(char *buf, + struct icp_qat_uof_filehdr *file_hdr, + char *chunk_id) +{ + struct icp_qat_uof_filechunkhdr *file_chunk; + struct icp_qat_uclo_objhdr *obj_hdr; + char *chunk; + int i; + + file_chunk = (struct icp_qat_uof_filechunkhdr + *)(buf + sizeof(struct icp_qat_uof_filehdr)); + for (i = 0; i < file_hdr->num_chunks; i++) { + if (!strncmp(file_chunk->chunk_id, + chunk_id, + ICP_QAT_UOF_OBJID_LEN)) { + chunk = buf + file_chunk->offset; + if (file_chunk->checksum != + qat_uclo_calc_str_checksum(chunk, file_chunk->size)) + break; + obj_hdr = + malloc(sizeof(*obj_hdr), M_QAT, M_WAITOK | M_ZERO); + obj_hdr->file_buff = chunk; + obj_hdr->checksum = file_chunk->checksum; + obj_hdr->size = file_chunk->size; + return obj_hdr; + } + file_chunk++; + } + return NULL; +} + +static unsigned int +qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj, + struct icp_qat_uof_image *image) +{ + struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab; + struct icp_qat_uof_objtable *neigh_reg_tab; + struct icp_qat_uof_code_page *code_page; + + code_page = + (struct icp_qat_uof_code_page *)((char *)image + + sizeof(struct icp_qat_uof_image)); + uc_var_tab = + (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof + + code_page->uc_var_tab_offset); + imp_var_tab = + (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof + + code_page->imp_var_tab_offset); + imp_expr_tab = + (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof + + code_page->imp_expr_tab_offset); + if (uc_var_tab->entry_num || imp_var_tab->entry_num || + imp_expr_tab->entry_num) { + pr_err("QAT: UOF can't contain imported variable to be parsed"); + return EINVAL; + } + neigh_reg_tab = + (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof + + code_page->neigh_reg_tab_offset); + if (neigh_reg_tab->entry_num) { + pr_err("QAT: UOF can't contain neighbor register table\n"); + return EINVAL; + } + if (image->numpages > 1) { + pr_err("QAT: UOF can't contain multiple pages\n"); + return EINVAL; + } + if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) { + pr_err("QAT: UOF can't use reloadable feature\n"); + return EFAULT; + } + return 0; +} + +static void +qat_uclo_map_image_page(struct icp_qat_uof_encap_obj *encap_uof_obj, + struct icp_qat_uof_image *img, + struct icp_qat_uclo_encap_page *page) +{ + struct icp_qat_uof_code_page *code_page; + struct icp_qat_uof_code_area *code_area; + struct icp_qat_uof_objtable *uword_block_tab; + struct icp_qat_uof_uword_block *uwblock; + int i; + + code_page = + (struct icp_qat_uof_code_page *)((char *)img + + sizeof(struct icp_qat_uof_image)); + page->def_page = code_page->def_page; + page->page_region = code_page->page_region; + page->beg_addr_v = code_page->beg_addr_v; + page->beg_addr_p = code_page->beg_addr_p; + code_area = + (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof + + code_page->code_area_offset); + page->micro_words_num = code_area->micro_words_num; + uword_block_tab = + (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof + + code_area->uword_block_tab); + page->uwblock_num = uword_block_tab->entry_num; + uwblock = (struct icp_qat_uof_uword_block + *)((char *)uword_block_tab + + sizeof(struct icp_qat_uof_objtable)); + page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock; + for (i = 0; i < uword_block_tab->entry_num; i++) + page->uwblock[i].micro_words = + (uintptr_t)encap_uof_obj->beg_uof + uwblock[i].uword_offset; +} + +static int +qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle, + struct icp_qat_uclo_encapme *ae_uimage, + int max_image) +{ + int i, j; + struct icp_qat_uof_chunkhdr *chunk_hdr = NULL; + struct icp_qat_uof_image *image; + struct icp_qat_uof_objtable *ae_regtab; + struct icp_qat_uof_objtable *init_reg_sym_tab; + struct icp_qat_uof_objtable *sbreak_tab; + struct icp_qat_uof_encap_obj *encap_uof_obj = + &obj_handle->encap_uof_obj; + + for (j = 0; j < max_image; j++) { + chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr, + ICP_QAT_UOF_IMAG, + chunk_hdr); + if (!chunk_hdr) + break; + image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof + + chunk_hdr->offset); + ae_regtab = + (struct icp_qat_uof_objtable *)(image->reg_tab_offset + + obj_handle->obj_hdr + ->file_buff); + ae_uimage[j].ae_reg_num = ae_regtab->entry_num; + ae_uimage[j].ae_reg = + (struct icp_qat_uof_ae_reg + *)(((char *)ae_regtab) + + sizeof(struct icp_qat_uof_objtable)); + init_reg_sym_tab = + (struct icp_qat_uof_objtable *)(image->init_reg_sym_tab + + obj_handle->obj_hdr + ->file_buff); + ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num; + ae_uimage[j].init_regsym = + (struct icp_qat_uof_init_regsym + *)(((char *)init_reg_sym_tab) + + sizeof(struct icp_qat_uof_objtable)); + sbreak_tab = (struct icp_qat_uof_objtable *)(image->sbreak_tab + + obj_handle->obj_hdr + ->file_buff); + ae_uimage[j].sbreak_num = sbreak_tab->entry_num; + ae_uimage[j].sbreak = + (struct icp_qat_uof_sbreak + *)(((char *)sbreak_tab) + + sizeof(struct icp_qat_uof_objtable)); + ae_uimage[j].img_ptr = image; + if (qat_uclo_check_image_compat(encap_uof_obj, image)) + goto out_err; + ae_uimage[j].page = + malloc(sizeof(struct icp_qat_uclo_encap_page), + M_QAT, + M_WAITOK | M_ZERO); + qat_uclo_map_image_page(encap_uof_obj, + image, + ae_uimage[j].page); + } + return j; +out_err: + for (i = 0; i < j; i++) + free(ae_uimage[i].page, M_QAT); + return 0; +} + +static int +qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae) +{ + int i; + int ae = 0; + unsigned long ae_mask = handle->hal_handle->ae_mask; + unsigned long cfg_ae_mask = handle->cfg_ae_mask; + int mflag = 0; + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + + for_each_set_bit(ae, &ae_mask, max_ae) + { + if (!test_bit(ae, &cfg_ae_mask)) + continue; + + for (i = 0; i < obj_handle->uimage_num; i++) { + unsigned long ae_assigned = + obj_handle->ae_uimage[i].img_ptr->ae_assigned; + if (!test_bit(ae, &ae_assigned)) + continue; + mflag = 1; + if (qat_uclo_init_ae_data(obj_handle, ae, i)) + return EINVAL; + } + } + if (!mflag) { + pr_err("QAT: uimage uses AE not set"); + return EINVAL; + } + return 0; +} + +static struct icp_qat_uof_strtable * +qat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr, + char *tab_name, + struct icp_qat_uof_strtable *str_table) +{ + struct icp_qat_uof_chunkhdr *chunk_hdr; + + chunk_hdr = + qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)obj_hdr->file_buff, + tab_name, + NULL); + if (chunk_hdr) { + int hdr_size; + + memcpy(&str_table->table_len, + obj_hdr->file_buff + chunk_hdr->offset, + sizeof(str_table->table_len)); + hdr_size = (char *)&str_table->strings - (char *)str_table; + str_table->strings = (uintptr_t)obj_hdr->file_buff + + chunk_hdr->offset + hdr_size; + return str_table; + } + return NULL; +} + +static void +qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj, + struct icp_qat_uclo_init_mem_table *init_mem_tab) +{ + struct icp_qat_uof_chunkhdr *chunk_hdr; + + chunk_hdr = + qat_uclo_find_chunk(encap_uof_obj->obj_hdr, ICP_QAT_UOF_IMEM, NULL); + if (chunk_hdr) { + memmove(&init_mem_tab->entry_num, + encap_uof_obj->beg_uof + chunk_hdr->offset, + sizeof(unsigned int)); + init_mem_tab->init_mem = + (struct icp_qat_uof_initmem *)(encap_uof_obj->beg_uof + + chunk_hdr->offset + + sizeof(unsigned int)); + } +} + +static unsigned int +qat_uclo_get_dev_type(struct icp_qat_fw_loader_handle *handle) +{ + switch (pci_get_device(GET_DEV(handle->accel_dev))) { + case ADF_DH895XCC_PCI_DEVICE_ID: + return ICP_QAT_AC_895XCC_DEV_TYPE; + case ADF_C62X_PCI_DEVICE_ID: + return ICP_QAT_AC_C62X_DEV_TYPE; + case ADF_C3XXX_PCI_DEVICE_ID: + return ICP_QAT_AC_C3XXX_DEV_TYPE; + case ADF_200XX_PCI_DEVICE_ID: + return ICP_QAT_AC_200XX_DEV_TYPE; + case ADF_C4XXX_PCI_DEVICE_ID: + return ICP_QAT_AC_C4XXX_DEV_TYPE; + default: + pr_err("QAT: unsupported device 0x%x\n", + pci_get_device(GET_DEV(handle->accel_dev))); + return 0; + } +} + +static int +qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle) +{ + unsigned int maj_ver, prod_type = obj_handle->prod_type; + + if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->ac_dev_type)) { + pr_err("QAT: UOF type 0x%x doesn't match with platform 0x%x\n", + obj_handle->encap_uof_obj.obj_hdr->ac_dev_type, + prod_type); + return EINVAL; + } + maj_ver = obj_handle->prod_rev & 0xff; + if (obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver || + obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver) { + pr_err("QAT: UOF maj_ver 0x%x out of range\n", maj_ver); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle, + unsigned char ae, + unsigned char ctx_mask, + enum icp_qat_uof_regtype reg_type, + unsigned short reg_addr, + unsigned int value) +{ + switch (reg_type) { + case ICP_GPA_ABS: + case ICP_GPB_ABS: + ctx_mask = 0; + return qat_hal_init_gpr( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_GPA_REL: + case ICP_GPB_REL: + return qat_hal_init_gpr( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_SR_ABS: + case ICP_DR_ABS: + case ICP_SR_RD_ABS: + case ICP_DR_RD_ABS: + ctx_mask = 0; + return qat_hal_init_rd_xfer( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_SR_REL: + case ICP_DR_REL: + case ICP_SR_RD_REL: + case ICP_DR_RD_REL: + return qat_hal_init_rd_xfer( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_SR_WR_ABS: + case ICP_DR_WR_ABS: + ctx_mask = 0; + return qat_hal_init_wr_xfer( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_SR_WR_REL: + case ICP_DR_WR_REL: + return qat_hal_init_wr_xfer( + handle, ae, ctx_mask, reg_type, reg_addr, value); + case ICP_NEIGH_REL: + return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value); + default: + pr_err("QAT: UOF uses unsupported reg type 0x%x\n", reg_type); + return EFAULT; + } + return 0; +} + +static int +qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle, + unsigned int ae, + struct icp_qat_uclo_encapme *encap_ae) +{ + unsigned int i; + unsigned char ctx_mask; + struct icp_qat_uof_init_regsym *init_regsym; + + if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) == + ICP_QAT_UCLO_MAX_CTX) + ctx_mask = 0xff; + else + ctx_mask = 0x55; + + for (i = 0; i < encap_ae->init_regsym_num; i++) { + unsigned int exp_res; + + init_regsym = &encap_ae->init_regsym[i]; + exp_res = init_regsym->value; + switch (init_regsym->init_type) { + case ICP_QAT_UOF_INIT_REG: + qat_uclo_init_reg(handle, + ae, + ctx_mask, + (enum icp_qat_uof_regtype) + init_regsym->reg_type, + (unsigned short)init_regsym->reg_addr, + exp_res); + break; + case ICP_QAT_UOF_INIT_REG_CTX: + /* check if ctx is appropriate for the ctxMode */ + if (!((1 << init_regsym->ctx) & ctx_mask)) { + pr_err("QAT: invalid ctx num = 0x%x\n", + init_regsym->ctx); + return EINVAL; + } + qat_uclo_init_reg( + handle, + ae, + (unsigned char)(1 << init_regsym->ctx), + (enum icp_qat_uof_regtype)init_regsym->reg_type, + (unsigned short)init_regsym->reg_addr, + exp_res); + break; + case ICP_QAT_UOF_INIT_EXPR: + pr_err("QAT: INIT_EXPR feature not supported\n"); + return EINVAL; + case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP: + pr_err("QAT: INIT_EXPR_ENDIAN_SWAP not supported\n"); + return EINVAL; + default: + break; + } + } + return 0; +} + +static int +qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int s; + unsigned int ae = 0; + struct icp_qat_uclo_aedata *aed; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + if (obj_handle->global_inited) + return 0; + if (obj_handle->init_mem_tab.entry_num) { + if (qat_uclo_init_memory(handle)) { + pr_err("QAT: initialize memory failed\n"); + return EINVAL; + } + } + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + aed = &obj_handle->ae_data[ae]; + for (s = 0; s < aed->slice_num; s++) { + if (!aed->ae_slices[s].encap_image) + continue; + if (qat_uclo_init_reg_sym( + handle, ae, aed->ae_slices[s].encap_image)) + return EINVAL; + } + } + obj_handle->global_inited = 1; + return 0; +} + +static int +qat_hal_set_modes(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uclo_objhandle *obj_handle, + unsigned char ae, + struct icp_qat_uof_image *uof_image) +{ + unsigned char nn_mode; + char ae_mode = 0; + + ae_mode = (char)ICP_QAT_CTX_MODE(uof_image->ae_mode); + if (qat_hal_set_ae_ctx_mode(handle, ae, ae_mode)) { + pr_err("QAT: qat_hal_set_ae_ctx_mode error\n"); + return EFAULT; + } + + ae_mode = (char)ICP_QAT_SHARED_USTORE_MODE(uof_image->ae_mode); + qat_hal_set_ae_scs_mode(handle, ae, ae_mode); + nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode); + + if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) { + pr_err("QAT: qat_hal_set_ae_nn_mode error\n"); + return EFAULT; + } + ae_mode = (char)ICP_QAT_LOC_MEM0_MODE(uof_image->ae_mode); + if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0, ae_mode)) { + pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n"); + return EFAULT; + } + ae_mode = (char)ICP_QAT_LOC_MEM1_MODE(uof_image->ae_mode); + if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1, ae_mode)) { + pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n"); + return EFAULT; + } + if (obj_handle->prod_type == ICP_QAT_AC_C4XXX_DEV_TYPE) { + ae_mode = (char)ICP_QAT_LOC_MEM2_MODE(uof_image->ae_mode); + if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM2, ae_mode)) { + pr_err("QAT: qat_hal_set_ae_lm_mode LMEM2 error\n"); + return EFAULT; + } + ae_mode = (char)ICP_QAT_LOC_MEM3_MODE(uof_image->ae_mode); + if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM3, ae_mode)) { + pr_err("QAT: qat_hal_set_ae_lm_mode LMEM3 error\n"); + return EFAULT; + } + ae_mode = (char)ICP_QAT_LOC_TINDEX_MODE(uof_image->ae_mode); + qat_hal_set_ae_tindex_mode(handle, ae, ae_mode); + } + return 0; +} + +static int +qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle) +{ + int error; + unsigned char s; + unsigned char ae = 0; + struct icp_qat_uof_image *uof_image; + struct icp_qat_uclo_aedata *ae_data; + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + unsigned long cfg_ae_mask = handle->cfg_ae_mask; + + if (!test_bit(ae, &cfg_ae_mask)) + continue; + + ae_data = &obj_handle->ae_data[ae]; + for (s = 0; s < min_t(unsigned int, + ae_data->slice_num, + ICP_QAT_UCLO_MAX_CTX); + s++) { + if (!obj_handle->ae_data[ae].ae_slices[s].encap_image) + continue; + uof_image = ae_data->ae_slices[s].encap_image->img_ptr; + error = qat_hal_set_modes(handle, + obj_handle, + ae, + uof_image); + if (error) + return error; + } + } + return 0; +} + +static void +qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + struct icp_qat_uclo_encapme *image; + int a; + + for (a = 0; a < obj_handle->uimage_num; a++) { + image = &obj_handle->ae_uimage[a]; + image->uwords_num = + image->page->beg_addr_p + image->page->micro_words_num; + } +} + +static int +qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int ae; + + obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff; + obj_handle->encap_uof_obj.obj_hdr = + (struct icp_qat_uof_objhdr *)obj_handle->obj_hdr->file_buff; + obj_handle->uword_in_bytes = 6; + obj_handle->prod_type = qat_uclo_get_dev_type(handle); + obj_handle->prod_rev = + PID_MAJOR_REV | (PID_MINOR_REV & handle->hal_handle->revision_id); + if (qat_uclo_check_uof_compat(obj_handle)) { + pr_err("QAT: UOF incompatible\n"); + return EINVAL; + } + obj_handle->uword_buf = malloc(UWORD_CPYBUF_SIZE * sizeof(uint64_t), + M_QAT, + M_WAITOK | M_ZERO); + obj_handle->ustore_phy_size = + (obj_handle->prod_type == ICP_QAT_AC_C4XXX_DEV_TYPE) ? 0x2000 : + 0x4000; + if (!obj_handle->obj_hdr->file_buff || + !qat_uclo_map_str_table(obj_handle->obj_hdr, + ICP_QAT_UOF_STRT, + &obj_handle->str_table)) { + pr_err("QAT: UOF doesn't have effective images\n"); + goto out_err; + } + obj_handle->uimage_num = + qat_uclo_map_uimage(obj_handle, + obj_handle->ae_uimage, + ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX); + if (!obj_handle->uimage_num) + goto out_err; + if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) { + pr_err("QAT: Bad object\n"); + goto out_check_uof_aemask_err; + } + qat_uclo_init_uword_num(handle); + qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj, + &obj_handle->init_mem_tab); + if (qat_uclo_set_ae_mode(handle)) + goto out_check_uof_aemask_err; + return 0; +out_check_uof_aemask_err: + for (ae = 0; ae < obj_handle->uimage_num; ae++) + free(obj_handle->ae_uimage[ae].page, M_QAT); +out_err: + free(obj_handle->uword_buf, M_QAT); + obj_handle->uword_buf = NULL; + return EFAULT; +} + +static int +qat_uclo_map_suof_file_hdr(const struct icp_qat_fw_loader_handle *handle, + const struct icp_qat_suof_filehdr *suof_ptr, + int suof_size) +{ + unsigned int check_sum = 0; + unsigned int min_ver_offset = 0; + struct icp_qat_suof_handle *suof_handle = handle->sobj_handle; + + suof_handle->file_id = ICP_QAT_SUOF_FID; + suof_handle->suof_buf = (const char *)suof_ptr; + suof_handle->suof_size = suof_size; + min_ver_offset = + suof_size - offsetof(struct icp_qat_suof_filehdr, min_ver); + check_sum = qat_uclo_calc_str_checksum((const char *)&suof_ptr->min_ver, + min_ver_offset); + if (check_sum != suof_ptr->check_sum) { + pr_err("QAT: incorrect SUOF checksum\n"); + return EINVAL; + } + suof_handle->check_sum = suof_ptr->check_sum; + suof_handle->min_ver = suof_ptr->min_ver; + suof_handle->maj_ver = suof_ptr->maj_ver; + suof_handle->fw_type = suof_ptr->fw_type; + return 0; +} + +static void +qat_uclo_map_simg(struct icp_qat_suof_handle *suof_handle, + struct icp_qat_suof_img_hdr *suof_img_hdr, + struct icp_qat_suof_chunk_hdr *suof_chunk_hdr) +{ + const struct icp_qat_simg_ae_mode *ae_mode; + struct icp_qat_suof_objhdr *suof_objhdr; + + suof_img_hdr->simg_buf = + (suof_handle->suof_buf + suof_chunk_hdr->offset + + sizeof(*suof_objhdr)); + suof_img_hdr->simg_len = + ((struct icp_qat_suof_objhdr *)(uintptr_t)(suof_handle->suof_buf + + suof_chunk_hdr->offset)) + ->img_length; + + suof_img_hdr->css_header = suof_img_hdr->simg_buf; + suof_img_hdr->css_key = + (suof_img_hdr->css_header + sizeof(struct icp_qat_css_hdr)); + suof_img_hdr->css_signature = suof_img_hdr->css_key + + ICP_QAT_CSS_FWSK_MODULUS_LEN + ICP_QAT_CSS_FWSK_EXPONENT_LEN; + suof_img_hdr->css_simg = + suof_img_hdr->css_signature + ICP_QAT_CSS_SIGNATURE_LEN; + + ae_mode = (const struct icp_qat_simg_ae_mode *)(suof_img_hdr->css_simg); + suof_img_hdr->ae_mask = ae_mode->ae_mask; + suof_img_hdr->simg_name = (unsigned long)&ae_mode->simg_name; + suof_img_hdr->appmeta_data = (unsigned long)&ae_mode->appmeta_data; + suof_img_hdr->fw_type = ae_mode->fw_type; +} + +static void +qat_uclo_map_suof_symobjs(struct icp_qat_suof_handle *suof_handle, + struct icp_qat_suof_chunk_hdr *suof_chunk_hdr) +{ + char **sym_str = (char **)&suof_handle->sym_str; + unsigned int *sym_size = &suof_handle->sym_size; + struct icp_qat_suof_strtable *str_table_obj; + + *sym_size = *(unsigned int *)(uintptr_t)(suof_chunk_hdr->offset + + suof_handle->suof_buf); + *sym_str = + (char *)(uintptr_t)(suof_handle->suof_buf + suof_chunk_hdr->offset + + sizeof(str_table_obj->tab_length)); +} + +static int +qat_uclo_check_simg_compat(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_suof_img_hdr *img_hdr) +{ + const struct icp_qat_simg_ae_mode *img_ae_mode = NULL; + unsigned int prod_rev, maj_ver, prod_type; + + prod_type = qat_uclo_get_dev_type(handle); + img_ae_mode = (const struct icp_qat_simg_ae_mode *)img_hdr->css_simg; + prod_rev = + PID_MAJOR_REV | (PID_MINOR_REV & handle->hal_handle->revision_id); + if (img_ae_mode->dev_type != prod_type) { + pr_err("QAT: incompatible product type %x\n", + img_ae_mode->dev_type); + return EINVAL; + } + maj_ver = prod_rev & 0xff; + if (maj_ver > img_ae_mode->devmax_ver || + maj_ver < img_ae_mode->devmin_ver) { + pr_err("QAT: incompatible device maj_ver 0x%x\n", maj_ver); + return EINVAL; + } + return 0; +} + +static void +qat_uclo_del_suof(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle; + + free(sobj_handle->img_table.simg_hdr, M_QAT); + sobj_handle->img_table.simg_hdr = NULL; + free(handle->sobj_handle, M_QAT); + handle->sobj_handle = NULL; +} + +static void +qat_uclo_tail_img(struct icp_qat_suof_img_hdr *suof_img_hdr, + unsigned int img_id, + unsigned int num_simgs) +{ + struct icp_qat_suof_img_hdr img_header; + + if ((img_id != num_simgs - 1) && img_id != ICP_QAT_UCLO_MAX_AE) { + memcpy(&img_header, + &suof_img_hdr[num_simgs - 1], + sizeof(*suof_img_hdr)); + memcpy(&suof_img_hdr[num_simgs - 1], + &suof_img_hdr[img_id], + sizeof(*suof_img_hdr)); + memcpy(&suof_img_hdr[img_id], + &img_header, + sizeof(*suof_img_hdr)); + } +} + +static int +qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle, + const struct icp_qat_suof_filehdr *suof_ptr, + int suof_size) +{ + struct icp_qat_suof_handle *suof_handle = handle->sobj_handle; + struct icp_qat_suof_chunk_hdr *suof_chunk_hdr = NULL; + struct icp_qat_suof_img_hdr *suof_img_hdr = NULL; + int ret = 0, ae0_img = ICP_QAT_UCLO_MAX_AE; + unsigned int i = 0; + struct icp_qat_suof_img_hdr img_header; + + if (!suof_ptr || suof_size == 0) { + pr_err("QAT: input parameter SUOF pointer/size is NULL\n"); + return EINVAL; + } + if (qat_uclo_check_suof_format(suof_ptr)) + return EINVAL; + ret = qat_uclo_map_suof_file_hdr(handle, suof_ptr, suof_size); + if (ret) + return ret; + suof_chunk_hdr = (struct icp_qat_suof_chunk_hdr *)((uintptr_t)suof_ptr + + sizeof(*suof_ptr)); + + qat_uclo_map_suof_symobjs(suof_handle, suof_chunk_hdr); + suof_handle->img_table.num_simgs = suof_ptr->num_chunks - 1; + + if (suof_handle->img_table.num_simgs != 0) { + suof_img_hdr = malloc(suof_handle->img_table.num_simgs * + sizeof(img_header), + M_QAT, + M_WAITOK | M_ZERO); + suof_handle->img_table.simg_hdr = suof_img_hdr; + } + + for (i = 0; i < suof_handle->img_table.num_simgs; i++) { + qat_uclo_map_simg(handle->sobj_handle, + &suof_img_hdr[i], + &suof_chunk_hdr[1 + i]); + ret = qat_uclo_check_simg_compat(handle, &suof_img_hdr[i]); + if (ret) + return ret; + suof_img_hdr[i].ae_mask &= handle->cfg_ae_mask; + if ((suof_img_hdr[i].ae_mask & 0x1) != 0) + ae0_img = i; + } + qat_uclo_tail_img(suof_img_hdr, + ae0_img, + suof_handle->img_table.num_simgs); + return 0; +} + +#define ADD_ADDR(high, low) ((((uint64_t)high) << 32) + (low)) +#define BITS_IN_DWORD 32 + +static int +qat_uclo_auth_fw(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_fw_auth_desc *desc) +{ + unsigned int fcu_sts, mem_cfg_err, retry = 0; + unsigned int fcu_ctl_csr, fcu_sts_csr; + unsigned int fcu_dram_hi_csr, fcu_dram_lo_csr; + u64 bus_addr; + + bus_addr = ADD_ADDR(desc->css_hdr_high, desc->css_hdr_low) - + sizeof(struct icp_qat_auth_chunk); + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + fcu_ctl_csr = FCU_CONTROL_C4XXX; + fcu_sts_csr = FCU_STATUS_C4XXX; + fcu_dram_hi_csr = FCU_DRAM_ADDR_HI_C4XXX; + fcu_dram_lo_csr = FCU_DRAM_ADDR_LO_C4XXX; + } else { + fcu_ctl_csr = FCU_CONTROL; + fcu_sts_csr = FCU_STATUS; + fcu_dram_hi_csr = FCU_DRAM_ADDR_HI; + fcu_dram_lo_csr = FCU_DRAM_ADDR_LO; + } + SET_FCU_CSR(handle, fcu_dram_hi_csr, (bus_addr >> BITS_IN_DWORD)); + SET_FCU_CSR(handle, fcu_dram_lo_csr, bus_addr); + SET_FCU_CSR(handle, fcu_ctl_csr, FCU_CTRL_CMD_AUTH); + + do { + pause_ms("adfstop", FW_AUTH_WAIT_PERIOD); + fcu_sts = GET_FCU_CSR(handle, fcu_sts_csr); + if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_FAIL) + goto auth_fail; + if (((fcu_sts >> FCU_STS_AUTHFWLD_POS) & 0x1)) + if ((fcu_sts & FCU_AUTH_STS_MASK) == FCU_STS_VERI_DONE) + return 0; + } while (retry++ < FW_AUTH_MAX_RETRY); +auth_fail: + pr_err("QAT: authentication error (FCU_STATUS = 0x%x),retry = %d\n", + fcu_sts & FCU_AUTH_STS_MASK, + retry); + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + mem_cfg_err = + (GET_FCU_CSR(handle, FCU_STATUS1_C4XXX) & MEM_CFG_ERR_BIT); + if (mem_cfg_err) + pr_err("QAT: MEM_CFG_ERR\n"); + } + return EINVAL; +} + +static int +qat_uclo_simg_alloc(struct icp_qat_fw_loader_handle *handle, + struct icp_firml_dram_desc *dram_desc, + unsigned int size) +{ + int ret; + + ret = bus_dma_mem_create(&dram_desc->dram_mem, + handle->accel_dev->dma_tag, + 1, + BUS_SPACE_MAXADDR, + size, + 0); + if (ret != 0) + return ret; + dram_desc->dram_base_addr_v = dram_desc->dram_mem.dma_vaddr; + dram_desc->dram_bus_addr = dram_desc->dram_mem.dma_baddr; + dram_desc->dram_size = size; + return 0; +} + +static void +qat_uclo_simg_free(struct icp_qat_fw_loader_handle *handle, + struct icp_firml_dram_desc *dram_desc) +{ + if (handle && dram_desc && dram_desc->dram_base_addr_v) + bus_dma_mem_free(&dram_desc->dram_mem); + + if (dram_desc) + explicit_bzero(dram_desc, sizeof(*dram_desc)); +} + +static int +qat_uclo_map_auth_fw(struct icp_qat_fw_loader_handle *handle, + const char *image, + unsigned int size, + struct icp_firml_dram_desc *img_desc, + struct icp_qat_fw_auth_desc **desc) +{ + const struct icp_qat_css_hdr *css_hdr = + (const struct icp_qat_css_hdr *)image; + struct icp_qat_fw_auth_desc *auth_desc; + struct icp_qat_auth_chunk *auth_chunk; + u64 virt_addr, bus_addr, virt_base; + unsigned int length, simg_offset = sizeof(*auth_chunk); + + if (size > (ICP_QAT_AE_IMG_OFFSET + ICP_QAT_CSS_MAX_IMAGE_LEN)) { + pr_err("QAT: error, input image size overflow %d\n", size); + return EINVAL; + } + length = (css_hdr->fw_type == CSS_AE_FIRMWARE) ? + ICP_QAT_CSS_AE_SIMG_LEN + simg_offset : + size + ICP_QAT_CSS_FWSK_PAD_LEN + simg_offset; + if (qat_uclo_simg_alloc(handle, img_desc, length)) { + pr_err("QAT: error, allocate continuous dram fail\n"); + return -ENOMEM; + } + + auth_chunk = img_desc->dram_base_addr_v; + auth_chunk->chunk_size = img_desc->dram_size; + auth_chunk->chunk_bus_addr = img_desc->dram_bus_addr; + virt_base = (uintptr_t)img_desc->dram_base_addr_v + simg_offset; + bus_addr = img_desc->dram_bus_addr + simg_offset; + auth_desc = img_desc->dram_base_addr_v; + auth_desc->css_hdr_high = (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->css_hdr_low = (unsigned int)bus_addr; + virt_addr = virt_base; + + memcpy((void *)(uintptr_t)virt_addr, image, sizeof(*css_hdr)); + /* pub key */ + bus_addr = ADD_ADDR(auth_desc->css_hdr_high, auth_desc->css_hdr_low) + + sizeof(*css_hdr); + virt_addr = virt_addr + sizeof(*css_hdr); + + auth_desc->fwsk_pub_high = (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->fwsk_pub_low = (unsigned int)bus_addr; + + memcpy((void *)(uintptr_t)virt_addr, + (const void *)(image + sizeof(*css_hdr)), + ICP_QAT_CSS_FWSK_MODULUS_LEN); + /* padding */ + explicit_bzero((void *)(uintptr_t)(virt_addr + + ICP_QAT_CSS_FWSK_MODULUS_LEN), + ICP_QAT_CSS_FWSK_PAD_LEN); + + /* exponent */ + memcpy((void *)(uintptr_t)(virt_addr + ICP_QAT_CSS_FWSK_MODULUS_LEN + + ICP_QAT_CSS_FWSK_PAD_LEN), + (const void *)(image + sizeof(*css_hdr) + + ICP_QAT_CSS_FWSK_MODULUS_LEN), + sizeof(unsigned int)); + + /* signature */ + bus_addr = ADD_ADDR(auth_desc->fwsk_pub_high, auth_desc->fwsk_pub_low) + + ICP_QAT_CSS_FWSK_PUB_LEN; + virt_addr = virt_addr + ICP_QAT_CSS_FWSK_PUB_LEN; + auth_desc->signature_high = (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->signature_low = (unsigned int)bus_addr; + + memcpy((void *)(uintptr_t)virt_addr, + (const void *)(image + sizeof(*css_hdr) + + ICP_QAT_CSS_FWSK_MODULUS_LEN + + ICP_QAT_CSS_FWSK_EXPONENT_LEN), + ICP_QAT_CSS_SIGNATURE_LEN); + + bus_addr = + ADD_ADDR(auth_desc->signature_high, auth_desc->signature_low) + + ICP_QAT_CSS_SIGNATURE_LEN; + virt_addr += ICP_QAT_CSS_SIGNATURE_LEN; + + auth_desc->img_high = (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->img_low = (unsigned int)bus_addr; + auth_desc->img_len = size - ICP_QAT_AE_IMG_OFFSET; + memcpy((void *)(uintptr_t)virt_addr, + (const void *)(image + ICP_QAT_AE_IMG_OFFSET), + auth_desc->img_len); + virt_addr = virt_base; + /* AE firmware */ + if (((struct icp_qat_css_hdr *)(uintptr_t)virt_addr)->fw_type == + CSS_AE_FIRMWARE) { + auth_desc->img_ae_mode_data_high = auth_desc->img_high; + auth_desc->img_ae_mode_data_low = auth_desc->img_low; + bus_addr = ADD_ADDR(auth_desc->img_ae_mode_data_high, + auth_desc->img_ae_mode_data_low) + + sizeof(struct icp_qat_simg_ae_mode); + + auth_desc->img_ae_init_data_high = + (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->img_ae_init_data_low = (unsigned int)bus_addr; + bus_addr += ICP_QAT_SIMG_AE_INIT_SEQ_LEN; + auth_desc->img_ae_insts_high = + (unsigned int)(bus_addr >> BITS_IN_DWORD); + auth_desc->img_ae_insts_low = (unsigned int)bus_addr; + virt_addr += sizeof(struct icp_qat_css_hdr) + + ICP_QAT_CSS_FWSK_PUB_LEN + ICP_QAT_CSS_SIGNATURE_LEN; + auth_desc->ae_mask = + ((struct icp_qat_simg_ae_mode *)virt_addr)->ae_mask & + handle->cfg_ae_mask; + } else { + auth_desc->img_ae_insts_high = auth_desc->img_high; + auth_desc->img_ae_insts_low = auth_desc->img_low; + } + *desc = auth_desc; + return 0; +} + +static int +qat_uclo_load_fw(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_fw_auth_desc *desc) +{ + unsigned int i = 0; + unsigned int fcu_sts; + unsigned int fcu_sts_csr, fcu_ctl_csr; + unsigned int loaded_aes = FCU_LOADED_AE_POS; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + if (IS_QAT_GEN3(pci_get_device(GET_DEV(handle->accel_dev)))) { + fcu_ctl_csr = FCU_CONTROL_C4XXX; + fcu_sts_csr = FCU_STATUS_C4XXX; + + } else { + fcu_ctl_csr = FCU_CONTROL; + fcu_sts_csr = FCU_STATUS; + } + + for_each_set_bit(i, &ae_mask, handle->hal_handle->ae_max_num) + { + int retry = 0; + + if (!((desc->ae_mask >> i) & 0x1)) + continue; + if (qat_hal_check_ae_active(handle, i)) { + pr_err("QAT: AE %d is active\n", i); + return EINVAL; + } + SET_FCU_CSR(handle, + fcu_ctl_csr, + (FCU_CTRL_CMD_LOAD | (i << FCU_CTRL_AE_POS))); + + do { + pause_ms("adfstop", FW_AUTH_WAIT_PERIOD); + fcu_sts = GET_FCU_CSR(handle, fcu_sts_csr); + if ((fcu_sts & FCU_AUTH_STS_MASK) == + FCU_STS_LOAD_DONE) { + loaded_aes = IS_QAT_GEN3(pci_get_device( + GET_DEV(handle->accel_dev))) ? + GET_FCU_CSR(handle, FCU_AE_LOADED_C4XXX) : + (fcu_sts >> FCU_LOADED_AE_POS); + if (loaded_aes & (1 << i)) + break; + } + } while (retry++ < FW_AUTH_MAX_RETRY); + if (retry > FW_AUTH_MAX_RETRY) { + pr_err("QAT: firmware load failed timeout %x\n", retry); + return EINVAL; + } + } + return 0; +} + +static int +qat_uclo_map_suof_obj(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + int mem_size) +{ + struct icp_qat_suof_handle *suof_handle; + + suof_handle = malloc(sizeof(*suof_handle), M_QAT, M_WAITOK | M_ZERO); + handle->sobj_handle = suof_handle; + if (qat_uclo_map_suof(handle, addr_ptr, mem_size)) { + qat_uclo_del_suof(handle); + pr_err("QAT: map SUOF failed\n"); + return EINVAL; + } + return 0; +} + +int +qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + int mem_size) +{ + struct icp_qat_fw_auth_desc *desc = NULL; + struct icp_firml_dram_desc img_desc; + int status = 0; + + if (handle->fw_auth) { + status = qat_uclo_map_auth_fw( + handle, addr_ptr, mem_size, &img_desc, &desc); + if (!status) + status = qat_uclo_auth_fw(handle, desc); + + qat_uclo_simg_free(handle, &img_desc); + } else { + if (pci_get_device(GET_DEV(handle->accel_dev)) == + ADF_C3XXX_PCI_DEVICE_ID) { + pr_err("QAT: C3XXX doesn't support unsigned MMP\n"); + return EINVAL; + } + status = qat_uclo_wr_sram_by_words(handle, + handle->hal_sram_offset, + addr_ptr, + mem_size); + } + return status; +} + +static int +qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + int mem_size) +{ + struct icp_qat_uof_filehdr *filehdr; + struct icp_qat_uclo_objhandle *objhdl; + + objhdl = malloc(sizeof(*objhdl), M_QAT, M_WAITOK | M_ZERO); + objhdl->obj_buf = malloc(mem_size, M_QAT, M_WAITOK); + bcopy(addr_ptr, objhdl->obj_buf, mem_size); + filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf; + if (qat_uclo_check_uof_format(filehdr)) + goto out_objhdr_err; + objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf, + filehdr, + ICP_QAT_UOF_OBJS); + if (!objhdl->obj_hdr) { + pr_err("QAT: object file chunk is null\n"); + goto out_objhdr_err; + } + handle->obj_handle = objhdl; + if (qat_uclo_parse_uof_obj(handle)) + goto out_overlay_obj_err; + return 0; + +out_overlay_obj_err: + handle->obj_handle = NULL; + free(objhdl->obj_hdr, M_QAT); +out_objhdr_err: + free(objhdl->obj_buf, M_QAT); + free(objhdl, M_QAT); + return ENOMEM; +} + +static int +qat_uclo_map_mof_file_hdr(struct icp_qat_fw_loader_handle *handle, + const struct icp_qat_mof_file_hdr *mof_ptr, + u32 mof_size) +{ + unsigned int checksum = 0; + unsigned int min_ver_offset = 0; + struct icp_qat_mof_handle *mobj_handle = handle->mobj_handle; + + mobj_handle->file_id = ICP_QAT_MOF_FID; + mobj_handle->mof_buf = (const char *)mof_ptr; + mobj_handle->mof_size = mof_size; + + min_ver_offset = + mof_size - offsetof(struct icp_qat_mof_file_hdr, min_ver); + checksum = qat_uclo_calc_str_checksum((const char *)&mof_ptr->min_ver, + min_ver_offset); + if (checksum != mof_ptr->checksum) { + pr_err("QAT: incorrect MOF checksum\n"); + return EINVAL; + } + mobj_handle->checksum = mof_ptr->checksum; + mobj_handle->min_ver = mof_ptr->min_ver; + mobj_handle->maj_ver = mof_ptr->maj_ver; + return 0; +} + +void +qat_uclo_del_mof(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_mof_handle *mobj_handle = handle->mobj_handle; + + free(mobj_handle->obj_table.obj_hdr, M_QAT); + mobj_handle->obj_table.obj_hdr = NULL; + free(handle->mobj_handle, M_QAT); + handle->mobj_handle = NULL; +} + +static int +qat_uclo_seek_obj_inside_mof(struct icp_qat_mof_handle *mobj_handle, + const char *obj_name, + const char **obj_ptr, + unsigned int *obj_size) +{ + unsigned int i; + struct icp_qat_mof_objhdr *obj_hdr = mobj_handle->obj_table.obj_hdr; + + for (i = 0; i < mobj_handle->obj_table.num_objs; i++) { + if (!strncmp(obj_hdr[i].obj_name, + obj_name, + ICP_QAT_SUOF_OBJ_NAME_LEN)) { + *obj_ptr = obj_hdr[i].obj_buf; + *obj_size = obj_hdr[i].obj_size; + break; + } + } + + if (i >= mobj_handle->obj_table.num_objs) { + pr_err("QAT: object %s is not found inside MOF\n", obj_name); + return EFAULT; + } + return 0; +} + +static int +qat_uclo_map_obj_from_mof(struct icp_qat_mof_handle *mobj_handle, + struct icp_qat_mof_objhdr *mobj_hdr, + struct icp_qat_mof_obj_chunkhdr *obj_chunkhdr) +{ + if ((strncmp((char *)obj_chunkhdr->chunk_id, + ICP_QAT_UOF_IMAG, + ICP_QAT_MOF_OBJ_CHUNKID_LEN)) == 0) { + mobj_hdr->obj_buf = + (const char *)((unsigned long)obj_chunkhdr->offset + + mobj_handle->uobjs_hdr); + } else if ((strncmp((char *)(obj_chunkhdr->chunk_id), + ICP_QAT_SUOF_IMAG, + ICP_QAT_MOF_OBJ_CHUNKID_LEN)) == 0) { + mobj_hdr->obj_buf = + (const char *)((unsigned long)obj_chunkhdr->offset + + mobj_handle->sobjs_hdr); + + } else { + pr_err("QAT: unsupported chunk id\n"); + return EINVAL; + } + mobj_hdr->obj_size = (unsigned int)obj_chunkhdr->size; + mobj_hdr->obj_name = + (char *)(obj_chunkhdr->name + mobj_handle->sym_str); + return 0; +} + +static int +qat_uclo_map_objs_from_mof(struct icp_qat_mof_handle *mobj_handle) +{ + struct icp_qat_mof_objhdr *mof_obj_hdr; + const struct icp_qat_mof_obj_hdr *uobj_hdr; + const struct icp_qat_mof_obj_hdr *sobj_hdr; + struct icp_qat_mof_obj_chunkhdr *uobj_chunkhdr; + struct icp_qat_mof_obj_chunkhdr *sobj_chunkhdr; + unsigned int uobj_chunk_num = 0, sobj_chunk_num = 0; + unsigned int *valid_chunks = 0; + int ret, i; + + uobj_hdr = (const struct icp_qat_mof_obj_hdr *)mobj_handle->uobjs_hdr; + sobj_hdr = (const struct icp_qat_mof_obj_hdr *)mobj_handle->sobjs_hdr; + if (uobj_hdr) + uobj_chunk_num = uobj_hdr->num_chunks; + if (sobj_hdr) + sobj_chunk_num = sobj_hdr->num_chunks; + + mof_obj_hdr = (struct icp_qat_mof_objhdr *) + malloc((uobj_chunk_num + sobj_chunk_num) * sizeof(*mof_obj_hdr), + M_QAT, + M_WAITOK | M_ZERO); + + mobj_handle->obj_table.obj_hdr = mof_obj_hdr; + valid_chunks = &mobj_handle->obj_table.num_objs; + uobj_chunkhdr = + (struct icp_qat_mof_obj_chunkhdr *)((uintptr_t)uobj_hdr + + sizeof(*uobj_hdr)); + sobj_chunkhdr = + (struct icp_qat_mof_obj_chunkhdr *)((uintptr_t)sobj_hdr + + sizeof(*sobj_hdr)); + + /* map uof objects */ + for (i = 0; i < uobj_chunk_num; i++) { + ret = qat_uclo_map_obj_from_mof(mobj_handle, + &mof_obj_hdr[*valid_chunks], + &uobj_chunkhdr[i]); + if (ret) + return ret; + (*valid_chunks)++; + } + + /* map suof objects */ + for (i = 0; i < sobj_chunk_num; i++) { + ret = qat_uclo_map_obj_from_mof(mobj_handle, + &mof_obj_hdr[*valid_chunks], + &sobj_chunkhdr[i]); + if (ret) + return ret; + (*valid_chunks)++; + } + + if ((uobj_chunk_num + sobj_chunk_num) != *valid_chunks) { + pr_err("QAT: inconsistent UOF/SUOF chunk amount\n"); + return EINVAL; + } + return 0; +} + +static void +qat_uclo_map_mof_symobjs(struct icp_qat_mof_handle *mobj_handle, + struct icp_qat_mof_chunkhdr *mof_chunkhdr) +{ + char **sym_str = (char **)&mobj_handle->sym_str; + unsigned int *sym_size = &mobj_handle->sym_size; + struct icp_qat_mof_str_table *str_table_obj; + + *sym_size = *(unsigned int *)(uintptr_t)(mof_chunkhdr->offset + + mobj_handle->mof_buf); + *sym_str = + (char *)(uintptr_t)(mobj_handle->mof_buf + mof_chunkhdr->offset + + sizeof(str_table_obj->tab_len)); +} + +static void +qat_uclo_map_mof_chunk(struct icp_qat_mof_handle *mobj_handle, + struct icp_qat_mof_chunkhdr *mof_chunkhdr) +{ + if (!strncmp(mof_chunkhdr->chunk_id, + ICP_QAT_MOF_SYM_OBJS, + ICP_QAT_MOF_OBJ_ID_LEN)) + qat_uclo_map_mof_symobjs(mobj_handle, mof_chunkhdr); + else if (!strncmp(mof_chunkhdr->chunk_id, + ICP_QAT_UOF_OBJS, + ICP_QAT_MOF_OBJ_ID_LEN)) + mobj_handle->uobjs_hdr = + mobj_handle->mof_buf + (unsigned long)mof_chunkhdr->offset; + else if (!strncmp(mof_chunkhdr->chunk_id, + ICP_QAT_SUOF_OBJS, + ICP_QAT_MOF_OBJ_ID_LEN)) + mobj_handle->sobjs_hdr = + mobj_handle->mof_buf + (unsigned long)mof_chunkhdr->offset; +} + +static int +qat_uclo_check_mof_format(const struct icp_qat_mof_file_hdr *mof_hdr) +{ + int maj = mof_hdr->maj_ver & 0xff; + int min = mof_hdr->min_ver & 0xff; + + if (mof_hdr->file_id != ICP_QAT_MOF_FID) { + pr_err("QAT: invalid header 0x%x\n", mof_hdr->file_id); + return EINVAL; + } + + if (mof_hdr->num_chunks <= 0x1) { + pr_err("QAT: MOF chunk amount is incorrect\n"); + return EINVAL; + } + if (maj != ICP_QAT_MOF_MAJVER || min != ICP_QAT_MOF_MINVER) { + pr_err("QAT: bad MOF version, major 0x%x, minor 0x%x\n", + maj, + min); + return EINVAL; + } + return 0; +} + +static int +qat_uclo_map_mof_obj(struct icp_qat_fw_loader_handle *handle, + const struct icp_qat_mof_file_hdr *mof_ptr, + u32 mof_size, + const char *obj_name, + const char **obj_ptr, + unsigned int *obj_size) +{ + struct icp_qat_mof_handle *mobj_handle; + struct icp_qat_mof_chunkhdr *mof_chunkhdr; + unsigned short chunks_num; + int ret; + unsigned int i; + + if (mof_ptr->file_id == ICP_QAT_UOF_FID || + mof_ptr->file_id == ICP_QAT_SUOF_FID) { + if (obj_ptr) + *obj_ptr = (const char *)mof_ptr; + if (obj_size) + *obj_size = (unsigned int)mof_size; + return 0; + } + if (qat_uclo_check_mof_format(mof_ptr)) + return EINVAL; + mobj_handle = malloc(sizeof(*mobj_handle), M_QAT, M_WAITOK | M_ZERO); + handle->mobj_handle = mobj_handle; + ret = qat_uclo_map_mof_file_hdr(handle, mof_ptr, mof_size); + if (ret) + return ret; + mof_chunkhdr = (struct icp_qat_mof_chunkhdr *)((uintptr_t)mof_ptr + + sizeof(*mof_ptr)); + chunks_num = mof_ptr->num_chunks; + /*Parse MOF file chunks*/ + for (i = 0; i < chunks_num; i++) + qat_uclo_map_mof_chunk(mobj_handle, &mof_chunkhdr[i]); + /*All sym_objs uobjs and sobjs should be available*/ + if (!mobj_handle->sym_str || + (!mobj_handle->uobjs_hdr && !mobj_handle->sobjs_hdr)) + return EINVAL; + ret = qat_uclo_map_objs_from_mof(mobj_handle); + if (ret) + return ret; + /*Seek specified uof object in MOF*/ + ret = qat_uclo_seek_obj_inside_mof(mobj_handle, + obj_name, + obj_ptr, + obj_size); + if (ret) + return ret; + return 0; +} + +int +qat_uclo_map_obj(struct icp_qat_fw_loader_handle *handle, + const void *addr_ptr, + u32 mem_size, + const char *obj_name) +{ + const char *obj_addr; + u32 obj_size; + int ret; + + BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE > + (sizeof(handle->hal_handle->ae_mask) * 8)); + + if (!handle || !addr_ptr || mem_size < 24) + return EINVAL; + + if (obj_name) { + ret = qat_uclo_map_mof_obj( + handle, addr_ptr, mem_size, obj_name, &obj_addr, &obj_size); + if (ret) + return ret; + } else { + obj_addr = addr_ptr; + obj_size = mem_size; + } + + return (handle->fw_auth) ? + qat_uclo_map_suof_obj(handle, obj_addr, obj_size) : + qat_uclo_map_uof_obj(handle, obj_addr, obj_size); +} + +void +qat_uclo_del_obj(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int a; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + if (handle->mobj_handle) + qat_uclo_del_mof(handle); + if (handle->sobj_handle) + qat_uclo_del_suof(handle); + if (!obj_handle) + return; + + free(obj_handle->uword_buf, M_QAT); + for (a = 0; a < obj_handle->uimage_num; a++) + free(obj_handle->ae_uimage[a].page, M_QAT); + + for_each_set_bit(a, &ae_mask, handle->hal_handle->ae_max_num) + { + qat_uclo_free_ae_data(&obj_handle->ae_data[a]); + } + + free(obj_handle->obj_hdr, M_QAT); + free(obj_handle->obj_buf, M_QAT); + free(obj_handle, M_QAT); + handle->obj_handle = NULL; +} + +static void +qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle, + struct icp_qat_uclo_encap_page *encap_page, + uint64_t *uword, + unsigned int addr_p, + unsigned int raddr, + uint64_t fill) +{ + uint64_t uwrd = 0; + unsigned int i, addr; + + if (!encap_page) { + *uword = fill; + return; + } + addr = (encap_page->page_region) ? raddr : addr_p; + for (i = 0; i < encap_page->uwblock_num; i++) { + if (addr >= encap_page->uwblock[i].start_addr && + addr <= encap_page->uwblock[i].start_addr + + encap_page->uwblock[i].words_num - 1) { + addr -= encap_page->uwblock[i].start_addr; + addr *= obj_handle->uword_in_bytes; + memcpy(&uwrd, + (void *)(((uintptr_t)encap_page->uwblock[i] + .micro_words) + + addr), + obj_handle->uword_in_bytes); + uwrd = uwrd & 0xbffffffffffull; + } + } + *uword = uwrd; + if (*uword == INVLD_UWORD) + *uword = fill; +} + +static void +qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uclo_encap_page *encap_page, + unsigned int ae) +{ + unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen; + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + uint64_t fill_pat; + + /* load the page starting at appropriate ustore address */ + /* get fill-pattern from an image -- they are all the same */ + memcpy(&fill_pat, + obj_handle->ae_uimage[0].img_ptr->fill_pattern, + sizeof(uint64_t)); + uw_physical_addr = encap_page->beg_addr_p; + uw_relative_addr = 0; + words_num = encap_page->micro_words_num; + while (words_num) { + if (words_num < UWORD_CPYBUF_SIZE) + cpylen = words_num; + else + cpylen = UWORD_CPYBUF_SIZE; + + /* load the buffer */ + for (i = 0; i < cpylen; i++) + qat_uclo_fill_uwords(obj_handle, + encap_page, + &obj_handle->uword_buf[i], + uw_physical_addr + i, + uw_relative_addr + i, + fill_pat); + + if (obj_handle->ae_data[ae].shareable_ustore) + /* copy the buffer to ustore */ + qat_hal_wr_coalesce_uwords(handle, + (unsigned char)ae, + uw_physical_addr, + cpylen, + obj_handle->uword_buf); + else + /* copy the buffer to ustore */ + qat_hal_wr_uwords(handle, + (unsigned char)ae, + uw_physical_addr, + cpylen, + obj_handle->uword_buf); + uw_physical_addr += cpylen; + uw_relative_addr += cpylen; + words_num -= cpylen; + } +} + +static void +qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle, + struct icp_qat_uof_image *image) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int ctx_mask, s; + struct icp_qat_uclo_page *page; + unsigned char ae = 0; + int ctx; + struct icp_qat_uclo_aedata *aed; + unsigned long ae_mask = handle->hal_handle->ae_mask; + + if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX) + ctx_mask = 0xff; + else + ctx_mask = 0x55; + /* load the default page and set assigned CTX PC + * to the entrypoint address + */ + for_each_set_bit(ae, &ae_mask, handle->hal_handle->ae_max_num) + { + unsigned long cfg_ae_mask = handle->cfg_ae_mask; + unsigned long ae_assigned = image->ae_assigned; + + if (!test_bit(ae, &cfg_ae_mask)) + continue; + + if (!test_bit(ae, &ae_assigned)) + continue; + + aed = &obj_handle->ae_data[ae]; + /* find the slice to which this image is assigned */ + for (s = 0; s < aed->slice_num; s++) { + if (image->ctx_assigned & + aed->ae_slices[s].ctx_mask_assigned) + break; + } + if (s >= aed->slice_num) + continue; + page = aed->ae_slices[s].page; + if (!page->encap_page->def_page) + continue; + qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae); + + page = aed->ae_slices[s].page; + for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) + aed->ae_slices[s].cur_page[ctx] = + (ctx_mask & (1 << ctx)) ? page : NULL; + qat_hal_set_live_ctx(handle, + (unsigned char)ae, + image->ctx_assigned); + qat_hal_set_pc(handle, + (unsigned char)ae, + image->ctx_assigned, + image->entry_address); + } +} + +static int +qat_uclo_wr_suof_img(struct icp_qat_fw_loader_handle *handle) +{ + unsigned int i; + struct icp_qat_fw_auth_desc *desc = NULL; + struct icp_firml_dram_desc img_desc; + struct icp_qat_suof_handle *sobj_handle = handle->sobj_handle; + struct icp_qat_suof_img_hdr *simg_hdr = sobj_handle->img_table.simg_hdr; + + for (i = 0; i < sobj_handle->img_table.num_simgs; i++) { + if (qat_uclo_map_auth_fw(handle, + (const char *)simg_hdr[i].simg_buf, + (unsigned int)(simg_hdr[i].simg_len), + &img_desc, + &desc)) + goto wr_err; + if (qat_uclo_auth_fw(handle, desc)) + goto wr_err; + if (qat_uclo_load_fw(handle, desc)) + goto wr_err; + qat_uclo_simg_free(handle, &img_desc); + } + return 0; +wr_err: + qat_uclo_simg_free(handle, &img_desc); + return -EINVAL; +} + +static int +qat_uclo_wr_uof_img(struct icp_qat_fw_loader_handle *handle) +{ + struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle; + unsigned int i; + + if (qat_uclo_init_globals(handle)) + return EINVAL; + for (i = 0; i < obj_handle->uimage_num; i++) { + if (!obj_handle->ae_uimage[i].img_ptr) + return EINVAL; + if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i])) + return EINVAL; + qat_uclo_wr_uimage_page(handle, + obj_handle->ae_uimage[i].img_ptr); + } + return 0; +} + +int +qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle) +{ + return (handle->fw_auth) ? qat_uclo_wr_suof_img(handle) : + qat_uclo_wr_uof_img(handle); +} + +int +qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle, + unsigned int cfg_ae_mask) +{ + if (!cfg_ae_mask) + return EINVAL; + + handle->cfg_ae_mask = cfg_ae_mask; + return 0; +} diff --git a/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.c b/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.c new file mode 100644 index 00000000000..22e1464cff1 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.c @@ -0,0 +1,541 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include +#include +#include "adf_200xx_hw_data.h" +#include "icp_qat_hw.h" +#include "adf_heartbeat.h" + +/* Worker thread to service arbiter mappings */ +static const u32 thrd_to_arb_map[ADF_200XX_MAX_ACCELENGINES] = + { 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA }; + +enum { DEV_200XX_SKU_1 = 0, DEV_200XX_SKU_2 = 1, DEV_200XX_SKU_3 = 2 }; + +static u32 thrd_to_arb_map_gen[ADF_200XX_MAX_ACCELENGINES] = { 0 }; + +static struct adf_hw_device_class qat_200xx_class = {.name = + ADF_200XX_DEVICE_NAME, + .type = DEV_200XX, + .instances = 0 }; + +static u32 +get_accel_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + + u32 fuse; + u32 straps; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + straps = pci_read_config(pdev, ADF_200XX_SOFTSTRAP_CSR_OFFSET, 4); + + return (~(fuse | straps)) >> ADF_200XX_ACCELERATORS_REG_OFFSET & + ADF_200XX_ACCELERATORS_MASK; +} + +static u32 +get_ae_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fuse; + u32 me_straps; + u32 me_disable; + u32 ssms_disabled; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + me_straps = pci_read_config(pdev, ADF_200XX_SOFTSTRAP_CSR_OFFSET, 4); + + /* If SSMs are disabled, then disable the corresponding MEs */ + ssms_disabled = + (~get_accel_mask(accel_dev)) & ADF_200XX_ACCELERATORS_MASK; + me_disable = 0x3; + while (ssms_disabled) { + if (ssms_disabled & 1) + me_straps |= me_disable; + ssms_disabled >>= 1; + me_disable <<= 2; + } + + return (~(fuse | me_straps)) & ADF_200XX_ACCELENGINES_MASK; +} + +static u32 +get_num_accels(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->accel_mask) + return 0; + + for (i = 0; i < ADF_200XX_MAX_ACCELERATORS; i++) { + if (self->accel_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_num_aes(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->ae_mask) + return 0; + + for (i = 0; i < ADF_200XX_MAX_ACCELENGINES; i++) { + if (self->ae_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_misc_bar_id(struct adf_hw_device_data *self) +{ + return ADF_200XX_PMISC_BAR; +} + +static u32 +get_etr_bar_id(struct adf_hw_device_data *self) +{ + return ADF_200XX_ETR_BAR; +} + +static u32 +get_sram_bar_id(struct adf_hw_device_data *self) +{ + return 0; +} + +static enum dev_sku_info +get_sku(struct adf_hw_device_data *self) +{ + int aes = get_num_aes(self); + + if (aes == 6) + return DEV_SKU_4; + + return DEV_SKU_UNKNOWN; +} + +static void +adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev, + u32 const **arb_map_config) +{ + int i; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + for (i = 0; i < ADF_200XX_MAX_ACCELENGINES; i++) { + thrd_to_arb_map_gen[i] = 0; + if (hw_device->ae_mask & (1 << i)) + thrd_to_arb_map_gen[i] = thrd_to_arb_map[i]; + } + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map, + thrd_to_arb_map_gen, + ADF_200XX_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; +} + +static u32 +get_pf2vf_offset(u32 i) +{ + return ADF_200XX_PF2VF_OFFSET(i); +} + +static u32 +get_vintmsk_offset(u32 i) +{ + return ADF_200XX_VINTMSK_OFFSET(i); +} + +static void +get_arb_info(struct arb_info *arb_csrs_info) +{ + arb_csrs_info->arbiter_offset = ADF_200XX_ARB_OFFSET; + arb_csrs_info->wrk_thd_2_srv_arb_map = + ADF_200XX_ARB_WRK_2_SER_MAP_OFFSET; + arb_csrs_info->wrk_cfg_offset = ADF_200XX_ARB_WQCFG_OFFSET; +} + +static void +get_admin_info(struct admin_info *admin_csrs_info) +{ + admin_csrs_info->mailbox_offset = ADF_200XX_MAILBOX_BASE_OFFSET; + admin_csrs_info->admin_msg_ur = ADF_200XX_ADMINMSGUR_OFFSET; + admin_csrs_info->admin_msg_lr = ADF_200XX_ADMINMSGLR_OFFSET; +} + +static void +get_errsou_offset(u32 *errsou3, u32 *errsou5) +{ + *errsou3 = ADF_200XX_ERRSOU3; + *errsou5 = ADF_200XX_ERRSOU5; +} + +static u32 +get_clock_speed(struct adf_hw_device_data *self) +{ + /* CPP clock is half high-speed clock */ + return self->clock_frequency / 2; +} + +static void +adf_enable_error_interrupts(struct resource *csr) +{ + ADF_CSR_WR(csr, ADF_ERRMSK0, ADF_200XX_ERRMSK0_CERR); /* ME0-ME3 */ + ADF_CSR_WR(csr, ADF_ERRMSK1, ADF_200XX_ERRMSK1_CERR); /* ME4-ME5 */ + ADF_CSR_WR(csr, ADF_ERRMSK5, ADF_200XX_ERRMSK5_CERR); /* SSM2 */ + + /* Reset everything except VFtoPF1_16. */ + adf_csr_fetch_and_and(csr, ADF_ERRMSK3, ADF_200XX_VF2PF1_16); + + /* RI CPP bus interface error detection and reporting. */ + ADF_CSR_WR(csr, ADF_200XX_RICPPINTCTL, ADF_200XX_RICPP_EN); + + /* TI CPP bus interface error detection and reporting. */ + ADF_CSR_WR(csr, ADF_200XX_TICPPINTCTL, ADF_200XX_TICPP_EN); + + /* Enable CFC Error interrupts and logging. */ + ADF_CSR_WR(csr, ADF_200XX_CPP_CFC_ERR_CTRL, ADF_200XX_CPP_CFC_UE); +} + +static void +adf_disable_error_interrupts(struct adf_accel_dev *accel_dev) +{ + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_200XX_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + + /* ME0-ME3 */ + ADF_CSR_WR(csr, + ADF_ERRMSK0, + ADF_200XX_ERRMSK0_UERR | ADF_200XX_ERRMSK0_CERR); + /* ME4-ME5 */ + ADF_CSR_WR(csr, + ADF_ERRMSK1, + ADF_200XX_ERRMSK1_UERR | ADF_200XX_ERRMSK1_CERR); + /* CPP Push Pull, RI, TI, SSM0-SSM1, CFC */ + ADF_CSR_WR(csr, ADF_ERRMSK3, ADF_200XX_ERRMSK3_UERR); + /* SSM2 */ + ADF_CSR_WR(csr, ADF_ERRMSK5, ADF_200XX_ERRMSK5_UERR); +} + +static int +adf_check_uncorrectable_error(struct adf_accel_dev *accel_dev) +{ + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_200XX_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + + u32 errsou0 = ADF_CSR_RD(csr, ADF_ERRSOU0) & ADF_200XX_ERRMSK0_UERR; + u32 errsou1 = ADF_CSR_RD(csr, ADF_ERRSOU1) & ADF_200XX_ERRMSK1_UERR; + u32 errsou3 = ADF_CSR_RD(csr, ADF_ERRSOU3) & ADF_200XX_ERRMSK3_UERR; + u32 errsou5 = ADF_CSR_RD(csr, ADF_ERRSOU5) & ADF_200XX_ERRMSK5_UERR; + + return (errsou0 | errsou1 | errsou3 | errsou5); +} + +static void +adf_enable_mmp_error_correction(struct resource *csr, + struct adf_hw_device_data *hw_data) +{ + unsigned int dev, mmp; + unsigned int mask; + + /* Enable MMP Logging */ + for (dev = 0, mask = hw_data->accel_mask; mask; dev++, mask >>= 1) { + if (!(mask & 1)) + continue; + /* Set power-up */ + adf_csr_fetch_and_and(csr, + ADF_200XX_SLICEPWRDOWN(dev), + ~ADF_200XX_MMP_PWR_UP_MSK); + + if (hw_data->accel_capabilities_mask & + ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) { + for (mmp = 0; mmp < ADF_MAX_MMP; ++mmp) { + /* + * The device supports PKE, + * so enable error reporting from MMP memory + */ + adf_csr_fetch_and_or(csr, + ADF_UERRSSMMMP(dev, mmp), + ADF_200XX_UERRSSMMMP_EN); + /* + * The device supports PKE, + * so enable error correction from MMP memory + */ + adf_csr_fetch_and_or(csr, + ADF_CERRSSMMMP(dev, mmp), + ADF_200XX_CERRSSMMMP_EN); + } + } else { + for (mmp = 0; mmp < ADF_MAX_MMP; ++mmp) { + /* + * The device doesn't support PKE, + * so disable error reporting from MMP memory + */ + adf_csr_fetch_and_and(csr, + ADF_UERRSSMMMP(dev, mmp), + ~ADF_200XX_UERRSSMMMP_EN); + /* + * The device doesn't support PKE, + * so disable error correction from MMP memory + */ + adf_csr_fetch_and_and(csr, + ADF_CERRSSMMMP(dev, mmp), + ~ADF_200XX_CERRSSMMMP_EN); + } + } + + /* Restore power-down value */ + adf_csr_fetch_and_or(csr, + ADF_200XX_SLICEPWRDOWN(dev), + ADF_200XX_MMP_PWR_UP_MSK); + + /* Disabling correctable error interrupts. */ + ADF_CSR_WR(csr, + ADF_200XX_INTMASKSSM(dev), + ADF_200XX_INTMASKSSM_UERR); + } +} + +static void +adf_enable_error_correction(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_200XX_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + unsigned int val, i; + unsigned int mask; + + /* Enable Accel Engine error detection & correction */ + mask = hw_device->ae_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_200XX_AE_CTX_ENABLES(i)); + val |= ADF_200XX_ENABLE_AE_ECC_ERR; + ADF_CSR_WR(csr, ADF_200XX_AE_CTX_ENABLES(i), val); + val = ADF_CSR_RD(csr, ADF_200XX_AE_MISC_CONTROL(i)); + val |= ADF_200XX_ENABLE_AE_ECC_PARITY_CORR; + ADF_CSR_WR(csr, ADF_200XX_AE_MISC_CONTROL(i), val); + } + + /* Enable shared memory error detection & correction */ + mask = hw_device->accel_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_200XX_UERRSSMSH(i)); + val |= ADF_200XX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_200XX_UERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_200XX_CERRSSMSH(i)); + val |= ADF_200XX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_200XX_CERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_PPERR(i)); + val |= ADF_200XX_PPERR_EN; + ADF_CSR_WR(csr, ADF_PPERR(i), val); + } + + adf_enable_error_interrupts(csr); + adf_enable_mmp_error_correction(csr, hw_device); +} + +static void +adf_enable_ints(struct adf_accel_dev *accel_dev) +{ + struct resource *addr; + + addr = (&GET_BARS(accel_dev)[ADF_200XX_PMISC_BAR])->virt_addr; + + /* Enable bundle and misc interrupts */ + ADF_CSR_WR(addr, ADF_200XX_SMIAPF0_MASK_OFFSET, ADF_200XX_SMIA0_MASK); + ADF_CSR_WR(addr, ADF_200XX_SMIAPF1_MASK_OFFSET, ADF_200XX_SMIA1_MASK); +} + +static u32 +get_ae_clock(struct adf_hw_device_data *self) +{ + /* + * Clock update interval is <16> ticks for 200xx. + */ + return self->clock_frequency / 16; +} + +static int +get_storage_enabled(struct adf_accel_dev *accel_dev, uint32_t *storage_enabled) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + strlcpy(key, ADF_STORAGE_FIRMWARE_ENABLED, sizeof(key)); + if (!adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) { + if (kstrtouint(val, 0, storage_enabled)) + return -EFAULT; + } + return 0; +} + +static int +measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret = 0; + + ret = adf_dev_measure_clock(accel_dev, + &frequency, + ADF_200XX_MIN_AE_FREQ, + ADF_200XX_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + +static u32 +adf_200xx_get_hw_cap(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuses; + u32 capabilities; + u32 straps; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 fuses = hw_data->fuses; + + /* Read accelerator capabilities mask */ + legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC + + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC + + ICP_ACCEL_CAPABILITIES_CIPHER + + ICP_ACCEL_CAPABILITIES_AUTHENTICATION + + ICP_ACCEL_CAPABILITIES_COMPRESSION + ICP_ACCEL_CAPABILITIES_ZUC + + ICP_ACCEL_CAPABILITIES_SHA3 + ICP_ACCEL_CAPABILITIES_HKDF + + ICP_ACCEL_CAPABILITIES_ECEDMONT + + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN; + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN); + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_ECEDMONT); + if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + if (legfuses & ICP_ACCEL_MASK_EIA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_ZUC; + if (legfuses & ICP_ACCEL_MASK_SHA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_SHA3; + + straps = pci_read_config(pdev, ADF_200XX_SOFTSTRAP_CSR_OFFSET, 4); + if ((straps | fuses) & ADF_200XX_POWERGATE_PKE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + if ((straps | fuses) & ADF_200XX_POWERGATE_CY) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + + return capabilities; +} + +static const char * +get_obj_name(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + return ADF_CXXX_AE_FW_NAME_CUSTOM1; +} + +static uint32_t +get_objs_num(struct adf_accel_dev *accel_dev) +{ + return 1; +} + +static uint32_t +get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services) +{ + return accel_dev->hw_device->ae_mask; +} + +void +adf_init_hw_data_200xx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class = &qat_200xx_class; + hw_data->instance_id = qat_200xx_class.instances++; + hw_data->num_banks = ADF_200XX_ETR_MAX_BANKS; + hw_data->num_rings_per_bank = ADF_ETR_MAX_RINGS_PER_BANK; + hw_data->num_accel = ADF_200XX_MAX_ACCELERATORS; + hw_data->num_logical_accel = 1; + hw_data->num_engines = ADF_200XX_MAX_ACCELENGINES; + hw_data->tx_rx_gap = ADF_200XX_RX_RINGS_OFFSET; + hw_data->tx_rings_mask = ADF_200XX_TX_RINGS_MASK; + hw_data->alloc_irq = adf_isr_resource_alloc; + hw_data->free_irq = adf_isr_resource_free; + hw_data->enable_error_correction = adf_enable_error_correction; + hw_data->check_uncorrectable_error = adf_check_uncorrectable_error; + hw_data->print_err_registers = adf_print_err_registers; + hw_data->disable_error_interrupts = adf_disable_error_interrupts; + hw_data->get_accel_mask = get_accel_mask; + hw_data->get_ae_mask = get_ae_mask; + hw_data->get_num_accels = get_num_accels; + hw_data->get_num_aes = get_num_aes; + hw_data->get_sram_bar_id = get_sram_bar_id; + hw_data->get_etr_bar_id = get_etr_bar_id; + hw_data->get_misc_bar_id = get_misc_bar_id; + hw_data->get_pf2vf_offset = get_pf2vf_offset; + hw_data->get_vintmsk_offset = get_vintmsk_offset; + hw_data->get_arb_info = get_arb_info; + hw_data->get_admin_info = get_admin_info; + hw_data->get_errsou_offset = get_errsou_offset; + hw_data->get_clock_speed = get_clock_speed; + hw_data->get_sku = get_sku; + hw_data->fw_name = ADF_200XX_FW; + hw_data->fw_mmp_name = ADF_200XX_MMP; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->disable_iov = adf_disable_sriov; + hw_data->send_admin_init = adf_send_admin_init; + hw_data->init_arb = adf_init_gen2_arb; + hw_data->exit_arb = adf_exit_arb; + hw_data->get_arb_mapping = adf_get_arbiter_mapping; + hw_data->enable_ints = adf_enable_ints; + hw_data->set_ssm_wdtimer = adf_set_ssm_wdtimer; + hw_data->check_slice_hang = adf_check_slice_hang; + hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms; + hw_data->disable_vf2pf_comms = adf_pf_disable_vf2pf_comms; + hw_data->restore_device = adf_dev_restore; + hw_data->reset_device = adf_reset_flr; + hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION; + hw_data->measure_clock = measure_clock; + hw_data->get_ae_clock = get_ae_clock; + hw_data->reset_device = adf_reset_flr; + hw_data->get_objs_num = get_objs_num; + hw_data->get_obj_name = get_obj_name; + hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; + hw_data->get_accel_cap = adf_200xx_get_hw_cap; + hw_data->clock_frequency = ADF_200XX_AE_FREQ; + hw_data->extended_dc_capabilities = 0; + hw_data->get_storage_enabled = get_storage_enabled; + hw_data->query_storage_cap = 1; + hw_data->get_heartbeat_status = adf_get_heartbeat_status; + hw_data->get_ae_clock = get_ae_clock; + hw_data->storage_enable = 0; + hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled; + hw_data->config_device = adf_config_device; + hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask; + hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP; + hw_data->pre_reset = adf_dev_pre_reset; + hw_data->post_reset = adf_dev_post_reset; +} + +void +adf_clean_hw_data_200xx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class->instances--; +} diff --git a/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.h b/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.h new file mode 100644 index 00000000000..069f59b5e24 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_200xx/adf_200xx_hw_data.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_200XX_HW_DATA_H_ +#define ADF_200XX_HW_DATA_H_ + +/* PCIe configuration space */ +#define ADF_200XX_PMISC_BAR 0 +#define ADF_200XX_ETR_BAR 1 +#define ADF_200XX_RX_RINGS_OFFSET 8 +#define ADF_200XX_TX_RINGS_MASK 0xFF +#define ADF_200XX_MAX_ACCELERATORS 3 +#define ADF_200XX_MAX_ACCELENGINES 6 +#define ADF_200XX_ACCELERATORS_REG_OFFSET 16 +#define ADF_200XX_ACCELERATORS_MASK 0x7 +#define ADF_200XX_ACCELENGINES_MASK 0x3F +#define ADF_200XX_ETR_MAX_BANKS 16 +#define ADF_200XX_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) +#define ADF_200XX_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) +#define ADF_200XX_SMIA0_MASK 0xFFFF +#define ADF_200XX_SMIA1_MASK 0x1 +#define ADF_200XX_SOFTSTRAP_CSR_OFFSET 0x2EC +#define ADF_200XX_POWERGATE_PKE BIT(24) +#define ADF_200XX_POWERGATE_CY BIT(23) + +#define ADF_200XX_PFIEERRUNCSTSR 0x280 + +/* Error detection and correction */ +#define ADF_200XX_AE_CTX_ENABLES(i) ((i)*0x1000 + 0x20818) +#define ADF_200XX_AE_MISC_CONTROL(i) ((i)*0x1000 + 0x20960) +#define ADF_200XX_ENABLE_AE_ECC_ERR BIT(28) +#define ADF_200XX_ENABLE_AE_ECC_PARITY_CORR (BIT(24) | BIT(12)) +#define ADF_200XX_UERRSSMSH(i) (i * 0x4000 + 0x18) +#define ADF_200XX_CERRSSMSH(i) (i * 0x4000 + 0x10) +#define ADF_200XX_ERRSSMSH_EN BIT(3) +#define ADF_200XX_ERRSOU3 (0x3A000 + 0x0C) +#define ADF_200XX_ERRSOU5 (0x3A000 + 0xD8) + +/* BIT(2) enables the logging of push/pull data errors. */ +#define ADF_200XX_PPERR_EN (BIT(2)) + +/* Mask for VF2PF interrupts */ +#define ADF_200XX_VF2PF1_16 (0xFFFF << 9) +#define ADF_200XX_ERRSOU3_VF2PF(errsou3) (((errsou3)&0x01FFFE00) >> 9) +#define ADF_200XX_ERRMSK3_VF2PF(vf_mask) (((vf_mask)&0xFFFF) << 9) + +/* Masks for correctable error interrupts. */ +#define ADF_200XX_ERRMSK0_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_200XX_ERRMSK1_CERR (BIT(8) | BIT(0)) +#define ADF_200XX_ERRMSK5_CERR (0) + +/* Masks for uncorrectable error interrupts. */ +#define ADF_200XX_ERRMSK0_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_200XX_ERRMSK1_UERR (BIT(9) | BIT(1)) +#define ADF_200XX_ERRMSK3_UERR \ + (BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(0)) +#define ADF_200XX_ERRMSK5_UERR (BIT(16)) + +/* RI CPP control */ +#define ADF_200XX_RICPPINTCTL (0x3A000 + 0x110) +/* + * BIT(2) enables error detection and reporting on the RI Parity Error. + * BIT(1) enables error detection and reporting on the RI CPP Pull interface. + * BIT(0) enables error detection and reporting on the RI CPP Push interface. + */ +#define ADF_200XX_RICPP_EN (BIT(2) | BIT(1) | BIT(0)) + +/* TI CPP control */ +#define ADF_200XX_TICPPINTCTL (0x3A400 + 0x138) +/* + * BIT(3) enables error detection and reporting on the ETR Parity Error. + * BIT(2) enables error detection and reporting on the TI Parity Error. + * BIT(1) enables error detection and reporting on the TI CPP Pull interface. + * BIT(0) enables error detection and reporting on the TI CPP Push interface. + */ +#define ADF_200XX_TICPP_EN (BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +/* CFC Uncorrectable Errors */ +#define ADF_200XX_CPP_CFC_ERR_CTRL (0x30000 + 0xC00) +/* + * BIT(1) enables interrupt. + * BIT(0) enables detecting and logging of push/pull data errors. + */ +#define ADF_200XX_CPP_CFC_UE (BIT(1) | BIT(0)) + +#define ADF_200XX_SLICEPWRDOWN(i) ((i)*0x4000 + 0x2C) +/* Enabling PKE4-PKE0. */ +#define ADF_200XX_MMP_PWR_UP_MSK \ + (BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16)) + +/* CPM Uncorrectable Errors */ +#define ADF_200XX_INTMASKSSM(i) ((i)*0x4000 + 0x0) +/* Disabling interrupts for correctable errors. */ +#define ADF_200XX_INTMASKSSM_UERR \ + (BIT(11) | BIT(9) | BIT(7) | BIT(5) | BIT(3) | BIT(1)) + +/* MMP */ +/* BIT(3) enables correction. */ +#define ADF_200XX_CERRSSMMMP_EN (BIT(3)) + +/* BIT(3) enables logging. */ +#define ADF_200XX_UERRSSMMMP_EN (BIT(3)) + +#define ADF_200XX_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i)*0x04)) +#define ADF_200XX_VINTMSK_OFFSET(i) (0x3A000 + 0x200 + ((i)*0x04)) + +/* Arbiter configuration */ +#define ADF_200XX_ARB_OFFSET 0x30000 +#define ADF_200XX_ARB_WRK_2_SER_MAP_OFFSET 0x180 +#define ADF_200XX_ARB_WQCFG_OFFSET 0x100 + +/* Admin Interface Reg Offset */ +#define ADF_200XX_ADMINMSGUR_OFFSET (0x3A000 + 0x574) +#define ADF_200XX_ADMINMSGLR_OFFSET (0x3A000 + 0x578) +#define ADF_200XX_MAILBOX_BASE_OFFSET 0x20970 + +/* Firmware Binary */ +#define ADF_200XX_FW "qat_200xx_fw" +#define ADF_200XX_MMP "qat_200xx_mmp_fw" + +void adf_init_hw_data_200xx(struct adf_hw_device_data *hw_data); +void adf_clean_hw_data_200xx(struct adf_hw_device_data *hw_data); + +#define ADF_200XX_AE_FREQ (685 * 1000000) +#define ADF_200XX_MIN_AE_FREQ (333 * 1000000) +#define ADF_200XX_MAX_AE_FREQ (685 * 1000000) + +#endif diff --git a/sys/dev/qat/qat_hw/qat_200xx/adf_drv.c b/sys/dev/qat/qat_hw/qat_200xx/adf_drv.c new file mode 100644 index 00000000000..65626ac4b56 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_200xx/adf_drv.c @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_200xx_hw_data.h" +#include "adf_fw_counters.h" +#include "adf_cfg_device.h" +#include +#include +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_cnvnr_freq_counters.h" + +static MALLOC_DEFINE(M_QAT_200XX, "qat_200xx", "qat_200xx"); + +#define ADF_SYSTEM_DEVICE(device_id) \ + { \ + PCI_VENDOR_ID_INTEL, device_id \ + } + +static const struct pci_device_id adf_pci_tbl[] = + { ADF_SYSTEM_DEVICE(ADF_200XX_PCI_DEVICE_ID), + { + 0, + } }; + +static int +adf_probe(device_t dev) +{ + const struct pci_device_id *id; + + for (id = adf_pci_tbl; id->vendor != 0; id++) { + if (pci_get_vendor(dev) == id->vendor && + pci_get_device(dev) == id->device) { + device_set_desc(dev, + "Intel " ADF_200XX_DEVICE_NAME + " QuickAssist"); + return BUS_PROBE_GENERIC; + } + } + return ENXIO; +} + +static void +adf_cleanup_accel(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; + int i; + + if (accel_dev->dma_tag) + bus_dma_tag_destroy(accel_dev->dma_tag); + for (i = 0; i < ADF_PCI_MAX_BARS; i++) { + struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; + + if (bar->virt_addr) + bus_free_resource(accel_pci_dev->pci_dev, + SYS_RES_MEMORY, + bar->virt_addr); + } + + if (accel_dev->hw_device) { + switch (pci_get_device(accel_pci_dev->pci_dev)) { + case ADF_200XX_PCI_DEVICE_ID: + adf_clean_hw_data_200xx(accel_dev->hw_device); + break; + default: + break; + } + free(accel_dev->hw_device, M_QAT_200XX); + accel_dev->hw_device = NULL; + } + adf_cfg_dev_remove(accel_dev); + adf_devmgr_rm_dev(accel_dev, NULL); +} + +static int +adf_attach(device_t dev) +{ + struct adf_accel_dev *accel_dev; + struct adf_accel_pci *accel_pci_dev; + struct adf_hw_device_data *hw_data; + unsigned int i = 0, bar_nr = 0, reg_val = 0; + int ret, rid; + struct adf_cfg_device *cfg_dev = NULL; + + /* Set pci MaxPayLoad to 256. Implemented to avoid the issue of + * Pci-passthrough causing Maxpayload to be reset to 128 bytes + * when the device is reset. + */ + if (pci_get_max_payload(dev) != 256) + pci_set_max_payload(dev, 256); + + accel_dev = device_get_softc(dev); + + INIT_LIST_HEAD(&accel_dev->crypto_list); + accel_pci_dev = &accel_dev->accel_pci_dev; + accel_pci_dev->pci_dev = dev; + + if (bus_get_domain(dev, &accel_pci_dev->node) != 0) + accel_pci_dev->node = 0; + + /* XXX: Revisit if we actually need a devmgr table at all. */ + + /* Add accel device to accel table. + * This should be called before adf_cleanup_accel is called + */ + if (adf_devmgr_add_dev(accel_dev, NULL)) { + device_printf(dev, "Failed to add new accelerator device.\n"); + return ENXIO; + } + + /* Allocate and configure device configuration structure */ + hw_data = malloc(sizeof(*hw_data), M_QAT_200XX, M_WAITOK | M_ZERO); + + accel_dev->hw_device = hw_data; + adf_init_hw_data_200xx(accel_dev->hw_device); + accel_pci_dev->revid = pci_get_revid(dev); + hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4); + if (accel_pci_dev->revid == 0x00) { + device_printf(dev, "A0 stepping is not supported.\n"); + ret = ENODEV; + goto out_err; + } + + /* Get PPAERUCM values and store */ + ret = adf_aer_store_ppaerucm_reg(dev, hw_data); + if (ret) + goto out_err; + + /* Clear PFIEERRUNCSTSR register bits if they are set */ + reg_val = pci_read_config(dev, ADF_200XX_PFIEERRUNCSTSR, 4); + if (reg_val) { + device_printf( + dev, + "Clearing PFIEERRUNCSTSR, previous status : %0x\n", + reg_val); + pci_write_config(dev, ADF_200XX_PFIEERRUNCSTSR, reg_val, 4); + } + + /* Get Accelerators and Accelerators Engines masks */ + hw_data->accel_mask = hw_data->get_accel_mask(accel_dev); + hw_data->ae_mask = hw_data->get_ae_mask(accel_dev); + + accel_pci_dev->sku = hw_data->get_sku(hw_data); + /* If the device has no acceleration engines then ignore it. */ + if (!hw_data->accel_mask || !hw_data->ae_mask || + (~hw_data->ae_mask & 0x01)) { + device_printf(dev, "No acceleration units found\n"); + ret = ENXIO; + goto out_err; + } + + /* Create device configuration table */ + ret = adf_cfg_dev_add(accel_dev); + if (ret) + goto out_err; + ret = adf_clock_debugfs_add(accel_dev); + if (ret) + goto out_err; + + pci_set_max_read_req(dev, 1024); + + ret = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, + NULL, + BUS_SPACE_MAXSIZE, + /* BUS_SPACE_UNRESTRICTED */ 1, + BUS_SPACE_MAXSIZE, + 0, + NULL, + NULL, + &accel_dev->dma_tag); + if (ret) + goto out_err; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + /* Find and map all the device's BARS */ + for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0; + bar_nr++) { + struct adf_bar *bar; + + /* + * XXX: This isn't quite right as it will ignore a BAR + * that wasn't assigned a valid resource range by the + * firmware. + */ + rid = PCIR_BAR(bar_nr); + if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0) + continue; + bar = &accel_pci_dev->pci_bars[i++]; + bar->virt_addr = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, + &rid, + RF_ACTIVE); + if (!bar->virt_addr) { + device_printf(dev, "Failed to map BAR %d\n", bar_nr); + ret = ENXIO; + goto out_err; + } + bar->base_addr = rman_get_start(bar->virt_addr); + bar->size = rman_get_size(bar->virt_addr); + } + pci_enable_busmaster(dev); + + if (!accel_dev->hw_device->config_device) { + ret = EFAULT; + goto out_err; + } + + ret = accel_dev->hw_device->config_device(accel_dev); + if (ret) + goto out_err; + + ret = adf_dev_init(accel_dev); + if (ret) + goto out_dev_shutdown; + + ret = adf_dev_start(accel_dev); + if (ret) + goto out_dev_stop; + + cfg_dev = accel_dev->cfg->dev; + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + return ret; +out_dev_stop: + adf_dev_stop(accel_dev); +out_dev_shutdown: + adf_dev_shutdown(accel_dev); +out_err: + adf_cleanup_accel(accel_dev); + return ret; +} + +static int +adf_detach(device_t dev) +{ + struct adf_accel_dev *accel_dev = device_get_softc(dev); + + if (adf_dev_stop(accel_dev)) { + device_printf(dev, "Failed to stop QAT accel dev\n"); + return EBUSY; + } + + adf_dev_shutdown(accel_dev); + + adf_cleanup_accel(accel_dev); + + return 0; +} + +static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe), + DEVMETHOD(device_attach, adf_attach), + DEVMETHOD(device_detach, adf_detach), + + DEVMETHOD_END }; + +static driver_t adf_driver = { "qat", + adf_methods, + sizeof(struct adf_accel_dev) }; + +DRIVER_MODULE_ORDERED(qat_200xx, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD); +MODULE_VERSION(qat_200xx, 1); +MODULE_DEPEND(qat_200xx, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_200xx, qat_api, 1, 1, 1); +MODULE_DEPEND(qat_200xx, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.c b/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.c new file mode 100644 index 00000000000..5f7fe324935 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.c @@ -0,0 +1,415 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include +#include +#include "adf_c3xxx_hw_data.h" +#include "icp_qat_hw.h" +#include "adf_heartbeat.h" + +/* Worker thread to service arbiter mappings */ +static const u32 thrd_to_arb_map[ADF_C3XXX_MAX_ACCELENGINES] = + { 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA }; + +enum { DEV_C3XXX_SKU_1 = 0, DEV_C3XXX_SKU_2 = 1, DEV_C3XXX_SKU_3 = 2 }; + +static u32 thrd_to_arb_map_gen[ADF_C3XXX_MAX_ACCELENGINES] = { 0 }; + +static struct adf_hw_device_class c3xxx_class = {.name = ADF_C3XXX_DEVICE_NAME, + .type = DEV_C3XXX, + .instances = 0 }; + +static u32 +get_accel_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + + u32 fuse; + u32 straps; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + straps = pci_read_config(pdev, ADF_C3XXX_SOFTSTRAP_CSR_OFFSET, 4); + + return (~(fuse | straps)) >> ADF_C3XXX_ACCELERATORS_REG_OFFSET & + ADF_C3XXX_ACCELERATORS_MASK; +} + +static u32 +get_ae_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fuse; + u32 me_straps; + u32 me_disable; + u32 ssms_disabled; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + me_straps = pci_read_config(pdev, ADF_C3XXX_SOFTSTRAP_CSR_OFFSET, 4); + + /* If SSMs are disabled, then disable the corresponding MEs */ + ssms_disabled = + (~get_accel_mask(accel_dev)) & ADF_C3XXX_ACCELERATORS_MASK; + me_disable = 0x3; + while (ssms_disabled) { + if (ssms_disabled & 1) + me_straps |= me_disable; + ssms_disabled >>= 1; + me_disable <<= 2; + } + + return (~(fuse | me_straps)) & ADF_C3XXX_ACCELENGINES_MASK; +} + +static u32 +get_num_accels(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->accel_mask) + return 0; + + for (i = 0; i < ADF_C3XXX_MAX_ACCELERATORS; i++) { + if (self->accel_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_num_aes(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->ae_mask) + return 0; + + for (i = 0; i < ADF_C3XXX_MAX_ACCELENGINES; i++) { + if (self->ae_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_misc_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C3XXX_PMISC_BAR; +} + +static u32 +get_etr_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C3XXX_ETR_BAR; +} + +static u32 +get_sram_bar_id(struct adf_hw_device_data *self) +{ + return 0; +} + +static enum dev_sku_info +get_sku(struct adf_hw_device_data *self) +{ + int aes = get_num_aes(self); + + if (aes == 6) + return DEV_SKU_4; + + return DEV_SKU_UNKNOWN; +} + +static void +adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev, + u32 const **arb_map_config) +{ + int i; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + for (i = 0; i < ADF_C3XXX_MAX_ACCELENGINES; i++) { + thrd_to_arb_map_gen[i] = 0; + if (hw_device->ae_mask & (1 << i)) + thrd_to_arb_map_gen[i] = thrd_to_arb_map[i]; + } + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map, + thrd_to_arb_map_gen, + ADF_C3XXX_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; +} + +static u32 +get_pf2vf_offset(u32 i) +{ + return ADF_C3XXX_PF2VF_OFFSET(i); +} + +static u32 +get_vintmsk_offset(u32 i) +{ + return ADF_C3XXX_VINTMSK_OFFSET(i); +} + +static void +get_arb_info(struct arb_info *arb_csrs_info) +{ + arb_csrs_info->arbiter_offset = ADF_C3XXX_ARB_OFFSET; + arb_csrs_info->wrk_thd_2_srv_arb_map = + ADF_C3XXX_ARB_WRK_2_SER_MAP_OFFSET; + arb_csrs_info->wrk_cfg_offset = ADF_C3XXX_ARB_WQCFG_OFFSET; +} + +static void +get_admin_info(struct admin_info *admin_csrs_info) +{ + admin_csrs_info->mailbox_offset = ADF_C3XXX_MAILBOX_BASE_OFFSET; + admin_csrs_info->admin_msg_ur = ADF_C3XXX_ADMINMSGUR_OFFSET; + admin_csrs_info->admin_msg_lr = ADF_C3XXX_ADMINMSGLR_OFFSET; +} + +static void +get_errsou_offset(u32 *errsou3, u32 *errsou5) +{ + *errsou3 = ADF_C3XXX_ERRSOU3; + *errsou5 = ADF_C3XXX_ERRSOU5; +} + +static u32 +get_clock_speed(struct adf_hw_device_data *self) +{ + /* CPP clock is half high-speed clock */ + return self->clock_frequency / 2; +} + +static void +adf_enable_error_correction(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_C3XXX_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + unsigned int val, i; + unsigned int mask; + + /* Enable Accel Engine error detection & correction */ + mask = hw_device->ae_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_C3XXX_AE_CTX_ENABLES(i)); + val |= ADF_C3XXX_ENABLE_AE_ECC_ERR; + ADF_CSR_WR(csr, ADF_C3XXX_AE_CTX_ENABLES(i), val); + val = ADF_CSR_RD(csr, ADF_C3XXX_AE_MISC_CONTROL(i)); + val |= ADF_C3XXX_ENABLE_AE_ECC_PARITY_CORR; + ADF_CSR_WR(csr, ADF_C3XXX_AE_MISC_CONTROL(i), val); + } + + /* Enable shared memory error detection & correction */ + mask = hw_device->accel_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_C3XXX_UERRSSMSH(i)); + val |= ADF_C3XXX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C3XXX_UERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_C3XXX_CERRSSMSH(i)); + val |= ADF_C3XXX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C3XXX_CERRSSMSH(i), val); + } +} + +static void +adf_enable_ints(struct adf_accel_dev *accel_dev) +{ + struct resource *addr; + + addr = (&GET_BARS(accel_dev)[ADF_C3XXX_PMISC_BAR])->virt_addr; + + /* Enable bundle and misc interrupts */ + ADF_CSR_WR(addr, ADF_C3XXX_SMIAPF0_MASK_OFFSET, ADF_C3XXX_SMIA0_MASK); + ADF_CSR_WR(addr, ADF_C3XXX_SMIAPF1_MASK_OFFSET, ADF_C3XXX_SMIA1_MASK); +} + +static u32 +get_ae_clock(struct adf_hw_device_data *self) +{ + /* + * Clock update interval is <16> ticks for c3xxx. + */ + return self->clock_frequency / 16; +} + +static int +get_storage_enabled(struct adf_accel_dev *accel_dev, uint32_t *storage_enabled) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + strlcpy(key, ADF_STORAGE_FIRMWARE_ENABLED, sizeof(key)); + if (!adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) { + if (kstrtouint(val, 0, storage_enabled)) + return -EFAULT; + } + return 0; +} + +static int +measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret = 0; + + ret = adf_dev_measure_clock(accel_dev, + &frequency, + ADF_C3XXX_MIN_AE_FREQ, + ADF_C3XXX_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + +static u32 +c3xxx_get_hw_cap(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuses; + u32 capabilities; + u32 straps; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 fuses = hw_data->fuses; + + /* Read accelerator capabilities mask */ + legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC + + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC + + ICP_ACCEL_CAPABILITIES_CIPHER + + ICP_ACCEL_CAPABILITIES_AUTHENTICATION + + ICP_ACCEL_CAPABILITIES_COMPRESSION + ICP_ACCEL_CAPABILITIES_ZUC + + ICP_ACCEL_CAPABILITIES_SHA3 + ICP_ACCEL_CAPABILITIES_HKDF + + ICP_ACCEL_CAPABILITIES_ECEDMONT + + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN; + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_HKDF | + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN); + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_ECEDMONT); + if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + if (legfuses & ICP_ACCEL_MASK_EIA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_ZUC; + if (legfuses & ICP_ACCEL_MASK_SHA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_SHA3; + + straps = pci_read_config(pdev, ADF_C3XXX_SOFTSTRAP_CSR_OFFSET, 4); + if ((straps | fuses) & ADF_C3XXX_POWERGATE_PKE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + if ((straps | fuses) & ADF_C3XXX_POWERGATE_CY) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + + return capabilities; +} + +static const char * +get_obj_name(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + return ADF_CXXX_AE_FW_NAME_CUSTOM1; +} + +static uint32_t +get_objs_num(struct adf_accel_dev *accel_dev) +{ + return 1; +} + +static uint32_t +get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services) +{ + return accel_dev->hw_device->ae_mask; +} + +void +adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class = &c3xxx_class; + hw_data->instance_id = c3xxx_class.instances++; + hw_data->num_banks = ADF_C3XXX_ETR_MAX_BANKS; + hw_data->num_rings_per_bank = ADF_ETR_MAX_RINGS_PER_BANK; + hw_data->num_accel = ADF_C3XXX_MAX_ACCELERATORS; + hw_data->num_logical_accel = 1; + hw_data->num_engines = ADF_C3XXX_MAX_ACCELENGINES; + hw_data->tx_rx_gap = ADF_C3XXX_RX_RINGS_OFFSET; + hw_data->tx_rings_mask = ADF_C3XXX_TX_RINGS_MASK; + hw_data->alloc_irq = adf_isr_resource_alloc; + hw_data->free_irq = adf_isr_resource_free; + hw_data->enable_error_correction = adf_enable_error_correction; + hw_data->print_err_registers = adf_print_err_registers; + hw_data->get_accel_mask = get_accel_mask; + hw_data->get_ae_mask = get_ae_mask; + hw_data->get_num_accels = get_num_accels; + hw_data->get_num_aes = get_num_aes; + hw_data->get_sram_bar_id = get_sram_bar_id; + hw_data->get_etr_bar_id = get_etr_bar_id; + hw_data->get_misc_bar_id = get_misc_bar_id; + hw_data->get_pf2vf_offset = get_pf2vf_offset; + hw_data->get_vintmsk_offset = get_vintmsk_offset; + hw_data->get_arb_info = get_arb_info; + hw_data->get_admin_info = get_admin_info; + hw_data->get_errsou_offset = get_errsou_offset; + hw_data->get_clock_speed = get_clock_speed; + hw_data->get_sku = get_sku; + hw_data->fw_name = ADF_C3XXX_FW; + hw_data->fw_mmp_name = ADF_C3XXX_MMP; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->disable_iov = adf_disable_sriov; + hw_data->send_admin_init = adf_send_admin_init; + hw_data->init_arb = adf_init_gen2_arb; + hw_data->exit_arb = adf_exit_arb; + hw_data->get_arb_mapping = adf_get_arbiter_mapping; + hw_data->enable_ints = adf_enable_ints; + hw_data->set_ssm_wdtimer = adf_set_ssm_wdtimer; + hw_data->check_slice_hang = adf_check_slice_hang; + hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms; + hw_data->disable_vf2pf_comms = adf_pf_disable_vf2pf_comms; + hw_data->restore_device = adf_dev_restore; + hw_data->reset_device = adf_reset_flr; + hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION; + hw_data->measure_clock = measure_clock; + hw_data->get_ae_clock = get_ae_clock; + hw_data->reset_device = adf_reset_flr; + hw_data->get_objs_num = get_objs_num; + hw_data->get_obj_name = get_obj_name; + hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; + hw_data->get_accel_cap = c3xxx_get_hw_cap; + hw_data->clock_frequency = ADF_C3XXX_AE_FREQ; + hw_data->extended_dc_capabilities = 0; + hw_data->get_storage_enabled = get_storage_enabled; + hw_data->query_storage_cap = 1; + hw_data->get_heartbeat_status = adf_get_heartbeat_status; + hw_data->get_ae_clock = get_ae_clock; + hw_data->storage_enable = 0; + hw_data->get_fw_image_type = adf_cfg_get_fw_image_type; + hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled; + hw_data->config_device = adf_config_device; + hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask; + hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP; + hw_data->pre_reset = adf_dev_pre_reset; + hw_data->post_reset = adf_dev_post_reset; +} + +void +adf_clean_hw_data_c3xxx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class->instances--; +} diff --git a/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.h b/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.h new file mode 100644 index 00000000000..1082bd61faf --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c3xxx/adf_c3xxx_hw_data.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C3XXX_HW_DATA_H_ +#define ADF_C3XXX_HW_DATA_H_ + +/* PCIe configuration space */ +#define ADF_C3XXX_PMISC_BAR 0 +#define ADF_C3XXX_ETR_BAR 1 +#define ADF_C3XXX_RX_RINGS_OFFSET 8 +#define ADF_C3XXX_TX_RINGS_MASK 0xFF +#define ADF_C3XXX_MAX_ACCELERATORS 3 +#define ADF_C3XXX_MAX_ACCELENGINES 6 +#define ADF_C3XXX_ACCELERATORS_REG_OFFSET 16 +#define ADF_C3XXX_ACCELERATORS_MASK 0x7 +#define ADF_C3XXX_ACCELENGINES_MASK 0x3F +#define ADF_C3XXX_ETR_MAX_BANKS 16 +#define ADF_C3XXX_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) +#define ADF_C3XXX_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) +#define ADF_C3XXX_SMIA0_MASK 0xFFFF +#define ADF_C3XXX_SMIA1_MASK 0x1 +#define ADF_C3XXX_SOFTSTRAP_CSR_OFFSET 0x2EC +#define ADF_C3XXX_POWERGATE_PKE BIT(24) +#define ADF_C3XXX_POWERGATE_CY BIT(23) + +/* Error detection and correction */ +#define ADF_C3XXX_AE_CTX_ENABLES(i) (i * 0x1000 + 0x20818) +#define ADF_C3XXX_AE_MISC_CONTROL(i) (i * 0x1000 + 0x20960) +#define ADF_C3XXX_ENABLE_AE_ECC_ERR BIT(28) +#define ADF_C3XXX_ENABLE_AE_ECC_PARITY_CORR (BIT(24) | BIT(12)) +#define ADF_C3XXX_UERRSSMSH(i) (i * 0x4000 + 0x18) +#define ADF_C3XXX_CERRSSMSH(i) (i * 0x4000 + 0x10) +#define ADF_C3XXX_ERRSSMSH_EN BIT(3) +#define ADF_C3XXX_ERRSOU3 (0x3A000 + 0x0C) +#define ADF_C3XXX_ERRSOU5 (0x3A000 + 0xD8) + +/* BIT(2) enables the logging of push/pull data errors. */ +#define ADF_C3XXX_PPERR_EN (BIT(2)) + +/* Mask for VF2PF interrupts */ +#define ADF_C3XXX_VF2PF1_16 (0xFFFF << 9) +#define ADF_C3XXX_ERRSOU3_VF2PF(errsou3) (((errsou3)&0x01FFFE00) >> 9) +#define ADF_C3XXX_ERRMSK3_VF2PF(vf_mask) (((vf_mask)&0xFFFF) << 9) + +/* Masks for correctable error interrupts. */ +#define ADF_C3XXX_ERRMSK0_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_C3XXX_ERRMSK1_CERR (BIT(8) | BIT(0)) +#define ADF_C3XXX_ERRMSK5_CERR (0) + +/* Masks for uncorrectable error interrupts. */ +#define ADF_C3XXX_ERRMSK0_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_C3XXX_ERRMSK1_UERR (BIT(9) | BIT(1)) +#define ADF_C3XXX_ERRMSK3_UERR \ + (BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(0)) +#define ADF_C3XXX_ERRMSK5_UERR (BIT(16)) + +/* RI CPP control */ +#define ADF_C3XXX_RICPPINTCTL (0x3A000 + 0x110) +/* + * BIT(2) enables error detection and reporting on the RI Parity Error. + * BIT(1) enables error detection and reporting on the RI CPP Pull interface. + * BIT(0) enables error detection and reporting on the RI CPP Push interface. + */ +#define ADF_C3XXX_RICPP_EN (BIT(2) | BIT(1) | BIT(0)) + +/* TI CPP control */ +#define ADF_C3XXX_TICPPINTCTL (0x3A400 + 0x138) +/* + * BIT(3) enables error detection and reporting on the ETR Parity Error. + * BIT(2) enables error detection and reporting on the TI Parity Error. + * BIT(1) enables error detection and reporting on the TI CPP Pull interface. + * BIT(0) enables error detection and reporting on the TI CPP Push interface. + */ +#define ADF_C3XXX_TICPP_EN (BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +/* CFC Uncorrectable Errors */ +#define ADF_C3XXX_CPP_CFC_ERR_CTRL (0x30000 + 0xC00) +/* + * BIT(1) enables interrupt. + * BIT(0) enables detecting and logging of push/pull data errors. + */ +#define ADF_C3XXX_CPP_CFC_UE (BIT(1) | BIT(0)) + +#define ADF_C3XXX_SLICEPWRDOWN(i) ((i)*0x4000 + 0x2C) +/* Enabling PKE4-PKE0. */ +#define ADF_C3XXX_MMP_PWR_UP_MSK \ + (BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16)) + +/* CPM Uncorrectable Errors */ +#define ADF_C3XXX_INTMASKSSM(i) ((i)*0x4000 + 0x0) +/* Disabling interrupts for correctable errors. */ +#define ADF_C3XXX_INTMASKSSM_UERR \ + (BIT(11) | BIT(9) | BIT(7) | BIT(5) | BIT(3) | BIT(1)) + +/* MMP */ +/* BIT(3) enables correction. */ +#define ADF_C3XXX_CERRSSMMMP_EN (BIT(3)) + +#define ADF_C3X_CLK_PER_SEC (343 * 1000000) +/* BIT(3) enables logging. */ +#define ADF_C3XXX_UERRSSMMMP_EN (BIT(3)) + +#define ADF_C3XXX_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i)*0x04)) +#define ADF_C3XXX_VINTMSK_OFFSET(i) (0x3A000 + 0x200 + ((i)*0x04)) + +/* Arbiter configuration */ +#define ADF_C3XXX_ARB_OFFSET 0x30000 +#define ADF_C3XXX_ARB_WRK_2_SER_MAP_OFFSET 0x180 +#define ADF_C3XXX_ARB_WQCFG_OFFSET 0x100 + +/* Admin Interface Reg Offset */ +#define ADF_C3XXX_ADMINMSGUR_OFFSET (0x3A000 + 0x574) +#define ADF_C3XXX_ADMINMSGLR_OFFSET (0x3A000 + 0x578) +#define ADF_C3XXX_MAILBOX_BASE_OFFSET 0x20970 + +/* Firmware Binary */ +#define ADF_C3XXX_FW "qat_c3xxx_fw" +#define ADF_C3XXX_MMP "qat_c3xxx_mmp_fw" + +void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data); +void adf_clean_hw_data_c3xxx(struct adf_hw_device_data *hw_data); + +#define ADF_C3XXX_AE_FREQ (685 * 1000000) +#define ADF_C3XXX_MIN_AE_FREQ (320 * 1000000) +#define ADF_C3XXX_MAX_AE_FREQ (685 * 1000000) + +#endif diff --git a/sys/dev/qat/qat_hw/qat_c3xxx/adf_drv.c b/sys/dev/qat/qat_hw/qat_c3xxx/adf_drv.c new file mode 100644 index 00000000000..307be8d3187 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c3xxx/adf_drv.c @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_c3xxx_hw_data.h" +#include "adf_fw_counters.h" +#include "adf_cfg_device.h" +#include +#include +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_cnvnr_freq_counters.h" + +static MALLOC_DEFINE(M_QAT_C3XXX, "qat_c3xxx", "qat_c3xxx"); + +#define ADF_SYSTEM_DEVICE(device_id) \ + { \ + PCI_VENDOR_ID_INTEL, device_id \ + } + +static const struct pci_device_id adf_pci_tbl[] = + { ADF_SYSTEM_DEVICE(ADF_C3XXX_PCI_DEVICE_ID), + { + 0, + } }; + +static int +adf_probe(device_t dev) +{ + const struct pci_device_id *id; + + for (id = adf_pci_tbl; id->vendor != 0; id++) { + if (pci_get_vendor(dev) == id->vendor && + pci_get_device(dev) == id->device) { + device_set_desc(dev, + "Intel " ADF_C3XXX_DEVICE_NAME + " QuickAssist"); + return BUS_PROBE_GENERIC; + } + } + return ENXIO; +} + +static void +adf_cleanup_accel(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; + int i; + + if (accel_dev->dma_tag) + bus_dma_tag_destroy(accel_dev->dma_tag); + for (i = 0; i < ADF_PCI_MAX_BARS; i++) { + struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; + + if (bar->virt_addr) + bus_free_resource(accel_pci_dev->pci_dev, + SYS_RES_MEMORY, + bar->virt_addr); + } + + if (accel_dev->hw_device) { + switch (pci_get_device(accel_pci_dev->pci_dev)) { + case ADF_C3XXX_PCI_DEVICE_ID: + adf_clean_hw_data_c3xxx(accel_dev->hw_device); + break; + default: + break; + } + free(accel_dev->hw_device, M_QAT_C3XXX); + accel_dev->hw_device = NULL; + } + adf_cfg_dev_remove(accel_dev); + adf_devmgr_rm_dev(accel_dev, NULL); +} + +static int +adf_attach(device_t dev) +{ + struct adf_accel_dev *accel_dev; + struct adf_accel_pci *accel_pci_dev; + struct adf_hw_device_data *hw_data; + unsigned int i, bar_nr; + int ret, rid; + struct adf_cfg_device *cfg_dev = NULL; + + /* Set pci MaxPayLoad to 256. Implemented to avoid the issue of + * Pci-passthrough causing Maxpayload to be reset to 128 bytes + * when the device is reset. */ + if (pci_get_max_payload(dev) != 256) + pci_set_max_payload(dev, 256); + + accel_dev = device_get_softc(dev); + + INIT_LIST_HEAD(&accel_dev->crypto_list); + accel_pci_dev = &accel_dev->accel_pci_dev; + accel_pci_dev->pci_dev = dev; + + if (bus_get_domain(dev, &accel_pci_dev->node) != 0) + accel_pci_dev->node = 0; + + /* XXX: Revisit if we actually need a devmgr table at all. */ + + /* Add accel device to accel table. + * This should be called before adf_cleanup_accel is called */ + if (adf_devmgr_add_dev(accel_dev, NULL)) { + device_printf(dev, "Failed to add new accelerator device.\n"); + return ENXIO; + } + + /* Allocate and configure device configuration structure */ + hw_data = malloc(sizeof(*hw_data), M_QAT_C3XXX, M_WAITOK | M_ZERO); + + accel_dev->hw_device = hw_data; + adf_init_hw_data_c3xxx(accel_dev->hw_device); + accel_pci_dev->revid = pci_get_revid(dev); + hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4); + if (accel_pci_dev->revid == 0x00) { + device_printf(dev, "A0 stepping is not supported.\n"); + ret = ENODEV; + goto out_err; + } + + /* Get PPAERUCM values and store */ + ret = adf_aer_store_ppaerucm_reg(dev, hw_data); + if (ret) + goto out_err; + + /* Get Accelerators and Accelerators Engines masks */ + hw_data->accel_mask = hw_data->get_accel_mask(accel_dev); + hw_data->ae_mask = hw_data->get_ae_mask(accel_dev); + + accel_pci_dev->sku = hw_data->get_sku(hw_data); + /* If the device has no acceleration engines then ignore it. */ + if (!hw_data->accel_mask || !hw_data->ae_mask || + ((~hw_data->ae_mask) & 0x01)) { + device_printf(dev, "No acceleration units found\n"); + ret = ENXIO; + goto out_err; + } + + /* Create device configuration table */ + ret = adf_cfg_dev_add(accel_dev); + if (ret) + goto out_err; + ret = adf_clock_debugfs_add(accel_dev); + if (ret) + goto out_err; + + pci_set_max_read_req(dev, 1024); + + ret = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, + NULL, + BUS_SPACE_MAXSIZE, + /* BUS_SPACE_UNRESTRICTED */ 1, + BUS_SPACE_MAXSIZE, + 0, + NULL, + NULL, + &accel_dev->dma_tag); + if (ret) + goto out_err; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + /* Find and map all the device's BARS */ + i = 0; + for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0; + bar_nr++) { + struct adf_bar *bar; + + /* + * XXX: This isn't quite right as it will ignore a BAR + * that wasn't assigned a valid resource range by the + * firmware. + */ + rid = PCIR_BAR(bar_nr); + if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0) + continue; + bar = &accel_pci_dev->pci_bars[i++]; + bar->virt_addr = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, + &rid, + RF_ACTIVE); + if (bar->virt_addr == NULL) { + device_printf(dev, "Failed to map BAR %d\n", bar_nr); + ret = ENXIO; + goto out_err; + } + bar->base_addr = rman_get_start(bar->virt_addr); + bar->size = rman_get_size(bar->virt_addr); + } + pci_enable_busmaster(dev); + + if (!accel_dev->hw_device->config_device) { + ret = EFAULT; + goto out_err; + } + + ret = accel_dev->hw_device->config_device(accel_dev); + if (ret) + goto out_err; + + ret = adf_dev_init(accel_dev); + if (ret) + goto out_dev_shutdown; + + ret = adf_dev_start(accel_dev); + if (ret) + goto out_dev_stop; + + cfg_dev = accel_dev->cfg->dev; + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + return ret; +out_dev_stop: + adf_dev_stop(accel_dev); +out_dev_shutdown: + adf_dev_shutdown(accel_dev); +out_err: + adf_cleanup_accel(accel_dev); + return ret; +} + +static int +adf_detach(device_t dev) +{ + struct adf_accel_dev *accel_dev = device_get_softc(dev); + + if (adf_dev_stop(accel_dev)) { + device_printf(dev, "Failed to stop QAT accel dev\n"); + return EBUSY; + } + + adf_dev_shutdown(accel_dev); + + adf_cleanup_accel(accel_dev); + + return 0; +} + +static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe), + DEVMETHOD(device_attach, adf_attach), + DEVMETHOD(device_detach, adf_detach), + + DEVMETHOD_END }; + +static driver_t adf_driver = { "qat", + adf_methods, + sizeof(struct adf_accel_dev) }; + +DRIVER_MODULE_ORDERED(qat_c3xxx, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD); +MODULE_VERSION(qat_c3xxx, 1); +MODULE_DEPEND(qat_c3xxx, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_c3xxx, qat_api, 1, 1, 1); +MODULE_DEPEND(qat_c3xxx, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ae_config.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ae_config.c new file mode 100644 index 00000000000..3dec7d07243 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ae_config.c @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_c4xxx_hw_data.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* String buffer size */ +#define AE_INFO_BUFFER_SIZE 50 + +#define AE_CONFIG_DBG_FILE "ae_config" + +static u8 +find_first_me_index(const u32 au_mask) +{ + u8 i; + u32 mask = au_mask; + + /* Retrieve the index of the first ME of an accel unit */ + for (i = 0; i < ADF_C4XXX_MAX_ACCELENGINES; i++) { + if (mask & BIT(i)) + return i; + } + + return 0; +} + +static u8 +get_au_index(u8 au_mask) +{ + u8 au_index = 0; + + while (au_mask) { + if (au_mask == BIT(0)) + return au_index; + au_index++; + au_mask = au_mask >> 1; + } + + return 0; +} + +static int adf_ae_config_show(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + struct adf_accel_dev *accel_dev = arg1; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct adf_accel_unit *accel_unit = accel_dev->au_info->au; + u8 i, j; + u8 au_index; + u8 ae_index; + u8 num_aes; + int ret = 0; + u32 num_au = hw_data->get_num_accel_units(hw_data); + + sbuf_new_for_sysctl(&sb, NULL, 2048, req); + + sbuf_printf(&sb, "\n"); + for (i = 0; i < num_au; i++) { + /* Retrieve accel unit index */ + au_index = get_au_index(accel_unit[i].au_mask); + + /* Retrieve index of fist ME in current accel unit */ + ae_index = find_first_me_index(accel_unit[i].ae_mask); + num_aes = accel_unit[i].num_ae; + + /* Retrieve accel unit type */ + switch (accel_unit[i].services) { + case ADF_ACCEL_CRYPTO: + sbuf_printf(&sb, + "\tAccel unit %d - CRYPTO\n", + au_index); + /* Display ME assignment for a particular accel unit */ + for (j = ae_index; j < (num_aes + ae_index); j++) + sbuf_printf(&sb, "\t\tAE[%d]: crypto\n", j); + break; + case ADF_ACCEL_COMPRESSION: + sbuf_printf(&sb, + "\tAccel unit %d - COMPRESSION\n", + au_index); + /* Display ME assignment for a particular accel unit */ + for (j = ae_index; j < (num_aes + ae_index); j++) + sbuf_printf(&sb, + "\t\tAE[%d]: compression\n", + j); + break; + case ADF_ACCEL_SERVICE_NULL: + default: + break; + } + } + + sbuf_finish(&sb); + ret = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); + sbuf_delete(&sb); + + return ret; +} + +static int +c4xxx_add_debugfs_ae_config(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx = NULL; + struct sysctl_oid *qat_sysctl_tree = NULL; + struct sysctl_oid *ae_conf_ctl = NULL; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + ae_conf_ctl = SYSCTL_ADD_PROC(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + AE_CONFIG_DBG_FILE, + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + adf_ae_config_show, + "A", + "AE config"); + accel_dev->debugfs_ae_config = ae_conf_ctl; + if (!accel_dev->debugfs_ae_config) { + device_printf(GET_DEV(accel_dev), + "Could not create debug ae config entry.\n"); + return EFAULT; + } + return 0; +} + +int +c4xxx_init_ae_config(struct adf_accel_dev *accel_dev) +{ + int ret = 0; + + /* Add a new file in debug file system with h/w version. */ + ret = c4xxx_add_debugfs_ae_config(accel_dev); + if (ret) { + c4xxx_exit_ae_config(accel_dev); + device_printf(GET_DEV(accel_dev), + "Could not create debugfs ae config file\n"); + return EINVAL; + } + + return 0; +} + +void +c4xxx_exit_ae_config(struct adf_accel_dev *accel_dev) +{ + if (!accel_dev->debugfs_ae_config) + return; + + /* Delete ae configuration file */ + remove_oid(accel_dev, accel_dev->debugfs_ae_config); + + accel_dev->debugfs_ae_config = NULL; +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.c new file mode 100644 index 00000000000..c8ff19d00bd --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.c @@ -0,0 +1,2302 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "adf_c4xxx_hw_data.h" +#include "adf_c4xxx_reset.h" +#include "adf_c4xxx_inline.h" +#include "adf_c4xxx_ras.h" +#include "adf_c4xxx_misc_error_stats.h" +#include "adf_c4xxx_pke_replay_stats.h" +#include "adf_heartbeat.h" +#include "icp_qat_fw_init_admin.h" +#include "icp_qat_hw.h" + +/* accel unit information */ +static struct adf_accel_unit adf_c4xxx_au_32_ae[] = + { { 0x1, 0x3, 0x3F, 0x1B, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x2, 0xC, 0xFC0, 0x6C0, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x4, 0x30, 0xF000, 0xF000, 4, ADF_ACCEL_SERVICE_NULL }, + { 0x8, 0xC0, 0x3F0000, 0x1B0000, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x10, 0x300, 0xFC00000, 0x6C00000, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x20, 0xC00, 0xF0000000, 0xF0000000, 4, ADF_ACCEL_SERVICE_NULL } }; + +static struct adf_accel_unit adf_c4xxx_au_24_ae[] = { + { 0x1, 0x3, 0x3F, 0x1B, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x2, 0xC, 0xFC0, 0x6C0, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x8, 0xC0, 0x3F0000, 0x1B0000, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x10, 0x300, 0xFC00000, 0x6C00000, 6, ADF_ACCEL_SERVICE_NULL }, +}; + +static struct adf_accel_unit adf_c4xxx_au_12_ae[] = { + { 0x1, 0x3, 0x3F, 0x1B, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x8, 0xC0, 0x3F0000, 0x1B0000, 6, ADF_ACCEL_SERVICE_NULL }, +}; + +static struct adf_accel_unit adf_c4xxx_au_emulation[] = + { { 0x1, 0x3, 0x3F, 0x1B, 6, ADF_ACCEL_SERVICE_NULL }, + { 0x2, 0xC, 0xC0, 0xC0, 2, ADF_ACCEL_SERVICE_NULL } }; + +/* Accel engine threads for each of the following services + * , , , + */ + +/* Thread mapping for SKU capable of symmetric cryptography */ +static const struct adf_ae_info adf_c4xxx_32_ae_sym[] = + { { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, + { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, + { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 2, 6, 3 } }; + +static const struct adf_ae_info adf_c4xxx_24_ae_sym[] = + { { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, + { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 1, 7, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, + { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 } }; + +static const struct adf_ae_info adf_c4xxx_12_ae_sym[] = + { { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, + { 1, 7, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 2, 6, 3 }, { 2, 6, 3 }, { 1, 7, 0 }, { 2, 6, 3 }, + { 2, 6, 3 }, { 1, 7, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 } }; + +/* Thread mapping for SKU capable of asymmetric and symmetric cryptography */ +static const struct adf_ae_info adf_c4xxx_32_ae[] = + { { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, + { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, + { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 2, 5, 3 } }; + +static const struct adf_ae_info adf_c4xxx_24_ae[] = + { { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, + { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 1, 6, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, + { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 } }; + +static const struct adf_ae_info adf_c4xxx_12_ae[] = + { { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, + { 1, 6, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 2, 5, 3 }, { 2, 5, 3 }, { 1, 6, 0 }, { 2, 5, 3 }, + { 2, 5, 3 }, { 1, 6, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, + { 0, 0, 0 }, { 0, 0, 0 } }; + +static struct adf_hw_device_class c4xxx_class = {.name = ADF_C4XXX_DEVICE_NAME, + .type = DEV_C4XXX, + .instances = 0 }; + +struct icp_qat_fw_init_c4xxx_admin_hb_stats { + struct icp_qat_fw_init_admin_hb_cnt stats[ADF_NUM_THREADS_PER_AE]; +}; + +struct adf_hb_count { + u16 ae_thread[ADF_NUM_THREADS_PER_AE]; +}; + +static const int sku_cy_au[] = ADF_C4XXX_NUM_CY_AU; +static const int sku_dc_au[] = ADF_C4XXX_NUM_DC_AU; +static const int sku_inline_au[] = ADF_C4XXX_NUM_INLINE_AU; + +/* + * C4xxx devices introduce new fuses and soft straps and + * are different from previous gen device implementations. + */ + +static u32 +get_accel_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fusectl0; + u32 softstrappull0; + + fusectl0 = pci_read_config(pdev, ADF_C4XXX_FUSECTL0_OFFSET, 4); + softstrappull0 = + pci_read_config(pdev, ADF_C4XXX_SOFTSTRAPPULL0_OFFSET, 4); + + return (~(fusectl0 | softstrappull0)) & ADF_C4XXX_ACCELERATORS_MASK; +} + +static u32 +get_ae_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fusectl1; + u32 softstrappull1; + + fusectl1 = pci_read_config(pdev, ADF_C4XXX_FUSECTL1_OFFSET, 4); + softstrappull1 = + pci_read_config(pdev, ADF_C4XXX_SOFTSTRAPPULL1_OFFSET, 4); + + /* Assume that AE and AU disable masks are consistent, so no + * checks against the AU mask are performed + */ + return (~(fusectl1 | softstrappull1)) & ADF_C4XXX_ACCELENGINES_MASK; +} + +static u32 +get_num_accels(struct adf_hw_device_data *self) +{ + return self ? hweight32(self->accel_mask) : 0; +} + +static u32 +get_num_aes(struct adf_hw_device_data *self) +{ + return self ? hweight32(self->ae_mask) : 0; +} + +static u32 +get_misc_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C4XXX_PMISC_BAR; +} + +static u32 +get_etr_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C4XXX_ETR_BAR; +} + +static u32 +get_sram_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C4XXX_SRAM_BAR; +} + +static inline void +c4xxx_unpack_ssm_wdtimer(u64 value, u32 *upper, u32 *lower) +{ + *lower = lower_32_bits(value); + *upper = upper_32_bits(value); +} + +/** + * c4xxx_set_ssm_wdtimer() - Initialize the slice hang watchdog timer. + * + * @param accel_dev Structure holding accelerator data. + * @return 0 on success, error code otherwise. + */ +static int +c4xxx_set_ssm_wdtimer(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = + &GET_BARS(accel_dev)[hw_device->get_misc_bar_id(hw_device)]; + struct resource *csr = misc_bar->virt_addr; + unsigned long accel_mask = hw_device->accel_mask; + u32 accel = 0; + u64 timer_val = ADF_C4XXX_SSM_WDT_64BIT_DEFAULT_VALUE; + u64 timer_val_pke = ADF_C4XXX_SSM_WDT_PKE_64BIT_DEFAULT_VALUE; + u32 ssm_wdt_low = 0, ssm_wdt_high = 0; + u32 ssm_wdt_pke_low = 0, ssm_wdt_pke_high = 0; + + /* Convert 64bit Slice Hang watchdog value into 32bit values for + * mmio write to 32bit CSRs. + */ + c4xxx_unpack_ssm_wdtimer(timer_val, &ssm_wdt_high, &ssm_wdt_low); + c4xxx_unpack_ssm_wdtimer(timer_val_pke, + &ssm_wdt_pke_high, + &ssm_wdt_pke_low); + + /* Configures Slice Hang watchdogs */ + for_each_set_bit(accel, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + ADF_CSR_WR(csr, ADF_C4XXX_SSMWDTL_OFFSET(accel), ssm_wdt_low); + ADF_CSR_WR(csr, ADF_C4XXX_SSMWDTH_OFFSET(accel), ssm_wdt_high); + ADF_CSR_WR(csr, + ADF_C4XXX_SSMWDTPKEL_OFFSET(accel), + ssm_wdt_pke_low); + ADF_CSR_WR(csr, + ADF_C4XXX_SSMWDTPKEH_OFFSET(accel), + ssm_wdt_pke_high); + } + + return 0; +} + +/** + * c4xxx_check_slice_hang() - Check slice hang status + * + * Return: true if a slice hange interrupt is serviced.. + */ +static bool +c4xxx_check_slice_hang(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = + &GET_BARS(accel_dev)[hw_device->get_misc_bar_id(hw_device)]; + struct resource *csr = misc_bar->virt_addr; + u32 slice_hang_offset; + u32 ia_slice_hang_offset; + u32 fw_irq_source; + u32 ia_irq_source; + u32 accel_num = 0; + bool handled = false; + u32 errsou10 = ADF_CSR_RD(csr, ADF_C4XXX_ERRSOU10); + unsigned long accel_mask; + + accel_mask = hw_device->accel_mask; + + for_each_set_bit(accel_num, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + if (!(errsou10 & ADF_C4XXX_IRQ_SRC_MASK(accel_num))) + continue; + + fw_irq_source = ADF_CSR_RD(csr, ADF_INTSTATSSM(accel_num)); + ia_irq_source = + ADF_CSR_RD(csr, ADF_C4XXX_IAINTSTATSSM(accel_num)); + ia_slice_hang_offset = + ADF_C4XXX_IASLICEHANGSTATUS_OFFSET(accel_num); + + /* FW did not clear SliceHang error, IA logs and clears + * the error + */ + if ((fw_irq_source & ADF_INTSTATSSM_SHANGERR) && + (ia_irq_source & ADF_INTSTATSSM_SHANGERR)) { + slice_hang_offset = + ADF_C4XXX_SLICEHANGSTATUS_OFFSET(accel_num); + + /* Bring hung slice out of reset */ + adf_csr_fetch_and_and(csr, slice_hang_offset, ~0); + + /* Log SliceHang error and clear an interrupt */ + handled = adf_handle_slice_hang(accel_dev, + accel_num, + csr, + ia_slice_hang_offset); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + /* FW cleared SliceHang, IA only logs an error */ + else if (!(fw_irq_source & ADF_INTSTATSSM_SHANGERR) && + (ia_irq_source & ADF_INTSTATSSM_SHANGERR)) { + /* Log SliceHang error and clear an interrupt */ + handled = adf_handle_slice_hang(accel_dev, + accel_num, + csr, + ia_slice_hang_offset); + + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + + /* Clear the associated IA interrupt */ + adf_csr_fetch_and_and(csr, + ADF_C4XXX_IAINTSTATSSM(accel_num), + ~BIT(13)); + } + + return handled; +} + +static bool +get_eth_doorbell_msg(struct adf_accel_dev *accel_dev) +{ + struct resource *csr = + (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 errsou11 = ADF_CSR_RD(csr, ADF_C4XXX_ERRSOU11); + u32 doorbell_int = ADF_CSR_RD(csr, ADF_C4XXX_ETH_DOORBELL_INT); + u32 eth_doorbell_reg[ADF_C4XXX_NUM_ETH_DOORBELL_REGS]; + bool handled = false; + u32 data_reg; + u8 i; + + /* Reset cannot be acknowledged until the reset */ + hw_device->reset_ack = false; + + /* Check if doorbell interrupt occurred. */ + if (errsou11 & ADF_C4XXX_DOORBELL_INT_SRC) { + /* Decode doorbell messages from ethernet device */ + for (i = 0; i < ADF_C4XXX_NUM_ETH_DOORBELL_REGS; i++) { + eth_doorbell_reg[i] = 0; + if (doorbell_int & BIT(i)) { + data_reg = ADF_C4XXX_ETH_DOORBELL(i); + eth_doorbell_reg[i] = ADF_CSR_RD(csr, data_reg); + device_printf( + GET_DEV(accel_dev), + "Receives Doorbell message(0x%08x)\n", + eth_doorbell_reg[i]); + } + } + /* Only need to check PF0 */ + if (eth_doorbell_reg[0] == ADF_C4XXX_IOSFSB_RESET_ACK) { + device_printf(GET_DEV(accel_dev), + "Receives pending reset ACK\n"); + hw_device->reset_ack = true; + } + /* Clear the interrupt source */ + ADF_CSR_WR(csr, + ADF_C4XXX_ETH_DOORBELL_INT, + ADF_C4XXX_ETH_DOORBELL_MASK); + handled = true; + } + + return handled; +} + +static enum dev_sku_info +get_sku(struct adf_hw_device_data *self) +{ + int aes = get_num_aes(self); + u32 capabilities = self->accel_capabilities_mask; + bool sym_only_sku = false; + + /* Check if SKU is capable only of symmetric cryptography + * via device capabilities. + */ + if ((capabilities & ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) && + !(capabilities & ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) && + !(capabilities & ADF_ACCEL_CAPABILITIES_COMPRESSION)) + sym_only_sku = true; + + switch (aes) { + case ADF_C4XXX_HIGH_SKU_AES: + if (sym_only_sku) + return DEV_SKU_1_CY; + return DEV_SKU_1; + case ADF_C4XXX_MED_SKU_AES: + if (sym_only_sku) + return DEV_SKU_2_CY; + return DEV_SKU_2; + case ADF_C4XXX_LOW_SKU_AES: + if (sym_only_sku) + return DEV_SKU_3_CY; + return DEV_SKU_3; + }; + + return DEV_SKU_UNKNOWN; +} + +static bool +c4xxx_check_prod_sku(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fusectl0 = 0; + + fusectl0 = pci_read_config(pdev, ADF_C4XXX_FUSECTL0_OFFSET, 4); + + if (fusectl0 & ADF_C4XXX_FUSE_PROD_SKU_MASK) + return true; + else + return false; +} + +static bool +adf_check_sym_only_sku_c4xxx(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuse = 0; + + legfuse = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + + if (legfuse & ADF_C4XXX_LEGFUSE_BASE_SKU_MASK) + return true; + else + return false; +} + +static void +adf_enable_slice_hang_detection(struct adf_accel_dev *accel_dev) +{ + struct resource *csr; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 accel = 0; + unsigned long accel_mask; + + csr = (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + accel_mask = hw_device->accel_mask; + + for_each_set_bit(accel, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + /* Unmasks Slice Hang interrupts so they can be seen by IA. */ + ADF_CSR_WR(csr, + ADF_C4XXX_SHINTMASKSSM_OFFSET(accel), + ADF_C4XXX_SHINTMASKSSM_VAL); + } +} + +static void +adf_enable_ras(struct adf_accel_dev *accel_dev) +{ + struct resource *csr; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 accel = 0; + unsigned long accel_mask; + + csr = (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + accel_mask = hw_device->accel_mask; + + for_each_set_bit(accel, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + ADF_CSR_WR(csr, + ADF_C4XXX_GET_SSMFEATREN_OFFSET(accel), + ADF_C4XXX_SSMFEATREN_VAL); + } +} + +static u32 +get_clock_speed(struct adf_hw_device_data *self) +{ + /* c4xxx CPP clock is equal to high-speed clock */ + return self->clock_frequency; +} + +static void +adf_enable_error_interrupts(struct adf_accel_dev *accel_dev) +{ + struct resource *csr, *aram_csr; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 accel = 0; + unsigned long accel_mask; + + csr = (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + aram_csr = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + accel_mask = hw_device->accel_mask; + + for_each_set_bit(accel, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + /* Enable shared memory, MMP, CPP, PPERR interrupts + * for a given accel + */ + ADF_CSR_WR(csr, ADF_C4XXX_GET_INTMASKSSM_OFFSET(accel), 0); + + /* Enable SPP parity error interrupts for a given accel */ + ADF_CSR_WR(csr, ADF_C4XXX_GET_SPPPARERRMSK_OFFSET(accel), 0); + + /* Enable ssm soft parity errors on given accel */ + ADF_CSR_WR(csr, + ADF_C4XXX_GET_SSMSOFTERRORPARITY_MASK_OFFSET(accel), + ADF_C4XXX_SSMSOFTERRORPARITY_MASK_VAL); + } + + /* Enable interrupts for VFtoPF0_127. */ + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK4, ADF_C4XXX_VF2PF0_31); + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK5, ADF_C4XXX_VF2PF32_63); + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK6, ADF_C4XXX_VF2PF64_95); + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK7, ADF_C4XXX_VF2PF96_127); + + /* Enable interrupts signaling ECC correctable errors for all AEs */ + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK8, ADF_C4XXX_ERRMSK8_COERR); + ADF_CSR_WR(csr, + ADF_C4XXX_HI_ME_COR_ERRLOG_ENABLE, + ADF_C4XXX_HI_ME_COR_ERRLOG_ENABLE_MASK); + + /* Enable error interrupts reported by ERRSOU9 */ + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK9, ADF_C4XXX_ERRMSK9_IRQ_MASK); + + /* Enable uncorrectable errors on all the AE */ + ADF_CSR_WR(csr, + ADF_C4XXX_HI_ME_UNCERR_LOG_ENABLE, + ADF_C4XXX_HI_ME_UNCERR_LOG_ENABLE_MASK); + + /* Enable CPP Agent to report command parity errors */ + ADF_CSR_WR(csr, + ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG_ENABLE, + ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG_ENABLE_MASK); + + /* Enable reporting of RI memory parity errors */ + ADF_CSR_WR(csr, + ADF_C4XXX_RI_MEM_PAR_ERR_EN0, + ADF_C4XXX_RI_MEM_PAR_ERR_EN0_MASK); + + /* Enable reporting of TI memory parity errors */ + ADF_CSR_WR(csr, + ADF_C4XXX_TI_MEM_PAR_ERR_EN0, + ADF_C4XXX_TI_MEM_PAR_ERR_EN0_MASK); + ADF_CSR_WR(csr, + ADF_C4XXX_TI_MEM_PAR_ERR_EN1, + ADF_C4XXX_TI_MEM_PAR_ERR_EN1_MASK); + + /* Enable SSM errors */ + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK10, ADF_C4XXX_ERRMSK10_SSM_ERR); + + /* Enable miscellaneous errors (ethernet doorbell aram, ici, ice) */ + ADF_CSR_WR(csr, ADF_C4XXX_ERRMSK11, ADF_C4XXX_ERRMSK11_ERR); + + /* RI CPP bus interface error detection and reporting. */ + ADF_CSR_WR(csr, ADF_C4XXX_RICPPINTCTL, ADF_C4XXX_RICPP_EN); + + /* TI CPP bus interface error detection and reporting. */ + ADF_CSR_WR(csr, ADF_C4XXX_TICPPINTCTL, ADF_C4XXX_TICPP_EN); + + /* Enable CFC Error interrupts and logging. */ + ADF_CSR_WR(csr, ADF_C4XXX_CPP_CFC_ERR_CTRL, ADF_C4XXX_CPP_CFC_UE); + + /* Enable ARAM correctable error detection. */ + ADF_CSR_WR(aram_csr, ADF_C4XXX_ARAMCERR, ADF_C4XXX_ARAM_CERR); + + /* Enable ARAM uncorrectable error detection. */ + ADF_CSR_WR(aram_csr, ADF_C4XXX_ARAMUERR, ADF_C4XXX_ARAM_UERR); + + /* Enable Push/Pull Misc Uncorrectable error interrupts and logging */ + ADF_CSR_WR(aram_csr, ADF_C4XXX_CPPMEMTGTERR, ADF_C4XXX_TGT_UERR); +} + +static void +adf_enable_mmp_error_correction(struct resource *csr, + struct adf_hw_device_data *hw_data) +{ + unsigned int accel = 0, mmp; + unsigned long uerrssmmmp_mask, cerrssmmmp_mask; + enum operation op; + unsigned long accel_mask; + + /* Prepare values and operation that will be performed on + * UERRSSMMMP and CERRSSMMMP registers on each MMP + */ + if (hw_data->accel_capabilities_mask & + ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) { + uerrssmmmp_mask = ADF_C4XXX_UERRSSMMMP_EN; + cerrssmmmp_mask = ADF_C4XXX_CERRSSMMMP_EN; + op = OR; + } else { + uerrssmmmp_mask = ~ADF_C4XXX_UERRSSMMMP_EN; + cerrssmmmp_mask = ~ADF_C4XXX_CERRSSMMMP_EN; + op = AND; + } + + accel_mask = hw_data->accel_mask; + + /* Enable MMP Logging */ + for_each_set_bit(accel, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + /* Set power-up */ + adf_csr_fetch_and_and(csr, + ADF_C4XXX_SLICEPWRDOWN(accel), + ~ADF_C4XXX_MMP_PWR_UP_MSK); + + for (mmp = 0; mmp < ADF_C4XXX_MAX_MMP; ++mmp) { + adf_csr_fetch_and_update(op, + csr, + ADF_C4XXX_UERRSSMMMP(accel, + mmp), + uerrssmmmp_mask); + adf_csr_fetch_and_update(op, + csr, + ADF_C4XXX_CERRSSMMMP(accel, + mmp), + cerrssmmmp_mask); + } + + /* Restore power-down value */ + adf_csr_fetch_and_or(csr, + ADF_C4XXX_SLICEPWRDOWN(accel), + ADF_C4XXX_MMP_PWR_UP_MSK); + } +} + +static u32 +get_pf2vf_offset(u32 i) +{ + return ADF_C4XXX_PF2VF_OFFSET(i); +} + +static u32 +get_vintmsk_offset(u32 i) +{ + return ADF_C4XXX_VINTMSK_OFFSET(i); +} + +static void +get_arb_info(struct arb_info *arb_csrs_info) +{ + arb_csrs_info->arbiter_offset = ADF_C4XXX_ARB_OFFSET; + arb_csrs_info->wrk_cfg_offset = ADF_C4XXX_ARB_WQCFG_OFFSET; +} + +static void +get_admin_info(struct admin_info *admin_csrs_info) +{ + admin_csrs_info->mailbox_offset = ADF_C4XXX_MAILBOX_BASE_OFFSET; + admin_csrs_info->admin_msg_ur = ADF_C4XXX_ADMINMSGUR_OFFSET; + admin_csrs_info->admin_msg_lr = ADF_C4XXX_ADMINMSGLR_OFFSET; +} + +static void +get_errsou_offset(u32 *errsou3, u32 *errsou5) +{ + *errsou3 = ADF_C4XXX_ERRSOU3; + *errsou5 = ADF_C4XXX_ERRSOU5; +} + +static void +adf_enable_error_correction(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + unsigned int val, i = 0; + unsigned long ae_mask; + unsigned long accel_mask; + + ae_mask = hw_device->ae_mask; + + /* Enable Accel Engine error detection & correction */ + for_each_set_bit(i, &ae_mask, ADF_C4XXX_MAX_ACCELENGINES) + { + val = ADF_CSR_RD(csr, ADF_C4XXX_AE_CTX_ENABLES(i)); + val |= ADF_C4XXX_ENABLE_AE_ECC_ERR; + ADF_CSR_WR(csr, ADF_C4XXX_AE_CTX_ENABLES(i), val); + val = ADF_CSR_RD(csr, ADF_C4XXX_AE_MISC_CONTROL(i)); + val |= ADF_C4XXX_ENABLE_AE_ECC_PARITY_CORR; + ADF_CSR_WR(csr, ADF_C4XXX_AE_MISC_CONTROL(i), val); + } + + accel_mask = hw_device->accel_mask; + + /* Enable shared memory error detection & correction */ + for_each_set_bit(i, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + val = ADF_CSR_RD(csr, ADF_C4XXX_UERRSSMSH(i)); + val |= ADF_C4XXX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C4XXX_UERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_C4XXX_CERRSSMSH(i)); + val |= ADF_C4XXX_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C4XXX_CERRSSMSH(i), val); + } + + adf_enable_ras(accel_dev); + adf_enable_mmp_error_correction(csr, hw_device); + adf_enable_slice_hang_detection(accel_dev); + adf_enable_error_interrupts(accel_dev); +} + +static void +adf_enable_ints(struct adf_accel_dev *accel_dev) +{ + struct resource *addr; + + addr = (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + + /* Enable bundle interrupts */ + ADF_CSR_WR(addr, ADF_C4XXX_SMIAPF0_MASK_OFFSET, ADF_C4XXX_SMIA0_MASK); + ADF_CSR_WR(addr, ADF_C4XXX_SMIAPF1_MASK_OFFSET, ADF_C4XXX_SMIA1_MASK); + ADF_CSR_WR(addr, ADF_C4XXX_SMIAPF2_MASK_OFFSET, ADF_C4XXX_SMIA2_MASK); + ADF_CSR_WR(addr, ADF_C4XXX_SMIAPF3_MASK_OFFSET, ADF_C4XXX_SMIA3_MASK); + /*Enable misc interrupts*/ + ADF_CSR_WR(addr, ADF_C4XXX_SMIAPF4_MASK_OFFSET, ADF_C4XXX_SMIA4_MASK); +} + +static u32 +get_ae_clock(struct adf_hw_device_data *self) +{ + /* Clock update interval is <16> ticks for c4xxx. */ + return self->clock_frequency / 16; +} + +static int +measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret = 0; + + ret = adf_dev_measure_clock(accel_dev, + &frequency, + ADF_C4XXX_MIN_AE_FREQ, + ADF_C4XXX_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + +static int +get_storage_enabled(struct adf_accel_dev *accel_dev, uint32_t *storage_enabled) +{ + if (accel_dev->au_info->num_dc_au > 0) { + *storage_enabled = 1; + GET_HW_DATA(accel_dev)->extended_dc_capabilities = + ICP_ACCEL_CAPABILITIES_ADVANCED_COMPRESSION; + } + return 0; +} + +static u32 +c4xxx_get_hw_cap(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuses; + u32 softstrappull0, softstrappull2; + u32 fusectl0, fusectl2; + u32 capabilities; + + /* Read accelerator capabilities mask */ + legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_AUTHENTICATION | + ICP_ACCEL_CAPABILITIES_COMPRESSION | ICP_ACCEL_CAPABILITIES_ZUC | + ICP_ACCEL_CAPABILITIES_HKDF | ICP_ACCEL_CAPABILITIES_SHA3_EXT | + ICP_ACCEL_CAPABILITIES_SM3 | ICP_ACCEL_CAPABILITIES_SM4 | + ICP_ACCEL_CAPABILITIES_CHACHA_POLY | + ICP_ACCEL_CAPABILITIES_AESGCM_SPC | + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY | + ICP_ACCEL_CAPABILITIES_ECEDMONT; + + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) { + capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + capabilities &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + } + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_ECEDMONT); + if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) { + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + capabilities &= ~ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY; + } + if (legfuses & ICP_ACCEL_MASK_EIA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_ZUC; + if (legfuses & ICP_ACCEL_MASK_SM3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_SM3; + if (legfuses & ICP_ACCEL_MASK_SM4_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_SM4; + + /* Read fusectl0 & softstrappull0 registers to ensure inline + * acceleration is not disabled + */ + softstrappull0 = + pci_read_config(pdev, ADF_C4XXX_SOFTSTRAPPULL0_OFFSET, 4); + fusectl0 = pci_read_config(pdev, ADF_C4XXX_FUSECTL0_OFFSET, 4); + if ((fusectl0 | softstrappull0) & ADF_C4XXX_FUSE_DISABLE_INLINE_MASK) + capabilities &= ~ICP_ACCEL_CAPABILITIES_INLINE; + + /* Read fusectl2 & softstrappull2 registers to check out if + * PKE/DC are enabled/disabled + */ + softstrappull2 = + pci_read_config(pdev, ADF_C4XXX_SOFTSTRAPPULL2_OFFSET, 4); + fusectl2 = pci_read_config(pdev, ADF_C4XXX_FUSECTL2_OFFSET, 4); + /* Disable PKE/DC cap if there are no PKE/DC-enabled AUs. */ + if (!(~fusectl2 & ~softstrappull2 & ADF_C4XXX_FUSE_PKE_MASK)) + capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + if (!(~fusectl2 & ~softstrappull2 & ADF_C4XXX_FUSE_COMP_MASK)) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_COMPRESSION | + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY); + + return capabilities; +} + +static int +c4xxx_configure_accel_units(struct adf_accel_dev *accel_dev) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 }; + unsigned long val; + char val_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + int sku; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + + sku = get_sku(hw_data); + + if (adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC)) + goto err; + + snprintf(key, sizeof(key), ADF_SERVICES_ENABLED); + + /* Base station SKU supports symmetric cryptography only. */ + if (adf_check_sym_only_sku_c4xxx(accel_dev)) + snprintf(val_str, sizeof(val_str), ADF_SERVICE_SYM); + else + snprintf(val_str, sizeof(val_str), ADF_SERVICE_CY); + + val = sku_dc_au[sku]; + if (val) { + strncat(val_str, + ADF_SERVICES_SEPARATOR ADF_SERVICE_DC, + ADF_CFG_MAX_VAL_LEN_IN_BYTES - + strnlen(val_str, sizeof(val_str)) - + ADF_CFG_NULL_TERM_SIZE); + } + + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)val_str, ADF_STR)) + goto err; + + snprintf(key, sizeof(key), ADF_NUM_CY_ACCEL_UNITS); + val = sku_cy_au[sku]; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_NUM_DC_ACCEL_UNITS); + val = sku_dc_au[sku]; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + snprintf(key, sizeof(key), ADF_NUM_INLINE_ACCEL_UNITS); + val = sku_inline_au[sku]; + if (adf_cfg_add_key_value_param( + accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC)) + goto err; + + return 0; +err: + device_printf(GET_DEV(accel_dev), "Failed to configure accel units\n"); + return EINVAL; +} + +static void +update_hw_capability(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_unit_info *au_info = accel_dev->au_info; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u32 disabled_caps = 0; + + if (!au_info->asym_ae_msk) + disabled_caps = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + + if (!au_info->sym_ae_msk) + disabled_caps |= ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | ICP_ACCEL_CAPABILITIES_ZUC | + ICP_ACCEL_CAPABILITIES_SHA3_EXT | + ICP_ACCEL_CAPABILITIES_SM3 | ICP_ACCEL_CAPABILITIES_SM4 | + ICP_ACCEL_CAPABILITIES_CHACHA_POLY | + ICP_ACCEL_CAPABILITIES_AESGCM_SPC; + + if (!au_info->dc_ae_msk) { + disabled_caps |= ICP_ACCEL_CAPABILITIES_COMPRESSION | + ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY; + hw_device->extended_dc_capabilities = 0; + } + + if (!au_info->inline_ingress_msk && !au_info->inline_egress_msk) + disabled_caps |= ICP_ACCEL_CAPABILITIES_INLINE; + + hw_device->accel_capabilities_mask = + c4xxx_get_hw_cap(accel_dev) & ~disabled_caps; +} + +static void +c4xxx_set_sadb_size(struct adf_accel_dev *accel_dev) +{ + u32 sadb_reg_value = 0; + struct resource *aram_csr_base; + + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + if (accel_dev->au_info->num_inline_au) { + /* REG_SA_DB_CTRL register initialisation */ + sadb_reg_value = ADF_C4XXX_SADB_REG_VALUE(accel_dev); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_DB_CTRL, + sadb_reg_value); + } else { + /* Zero the SADB size when inline is disabled. */ + adf_csr_fetch_and_and(aram_csr_base, + ADF_C4XXX_REG_SA_DB_CTRL, + ADF_C4XXX_SADB_SIZE_BIT); + } + /* REG_SA_CTRL_LOCK register initialisation. We set the lock + * bit in order to prevent the REG_SA_DB_CTRL to be + * overwritten + */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_CTRL_LOCK, + ADF_C4XXX_DEFAULT_SA_CTRL_LOCKOUT); +} + +static void +c4xxx_init_error_notification_configuration(struct adf_accel_dev *accel_dev, + u32 offset) +{ + struct resource *aram_csr_base; + + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + + /* configure error notification configuration registers */ + /* Set CD Parity error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_RF_PARITY_ERR_0 + offset, + ADF_C4XXX_CD_RF_PARITY_ERR_0_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_RF_PARITY_ERR_1 + offset, + ADF_C4XXX_CD_RF_PARITY_ERR_1_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_RF_PARITY_ERR_2 + offset, + ADF_C4XXX_CD_RF_PARITY_ERR_2_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_RF_PARITY_ERR_3 + offset, + ADF_C4XXX_CD_RF_PARITY_ERR_3_VAL); + /* Set CD RAM ECC Correctable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_CERR + offset, + ADF_C4XXX_CD_CERR_VAL); + /* Set CD RAM ECC UnCorrectable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CD_UERR + offset, + ADF_C4XXX_CD_UERR_VAL); + /* Set Inline (excl cmd_dis) Parity Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_0 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_0_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_1 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_1_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_2 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_2_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_3 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_3_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_4 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_4_VAL); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_5 + offset, + ADF_C4XXX_INLN_RF_PARITY_ERR_5_VAL); + /* Set Parser RAM ECC Correctable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSER_CERR + offset, + ADF_C4XXX_PARSER_CERR_VAL); + /* Set Parser RAM ECC UnCorrectable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSER_UERR + offset, + ADF_C4XXX_PARSER_UERR_VAL); + /* Set CTPB RAM ECC Correctable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CTPB_CERR + offset, + ADF_C4XXX_CTPB_CERR_VAL); + /* Set CTPB RAM ECC UnCorrectable Error */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CTPB_UERR + offset, + ADF_C4XXX_CTPB_UERR_VAL); + /* Set CPP Interface Status */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CPPM_ERR_STAT + offset, + ADF_C4XXX_CPPM_ERR_STAT_VAL); + /* Set CGST_MGMT_INT */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CONGESTION_MGMT_INT + offset, + ADF_C4XXX_CONGESTION_MGMT_INI_VAL); + /* CPP Interface Status */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_CPPT_ERR_STAT + offset, + ADF_C4XXX_CPPT_ERR_STAT_VAL); + /* MAC Interrupt Mask */ + ADF_CSR_WR64(aram_csr_base, + ADF_C4XXX_IC_MAC_IM + offset, + ADF_C4XXX_MAC_IM_VAL); +} + +static void +c4xxx_enable_parse_extraction(struct adf_accel_dev *accel_dev) +{ + struct resource *aram_csr_base; + + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + + /* Enable Inline Parse Extraction CRSs */ + + /* Set IC_PARSE_CTRL register */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_CTRL_OFFSET, + ADF_C4XXX_IC_PARSE_CTRL_OFFSET_DEFAULT_VALUE); + + /* Set IC_PARSE_FIXED_DATA(0) */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_FIXED_DATA(0), + ADF_C4XXX_DEFAULT_IC_PARSE_FIXED_DATA_0); + + /* Set IC_PARSE_FIXED_LENGTH */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_FIXED_LENGTH, + ADF_C4XXX_DEFAULT_IC_PARSE_FIXED_LEN); + + /* Configure ESP protocol from an IPv4 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_OFFSET_0, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_0_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_LENGTH_0, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_0_VALUE); + /* Configure protocol extraction field from an IPv4 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_OFFSET_1, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_1_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_LENGTH_1, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_1_VALUE); + /* Configure SPI extraction field from an IPv4 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_OFFSET_2, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_2_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_LENGTH_2, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_2_VALUE); + /* Configure destination field IP address from an IPv4 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_OFFSET_3, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_3_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV4_LENGTH_3, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_3_VALUE); + + /* Configure function number extraction field from an IPv6 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_OFFSET_0, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_0_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_LENGTH_0, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_0_VALUE); + /* Configure protocol extraction field from an IPv6 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_OFFSET_1, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_1_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_LENGTH_1, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_1_VALUE); + /* Configure SPI extraction field from an IPv6 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_OFFSET_2, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_2_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_LENGTH_2, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_2_VALUE); + /* Configure destination field IP address from an IPv6 header */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_OFFSET_3, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_3_VALUE); + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_IC_PARSE_IPV6_LENGTH_3, + ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_3_VALUE); +} + +static int +adf_get_inline_ipsec_algo_group(struct adf_accel_dev *accel_dev, + unsigned long *ipsec_algo_group) +{ + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + if (adf_cfg_get_param_value( + accel_dev, ADF_INLINE_SEC, ADF_INLINE_IPSEC_ALGO_GROUP, val)) + return EFAULT; + if (kstrtoul(val, 0, ipsec_algo_group)) + return EFAULT; + + /* Verify the ipsec_algo_group */ + if (*ipsec_algo_group >= IPSEC_ALGO_GROUP_DELIMITER) { + device_printf( + GET_DEV(accel_dev), + "Unsupported IPSEC algo group %lu in config file!\n", + *ipsec_algo_group); + return EFAULT; + } + + return 0; +} + +static int +c4xxx_init_inline_hw(struct adf_accel_dev *accel_dev) +{ + u32 sa_entry_reg_value = 0; + u32 sa_fn_lim = 0; + u32 supported_algo = 0; + struct resource *aram_csr_base; + u32 offset; + unsigned long ipsec_algo_group = IPSEC_DEFAUL_ALGO_GROUP; + + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + + if (adf_get_inline_ipsec_algo_group(accel_dev, &ipsec_algo_group)) + return EFAULT; + + sa_entry_reg_value |= + (ADF_C4XXX_DEFAULT_LU_KEY_LEN << ADF_C4XXX_LU_KEY_LEN_BIT_OFFSET); + if (ipsec_algo_group == IPSEC_DEFAUL_ALGO_GROUP) { + sa_entry_reg_value |= ADF_C4XXX_DEFAULT_SA_SIZE; + sa_fn_lim = + ADF_C4XXX_FUNC_LIMIT(accel_dev, ADF_C4XXX_DEFAULT_SA_SIZE); + supported_algo = ADF_C4XXX_DEFAULT_SUPPORTED_ALGORITHMS; + } else if (ipsec_algo_group == IPSEC_ALGO_GROUP1) { + sa_entry_reg_value |= ADF_C4XXX_ALGO_GROUP1_SA_SIZE; + sa_fn_lim = ADF_C4XXX_FUNC_LIMIT(accel_dev, + ADF_C4XXX_ALGO_GROUP1_SA_SIZE); + supported_algo = ADF_C4XXX_SUPPORTED_ALGORITHMS_GROUP1; + } else { + return EFAULT; + } + + /* REG_SA_ENTRY_CTRL register initialisation */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_ENTRY_CTRL, + sa_entry_reg_value); + + /* REG_SAL_FUNC_LIMITS register initialisation. Only the first register + * needs to be initialised to enable as it is assigned to a physical + * function. Other registers will be initialised by the LAN PF driver. + * The function limits is initialised to its maximal value. + */ + ADF_CSR_WR(aram_csr_base, ADF_C4XXX_REG_SA_FUNC_LIMITS, sa_fn_lim); + + /* Initialize REG_SA_SCRATCH[0] register to + * advertise supported crypto algorithms + */ + ADF_CSR_WR(aram_csr_base, ADF_C4XXX_REG_SA_SCRATCH_0, supported_algo); + + /* REG_SA_SCRATCH[2] register initialisation + * to advertise supported crypto offload features. + */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_SCRATCH_2, + ADF_C4XXX_DEFAULT_CY_OFFLOAD_FEATURES); + + /* Overwrite default MAC_CFG register in ingress offset */ + ADF_CSR_WR64(aram_csr_base, + ADF_C4XXX_MAC_CFG + ADF_C4XXX_INLINE_INGRESS_OFFSET, + ADF_C4XXX_MAC_CFG_VALUE); + + /* Overwrite default MAC_CFG register in egress offset */ + ADF_CSR_WR64(aram_csr_base, + ADF_C4XXX_MAC_CFG + ADF_C4XXX_INLINE_EGRESS_OFFSET, + ADF_C4XXX_MAC_CFG_VALUE); + + /* Overwrite default MAC_PIA_CFG + * (Packet Interface Adapter Configuration) registers + * in ingress offset + */ + ADF_CSR_WR64(aram_csr_base, + ADF_C4XXX_MAC_PIA_CFG + ADF_C4XXX_INLINE_INGRESS_OFFSET, + ADF_C4XXX_MAC_PIA_CFG_VALUE); + + /* Overwrite default MAC_PIA_CFG in egress offset */ + ADF_CSR_WR64(aram_csr_base, + ADF_C4XXX_MAC_PIA_CFG + ADF_C4XXX_INLINE_EGRESS_OFFSET, + ADF_C4XXX_MAC_PIA_CFG_VALUE); + + c4xxx_enable_parse_extraction(accel_dev); + + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_INGRESS_CMD_DIS_MISC, + ADF_C4XXX_REG_CMD_DIS_MISC_DEFAULT_VALUE); + + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_EGRESS_CMD_DIS_MISC, + ADF_C4XXX_REG_CMD_DIS_MISC_DEFAULT_VALUE); + + /* Set bits<1:0> in ADF_C4XXX_INLINE_CAPABILITY register to + * advertize that both ingress and egress directions are available + */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_INLINE_CAPABILITY, + ADF_C4XXX_INLINE_CAPABILITIES); + + /* Set error notification configuration of ingress */ + offset = ADF_C4XXX_INLINE_INGRESS_OFFSET; + c4xxx_init_error_notification_configuration(accel_dev, offset); + /* Set error notification configuration of egress */ + offset = ADF_C4XXX_INLINE_EGRESS_OFFSET; + c4xxx_init_error_notification_configuration(accel_dev, offset); + + return 0; +} + +static void +adf_enable_inline_notification(struct adf_accel_dev *accel_dev) +{ + struct resource *aram_csr_base; + + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + + /* Set bit<0> in ADF_C4XXX_REG_SA_INLINE_ENABLE to advertise + * that inline is enabled. + */ + ADF_CSR_WR(aram_csr_base, + ADF_C4XXX_REG_SA_INLINE_ENABLE, + ADF_C4XXX_INLINE_ENABLED); +} + +static int +c4xxx_init_aram_config(struct adf_accel_dev *accel_dev) +{ + u32 aram_size = ADF_C4XXX_2MB_ARAM_SIZE; + u32 ibuff_mem_needed = 0; + u32 usable_aram_size = 0; + struct adf_hw_aram_info *aram_info; + u32 sa_db_ctl_value; + struct resource *aram_csr_base; + u8 profile = 0; + u32 sadb_size = 0; + u32 sa_size = 0; + unsigned long ipsec_algo_group = IPSEC_DEFAUL_ALGO_GROUP; + u32 i; + + if (accel_dev->au_info->num_inline_au > 0) + if (adf_get_inline_ipsec_algo_group(accel_dev, + &ipsec_algo_group)) + return EFAULT; + + /* Allocate memory for adf_hw_aram_info */ + aram_info = kzalloc(sizeof(*accel_dev->aram_info), GFP_KERNEL); + if (!aram_info) + return ENOMEM; + + /* Initialise Inline direction */ + aram_info->inline_direction_egress_mask = 0; + if (accel_dev->au_info->num_inline_au) { + /* Set inline direction bitmap in the ARAM to + * inform firmware which ME is egress + */ + aram_info->inline_direction_egress_mask = + accel_dev->au_info->inline_egress_msk; + + /* User profile is valid, we can now add it + * in the ARAM partition table + */ + aram_info->inline_congest_mngt_profile = profile; + } + /* Initialise DC ME mask, "1" = ME is used for DC operations */ + aram_info->dc_ae_mask = accel_dev->au_info->dc_ae_msk; + + /* Initialise CY ME mask, "1" = ME is used for CY operations + * Since asym service can also be enabled on inline AEs, here + * we use the sym ae mask for configuring the cy_ae_msk + */ + aram_info->cy_ae_mask = accel_dev->au_info->sym_ae_msk; + + /* Configure number of long words in the ARAM */ + aram_info->num_aram_lw_entries = ADF_C4XXX_NUM_ARAM_ENTRIES; + + /* Reset region offset values to 0xffffffff */ + aram_info->mmp_region_offset = ~aram_info->mmp_region_offset; + aram_info->skm_region_offset = ~aram_info->skm_region_offset; + aram_info->inter_buff_aram_region_offset = + ~aram_info->inter_buff_aram_region_offset; + + /* Determine ARAM size */ + aram_csr_base = (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + sa_db_ctl_value = ADF_CSR_RD(aram_csr_base, ADF_C4XXX_REG_SA_DB_CTRL); + + aram_size = (sa_db_ctl_value & ADF_C4XXX_SADB_SIZE_BIT) ? + ADF_C4XXX_2MB_ARAM_SIZE : + ADF_C4XXX_4MB_ARAM_SIZE; + device_printf(GET_DEV(accel_dev), + "Total available accelerator memory: %uMB\n", + aram_size / ADF_C4XXX_1MB_SIZE); + + /* Compute MMP region offset */ + aram_info->mmp_region_size = ADF_C4XXX_DEFAULT_MMP_REGION_SIZE; + aram_info->mmp_region_offset = aram_size - aram_info->mmp_region_size; + + if (accel_dev->au_info->num_cy_au || + accel_dev->au_info->num_inline_au) { + /* Crypto is available therefore we must + * include space in the ARAM for SKM. + */ + aram_info->skm_region_size = ADF_C4XXX_DEFAULT_SKM_REGION_SIZE; + /* Compute SKM region offset */ + aram_info->skm_region_offset = aram_size - + (aram_info->mmp_region_size + aram_info->skm_region_size); + } + + /* SADB always start at offset 0. */ + if (accel_dev->au_info->num_inline_au) { + /* Inline is available therefore we must + * use remaining ARAM for the SADB. + */ + sadb_size = aram_size - + (aram_info->mmp_region_size + aram_info->skm_region_size); + + /* + * When the inline service is enabled, the policy is that + * compression gives up it's space in ARAM to allow for a + * larger SADB. Compression must use DRAM instead of ARAM. + */ + aram_info->inter_buff_aram_region_size = 0; + + /* the SADB size must be an integral multiple of the SA size */ + if (ipsec_algo_group == IPSEC_DEFAUL_ALGO_GROUP) { + sa_size = ADF_C4XXX_DEFAULT_SA_SIZE; + } else { + /* IPSEC_ALGO_GROUP1 + * Total 2 algo groups. + */ + sa_size = ADF_C4XXX_ALGO_GROUP1_SA_SIZE; + } + + sadb_size = sadb_size - + (sadb_size % ADF_C4XXX_SA_SIZE_IN_BYTES(sa_size)); + aram_info->sadb_region_size = sadb_size; + } + + if (accel_dev->au_info->num_dc_au && + !accel_dev->au_info->num_inline_au) { + /* Compression is available therefore we must see if there is + * space in the ARAM for intermediate buffers. + */ + aram_info->inter_buff_aram_region_size = 0; + usable_aram_size = aram_size - + (aram_info->mmp_region_size + aram_info->skm_region_size); + + for (i = 1; i <= accel_dev->au_info->num_dc_au; i++) { + if ((i * ADF_C4XXX_AU_COMPR_INTERM_SIZE) > + usable_aram_size) + break; + + ibuff_mem_needed = i * ADF_C4XXX_AU_COMPR_INTERM_SIZE; + } + + /* Set remaining ARAM to intermediate buffers. Firmware handles + * fallback to DRAM for cases were number of AU assigned + * to compression exceeds available ARAM memory. + */ + aram_info->inter_buff_aram_region_size = ibuff_mem_needed; + + /* If ARAM is used for compression set its initial offset. */ + if (aram_info->inter_buff_aram_region_size) + aram_info->inter_buff_aram_region_offset = 0; + } + + accel_dev->aram_info = aram_info; + + return 0; +} + +static void +c4xxx_exit_aram_config(struct adf_accel_dev *accel_dev) +{ + kfree(accel_dev->aram_info); + accel_dev->aram_info = NULL; +} + +static u32 +get_num_accel_units(struct adf_hw_device_data *self) +{ + u32 i = 0, num_accel = 0; + unsigned long accel_mask = 0; + + if (!self || !self->accel_mask) + return 0; + + accel_mask = self->accel_mask; + + for_each_set_bit(i, &accel_mask, ADF_C4XXX_MAX_ACCELERATORS) + { + num_accel++; + } + + return num_accel / ADF_C4XXX_NUM_ACCEL_PER_AU; +} + +static int +get_accel_unit(struct adf_hw_device_data *self, + struct adf_accel_unit **accel_unit) +{ + enum dev_sku_info sku; + + sku = get_sku(self); + + switch (sku) { + case DEV_SKU_1: + case DEV_SKU_1_CY: + *accel_unit = adf_c4xxx_au_32_ae; + break; + case DEV_SKU_2: + case DEV_SKU_2_CY: + *accel_unit = adf_c4xxx_au_24_ae; + break; + case DEV_SKU_3: + case DEV_SKU_3_CY: + *accel_unit = adf_c4xxx_au_12_ae; + break; + default: + *accel_unit = adf_c4xxx_au_emulation; + break; + } + return 0; +} + +static int +get_ae_info(struct adf_hw_device_data *self, const struct adf_ae_info **ae_info) +{ + enum dev_sku_info sku; + + sku = get_sku(self); + + switch (sku) { + case DEV_SKU_1: + *ae_info = adf_c4xxx_32_ae; + break; + case DEV_SKU_1_CY: + *ae_info = adf_c4xxx_32_ae_sym; + break; + case DEV_SKU_2: + *ae_info = adf_c4xxx_24_ae; + break; + case DEV_SKU_2_CY: + *ae_info = adf_c4xxx_24_ae_sym; + break; + case DEV_SKU_3: + *ae_info = adf_c4xxx_12_ae; + break; + case DEV_SKU_3_CY: + *ae_info = adf_c4xxx_12_ae_sym; + break; + default: + *ae_info = adf_c4xxx_12_ae; + break; + } + return 0; +} + +static int +adf_add_debugfs_info(struct adf_accel_dev *accel_dev) +{ + /* Add Accel Unit configuration table to debug FS interface */ + if (c4xxx_init_ae_config(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to create entry for AE configuration\n"); + return EFAULT; + } + + return 0; +} + +static void +adf_remove_debugfs_info(struct adf_accel_dev *accel_dev) +{ + /* Remove Accel Unit configuration table from debug FS interface */ + c4xxx_exit_ae_config(accel_dev); +} + +static int +check_svc_to_hw_capabilities(struct adf_accel_dev *accel_dev, + const char *svc_name, + enum icp_qat_capabilities_mask cap) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 hw_cap = hw_data->accel_capabilities_mask; + + hw_cap &= cap; + if (hw_cap != cap) { + device_printf(GET_DEV(accel_dev), + "Service not supported by accelerator: %s\n", + svc_name); + return EPERM; + } + + return 0; +} + +static int +check_accel_unit_config(struct adf_accel_dev *accel_dev, + u8 num_cy_au, + u8 num_dc_au, + u8 num_inline_au) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + u32 num_au = hw_data->get_num_accel_units(hw_data); + u32 service_mask = ADF_ACCEL_SERVICE_NULL; + char *token, *cur_str; + int ret = 0; + + /* Get the services enabled by user */ + snprintf(key, sizeof(key), ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + cur_str = val; + token = strsep(&cur_str, ADF_SERVICES_SEPARATOR); + while (token) { + if (!strncmp(token, ADF_SERVICE_CY, strlen(ADF_SERVICE_CY))) { + service_mask |= ADF_ACCEL_CRYPTO; + ret |= check_svc_to_hw_capabilities( + accel_dev, + token, + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC); + } + + if (!strncmp(token, ADF_CFG_SYM, strlen(ADF_CFG_SYM))) { + service_mask |= ADF_ACCEL_CRYPTO; + ret |= check_svc_to_hw_capabilities( + accel_dev, + token, + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC); + } + + if (!strncmp(token, ADF_CFG_ASYM, strlen(ADF_CFG_ASYM))) { + /* Handle a special case of services 'asym;inline' + * enabled where ASYM is handled by Inline firmware + * at AE level. This configuration allows to enable + * ASYM service without accel units assigned to + * CRYPTO service, e.g. + * num_inline_au = 6 + * num_cy_au = 0 + */ + if (num_inline_au < num_au) + service_mask |= ADF_ACCEL_CRYPTO; + + ret |= check_svc_to_hw_capabilities( + accel_dev, + token, + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC); + } + + if (!strncmp(token, ADF_SERVICE_DC, strlen(ADF_SERVICE_DC))) { + service_mask |= ADF_ACCEL_COMPRESSION; + ret |= check_svc_to_hw_capabilities( + accel_dev, + token, + ICP_ACCEL_CAPABILITIES_COMPRESSION); + } + + if (!strncmp(token, + ADF_SERVICE_INLINE, + strlen(ADF_SERVICE_INLINE))) { + service_mask |= ADF_ACCEL_INLINE_CRYPTO; + ret |= check_svc_to_hw_capabilities( + accel_dev, token, ICP_ACCEL_CAPABILITIES_INLINE); + } + + token = strsep(&cur_str, ADF_SERVICES_SEPARATOR); + } + + /* Ensure the user doesn't enable services that are not supported by + * accelerator. + */ + if (ret) { + device_printf(GET_DEV(accel_dev), + "Invalid accelerator configuration.\n"); + return EFAULT; + } + + if (!(service_mask & ADF_ACCEL_COMPRESSION) && num_dc_au > 0) { + device_printf(GET_DEV(accel_dev), + "Invalid accel unit config.\n"); + device_printf( + GET_DEV(accel_dev), + "DC accel units set when dc service not enabled\n"); + return EFAULT; + } + + if (!(service_mask & ADF_ACCEL_CRYPTO) && num_cy_au > 0) { + device_printf(GET_DEV(accel_dev), + "Invalid accel unit config.\n"); + device_printf( + GET_DEV(accel_dev), + "CY accel units set when cy service not enabled\n"); + return EFAULT; + } + + if (!(service_mask & ADF_ACCEL_INLINE_CRYPTO) && num_inline_au > 0) { + device_printf(GET_DEV(accel_dev), + "Invalid accel unit config.\n" + "Inline feature not supported.\n"); + return EFAULT; + } + + hw_data->service_mask = service_mask; + /* Ensure the user doesn't allocate more than max accel units */ + if (num_au != (num_cy_au + num_dc_au + num_inline_au)) { + device_printf(GET_DEV(accel_dev), + "Invalid accel unit config.\n"); + device_printf(GET_DEV(accel_dev), + "Max accel units is %d\n", + num_au); + return EFAULT; + } + + /* Ensure user allocates hardware resources for enabled services */ + if (!num_cy_au && (service_mask & ADF_ACCEL_CRYPTO)) { + device_printf(GET_DEV(accel_dev), + "Failed to enable cy service!\n"); + device_printf(GET_DEV(accel_dev), + "%s should not be 0", + ADF_NUM_CY_ACCEL_UNITS); + return EFAULT; + } + if (!num_dc_au && (service_mask & ADF_ACCEL_COMPRESSION)) { + device_printf(GET_DEV(accel_dev), + "Failed to enable dc service!\n"); + device_printf(GET_DEV(accel_dev), + "%s should not be 0", + ADF_NUM_DC_ACCEL_UNITS); + return EFAULT; + } + if (!num_inline_au && (service_mask & ADF_ACCEL_INLINE_CRYPTO)) { + device_printf(GET_DEV(accel_dev), "Failed to enable"); + device_printf(GET_DEV(accel_dev), " inline service!"); + device_printf(GET_DEV(accel_dev), + " %s should not be 0\n", + ADF_NUM_INLINE_ACCEL_UNITS); + return EFAULT; + } + + return 0; +} + +static int +get_accel_unit_config(struct adf_accel_dev *accel_dev, + u8 *num_cy_au, + u8 *num_dc_au, + u8 *num_inline_au) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + /* Get the number of accel units allocated for each service */ + snprintf(key, sizeof(key), ADF_NUM_CY_ACCEL_UNITS); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + if (compat_strtou8(val, 10, num_cy_au)) + return EFAULT; + snprintf(key, sizeof(key), ADF_NUM_DC_ACCEL_UNITS); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + if (compat_strtou8(val, 10, num_dc_au)) + return EFAULT; + + snprintf(key, sizeof(key), ADF_NUM_INLINE_ACCEL_UNITS); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + if (compat_strtou8(val, 10, num_inline_au)) + return EFAULT; + + return 0; +} + +/* Function reads the inline ingress/egress configuration + * and returns the number of AEs reserved for ingress + * and egress for accel units which are allocated for + * inline service + */ +static int +adf_get_inline_config(struct adf_accel_dev *accel_dev, u32 *num_ingress_aes) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + char *value; + u32 num_au = hw_data->get_num_accel_units(hw_data); + unsigned long ingress, egress = 0; + struct adf_accel_unit *accel_unit = accel_dev->au_info->au; + u32 num_inline_aes = 0, num_ingress_ae = 0; + u32 i = 0; + + snprintf(key, sizeof(key), ADF_INLINE_INGRESS); + if (adf_cfg_get_param_value(accel_dev, ADF_INLINE_SEC, key, val)) { + device_printf(GET_DEV(accel_dev), "Failed to find ingress\n"); + return EFAULT; + } + value = val; + value = strsep(&value, ADF_C4XXX_PERCENTAGE); + if (compat_strtoul(value, 10, &ingress)) + return EFAULT; + + snprintf(key, sizeof(key), ADF_INLINE_EGRESS); + if (adf_cfg_get_param_value(accel_dev, ADF_INLINE_SEC, key, val)) { + device_printf(GET_DEV(accel_dev), "Failed to find egress\n"); + return EFAULT; + } + value = val; + value = strsep(&value, ADF_C4XXX_PERCENTAGE); + if (compat_strtoul(value, 10, &egress)) + return EFAULT; + + if (ingress + egress != ADF_C4XXX_100) { + device_printf(GET_DEV(accel_dev), + "The sum of ingress and egress should be 100\n"); + return EFAULT; + } + + for (i = 0; i < num_au; i++) { + if (accel_unit[i].services == ADF_ACCEL_INLINE_CRYPTO) + num_inline_aes += accel_unit[i].num_ae; + } + + num_ingress_ae = num_inline_aes * ingress / ADF_C4XXX_100; + if (((num_inline_aes * ingress) % ADF_C4XXX_100) > + ADF_C4XXX_ROUND_LIMIT) + num_ingress_ae++; + + *num_ingress_aes = num_ingress_ae; + return 0; +} + +static int +adf_set_inline_ae_mask(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_au = hw_data->get_num_accel_units(hw_data); + struct adf_accel_unit_info *au_info = accel_dev->au_info; + struct adf_accel_unit *accel_unit = accel_dev->au_info->au; + u32 num_ingress_ae = 0; + u32 ingress_msk = 0; + u32 i, j, ae_mask; + + if (adf_get_inline_config(accel_dev, &num_ingress_ae)) + return EFAULT; + + for (i = 0; i < num_au; i++) { + j = 0; + if (accel_unit[i].services == ADF_ACCEL_INLINE_CRYPTO) { + /* AEs with inline service enabled are also used + * for asymmetric crypto + */ + au_info->asym_ae_msk |= accel_unit[i].ae_mask; + ae_mask = accel_unit[i].ae_mask; + while (num_ingress_ae && ae_mask) { + if (ae_mask & 1) { + ingress_msk |= BIT(j); + num_ingress_ae--; + } + ae_mask = ae_mask >> 1; + j++; + } + au_info->inline_ingress_msk |= ingress_msk; + + au_info->inline_egress_msk |= + ~(au_info->inline_ingress_msk) & + accel_unit[i].ae_mask; + } + } + + return 0; +} + +static int +adf_set_ae_mask(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_au = hw_data->get_num_accel_units(hw_data); + struct adf_accel_unit_info *au_info = accel_dev->au_info; + struct adf_accel_unit *accel_unit = accel_dev->au_info->au; + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + char *token, *cur_str; + bool asym_en = false, sym_en = false; + u32 i; + + /* Get the services enabled by user */ + snprintf(key, sizeof(key), ADF_SERVICES_ENABLED); + if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) + return EFAULT; + cur_str = val; + token = strsep(&cur_str, ADF_SERVICES_SEPARATOR); + while (token) { + if (!strncmp(token, ADF_CFG_ASYM, strlen(ADF_CFG_ASYM))) + asym_en = true; + if (!strncmp(token, ADF_CFG_SYM, strlen(ADF_CFG_SYM))) + sym_en = true; + if (!strncmp(token, ADF_CFG_CY, strlen(ADF_CFG_CY))) { + sym_en = true; + asym_en = true; + } + token = strsep(&cur_str, ADF_SERVICES_SEPARATOR); + } + + for (i = 0; i < num_au; i++) { + if (accel_unit[i].services == ADF_ACCEL_CRYPTO) { + /* AEs that support crypto can perform both + * symmetric and asymmetric crypto, however + * we only enable the threads if the relevant + * service is also enabled + */ + if (asym_en) + au_info->asym_ae_msk |= accel_unit[i].ae_mask; + if (sym_en) + au_info->sym_ae_msk |= accel_unit[i].ae_mask; + } else if (accel_unit[i].services == ADF_ACCEL_COMPRESSION) { + au_info->dc_ae_msk |= accel_unit[i].comp_ae_mask; + } + } + return 0; +} + +static int +adf_init_accel_unit_services(struct adf_accel_dev *accel_dev) +{ + u8 num_cy_au, num_dc_au, num_inline_au; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_au = hw_data->get_num_accel_units(hw_data); + struct adf_accel_unit *accel_unit; + const struct adf_ae_info *ae_info; + int i; + + if (get_accel_unit_config( + accel_dev, &num_cy_au, &num_dc_au, &num_inline_au)) { + device_printf(GET_DEV(accel_dev), "Invalid accel unit cfg\n"); + return EFAULT; + } + + if (check_accel_unit_config( + accel_dev, num_cy_au, num_dc_au, num_inline_au)) + return EFAULT; + + accel_dev->au_info = kzalloc(sizeof(*accel_dev->au_info), GFP_KERNEL); + if (!accel_dev->au_info) + return ENOMEM; + + accel_dev->au_info->num_cy_au = num_cy_au; + accel_dev->au_info->num_dc_au = num_dc_au; + accel_dev->au_info->num_inline_au = num_inline_au; + + if (get_ae_info(hw_data, &ae_info)) { + device_printf(GET_DEV(accel_dev), "Failed to get ae info\n"); + goto err_au_info; + } + accel_dev->au_info->ae_info = ae_info; + + if (get_accel_unit(hw_data, &accel_unit)) { + device_printf(GET_DEV(accel_dev), "Failed to get accel unit\n"); + goto err_ae_info; + } + + /* Enable compression accel units */ + /* Accel units with 4AEs are reserved for compression first */ + for (i = num_au - 1; i >= 0 && num_dc_au > 0; i--) { + if (accel_unit[i].num_ae == ADF_C4XXX_4_AE) { + accel_unit[i].services = ADF_ACCEL_COMPRESSION; + num_dc_au--; + } + } + for (i = num_au - 1; i >= 0 && num_dc_au > 0; i--) { + if (accel_unit[i].services == ADF_ACCEL_SERVICE_NULL) { + accel_unit[i].services = ADF_ACCEL_COMPRESSION; + num_dc_au--; + } + } + + /* Enable inline accel units */ + for (i = 0; i < num_au && num_inline_au > 0; i++) { + if (accel_unit[i].services == ADF_ACCEL_SERVICE_NULL) { + accel_unit[i].services = ADF_ACCEL_INLINE_CRYPTO; + num_inline_au--; + } + } + + /* Enable crypto accel units */ + for (i = 0; i < num_au && num_cy_au > 0; i++) { + if (accel_unit[i].services == ADF_ACCEL_SERVICE_NULL) { + accel_unit[i].services = ADF_ACCEL_CRYPTO; + num_cy_au--; + } + } + accel_dev->au_info->au = accel_unit; + return 0; + +err_ae_info: + accel_dev->au_info->ae_info = NULL; +err_au_info: + kfree(accel_dev->au_info); + accel_dev->au_info = NULL; + return EFAULT; +} + +static void +adf_exit_accel_unit_services(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_au = hw_data->get_num_accel_units(hw_data); + int i; + + if (accel_dev->au_info) { + if (accel_dev->au_info->au) { + for (i = 0; i < num_au; i++) { + accel_dev->au_info->au[i].services = + ADF_ACCEL_SERVICE_NULL; + } + } + accel_dev->au_info->au = NULL; + accel_dev->au_info->ae_info = NULL; + kfree(accel_dev->au_info); + accel_dev->au_info = NULL; + } +} + +static inline void +adf_c4xxx_reset_hw_units(struct adf_accel_dev *accel_dev) +{ + struct resource *pmisc = + (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + + u32 global_clk_enable = ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ARAM | + ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ICI_ENABLE | + ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ICE_ENABLE; + + u32 ixp_reset_generic = ADF_C4XXX_IXP_RESET_GENERIC_ARAM | + ADF_C4XXX_IXP_RESET_GENERIC_INLINE_EGRESS | + ADF_C4XXX_IXP_RESET_GENERIC_INLINE_INGRESS; + + /* To properly reset each of the units driver must: + * 1)Call out resetactive state using ixp reset generic + * register; + * 2)Disable generic clock; + * 3)Take device out of reset by clearing ixp reset + * generic register; + * 4)Re-enable generic clock; + */ + ADF_CSR_WR(pmisc, ADF_C4XXX_IXP_RESET_GENERIC, ixp_reset_generic); + ADF_CSR_WR(pmisc, + ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC, + ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_DISABLE_ALL); + ADF_CSR_WR(pmisc, + ADF_C4XXX_IXP_RESET_GENERIC, + ADF_C4XXX_IXP_RESET_GENERIC_OUT_OF_RESET_TRIGGER); + ADF_CSR_WR(pmisc, + ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC, + global_clk_enable); +} + +static int +adf_init_accel_units(struct adf_accel_dev *accel_dev) +{ + struct resource *csr = + (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + + if (adf_init_accel_unit_services(accel_dev)) + return EFAULT; + + /* Set cy and dc enabled AE masks */ + if (accel_dev->au_info->num_cy_au || accel_dev->au_info->num_dc_au) { + if (adf_set_ae_mask(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to set ae masks\n"); + goto err_au; + } + } + /* Set ingress/egress ae mask if inline is enabled */ + if (accel_dev->au_info->num_inline_au) { + if (adf_set_inline_ae_mask(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to set inline ae masks\n"); + goto err_au; + } + } + /* Define ARAM regions */ + if (c4xxx_init_aram_config(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to init aram config\n"); + goto err_au; + } + /* Configure h/w registers for inline operations */ + if (accel_dev->au_info->num_inline_au > 0) + /* Initialise configuration parsing registers */ + if (c4xxx_init_inline_hw(accel_dev)) + goto err_au; + + c4xxx_set_sadb_size(accel_dev); + + if (accel_dev->au_info->num_inline_au > 0) { + /* ici/ice interrupt shall be enabled after msi-x enabled */ + ADF_CSR_WR(csr, + ADF_C4XXX_ERRMSK11, + ADF_C4XXX_ERRMSK11_ERR_DISABLE_ICI_ICE_INTR); + adf_enable_inline_notification(accel_dev); + } + + update_hw_capability(accel_dev); + if (adf_add_debugfs_info(accel_dev)) { + device_printf(GET_DEV(accel_dev), + "Failed to add debug FS information\n"); + goto err_au; + } + return 0; + +err_au: + /* Free and clear accel unit data structures */ + adf_exit_accel_unit_services(accel_dev); + return EFAULT; +} + +static void +adf_exit_accel_units(struct adf_accel_dev *accel_dev) +{ + adf_exit_accel_unit_services(accel_dev); + /* Free aram mapping structure */ + c4xxx_exit_aram_config(accel_dev); + /* Remove entries in debug FS */ + adf_remove_debugfs_info(accel_dev); +} + +static const char * +get_obj_name(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + u32 capabilities = GET_HW_DATA(accel_dev)->accel_capabilities_mask; + bool sym_only_sku = false; + + /* Check if SKU is capable only of symmetric cryptography + * via device capabilities. + */ + if ((capabilities & ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) && + !(capabilities & ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) && + !(capabilities & ADF_ACCEL_CAPABILITIES_COMPRESSION)) + sym_only_sku = true; + + switch (service) { + case ADF_ACCEL_INLINE_CRYPTO: + return ADF_C4XXX_INLINE_OBJ; + case ADF_ACCEL_CRYPTO: + if (sym_only_sku) + return ADF_C4XXX_SYM_OBJ; + else + return ADF_C4XXX_CY_OBJ; + break; + case ADF_ACCEL_COMPRESSION: + return ADF_C4XXX_DC_OBJ; + default: + return NULL; + } +} + +static uint32_t +get_objs_num(struct adf_accel_dev *accel_dev) +{ + u32 srv = 0; + u32 max_srv_id = 0; + unsigned long service_mask = accel_dev->hw_device->service_mask; + + /* The objects number corresponds to the number of services */ + for_each_set_bit(srv, &service_mask, ADF_C4XXX_MAX_OBJ) + { + max_srv_id = srv; + } + + return (max_srv_id + 1); +} + +static uint32_t +get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + u32 ae_mask = 0; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_au = hw_data->get_num_accel_units(hw_data); + struct adf_accel_unit *accel_unit = accel_dev->au_info->au; + u32 i = 0; + + if (service == ADF_ACCEL_SERVICE_NULL) + return 0; + + for (i = 0; i < num_au; i++) { + if (accel_unit[i].services == service) + ae_mask |= accel_unit[i].ae_mask; + } + return ae_mask; +} + +static void +configure_iov_threads(struct adf_accel_dev *accel_dev, bool enable) +{ + struct resource *addr; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_aes = hw_data->get_num_aes(hw_data); + u32 reg = 0x0; + u32 i; + + addr = (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + + /* Set/Unset Valid bits in AE Thread to PCIe Function Mapping */ + for (i = 0; i < ADF_C4XXX_AE2FUNC_REG_PER_AE * num_aes; i++) { + reg = ADF_CSR_RD(addr + ADF_C4XXX_AE2FUNC_MAP_OFFSET, + i * ADF_C4XXX_AE2FUNC_MAP_REG_SIZE); + if (enable) + reg |= ADF_C4XXX_AE2FUNC_MAP_VALID; + else + reg &= ~ADF_C4XXX_AE2FUNC_MAP_VALID; + ADF_CSR_WR(addr + ADF_C4XXX_AE2FUNC_MAP_OFFSET, + i * ADF_C4XXX_AE2FUNC_MAP_REG_SIZE, + reg); + } +} + +static int +adf_get_heartbeat_status_c4xxx(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct icp_qat_fw_init_c4xxx_admin_hb_stats *live_s = + (struct icp_qat_fw_init_c4xxx_admin_hb_stats *) + accel_dev->admin->virt_hb_addr; + const size_t max_aes = hw_device->get_num_aes(hw_device); + const size_t stats_size = + max_aes * sizeof(struct icp_qat_fw_init_c4xxx_admin_hb_stats); + int ret = 0; + size_t ae = 0, thr; + unsigned long ae_mask = 0; + int num_threads_per_ae = ADF_NUM_THREADS_PER_AE; + + /* + * Memory layout of Heartbeat + * + * +----------------+----------------+---------+ + * | Live value | Last value | Count | + * +----------------+----------------+---------+ + * \_______________/\_______________/\________/ + * ^ ^ ^ + * | | | + * | | max_aes * sizeof(adf_hb_count) + * | max_aes * + * sizeof(icp_qat_fw_init_c4xxx_admin_hb_stats) + * max_aes * sizeof(icp_qat_fw_init_c4xxx_admin_hb_stats) + */ + struct icp_qat_fw_init_c4xxx_admin_hb_stats *curr_s; + struct icp_qat_fw_init_c4xxx_admin_hb_stats *last_s = live_s + max_aes; + struct adf_hb_count *count = (struct adf_hb_count *)(last_s + max_aes); + + curr_s = malloc(stats_size, M_QAT, M_WAITOK | M_ZERO); + + memcpy(curr_s, live_s, stats_size); + ae_mask = hw_device->ae_mask; + + for_each_set_bit(ae, &ae_mask, max_aes) + { + for (thr = 0; thr < num_threads_per_ae; ++thr) { + struct icp_qat_fw_init_admin_hb_cnt *curr = + &curr_s[ae].stats[thr]; + struct icp_qat_fw_init_admin_hb_cnt *prev = + &last_s[ae].stats[thr]; + u16 req = curr->req_heartbeat_cnt; + u16 resp = curr->resp_heartbeat_cnt; + u16 last = prev->resp_heartbeat_cnt; + + if ((thr == ADF_AE_ADMIN_THREAD || req != resp) && + resp == last) { + u16 retry = ++count[ae].ae_thread[thr]; + + if (retry >= ADF_CFG_HB_COUNT_THRESHOLD) + ret = EIO; + } else { + count[ae].ae_thread[thr] = 0; + } + } + } + + /* Copy current stats for the next iteration */ + memcpy(last_s, curr_s, stats_size); + free(curr_s, M_QAT); + + return ret; +} + +void +adf_init_hw_data_c4xxx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class = &c4xxx_class; + hw_data->instance_id = c4xxx_class.instances++; + hw_data->num_banks = ADF_C4XXX_ETR_MAX_BANKS; + hw_data->num_rings_per_bank = ADF_C4XXX_NUM_RINGS_PER_BANK; + hw_data->num_accel = ADF_C4XXX_MAX_ACCELERATORS; + hw_data->num_engines = ADF_C4XXX_MAX_ACCELENGINES; + hw_data->num_logical_accel = 1; + hw_data->tx_rx_gap = ADF_C4XXX_RX_RINGS_OFFSET; + hw_data->tx_rings_mask = ADF_C4XXX_TX_RINGS_MASK; + hw_data->alloc_irq = adf_isr_resource_alloc; + hw_data->free_irq = adf_isr_resource_free; + hw_data->enable_error_correction = adf_enable_error_correction; + hw_data->init_ras = adf_init_ras; + hw_data->exit_ras = adf_exit_ras; + hw_data->ras_interrupts = adf_ras_interrupts; + hw_data->get_accel_mask = get_accel_mask; + hw_data->get_ae_mask = get_ae_mask; + hw_data->get_num_accels = get_num_accels; + hw_data->get_num_aes = get_num_aes; + hw_data->get_num_accel_units = get_num_accel_units; + hw_data->get_sram_bar_id = get_sram_bar_id; + hw_data->get_etr_bar_id = get_etr_bar_id; + hw_data->get_misc_bar_id = get_misc_bar_id; + hw_data->get_pf2vf_offset = get_pf2vf_offset; + hw_data->get_vintmsk_offset = get_vintmsk_offset; + hw_data->get_arb_info = get_arb_info; + hw_data->get_admin_info = get_admin_info; + hw_data->get_errsou_offset = get_errsou_offset; + hw_data->get_clock_speed = get_clock_speed; + hw_data->get_eth_doorbell_msg = get_eth_doorbell_msg; + hw_data->get_sku = get_sku; + hw_data->check_prod_sku = c4xxx_check_prod_sku; + hw_data->fw_name = ADF_C4XXX_FW; + hw_data->fw_mmp_name = ADF_C4XXX_MMP; + hw_data->get_obj_name = get_obj_name; + hw_data->get_objs_num = get_objs_num; + hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->configure_iov_threads = configure_iov_threads; + hw_data->disable_iov = adf_disable_sriov; + hw_data->send_admin_init = adf_send_admin_init; + hw_data->init_arb = adf_init_arb_c4xxx; + hw_data->exit_arb = adf_exit_arb_c4xxx; + hw_data->disable_arb = adf_disable_arb; + hw_data->enable_ints = adf_enable_ints; + hw_data->set_ssm_wdtimer = c4xxx_set_ssm_wdtimer; + hw_data->check_slice_hang = c4xxx_check_slice_hang; + hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms; + hw_data->disable_vf2pf_comms = adf_pf_disable_vf2pf_comms; + hw_data->reset_device = adf_reset_flr; + hw_data->restore_device = adf_c4xxx_dev_restore; + hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION; + hw_data->init_accel_units = adf_init_accel_units; + hw_data->reset_hw_units = adf_c4xxx_reset_hw_units; + hw_data->exit_accel_units = adf_exit_accel_units; + hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP; + hw_data->get_heartbeat_status = adf_get_heartbeat_status_c4xxx; + hw_data->get_ae_clock = get_ae_clock; + hw_data->clock_frequency = ADF_C4XXX_AE_FREQ; + hw_data->measure_clock = measure_clock; + hw_data->add_pke_stats = adf_pke_replay_counters_add_c4xxx; + hw_data->remove_pke_stats = adf_pke_replay_counters_remove_c4xxx; + hw_data->add_misc_error = adf_misc_error_add_c4xxx; + hw_data->remove_misc_error = adf_misc_error_remove_c4xxx; + hw_data->extended_dc_capabilities = 0; + hw_data->get_storage_enabled = get_storage_enabled; + hw_data->query_storage_cap = 0; + hw_data->get_accel_cap = c4xxx_get_hw_cap; + hw_data->configure_accel_units = c4xxx_configure_accel_units; + hw_data->pre_reset = adf_dev_pre_reset; + hw_data->post_reset = adf_dev_post_reset; + hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled; + hw_data->count_ras_event = adf_fw_count_ras_event; + hw_data->config_device = adf_config_device; + hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask; +} + +void +adf_clean_hw_data_c4xxx(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class->instances--; +} + +void +remove_oid(struct adf_accel_dev *accel_dev, struct sysctl_oid *oid) +{ + struct sysctl_ctx_list *qat_sysctl_ctx; + int ret; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + + ret = sysctl_ctx_entry_del(qat_sysctl_ctx, oid); + if (ret) + device_printf(GET_DEV(accel_dev), "Failed to delete entry\n"); + + ret = sysctl_remove_oid(oid, 1, 1); + if (ret) + device_printf(GET_DEV(accel_dev), "Failed to delete oid\n"); +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.h new file mode 100644 index 00000000000..8edc9d7f1a0 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_hw_data.h @@ -0,0 +1,570 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C4XXX_HW_DATA_H_ +#define ADF_C4XXX_HW_DATA_H_ + +#include + +/* PCIe configuration space */ +#define ADF_C4XXX_SRAM_BAR 0 +#define ADF_C4XXX_PMISC_BAR 1 +#define ADF_C4XXX_ETR_BAR 2 +#define ADF_C4XXX_RX_RINGS_OFFSET 4 +#define ADF_C4XXX_TX_RINGS_MASK 0xF + +#define ADF_C4XXX_MAX_ACCELERATORS 12 +#define ADF_C4XXX_MAX_ACCELUNITS 6 +#define ADF_C4XXX_MAX_ACCELENGINES 32 +#define ADF_C4XXX_ACCELERATORS_REG_OFFSET 16 + +/* Soft straps offsets */ +#define ADF_C4XXX_SOFTSTRAPPULL0_OFFSET (0x344) +#define ADF_C4XXX_SOFTSTRAPPULL1_OFFSET (0x348) +#define ADF_C4XXX_SOFTSTRAPPULL2_OFFSET (0x34C) + +/* Physical function fuses offsets */ +#define ADF_C4XXX_FUSECTL0_OFFSET (0x350) +#define ADF_C4XXX_FUSECTL1_OFFSET (0x354) +#define ADF_C4XXX_FUSECTL2_OFFSET (0x358) + +#define ADF_C4XXX_FUSE_PKE_MASK (0xFFF000) +#define ADF_C4XXX_FUSE_COMP_MASK (0x000FFF) +#define ADF_C4XXX_FUSE_PROD_SKU_MASK BIT(31) + +#define ADF_C4XXX_LEGFUSE_BASE_SKU_MASK (BIT(2) | BIT(3)) + +#define ADF_C4XXX_FUSE_DISABLE_INLINE_INGRESS BIT(12) +#define ADF_C4XXX_FUSE_DISABLE_INLINE_EGRESS BIT(13) +#define ADF_C4XXX_FUSE_DISABLE_INLINE_MASK \ + (ADF_C4XXX_FUSE_DISABLE_INLINE_INGRESS | \ + ADF_C4XXX_FUSE_DISABLE_INLINE_EGRESS) + +#define ADF_C4XXX_ACCELERATORS_MASK (0xFFF) +#define ADF_C4XXX_ACCELENGINES_MASK (0xFFFFFFFF) + +#define ADF_C4XXX_ETR_MAX_BANKS 128 +#define ADF_C4XXX_SMIAPF0_MASK_OFFSET (0x60000 + 0x20) +#define ADF_C4XXX_SMIAPF1_MASK_OFFSET (0x60000 + 0x24) +#define ADF_C4XXX_SMIAPF2_MASK_OFFSET (0x60000 + 0x28) +#define ADF_C4XXX_SMIAPF3_MASK_OFFSET (0x60000 + 0x2C) +#define ADF_C4XXX_SMIAPF4_MASK_OFFSET (0x60000 + 0x30) +#define ADF_C4XXX_SMIA0_MASK 0xFFFFFFFF +#define ADF_C4XXX_SMIA1_MASK 0xFFFFFFFF +#define ADF_C4XXX_SMIA2_MASK 0xFFFFFFFF +#define ADF_C4XXX_SMIA3_MASK 0xFFFFFFFF +#define ADF_C4XXX_SMIA4_MASK 0x1 +/* Bank and ring configuration */ +#define ADF_C4XXX_NUM_RINGS_PER_BANK 8 +/* Error detection and correction */ +#define ADF_C4XXX_AE_CTX_ENABLES(i) (0x40818 + ((i)*0x1000)) +#define ADF_C4XXX_AE_MISC_CONTROL(i) (0x40960 + ((i)*0x1000)) +#define ADF_C4XXX_ENABLE_AE_ECC_ERR BIT(28) +#define ADF_C4XXX_ENABLE_AE_ECC_PARITY_CORR (BIT(24) | BIT(12)) +#define ADF_C4XXX_UERRSSMSH(i) (0x18 + ((i)*0x4000)) +#define ADF_C4XXX_UERRSSMSH_INTS_CLEAR_MASK (~BIT(0) ^ BIT(16)) +#define ADF_C4XXX_CERRSSMSH(i) (0x10 + ((i)*0x4000)) +#define ADF_C4XXX_CERRSSMSH_INTS_CLEAR_MASK (~BIT(0)) +#define ADF_C4XXX_ERRSSMSH_EN BIT(3) +#define ADF_C4XXX_PF2VF_OFFSET(i) (0x62400 + ((i)*0x04)) +#define ADF_C4XXX_VINTMSK_OFFSET(i) (0x62200 + ((i)*0x04)) + +/* Doorbell interrupt detection in ERRSOU11 */ +#define ADF_C4XXX_DOORBELL_INT_SRC BIT(10) + +/* Doorbell interrupt register definitions */ +#define ADF_C4XXX_ETH_DOORBELL_INT (0x60108) + +/* Clear <3:0> in ETH_DOORBELL_INT */ +#define ADF_C4XXX_ETH_DOORBELL_MASK 0xF + +/* Doorbell register definitions */ +#define ADF_C4XXX_NUM_ETH_DOORBELL_REGS (4) +#define ADF_C4XXX_ETH_DOORBELL(i) (0x61500 + ((i)*0x04)) + +/* Error source registers */ +#define ADF_C4XXX_ERRSOU0 (0x60000 + 0x40) +#define ADF_C4XXX_ERRSOU1 (0x60000 + 0x44) +#define ADF_C4XXX_ERRSOU2 (0x60000 + 0x48) +#define ADF_C4XXX_ERRSOU3 (0x60000 + 0x4C) +#define ADF_C4XXX_ERRSOU4 (0x60000 + 0x50) +#define ADF_C4XXX_ERRSOU5 (0x60000 + 0x54) +#define ADF_C4XXX_ERRSOU6 (0x60000 + 0x58) +#define ADF_C4XXX_ERRSOU7 (0x60000 + 0x5C) +#define ADF_C4XXX_ERRSOU8 (0x60000 + 0x60) +#define ADF_C4XXX_ERRSOU9 (0x60000 + 0x64) +#define ADF_C4XXX_ERRSOU10 (0x60000 + 0x68) +#define ADF_C4XXX_ERRSOU11 (0x60000 + 0x6C) + +/* Error source mask registers */ +#define ADF_C4XXX_ERRMSK0 (0x60000 + 0xC0) +#define ADF_C4XXX_ERRMSK1 (0x60000 + 0xC4) +#define ADF_C4XXX_ERRMSK2 (0x60000 + 0xC8) +#define ADF_C4XXX_ERRMSK3 (0x60000 + 0xCC) +#define ADF_C4XXX_ERRMSK4 (0x60000 + 0xD0) +#define ADF_C4XXX_ERRMSK5 (0x60000 + 0xD4) +#define ADF_C4XXX_ERRMSK6 (0x60000 + 0xD8) +#define ADF_C4XXX_ERRMSK7 (0x60000 + 0xDC) +#define ADF_C4XXX_ERRMSK8 (0x60000 + 0xE0) +#define ADF_C4XXX_ERRMSK9 (0x60000 + 0xE4) +#define ADF_C4XXX_ERRMSK10 (0x60000 + 0xE8) +#define ADF_C4XXX_ERRMSK11 (0x60000 + 0xEC) + +/* Slice Hang enabling related registers */ +#define ADF_C4XXX_SHINTMASKSSM (0x1018) +#define ADF_C4XXX_SSMWDTL (0x54) +#define ADF_C4XXX_SSMWDTH (0x5C) +#define ADF_C4XXX_SSMWDTPKEL (0x58) +#define ADF_C4XXX_SSMWDTPKEH (0x60) +#define ADF_C4XXX_SLICEHANGSTATUS (0x4C) +#define ADF_C4XXX_IASLICEHANGSTATUS (0x50) + +#define ADF_C4XXX_SHINTMASKSSM_VAL (0x00) + +/* Set default value of Slice Hang watchdogs in clock cycles */ +#define ADF_C4XXX_SSM_WDT_64BIT_DEFAULT_VALUE 0x3D0900 +#define ADF_C4XXX_SSM_WDT_PKE_64BIT_DEFAULT_VALUE 0x3000000 + +/* Return interrupt accelerator source mask */ +#define ADF_C4XXX_IRQ_SRC_MASK(accel) (1 << (accel)) + +/* Return address of SHINTMASKSSM register for a given accelerator */ +#define ADF_C4XXX_SHINTMASKSSM_OFFSET(accel) \ + (ADF_C4XXX_SHINTMASKSSM + ((accel)*0x4000)) + +/* Return address of SSMWDTL register for a given accelerator */ +#define ADF_C4XXX_SSMWDTL_OFFSET(accel) (ADF_C4XXX_SSMWDTL + ((accel)*0x4000)) + +/* Return address of SSMWDTH register for a given accelerator */ +#define ADF_C4XXX_SSMWDTH_OFFSET(accel) (ADF_C4XXX_SSMWDTH + ((accel)*0x4000)) + +/* Return address of SSMWDTPKEL register for a given accelerator */ +#define ADF_C4XXX_SSMWDTPKEL_OFFSET(accel) \ + (ADF_C4XXX_SSMWDTPKEL + ((accel)*0x4000)) + +/* Return address of SSMWDTPKEH register for a given accelerator */ +#define ADF_C4XXX_SSMWDTPKEH_OFFSET(accel) \ + (ADF_C4XXX_SSMWDTPKEH + ((accel)*0x4000)) + +/* Return address of SLICEHANGSTATUS register for a given accelerator */ +#define ADF_C4XXX_SLICEHANGSTATUS_OFFSET(accel) \ + (ADF_C4XXX_SLICEHANGSTATUS + ((accel)*0x4000)) + +/* Return address of IASLICEHANGSTATUS register for a given accelerator */ +#define ADF_C4XXX_IASLICEHANGSTATUS_OFFSET(accel) \ + (ADF_C4XXX_IASLICEHANGSTATUS + ((accel)*0x4000)) + +/* RAS enabling related registers */ +#define ADF_C4XXX_SSMFEATREN (0x2010) +#define ADF_C4XXX_SSMSOFTERRORPARITY_MASK (0x1008) + +/* Return address of SSMFEATREN register for given accel */ +#define ADF_C4XXX_GET_SSMFEATREN_OFFSET(accel) \ + (ADF_C4XXX_SSMFEATREN + ((accel)*0x4000)) + +/* Return address of SSMSOFTERRORPARITY_MASK register for given accel */ +#define ADF_C4XXX_GET_SSMSOFTERRORPARITY_MASK_OFFSET(accel) \ + (ADF_C4XXX_SSMSOFTERRORPARITY_MASK + ((accel)*0x4000)) + +/* RAS enabling related registers values to be written */ +#define ADF_C4XXX_SSMFEATREN_VAL (0xFD) +#define ADF_C4XXX_SSMSOFTERRORPARITY_MASK_VAL (0x00) + +/* Enable VF2PF interrupt in ERRMSK4 to ERRMSK7 */ +#define ADF_C4XXX_VF2PF0_31 0x0 +#define ADF_C4XXX_VF2PF32_63 0x0 +#define ADF_C4XXX_VF2PF64_95 0x0 +#define ADF_C4XXX_VF2PF96_127 0x0 + +/* AEx Correctable Error Mask in ERRMSK8 */ +#define ADF_C4XXX_ERRMSK8_COERR 0x0 +#define ADF_C4XXX_ERRSOU8_MECORR_MASK BIT(0) +#define ADF_C4XXX_HI_ME_COR_ERRLOG (0x60104) +#define ADF_C4XXX_HI_ME_COR_ERRLOG_ENABLE (0x61600) +#define ADF_C4XXX_HI_ME_COR_ERRLOG_ENABLE_MASK (0xFFFFFFFF) +#define ADF_C4XXX_HI_ME_COR_ERRLOG_SIZE_IN_BITS (32) + +/* Group of registers related to ERRSOU9 handling + * + * AEx Uncorrectable Error Mask in ERRMSK9 + * CPP Command Parity Errors Mask in ERRMSK9 + * RI Memory Parity Errors Mask in ERRMSK9 + * TI Memory Parity Errors Mask in ERRMSK9 + */ +#define ADF_C4XXX_ERRMSK9_IRQ_MASK 0x0 +#define ADF_C4XXX_ME_UNCORR_ERROR BIT(0) +#define ADF_C4XXX_CPP_CMD_PAR_ERR BIT(1) +#define ADF_C4XXX_RI_MEM_PAR_ERR BIT(2) +#define ADF_C4XXX_TI_MEM_PAR_ERR BIT(3) + +#define ADF_C4XXX_ERRSOU9_ERROR_MASK \ + (ADF_C4XXX_ME_UNCORR_ERROR | ADF_C4XXX_CPP_CMD_PAR_ERR | \ + ADF_C4XXX_RI_MEM_PAR_ERR | ADF_C4XXX_TI_MEM_PAR_ERR) + +#define ADF_C4XXX_HI_ME_UNCERR_LOG (0x60100) +#define ADF_C4XXX_HI_ME_UNCERR_LOG_ENABLE (0x61608) +#define ADF_C4XXX_HI_ME_UNCERR_LOG_ENABLE_MASK (0xFFFFFFFF) +#define ADF_C4XXX_HI_ME_UNCOR_ERRLOG_BITS (32) + +/* HI CPP Agents Command parity Error Log + * CSR name: hicppagentcmdparerrlog + */ +#define ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG (0x6010C) +#define ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG_ENABLE (0x61604) +#define ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG_ENABLE_MASK (0xFFFFFFFF) +#define ADF_C4XXX_TI_CMD_PAR_ERR BIT(0) +#define ADF_C4XXX_RI_CMD_PAR_ERR BIT(1) +#define ADF_C4XXX_ICI_CMD_PAR_ERR BIT(2) +#define ADF_C4XXX_ICE_CMD_PAR_ERR BIT(3) +#define ADF_C4XXX_ARAM_CMD_PAR_ERR BIT(4) +#define ADF_C4XXX_CFC_CMD_PAR_ERR BIT(5) +#define ADF_C4XXX_SSM_CMD_PAR_ERR(value) (((u32)(value) >> 6) & 0xFFF) + +/* RI Memory Parity Error Status Register + * CSR name: rimem_parerr_sts + */ +#define ADF_C4XXX_RI_MEM_PAR_ERR_STS (0x61610) +#define ADF_C4XXX_RI_MEM_PAR_ERR_EN0 (0x61614) +#define ADF_C4XXX_RI_MEM_PAR_ERR_FERR (0x61618) +#define ADF_C4XXX_RI_MEM_PAR_ERR_EN0_MASK (0x7FFFFF) +#define ADF_C4XXX_RI_MEM_MSIX_TBL_INT_MASK (BIT(22)) +#define ADF_C4XXX_RI_MEM_PAR_ERR_STS_MASK \ + (ADF_C4XXX_RI_MEM_PAR_ERR_EN0_MASK ^ ADF_C4XXX_RI_MEM_MSIX_TBL_INT_MASK) + +/* TI Memory Parity Error Status Register + * CSR name: ti_mem_par_err_sts0, ti_mem_par_err_sts1 + */ +#define ADF_C4XXX_TI_MEM_PAR_ERR_STS0 (0x68604) +#define ADF_C4XXX_TI_MEM_PAR_ERR_EN0 (0x68608) +#define ADF_C4XXX_TI_MEM_PAR_ERR_EN0_MASK (0xFFFFFFFF) +#define ADF_C4XXX_TI_MEM_PAR_ERR_STS1 (0x68610) +#define ADF_C4XXX_TI_MEM_PAR_ERR_EN1 (0x68614) +#define ADF_C4XXX_TI_MEM_PAR_ERR_EN1_MASK (0x7FFFF) +#define ADF_C4XXX_TI_MEM_PAR_ERR_STS1_MASK (ADF_C4XXX_TI_MEM_PAR_ERR_EN1_MASK) +#define ADF_C4XXX_TI_MEM_PAR_ERR_FIRST_ERROR (0x68618) + +/* Enable SSM<11:0> in ERRMSK10 */ +#define ADF_C4XXX_ERRMSK10_SSM_ERR 0x0 +#define ADF_C4XXX_ERRSOU10_RAS_MASK 0x1FFF +#define ADF_C4XXX_ERRSOU10_PUSHPULL_MASK BIT(12) + +#define ADF_C4XXX_IASTATSSM_UERRSSMSH_MASK BIT(0) +#define ADF_C4XXX_IASTATSSM_CERRSSMSH_MASK BIT(1) +#define ADF_C4XXX_IASTATSSM_UERRSSMMMP0_MASK BIT(2) +#define ADF_C4XXX_IASTATSSM_CERRSSMMMP0_MASK BIT(3) +#define ADF_C4XXX_IASTATSSM_UERRSSMMMP1_MASK BIT(4) +#define ADF_C4XXX_IASTATSSM_CERRSSMMMP1_MASK BIT(5) +#define ADF_C4XXX_IASTATSSM_UERRSSMMMP2_MASK BIT(6) +#define ADF_C4XXX_IASTATSSM_CERRSSMMMP2_MASK BIT(7) +#define ADF_C4XXX_IASTATSSM_UERRSSMMMP3_MASK BIT(8) +#define ADF_C4XXX_IASTATSSM_CERRSSMMMP3_MASK BIT(9) +#define ADF_C4XXX_IASTATSSM_UERRSSMMMP4_MASK BIT(10) +#define ADF_C4XXX_IASTATSSM_CERRSSMMMP4_MASK BIT(11) +#define ADF_C4XXX_IASTATSSM_PPERR_MASK BIT(12) +#define ADF_C4XXX_IASTATSSM_SPPPAR_ERR_MASK BIT(14) +#define ADF_C4XXX_IASTATSSM_CPPPAR_ERR_MASK BIT(15) +#define ADF_C4XXX_IASTATSSM_RFPAR_ERR_MASK BIT(16) + +#define ADF_C4XXX_IAINTSTATSSM(i) ((i)*0x4000 + 0x206C) +#define ADF_C4XXX_IASTATSSM_MASK 0x1DFFF +#define ADF_C4XXX_IASTATSSM_CLR_MASK 0xFFFE2000 +#define ADF_C4XXX_IASTATSSM_BITS 17 +#define ADF_C4XXX_IASTATSSM_SLICE_HANG_ERR_BIT 13 +#define ADF_C4XXX_IASTATSSM_SPP_PAR_ERR_BIT 14 +#define ADF_C4XXX_IASTATSSM_CPP_PAR_ERR_BIT 15 + +/* Accelerator Interrupt Mask (SSM) + * CSR name: intmaskssm[0..11] + * Returns address of INTMASKSSM register for a given accel. + * This register is used to unmask SSM interrupts to host + * reported by ERRSOU10. + */ +#define ADF_C4XXX_GET_INTMASKSSM_OFFSET(accel) ((accel)*0x4000) + +/* Base address of SPP parity error mask register + * CSR name: sppparerrmsk[0..11] + */ +#define ADF_C4XXX_SPPPARERRMSK_OFFSET (0x2028) + +/* Returns address of SPPPARERRMSK register for a given accel. + * This register is used to unmask SPP parity errors interrupts to host + * reported by ERRSOU10. + */ +#define ADF_C4XXX_GET_SPPPARERRMSK_OFFSET(accel) \ + (ADF_C4XXX_SPPPARERRMSK_OFFSET + ((accel)*0x4000)) + +#define ADF_C4XXX_EXPRPSSMCPR0(i) ((i)*0x4000 + 0x400) +#define ADF_C4XXX_EXPRPSSMXLT0(i) ((i)*0x4000 + 0x500) +#define ADF_C4XXX_EXPRPSSMCPR1(i) ((i)*0x4000 + 0x1400) +#define ADF_C4XXX_EXPRPSSMXLT1(i) ((i)*0x4000 + 0x1500) + +#define ADF_C4XXX_EXPRPSSM_FATAL_MASK BIT(2) +#define ADF_C4XXX_EXPRPSSM_SOFT_MASK BIT(3) + +#define ADF_C4XXX_PPERR_INTS_CLEAR_MASK BIT(0) + +#define ADF_C4XXX_SSMSOFTERRORPARITY(i) ((i)*0x4000 + 0x1000) +#define ADF_C4XXX_SSMCPPERR(i) ((i)*0x4000 + 0x2030) + +/* ethernet doorbell in ERRMSK11 + * timisc in ERRMSK11 + * rimisc in ERRMSK11 + * ppmiscerr in ERRMSK11 + * cerr in ERRMSK11 + * uerr in ERRMSK11 + * ici in ERRMSK11 + * ice in ERRMSK11 + */ +#define ADF_C4XXX_ERRMSK11_ERR 0x0 +/* + * BIT(7) disables ICI interrupt + * BIT(8) disables ICE interrupt + */ +#define ADF_C4XXX_ERRMSK11_ERR_DISABLE_ICI_ICE_INTR (BIT(7) | BIT(8)) + +/* RAS mask for errors reported by ERRSOU11 */ +#define ADF_C4XXX_ERRSOU11_ERROR_MASK (0x1FF) +#define ADF_C4XXX_TI_MISC BIT(0) +#define ADF_C4XXX_RI_PUSH_PULL_PAR_ERR BIT(1) +#define ADF_C4XXX_TI_PUSH_PULL_PAR_ERR BIT(2) +#define ADF_C4XXX_ARAM_CORR_ERR BIT(3) +#define ADF_C4XXX_ARAM_UNCORR_ERR BIT(4) +#define ADF_C4XXX_TI_PULL_PAR_ERR BIT(5) +#define ADF_C4XXX_RI_PUSH_PAR_ERR BIT(6) +#define ADF_C4XXX_INLINE_INGRESS_INTR BIT(7) +#define ADF_C4XXX_INLINE_EGRESS_INTR BIT(8) + +/* TI Misc error status */ +#define ADF_C4XXX_TI_MISC_STS (0x6854C) +#define ADF_C4XXX_TI_MISC_ERR_MASK (BIT(0)) +#define ADF_C4XXX_GET_TI_MISC_ERR_TYPE(status) ((status) >> 1 & 0x3) +#define ADF_C4XXX_TI_BME_RESP_ORDER_ERR (0x1) +#define ADF_C4XXX_TI_RESP_ORDER_ERR (0x2) + +/* RI CPP interface status register */ +#define ADF_C4XXX_RI_CPP_INT_STS (0x61118) +#define ADF_C4XXX_RI_CPP_INT_STS_PUSH_ERR BIT(0) +#define ADF_C4XXX_RI_CPP_INT_STS_PULL_ERR BIT(1) +#define ADF_C4XXX_RI_CPP_INT_STS_PUSH_DATA_PAR_ERR BIT(2) +#define ADF_C4XXX_GET_CPP_BUS_FROM_STS(status) ((status) >> 31 & 0x1) + +/* RI CPP interface control register. */ +#define ADF_C4XXX_RICPPINTCTL (0x61000 + 0x004) +/* + * BIT(3) enables error parity checking on CPP. + * BIT(2) enables error detection and reporting on the RI Parity Error. + * BIT(1) enables error detection and reporting on the RI CPP Pull interface. + * BIT(0) enables error detection and reporting on the RI CPP Push interface. + */ +#define ADF_C4XXX_RICPP_EN (BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +/* TI CPP interface status register */ +#define ADF_C4XXX_TI_CPP_INT_STS (0x6853C) +#define ADF_C4XXX_TI_CPP_INT_STS_PUSH_ERR BIT(0) +#define ADF_C4XXX_TI_CPP_INT_STS_PULL_ERR BIT(1) +#define ADF_C4XXX_TI_CPP_INT_STS_PUSH_DATA_PAR_ERR BIT(2) + +#define ADF_C4XXX_TICPPINTCTL (0x68000 + 0x538) +/* + * BIT(4) enables 'stop and scream' feature for TI RF. + * BIT(3) enables CPP command and pull data parity checking. + * BIT(2) enables data parity error detection and reporting on the TI CPP + * Pull interface. + * BIT(1) enables error detection and reporting on the TI CPP Pull interface. + * BIT(0) enables error detection and reporting on the TI CPP Push interface. + */ +#define ADF_C4XXX_TICPP_EN (BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +/* CPP error control and logging register */ +#define ADF_C4XXX_CPP_CFC_ERR_CTRL (0x70000 + 0xC00) + +/* + * BIT(1) enables generation of irqs to the PCIe endpoint + * for the errors specified in CPP_CFC_ERR_STATUS + * BIT(0) enables detecting and logging of push/pull data errors. + */ +#define ADF_C4XXX_CPP_CFC_UE (BIT(1) | BIT(0)) + +/* ARAM error interrupt enable registers */ +#define ADF_C4XXX_ARAMCERR (0x101700) +#define ADF_C4XXX_ARAMUERR (0x101704) +#define ADF_C4XXX_CPPMEMTGTERR (0x101710) +#define ADF_C4XXX_ARAM_CORR_ERR_MASK (BIT(0)) +#define ADF_C4XXX_ARAM_UNCORR_ERR_MASK (BIT(0)) +#define ADF_C4XXX_CLEAR_CSR_BIT(csr, bit_num) ((csr) &= ~(BIT(bit_num))) + +/* ARAM correctable errors defined in ARAMCERR + * Bit<3> Enable fixing and logging correctable errors by hardware. + * Bit<26> Enable interrupt to host for ARAM correctable errors. + */ +#define ADF_C4XXX_ARAM_CERR (BIT(3) | BIT(26)) + +/* ARAM correctable errors defined in ARAMUERR + * Bit<3> Enable detection and logging of ARAM uncorrectable errors. + * Bit<19> Enable interrupt to host for ARAM uncorrectable errors. + */ +#define ADF_C4XXX_ARAM_UERR (BIT(3) | BIT(19)) + +/* Misc memory target error registers in CPPMEMTGTERR + * Bit<2> CPP memory push/pull error enable bit + * Bit<7> RI push/pull error enable bit + * Bit<8> ARAM pull data parity check bit + * Bit<9> RAS push error enable bit + */ +#define ADF_C4XXX_TGT_UERR (BIT(9) | BIT(8) | BIT(7) | BIT(2)) + +/* Slice power down register */ +#define ADF_C4XXX_SLICEPWRDOWN(i) (((i)*0x4000) + 0x2C) + +/* Enabling PKE0 to PKE4. */ +#define ADF_C4XXX_MMP_PWR_UP_MSK \ + (BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16)) + +/* Error registers for MMP0-MMP4. */ +#define ADF_C4XXX_MAX_MMP (5) + +#define ADF_C4XXX_MMP_BASE(i) ((i)*0x1000 % 0x3800) +#define ADF_C4XXX_CERRSSMMMP(i, n) ((i)*0x4000 + ADF_C4XXX_MMP_BASE(n) + 0x380) +#define ADF_C4XXX_UERRSSMMMP(i, n) ((i)*0x4000 + ADF_C4XXX_MMP_BASE(n) + 0x388) +#define ADF_C4XXX_UERRSSMMMPAD(i, n) \ + ((i)*0x4000 + ADF_C4XXX_MMP_BASE(n) + 0x38C) +#define ADF_C4XXX_INTMASKSSM(i) ((i)*0x4000 + 0x0) + +#define ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK ((BIT(16) | BIT(0))) +#define ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK BIT(0) + +/* Bit<3> enables logging of MMP uncorrectable errors */ +#define ADF_C4XXX_UERRSSMMMP_EN BIT(3) + +/* Bit<3> enables logging of MMP correctable errors */ +#define ADF_C4XXX_CERRSSMMMP_EN BIT(3) + +#define ADF_C4XXX_ERRMSK_VF2PF_OFFSET(i) (ADF_C4XXX_ERRMSK4 + ((i)*0x04)) + +/* RAM base address registers */ +#define ADF_C4XXX_RAMBASEADDRHI 0x71020 + +#define ADF_C4XXX_NUM_ARAM_ENTRIES 8 + +/* ARAM region sizes in bytes */ +#define ADF_C4XXX_1MB_SIZE (1024 * 1024) +#define ADF_C4XXX_2MB_ARAM_SIZE (2 * ADF_C4XXX_1MB_SIZE) +#define ADF_C4XXX_4MB_ARAM_SIZE (4 * ADF_C4XXX_1MB_SIZE) +#define ADF_C4XXX_DEFAULT_MMP_REGION_SIZE (1024 * 256) +#define ADF_C4XXX_DEFAULT_SKM_REGION_SIZE (1024 * 256) +#define ADF_C4XXX_AU_COMPR_INTERM_SIZE (1024 * 128 * 2 * 2) +#define ADF_C4XXX_DEF_ASYM_MASK 0x1 + +/* Arbiter configuration */ +#define ADF_C4XXX_ARB_OFFSET 0x80000 +#define ADF_C4XXX_ARB_WQCFG_OFFSET 0x200 + +/* Admin Interface Reg Offset */ +#define ADF_C4XXX_ADMINMSGUR_OFFSET (0x60000 + 0x8000 + 0x400 + 0x174) +#define ADF_C4XXX_ADMINMSGLR_OFFSET (0x60000 + 0x8000 + 0x400 + 0x178) +#define ADF_C4XXX_MAILBOX_BASE_OFFSET 0x40970 + +/* AE to function mapping */ +#define ADF_C4XXX_AE2FUNC_REG_PER_AE 8 +#define ADF_C4XXX_AE2FUNC_MAP_OFFSET 0x68800 +#define ADF_C4XXX_AE2FUNC_MAP_REG_SIZE 4 +#define ADF_C4XXX_AE2FUNC_MAP_VALID BIT(8) + +/* Enable each of the units on the chip */ +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC 0x7096C +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_DISABLE_ALL 0x0 +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ICE_ENABLE BIT(4) +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ICI_ENABLE BIT(3) +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_ARAM BIT(2) + +/* Clock is fully sets up after some delay */ +#define ADF_C4XXX_GLOBAL_CLK_ENABLE_GENERIC_RESTART_DELAY 10 +#define ADF_C4XXX_GLOBAL_CLK_RESTART_LOOP 10 + +/* Reset each of the PPC units on the chip */ +#define ADF_C4XXX_IXP_RESET_GENERIC 0x70940 +#define ADF_C4XXX_IXP_RESET_GENERIC_OUT_OF_RESET_TRIGGER 0x0 +#define ADF_C4XXX_IXP_RESET_GENERIC_INLINE_INGRESS BIT(4) +#define ADF_C4XXX_IXP_RESET_GENERIC_INLINE_EGRESS BIT(3) +#define ADF_C4XXX_IXP_RESET_GENERIC_ARAM BIT(2) + +/* Default accel unit configuration */ +#define ADF_C4XXX_NUM_CY_AU \ + { \ + [DEV_SKU_1] = 4, [DEV_SKU_1_CY] = 6, [DEV_SKU_2] = 3, \ + [DEV_SKU_2_CY] = 4, [DEV_SKU_3] = 1, [DEV_SKU_3_CY] = 2, \ + [DEV_SKU_UNKNOWN] = 0 \ + } +#define ADF_C4XXX_NUM_DC_AU \ + { \ + [DEV_SKU_1] = 2, [DEV_SKU_1_CY] = 0, [DEV_SKU_2] = 1, \ + [DEV_SKU_2_CY] = 0, [DEV_SKU_3] = 1, [DEV_SKU_3_CY] = 0, \ + [DEV_SKU_UNKNOWN] = 0 \ + } + +#define ADF_C4XXX_NUM_ACCEL_PER_AU 2 +#define ADF_C4XXX_NUM_INLINE_AU \ + { \ + [DEV_SKU_1] = 0, [DEV_SKU_1_CY] = 0, [DEV_SKU_2] = 0, \ + [DEV_SKU_2_CY] = 0, [DEV_SKU_3] = 0, [DEV_SKU_3_CY] = 0, \ + [DEV_SKU_UNKNOWN] = 0 \ + } +#define ADF_C4XXX_6_AE 6 +#define ADF_C4XXX_4_AE 4 +#define ADF_C4XXX_100 100 +#define ADF_C4XXX_ROUND_LIMIT 5 +#define ADF_C4XXX_PERCENTAGE "%" + +#define ADF_C4XXX_ARB_CY 0x12222222 +#define ADF_C4XXX_ARB_DC 0x00000888 + +/* Default accel firmware maximal object*/ +#define ADF_C4XXX_MAX_OBJ 4 + +/* Default 4 partitions for services */ +#define ADF_C4XXX_PART_ASYM 0 +#define ADF_C4XXX_PART_SYM 1 +#define ADF_C4XXX_PART_UNUSED 2 +#define ADF_C4XXX_PART_DC 3 +#define ADF_C4XXX_PARTS_PER_GRP 16 + +#define ADF_C4XXX_PARTITION_LUT_OFFSET 0x81000 +#define ADF_C4XXX_WRKTHD2PARTMAP 0x82000 +#define ADF_C4XXX_WQM_SIZE 0x4 + +#define ADF_C4XXX_DEFAULT_PARTITIONS \ + (ADF_C4XXX_PART_ASYM | ADF_C4XXX_PART_SYM << 8 | \ + ADF_C4XXX_PART_UNUSED << 16 | ADF_C4XXX_PART_DC << 24) + +/* SKU configurations */ +#define ADF_C4XXX_HIGH_SKU_AES 32 +#define ADF_C4XXX_MED_SKU_AES 24 +#define ADF_C4XXX_LOW_SKU_AES 12 + +#define READ_CSR_WQM(csr_addr, csr_offset, index) \ + ADF_CSR_RD(csr_addr, (csr_offset) + ((index)*ADF_C4XXX_WQM_SIZE)) + +#define WRITE_CSR_WQM(csr_addr, csr_offset, index, value) \ + ADF_CSR_WR(csr_addr, (csr_offset) + ((index)*ADF_C4XXX_WQM_SIZE), value) + +/* Firmware Binary */ +#define ADF_C4XXX_FW "qat_c4xxx_fw" +#define ADF_C4XXX_MMP "qat_c4xxx_mmp_fw" +#define ADF_C4XXX_INLINE_OBJ "qat_c4xxx_inline.bin" +#define ADF_C4XXX_DC_OBJ "qat_c4xxx_dc.bin" +#define ADF_C4XXX_CY_OBJ "qat_c4xxx_cy.bin" +#define ADF_C4XXX_SYM_OBJ "qat_c4xxx_sym.bin" + +void adf_init_hw_data_c4xxx(struct adf_hw_device_data *hw_data); +void adf_clean_hw_data_c4xxx(struct adf_hw_device_data *hw_data); +int adf_init_arb_c4xxx(struct adf_accel_dev *accel_dev); +void adf_exit_arb_c4xxx(struct adf_accel_dev *accel_dev); + +#define ADF_C4XXX_AE_FREQ (800 * 1000000) +#define ADF_C4XXX_MIN_AE_FREQ (571 * 1000000) +#define ADF_C4XXX_MAX_AE_FREQ (800 * 1000000) + +int c4xxx_init_ae_config(struct adf_accel_dev *accel_dev); +void c4xxx_exit_ae_config(struct adf_accel_dev *accel_dev); +void remove_oid(struct adf_accel_dev *accel_dev, struct sysctl_oid *oid); +#endif diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_inline.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_inline.h new file mode 100644 index 00000000000..aace6081c53 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_inline.h @@ -0,0 +1,599 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C4XXX_INLINE_H_ +#define ADF_C4XXX_INLINE_H_ + +/* Inline register addresses in SRAM BAR */ +#define ARAM_CSR_BAR_OFFSET 0x100000 +#define ADF_C4XXX_REG_SA_CTRL_LOCK (ARAM_CSR_BAR_OFFSET + 0x00) +#define ADF_C4XXX_REG_SA_SCRATCH_0 (ARAM_CSR_BAR_OFFSET + 0x04) +#define ADF_C4XXX_REG_SA_SCRATCH_2 (ARAM_CSR_BAR_OFFSET + 0x0C) +#define ADF_C4XXX_REG_SA_ENTRY_CTRL (ARAM_CSR_BAR_OFFSET + 0x18) +#define ADF_C4XXX_REG_SA_DB_CTRL (ARAM_CSR_BAR_OFFSET + 0x1C) +#define ADF_C4XXX_REG_SA_REMAP (ARAM_CSR_BAR_OFFSET + 0x20) +#define ADF_C4XXX_REG_SA_INLINE_CAPABILITY (ARAM_CSR_BAR_OFFSET + 0x24) +#define ADF_C4XXX_REG_SA_INLINE_ENABLE (ARAM_CSR_BAR_OFFSET + 0x28) +#define ADF_C4XXX_REG_SA_LINK_UP (ARAM_CSR_BAR_OFFSET + 0x2C) +#define ADF_C4XXX_REG_SA_FUNC_LIMITS (ARAM_CSR_BAR_OFFSET + 0x38) + +#define ADF_C4XXX_SADB_SIZE_BIT BIT(24) +#define ADF_C4XXX_SADB_SIZE_IN_WORDS(accel_dev) \ + ((accel_dev)->aram_info->sadb_region_size / 32) +#define ADF_C4XXX_DEFAULT_MAX_CHAIN_LEN 0 +#define ADF_C4XXX_DEFAULT_LIMIT_CHAIN_LEN 0 +/* SADB CTRL register bit offsets */ +#define ADF_C4XXX_SADB_BIT_OFFSET 6 +#define ADF_C4XXX_MAX_CHAIN_LEN_BIT_OFFS 1 + +#define ADF_C4XXX_SADB_REG_VALUE(accel_dev) \ + ((ADF_C4XXX_SADB_SIZE_IN_WORDS(accel_dev) \ + << ADF_C4XXX_SADB_BIT_OFFSET) | \ + (ADF_C4XXX_DEFAULT_MAX_CHAIN_LEN \ + << ADF_C4XXX_MAX_CHAIN_LEN_BIT_OFFS) | \ + (ADF_C4XXX_DEFAULT_LIMIT_CHAIN_LEN)) + +#define ADF_C4XXX_INLINE_INGRESS_OFFSET 0x0 +#define ADF_C4XXX_INLINE_EGRESS_OFFSET 0x1000 + +/* MAC_CFG register access related definitions */ +#define ADF_C4XXX_STATS_REQUEST_ENABLED BIT(16) +#define ADF_C4XXX_STATS_REQUEST_DISABLED ~BIT(16) +#define ADF_C4XXX_UNLOCK true +#define ADF_C4XXX_LOCK false + +/* MAC IP register access related definitions */ +#define ADF_C4XXX_MAC_STATS_READY BIT(0) +#define ADF_C4XXX_MAX_NUM_STAT_READY_READS 10 +#define ADF_C4XXX_MAC_STATS_POLLING_INTERVAL 100 +#define ADF_C4XXX_MAC_ERROR_TX_UNDERRUN BIT(6) +#define ADF_C4XXX_MAC_ERROR_TX_FCS BIT(7) +#define ADF_C4XXX_MAC_ERROR_TX_DATA_CORRUPT BIT(8) +#define ADF_C4XXX_MAC_ERROR_RX_OVERRUN BIT(9) +#define ADF_C4XXX_MAC_ERROR_RX_RUNT BIT(10) +#define ADF_C4XXX_MAC_ERROR_RX_UNDERSIZE BIT(11) +#define ADF_C4XXX_MAC_ERROR_RX_JABBER BIT(12) +#define ADF_C4XXX_MAC_ERROR_RX_OVERSIZE BIT(13) +#define ADF_C4XXX_MAC_ERROR_RX_FCS BIT(14) +#define ADF_C4XXX_MAC_ERROR_RX_FRAME BIT(15) +#define ADF_C4XXX_MAC_ERROR_RX_CODE BIT(16) +#define ADF_C4XXX_MAC_ERROR_RX_PREAMBLE BIT(17) +#define ADF_C4XXX_MAC_RX_LINK_UP BIT(21) +#define ADF_C4XXX_MAC_INVALID_SPEED BIT(31) +#define ADF_C4XXX_MAC_PIA_RX_FIFO_OVERRUN (1ULL << 32) +#define ADF_C4XXX_MAC_PIA_TX_FIFO_OVERRUN (1ULL << 33) +#define ADF_C4XXX_MAC_PIA_TX_FIFO_UNDERRUN (1ULL << 34) + +/* 64-bit inline control registers. It will require + * adding ADF_C4XXX_INLINE_INGRESS_OFFSET to the address for ingress + * direction or ADF_C4XXX_INLINE_EGRESS_OFFSET to the address for + * egress direction + */ +#define ADF_C4XXX_MAC_IP 0x8 +#define ADF_C4XXX_MAC_CFG 0x18 +#define ADF_C4XXX_MAC_PIA_CFG 0xA0 + +/* Default MAC_CFG value + * - MAC_LINKUP_ENABLE = 1 + * - MAX_FRAME_LENGTH = 0x2600 + */ +#define ADF_C4XXX_MAC_CFG_VALUE 0x00000000FA0C2600 + +/* Bit definitions for MAC_PIA_CFG register */ +#define ADF_C4XXX_ONPI_ENABLE BIT(0) +#define ADF_C4XXX_XOFF_ENABLE BIT(10) + +/* New default value for MAC_PIA_CFG register */ +#define ADF_C4XXX_MAC_PIA_CFG_VALUE \ + (ADF_C4XXX_XOFF_ENABLE | ADF_C4XXX_ONPI_ENABLE) + +/* 64-bit Inline statistics registers. It will require + * adding ADF_C4XXX_INLINE_INGRESS_OFFSET to the address for ingress + * direction or ADF_C4XXX_INLINE_EGRESS_OFFSET to the address for + * egress direction + */ +#define ADF_C4XXX_MAC_STAT_TX_OCTET 0x100 +#define ADF_C4XXX_MAC_STAT_TX_FRAME 0x110 +#define ADF_C4XXX_MAC_STAT_TX_BAD_FRAME 0x118 +#define ADF_C4XXX_MAC_STAT_TX_FCS_ERROR 0x120 +#define ADF_C4XXX_MAC_STAT_TX_64 0x130 +#define ADF_C4XXX_MAC_STAT_TX_65 0x138 +#define ADF_C4XXX_MAC_STAT_TX_128 0x140 +#define ADF_C4XXX_MAC_STAT_TX_256 0x148 +#define ADF_C4XXX_MAC_STAT_TX_512 0x150 +#define ADF_C4XXX_MAC_STAT_TX_1024 0x158 +#define ADF_C4XXX_MAC_STAT_TX_1519 0x160 +#define ADF_C4XXX_MAC_STAT_TX_JABBER 0x168 +#define ADF_C4XXX_MAC_STAT_RX_OCTET 0x200 +#define ADF_C4XXX_MAC_STAT_RX_FRAME 0x210 +#define ADF_C4XXX_MAC_STAT_RX_BAD_FRAME 0x218 +#define ADF_C4XXX_MAC_STAT_RX_FCS_ERROR 0x220 +#define ADF_C4XXX_MAC_STAT_RX_64 0x250 +#define ADF_C4XXX_MAC_STAT_RX_65 0x258 +#define ADF_C4XXX_MAC_STAT_RX_128 0x260 +#define ADF_C4XXX_MAC_STAT_RX_256 0x268 +#define ADF_C4XXX_MAC_STAT_RX_512 0x270 +#define ADF_C4XXX_MAC_STAT_RX_1024 0x278 +#define ADF_C4XXX_MAC_STAT_RX_1519 0x280 +#define ADF_C4XXX_MAC_STAT_RX_OVERSIZE 0x288 +#define ADF_C4XXX_MAC_STAT_RX_JABBER 0x290 + +/* 32-bit Inline statistics registers. It will require + * adding ADF_C4XXX_INLINE_INGRESS_OFFSET to the address for ingress + * direction or ADF_C4XXX_INLINE_EGRESS_OFFSET to the address for + * egress direction + */ +#define ADF_C4XXX_IC_PAR_IPSEC_DESC_COUNT 0xBC0 +#define ADF_C4XXX_IC_PAR_MIXED_DESC_COUNT 0xBC4 +#define ADF_C4XXX_IC_PAR_FULLY_CLEAR_DESC_COUNT 0xBC8 +#define ADF_C4XXX_IC_PAR_CLR_COUNT 0xBCC +#define ADF_C4XXX_IC_CTPB_PKT_COUNT 0xDF4 +#define ADF_C4XXX_RB_DATA_COUNT 0xDF8 +#define ADF_C4XXX_IC_CLEAR_DESC_COUNT 0xDFC +#define ADF_C4XXX_IC_IPSEC_DESC_COUNT 0xE00 + +/* REG_CMD_DIS_MISC bit definitions */ +#define ADF_C4XXX_BYTE_SWAP_ENABLE BIT(0) +#define ADF_C4XXX_REG_CMD_DIS_MISC_DEFAULT_VALUE (ADF_C4XXX_BYTE_SWAP_ENABLE) + +/* Command Dispatch Misc Register */ +#define ADF_C4XXX_INGRESS_CMD_DIS_MISC (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0x8A8) + +#define ADF_C4XXX_EGRESS_CMD_DIS_MISC (ADF_C4XXX_INLINE_EGRESS_OFFSET + 0x8A8) + +/* Congestion management threshold registers */ +#define ADF_C4XXX_NEXT_FCTHRESH_OFFSET 4 + +/* Number of congestion management domains */ +#define ADF_C4XXX_NUM_CONGEST_DOMAINS 8 + +#define ADF_C4XXX_BB_FCHTHRESH_OFFSET 0xB78 + +/* IC_BB_FCHTHRESH registers */ +#define ADF_C4XXX_ICI_BB_FCHTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_BB_FCHTHRESH_OFFSET) + +#define ADF_C4XXX_ICE_BB_FCHTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_BB_FCHTHRESH_OFFSET) + +#define ADF_C4XXX_WR_ICI_BB_FCHTHRESH(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICI_BB_FCHTHRESH_OFFSET + \ + (index)*ADF_C4XXX_NEXT_FCTHRESH_OFFSET), \ + value) + +#define ADF_C4XXX_WR_ICE_BB_FCHTHRESH(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICE_BB_FCHTHRESH_OFFSET + \ + (index)*ADF_C4XXX_NEXT_FCTHRESH_OFFSET), \ + value) + +#define ADF_C4XXX_BB_FCLTHRESH_OFFSET 0xB98 + +/* IC_BB_FCLTHRESH registers */ +#define ADF_C4XXX_ICI_BB_FCLTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_BB_FCLTHRESH_OFFSET) + +#define ADF_C4XXX_ICE_BB_FCLTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_BB_FCLTHRESH_OFFSET) + +#define ADF_C4XXX_WR_ICI_BB_FCLTHRESH(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICI_BB_FCLTHRESH_OFFSET + \ + (index)*ADF_C4XXX_NEXT_FCTHRESH_OFFSET), \ + value) + +#define ADF_C4XXX_WR_ICE_BB_FCLTHRESH(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICE_BB_FCLTHRESH_OFFSET + \ + (index)*ADF_C4XXX_NEXT_FCTHRESH_OFFSET), \ + value) + +#define ADF_C4XXX_BB_BEHTHRESH_OFFSET 0xBB8 +#define ADF_C4XXX_BB_BELTHRESH_OFFSET 0xBBC +#define ADF_C4XXX_BEWIP_THRESH_OFFSET 0xDEC +#define ADF_C4XXX_CTPB_THRESH_OFFSET 0xDE8 +#define ADF_C4XXX_CIRQ_OFFSET 0xDE4 +#define ADF_C4XXX_Q2MEMAP_OFFSET 0xC04 + +/* IC_BB_BEHTHRESH register */ +#define ADF_C4XXX_ICI_BB_BEHTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_BB_BEHTHRESH_OFFSET) + +#define ADF_C4XXX_ICE_BB_BEHTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_BB_BEHTHRESH_OFFSET) + +/* IC_BB_BELTHRESH register */ +#define ADF_C4XXX_ICI_BB_BELTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_BB_BELTHRESH_OFFSET) + +#define ADF_C4XXX_ICE_BB_BELTHRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_BB_BELTHRESH_OFFSET) + +/* IC_BEWIP_THRESH register */ +#define ADF_C4XXX_ICI_BEWIP_THRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_BEWIP_THRESH_OFFSET) + +#define ADF_C4XXX_ICE_BEWIP_THRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_BEWIP_THRESH_OFFSET) + +/* IC_CTPB_THRESH register */ +#define ADF_C4XXX_ICI_CTPB_THRESH_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_CTPB_THRESH_OFFSET) + +#define ADF_C4XXX_ICE_CTPB_THRESH_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_CTPB_THRESH_OFFSET) + +/* ADF_C4XXX_ICI_CIRQ_OFFSET */ +#define ADF_C4XXX_ICI_CIRQ_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_CIRQ_OFFSET) + +#define ADF_C4XXX_ICE_CIRQ_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_CIRQ_OFFSET) + +/* IC_Q2MEMAP register */ +#define ADF_C4XXX_ICI_Q2MEMAP_OFFSET \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + ADF_C4XXX_Q2MEMAP_OFFSET) + +#define ADF_C4XXX_ICE_Q2MEMAP_OFFSET \ + (ADF_C4XXX_INLINE_EGRESS_OFFSET + ADF_C4XXX_Q2MEMAP_OFFSET) + +#define ADF_C4XXX_NEXT_Q2MEMAP_OFFSET 4 +#define ADF_C4XXX_NUM_Q2MEMAP_REGISTERS 8 + +#define ADF_C4XXX_WR_CSR_ICI_Q2MEMAP(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICI_Q2MEMAP_OFFSET + \ + (index)*ADF_C4XXX_NEXT_Q2MEMAP_OFFSET), \ + value) + +#define ADF_C4XXX_WR_CSR_ICE_Q2MEMAP(csr_base_addr, index, value) \ + ADF_CSR_WR(csr_base_addr, \ + (ADF_C4XXX_ICE_Q2MEMAP_OFFSET + \ + (index)*ADF_C4XXX_NEXT_Q2MEMAP_OFFSET), \ + value) + +/* IC_PARSE_CTRL register */ +#define ADF_C4XXX_DEFAULT_KEY_LENGTH 21 +#define ADF_C4XXX_DEFAULT_REL_ABS_OFFSET 1 +#define ADF_C4XXX_DEFAULT_NUM_TUPLES 4 +#define ADF_C4XXX_IC_PARSE_CTRL_OFFSET_DEFAULT_VALUE \ + ((ADF_C4XXX_DEFAULT_KEY_LENGTH << 4) | \ + (ADF_C4XXX_DEFAULT_REL_ABS_OFFSET << 3) | \ + (ADF_C4XXX_DEFAULT_NUM_TUPLES)) + +/* Configuration parsing register definitions */ +#define ADF_C4XXX_IC_PARSE_CTRL_OFFSET (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB00) + +/* Fixed data parsing register */ +#define ADF_C4XXX_IC_PARSE_FIXED_DATA(i) \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB04 + ((i)*4)) +#define ADF_C4XXX_DEFAULT_IC_PARSE_FIXED_DATA_0 0x32 + +/* Fixed length parsing register */ +#define ADF_C4XXX_IC_PARSE_FIXED_LENGTH \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB14) +#define ADF_C4XXX_DEFAULT_IC_PARSE_FIXED_LEN 0x0 + +/* IC_PARSE_IPV4 offset and length registers */ +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_0 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB18) +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_1 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB1C) +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_2 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB20) +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_3 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB24) +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_4 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB28) +#define ADF_C4XXX_IC_PARSE_IPV4_OFFSET_5 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB2C) + +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_0 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB30) +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_1 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB34) +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_2 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB38) +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_3 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB3C) +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_4 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB40) +#define ADF_C4XXX_IC_PARSE_IPV4_LENGTH_5 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB44) + +#define ADF_C4XXX_IPV4_OFFSET_0_PARSER_BASE 0x1 +#define ADF_C4XXX_IPV4_OFFSET_0_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_0_VALUE \ + ((ADF_C4XXX_IPV4_OFFSET_0_PARSER_BASE << 29) | \ + ADF_C4XXX_IPV4_OFFSET_0_OFFSET) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_0_VALUE 0 + +#define ADF_C4XXX_IPV4_OFFSET_1_PARSER_BASE 0x2 +#define ADF_C4XXX_IPV4_OFFSET_1_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_1_VALUE \ + ((ADF_C4XXX_IPV4_OFFSET_1_PARSER_BASE << 29) | \ + ADF_C4XXX_IPV4_OFFSET_1_OFFSET) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_1_VALUE 3 + +#define ADF_C4XXX_IPV4_OFFSET_2_PARSER_BASE 0x4 +#define ADF_C4XXX_IPV4_OFFSET_2_OFFSET 0x10 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_2_VALUE \ + ((ADF_C4XXX_IPV4_OFFSET_2_PARSER_BASE << 29) | \ + ADF_C4XXX_IPV4_OFFSET_2_OFFSET) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_2_VALUE 3 + +#define ADF_C4XXX_IPV4_OFFSET_3_PARSER_BASE 0x0 +#define ADF_C4XXX_IPV4_OFFSET_3_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_OFFS_3_VALUE \ + ((ADF_C4XXX_IPV4_OFFSET_3_PARSER_BASE << 29) | \ + ADF_C4XXX_IPV4_OFFSET_3_OFFSET) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV4_LEN_3_VALUE 0 + +/* IC_PARSE_IPV6 offset and length registers */ +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_0 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB48) +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_1 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB4C) +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_2 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB50) +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_3 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB54) +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_4 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB58) +#define ADF_C4XXX_IC_PARSE_IPV6_OFFSET_5 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB5C) + +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_0 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB60) +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_1 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB64) +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_2 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB68) +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_3 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB6C) +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_4 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB70) +#define ADF_C4XXX_IC_PARSE_IPV6_LENGTH_5 \ + (ADF_C4XXX_INLINE_INGRESS_OFFSET + 0xB74) + +#define ADF_C4XXX_IPV6_OFFSET_0_PARSER_BASE 0x1 +#define ADF_C4XXX_IPV6_OFFSET_0_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_0_VALUE \ + ((ADF_C4XXX_IPV6_OFFSET_0_PARSER_BASE << 29) | \ + (ADF_C4XXX_IPV6_OFFSET_0_OFFSET)) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_0_VALUE 0 + +#define ADF_C4XXX_IPV6_OFFSET_1_PARSER_BASE 0x2 +#define ADF_C4XXX_IPV6_OFFSET_1_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_1_VALUE \ + ((ADF_C4XXX_IPV6_OFFSET_1_PARSER_BASE << 29) | \ + (ADF_C4XXX_IPV6_OFFSET_1_OFFSET)) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_1_VALUE 3 + +#define ADF_C4XXX_IPV6_OFFSET_2_PARSER_BASE 0x4 +#define ADF_C4XXX_IPV6_OFFSET_2_OFFSET 0x18 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_2_VALUE \ + ((ADF_C4XXX_IPV6_OFFSET_2_PARSER_BASE << 29) | \ + (ADF_C4XXX_IPV6_OFFSET_2_OFFSET)) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_2_VALUE 0xF + +#define ADF_C4XXX_IPV6_OFFSET_3_PARSER_BASE 0x0 +#define ADF_C4XXX_IPV6_OFFSET_3_OFFSET 0x0 +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_OFFS_3_VALUE \ + ((ADF_C4XXX_IPV6_OFFSET_3_PARSER_BASE << 29) | \ + (ADF_C4XXX_IPV6_OFFSET_3_OFFSET)) +#define ADF_C4XXX_DEFAULT_IC_PARSE_IPV6_LEN_3_VALUE 0x0 + +/* error notification configuration registers */ + +#define ADF_C4XXX_IC_CD_RF_PARITY_ERR_0 0xA00 +#define ADF_C4XXX_IC_CD_RF_PARITY_ERR_1 0xA04 +#define ADF_C4XXX_IC_CD_RF_PARITY_ERR_2 0xA08 +#define ADF_C4XXX_IC_CD_RF_PARITY_ERR_3 0xA0C +#define ADF_C4XXX_IC_CD_CERR 0xA10 +#define ADF_C4XXX_IC_CD_UERR 0xA14 + +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_0 0xF00 +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_1 0xF04 +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_2 0xF08 +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_3 0xF0C +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_4 0xF10 +#define ADF_C4XXX_IC_INLN_RF_PARITY_ERR_5 0xF14 +#define ADF_C4XXX_IC_PARSER_CERR 0xF18 +#define ADF_C4XXX_IC_PARSER_UERR 0xF1C +#define ADF_C4XXX_IC_CTPB_CERR 0xF28 +#define ADF_C4XXX_IC_CTPB_UERR 0xF2C +#define ADF_C4XXX_IC_CPPM_ERR_STAT 0xF3C +#define ADF_C4XXX_IC_CONGESTION_MGMT_INT 0xF58 + +#define ADF_C4XXX_IC_CPPT_ERR_STAT 0x704 +#define ADF_C4XXX_IC_MAC_IM 0x10 + +#define ADF_C4XXX_CD_RF_PARITY_ERR_0_VAL 0x22222222 +#define ADF_C4XXX_CD_RF_PARITY_ERR_1_VAL 0x22222323 +#define ADF_C4XXX_CD_RF_PARITY_ERR_2_VAL 0x00022222 +#define ADF_C4XXX_CD_RF_PARITY_ERR_3_VAL 0x00000000 +#define ADF_C4XXX_CD_UERR_VAL 0x00000008 +#define ADF_C4XXX_CD_CERR_VAL 0x00000008 +#define ADF_C4XXX_PARSER_UERR_VAL 0x00100008 +#define ADF_C4XXX_PARSER_CERR_VAL 0x00000008 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_0_VAL 0x33333333 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_1_VAL 0x33333333 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_2_VAL 0x33333333 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_3_VAL 0x22222222 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_4_VAL 0x22222222 +#define ADF_C4XXX_INLN_RF_PARITY_ERR_5_VAL 0x00333232 +#define ADF_C4XXX_CTPB_UERR_VAL 0x00000008 +#define ADF_C4XXX_CTPB_CERR_VAL 0x00000008 +#define ADF_C4XXX_CPPM_ERR_STAT_VAL 0x00007000 +#define ADF_C4XXX_CPPT_ERR_STAT_VAL 0x000001C0 +#define ADF_C4XXX_CONGESTION_MGMT_INI_VAL 0x00000001 +#define ADF_C4XXX_MAC_IM_VAL 0x000000087FDC003E + +/* parser ram ecc uerr */ +#define ADF_C4XXX_PARSER_UERR_INTR BIT(0) +/* multiple err */ +#define ADF_C4XXX_PARSER_MUL_UERR_INTR BIT(18) +#define ADF_C4XXX_PARSER_DESC_UERR_INTR_ENA BIT(20) + +#define ADF_C4XXX_RF_PAR_ERR_BITS 32 +#define ADF_C4XXX_MAX_STR_LEN 64 +#define RF_PAR_MUL_MAP(bit_num) (((bit_num)-2) / 4) +#define RF_PAR_MAP(bit_num) (((bit_num)-3) / 4) + +/* cd rf parity error + * BIT(2) rf parity mul 0 + * BIT(3) rf parity 0 + * BIT(10) rf parity mul 2 + * BIT(11) rf parity 2 + */ +#define ADF_C4XXX_CD_RF_PAR_ERR_1_INTR (BIT(2) | BIT(3) | BIT(10) | BIT(11)) + +/* inln rf parity error + * BIT(2) rf parity mul 0 + * BIT(3) rf parity 0 + * BIT(6) rf parity mul 1 + * BIT(7) rf parity 1 + * BIT(10) rf parity mul 2 + * BIT(11) rf parity 2 + * BIT(14) rf parity mul 3 + * BIT(15) rf parity 3 + * BIT(18) rf parity mul 4 + * BIT(19) rf parity 4 + * BIT(22) rf parity mul 5 + * BIT(23) rf parity 5 + * BIT(26) rf parity mul 6 + * BIT(27) rf parity 6 + * BIT(30) rf parity mul 7 + * BIT(31) rf parity 7 + */ +#define ADF_C4XXX_INLN_RF_PAR_ERR_0_INTR \ + (BIT(2) | BIT(3) | BIT(6) | BIT(7) | BIT(10) | BIT(11) | BIT(14) | \ + BIT(15) | BIT(18) | BIT(19) | BIT(22) | BIT(23) | BIT(26) | BIT(27) | \ + BIT(30) | BIT(31)) +#define ADF_C4XXX_INLN_RF_PAR_ERR_1_INTR ADF_C4XXX_INLN_RF_PAR_ERR_0_INTR +#define ADF_C4XXX_INLN_RF_PAR_ERR_2_INTR ADF_C4XXX_INLN_RF_PAR_ERR_0_INTR +#define ADF_C4XXX_INLN_RF_PAR_ERR_5_INTR \ + (BIT(6) | BIT(7) | BIT(14) | BIT(15) | BIT(18) | BIT(19) | BIT(22) | \ + BIT(23)) + +/* Congestion mgmt events */ +#define ADF_C4XXX_CONGESTION_MGMT_CTPB_GLOBAL_CROSSED BIT(1) +#define ADF_C4XXX_CONGESTION_MGMT_XOFF_CIRQ_OUT BIT(2) +#define ADF_C4XXX_CONGESTION_MGMT_XOFF_CIRQ_IN BIT(3) + +/* AEAD algorithm definitions in REG_SA_SCRATCH[0] register. + * Bits<6:5> are reserved for expansion. + */ +#define AES128_GCM BIT(0) +#define AES192_GCM BIT(1) +#define AES256_GCM BIT(2) +#define AES128_CCM BIT(3) +#define CHACHA20_POLY1305 BIT(4) +/* Cipher algorithm definitions in REG_SA_SCRATCH[0] register + * Bit<15> is reserved for expansion. + */ +#define CIPHER_NULL BIT(7) +#define AES128_CBC BIT(8) +#define AES192_CBC BIT(9) +#define AES256_CBC BIT(10) +#define AES128_CTR BIT(11) +#define AES192_CTR BIT(12) +#define AES256_CTR BIT(13) +#define _3DES_CBC BIT(14) +/* Authentication algorithm definitions in REG_SA_SCRATCH[0] register + * Bits<25:30> are reserved for expansion. + */ +#define HMAC_MD5_96 BIT(16) +#define HMAC_SHA1_96 BIT(17) +#define HMAC_SHA256_128 BIT(18) +#define HMAC_SHA384_192 BIT(19) +#define HMAC_SHA512_256 BIT(20) +#define AES_GMAC_AES_128 BIT(21) +#define AES_XCBC_MAC_96 BIT(22) +#define AES_CMAC_96 BIT(23) +#define AUTH_NULL BIT(24) + +/* Algo group0:DEFAULT */ +#define ADF_C4XXX_DEFAULT_SUPPORTED_ALGORITHMS \ + (AES128_GCM | \ + (AES192_GCM | AES256_GCM | AES128_CCM | CHACHA20_POLY1305) | \ + (CIPHER_NULL | AES128_CBC | AES192_CBC | AES256_CBC) | \ + (AES128_CTR | AES192_CTR | AES256_CTR | _3DES_CBC) | \ + (HMAC_MD5_96 | HMAC_SHA1_96 | HMAC_SHA256_128) | \ + (HMAC_SHA384_192 | HMAC_SHA512_256 | AES_GMAC_AES_128) | \ + (AES_XCBC_MAC_96 | AES_CMAC_96 | AUTH_NULL)) + +/* Algo group1 */ +#define ADF_C4XXX_SUPPORTED_ALGORITHMS_GROUP1 \ + (AES128_GCM | (AES256_GCM | CHACHA20_POLY1305)) + +/* Supported crypto offload features in REG_SA_SCRATCH[2] register */ +#define ADF_C4XXX_IPSEC_ESP BIT(0) +#define ADF_C4XXX_IPSEC_AH BIT(1) +#define ADF_C4XXX_UDP_ENCAPSULATION BIT(2) +#define ADF_C4XXX_IPSEC_TUNNEL_MODE BIT(3) +#define ADF_C4XXX_IPSEC_TRANSPORT_MODE BIT(4) +#define ADF_C4XXX_IPSEC_EXT_SEQ_NUM BIT(5) + +#define ADF_C4XXX_DEFAULT_CY_OFFLOAD_FEATURES \ + (ADF_C4XXX_IPSEC_ESP | \ + (ADF_C4XXX_UDP_ENCAPSULATION | ADF_C4XXX_IPSEC_TUNNEL_MODE) | \ + (ADF_C4XXX_IPSEC_TRANSPORT_MODE | ADF_C4XXX_IPSEC_EXT_SEQ_NUM)) + +/* REG_SA_CTRL_LOCK default value */ +#define ADF_C4XXX_DEFAULT_SA_CTRL_LOCKOUT BIT(0) + +/* SA ENTRY CTRL default values */ +#define ADF_C4XXX_DEFAULT_LU_KEY_LEN 21 + +/* Sa size for algo group0 */ +#define ADF_C4XXX_DEFAULT_SA_SIZE 6 + +/* Sa size for algo group1 */ +#define ADF_C4XXX_ALGO_GROUP1_SA_SIZE 2 + +/* SA size is based on 32byte granularity + * A value of zero indicates an SA size of 32 bytes + */ +#define ADF_C4XXX_SA_SIZE_IN_BYTES(sa_size) (((sa_size) + 1) * 32) + +/* SA ENTRY CTRL register bit offsets */ +#define ADF_C4XXX_LU_KEY_LEN_BIT_OFFSET 5 + +/* REG_SA_FUNC_LIMITS default value */ +#define ADF_C4XXX_FUNC_LIMIT(accel_dev, sa_size) \ + (ADF_C4XXX_SADB_SIZE_IN_WORDS(accel_dev) / ((sa_size) + 1)) + +/* REG_SA_INLINE_ENABLE bit definition */ +#define ADF_C4XXX_INLINE_ENABLED BIT(0) + +/* REG_SA_INLINE_CAPABILITY bit definitions */ +#define ADF_C4XXX_INLINE_INGRESS_ENABLE BIT(0) +#define ADF_C4XXX_INLINE_EGRESS_ENABLE BIT(1) +#define ADF_C4XXX_INLINE_CAPABILITIES \ + (ADF_C4XXX_INLINE_INGRESS_ENABLE | ADF_C4XXX_INLINE_EGRESS_ENABLE) + +/* Congestion management profile information */ +enum congest_mngt_profile_info { + CIRQ_CFG_1 = 0, + CIRQ_CFG_2, + CIRQ_CFG_3, + BEST_EFFORT_SINGLE_QUEUE, + BEST_EFFORT_8_QUEUES, +}; + +/* IPsec Algo Group */ +enum ipsec_algo_group_info { + IPSEC_DEFAUL_ALGO_GROUP = 0, + IPSEC_ALGO_GROUP1, + IPSEC_ALGO_GROUP_DELIMITER +}; + +int get_congestion_management_profile(struct adf_accel_dev *accel_dev, + u8 *profile); +int c4xxx_init_congestion_management(struct adf_accel_dev *accel_dev); +int c4xxx_init_debugfs_inline_dir(struct adf_accel_dev *accel_dev); +void c4xxx_exit_debugfs_inline_dir(struct adf_accel_dev *accel_dev); +#endif /* ADF_C4XXX_INLINE_H_ */ diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.c new file mode 100644 index 00000000000..444c8753abd --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_c4xxx_hw_data.h" +#include "adf_c4xxx_misc_error_stats.h" +#include "adf_common_drv.h" +#include "adf_cfg_common.h" +#include +#include + +#define MISC_ERROR_DBG_FILE "misc_error_stats" +#define LINE \ + "+-----------------------------------------------------------------+\n" +#define BANNER \ + "| Miscellaneous Error Statistics for Qat Device |\n" + +static void *misc_counter; + +struct adf_dev_miscellaneous_stats { + u64 misc_counter; +}; + +static int qat_misc_error_show(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + + sbuf_new_for_sysctl(&sb, NULL, 256, req); + sbuf_printf(&sb, "\n"); + sbuf_printf(&sb, LINE); + sbuf_printf(&sb, + "| Miscellaneous Error: %40llu |\n", + (unsigned long long)((struct adf_dev_miscellaneous_stats *) + misc_counter) + ->misc_counter); + + sbuf_finish(&sb); + SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); + sbuf_delete(&sb); + + return 0; +} + +/** + * adf_misc_error_add_c4xxx() - Create debugfs entry for + * acceleration device Freq counters. + * @accel_dev: Pointer to acceleration device. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_misc_error_add_c4xxx(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx = NULL; + struct sysctl_oid *qat_sysctl_tree = NULL; + struct sysctl_oid *misc_er_file = NULL; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + misc_er_file = SYSCTL_ADD_PROC(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + MISC_ERROR_DBG_FILE, + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + qat_misc_error_show, + "A", + "QAT Miscellaneous Error Statistics"); + accel_dev->misc_error_dbgfile = misc_er_file; + if (!accel_dev->misc_error_dbgfile) { + device_printf( + GET_DEV(accel_dev), + "Failed to create qat miscellaneous error debugfs entry.\n"); + return ENOENT; + } + + misc_counter = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!misc_counter) + return ENOMEM; + + memset(misc_counter, 0, PAGE_SIZE); + + return 0; +} + +/** + * adf_misc_error_remove_c4xxx() - Remove debugfs entry for + * acceleration device misc error counter. + * @accel_dev: Pointer to acceleration device. + * + * Return: void + */ +void +adf_misc_error_remove_c4xxx(struct adf_accel_dev *accel_dev) +{ + if (accel_dev->misc_error_dbgfile) { + remove_oid(accel_dev, accel_dev->misc_error_dbgfile); + accel_dev->misc_error_dbgfile = NULL; + } + + kfree(misc_counter); + misc_counter = NULL; +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.h new file mode 100644 index 00000000000..e52c0c815ef --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_misc_error_stats.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C4XXX_MISC_ERROR_STATS_H_ +#define ADF_C4XXX_MISC_ERROR_STATS_H_ + +#include "adf_accel_devices.h" + +int adf_misc_error_add_c4xxx(struct adf_accel_dev *accel_dev); +void adf_misc_error_remove_c4xxx(struct adf_accel_dev *accel_dev); + +#endif diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.c new file mode 100644 index 00000000000..96cead96acc --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_c4xxx_hw_data.h" +#include "adf_c4xxx_pke_replay_stats.h" +#include "adf_common_drv.h" +#include "icp_qat_fw_init_admin.h" +#include +#include + +#define PKE_REPLAY_DBG_FILE "pke_replay_stats" +#define LINE \ + "+-----------------------------------------------------------------+\n" +#define BANNER \ + "| PKE Replay Statistics for Qat Device |\n" + +static int qat_pke_replay_counters_show(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + struct adf_accel_dev *accel_dev = arg1; + int ret = 0; + u64 suc_counter = 0; + u64 unsuc_counter = 0; + + sbuf_new_for_sysctl(&sb, NULL, 256, req); + + sbuf_printf(&sb, "\n"); + sbuf_printf(&sb, LINE); + + ret = adf_get_fw_pke_stats(accel_dev, &suc_counter, &unsuc_counter); + if (ret) + return ret; + + sbuf_printf( + &sb, + "| Successful Replays: %40llu |\n| Unsuccessful Replays: %40llu |\n", + (unsigned long long)suc_counter, + (unsigned long long)unsuc_counter); + + sbuf_finish(&sb); + SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); + sbuf_delete(&sb); + + return 0; +} + +/** + * adf_pke_replay_counters_add_c4xxx() - Create debugfs entry for + * acceleration device Freq counters. + * @accel_dev: Pointer to acceleration device. + * + * Return: 0 on success, error code otherwise. + */ +int +adf_pke_replay_counters_add_c4xxx(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx = NULL; + struct sysctl_oid *qat_sysctl_tree = NULL; + struct sysctl_oid *pke_rep_file = NULL; + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + + pke_rep_file = SYSCTL_ADD_PROC(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + PKE_REPLAY_DBG_FILE, + CTLTYPE_STRING | CTLFLAG_RD, + accel_dev, + 0, + qat_pke_replay_counters_show, + "A", + "QAT PKE Replay Statistics"); + accel_dev->pke_replay_dbgfile = pke_rep_file; + if (!accel_dev->pke_replay_dbgfile) { + device_printf( + GET_DEV(accel_dev), + "Failed to create qat pke replay debugfs entry.\n"); + return ENOENT; + } + return 0; +} + +/** + * adf_pke_replay_counters_remove_c4xxx() - Remove debugfs entry for + * acceleration device Freq counters. + * @accel_dev: Pointer to acceleration device. + * + * Return: void + */ +void +adf_pke_replay_counters_remove_c4xxx(struct adf_accel_dev *accel_dev) +{ + if (accel_dev->pke_replay_dbgfile) { + remove_oid(accel_dev, accel_dev->pke_replay_dbgfile); + accel_dev->pke_replay_dbgfile = NULL; + } +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.h new file mode 100644 index 00000000000..5fe4e747d87 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_pke_replay_stats.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C4XXX_PKE_REPLAY_STATS_H_ +#define ADF_C4XXX_PKE_REPLAY_STATS_H_ + +#include "adf_accel_devices.h" + +int adf_pke_replay_counters_add_c4xxx(struct adf_accel_dev *accel_dev); +void adf_pke_replay_counters_remove_c4xxx(struct adf_accel_dev *accel_dev); + +#endif diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.c new file mode 100644 index 00000000000..c6864100390 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.c @@ -0,0 +1,1345 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_c4xxx_ras.h" +#include "adf_accel_devices.h" +#include "adf_c4xxx_hw_data.h" +#include +#include "adf_c4xxx_inline.h" + +#define ADF_RAS_STR_LEN 64 + +static int adf_sysctl_read_ras_correctable(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + unsigned long counter = 0; + + if (accel_dev->ras_counters) + counter = atomic_read(&accel_dev->ras_counters[ADF_RAS_CORR]); + + return SYSCTL_OUT(req, &counter, sizeof(counter)); +} + +static int adf_sysctl_read_ras_uncorrectable(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + unsigned long counter = 0; + + if (accel_dev->ras_counters) + counter = atomic_read(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + + return SYSCTL_OUT(req, &counter, sizeof(counter)); +} + +static int adf_sysctl_read_ras_fatal(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + unsigned long counter = 0; + + if (accel_dev->ras_counters) + counter = atomic_read(&accel_dev->ras_counters[ADF_RAS_FATAL]); + + return SYSCTL_OUT(req, &counter, sizeof(counter)); +} + +static int adf_sysctl_write_ras_reset(SYSCTL_HANDLER_ARGS) +{ + struct adf_accel_dev *accel_dev = arg1; + int value = 0; + int ret = SYSCTL_IN(req, &value, sizeof(value)); + + if (!ret && value != 0 && accel_dev->ras_counters) { + } + + return SYSCTL_OUT(req, &value, sizeof(value)); +} + +int +adf_init_ras(struct adf_accel_dev *accel_dev) +{ + struct sysctl_ctx_list *qat_sysctl_ctx; + struct sysctl_oid *qat_sysctl_tree; + struct sysctl_oid *ras_corr; + struct sysctl_oid *ras_uncor; + struct sysctl_oid *ras_fat; + struct sysctl_oid *ras_res; + int i; + + accel_dev->ras_counters = kcalloc(ADF_RAS_ERRORS, + sizeof(*accel_dev->ras_counters), + GFP_KERNEL); + if (!accel_dev->ras_counters) + return -ENOMEM; + + for (i = 0; i < ADF_RAS_ERRORS; ++i) + + qat_sysctl_ctx = + device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); + qat_sysctl_tree = + device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); + ras_corr = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "ras_correctable", + CTLTYPE_ULONG | CTLFLAG_RD | CTLFLAG_DYN, + accel_dev, + 0, + adf_sysctl_read_ras_correctable, + "LU", + "QAT RAS correctable"); + accel_dev->ras_correctable = ras_corr; + if (!accel_dev->ras_correctable) { + device_printf(GET_DEV(accel_dev), + "Failed to register ras_correctable sysctl\n"); + return -EINVAL; + } + ras_uncor = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "ras_uncorrectable", + CTLTYPE_ULONG | CTLFLAG_RD | CTLFLAG_DYN, + accel_dev, + 0, + adf_sysctl_read_ras_uncorrectable, + "LU", + "QAT RAS uncorrectable"); + accel_dev->ras_uncorrectable = ras_uncor; + if (!accel_dev->ras_uncorrectable) { + device_printf(GET_DEV(accel_dev), + "Failed to register ras_uncorrectable sysctl\n"); + return -EINVAL; + } + + ras_fat = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "ras_fatal", + CTLTYPE_ULONG | CTLFLAG_RD | CTLFLAG_DYN, + accel_dev, + 0, + adf_sysctl_read_ras_fatal, + "LU", + "QAT RAS fatal"); + accel_dev->ras_fatal = ras_fat; + if (!accel_dev->ras_fatal) { + device_printf(GET_DEV(accel_dev), + "Failed to register ras_fatal sysctl\n"); + return -EINVAL; + } + + ras_res = SYSCTL_ADD_OID(qat_sysctl_ctx, + SYSCTL_CHILDREN(qat_sysctl_tree), + OID_AUTO, + "ras_reset", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_DYN, + accel_dev, + 0, + adf_sysctl_write_ras_reset, + "I", + "QAT RAS reset"); + accel_dev->ras_reset = ras_res; + if (!accel_dev->ras_reset) { + device_printf(GET_DEV(accel_dev), + "Failed to register ras_reset sysctl\n"); + return -EINVAL; + } + + return 0; +} + +void +adf_exit_ras(struct adf_accel_dev *accel_dev) +{ + if (accel_dev->ras_counters) { + remove_oid(accel_dev, accel_dev->ras_correctable); + remove_oid(accel_dev, accel_dev->ras_uncorrectable); + remove_oid(accel_dev, accel_dev->ras_fatal); + remove_oid(accel_dev, accel_dev->ras_reset); + + accel_dev->ras_correctable = NULL; + accel_dev->ras_uncorrectable = NULL; + accel_dev->ras_fatal = NULL; + accel_dev->ras_reset = NULL; + + kfree(accel_dev->ras_counters); + accel_dev->ras_counters = NULL; + } +} + +static inline void +adf_log_source_iastatssm(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 iastatssm, + u32 accel_num) +{ + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMSH_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error shared memory detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMSH_MASK) + device_printf( + GET_DEV(accel_dev), + "Correctable error shared memory detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP0_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error MMP0 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP0_MASK) + device_printf(GET_DEV(accel_dev), + "Correctable error MMP0 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP1_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error MMP1 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP1_MASK) + device_printf(GET_DEV(accel_dev), + "Correctable error MMP1 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP2_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error MMP2 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP2_MASK) + device_printf(GET_DEV(accel_dev), + "Correctable error MMP2 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP3_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error MMP3 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP3_MASK) + device_printf(GET_DEV(accel_dev), + "Correctable error MMP3 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP4_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error MMP4 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP4_MASK) + device_printf(GET_DEV(accel_dev), + "Correctable error MMP4 detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_PPERR_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable error Push or Pull detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_CPPPAR_ERR_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable CPP parity error detected in accel: %u\n", + accel_num); + + if (iastatssm & ADF_C4XXX_IASTATSSM_RFPAR_ERR_MASK) + device_printf( + GET_DEV(accel_dev), + "Uncorrectable SSM RF parity error detected in accel: %u\n", + accel_num); +} + +static inline void +adf_clear_source_statssm(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 statssm, + u32 accel_num) +{ + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMSH_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMSH(accel_num), + ADF_C4XXX_UERRSSMSH_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMSH_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMSH(accel_num), + ADF_C4XXX_CERRSSMSH_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP0_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMMMP(accel_num, 0), + ~ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP0_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMMMP(accel_num, 0), + ~ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP1_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMMMP(accel_num, 1), + ~ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP1_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMMMP(accel_num, 1), + ~ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP2_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMMMP(accel_num, 2), + ~ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP2_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMMMP(accel_num, 2), + ~ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP3_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMMMP(accel_num, 3), + ~ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP3_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMMMP(accel_num, 3), + ~ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_UERRSSMMMP4_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_UERRSSMMMP(accel_num, 4), + ~ADF_C4XXX_UERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_CERRSSMMMP4_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_CERRSSMMMP(accel_num, 4), + ~ADF_C4XXX_CERRSSMMMP_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_PPERR_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_PPERR(accel_num), + ~ADF_C4XXX_PPERR_INTS_CLEAR_MASK); + + if (statssm & ADF_C4XXX_IASTATSSM_RFPAR_ERR_MASK) + adf_csr_fetch_and_or(pmisc, + ADF_C4XXX_SSMSOFTERRORPARITY(accel_num), + 0UL); + + if (statssm & ADF_C4XXX_IASTATSSM_CPPPAR_ERR_MASK) + adf_csr_fetch_and_or(pmisc, + ADF_C4XXX_SSMCPPERR(accel_num), + 0UL); +} + +static inline void +adf_process_errsou8(struct adf_accel_dev *accel_dev, struct resource *pmisc) +{ + int i; + u32 mecorrerr = ADF_CSR_RD(pmisc, ADF_C4XXX_HI_ME_COR_ERRLOG); + const unsigned long tmp_mecorrerr = mecorrerr; + + /* For each correctable error in ME increment RAS counter */ + for_each_set_bit(i, + &tmp_mecorrerr, + ADF_C4XXX_HI_ME_COR_ERRLOG_SIZE_IN_BITS) + { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + device_printf(GET_DEV(accel_dev), + "Correctable error detected in AE%d\n", + i); + } + + /* Clear interrupt from errsou8 (RW1C) */ + ADF_CSR_WR(pmisc, ADF_C4XXX_HI_ME_COR_ERRLOG, mecorrerr); +} + +static inline void +adf_handle_ae_uncorr_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + int i; + u32 me_uncorr_err = ADF_CSR_RD(pmisc, ADF_C4XXX_HI_ME_UNCERR_LOG); + const unsigned long tmp_me_uncorr_err = me_uncorr_err; + + /* For each uncorrectable fatal error in AE increment RAS error + * counter. + */ + for_each_set_bit(i, + &tmp_me_uncorr_err, + ADF_C4XXX_HI_ME_UNCOR_ERRLOG_BITS) + { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_FATAL]); + device_printf(GET_DEV(accel_dev), + "Uncorrectable error detected in AE%d\n", + i); + } + + /* Clear interrupt from me_uncorr_err (RW1C) */ + ADF_CSR_WR(pmisc, ADF_C4XXX_HI_ME_UNCERR_LOG, me_uncorr_err); +} + +static inline void +adf_handle_ri_mem_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + bool *reset_required) +{ + u32 ri_mem_par_err_sts = 0; + u32 ri_mem_par_err_ferr = 0; + + ri_mem_par_err_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_RI_MEM_PAR_ERR_STS); + + ri_mem_par_err_ferr = ADF_CSR_RD(pmisc, ADF_C4XXX_RI_MEM_PAR_ERR_FERR); + + if (ri_mem_par_err_sts & ADF_C4XXX_RI_MEM_PAR_ERR_STS_MASK) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "Uncorrectable RI memory parity error detected.\n"); + } + + if (ri_mem_par_err_sts & ADF_C4XXX_RI_MEM_MSIX_TBL_INT_MASK) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_FATAL]); + device_printf( + GET_DEV(accel_dev), + "Uncorrectable fatal MSIX table parity error detected.\n"); + *reset_required = true; + } + + device_printf(GET_DEV(accel_dev), + "ri_mem_par_err_sts=0x%X\tri_mem_par_err_ferr=%u\n", + ri_mem_par_err_sts, + ri_mem_par_err_ferr); + + ADF_CSR_WR(pmisc, ADF_C4XXX_RI_MEM_PAR_ERR_STS, ri_mem_par_err_sts); +} + +static inline void +adf_handle_ti_mem_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 ti_mem_par_err_sts0 = 0; + u32 ti_mem_par_err_sts1 = 0; + u32 ti_mem_par_err_ferr = 0; + + ti_mem_par_err_sts0 = ADF_CSR_RD(pmisc, ADF_C4XXX_TI_MEM_PAR_ERR_STS0); + ti_mem_par_err_sts1 = ADF_CSR_RD(pmisc, ADF_C4XXX_TI_MEM_PAR_ERR_STS1); + ti_mem_par_err_ferr = + ADF_CSR_RD(pmisc, ADF_C4XXX_TI_MEM_PAR_ERR_FIRST_ERROR); + + atomic_inc(&accel_dev->ras_counters[ADF_RAS_FATAL]); + ti_mem_par_err_sts1 &= ADF_C4XXX_TI_MEM_PAR_ERR_STS1_MASK; + + device_printf(GET_DEV(accel_dev), + "Uncorrectable TI memory parity error detected.\n"); + device_printf(GET_DEV(accel_dev), + "ti_mem_par_err_sts0=0x%X\tti_mem_par_err_sts1=0x%X\t" + "ti_mem_par_err_ferr=0x%X\n", + ti_mem_par_err_sts0, + ti_mem_par_err_sts1, + ti_mem_par_err_ferr); + + ADF_CSR_WR(pmisc, ADF_C4XXX_TI_MEM_PAR_ERR_STS0, ti_mem_par_err_sts0); + ADF_CSR_WR(pmisc, ADF_C4XXX_TI_MEM_PAR_ERR_STS1, ti_mem_par_err_sts1); +} + +static inline void +adf_log_fatal_cmd_par_err(struct adf_accel_dev *accel_dev, char *err_type) +{ + atomic_inc(&accel_dev->ras_counters[ADF_RAS_FATAL]); + device_printf(GET_DEV(accel_dev), + "Fatal error detected: %s command parity\n", + err_type); +} + +static inline void +adf_handle_host_cpp_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 host_cpp_par_err = 0; + + host_cpp_par_err = + ADF_CSR_RD(pmisc, ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG); + + if (host_cpp_par_err & ADF_C4XXX_TI_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "TI"); + + if (host_cpp_par_err & ADF_C4XXX_RI_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "RI"); + + if (host_cpp_par_err & ADF_C4XXX_ICI_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "ICI"); + + if (host_cpp_par_err & ADF_C4XXX_ICE_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "ICE"); + + if (host_cpp_par_err & ADF_C4XXX_ARAM_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "ARAM"); + + if (host_cpp_par_err & ADF_C4XXX_CFC_CMD_PAR_ERR) + adf_log_fatal_cmd_par_err(accel_dev, "CFC"); + + if (ADF_C4XXX_SSM_CMD_PAR_ERR(host_cpp_par_err)) + adf_log_fatal_cmd_par_err(accel_dev, "SSM"); + + /* Clear interrupt from host_cpp_par_err (RW1C) */ + ADF_CSR_WR(pmisc, + ADF_C4XXX_HI_CPP_AGENT_CMD_PAR_ERR_LOG, + host_cpp_par_err); +} + +static inline void +adf_process_errsou9(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 errsou, + bool *reset_required) +{ + if (errsou & ADF_C4XXX_ME_UNCORR_ERROR) { + adf_handle_ae_uncorr_err(accel_dev, pmisc); + + /* Notify caller that function level reset is required. */ + *reset_required = true; + } + + if (errsou & ADF_C4XXX_CPP_CMD_PAR_ERR) { + adf_handle_host_cpp_par_err(accel_dev, pmisc); + *reset_required = true; + } + + /* RI memory parity errors are uncorrectable non-fatal errors + * with exception of bit 22 MSIX table parity error, which should + * be treated as fatal error, followed by device restart. + */ + if (errsou & ADF_C4XXX_RI_MEM_PAR_ERR) + adf_handle_ri_mem_par_err(accel_dev, pmisc, reset_required); + + if (errsou & ADF_C4XXX_TI_MEM_PAR_ERR) { + adf_handle_ti_mem_par_err(accel_dev, pmisc); + *reset_required = true; + } +} + +static inline void +adf_process_exprpssmcpr(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 accel) +{ + u32 exprpssmcpr; + + /* CPR0 */ + exprpssmcpr = ADF_CSR_RD(pmisc, ADF_C4XXX_EXPRPSSMCPR0(accel)); + if (exprpssmcpr & ADF_C4XXX_EXPRPSSM_FATAL_MASK) { + device_printf(GET_DEV(accel_dev), + "Uncorrectable error CPR0 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + if (exprpssmcpr & ADF_C4XXX_EXPRPSSM_SOFT_MASK) { + device_printf(GET_DEV(accel_dev), + "Correctable error CPR0 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + } + ADF_CSR_WR(pmisc, ADF_C4XXX_EXPRPSSMCPR0(accel), 0); + + /* CPR1 */ + exprpssmcpr = ADF_CSR_RD(pmisc, ADF_C4XXX_EXPRPSSMCPR1(accel)); + if (exprpssmcpr & ADF_C4XXX_EXPRPSSM_FATAL_MASK) { + device_printf(GET_DEV(accel_dev), + "Uncorrectable error CPR1 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + if (exprpssmcpr & ADF_C4XXX_EXPRPSSM_SOFT_MASK) { + device_printf(GET_DEV(accel_dev), + "Correctable error CPR1 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + } + ADF_CSR_WR(pmisc, ADF_C4XXX_EXPRPSSMCPR1(accel), 0); +} + +static inline void +adf_process_exprpssmxlt(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 accel) +{ + u32 exprpssmxlt; + + /* XTL0 */ + exprpssmxlt = ADF_CSR_RD(pmisc, ADF_C4XXX_EXPRPSSMXLT0(accel)); + if (exprpssmxlt & ADF_C4XXX_EXPRPSSM_FATAL_MASK) { + device_printf(GET_DEV(accel_dev), + "Uncorrectable error XLT0 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + if (exprpssmxlt & ADF_C4XXX_EXPRPSSM_SOFT_MASK) { + device_printf(GET_DEV(accel_dev), + "Correctable error XLT0 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + } + ADF_CSR_WR(pmisc, ADF_C4XXX_EXPRPSSMXLT0(accel), 0); + + /* XTL1 */ + exprpssmxlt = ADF_CSR_RD(pmisc, ADF_C4XXX_EXPRPSSMXLT1(accel)); + if (exprpssmxlt & ADF_C4XXX_EXPRPSSM_FATAL_MASK) { + device_printf(GET_DEV(accel_dev), + "Uncorrectable error XLT1 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + } + if (exprpssmxlt & ADF_C4XXX_EXPRPSSM_SOFT_MASK) { + device_printf(GET_DEV(accel_dev), + "Correctable error XLT1 detected in accel %u\n", + accel); + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + } + ADF_CSR_WR(pmisc, ADF_C4XXX_EXPRPSSMXLT0(accel), 0); +} + +static inline void +adf_process_spp_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 accel, + bool *reset_required) +{ + /* All SPP parity errors are treated as uncorrectable fatal errors */ + atomic_inc(&accel_dev->ras_counters[ADF_RAS_FATAL]); + *reset_required = true; + device_printf(GET_DEV(accel_dev), + "Uncorrectable fatal SPP parity error detected\n"); +} + +static inline void +adf_process_statssm(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 accel, + bool *reset_required) +{ + u32 i; + u32 statssm = ADF_CSR_RD(pmisc, ADF_INTSTATSSM(accel)); + u32 iastatssm = ADF_CSR_RD(pmisc, ADF_C4XXX_IAINTSTATSSM(accel)); + bool type; + const unsigned long tmp_iastatssm = iastatssm; + + /* First collect all errors */ + for_each_set_bit(i, &tmp_iastatssm, ADF_C4XXX_IASTATSSM_BITS) + { + if (i == ADF_C4XXX_IASTATSSM_SLICE_HANG_ERR_BIT) { + /* Slice Hang error is being handled in + * separate function adf_check_slice_hang_c4xxx(), + * which also increments RAS counters for + * SliceHang error. + */ + continue; + } + if (i == ADF_C4XXX_IASTATSSM_SPP_PAR_ERR_BIT) { + adf_process_spp_par_err(accel_dev, + pmisc, + accel, + reset_required); + continue; + } + + type = (i % 2) ? ADF_RAS_CORR : ADF_RAS_UNCORR; + if (i == ADF_C4XXX_IASTATSSM_CPP_PAR_ERR_BIT) + type = ADF_RAS_UNCORR; + + atomic_inc(&accel_dev->ras_counters[type]); + } + + /* If iastatssm is set, we need to log the error */ + if (iastatssm & ADF_C4XXX_IASTATSSM_MASK) + adf_log_source_iastatssm(accel_dev, pmisc, iastatssm, accel); + /* If statssm is set, we need to clear the error sources */ + if (statssm & ADF_C4XXX_IASTATSSM_MASK) + adf_clear_source_statssm(accel_dev, pmisc, statssm, accel); + /* Clear the iastatssm after clearing error sources */ + if (iastatssm & ADF_C4XXX_IASTATSSM_MASK) + adf_csr_fetch_and_and(pmisc, + ADF_C4XXX_IAINTSTATSSM(accel), + ADF_C4XXX_IASTATSSM_CLR_MASK); +} + +static inline void +adf_process_errsou10(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 errsou, + u32 num_accels, + bool *reset_required) +{ + int accel; + const unsigned long tmp_errsou = errsou; + + for_each_set_bit(accel, &tmp_errsou, num_accels) + { + adf_process_statssm(accel_dev, pmisc, accel, reset_required); + adf_process_exprpssmcpr(accel_dev, pmisc, accel); + adf_process_exprpssmxlt(accel_dev, pmisc, accel); + } +} + +/* ERRSOU 11 */ +static inline void +adf_handle_ti_misc_err(struct adf_accel_dev *accel_dev, struct resource *pmisc) +{ + u32 ti_misc_sts = 0; + u32 err_type = 0; + + ti_misc_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_TI_MISC_STS); + dev_dbg(GET_DEV(accel_dev), "ti_misc_sts = 0x%X\n", ti_misc_sts); + + if (ti_misc_sts & ADF_C4XXX_TI_MISC_ERR_MASK) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + + /* If TI misc error occurred then check its type */ + err_type = ADF_C4XXX_GET_TI_MISC_ERR_TYPE(ti_misc_sts); + if (err_type == ADF_C4XXX_TI_BME_RESP_ORDER_ERR) { + device_printf( + GET_DEV(accel_dev), + "Uncorrectable non-fatal BME response order error.\n"); + + } else if (err_type == ADF_C4XXX_TI_RESP_ORDER_ERR) { + device_printf( + GET_DEV(accel_dev), + "Uncorrectable non-fatal response order error.\n"); + } + + /* Clear the interrupt and allow the next error to be + * logged. + */ + ADF_CSR_WR(pmisc, ADF_C4XXX_TI_MISC_STS, BIT(0)); + } +} + +static inline void +adf_handle_ri_push_pull_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 ri_cpp_int_sts = 0; + u32 err_clear_mask = 0; + + ri_cpp_int_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_RI_CPP_INT_STS); + dev_dbg(GET_DEV(accel_dev), "ri_cpp_int_sts = 0x%X\n", ri_cpp_int_sts); + + if (ri_cpp_int_sts & ADF_C4XXX_RI_CPP_INT_STS_PUSH_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal RI push error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ri_cpp_int_sts)); + + err_clear_mask |= ADF_C4XXX_RI_CPP_INT_STS_PUSH_ERR; + } + + if (ri_cpp_int_sts & ADF_C4XXX_RI_CPP_INT_STS_PULL_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal RI pull error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ri_cpp_int_sts)); + + err_clear_mask |= ADF_C4XXX_RI_CPP_INT_STS_PULL_ERR; + } + + /* Clear the interrupt for handled errors and allow the next error + * to be logged. + */ + ADF_CSR_WR(pmisc, ADF_C4XXX_RI_CPP_INT_STS, err_clear_mask); +} + +static inline void +adf_handle_ti_push_pull_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 ti_cpp_int_sts = 0; + u32 err_clear_mask = 0; + + ti_cpp_int_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_TI_CPP_INT_STS); + dev_dbg(GET_DEV(accel_dev), "ti_cpp_int_sts = 0x%X\n", ti_cpp_int_sts); + + if (ti_cpp_int_sts & ADF_C4XXX_TI_CPP_INT_STS_PUSH_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal TI push error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ti_cpp_int_sts)); + + err_clear_mask |= ADF_C4XXX_TI_CPP_INT_STS_PUSH_ERR; + } + + if (ti_cpp_int_sts & ADF_C4XXX_TI_CPP_INT_STS_PULL_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal TI pull error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ti_cpp_int_sts)); + + err_clear_mask |= ADF_C4XXX_TI_CPP_INT_STS_PULL_ERR; + } + + /* Clear the interrupt for handled errors and allow the next error + * to be logged. + */ + ADF_CSR_WR(pmisc, ADF_C4XXX_TI_CPP_INT_STS, err_clear_mask); +} + +static inline void +adf_handle_aram_corr_err(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr) +{ + u32 aram_cerr = 0; + + aram_cerr = ADF_CSR_RD(aram_base_addr, ADF_C4XXX_ARAMCERR); + dev_dbg(GET_DEV(accel_dev), "aram_cerr = 0x%X\n", aram_cerr); + + if (aram_cerr & ADF_C4XXX_ARAM_CORR_ERR_MASK) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_CORR]); + device_printf(GET_DEV(accel_dev), + "Correctable ARAM error detected.\n"); + } + + /* Clear correctable ARAM error interrupt. */ + ADF_C4XXX_CLEAR_CSR_BIT(aram_cerr, 0); + ADF_CSR_WR(aram_base_addr, ADF_C4XXX_ARAMCERR, aram_cerr); +} + +static inline void +adf_handle_aram_uncorr_err(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr) +{ + u32 aram_uerr = 0; + + aram_uerr = ADF_CSR_RD(aram_base_addr, ADF_C4XXX_ARAMUERR); + dev_dbg(GET_DEV(accel_dev), "aram_uerr = 0x%X\n", aram_uerr); + + if (aram_uerr & ADF_C4XXX_ARAM_UNCORR_ERR_MASK) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf(GET_DEV(accel_dev), + "Uncorrectable non-fatal ARAM error detected.\n"); + } + + /* Clear uncorrectable ARAM error interrupt. */ + ADF_C4XXX_CLEAR_CSR_BIT(aram_uerr, 0); + ADF_CSR_WR(aram_base_addr, ADF_C4XXX_ARAMUERR, aram_uerr); +} + +static inline void +adf_handle_ti_pull_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 ti_cpp_int_sts = 0; + + ti_cpp_int_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_TI_CPP_INT_STS); + dev_dbg(GET_DEV(accel_dev), "ti_cpp_int_sts = 0x%X\n", ti_cpp_int_sts); + + if (ti_cpp_int_sts & ADF_C4XXX_TI_CPP_INT_STS_PUSH_DATA_PAR_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal TI pull data parity error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ti_cpp_int_sts)); + } + + /* Clear the interrupt and allow the next error to be logged. */ + ADF_CSR_WR(pmisc, + ADF_C4XXX_TI_CPP_INT_STS, + ADF_C4XXX_TI_CPP_INT_STS_PUSH_DATA_PAR_ERR); +} + +static inline void +adf_handle_ri_push_par_err(struct adf_accel_dev *accel_dev, + struct resource *pmisc) +{ + u32 ri_cpp_int_sts = 0; + + ri_cpp_int_sts = ADF_CSR_RD(pmisc, ADF_C4XXX_RI_CPP_INT_STS); + dev_dbg(GET_DEV(accel_dev), "ri_cpp_int_sts = 0x%X\n", ri_cpp_int_sts); + + if (ri_cpp_int_sts & ADF_C4XXX_RI_CPP_INT_STS_PUSH_DATA_PAR_ERR) { + atomic_inc(&accel_dev->ras_counters[ADF_RAS_UNCORR]); + device_printf( + GET_DEV(accel_dev), + "CPP%d: Uncorrectable non-fatal RI push data parity error detected.\n", + ADF_C4XXX_GET_CPP_BUS_FROM_STS(ri_cpp_int_sts)); + } + + /* Clear the interrupt and allow the next error to be logged. */ + ADF_CSR_WR(pmisc, + ADF_C4XXX_RI_CPP_INT_STS, + ADF_C4XXX_RI_CPP_INT_STS_PUSH_DATA_PAR_ERR); +} + +static inline void +adf_log_inln_err(struct adf_accel_dev *accel_dev, + u32 offset, + u8 ras_type, + char *msg) +{ + if (ras_type >= ADF_RAS_ERRORS) { + device_printf(GET_DEV(accel_dev), + "Invalid ras type %u\n", + ras_type); + return; + } + + if (offset == ADF_C4XXX_INLINE_INGRESS_OFFSET) { + if (ras_type == ADF_RAS_CORR) + dev_dbg(GET_DEV(accel_dev), "Detect ici %s\n", msg); + else + device_printf(GET_DEV(accel_dev), + "Detect ici %s\n", + msg); + } else { + if (ras_type == ADF_RAS_CORR) + dev_dbg(GET_DEV(accel_dev), "Detect ice %s\n", msg); + else + device_printf(GET_DEV(accel_dev), + "Detect ice %s\n", + msg); + } + atomic_inc(&accel_dev->ras_counters[ras_type]); +} + +static inline void +adf_handle_parser_uerr(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 offset, + bool *reset_required) +{ + u32 reg_val = 0; + + reg_val = ADF_CSR_RD(aram_base_addr, ADF_C4XXX_IC_PARSER_UERR + offset); + if (reg_val & ADF_C4XXX_PARSER_UERR_INTR) { + /* Mask inten */ + reg_val &= ~ADF_C4XXX_PARSER_DESC_UERR_INTR_ENA; + ADF_CSR_WR(aram_base_addr, + ADF_C4XXX_IC_PARSER_UERR + offset, + reg_val); + + /* Fatal error then increase RAS error counter + * and reset CPM + */ + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "parser uncorr fatal err"); + *reset_required = true; + } +} + +static inline void +adf_handle_mac_intr(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 offset, + bool *reset_required) +{ + u64 reg_val; + + reg_val = ADF_CSR_RD64(aram_base_addr, ADF_C4XXX_MAC_IP + offset); + + /* Handle the MAC interrupts masked out in MAC_IM */ + if (reg_val & ADF_C4XXX_MAC_ERROR_TX_UNDERRUN) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "err tx underrun"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_TX_FCS) + adf_log_inln_err(accel_dev, offset, ADF_RAS_CORR, "err tx fcs"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_TX_DATA_CORRUPT) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "err tx data corrupt"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_OVERRUN) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "err rx overrun fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_RUNT) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "err rx runt fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_UNDERSIZE) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "err rx undersize fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_JABBER) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "err rx jabber fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_OVERSIZE) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "err rx oversize fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_FCS) + adf_log_inln_err(accel_dev, offset, ADF_RAS_CORR, "err rx fcs"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_FRAME) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "err rx frame"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_CODE) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "err rx code"); + + if (reg_val & ADF_C4XXX_MAC_ERROR_RX_PREAMBLE) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "err rx preamble"); + + if (reg_val & ADF_C4XXX_MAC_RX_LINK_UP) + adf_log_inln_err(accel_dev, offset, ADF_RAS_CORR, "rx link up"); + + if (reg_val & ADF_C4XXX_MAC_INVALID_SPEED) + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "invalid speed"); + + if (reg_val & ADF_C4XXX_MAC_PIA_RX_FIFO_OVERRUN) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "pia rx fifo overrun fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_PIA_TX_FIFO_OVERRUN) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "pia tx fifo overrun fatal err"); + } + + if (reg_val & ADF_C4XXX_MAC_PIA_TX_FIFO_UNDERRUN) { + *reset_required = true; + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + "pia tx fifo underrun fatal err"); + } + + /* Clear the interrupt and allow the next error to be logged. */ + ADF_CSR_WR64(aram_base_addr, ADF_C4XXX_MAC_IP + offset, reg_val); +} + +static inline bool +adf_handle_rf_par_err(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 rf_par_addr, + u32 rf_par_msk, + u32 offset, + char *msg) +{ + u32 reg_val; + unsigned long intr_status; + int i; + char strbuf[ADF_C4XXX_MAX_STR_LEN]; + + /* Handle rf parity error */ + reg_val = ADF_CSR_RD(aram_base_addr, rf_par_addr + offset); + intr_status = reg_val & rf_par_msk; + if (intr_status) { + for_each_set_bit(i, &intr_status, ADF_C4XXX_RF_PAR_ERR_BITS) + { + if (i % 2 == 0) + snprintf(strbuf, + sizeof(strbuf), + "%s mul par %u uncorr fatal err", + msg, + RF_PAR_MUL_MAP(i)); + + else + snprintf(strbuf, + sizeof(strbuf), + "%s par %u uncorr fatal err", + msg, + RF_PAR_MAP(i)); + + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_FATAL, + strbuf); + } + + /* Clear the interrupt and allow the next error to be logged. */ + ADF_CSR_WR(aram_base_addr, rf_par_addr + offset, reg_val); + return true; + } + return false; +} + +static inline void +adf_handle_cd_rf_par_err(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 offset, + bool *reset_required) +{ + /* Handle reg_cd_rf_parity_err[1] */ + *reset_required |= + adf_handle_rf_par_err(accel_dev, + aram_base_addr, + ADF_C4XXX_IC_CD_RF_PARITY_ERR_1, + ADF_C4XXX_CD_RF_PAR_ERR_1_INTR, + offset, + "cd rf par[1]:") ? + true : + false; +} + +static inline void +adf_handle_inln_rf_par_err(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 offset, + bool *reset_required) +{ + /* Handle reg_inln_rf_parity_err[0] */ + *reset_required |= + adf_handle_rf_par_err(accel_dev, + aram_base_addr, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_0, + ADF_C4XXX_INLN_RF_PAR_ERR_0_INTR, + offset, + "inln rf par[0]:") ? + true : + false; + + /* Handle reg_inln_rf_parity_err[1] */ + *reset_required |= + adf_handle_rf_par_err(accel_dev, + aram_base_addr, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_1, + ADF_C4XXX_INLN_RF_PAR_ERR_1_INTR, + offset, + "inln rf par[1]:") ? + true : + false; + + /* Handle reg_inln_rf_parity_err[2] */ + *reset_required |= + adf_handle_rf_par_err(accel_dev, + aram_base_addr, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_2, + ADF_C4XXX_INLN_RF_PAR_ERR_2_INTR, + offset, + "inln rf par[2]:") ? + true : + false; + + /* Handle reg_inln_rf_parity_err[5] */ + *reset_required |= + adf_handle_rf_par_err(accel_dev, + aram_base_addr, + ADF_C4XXX_IC_INLN_RF_PARITY_ERR_5, + ADF_C4XXX_INLN_RF_PAR_ERR_5_INTR, + offset, + "inln rf par[5]:") ? + true : + false; +} + +static inline void +adf_handle_congest_mngt_intr(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 offset, + bool *reset_required) +{ + u32 reg_val; + + reg_val = ADF_CSR_RD(aram_base_addr, + ADF_C4XXX_IC_CONGESTION_MGMT_INT + offset); + + /* A mis-configuration of CPM, a mis-configuration of the Ethernet + * Complex or that the traffic profile has deviated from that for + * which the resources were configured + */ + if (reg_val & ADF_C4XXX_CONGESTION_MGMT_CTPB_GLOBAL_CROSSED) { + adf_log_inln_err( + accel_dev, + offset, + ADF_RAS_FATAL, + "congestion mgmt ctpb global crossed fatal err"); + *reset_required = true; + } + + if (reg_val & ADF_C4XXX_CONGESTION_MGMT_XOFF_CIRQ_OUT) { + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "congestion mgmt XOFF cirq out err"); + } + + if (reg_val & ADF_C4XXX_CONGESTION_MGMT_XOFF_CIRQ_IN) { + adf_log_inln_err(accel_dev, + offset, + ADF_RAS_CORR, + "congestion mgmt XOFF cirq in err"); + } + + /* Clear the interrupt and allow the next error to be logged */ + ADF_CSR_WR(aram_base_addr, + ADF_C4XXX_IC_CONGESTION_MGMT_INT + offset, + reg_val); +} + +static inline void +adf_handle_inline_intr(struct adf_accel_dev *accel_dev, + struct resource *aram_base_addr, + u32 csr_offset, + bool *reset_required) +{ + adf_handle_cd_rf_par_err(accel_dev, + aram_base_addr, + csr_offset, + reset_required); + + adf_handle_parser_uerr(accel_dev, + aram_base_addr, + csr_offset, + reset_required); + + adf_handle_inln_rf_par_err(accel_dev, + aram_base_addr, + csr_offset, + reset_required); + + adf_handle_congest_mngt_intr(accel_dev, + aram_base_addr, + csr_offset, + reset_required); + + adf_handle_mac_intr(accel_dev, + aram_base_addr, + csr_offset, + reset_required); +} + +static inline void +adf_process_errsou11(struct adf_accel_dev *accel_dev, + struct resource *pmisc, + u32 errsou, + bool *reset_required) +{ + struct resource *aram_base_addr = + (&GET_BARS(accel_dev)[ADF_C4XXX_SRAM_BAR])->virt_addr; + + if (errsou & ADF_C4XXX_TI_MISC) + adf_handle_ti_misc_err(accel_dev, pmisc); + + if (errsou & ADF_C4XXX_RI_PUSH_PULL_PAR_ERR) + adf_handle_ri_push_pull_par_err(accel_dev, pmisc); + + if (errsou & ADF_C4XXX_TI_PUSH_PULL_PAR_ERR) + adf_handle_ti_push_pull_par_err(accel_dev, pmisc); + + if (errsou & ADF_C4XXX_ARAM_CORR_ERR) + adf_handle_aram_corr_err(accel_dev, aram_base_addr); + + if (errsou & ADF_C4XXX_ARAM_UNCORR_ERR) + adf_handle_aram_uncorr_err(accel_dev, aram_base_addr); + + if (errsou & ADF_C4XXX_TI_PULL_PAR_ERR) + adf_handle_ti_pull_par_err(accel_dev, pmisc); + + if (errsou & ADF_C4XXX_RI_PUSH_PAR_ERR) + adf_handle_ri_push_par_err(accel_dev, pmisc); + + if (errsou & ADF_C4XXX_INLINE_INGRESS_INTR) + adf_handle_inline_intr(accel_dev, + aram_base_addr, + ADF_C4XXX_INLINE_INGRESS_OFFSET, + reset_required); + + if (errsou & ADF_C4XXX_INLINE_EGRESS_INTR) + adf_handle_inline_intr(accel_dev, + aram_base_addr, + ADF_C4XXX_INLINE_EGRESS_OFFSET, + reset_required); +} + +bool +adf_ras_interrupts(struct adf_accel_dev *accel_dev, bool *reset_required) +{ + u32 errsou = 0; + bool handled = false; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 num_accels = hw_data->get_num_accels(hw_data); + struct resource *pmisc = + (&GET_BARS(accel_dev)[ADF_C4XXX_PMISC_BAR])->virt_addr; + + if (unlikely(!reset_required)) { + device_printf(GET_DEV(accel_dev), + "Invalid pointer reset_required\n"); + return false; + } + + /* errsou8 */ + errsou = ADF_CSR_RD(pmisc, ADF_C4XXX_ERRSOU8); + if (errsou & ADF_C4XXX_ERRSOU8_MECORR_MASK) { + adf_process_errsou8(accel_dev, pmisc); + handled = true; + } + + /* errsou9 */ + errsou = ADF_CSR_RD(pmisc, ADF_C4XXX_ERRSOU9); + if (errsou & ADF_C4XXX_ERRSOU9_ERROR_MASK) { + adf_process_errsou9(accel_dev, pmisc, errsou, reset_required); + handled = true; + } + + /* errsou10 */ + errsou = ADF_CSR_RD(pmisc, ADF_C4XXX_ERRSOU10); + if (errsou & ADF_C4XXX_ERRSOU10_RAS_MASK) { + adf_process_errsou10( + accel_dev, pmisc, errsou, num_accels, reset_required); + handled = true; + } + + /* errsou11 */ + errsou = ADF_CSR_RD(pmisc, ADF_C4XXX_ERRSOU11); + if (errsou & ADF_C4XXX_ERRSOU11_ERROR_MASK) { + adf_process_errsou11(accel_dev, pmisc, errsou, reset_required); + handled = true; + } + + return handled; +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.h new file mode 100644 index 00000000000..0c8119c6d87 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_ras.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_RAS_H +#define ADF_RAS_H + +#include + +#define ADF_RAS_CORR 0 +#define ADF_RAS_UNCORR 1 +#define ADF_RAS_FATAL 2 +#define ADF_RAS_ERRORS 3 + +struct adf_accel_dev; + +int adf_init_ras(struct adf_accel_dev *accel_dev); +void adf_exit_ras(struct adf_accel_dev *accel_dev); +bool adf_ras_interrupts(struct adf_accel_dev *accel_dev, bool *reset_required); + +#endif /* ADF_RAS_H */ diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_res_part.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_res_part.c new file mode 100644 index 00000000000..dcbc89b1d15 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_res_part.c @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_cfg_common.h" +#include "adf_transport_internal.h" +#include "icp_qat_hw.h" +#include "adf_c4xxx_hw_data.h" + +#define ADF_C4XXX_PARTTITION_SHIFT 8 +#define ADF_C4XXX_PARTITION(svc, ring) \ + ((svc) << ((ring)*ADF_C4XXX_PARTTITION_SHIFT)) + +static void +adf_get_partitions_mask(struct adf_accel_dev *accel_dev, u32 *partitions_mask) +{ + device_t dev = accel_to_pci_dev(accel_dev); + u32 enabled_partitions_msk = 0; + u8 ring_pair = 0; + enum adf_cfg_service_type serv_type = 0; + u16 ring_to_svc_map = accel_dev->hw_device->ring_to_svc_map; + + for (ring_pair = 0; ring_pair < ADF_CFG_NUM_SERVICES; ring_pair++) { + serv_type = GET_SRV_TYPE(ring_to_svc_map, ring_pair); + switch (serv_type) { + case CRYPTO: { + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_ASYM, + ring_pair++); + if (ring_pair < ADF_CFG_NUM_SERVICES) + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_SYM, + ring_pair); + else + device_printf( + dev, "Failed to enable SYM partition.\n"); + break; + } + case COMP: + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_DC, ring_pair); + break; + case SYM: + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_SYM, ring_pair); + break; + case ASYM: + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_ASYM, ring_pair); + break; + default: + enabled_partitions_msk |= + ADF_C4XXX_PARTITION(ADF_C4XXX_PART_UNUSED, + ring_pair); + break; + } + } + *partitions_mask = enabled_partitions_msk; +} + +static void +adf_enable_sym_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition) +{ + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info; + u32 num_sym_thds = ae_info[ae].num_sym_thd; + u32 i; + u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP; + u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP | + (BIT(partition % ADF_C4XXX_PARTS_PER_GRP)); + + for (i = 0; i < num_sym_thds; i++) + WRITE_CSR_WQM(csr, + ADF_C4XXX_WRKTHD2PARTMAP, + (ae * ADF_NUM_THREADS_PER_AE + i), + wkrthd2_partmap); +} + +static void +adf_enable_asym_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition) +{ + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info; + u32 num_asym_thds = ae_info[ae].num_asym_thd; + u32 i; + u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP; + u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP | + (BIT(partition % ADF_C4XXX_PARTS_PER_GRP)); + /* For asymmetric cryptography SKU we have one thread less */ + u32 num_all_thds = ADF_NUM_THREADS_PER_AE - 2; + + for (i = num_all_thds; i > (num_all_thds - num_asym_thds); i--) + WRITE_CSR_WQM(csr, + ADF_C4XXX_WRKTHD2PARTMAP, + (ae * ADF_NUM_THREADS_PER_AE + i), + wkrthd2_partmap); +} + +static void +adf_enable_dc_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition) +{ + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info; + u32 num_dc_thds = ae_info[ae].num_dc_thd; + u32 i; + u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP; + u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP | + (BIT(partition % ADF_C4XXX_PARTS_PER_GRP)); + + for (i = 0; i < num_dc_thds; i++) + WRITE_CSR_WQM(csr, + ADF_C4XXX_WRKTHD2PARTMAP, + (ae * ADF_NUM_THREADS_PER_AE + i), + wkrthd2_partmap); +} + +/* Initialise Resource partitioning. + * Initialise a default set of 4 partitions to arbitrate + * request rings per bundle. + */ +int +adf_init_arb_c4xxx(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *csr = accel_dev->transport->banks[0].csr_addr; + struct adf_accel_unit_info *au_info = accel_dev->au_info; + u32 i; + unsigned long ae_mask; + u32 partitions_mask = 0; + + /* invoke common adf_init_arb */ + adf_init_arb(accel_dev); + + adf_get_partitions_mask(accel_dev, &partitions_mask); + for (i = 0; i < hw_data->num_banks; i++) + WRITE_CSR_WQM(csr, + ADF_C4XXX_PARTITION_LUT_OFFSET, + i, + partitions_mask); + + ae_mask = hw_data->ae_mask; + + /* Assigning default partitions to accel engine + * worker threads + */ + for_each_set_bit(i, &ae_mask, ADF_C4XXX_MAX_ACCELENGINES) + { + if (BIT(i) & au_info->sym_ae_msk) + adf_enable_sym_threads(accel_dev, + i, + ADF_C4XXX_PART_SYM); + if (BIT(i) & au_info->asym_ae_msk) + adf_enable_asym_threads(accel_dev, + i, + ADF_C4XXX_PART_ASYM); + if (BIT(i) & au_info->dc_ae_msk) + adf_enable_dc_threads(accel_dev, i, ADF_C4XXX_PART_DC); + } + + return 0; +} + +/* Disable the resource partitioning feature + * and restore the default partitioning scheme + */ +void +adf_exit_arb_c4xxx(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + struct resource *csr; + u32 i; + unsigned long ae_mask; + + if (!accel_dev->transport) + return; + csr = accel_dev->transport->banks[0].csr_addr; + + /* Restore the default partitionLUT registers */ + for (i = 0; i < hw_data->num_banks; i++) + WRITE_CSR_WQM(csr, + ADF_C4XXX_PARTITION_LUT_OFFSET, + i, + ADF_C4XXX_DEFAULT_PARTITIONS); + + ae_mask = hw_data->ae_mask; + + /* Reset worker thread to partition mapping */ + for (i = 0; i < hw_data->num_engines * ADF_NUM_THREADS_PER_AE; i++) { + if (!test_bit((u32)(i / ADF_NUM_THREADS_PER_AE), &ae_mask)) + continue; + + WRITE_CSR_WQM(csr, ADF_C4XXX_WRKTHD2PARTMAP, i, 0); + } +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.c new file mode 100644 index 00000000000..391851b2113 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include "adf_c4xxx_reset.h" + +static void +adf_check_uncorr_status(struct adf_accel_dev *accel_dev) +{ + u32 uncorr_err; + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + + uncorr_err = pci_read_config(pdev, PCI_EXP_AERUCS, 4); + if (uncorr_err & PCIE_C4XXX_VALID_ERR_MASK) { + device_printf(GET_DEV(accel_dev), + "Uncorrectable error occurred during reset\n"); + device_printf(GET_DEV(accel_dev), + "Error code value: 0x%04x\n", + uncorr_err); + } +} + +static void +adf_c4xxx_dev_reset(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + u8 count = 0; + uintptr_t device_id1; + uintptr_t device_id2; + + /* Read device ID before triggering reset */ + device_id1 = pci_read_config(pdev, PCIR_DEVICE, 2); + hw_device->reset_device(accel_dev); + + /* Wait for reset to complete */ + do { + /* Ensure we have the configuration space restored */ + device_id2 = pci_read_config(pdev, PCIR_DEVICE, 2); + if (device_id1 == device_id2) { + /* Check if a PCIe uncorrectable error occurred + * during the reset + */ + adf_check_uncorr_status(accel_dev); + return; + } + count++; + pause_ms("adfstop", 100); + } while (count < ADF_PCIE_FLR_ATTEMPT); + device_printf(GET_DEV(accel_dev), + "Too many attempts to read back config space.\n"); +} + +void +adf_c4xxx_dev_restore(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 pmisclbar1; + u32 pmisclbar2; + u32 pmiscubar1; + u32 pmiscubar2; + + if (hw_device->reset_device) { + device_printf(GET_DEV(accel_dev), + "Resetting device qat_dev%d\n", + accel_dev->accel_id); + + /* Read pmiscubar and pmisclbar */ + pmisclbar1 = pci_read_config(pdev, ADF_PMISC_L_OFFSET, 4); + pmiscubar1 = pci_read_config(pdev, ADF_PMISC_U_OFFSET, 4); + + adf_c4xxx_dev_reset(accel_dev); + pci_restore_state(pdev); + + /* Read pmiscubar and pmisclbar */ + pmisclbar2 = pci_read_config(pdev, ADF_PMISC_L_OFFSET, 4); + pmiscubar2 = pci_read_config(pdev, ADF_PMISC_U_OFFSET, 4); + + /* Check if restore operation has completed successfully */ + if (pmisclbar1 != pmisclbar2 || pmiscubar1 != pmiscubar2) { + device_printf( + GET_DEV(accel_dev), + "Failed to restore device configuration\n"); + return; + } + pci_save_state(pdev); + } + + if (hw_device->post_reset) { + dev_dbg(GET_DEV(accel_dev), "Performing post reset restore\n"); + hw_device->post_reset(accel_dev); + } +} diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.h b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.h new file mode 100644 index 00000000000..07406f06397 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_c4xxx_reset.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C4XXX_RESET_H_ +#define ADF_C4XXX_RESET_H_ + +#include +#include +#include "adf_c4xxx_hw_data.h" + +/* IA2IOSFSB register definitions */ +#define ADF_C4XXX_IA2IOSFSB_PORTCMD (0x60000 + 0x1320) +#define ADF_C4XXX_IA2IOSFSB_LOADD (0x60000 + 0x1324) +#define ADF_C4XXX_IA2IOSFSB_HIADD (0x60000 + 0x1328) +#define ADF_C4XXX_IA2IOSFSB_DATA(index) ((index)*0x4 + 0x60000 + 0x132C) +#define ADF_C4XXX_IA2IOSFSB_KHOLE (0x60000 + 0x136C) +#define ADF_C4XXX_IA2IOSFSB_STATUS (0x60000 + 0x1370) + +/* IOSF-SB Port command definitions */ +/* Ethernet controller Port ID */ +#define ADF_C4XXX_ETH_PORT_ID 0x61 +/* Byte enable */ +#define ADF_C4XXX_PORTD_CMD_BE 0xFF +/* Non posted; Only non-posted commands are used */ +#define ADF_C4XXX_PORTD_CMD_NP 0x1 +/* Number of DWORDs to transfer */ +#define ADF_C4XXX_PORTD_CMD_LENDW 0x2 +/* Extended header always used */ +#define ADF_C4XXX_PORTD_CMD_EH 0x1 +/* Address length */ +#define ADF_C4XXX_PORTD_CMD_ALEN 0x0 +/* Message opcode: Private Register Write Non-Posted or Posted Message*/ +#define ADF_C4XXX_MOPCODE 0x07 + +/* Compute port command based on port ID */ +#define ADF_C4XXX_GET_PORT_CMD(port_id) \ + ((((port_id)&0xFF) << 24) | (ADF_C4XXX_PORTD_CMD_BE << 16) | \ + (ADF_C4XXX_PORTD_CMD_NP << 15) | (ADF_C4XXX_PORTD_CMD_LENDW << 10) | \ + (ADF_C4XXX_PORTD_CMD_EH << 9) | (ADF_C4XXX_PORTD_CMD_ALEN << 8) | \ + (ADF_C4XXX_MOPCODE)) + +/* Pending reset event/ack message over IOSF-SB */ +#define ADF_C4XXX_IOSFSB_RESET_EVENT BIT(0) +#define ADF_C4XXX_IOSFSB_RESET_ACK BIT(7) + +/* Upon an FLR, the PCI_EXP_AERUCS register must be read and we must make sure + * that not other bit is set excepted the: + * - UR (Unsupported request) bit<20> + * - IEUNC (Uncorrectable Internal Error) bit <22> + */ +#define PCIE_C4XXX_VALID_ERR_MASK (~BIT(20) ^ BIT(22)) + +/* Trigger: trigger an IOSF SB message */ +#define ADF_C4XXX_IOSFSB_TRIGGER BIT(0) + +/* IOSF-SB status definitions */ +/* Response status bits<1:0> definitions + * 00 = Successful + * 01 = Unsuccessful + * 10 = Powered down + * 11 = Multicast + */ +#define ADF_C4XXX_IA2IOSFSB_STATUS_RTS (BIT(0) | BIT(1)) +#define ADF_C4XXX_IA2IOSFSB_STATUS_PEND BIT(6) +/* Allow 100ms polling interval */ +#define ADF_C4XXX_IA2IOSFSB_POLLING_INTERVAL 100 +/* Allow a maximum of 500ms before timing out */ +#define ADF_C4XXX_IA2IOSFSB_POLLING_COUNT 5 + +/* Ethernet notification polling interval */ +#define ADF_C4XXX_MAX_ETH_ACK_ATTEMPT 100 +#define ADF_C4XXX_ETH_ACK_POLLING_INTERVAL 10 + +void adf_c4xxx_dev_restore(struct adf_accel_dev *accel_dev); +void notify_and_wait_ethernet(struct adf_accel_dev *accel_dev); +#endif diff --git a/sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c b/sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c new file mode 100644 index 00000000000..3470e4e8a8a --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_c4xxx_hw_data.h" +#include "adf_fw_counters.h" +#include "adf_cfg_device.h" +#include +#include +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_cnvnr_freq_counters.h" + +static MALLOC_DEFINE(M_QAT_C4XXX, "qat_c4xx", "qat_c4xx"); + +#define ADF_SYSTEM_DEVICE(device_id) \ + { \ + PCI_VENDOR_ID_INTEL, device_id \ + } + +static const struct pci_device_id adf_pci_tbl[] = + { ADF_SYSTEM_DEVICE(ADF_C4XXX_PCI_DEVICE_ID), + { + 0, + } }; + +static int +adf_probe(device_t dev) +{ + const struct pci_device_id *id; + + for (id = adf_pci_tbl; id->vendor != 0; id++) { + if (pci_get_vendor(dev) == id->vendor && + pci_get_device(dev) == id->device) { + device_set_desc(dev, + "Intel " ADF_C4XXX_DEVICE_NAME + " QuickAssist"); + return BUS_PROBE_GENERIC; + } + } + return ENXIO; +} + +static void +adf_cleanup_accel(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; + int i; + + if (accel_dev->dma_tag) + bus_dma_tag_destroy(accel_dev->dma_tag); + for (i = 0; i < ADF_PCI_MAX_BARS; i++) { + struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; + + if (bar->virt_addr) + bus_free_resource(accel_pci_dev->pci_dev, + SYS_RES_MEMORY, + bar->virt_addr); + } + + if (accel_dev->hw_device) { + switch (pci_get_device(accel_pci_dev->pci_dev)) { + case ADF_C4XXX_PCI_DEVICE_ID: + adf_clean_hw_data_c4xxx(accel_dev->hw_device); + break; + default: + break; + } + free(accel_dev->hw_device, M_QAT_C4XXX); + accel_dev->hw_device = NULL; + } + adf_cfg_dev_remove(accel_dev); + adf_devmgr_rm_dev(accel_dev, NULL); +} + +static int +adf_attach(device_t dev) +{ + struct adf_accel_dev *accel_dev; + struct adf_accel_pci *accel_pci_dev; + struct adf_hw_device_data *hw_data; + unsigned int i, bar_nr; + int ret, rid; + struct adf_cfg_device *cfg_dev = NULL; + + /* Set pci MaxPayLoad to 256. Implemented to avoid the issue of + * Pci-passthrough causing Maxpayload to be reset to 128 bytes + * when the device is reset. + */ + if (pci_get_max_payload(dev) != 256) + pci_set_max_payload(dev, 256); + + accel_dev = device_get_softc(dev); + + INIT_LIST_HEAD(&accel_dev->crypto_list); + accel_pci_dev = &accel_dev->accel_pci_dev; + accel_pci_dev->pci_dev = dev; + + if (bus_get_domain(dev, &accel_pci_dev->node) != 0) + accel_pci_dev->node = 0; + + /* XXX: Revisit if we actually need a devmgr table at all. */ + + /* Add accel device to accel table. + * This should be called before adf_cleanup_accel is called + */ + if (adf_devmgr_add_dev(accel_dev, NULL)) { + device_printf(dev, "Failed to add new accelerator device.\n"); + return ENXIO; + } + + /* Allocate and configure device configuration structure */ + hw_data = malloc(sizeof(*hw_data), M_QAT_C4XXX, M_WAITOK | M_ZERO); + + accel_dev->hw_device = hw_data; + adf_init_hw_data_c4xxx(accel_dev->hw_device); + accel_pci_dev->revid = pci_get_revid(dev); + hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4); + + /* Get PPAERUCM values and store */ + ret = adf_aer_store_ppaerucm_reg(dev, hw_data); + if (ret) + goto out_err; + + /* Get Accelerators and Accelerators Engines masks */ + hw_data->accel_mask = hw_data->get_accel_mask(accel_dev); + hw_data->ae_mask = hw_data->get_ae_mask(accel_dev); + + /* If the device has no acceleration engines then ignore it. */ + if (!hw_data->accel_mask || !hw_data->ae_mask || + (~hw_data->ae_mask & 0x01)) { + device_printf(dev, "No acceleration units found\n"); + ret = ENXIO; + goto out_err; + } + + /* Create device configuration table */ + ret = adf_cfg_dev_add(accel_dev); + if (ret) + goto out_err; + + ret = adf_clock_debugfs_add(accel_dev); + if (ret) + goto out_err; + + pci_set_max_read_req(dev, 1024); + + ret = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, + NULL, + BUS_SPACE_MAXSIZE, + /*BUS_SPACE_UNRESTRICTED*/ 1, + BUS_SPACE_MAXSIZE, + 0, + NULL, + NULL, + &accel_dev->dma_tag); + if (ret) + goto out_err; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + accel_pci_dev->sku = hw_data->get_sku(hw_data); + + /* Find and map all the device's BARS */ + i = 0; + for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0; + bar_nr++) { + struct adf_bar *bar; + + /* + * XXX: This isn't quite right as it will ignore a BAR + * that wasn't assigned a valid resource range by the + * firmware. + */ + rid = PCIR_BAR(bar_nr); + if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0) + continue; + bar = &accel_pci_dev->pci_bars[i++]; + bar->virt_addr = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, + &rid, + RF_ACTIVE); + if (!bar->virt_addr) { + device_printf(dev, "Failed to map BAR %d\n", bar_nr); + ret = ENXIO; + goto out_err; + } + bar->base_addr = rman_get_start(bar->virt_addr); + bar->size = rman_get_start(bar->virt_addr); + } + pci_enable_busmaster(dev); + + if (!accel_dev->hw_device->config_device) { + ret = EFAULT; + goto out_err; + } + + ret = accel_dev->hw_device->config_device(accel_dev); + if (ret) + goto out_err; + + ret = adf_dev_init(accel_dev); + if (ret) + goto out_dev_shutdown; + + ret = adf_dev_start(accel_dev); + if (ret) + goto out_dev_stop; + + cfg_dev = accel_dev->cfg->dev; + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + return ret; +out_dev_stop: + adf_dev_stop(accel_dev); +out_dev_shutdown: + adf_dev_shutdown(accel_dev); +out_err: + adf_cleanup_accel(accel_dev); + return ret; +} + +static int +adf_detach(device_t dev) +{ + struct adf_accel_dev *accel_dev = device_get_softc(dev); + + if (adf_dev_stop(accel_dev)) { + device_printf(dev, "Failed to stop QAT accel dev\n"); + return EBUSY; + } + + adf_dev_shutdown(accel_dev); + + adf_cleanup_accel(accel_dev); + + return 0; +} + +static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe), + DEVMETHOD(device_attach, adf_attach), + DEVMETHOD(device_detach, adf_detach), + + DEVMETHOD_END }; + +static driver_t adf_driver = { "qat", + adf_methods, + sizeof(struct adf_accel_dev) }; + +DRIVER_MODULE_ORDERED(qat_c4xxx, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD); +MODULE_VERSION(qat_c4xxx, 1); +MODULE_DEPEND(qat_c4xxx, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_c4xxx, qat_api, 1, 1, 1); +MODULE_DEPEND(qat_c4xxx, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.c b/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.c new file mode 100644 index 00000000000..2ff72b94fa5 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.c @@ -0,0 +1,420 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include +#include +#include +#include +#include +#include "adf_c62x_hw_data.h" +#include "icp_qat_hw.h" +#include "adf_cfg.h" +#include "adf_heartbeat.h" + +/* Worker thread to service arbiter mappings */ +static const u32 thrd_to_arb_map[ADF_C62X_MAX_ACCELENGINES] = + { 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA, 0x12222AAA, + 0x11222AAA, 0x12222AAA, 0x11222AAA, 0x12222AAA, 0x11222AAA }; + +enum { DEV_C62X_SKU_1 = 0, DEV_C62X_SKU_2 = 1 }; + +static u32 thrd_to_arb_map_gen[ADF_C62X_MAX_ACCELENGINES] = { 0 }; + +static struct adf_hw_device_class c62x_class = {.name = ADF_C62X_DEVICE_NAME, + .type = DEV_C62X, + .instances = 0 }; + +static u32 +get_accel_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + + u32 fuse; + u32 straps; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + straps = pci_read_config(pdev, ADF_C62X_SOFTSTRAP_CSR_OFFSET, 4); + + return (~(fuse | straps)) >> ADF_C62X_ACCELERATORS_REG_OFFSET & + ADF_C62X_ACCELERATORS_MASK; +} + +static u32 +get_ae_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fuse; + u32 me_straps; + u32 me_disable; + u32 ssms_disabled; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + me_straps = pci_read_config(pdev, ADF_C62X_SOFTSTRAP_CSR_OFFSET, 4); + + /* If SSMs are disabled, then disable the corresponding MEs */ + ssms_disabled = + (~get_accel_mask(accel_dev)) & ADF_C62X_ACCELERATORS_MASK; + me_disable = 0x3; + while (ssms_disabled) { + if (ssms_disabled & 1) + me_straps |= me_disable; + ssms_disabled >>= 1; + me_disable <<= 2; + } + + return (~(fuse | me_straps)) & ADF_C62X_ACCELENGINES_MASK; +} + +static u32 +get_num_accels(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->accel_mask) + return 0; + + for (i = 0; i < ADF_C62X_MAX_ACCELERATORS; i++) { + if (self->accel_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_num_aes(struct adf_hw_device_data *self) +{ + u32 i, ctr = 0; + + if (!self || !self->ae_mask) + return 0; + + for (i = 0; i < ADF_C62X_MAX_ACCELENGINES; i++) { + if (self->ae_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static u32 +get_misc_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C62X_PMISC_BAR; +} + +static u32 +get_etr_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C62X_ETR_BAR; +} + +static u32 +get_sram_bar_id(struct adf_hw_device_data *self) +{ + return ADF_C62X_SRAM_BAR; +} + +static enum dev_sku_info +get_sku(struct adf_hw_device_data *self) +{ + int aes = get_num_aes(self); + + if (aes == 8) + return DEV_SKU_2; + else if (aes == 10) + return DEV_SKU_4; + + return DEV_SKU_UNKNOWN; +} + +static void +adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev, + u32 const **arb_map_config) +{ + int i; + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + + for (i = 0; i < ADF_C62X_MAX_ACCELENGINES; i++) { + thrd_to_arb_map_gen[i] = 0; + if (hw_device->ae_mask & (1 << i)) + thrd_to_arb_map_gen[i] = thrd_to_arb_map[i]; + } + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map, + thrd_to_arb_map_gen, + ADF_C62X_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; +} + +static u32 +get_pf2vf_offset(u32 i) +{ + return ADF_C62X_PF2VF_OFFSET(i); +} + +static u32 +get_vintmsk_offset(u32 i) +{ + return ADF_C62X_VINTMSK_OFFSET(i); +} + +static void +get_arb_info(struct arb_info *arb_csrs_info) +{ + arb_csrs_info->arbiter_offset = ADF_C62X_ARB_OFFSET; + arb_csrs_info->wrk_thd_2_srv_arb_map = + ADF_C62X_ARB_WRK_2_SER_MAP_OFFSET; + arb_csrs_info->wrk_cfg_offset = ADF_C62X_ARB_WQCFG_OFFSET; +} + +static void +get_admin_info(struct admin_info *admin_csrs_info) +{ + admin_csrs_info->mailbox_offset = ADF_C62X_MAILBOX_BASE_OFFSET; + admin_csrs_info->admin_msg_ur = ADF_C62X_ADMINMSGUR_OFFSET; + admin_csrs_info->admin_msg_lr = ADF_C62X_ADMINMSGLR_OFFSET; +} + +static void +get_errsou_offset(u32 *errsou3, u32 *errsou5) +{ + *errsou3 = ADF_C62X_ERRSOU3; + *errsou5 = ADF_C62X_ERRSOU5; +} + +static u32 +get_clock_speed(struct adf_hw_device_data *self) +{ + /* CPP clock is half high-speed clock */ + return self->clock_frequency / 2; +} + +static void +adf_enable_error_correction(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_C62X_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + unsigned int val, i; + unsigned int mask; + + /* Enable Accel Engine error detection & correction */ + mask = hw_device->ae_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_C62X_AE_CTX_ENABLES(i)); + val |= ADF_C62X_ENABLE_AE_ECC_ERR; + ADF_CSR_WR(csr, ADF_C62X_AE_CTX_ENABLES(i), val); + val = ADF_CSR_RD(csr, ADF_C62X_AE_MISC_CONTROL(i)); + val |= ADF_C62X_ENABLE_AE_ECC_PARITY_CORR; + ADF_CSR_WR(csr, ADF_C62X_AE_MISC_CONTROL(i), val); + } + + /* Enable shared memory error detection & correction */ + mask = hw_device->accel_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_C62X_UERRSSMSH(i)); + val |= ADF_C62X_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C62X_UERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_C62X_CERRSSMSH(i)); + val |= ADF_C62X_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_C62X_CERRSSMSH(i), val); + } +} + +static void +adf_enable_ints(struct adf_accel_dev *accel_dev) +{ + struct resource *addr; + + addr = (&GET_BARS(accel_dev)[ADF_C62X_PMISC_BAR])->virt_addr; + + /* Enable bundle and misc interrupts */ + ADF_CSR_WR(addr, ADF_C62X_SMIAPF0_MASK_OFFSET, ADF_C62X_SMIA0_MASK); + ADF_CSR_WR(addr, ADF_C62X_SMIAPF1_MASK_OFFSET, ADF_C62X_SMIA1_MASK); +} + +static u32 +get_ae_clock(struct adf_hw_device_data *self) +{ + /* + * Clock update interval is <16> ticks for c62x. + */ + return self->clock_frequency / 16; +} + +static int +get_storage_enabled(struct adf_accel_dev *accel_dev, uint32_t *storage_enabled) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + strlcpy(key, ADF_STORAGE_FIRMWARE_ENABLED, sizeof(key)); + if (!adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) { + if (kstrtouint(val, 0, storage_enabled)) + return -EFAULT; + } + return 0; +} + +static int +measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret = 0; + + ret = adf_dev_measure_clock(accel_dev, + &frequency, + ADF_C62X_MIN_AE_FREQ, + ADF_C62X_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + +static u32 +c62x_get_hw_cap(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuses; + u32 capabilities; + u32 straps; + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 fuses = hw_data->fuses; + + /* Read accelerator capabilities mask */ + legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC + + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC + + ICP_ACCEL_CAPABILITIES_CIPHER + + ICP_ACCEL_CAPABILITIES_AUTHENTICATION + + ICP_ACCEL_CAPABILITIES_COMPRESSION + ICP_ACCEL_CAPABILITIES_ZUC + + ICP_ACCEL_CAPABILITIES_SHA3 + ICP_ACCEL_CAPABILITIES_HKDF + + ICP_ACCEL_CAPABILITIES_ECEDMONT + + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN; + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_HKDF | + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN); + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_ECEDMONT); + if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + if (legfuses & ICP_ACCEL_MASK_EIA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_ZUC; + if (legfuses & ICP_ACCEL_MASK_SHA3_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_SHA3; + + straps = pci_read_config(pdev, ADF_C62X_SOFTSTRAP_CSR_OFFSET, 4); + if ((straps | fuses) & ADF_C62X_POWERGATE_PKE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + if ((straps | fuses) & ADF_C62X_POWERGATE_DC) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + + return capabilities; +} + +static const char * +get_obj_name(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + return ADF_CXXX_AE_FW_NAME_CUSTOM1; +} + +static uint32_t +get_objs_num(struct adf_accel_dev *accel_dev) +{ + return 1; +} + +static uint32_t +get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services) +{ + return accel_dev->hw_device->ae_mask; +} + +void +adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class = &c62x_class; + hw_data->instance_id = c62x_class.instances++; + hw_data->num_banks = ADF_C62X_ETR_MAX_BANKS; + hw_data->num_rings_per_bank = ADF_ETR_MAX_RINGS_PER_BANK; + hw_data->num_accel = ADF_C62X_MAX_ACCELERATORS; + hw_data->num_logical_accel = 1; + hw_data->num_engines = ADF_C62X_MAX_ACCELENGINES; + hw_data->tx_rx_gap = ADF_C62X_RX_RINGS_OFFSET; + hw_data->tx_rings_mask = ADF_C62X_TX_RINGS_MASK; + hw_data->alloc_irq = adf_isr_resource_alloc; + hw_data->free_irq = adf_isr_resource_free; + hw_data->enable_error_correction = adf_enable_error_correction; + hw_data->print_err_registers = adf_print_err_registers; + hw_data->get_accel_mask = get_accel_mask; + hw_data->get_ae_mask = get_ae_mask; + hw_data->get_num_accels = get_num_accels; + hw_data->get_num_aes = get_num_aes; + hw_data->get_sram_bar_id = get_sram_bar_id; + hw_data->get_etr_bar_id = get_etr_bar_id; + hw_data->get_misc_bar_id = get_misc_bar_id; + hw_data->get_pf2vf_offset = get_pf2vf_offset; + hw_data->get_vintmsk_offset = get_vintmsk_offset; + hw_data->get_arb_info = get_arb_info; + hw_data->get_admin_info = get_admin_info; + hw_data->get_errsou_offset = get_errsou_offset; + hw_data->get_clock_speed = get_clock_speed; + hw_data->get_sku = get_sku; + hw_data->fw_name = ADF_C62X_FW; + hw_data->fw_mmp_name = ADF_C62X_MMP; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->disable_iov = adf_disable_sriov; + hw_data->send_admin_init = adf_send_admin_init; + hw_data->init_arb = adf_init_gen2_arb; + hw_data->exit_arb = adf_exit_arb; + hw_data->get_arb_mapping = adf_get_arbiter_mapping; + hw_data->enable_ints = adf_enable_ints; + hw_data->set_ssm_wdtimer = adf_set_ssm_wdtimer; + hw_data->check_slice_hang = adf_check_slice_hang; + hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms; + hw_data->disable_vf2pf_comms = adf_pf_disable_vf2pf_comms; + hw_data->restore_device = adf_dev_restore; + hw_data->reset_device = adf_reset_flr; + hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION; + hw_data->get_objs_num = get_objs_num; + hw_data->get_obj_name = get_obj_name; + hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; + hw_data->clock_frequency = ADF_C62X_AE_FREQ; + hw_data->measure_clock = measure_clock; + hw_data->get_ae_clock = get_ae_clock; + hw_data->get_accel_cap = c62x_get_hw_cap; + hw_data->reset_device = adf_reset_flr; + hw_data->extended_dc_capabilities = 0; + hw_data->get_storage_enabled = get_storage_enabled; + hw_data->query_storage_cap = 1; + hw_data->get_heartbeat_status = adf_get_heartbeat_status; + hw_data->get_ae_clock = get_ae_clock; + hw_data->storage_enable = 0; + hw_data->get_fw_image_type = adf_cfg_get_fw_image_type; + hw_data->config_device = adf_config_device; + hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled; + hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask; + hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP; + hw_data->pre_reset = adf_dev_pre_reset; + hw_data->post_reset = adf_dev_post_reset; +} + +void +adf_clean_hw_data_c62x(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class->instances--; +} diff --git a/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.h b/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.h new file mode 100644 index 00000000000..e379067c00b --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c62x/adf_c62x_hw_data.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_C62X_HW_DATA_H_ +#define ADF_C62X_HW_DATA_H_ + +/* PCIe configuration space */ +#define ADF_C62X_SRAM_BAR 0 +#define ADF_C62X_PMISC_BAR 1 +#define ADF_C62X_ETR_BAR 2 +#define ADF_C62X_RX_RINGS_OFFSET 8 +#define ADF_C62X_TX_RINGS_MASK 0xFF +#define ADF_C62X_MAX_ACCELERATORS 5 +#define ADF_C62X_MAX_ACCELENGINES 10 +#define ADF_C62X_ACCELERATORS_REG_OFFSET 16 +#define ADF_C62X_ACCELERATORS_MASK 0x1F +#define ADF_C62X_ACCELENGINES_MASK 0x3FF +#define ADF_C62X_ETR_MAX_BANKS 16 +#define ADF_C62X_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) +#define ADF_C62X_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) +#define ADF_C62X_SMIA0_MASK 0xFFFF +#define ADF_C62X_SMIA1_MASK 0x1 +#define ADF_C62X_SOFTSTRAP_CSR_OFFSET 0x2EC +#define ADF_C62X_POWERGATE_PKE BIT(24) +#define ADF_C62X_POWERGATE_DC BIT(23) + +/* Error detection and correction */ +#define ADF_C62X_AE_CTX_ENABLES(i) (i * 0x1000 + 0x20818) +#define ADF_C62X_AE_MISC_CONTROL(i) (i * 0x1000 + 0x20960) +#define ADF_C62X_ENABLE_AE_ECC_ERR BIT(28) +#define ADF_C62X_ENABLE_AE_ECC_PARITY_CORR (BIT(24) | BIT(12)) +#define ADF_C62X_UERRSSMSH(i) (i * 0x4000 + 0x18) +#define ADF_C62X_CERRSSMSH(i) (i * 0x4000 + 0x10) +#define ADF_C62X_ERRSOU3 (0x3A000 + 0x0C) +#define ADF_C62X_ERRSOU5 (0x3A000 + 0xD8) +#define ADF_C62X_ERRSSMSH_EN (BIT(3)) +/* BIT(2) enables the logging of push/pull data errors. */ +#define ADF_C62X_PPERR_EN (BIT(2)) + +/* Mask for VF2PF interrupts */ +#define ADF_C62X_VF2PF1_16 (0xFFFF << 9) +#define ADF_C62X_ERRSOU3_VF2PF(errsou3) (((errsou3)&0x01FFFE00) >> 9) +#define ADF_C62X_ERRMSK3_VF2PF(vf_mask) (((vf_mask)&0xFFFF) << 9) + +/* Masks for correctable error interrupts. */ +#define ADF_C62X_ERRMSK0_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_C62X_ERRMSK1_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_C62X_ERRMSK3_CERR (BIT(7)) +#define ADF_C62X_ERRMSK4_CERR (BIT(8) | BIT(0)) +#define ADF_C62X_ERRMSK5_CERR (0) + +/* Masks for uncorrectable error interrupts. */ +#define ADF_C62X_ERRMSK0_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_C62X_ERRMSK1_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_C62X_ERRMSK3_UERR \ + (BIT(8) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(0)) +#define ADF_C62X_ERRMSK4_UERR (BIT(9) | BIT(1)) +#define ADF_C62X_ERRMSK5_UERR (BIT(18) | BIT(17) | BIT(16)) + +/* RI CPP control */ +#define ADF_C62X_RICPPINTCTL (0x3A000 + 0x110) +/* + * BIT(2) enables error detection and reporting on the RI Parity Error. + * BIT(1) enables error detection and reporting on the RI CPP Pull interface. + * BIT(0) enables error detection and reporting on the RI CPP Push interface. + */ +#define ADF_C62X_RICPP_EN (BIT(2) | BIT(1) | BIT(0)) + +/* TI CPP control */ +#define ADF_C62X_TICPPINTCTL (0x3A400 + 0x138) +/* + * BIT(4) enables parity error detection and reporting on the Secure RAM. + * BIT(3) enables error detection and reporting on the ETR Parity Error. + * BIT(2) enables error detection and reporting on the TI Parity Error. + * BIT(1) enables error detection and reporting on the TI CPP Pull interface. + * BIT(0) enables error detection and reporting on the TI CPP Push interface. + */ +#define ADF_C62X_TICPP_EN (BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +/* CFC Uncorrectable Errors */ +#define ADF_C62X_CPP_CFC_ERR_CTRL (0x30000 + 0xC00) +/* + * BIT(1) enables interrupt. + * BIT(0) enables detecting and logging of push/pull data errors. + */ +#define ADF_C62X_CPP_CFC_UE (BIT(1) | BIT(0)) + +#define ADF_C62X_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i)*0x04)) +#define ADF_C62X_VINTMSK_OFFSET(i) (0x3A000 + 0x200 + ((i)*0x04)) + +/* Arbiter configuration */ +#define ADF_C62X_ARB_OFFSET 0x30000 +#define ADF_C62X_ARB_WRK_2_SER_MAP_OFFSET 0x180 +#define ADF_C62X_ARB_WQCFG_OFFSET 0x100 + +/* Admin Interface Reg Offset */ +#define ADF_C62X_ADMINMSGUR_OFFSET (0x3A000 + 0x574) +#define ADF_C62X_ADMINMSGLR_OFFSET (0x3A000 + 0x578) +#define ADF_C62X_MAILBOX_BASE_OFFSET 0x20970 + +/* Firmware Binary */ +#define ADF_C62X_FW "qat_c62x_fw" +#define ADF_C62X_MMP "qat_c62x_mmp_fw" + +void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data); +void adf_clean_hw_data_c62x(struct adf_hw_device_data *hw_data); + +#define ADF_C62X_AE_FREQ (685 * 1000000) + +#define ADF_C62X_MIN_AE_FREQ (533 * 1000000) +#define ADF_C62X_MAX_AE_FREQ (800 * 1000000) + +#define ADF_C62X_THREADS_ON_ENGINE 8 +#define ADF_C62X_MAX_SERVICES 4 +#define ADF_C62X_DEF_ASYM_MASK 0x03 + +#endif diff --git a/sys/dev/qat/qat_hw/qat_c62x/adf_drv.c b/sys/dev/qat/qat_hw/qat_c62x/adf_drv.c new file mode 100644 index 00000000000..ebeb4949a8c --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_c62x/adf_drv.c @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_c62x_hw_data.h" +#include "adf_fw_counters.h" +#include "adf_cfg_device.h" +#include +#include +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_cnvnr_freq_counters.h" + +static MALLOC_DEFINE(M_QAT_C62X, "qat_c62x", "qat_c62x"); + +#define ADF_SYSTEM_DEVICE(device_id) \ + { \ + PCI_VENDOR_ID_INTEL, device_id \ + } + +static const struct pci_device_id adf_pci_tbl[] = { ADF_SYSTEM_DEVICE( + ADF_C62X_PCI_DEVICE_ID), + { + 0, + } }; + +static int +adf_probe(device_t dev) +{ + const struct pci_device_id *id; + + for (id = adf_pci_tbl; id->vendor != 0; id++) { + if (pci_get_vendor(dev) == id->vendor && + pci_get_device(dev) == id->device) { + device_set_desc(dev, + "Intel " ADF_C62X_DEVICE_NAME + " QuickAssist"); + return BUS_PROBE_GENERIC; + } + } + return ENXIO; +} + +static void +adf_cleanup_accel(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; + int i; + + if (accel_dev->dma_tag) + bus_dma_tag_destroy(accel_dev->dma_tag); + for (i = 0; i < ADF_PCI_MAX_BARS; i++) { + struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; + + if (bar->virt_addr) + bus_free_resource(accel_pci_dev->pci_dev, + SYS_RES_MEMORY, + bar->virt_addr); + } + + if (accel_dev->hw_device) { + switch (pci_get_device(accel_pci_dev->pci_dev)) { + case ADF_C62X_PCI_DEVICE_ID: + adf_clean_hw_data_c62x(accel_dev->hw_device); + break; + default: + break; + } + free(accel_dev->hw_device, M_QAT_C62X); + accel_dev->hw_device = NULL; + } + adf_cfg_dev_remove(accel_dev); + adf_devmgr_rm_dev(accel_dev, NULL); +} + +static int +adf_attach(device_t dev) +{ + struct adf_accel_dev *accel_dev; + struct adf_accel_pci *accel_pci_dev; + struct adf_hw_device_data *hw_data; + unsigned int i, bar_nr; + int ret, rid; + struct adf_cfg_device *cfg_dev = NULL; + + /* Set pci MaxPayLoad to 256. Implemented to avoid the issue of + * Pci-passthrough causing Maxpayload to be reset to 128 bytes + * when the device is reset. */ + if (pci_get_max_payload(dev) != 256) + pci_set_max_payload(dev, 256); + + accel_dev = device_get_softc(dev); + + INIT_LIST_HEAD(&accel_dev->crypto_list); + accel_pci_dev = &accel_dev->accel_pci_dev; + accel_pci_dev->pci_dev = dev; + + if (bus_get_domain(dev, &accel_pci_dev->node) != 0) + accel_pci_dev->node = 0; + + /* XXX: Revisit if we actually need a devmgr table at all. */ + + /* Add accel device to accel table. + * This should be called before adf_cleanup_accel is called */ + if (adf_devmgr_add_dev(accel_dev, NULL)) { + device_printf(dev, "Failed to add new accelerator device.\n"); + return ENXIO; + } + + /* Allocate and configure device configuration structure */ + hw_data = malloc(sizeof(*hw_data), M_QAT_C62X, M_WAITOK | M_ZERO); + + accel_dev->hw_device = hw_data; + adf_init_hw_data_c62x(accel_dev->hw_device); + accel_pci_dev->revid = pci_get_revid(dev); + hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4); + if (accel_pci_dev->revid == 0x00) { + device_printf(dev, "A0 stepping is not supported.\n"); + ret = ENODEV; + goto out_err; + } + + /* Get PPAERUCM values and store */ + ret = adf_aer_store_ppaerucm_reg(dev, hw_data); + if (ret) + goto out_err; + + /* Get Accelerators and Accelerators Engines masks */ + hw_data->accel_mask = hw_data->get_accel_mask(accel_dev); + hw_data->ae_mask = hw_data->get_ae_mask(accel_dev); + accel_pci_dev->sku = hw_data->get_sku(hw_data); + /* If the device has no acceleration engines then ignore it. */ + if (!hw_data->accel_mask || !hw_data->ae_mask || + ((~hw_data->ae_mask) & 0x01)) { + device_printf(dev, "No acceleration units found\n"); + ret = ENXIO; + goto out_err; + } + + /* Create device configuration table */ + ret = adf_cfg_dev_add(accel_dev); + if (ret) + goto out_err; + + ret = adf_clock_debugfs_add(accel_dev); + if (ret) + goto out_err; + + pci_set_max_read_req(dev, 1024); + + ret = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, + NULL, + BUS_SPACE_MAXSIZE, + /* BUS_SPACE_UNRESTRICTED */ 1, + BUS_SPACE_MAXSIZE, + 0, + NULL, + NULL, + &accel_dev->dma_tag); + if (ret) + goto out_err; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + /* Find and map all the device's BARS */ + i = (hw_data->fuses & ADF_DEVICE_FUSECTL_MASK) ? 1 : 0; + for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0; + bar_nr++) { + struct adf_bar *bar; + + /* + * XXX: This isn't quite right as it will ignore a BAR + * that wasn't assigned a valid resource range by the + * firmware. + */ + rid = PCIR_BAR(bar_nr); + if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0) + continue; + bar = &accel_pci_dev->pci_bars[i++]; + bar->virt_addr = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, + &rid, + RF_ACTIVE); + + if (bar->virt_addr == NULL) { + device_printf(dev, "Failed to map BAR %d\n", bar_nr); + ret = ENXIO; + goto out_err; + } + bar->base_addr = rman_get_start(bar->virt_addr); + bar->size = rman_get_size(bar->virt_addr); + } + pci_enable_busmaster(dev); + + if (!accel_dev->hw_device->config_device) { + ret = EFAULT; + goto out_err; + } + + ret = accel_dev->hw_device->config_device(accel_dev); + if (ret) + goto out_err; + + ret = adf_dev_init(accel_dev); + if (ret) + goto out_dev_shutdown; + + ret = adf_dev_start(accel_dev); + if (ret) + goto out_dev_stop; + + cfg_dev = accel_dev->cfg->dev; + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + return ret; +out_dev_stop: + adf_dev_stop(accel_dev); +out_dev_shutdown: + adf_dev_shutdown(accel_dev); +out_err: + adf_cleanup_accel(accel_dev); + return ret; +} + +static int +adf_detach(device_t dev) +{ + struct adf_accel_dev *accel_dev = device_get_softc(dev); + + if (adf_dev_stop(accel_dev)) { + device_printf(dev, "Failed to stop QAT accel dev\n"); + return EBUSY; + } + + adf_dev_shutdown(accel_dev); + + adf_cleanup_accel(accel_dev); + + return 0; +} + +static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe), + DEVMETHOD(device_attach, adf_attach), + DEVMETHOD(device_detach, adf_detach), + + DEVMETHOD_END }; + +static driver_t adf_driver = { "qat", + adf_methods, + sizeof(struct adf_accel_dev) }; + +DRIVER_MODULE_ORDERED(qat_c62x, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD); +MODULE_VERSION(qat_c62x, 1); +MODULE_DEPEND(qat_c62x, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_c62x, qat_api, 1, 1, 1); +MODULE_DEPEND(qat_c62x, linuxkpi, 1, 1, 1); diff --git a/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.c b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.c new file mode 100644 index 00000000000..44dde075079 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.c @@ -0,0 +1,405 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include +#include +#include +#include +#include "adf_dh895xcc_hw_data.h" +#include "icp_qat_hw.h" +#include "adf_heartbeat.h" + +/* Worker thread to service arbiter mappings based on dev SKUs */ +static const u32 thrd_to_arb_map_sku4[] = + { 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666, 0x12222AAA, 0x11222222, + 0x12222AAA, 0x11222222, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; + +static const u32 thrd_to_arb_map_sku6[] = + { 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666, 0x12222AAA, 0x11222222, + 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222 }; + +static const u32 thrd_to_arb_map_sku3[] = + { 0x00000888, 0x00000000, 0x00000888, 0x00000000, 0x00000888, 0x00000000, + 0x00000888, 0x00000000, 0x00000888, 0x00000000, 0x00000888, 0x00000000 }; + +static u32 thrd_to_arb_map_gen[ADF_DH895XCC_MAX_ACCELENGINES] = { 0 }; + +static struct adf_hw_device_class dh895xcc_class = + {.name = ADF_DH895XCC_DEVICE_NAME, .type = DEV_DH895XCC, .instances = 0 }; + +static u32 +get_accel_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fuse; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + + return (~fuse) >> ADF_DH895XCC_ACCELERATORS_REG_OFFSET & + ADF_DH895XCC_ACCELERATORS_MASK; +} + +static u32 +get_ae_mask(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 fuse; + + fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4); + + return (~fuse) & ADF_DH895XCC_ACCELENGINES_MASK; +} + +static uint32_t +get_num_accels(struct adf_hw_device_data *self) +{ + uint32_t i, ctr = 0; + + if (!self || !self->accel_mask) + return 0; + + for (i = 0; i < ADF_DH895XCC_MAX_ACCELERATORS; i++) { + if (self->accel_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static uint32_t +get_num_aes(struct adf_hw_device_data *self) +{ + uint32_t i, ctr = 0; + + if (!self || !self->ae_mask) + return 0; + + for (i = 0; i < ADF_DH895XCC_MAX_ACCELENGINES; i++) { + if (self->ae_mask & (1 << i)) + ctr++; + } + return ctr; +} + +static uint32_t +get_misc_bar_id(struct adf_hw_device_data *self) +{ + return ADF_DH895XCC_PMISC_BAR; +} + +static uint32_t +get_etr_bar_id(struct adf_hw_device_data *self) +{ + return ADF_DH895XCC_ETR_BAR; +} + +static uint32_t +get_sram_bar_id(struct adf_hw_device_data *self) +{ + return ADF_DH895XCC_SRAM_BAR; +} + +static enum dev_sku_info +get_sku(struct adf_hw_device_data *self) +{ + int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK) >> + ADF_DH895XCC_FUSECTL_SKU_SHIFT; + + switch (sku) { + case ADF_DH895XCC_FUSECTL_SKU_1: + return DEV_SKU_1; + case ADF_DH895XCC_FUSECTL_SKU_2: + return DEV_SKU_2; + case ADF_DH895XCC_FUSECTL_SKU_3: + return DEV_SKU_3; + case ADF_DH895XCC_FUSECTL_SKU_4: + return DEV_SKU_4; + default: + return DEV_SKU_UNKNOWN; + } + return DEV_SKU_UNKNOWN; +} + +static void +adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev, + u32 const **arb_map_config) +{ + switch (accel_dev->accel_pci_dev.sku) { + case DEV_SKU_1: + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map_sku4, + thrd_to_arb_map_gen, + ADF_DH895XCC_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; + break; + + case DEV_SKU_2: + case DEV_SKU_4: + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map_sku6, + thrd_to_arb_map_gen, + ADF_DH895XCC_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; + break; + + case DEV_SKU_3: + adf_cfg_gen_dispatch_arbiter(accel_dev, + thrd_to_arb_map_sku3, + thrd_to_arb_map_gen, + ADF_DH895XCC_MAX_ACCELENGINES); + *arb_map_config = thrd_to_arb_map_gen; + break; + + default: + device_printf(GET_DEV(accel_dev), + "The configuration doesn't match any SKU"); + *arb_map_config = NULL; + } +} + +static uint32_t +get_pf2vf_offset(uint32_t i) +{ + return ADF_DH895XCC_PF2VF_OFFSET(i); +} + +static uint32_t +get_vintmsk_offset(uint32_t i) +{ + return ADF_DH895XCC_VINTMSK_OFFSET(i); +} + +static void +get_arb_info(struct arb_info *arb_csrs_info) +{ + arb_csrs_info->arbiter_offset = ADF_DH895XCC_ARB_OFFSET; + arb_csrs_info->wrk_thd_2_srv_arb_map = + ADF_DH895XCC_ARB_WRK_2_SER_MAP_OFFSET; + arb_csrs_info->wrk_cfg_offset = ADF_DH895XCC_ARB_WQCFG_OFFSET; +} + +static void +get_admin_info(struct admin_info *admin_csrs_info) +{ + admin_csrs_info->mailbox_offset = ADF_DH895XCC_MAILBOX_BASE_OFFSET; + admin_csrs_info->admin_msg_ur = ADF_DH895XCC_ADMINMSGUR_OFFSET; + admin_csrs_info->admin_msg_lr = ADF_DH895XCC_ADMINMSGLR_OFFSET; +} + +static void +get_errsou_offset(u32 *errsou3, u32 *errsou5) +{ + *errsou3 = ADF_DH895XCC_ERRSOU3; + *errsou5 = ADF_DH895XCC_ERRSOU5; +} + +static u32 +get_clock_speed(struct adf_hw_device_data *self) +{ + /* CPP clock is half high-speed clock */ + return self->clock_frequency / 2; +} + +static void +adf_enable_error_correction(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR]; + struct resource *csr = misc_bar->virt_addr; + unsigned int val, i; + unsigned int mask; + + /* Enable Accel Engine error detection & correction */ + mask = hw_device->ae_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_CTX_ENABLES(i)); + val |= ADF_DH895XCC_ENABLE_AE_ECC_ERR; + ADF_CSR_WR(csr, ADF_DH895XCC_AE_CTX_ENABLES(i), val); + val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_MISC_CONTROL(i)); + val |= ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR; + ADF_CSR_WR(csr, ADF_DH895XCC_AE_MISC_CONTROL(i), val); + } + + /* Enable shared memory error detection & correction */ + mask = hw_device->accel_mask; + for (i = 0; mask; i++, mask >>= 1) { + if (!(mask & 1)) + continue; + val = ADF_CSR_RD(csr, ADF_DH895XCC_UERRSSMSH(i)); + val |= ADF_DH895XCC_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_DH895XCC_UERRSSMSH(i), val); + val = ADF_CSR_RD(csr, ADF_DH895XCC_CERRSSMSH(i)); + val |= ADF_DH895XCC_ERRSSMSH_EN; + ADF_CSR_WR(csr, ADF_DH895XCC_CERRSSMSH(i), val); + } +} + +static void +adf_enable_ints(struct adf_accel_dev *accel_dev) +{ + struct resource *addr; + + addr = (&GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR])->virt_addr; + + /* Enable bundle and misc interrupts */ + ADF_CSR_WR(addr, + ADF_DH895XCC_SMIAPF0_MASK_OFFSET, + accel_dev->u1.pf.vf_info ? + 0 : + (1ULL << GET_MAX_BANKS(accel_dev)) - 1); + ADF_CSR_WR(addr, + ADF_DH895XCC_SMIAPF1_MASK_OFFSET, + ADF_DH895XCC_SMIA1_MASK); +} + +static u32 +get_ae_clock(struct adf_hw_device_data *self) +{ + /* + * Clock update interval is <16> ticks for dh895xcc. + */ + return self->clock_frequency / 16; +} + +static int +get_storage_enabled(struct adf_accel_dev *accel_dev, u32 *storage_enabled) +{ + char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; + char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + strlcpy(key, ADF_STORAGE_FIRMWARE_ENABLED, sizeof(key)); + if (!adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) { + if (kstrtouint(val, 0, storage_enabled)) + return -EFAULT; + } + return 0; +} + +static u32 +dh895xcc_get_hw_cap(struct adf_accel_dev *accel_dev) +{ + device_t pdev = accel_dev->accel_pci_dev.pci_dev; + u32 legfuses; + u32 capabilities; + + /* Read accelerator capabilities mask */ + legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4); + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC + + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC + + ICP_ACCEL_CAPABILITIES_CIPHER + + ICP_ACCEL_CAPABILITIES_AUTHENTICATION + + ICP_ACCEL_CAPABILITIES_COMPRESSION + ICP_ACCEL_CAPABILITIES_RAND + + ICP_ACCEL_CAPABILITIES_HKDF + ICP_ACCEL_CAPABILITIES_ECEDMONT + + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN; + + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_HKDF | + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN); + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) + capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_ECEDMONT); + if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) + capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; + + return capabilities; +} + +static const char * +get_obj_name(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services service) +{ + return ADF_DH895XCC_AE_FW_NAME_CUSTOM1; +} + +static u32 +get_objs_num(struct adf_accel_dev *accel_dev) +{ + return 1; +} + +static u32 +get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev, + enum adf_accel_unit_services services) +{ + return accel_dev->hw_device->ae_mask; +} + +void +adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class = &dh895xcc_class; + hw_data->instance_id = dh895xcc_class.instances++; + hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS; + hw_data->num_rings_per_bank = ADF_ETR_MAX_RINGS_PER_BANK; + hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS; + hw_data->num_logical_accel = 1; + hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES; + hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET; + hw_data->tx_rings_mask = ADF_DH895XCC_TX_RINGS_MASK; + hw_data->alloc_irq = adf_isr_resource_alloc; + hw_data->free_irq = adf_isr_resource_free; + hw_data->enable_error_correction = adf_enable_error_correction; + hw_data->print_err_registers = adf_print_err_registers; + hw_data->get_accel_mask = get_accel_mask; + hw_data->get_ae_mask = get_ae_mask; + hw_data->get_num_accels = get_num_accels; + hw_data->get_num_aes = get_num_aes; + hw_data->get_etr_bar_id = get_etr_bar_id; + hw_data->get_misc_bar_id = get_misc_bar_id; + hw_data->get_pf2vf_offset = get_pf2vf_offset; + hw_data->get_vintmsk_offset = get_vintmsk_offset; + hw_data->get_arb_info = get_arb_info; + hw_data->get_admin_info = get_admin_info; + hw_data->get_errsou_offset = get_errsou_offset; + hw_data->get_clock_speed = get_clock_speed; + hw_data->get_sram_bar_id = get_sram_bar_id; + hw_data->get_sku = get_sku; + hw_data->fw_name = ADF_DH895XCC_FW; + hw_data->fw_mmp_name = ADF_DH895XCC_MMP; + hw_data->init_admin_comms = adf_init_admin_comms; + hw_data->exit_admin_comms = adf_exit_admin_comms; + hw_data->disable_iov = adf_disable_sriov; + hw_data->send_admin_init = adf_send_admin_init; + hw_data->init_arb = adf_init_gen2_arb; + hw_data->exit_arb = adf_exit_arb; + hw_data->get_arb_mapping = adf_get_arbiter_mapping; + hw_data->enable_ints = adf_enable_ints; + hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms; + hw_data->disable_vf2pf_comms = adf_pf_disable_vf2pf_comms; + hw_data->reset_device = adf_reset_sbr; + hw_data->restore_device = adf_dev_restore; + hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION; + hw_data->get_accel_cap = dh895xcc_get_hw_cap; + hw_data->get_heartbeat_status = adf_get_heartbeat_status; + hw_data->get_ae_clock = get_ae_clock; + hw_data->get_objs_num = get_objs_num; + hw_data->get_obj_name = get_obj_name; + hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask; + hw_data->clock_frequency = ADF_DH895XCC_AE_FREQ; + hw_data->extended_dc_capabilities = 0; + hw_data->get_storage_enabled = get_storage_enabled; + hw_data->query_storage_cap = 1; + hw_data->get_heartbeat_status = adf_get_heartbeat_status; + hw_data->get_ae_clock = get_ae_clock; + hw_data->storage_enable = 0; + hw_data->get_fw_image_type = adf_cfg_get_fw_image_type; + hw_data->config_device = adf_config_device; + hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled; + hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask; + hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP; + hw_data->pre_reset = adf_dev_pre_reset; + hw_data->post_reset = adf_dev_post_reset; +} + +void +adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) +{ + hw_data->dev_class->instances--; +} diff --git a/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.h b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.h new file mode 100644 index 00000000000..e193c044c04 --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_dh895xcc_hw_data.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef ADF_DH895x_HW_DATA_H_ +#define ADF_DH895x_HW_DATA_H_ + +/* PCIe configuration space */ +#define ADF_DH895XCC_SRAM_BAR 0 +#define ADF_DH895XCC_PMISC_BAR 1 +#define ADF_DH895XCC_ETR_BAR 2 +#define ADF_DH895XCC_RX_RINGS_OFFSET 8 +#define ADF_DH895XCC_TX_RINGS_MASK 0xFF +#define ADF_DH895XCC_FUSECTL_SKU_MASK 0x300000 +#define ADF_DH895XCC_FUSECTL_SKU_SHIFT 20 +#define ADF_DH895XCC_FUSECTL_SKU_1 0x0 +#define ADF_DH895XCC_FUSECTL_SKU_2 0x1 +#define ADF_DH895XCC_FUSECTL_SKU_3 0x2 +#define ADF_DH895XCC_FUSECTL_SKU_4 0x3 +#define ADF_DH895XCC_MAX_ACCELERATORS 6 +#define ADF_DH895XCC_MAX_ACCELENGINES 12 +#define ADF_DH895XCC_ACCELERATORS_REG_OFFSET 13 +#define ADF_DH895XCC_ACCELERATORS_MASK 0x3F +#define ADF_DH895XCC_ACCELENGINES_MASK 0xFFF +#define ADF_DH895XCC_ETR_MAX_BANKS 32 +#define ADF_DH895XCC_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) +#define ADF_DH895XCC_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) +#define ADF_DH895XCC_SMIA0_MASK 0xFFFFFFFF +#define ADF_DH895XCC_SMIA1_MASK 0x1 +/* Error detection and correction */ +#define ADF_DH895XCC_AE_CTX_ENABLES(i) (i * 0x1000 + 0x20818) +#define ADF_DH895XCC_AE_MISC_CONTROL(i) (i * 0x1000 + 0x20960) +#define ADF_DH895XCC_ENABLE_AE_ECC_ERR BIT(28) +#define ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR (BIT(24) | BIT(12)) +#define ADF_DH895XCC_UERRSSMSH(i) (i * 0x4000 + 0x18) +#define ADF_DH895XCC_CERRSSMSH(i) (i * 0x4000 + 0x10) +#define ADF_DH895XCC_ERRSSMSH_EN BIT(3) +#define ADF_DH895XCC_ERRSOU3 (0x3A000 + 0x0C) +#define ADF_DH895XCC_ERRSOU5 (0x3A000 + 0xD8) +/* BIT(2) enables the logging of push/pull data errors. */ +#define ADF_DH895XCC_PPERR_EN (BIT(2)) + +/* Masks for VF2PF interrupts */ +#define ADF_DH895XCC_VF2PF1_16 (0xFFFF << 9) +#define ADF_DH895XCC_VF2PF17_32 (0xFFFF) +#define ADF_DH895XCC_ERRSOU3_VF2PF_L(errsou3) (((errsou3)&0x01FFFE00) >> 9) +#define ADF_DH895XCC_ERRSOU5_VF2PF_U(errsou5) (((errsou5)&0x0000FFFF) << 16) +#define ADF_DH895XCC_ERRMSK3_VF2PF_L(vf_mask) (((vf_mask)&0xFFFF) << 9) +#define ADF_DH895XCC_ERRMSK5_VF2PF_U(vf_mask) ((vf_mask) >> 16) + +/* Masks for correctable error interrupts. */ +#define ADF_DH895XCC_ERRMSK0_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_DH895XCC_ERRMSK1_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_DH895XCC_ERRMSK3_CERR (BIT(7)) +#define ADF_DH895XCC_ERRMSK4_CERR (BIT(24) | BIT(16) | BIT(8) | BIT(0)) +#define ADF_DH895XCC_ERRMSK5_CERR (0) + +/* Masks for uncorrectable error interrupts. */ +#define ADF_DH895XCC_ERRMSK0_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_DH895XCC_ERRMSK1_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_DH895XCC_ERRMSK3_UERR \ + (BIT(8) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(0)) +#define ADF_DH895XCC_ERRMSK4_UERR (BIT(25) | BIT(17) | BIT(9) | BIT(1)) +#define ADF_DH895XCC_ERRMSK5_UERR (BIT(19) | BIT(18) | BIT(17) | BIT(16)) + +/* RI CPP control */ +#define ADF_DH895XCC_RICPPINTCTL (0x3A000 + 0x110) +/* + * BIT(1) enables error detection and reporting on the RI CPP Pull interface. + * BIT(0) enables error detection and reporting on the RI CPP Push interface. + */ +#define ADF_DH895XCC_RICPP_EN (BIT(1) | BIT(0)) + +/* TI CPP control */ +#define ADF_DH895XCC_TICPPINTCTL (0x3A400 + 0x138) +/* + * BIT(1) enables error detection and reporting on the TI CPP Pull interface. + * BIT(0) enables error detection and reporting on the TI CPP Push interface. + */ +#define ADF_DH895XCC_TICPP_EN (BIT(1) | BIT(0)) + +/* CFC Uncorrectable Errors */ +#define ADF_DH895XCC_CPP_SHAC_ERR_CTRL (0x30000 + 0xC00) +/* + * BIT(1) enables interrupt. + * BIT(0) enables detecting and logging of push/pull data errors. + */ +#define ADF_DH895XCC_CPP_SHAC_UE (BIT(1) | BIT(0)) + +/* Correctable SecureRAM Error Reg */ +#define ADF_DH895XCC_ESRAMCERR (0x3AC00 + 0x00) +/* BIT(3) enables fixing and logging of correctable errors. */ +#define ADF_DH895XCC_ESRAM_CERR (BIT(3)) + +/* Uncorrectable SecureRAM Error Reg */ +#define ADF_DH895XCC_ESRAMUERR (ADF_SECRAMUERR) +/* + * BIT(17) enables interrupt. + * BIT(3) enables detecting and logging of uncorrectable errors. + */ +#define ADF_DH895XCC_ESRAM_UERR (BIT(17) | BIT(3)) + +/* Miscellaneous Memory Target Errors Register */ +/* + * BIT(3) enables detecting and logging push/pull data errors. + * BIT(2) enables interrupt. + */ +#define ADF_DH895XCC_TGT_UERR (BIT(3) | BIT(2)) + +#define ADF_DH895XCC_SLICEPWRDOWN(i) ((i)*0x4000 + 0x2C) +/* Enabling PKE4-PKE0. */ +#define ADF_DH895XCC_MMP_PWR_UP_MSK (BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3)) + +/* CPM Uncorrectable Errors */ +#define ADF_DH895XCC_INTMASKSSM(i) ((i)*0x4000 + 0x0) +/* Disabling interrupts for correctable errors. */ +#define ADF_DH895XCC_INTMASKSSM_UERR \ + (BIT(11) | BIT(9) | BIT(7) | BIT(5) | BIT(3) | BIT(1)) + +/* MMP */ +/* BIT(3) enables correction. */ +#define ADF_DH895XCC_CERRSSMMMP_EN (BIT(3)) + +/* BIT(3) enables logging. */ +#define ADF_DH895XCC_UERRSSMMMP_EN (BIT(3)) + +#define ADF_DH895XCC_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i)*0x04)) +#define ADF_DH895XCC_VINTMSK_OFFSET(i) (0x3A000 + 0x200 + ((i)*0x04)) + +/* Arbiter configuration */ +#define ADF_DH895XCC_ARB_OFFSET 0x30000 +#define ADF_DH895XCC_ARB_WRK_2_SER_MAP_OFFSET 0x180 +#define ADF_DH895XCC_ARB_WQCFG_OFFSET 0x100 + +/* Admin Interface Reg Offset */ +#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574) +#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578) +#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970 + +/* FW names */ +#define ADF_DH895XCC_FW "qat_dh895xcc_fw" +#define ADF_DH895XCC_MMP "qat_dh895xcc_mmp_fw" + +void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data); +void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data); +#define ADF_DH895XCC_AE_FREQ (933 * 1000000) +#endif diff --git a/sys/dev/qat/qat_hw/qat_dh895xcc/adf_drv.c b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_drv.c new file mode 100644 index 00000000000..2ddff279e4e --- /dev/null +++ b/sys/dev/qat/qat_hw/qat_dh895xcc/adf_drv.c @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#include "qat_freebsd.h" +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_accel_devices.h" +#include "adf_dh895xcc_hw_data.h" +#include "adf_fw_counters.h" +#include "adf_cfg_device.h" +#include +#include +#include +#include +#include +#include "adf_heartbeat_dbg.h" +#include "adf_cnvnr_freq_counters.h" + +static MALLOC_DEFINE(M_QAT_DH895XCC, "qat_dh895xcc", "qat_dh895xcc"); + +#define ADF_SYSTEM_DEVICE(device_id) \ + { \ + PCI_VENDOR_ID_INTEL, device_id \ + } + +static const struct pci_device_id adf_pci_tbl[] = + { ADF_SYSTEM_DEVICE(ADF_DH895XCC_PCI_DEVICE_ID), + { + 0, + } }; + +static int +adf_probe(device_t dev) +{ + const struct pci_device_id *id; + + for (id = adf_pci_tbl; id->vendor != 0; id++) { + if (pci_get_vendor(dev) == id->vendor && + pci_get_device(dev) == id->device) { + device_set_desc(dev, + "Intel " ADF_DH895XCC_DEVICE_NAME + " QuickAssist"); + return BUS_PROBE_DEFAULT; + } + } + return ENXIO; +} + +static void +adf_cleanup_accel(struct adf_accel_dev *accel_dev) +{ + struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev; + int i; + + if (accel_dev->dma_tag) + bus_dma_tag_destroy(accel_dev->dma_tag); + for (i = 0; i < ADF_PCI_MAX_BARS; i++) { + struct adf_bar *bar = &accel_pci_dev->pci_bars[i]; + + if (bar->virt_addr) + bus_free_resource(accel_pci_dev->pci_dev, + SYS_RES_MEMORY, + bar->virt_addr); + } + + if (accel_dev->hw_device) { + switch (pci_get_device(accel_pci_dev->pci_dev)) { + case ADF_DH895XCC_PCI_DEVICE_ID: + adf_clean_hw_data_dh895xcc(accel_dev->hw_device); + break; + default: + break; + } + free(accel_dev->hw_device, M_QAT_DH895XCC); + accel_dev->hw_device = NULL; + } + adf_cfg_dev_remove(accel_dev); + adf_devmgr_rm_dev(accel_dev, NULL); +} + +static int +adf_attach(device_t dev) +{ + struct adf_accel_dev *accel_dev; + struct adf_accel_pci *accel_pci_dev; + struct adf_hw_device_data *hw_data; + unsigned int i, bar_nr; + int ret, rid; + struct adf_cfg_device *cfg_dev = NULL; + + /* Set pci MaxPayLoad to 256. Implemented to avoid the issue of + * Pci-passthrough causing Maxpayload to be reset to 128 bytes + * when the device is reset. */ + if (pci_get_max_payload(dev) != 256) + pci_set_max_payload(dev, 256); + + accel_dev = device_get_softc(dev); + + INIT_LIST_HEAD(&accel_dev->crypto_list); + accel_pci_dev = &accel_dev->accel_pci_dev; + accel_pci_dev->pci_dev = dev; + + if (bus_get_domain(dev, &accel_pci_dev->node) != 0) + accel_pci_dev->node = 0; + + /* Add accel device to accel table. + * This should be called before adf_cleanup_accel is called */ + if (adf_devmgr_add_dev(accel_dev, NULL)) { + device_printf(dev, "Failed to add new accelerator device.\n"); + return ENXIO; + } + + /* Allocate and configure device configuration structure */ + hw_data = malloc(sizeof(*hw_data), M_QAT_DH895XCC, M_WAITOK | M_ZERO); + + accel_dev->hw_device = hw_data; + adf_init_hw_data_dh895xcc(accel_dev->hw_device); + accel_pci_dev->revid = pci_get_revid(dev); + hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4); + + /* Get PPAERUCM values and store */ + ret = adf_aer_store_ppaerucm_reg(dev, hw_data); + if (ret) + goto out_err; + + /* Get Accelerators and Accelerators Engines masks */ + hw_data->accel_mask = hw_data->get_accel_mask(accel_dev); + hw_data->ae_mask = hw_data->get_ae_mask(accel_dev); + accel_pci_dev->sku = hw_data->get_sku(hw_data); + /* If the device has no acceleration engines then ignore it. */ + if (!hw_data->accel_mask || !hw_data->ae_mask || + ((~hw_data->ae_mask) & 0x01)) { + device_printf(dev, "No acceleration units found\n"); + ret = ENXIO; + goto out_err; + } + + /* Create device configuration table */ + ret = adf_cfg_dev_add(accel_dev); + if (ret) + goto out_err; + + pci_set_max_read_req(dev, 1024); + + ret = bus_dma_tag_create(bus_get_dma_tag(dev), + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, + NULL, + BUS_SPACE_MAXSIZE, + /* BUS_SPACE_UNRESTRICTED */ 1, + BUS_SPACE_MAXSIZE, + 0, + NULL, + NULL, + &accel_dev->dma_tag); + if (ret) + goto out_err; + + if (hw_data->get_accel_cap) { + hw_data->accel_capabilities_mask = + hw_data->get_accel_cap(accel_dev); + } + + /* Find and map all the device's BARS */ + i = 0; + for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0; + bar_nr++) { + struct adf_bar *bar; + + /* + * This will ignore a BAR + * that wasn't assigned a valid resource range by the + * firmware. + */ + rid = PCIR_BAR(bar_nr); + if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0) + continue; + bar = &accel_pci_dev->pci_bars[i++]; + bar->virt_addr = bus_alloc_resource_any(dev, + SYS_RES_MEMORY, + &rid, + RF_ACTIVE); + if (bar->virt_addr == NULL) { + device_printf(dev, "Failed to map BAR %d\n", bar_nr); + ret = ENXIO; + goto out_err; + } + bar->base_addr = rman_get_start(bar->virt_addr); + bar->size = rman_get_size(bar->virt_addr); + } + pci_enable_busmaster(dev); + + if (!accel_dev->hw_device->config_device) { + ret = EFAULT; + goto out_err; + } + + ret = accel_dev->hw_device->config_device(accel_dev); + if (ret) + goto out_err; + + ret = adf_dev_init(accel_dev); + if (ret) + goto out_dev_shutdown; + + ret = adf_dev_start(accel_dev); + if (ret) + goto out_dev_stop; + + cfg_dev = accel_dev->cfg->dev; + adf_cfg_device_clear(cfg_dev, accel_dev); + free(cfg_dev, M_QAT); + accel_dev->cfg->dev = NULL; + return ret; +out_dev_stop: + adf_dev_stop(accel_dev); +out_dev_shutdown: + adf_dev_shutdown(accel_dev); +out_err: + adf_cleanup_accel(accel_dev); + return ret; +} + +static int +adf_detach(device_t dev) +{ + struct adf_accel_dev *accel_dev = device_get_softc(dev); + + if (adf_dev_stop(accel_dev)) { + device_printf(dev, "Failed to stop QAT accel dev\n"); + return EBUSY; + } + + adf_dev_shutdown(accel_dev); + + adf_cleanup_accel(accel_dev); + return 0; +} + +static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe), + DEVMETHOD(device_attach, adf_attach), + DEVMETHOD(device_detach, adf_detach), + + DEVMETHOD_END }; + +static driver_t adf_driver = { "qat", + adf_methods, + sizeof(struct adf_accel_dev) }; + +DRIVER_MODULE_ORDERED(qat_dh895xcc, + pci, + adf_driver, + NULL, + NULL, + SI_ORDER_THIRD); +MODULE_VERSION(qat_dh895xcc, 1); +MODULE_DEPEND(qat_dh895xcc, qat_common, 1, 1, 1); +MODULE_DEPEND(qat_dh895xcc, qat_api, 1, 1, 1); +MODULE_DEPEND(qat_dh895xcc, linuxkpi, 1, 1, 1); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 74dab4e6fa6..f460a102b20 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -307,6 +307,7 @@ SUBDIR= \ pty \ puc \ pwm \ + ${_qat} \ ${_qat_c2xxx} \ ${_qatfw} \ ${_qlxge} \ @@ -681,6 +682,7 @@ _mgb= mgb _nctgpio= nctgpio _ntb= ntb _ocs_fc= ocs_fc +_qat= qat _qat_c2xxx= qat_c2xxx _qatfw= qatfw .if ${MK_OFED} != "no" || defined(ALL_MODULES) diff --git a/sys/modules/qat/Makefile b/sys/modules/qat/Makefile new file mode 100644 index 00000000000..52fe5623b06 --- /dev/null +++ b/sys/modules/qat/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +SUBDIR= qat_common \ + qat_api \ + qat_hw \ + qat + +.include diff --git a/sys/modules/qat/qat/Makefile b/sys/modules/qat/qat/Makefile new file mode 100644 index 00000000000..7973faa2c4c --- /dev/null +++ b/sys/modules/qat/qat/Makefile @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/dev/qat/qat + +KMOD= qat +SRCS+= qat_ocf.c qat_ocf_mem_pool.c qat_ocf_utils.c +SRCS+= device_if.h bus_if.h vnode_if.h pci_if.h cryptodev_if.h + +CFLAGS+= -I${SYSDIR}/compat/linuxkpi/common/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include/common +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include/lac +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_utils/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_direct/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/firmware/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/crypto/sym/include + +CWARNFLAGS.qat_ocf.c += -Wno-incompatible-pointer-types-discards-qualifiers +CWARNFLAGS.qat_ocf_utils.c += -Wno-incompatible-pointer-types-discards-qualifiers + +.include diff --git a/sys/modules/qat/qat_api/Makefile b/sys/modules/qat/qat_api/Makefile new file mode 100644 index 00000000000..5dd4bc25285 --- /dev/null +++ b/sys/modules/qat/qat_api/Makefile @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/dev/qat/qat_api + +KMOD= qat_api + +SRCS+= freebsd_module.c +SRCS+= common/compression/dc_datapath.c +SRCS+= common/compression/dc_header_footer.c +SRCS+= common/compression/dc_session.c +SRCS+= common/compression/dc_stats.c +SRCS+= common/compression/dc_buffers.c +SRCS+= common/compression/dc_dp.c +SRCS+= common/compression/icp_sal_dc_err.c +SRCS+= common/utils/lac_buffer_desc.c +SRCS+= common/utils/lac_mem.c +SRCS+= common/utils/lac_mem_pools.c +SRCS+= common/utils/lac_sync.c +SRCS+= common/utils/sal_service_state.c +SRCS+= common/utils/sal_statistics.c +SRCS+= common/utils/sal_string_parse.c +SRCS+= common/utils/sal_versions.c +SRCS+= common/utils/sal_user_process.c +SRCS+= common/ctrl/sal_list.c +SRCS+= common/ctrl/sal_compression.c +SRCS+= common/ctrl/sal_ctrl_services.c +SRCS+= common/ctrl/sal_create_services.c +SRCS+= common/ctrl/sal_crypto.c +SRCS+= common/qat_comms/sal_qat_cmn_msg.c +SRCS+= common/crypto/sym/lac_sym_api.c +SRCS+= common/crypto/sym/lac_sym_cb.c +SRCS+= common/crypto/sym/lac_sym_queue.c +SRCS+= common/crypto/sym/lac_sym_cipher.c +SRCS+= common/crypto/sym/lac_sym_alg_chain.c +SRCS+= common/crypto/sym/lac_sym_auth_enc.c +SRCS+= common/crypto/sym/lac_sym_hash.c +SRCS+= common/crypto/sym/lac_sym_hash_sw_precomputes.c +SRCS+= common/crypto/sym/lac_sym_stats.c +SRCS+= common/crypto/sym/lac_sym_compile_check.c +SRCS+= common/crypto/sym/lac_sym_partial.c +SRCS+= common/crypto/sym/lac_sym_dp.c +SRCS+= common/crypto/sym/qat/lac_sym_qat.c +SRCS+= common/crypto/sym/qat/lac_sym_qat_hash.c +SRCS+= common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c +SRCS+= common/crypto/sym/qat/lac_sym_qat_cipher.c +SRCS+= common/crypto/sym/qat/lac_sym_qat_key.c +SRCS+= common/crypto/sym/key/lac_sym_key.c +SRCS+= common/stubs/lac_stubs.c +SRCS+= device/dev_info.c +SRCS+= qat_kernel/src/lac_adf_interface_freebsd.c +SRCS+= qat_kernel/src/qat_transport.c +SRCS+= qat_kernel/src/lac_symbols.c +SRCS+= qat_utils/src/QatUtilsServices.c +SRCS+= qat_utils/src/QatUtilsSemaphore.c +SRCS+= qat_utils/src/QatUtilsSpinLock.c +SRCS+= qat_utils/src/QatUtilsAtomic.c +SRCS+= qat_utils/src/QatUtilsCrypto.c +SRCS+= bus_if.h cryptodev_if.h device_if.h pci_if.h vnode_if.h + +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include/lac +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include/dc +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_direct/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_kernel/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_utils/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/compression/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/crypto/sym/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/firmware/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include/common +CFLAGS+= -I${SYSDIR}/compat/linuxkpi/common/include + +CWARNFLAGS += -Wno-pointer-sign +.include diff --git a/sys/modules/qat/qat_common/Makefile b/sys/modules/qat/qat_common/Makefile new file mode 100644 index 00000000000..a2ea45fb684 --- /dev/null +++ b/sys/modules/qat/qat_common/Makefile @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/dev/qat/qat_common + +KMOD= qat_common + +SRCS+= adf_accel_engine.c adf_freebsd_admin.c adf_aer.c adf_cfg.c qat_common_module.c +SRCS+= adf_heartbeat.c adf_freebsd_heartbeat_dbg.c +SRCS+= adf_dev_mgr.c adf_hw_arbiter.c +SRCS+= adf_init.c adf_transport.c adf_isr.c adf_fw_counters.c adf_dev_err.c +SRCS+= qat_freebsd.c +SRCS+= adf_freebsd_cfg_dev_dbg.c adf_freebsd_ver_dbg.c +SRCS+= adf_cfg_device.c adf_cfg_section.c adf_cfg_instance.c adf_cfg_bundle.c +SRCS+= qat_hal.c qat_uclo.c +SRCS+= adf_vf_isr.c adf_pf2vf_msg.c +SRCS+= adf_vf2pf_msg.c +SRCS+= adf_pf2vf_capabilities.c +SRCS+= adf_pf2vf_ring_to_svc_map.c +SRCS+= adf_freebsd_transport_debug.c adf_clock.c +SRCS+= adf_freebsd_cnvnr_ctrs_dbg.c +SRCS+= adf_freebsd_pfvf_ctrs_dbg.c +SRCS+= bus_if.h device_if.h pci_if.h vnode_if.h + +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include/common +CFLAGS+= -I${SYSDIR}/compat/linuxkpi/common/include + +.include diff --git a/sys/modules/qat/qat_hw/Makefile b/sys/modules/qat/qat_hw/Makefile new file mode 100644 index 00000000000..813f894757a --- /dev/null +++ b/sys/modules/qat/qat_hw/Makefile @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/dev/qat/qat_hw + +KMOD= qat_hw +SRCS+= qat_c62x/adf_c62x_hw_data.c qat_c62x/adf_drv.c +SRCS+= qat_200xx/adf_200xx_hw_data.c qat_200xx/adf_drv.c +SRCS+= qat_c3xxx/adf_c3xxx_hw_data.c qat_c3xxx/adf_drv.c +SRCS+= qat_dh895xcc/adf_dh895xcc_hw_data.c qat_dh895xcc/adf_drv.c +SRCS+= qat_c4xxx/adf_c4xxx_hw_data.c qat_c4xxx/adf_drv.c qat_c4xxx/adf_c4xxx_ae_config.c qat_c4xxx/adf_c4xxx_misc_error_stats.c +SRCS+= qat_c4xxx/adf_c4xxx_pke_replay_stats.c qat_c4xxx/adf_c4xxx_ras.c qat_c4xxx/adf_c4xxx_res_part.c +SRCS+= qat_c4xxx/adf_c4xxx_reset.c +SRCS+= device_if.h bus_if.h vnode_if.h pci_if.h cryptodev_if.h + +CFLAGS+= -I${SYSDIR}/compat/linuxkpi/common/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/include/common +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/include/lac +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_utils/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/qat_direct/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/firmware/include +CFLAGS+= -I${SRCTOP}/sys/dev/qat/qat_api/common/crypto/sym/include + +.include diff --git a/sys/modules/qatfw/Makefile b/sys/modules/qatfw/Makefile index e043fd390d2..098771477ba 100644 --- a/sys/modules/qatfw/Makefile +++ b/sys/modules/qatfw/Makefile @@ -1,5 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation # $FreeBSD$ - -SUBDIR= qat_c2xxx +SUBDIR= qat_c62x \ + qat_200xx \ + qat_c2xxx \ + qat_c3xxx \ + qat_c4xxx \ + qat_dh895xcc .include diff --git a/sys/modules/qatfw/qat_200xx/Makefile b/sys/modules/qatfw/qat_200xx/Makefile new file mode 100644 index 00000000000..95810cfeb97 --- /dev/null +++ b/sys/modules/qatfw/qat_200xx/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/contrib/dev/qat + +KMOD= qat_200xx_fw + +FIRMWS= ${SRCTOP}/sys/contrib/dev/qat/qat_200xx.bin:qat_200xx_fw:111 ${SRCTOP}/sys/contrib/dev/qat/qat_200xx_mmp.bin:qat_200xx_mmp_fw:111 + +.include diff --git a/sys/modules/qatfw/qat_c3xxx/Makefile b/sys/modules/qatfw/qat_c3xxx/Makefile new file mode 100644 index 00000000000..325cb69fb5b --- /dev/null +++ b/sys/modules/qatfw/qat_c3xxx/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/contrib/dev/qat + +KMOD= qat_c3xxx_fw + +FIRMWS= ${SRCTOP}/sys/contrib/dev/qat/qat_c3xxx.bin:qat_c3xxx_fw:111 ${SRCTOP}/sys/contrib/dev/qat/qat_c3xxx_mmp.bin:qat_c3xxx_mmp_fw:111 + +.include diff --git a/sys/modules/qatfw/qat_c4xxx/Makefile b/sys/modules/qatfw/qat_c4xxx/Makefile new file mode 100644 index 00000000000..ee9d27dd733 --- /dev/null +++ b/sys/modules/qatfw/qat_c4xxx/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/contrib/dev/qat + +KMOD= qat_c4xxx_fw + +FIRMWS= ${SRCTOP}/sys/contrib/dev/qat/qat_c4xxx.bin:qat_c4xxx_fw:111 ${SRCTOP}/sys/contrib/dev/qat/qat_c4xxx_mmp.bin:qat_c4xxx_mmp_fw:111 + +.include diff --git a/sys/modules/qatfw/qat_c62x/Makefile b/sys/modules/qatfw/qat_c62x/Makefile new file mode 100644 index 00000000000..2eb636e8bbd --- /dev/null +++ b/sys/modules/qatfw/qat_c62x/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/contrib/dev/qat + +KMOD= qat_c62x_fw + +FIRMWS= ${SRCTOP}/sys/contrib/dev/qat/qat_c62x.bin:qat_c62x_fw:111 ${SRCTOP}/sys/contrib/dev/qat/qat_c62x_mmp.bin:qat_c62x_mmp_fw:111 + +.include diff --git a/sys/modules/qatfw/qat_dh895xcc/Makefile b/sys/modules/qatfw/qat_dh895xcc/Makefile new file mode 100644 index 00000000000..343398a7e11 --- /dev/null +++ b/sys/modules/qatfw/qat_dh895xcc/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2007-2022 Intel Corporation +# $FreeBSD$ +.PATH: ${SRCTOP}/sys/contrib/dev/qat + +KMOD= qat_dh895xcc_fw + +FIRMWS= ${SRCTOP}/sys/contrib/dev/qat/qat_895xcc.bin:qat_dh895xcc_fw:111 ${SRCTOP}/sys/contrib/dev/qat/qat_895xcc_mmp.bin:qat_dh895xcc_mmp_fw:111 + +.include

    ve$8UO3yPM9h~T_UP8 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

|@RIK^?xSO? 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 XSRAl8U~$0WfW-le0~QDVPjKKruIvsY literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_200xx_mmp.bin b/sys/contrib/dev/qat/qat_200xx_mmp.bin new file mode 100644 index 0000000000000000000000000000000000000000..0f1f811eef4112fe3810015a97a3e1e1da49a2b7 GIT binary patch literal 120452 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 literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_895xcc.bin b/sys/contrib/dev/qat/qat_895xcc.bin new file mode 100644 index 0000000000000000000000000000000000000000..a642e1dc73aaf6c58f85c5fbab714e8f7e34e656 GIT binary patch literal 1321568 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 z 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%0DH{0qh|`7L}4H0Ty5_MD`Y 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 QeUAs;D+BM5d3XQ&A3vb67XSbN literal 0 HcmV?d00001 diff --git a/sys/contrib/dev/qat/qat_895xcc_mmp.bin b/sys/contrib/dev/qat/qat_895xcc_mmp.bin new file mode 100644 index 0000000000000000000000000000000000000000..f2c0abe493cd16da3c3389373ec57f102e8c75c0 GIT binary patch literal 119808 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