mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
pva: mirror from gitlab cv/pva-sys-sw
Gitlab commit 54b5ea8396784 ("Revert "deploy: Update NvSCI p...")
Changes since last deployment:
54b5ea83: Revert "deploy: Update NvSCI path in tegra tree"
1d42b346: Revert "deploy: update nvidia-oot path"
5819cf8b: Fix Misra defect of type 5.1
d9561abf: Fw: Fix Misra defects
ec8941c0: coverity: Qnx safety upload job timout increase
66fb1410: Fix pva_waiter_thread_func in umd tests.
0f06989c: Misra defect fixes in QNX KMD
76532814: Static defect fixes
1cbd5a36: Fix Misra defects
0deee89b: Fix misra defects
60335a28: Fix Misra defects
dbd5301d: Port pva_intf_test to pva_umd_tests
d2e0b878: fw: Fix CCM violations in DMA cmds
f4bc3069: Misra fixes in QNX KMD
f07460f1: fw: Make pva_fw_bm_sections.h private include
cf3c9eaa: pva_fw: prevent interrupt storm on print flush
8d11e690: tests: tag tests with negative and long_duration
e2c592dc: Add dmesg checks for non-negative UMD tests
c162d5d4: deploy: fix scatter file dependency
920f6439: tests: Mark negative tests with prefix negative_
bf855422: fw: Fix abort message overflow
00fa97d6: fw: refactor: remove unused or empty files
34d3f41f: fw: refactor: use _init_ in boot unit file names
ca0dfd16: fw: refactor: clean-up function scopes
8215ec86: Static defect fixes(Misra 10.3, CERT INT31-C)
4ffaaf80: Static defects in QNX KMD
0a8af77b: kmd: DMA validation disabled for test_mode
21063625: perf: add new perf metrics
38532a9b: ci: exclude pva_fw_bm_sections.h from checkpatch
19adcb9a: fw: refactor baremetal v3 folder
f03503ba: fw: refactor baremetal wdt folder
6530b0f1: fw: refactor baremetal utility folder
46c373fb: fw: refactor baremetal pe folder
4c3e2ccf: fw: refactor baremetal hal folder
f0f2e0d3: fw: refactor baremetal dma folder
b95e6512: fw: refactor baremetal boot code
9a8552c6: Static defect fixes
7377ba1c: coverity: fix coverity file permissions
79437d05: coverity: upload cert data for non safety
b9d4eb16: pva: Update allowed state APIs in UMD
7ea85e62: Fix static defects pfsd part 3
d83d03fc: fw: Refactor switch-case statements
d562a635: fw: Fix MISRA violation
040a1a29: Update CI/CD pipeline builds
d88e3378: fw: fix static defects in l2sram changes
d6c0b729: Increasing SIM timeout
f34c1707: L2SRAM Bug Fix
d8ea3fe5: fw: Fix MISRA defects (10.3, 10.4, 1.5)
d585b0f9: tests: Port Security Checks from V2
ef70bab8: Port interaface ests to pva_umd_tests
188fbbed: Misra Violation Fixes
421c1fc0: Static defects in QNX KMD
b0cddda4: cmake: Fix cupva build
af5d307d: Fix GENERIC_CLOCK_FRQ & eventlib_write call, others
849a4a9e: fw: remove PE interrupt log print
da3c1a16: PVA: export pva_get_api_restrictions umd library
884c1617: Standardize baremetal src code
b9ea40ac: Re-enable the tests filtered out in the bug
4016fbaf: fw: Move R5 OCD code to DRAM
d50803b1: fw: Fix CERT defects
6b699175: dvms: Update the public API for DVMS state
c5b550bc: cmake: fix precedence of CLI arg
20af216d: docker: update coverity license
33a28dbd: Fix MISRA 10.4 defects in QNX KMD
187b4414: Fix static defects in pfsd change
91cea667: ci: Add Parallel SQA Stress Test Pipeline
ec8d5f6a: Fix MISRA defects in QNX KMD
b8dd4b72: Fix static defects in pfsd change
98b52770: Port the following pva_intf_test to pva_umd_tests.
2e8e48b0: Updates in QNX KMD: MISRA Fixes
ca4a4e47: Update elfs to fix PPE parity error
c1e97e29: Fix CERT defects in QNX KMD
9f012192: fw: Fix static defects
0434d413: Update deploy script to use PROD and DEV profiles
79c141a3: kmd: bugfix: enforce ctx init for sync ops
c2d19878: fw: Fix Cert defects
2ef3651b: fw: Fix CERT defects
668e92f6: Update device probe in Linux KMD
96c4c365: Fix FW error printing for baremetal
10e76b98: Port the following interface tests to umd tests.
01e68097: Enable pva_fw_utests in CI/CD.
e7928a62: Fix CERT defects in QNX KMD
82af1ecb: tests: mark negative UMD tests with prefix
72400087: kmd: fix incorrect log level
d5d1ac35: Update kernel API class_create
72e01b15: deploy: Add nvplayfair to tests template
1237841a: Add pfsd support
6c481474: Update tests and CI for safety builds
88346e94: Add PROD, DEV and INTERNAL build profiles
872f814f: Add build flag for Tegrastats
2ea9c786: Add build flag for MODS test support
4cb0c338: Add build flag for error injection
4d530991: Add build flags for FW profiling and tracepoints
4a02d022: Add build flag for debug prints
fc2aa7aa: Add build flag for VPU OCD (DOIP)
5ccf9d23: Add build flag for HWPM
c69dc657: Add build flag for golden reg checks
21529167: fw: Fix Cert defects
80e032c9: fw: Fix CCM violations in FW cmds
e170cc47: fw: Fix L2SRAM CCM violation
02b82f60: Fix QNX KMD Misra Violations
6594180b: fw: Fix CCM violations
b34f050d: umd: Misra Dir 4.7 defects fix
7a5d7f74: umd: Fix CERT and Top25 defects
7d49aeea: umd: Fix cert INT31 INT34 INT36 defects
aaef325b: fw: Fix dma cmds CCM violations
a1bcadcd: Fix HWPM base address and init failures
437bdeec: Cleanup device probe and wrapper indirections in Linux kernel
0bd92f89: fw: Fix CCM violations
9c01c5c2: fw: Fix L2SRAM CCM violations
25d314fe: doxy: Update Doxygen comments to make it more generic
cfd6fcbe: KMD: Added documentation for common
e7b93f9a: doxy: Add Doxygen to all KMD shim APIs
da32cbea: doxy: Add Doxygen comments for KMD QNX files
5e22bb15: ci: Reduce test iteration count
2a91d9e5: ci: Remove testing for debug build
b56ead62: fw: Fix pe CCM violations
1ac4c005: fw: Fix DMA CCM violations
e223d5ee: fw: Fix PE CCM violations
75d229cc: Improve error path for FW coverage dump
2d5be991: Do not use GSC when testing in CI
c81f3b72: dedicated coverage tests script
8e8ab336: ci: Add firmware vectorcast build to CI
eb7ea48d: vcast.py: Add firmware support
f3e344af: Add vcast build + test to CI
8e5db8ba: Add vectorcast support
5bc91a84: Add vectorcast to docker image
02d82e46: Fix KMD Misra Rule 10.1 violations
e2386c0c: Dump PVA FW Coverage
3996decf: umd: Fix CERT and MISRA defects
d9fe5c5d: Add QNX SR support in CI/CD
d1c991a9: pva: coverity 7.2 release update
754c74ec: Port the following intreface tests to umd tests
25fe8a38: pva_fw: Setup DMA to also support memcpy
4f9d9f79: fw: Fix basic MISRA defects
62393350: umd tests: add perf test
ae2fbfa3: libs: Fix mul overflow CCM violation
0cbfa44f: Update VPU apps
e86a22ee: Fix Vpu error tests
435a16ea: ci: Modify Interface Test filter
1953f2d7: Port the following tests
90ac41ef: Implement synchronous memory unregistration
e29aaead: kmd: Fix DVMS CCM violations
7a46bc75: kmd: Fix hwseq validate CCM violation
3d8691cf: libs: Fix CCM violation in muls64 helper
98ca3972: kmd: Fix shared buffer CCM violation
4ba27920: kmd: Fix devctl CCM violations
640a7d58: perf: Fetch asl binaries for linux perf tests
4f25e30d: pva_fw: Add fast dma setup for transfers
3a73eb6c: kmd: Fix CCM violation in kmd context
72de95cf: kmd: Fix CCM violations in qnx_main and silicon exec
200a0fe6: ci: Remove checkGitlabJob.py
8bd635ce: coverity: Upgrade versions of Coverity and MISRA config
9c44087f: fw: Isolate VPU HW state reading retries
bee65065: kmd: Log error at the correct level
a5e9570a: deploy: Consider forked branch for commit message
91f1ceb4: tests: Fix VPU OCD expected value
7742f0ae: Add testing support for qnx nsr thor in CI/CD.
0ec69957: umd: Fix basic MISRA defects
beac9313: pva: update _PULSE_CODE_COIDDEATH handling
46192073: doip test: Add test to r/w to CSITE reg
accb2184: kmd: Fix dma_cfg_validate CCM violations
6da720c1: kmd: Fix misc CCM violations
e73779dc: Integrate PVA QNX KMD with DVMS Framework
4556b3f3: kmd: Fix op handler CCM violation
59da12ec: kmd: Fix CCM violation in DMA binding
3404ab99: pva_kmd: Fix a double free static defect
f99ff7c0: umd: Fix CCM Violations in queue_create and cuextend impl
d41fe841: pva_fw: Fixed unsigned type mismatch issues
dbc71f66: Port the following pva_intf_test to pva_umd_tests
b871295e: Change FAILED to failed
fe5c0ec3: ci: Unload default KMD driver on launch
0744de61: Skip duplicated memset in pva_fw_init_cmd_runner
c482932e: Update UMD export file
7f68160f: Fix parallel_scheduling_test_SingleProcessOnly
a869d997: Add VPU return code to context error struct
65108714: fw: Fix macro based type mismatch
3c28728e: Update tests affected by context error
fa208034: Add string representation of context error
71c91d38: umd: Fix nvsci import CCM Violations
6b7c1c05: Remove foreign syncpoint wait support
e512f5d4: Remove qnx/src path from deployment
63cce5ea: cursor: Update prebuilt image path
c14e51d5: docs: Add docs for async error handling
f90d047b: Implement asynchronous error report
5e9eb1f0: umd: Fix Data Channel CCM violation
1cdb79ed: umd: Fix CCM violations in NvSci export and image functions
87592b3f: ci: remove tcu_muxer support
fbf18cdb: DOIP: Fix overflow in Linux
b075f8cf: umd: Fix CCM violation in pva_context_create
a68a617a: Increase timeout value to handle big queues
fb356df3: KMD: Add support for DOIP in QNX
d560be9a: ci: support to track pva solutions algo perf
52111da4: umd: Fix CCM violation in cuextend_validate_memory_unregister
2f05b223: umd: Fix CCM violations in CUExtend memory register functions
c4803585: coverage: add umd code coverage support
3ed84a70: coverity: support safety build for qnx and baremetal
61cbe299: pva: fix static defects
5d07da65: Remove unused fields in UMD context
9f5a2654: Add foreign syncpoint waiter
4e388d3b: Remove limit on concurrent syncpoint wait
ab7e9bc8: nsight: update fence tracepoint
109a7368: nsight: Disable nsight support in safety builds
c9a66b30: nsight: fix engine reservation tracing
13024df9: nsight: clean-up and rename several fields
20cb20cb: nsight: Support redesigned tracepoints on QNX
ab55d48a: nsight: redesign tracepoints for V3 stack
7d6c1630: ci: install xxd tool for build env
Forked changes (dropped):
b2843456: pva: fix static defects
11700626: Revert "Remove WAR of skipping symbol type check"
121b314d: Revert "native: Add symbol type check for native"
b389a5fe: Revert "deploy: Update NvSCI path in tegra tree"
d240f306: Update pva_umd_host_misc.c license
78929b03: Revert "deploy: update nvidia-oot path"
7012c123: Remove unused fields in UMD context
4b7d4634: Add foreign syncpoint waiter
fdb28e8e: Remove limit on concurrent syncpoint wait
Change-Id: I5610d6936207a780668a391f4f7fea0a4cd685dd
Signed-off-by: nanwa <nanwa@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3508228
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
@@ -27,11 +27,15 @@ pva_objs += \
|
|||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_binding.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_binding.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_validate.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_validate.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_write.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_dma_cfg_write.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_fw_debug.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_fw_debug_printf.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_fw_profiler.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_fw_tracepoints.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_hwseq_validate.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_hwseq_validate.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_msg.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_msg.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_op_handler.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_op_handler.o \
|
||||||
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pfsd.o \
|
||||||
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pfsd_data.o \
|
||||||
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pfsd_t23x_dma_cfg.o \
|
||||||
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pfsd_t26x_dma_cfg.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pm.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_pm.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_queue.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_queue.o \
|
||||||
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_resource_table.o \
|
$(PVA_SYS_DIR)/src/kmd/common/pva_kmd_resource_table.o \
|
||||||
@@ -82,12 +86,22 @@ pva_def_flags += \
|
|||||||
-DPVA_BUILD_MODE_SIM=4 \
|
-DPVA_BUILD_MODE_SIM=4 \
|
||||||
-DPVA_DEV_MAIN_COMPATIBLE=1 \
|
-DPVA_DEV_MAIN_COMPATIBLE=1 \
|
||||||
-DPVA_ENABLE_CUDA=1 \
|
-DPVA_ENABLE_CUDA=1 \
|
||||||
|
-DPVA_ENABLE_DEBUG_ASSERT=0 \
|
||||||
|
-DPVA_ENABLE_DEBUG_PRINTS=0 \
|
||||||
|
-DPVA_ENABLE_FW_PROFILING=0 \
|
||||||
|
-DPVA_ENABLE_FW_TRACEPOINTS=1 \
|
||||||
|
-DPVA_ENABLE_GOLDEN_REGISTER_CHECKS=1 \
|
||||||
|
-DPVA_ENABLE_HWPM=1 \
|
||||||
-DPVA_ENABLE_NSYS_PROFILING=1 \
|
-DPVA_ENABLE_NSYS_PROFILING=1 \
|
||||||
-DPVA_ENABLE_R5_OCD=0 \
|
-DPVA_ENABLE_R5_OCD=0 \
|
||||||
-DPVA_IS_DEBUG=0 \
|
-DPVA_ENABLE_TEGRASTATS=1 \
|
||||||
|
-DPVA_ENABLE_VPU_OCD=1 \
|
||||||
|
-DPVA_ENABLE_VPU_PRINTFS=1 \
|
||||||
|
-DPVA_ERR_INJECT=0 \
|
||||||
-DPVA_SAFETY=0 \
|
-DPVA_SAFETY=0 \
|
||||||
-DPVA_SKIP_SYMBOL_TYPE_CHECK \
|
|
||||||
-DPVA_SUPPORT_XBAR_RAW=1 \
|
-DPVA_SUPPORT_XBAR_RAW=1 \
|
||||||
|
-DPVA_VCAST=0 \
|
||||||
|
-DSYSTEM_TESTS_ENABLED=1 \
|
||||||
-Dpva_kmd_linux_dummy_EXPORTS \
|
-Dpva_kmd_linux_dummy_EXPORTS \
|
||||||
|
|
||||||
###### End generated section ######
|
###### End generated section ######
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#define PVA_CMD_PRIV_OPCODE_FLAG (1U << 7U)
|
#define PVA_CMD_PRIV_OPCODE_FLAG (1U << 7U)
|
||||||
|
|
||||||
#define PVA_RESOURCE_ID_BASE 1U
|
#define PVA_RESOURCE_ID_BASE 1U
|
||||||
|
|
||||||
struct pva_resource_entry {
|
struct pva_resource_entry {
|
||||||
uint8_t access_flags : 2; // 1: RO, 2: WO, 3: RW
|
uint8_t access_flags : 2; // 1: RO, 2: WO, 3: RW
|
||||||
uint8_t reserved : 4;
|
uint8_t reserved : 4;
|
||||||
@@ -42,9 +43,11 @@ struct pva_cmd_init_resource_table {
|
|||||||
* 1-7 are users'. */
|
* 1-7 are users'. */
|
||||||
uint8_t resource_table_id;
|
uint8_t resource_table_id;
|
||||||
uint8_t resource_table_addr_hi;
|
uint8_t resource_table_addr_hi;
|
||||||
uint8_t pad[2];
|
uint8_t ctx_status_addr_hi;
|
||||||
|
uint8_t pad[1];
|
||||||
uint32_t resource_table_addr_lo;
|
uint32_t resource_table_addr_lo;
|
||||||
uint32_t max_n_entries;
|
uint32_t max_n_entries;
|
||||||
|
uint32_t ctx_status_addr_lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pva_cmd_deinit_resource_table {
|
struct pva_cmd_deinit_resource_table {
|
||||||
@@ -156,7 +159,13 @@ struct pva_cmd_get_version {
|
|||||||
uint32_t buffer_iova_lo;
|
uint32_t buffer_iova_lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PVA_CMD_PRIV_OPCODE_COUNT 15U
|
struct pva_cmd_set_pfsd_cmd_buffer_size {
|
||||||
|
#define PVA_CMD_OPCODE_SET_PFSD_CMD_BUFFER_SIZE (15U | PVA_CMD_PRIV_OPCODE_FLAG)
|
||||||
|
struct pva_cmd_header header;
|
||||||
|
uint32_t cmd_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PVA_CMD_PRIV_OPCODE_COUNT 16U
|
||||||
|
|
||||||
struct pva_fw_prefence {
|
struct pva_fw_prefence {
|
||||||
uint8_t offset_hi;
|
uint8_t offset_hi;
|
||||||
@@ -172,7 +181,7 @@ struct pva_fw_postfence {
|
|||||||
/** Privileged user queue may need to trigger fence that exists in user's own
|
/** Privileged user queue may need to trigger fence that exists in user's own
|
||||||
* resource table. Set this flags to tell FW to use user's resource table when
|
* resource table. Set this flags to tell FW to use user's resource table when
|
||||||
* writing this post fence. This also applies to timestamp resource ID. */
|
* writing this post fence. This also applies to timestamp resource ID. */
|
||||||
#define PVA_FW_POSTFENCE_FLAGS_USER_FENCE (1 << 0)
|
#define PVA_FW_POSTFENCE_FLAGS_USER_FENCE (1U << 0U)
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t pad0;
|
uint8_t pad0;
|
||||||
uint32_t offset_lo;
|
uint32_t offset_lo;
|
||||||
@@ -306,42 +315,42 @@ static inline uint32_t pva_fw_queue_space(uint32_t head, uint32_t tail,
|
|||||||
* msg[4] = STATUS6
|
* msg[4] = STATUS6
|
||||||
* msg[5] = STATUS7
|
* msg[5] = STATUS7
|
||||||
*/
|
*/
|
||||||
#define PVA_FW_MSG_STATUS_BASE 3
|
#define PVA_FW_MSG_STATUS_BASE 3U
|
||||||
#define PVA_FW_MSG_STATUS_LAST 8
|
#define PVA_FW_MSG_STATUS_LAST 8U
|
||||||
|
|
||||||
#define PVA_FW_MSG_TYPE_MSB 30
|
#define PVA_FW_MSG_TYPE_MSB 30U
|
||||||
#define PVA_FW_MSG_TYPE_LSB 25
|
#define PVA_FW_MSG_TYPE_LSB 25U
|
||||||
#define PVA_FW_MSG_LEN_MSB 24
|
#define PVA_FW_MSG_LEN_MSB 24U
|
||||||
#define PVA_FW_MSG_LEN_LSB 22
|
#define PVA_FW_MSG_LEN_LSB 22U
|
||||||
/* The remaining bits (0 - 21) of msg[0] can be used for message specific
|
/* The remaining bits (0 - 21) of msg[0] can be used for message specific
|
||||||
* payload */
|
* payload */
|
||||||
|
|
||||||
/* Message types: R5 -> CCPLEX */
|
/* Message types: R5 -> CCPLEX */
|
||||||
#define PVA_FW_MSG_TYPE_ABORT 1
|
#define PVA_FW_MSG_TYPE_ABORT 1U
|
||||||
#define PVA_FW_MSG_TYPE_BOOT_DONE 2
|
#define PVA_FW_MSG_TYPE_BOOT_DONE 2U
|
||||||
#define PVA_FW_MSG_TYPE_FLUSH_PRINT 3
|
#define PVA_FW_MSG_TYPE_FLUSH_PRINT 3U
|
||||||
#define PVA_FW_MSG_TYPE_RESOURCE_UNREGISTER 3
|
#define PVA_FW_MSG_TYPE_FAST_RESET_FAILURE 4U
|
||||||
|
|
||||||
/* Message types: CCPLEX -> R5 */
|
/* Message types: CCPLEX -> R5 */
|
||||||
#define PVA_FW_MSG_TYPE_UPDATE_TAIL 32
|
#define PVA_FW_MSG_TYPE_UPDATE_TAIL 32U
|
||||||
|
|
||||||
/* Parameters for message ABORT
|
/* Parameters for message ABORT
|
||||||
* ABORT message contains a short string (up to 22 chars).
|
* ABORT message contains a short string (up to 22 chars).
|
||||||
* The first two charactors are in the message header (bit 15 - 0).
|
* The first two charactors are in the message header (bit 15 - 0).
|
||||||
*/
|
*/
|
||||||
#define PVA_FW_MSG_ABORT_STR_MAX_LEN 22
|
#define PVA_FW_MSG_ABORT_STR_MAX_LEN 22U
|
||||||
|
|
||||||
/* Parameters for message BOOT_DONE */
|
/* Parameters for message BOOT_DONE */
|
||||||
#define PVA_FW_MSG_R5_START_TIME_LO_IDX 1
|
#define PVA_FW_MSG_R5_START_TIME_LO_IDX 1U
|
||||||
#define PVA_FW_MSG_R5_START_TIME_HI_IDX 2
|
#define PVA_FW_MSG_R5_START_TIME_HI_IDX 2U
|
||||||
#define PVA_FW_MSG_R5_READY_TIME_LO_IDX 3
|
#define PVA_FW_MSG_R5_READY_TIME_LO_IDX 3U
|
||||||
#define PVA_FW_MSG_R5_READY_TIME_HI_IDX 4
|
#define PVA_FW_MSG_R5_READY_TIME_HI_IDX 4U
|
||||||
|
|
||||||
#define PVA_MAX_DEBUG_LOG_MSG_CHARACTERS 100
|
#define PVA_MAX_DEBUG_LOG_MSG_CHARACTERS 100U
|
||||||
/* Parameters for message FLUSH PRINT */
|
/* Parameters for message FLUSH PRINT */
|
||||||
struct pva_fw_print_buffer_header {
|
struct pva_fw_print_buffer_header {
|
||||||
#define PVA_FW_PRINT_BUFFER_OVERFLOWED (1 << 0)
|
#define PVA_FW_PRINT_BUFFER_OVERFLOWED (1U << 0U)
|
||||||
#define PVA_FW_PRINT_FAILURE (1 << 1)
|
#define PVA_FW_PRINT_FAILURE (1U << 1U)
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t head;
|
uint32_t head;
|
||||||
uint32_t tail;
|
uint32_t tail;
|
||||||
@@ -351,8 +360,8 @@ struct pva_fw_print_buffer_header {
|
|||||||
|
|
||||||
/* Parameters for message resource unregister */
|
/* Parameters for message resource unregister */
|
||||||
/* Table ID is stored in msg[0], bit: 0 - 7 */
|
/* Table ID is stored in msg[0], bit: 0 - 7 */
|
||||||
#define PVA_FW_MSG_RESOURCE_TABLE_ID_MSB 7
|
#define PVA_FW_MSG_RESOURCE_TABLE_ID_MSB 7U
|
||||||
#define PVA_FW_MSG_RESOURCE_TABLE_ID_LSB 0
|
#define PVA_FW_MSG_RESOURCE_TABLE_ID_LSB 0U
|
||||||
/* Followed by up to 5 resource IDs. The actual number of resource ID is
|
/* Followed by up to 5 resource IDs. The actual number of resource ID is
|
||||||
* indicated by the message length. */
|
* indicated by the message length. */
|
||||||
|
|
||||||
@@ -388,35 +397,45 @@ struct pva_fw_event_message {
|
|||||||
|
|
||||||
// Each event is one of the following types. This should fit within 3 bits
|
// Each event is one of the following types. This should fit within 3 bits
|
||||||
enum pva_fw_events_type {
|
enum pva_fw_events_type {
|
||||||
EVENT_TRY = 0U,
|
PVA_EVENT_CMD_ATTEMPTING = 0U,
|
||||||
EVENT_START,
|
PVA_EVENT_CMD_STARTED,
|
||||||
EVENT_YIELD,
|
PVA_EVENT_CMD_YIELDED,
|
||||||
EVENT_DONE,
|
PVA_EVENT_CMD_COMPLETED,
|
||||||
EVENT_ERROR,
|
PVA_EVENT_CMD_FAILED,
|
||||||
EVENT_TYPE_MAX = 7U
|
PVA_EVENT_TYPE_MAX = 7U
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const char *event_type_to_string(enum pva_fw_events_type status)
|
static inline const char *event_type_to_string(enum pva_fw_events_type status)
|
||||||
{
|
{
|
||||||
|
const char *result = "";
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case EVENT_TRY:
|
case PVA_EVENT_CMD_ATTEMPTING:
|
||||||
return "TRY";
|
result = "TRY";
|
||||||
case EVENT_START:
|
break;
|
||||||
return "START";
|
case PVA_EVENT_CMD_STARTED:
|
||||||
case EVENT_YIELD:
|
result = "START";
|
||||||
return "YIELD";
|
break;
|
||||||
case EVENT_DONE:
|
case PVA_EVENT_CMD_YIELDED:
|
||||||
return "DONE";
|
result = "YIELD";
|
||||||
case EVENT_ERROR:
|
break;
|
||||||
return "ERROR";
|
case PVA_EVENT_CMD_COMPLETED:
|
||||||
|
result = "DONE";
|
||||||
|
break;
|
||||||
|
case PVA_EVENT_CMD_FAILED:
|
||||||
|
result = "ERROR";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return "";
|
result = "";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_fw_timestamp_t {
|
enum pva_fw_timestamp_t {
|
||||||
TIMESTAMP_TYPE_TSE = 0,
|
TIMESTAMP_TYPE_TSE = 0U,
|
||||||
TIMESTAMP_TYPE_CYCLE_COUNT = 1
|
TIMESTAMP_TYPE_CYCLE_COUNT = 1U
|
||||||
};
|
};
|
||||||
/* End of PVA FW Event profiling definitions */
|
/* End of PVA FW Event profiling definitions */
|
||||||
|
|
||||||
@@ -436,8 +455,8 @@ enum pva_fw_timestamp_t {
|
|||||||
// buffer size properties as KMD might use this for validation of buffer accesses.
|
// buffer size properties as KMD might use this for validation of buffer accesses.
|
||||||
// If FW somehow corrupts 'size', KMD might end up accessing out of bounds.
|
// If FW somehow corrupts 'size', KMD might end up accessing out of bounds.
|
||||||
struct pva_fw_shared_buffer_header {
|
struct pva_fw_shared_buffer_header {
|
||||||
#define PVA_KMD_FW_BUF_FLAG_OVERFLOW (1 << 0)
|
#define PVA_KMD_FW_BUF_FLAG_OVERFLOW (1U << 0U)
|
||||||
#define PVA_KMD_FW_BUF_FLAG_ERROR (1 << 1)
|
#define PVA_KMD_FW_BUF_FLAG_ERROR (1U << 1U)
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t element_size;
|
uint32_t element_size;
|
||||||
uint32_t head;
|
uint32_t head;
|
||||||
@@ -445,13 +464,13 @@ struct pva_fw_shared_buffer_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pva_kmd_fw_buffer_msg_header {
|
struct pva_kmd_fw_buffer_msg_header {
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_FW_EVENT 0
|
#define PVA_KMD_FW_BUF_MSG_TYPE_FW_EVENT 0U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_CMD_BUF_TRACE 1
|
#define PVA_KMD_FW_BUF_MSG_TYPE_CMD_BUF_TRACE 1U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_VPU_TRACE 2
|
#define PVA_KMD_FW_BUF_MSG_TYPE_VPU_TRACE 2U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_FENCE_TRACE 3
|
#define PVA_KMD_FW_BUF_MSG_TYPE_FENCE_TRACE 3U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_ENGINE_ACQUIRE_TRACE 4
|
#define PVA_KMD_FW_BUF_MSG_TYPE_ENGINE_ACQUIRE_TRACE 4U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_RES_UNREG 5
|
#define PVA_KMD_FW_BUF_MSG_TYPE_RES_UNREG 5U
|
||||||
#define PVA_KMD_FW_BUF_MSG_TYPE_FW_TRACEPOINT 6
|
#define PVA_KMD_FW_BUF_MSG_TYPE_FW_TRACEPOINT 6U
|
||||||
uint32_t type : 8;
|
uint32_t type : 8;
|
||||||
// Size of payload in bytes. Includes the size of the header.
|
// Size of payload in bytes. Includes the size of the header.
|
||||||
uint32_t size : 24;
|
uint32_t size : 24;
|
||||||
@@ -523,10 +542,10 @@ struct pva_kmd_fw_tegrastats {
|
|||||||
uint64_t total_utilization[PVA_NUM_PVE];
|
uint64_t total_utilization[PVA_NUM_PVE];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PVA_MAX_CMDBUF_CHUNK_LEN 1024
|
#define PVA_MAX_CMDBUF_CHUNK_LEN 1024U
|
||||||
#define PVA_MAX_CMDBUF_CHUNK_SIZE (sizeof(uint32_t) * PVA_MAX_CMDBUF_CHUNK_LEN)
|
#define PVA_MAX_CMDBUF_CHUNK_SIZE (sizeof(uint32_t) * PVA_MAX_CMDBUF_CHUNK_LEN)
|
||||||
|
|
||||||
#define PVA_TEST_MODE_MAX_CMDBUF_CHUNK_LEN 256
|
#define PVA_TEST_MODE_MAX_CMDBUF_CHUNK_LEN 256U
|
||||||
#define PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE \
|
#define PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE \
|
||||||
(sizeof(uint32_t) * PVA_TEST_MODE_MAX_CMDBUF_CHUNK_LEN)
|
(sizeof(uint32_t) * PVA_TEST_MODE_MAX_CMDBUF_CHUNK_LEN)
|
||||||
|
|
||||||
@@ -563,60 +582,89 @@ struct pva_fw_tracepoint {
|
|||||||
|
|
||||||
static inline const char *pva_fw_tracepoint_type_to_string(uint32_t type)
|
static inline const char *pva_fw_tracepoint_type_to_string(uint32_t type)
|
||||||
{
|
{
|
||||||
|
const char *result = "UNKNOWN";
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PVA_FW_TP_LVL_NONE:
|
case PVA_FW_TP_LVL_NONE:
|
||||||
return "NONE";
|
result = "NONE";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_LVL_CMD_BUF:
|
case PVA_FW_TP_LVL_CMD_BUF:
|
||||||
return "CMD_BUF";
|
result = "CMD_BUF";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_LVL_VPU:
|
case PVA_FW_TP_LVL_VPU:
|
||||||
return "VPU";
|
result = "VPU";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_LVL_DMA:
|
case PVA_FW_TP_LVL_DMA:
|
||||||
return "DMA";
|
result = "DMA";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_LVL_L2SRAM:
|
case PVA_FW_TP_LVL_L2SRAM:
|
||||||
return "L2SRAM";
|
result = "L2SRAM";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_LVL_PPE:
|
case PVA_FW_TP_LVL_PPE:
|
||||||
return "PPE";
|
result = "PPE";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
result = "UNKNOWN";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char *pva_fw_tracepoint_flags_to_string(uint32_t flags)
|
static inline const char *pva_fw_tracepoint_flags_to_string(uint32_t flags)
|
||||||
{
|
{
|
||||||
|
const char *result = "UNKNOWN";
|
||||||
|
|
||||||
switch (flags) {
|
switch (flags) {
|
||||||
case PVA_FW_TP_FLAG_NONE:
|
case PVA_FW_TP_FLAG_NONE:
|
||||||
return "NONE";
|
result = "NONE";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_FLAG_START:
|
case PVA_FW_TP_FLAG_START:
|
||||||
return "START";
|
result = "START";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_FLAG_END:
|
case PVA_FW_TP_FLAG_END:
|
||||||
return "END";
|
result = "END";
|
||||||
|
break;
|
||||||
case PVA_FW_TP_FLAG_ERROR:
|
case PVA_FW_TP_FLAG_ERROR:
|
||||||
return "ERROR";
|
result = "ERROR";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
result = "UNKNOWN";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char *pva_fw_tracepoint_slot_id_to_string(uint32_t slot_id)
|
static inline const char *pva_fw_tracepoint_slot_id_to_string(uint32_t slot_id)
|
||||||
{
|
{
|
||||||
|
const char *result = "UNKNOWN";
|
||||||
|
|
||||||
switch (slot_id) {
|
switch (slot_id) {
|
||||||
case 0:
|
case 0:
|
||||||
return "PRIV_SLOT";
|
result = "PRIV_SLOT";
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
return "USER_SLOT_1";
|
result = "USER_SLOT_1";
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return "USER_SLOT_2";
|
result = "USER_SLOT_2";
|
||||||
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
return "USER_PRIV_SLOT";
|
result = "USER_PRIV_SLOT";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
result = "UNKNOWN";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PVA_R5_OCD_TYPE_MMIO_READ 1
|
#define PVA_R5_OCD_TYPE_MMIO_READ 1U
|
||||||
#define PVA_R5_OCD_TYPE_MMIO_WRITE 2
|
#define PVA_R5_OCD_TYPE_MMIO_WRITE 2U
|
||||||
#define PVA_R5_OCD_TYPE_REG_READ 3
|
#define PVA_R5_OCD_TYPE_REG_READ 3U
|
||||||
#define PVA_R5_OCD_TYPE_REG_WRITE 4
|
#define PVA_R5_OCD_TYPE_REG_WRITE 4U
|
||||||
|
|
||||||
#define PVA_R5_OCD_MAX_DATA_SIZE FW_TRACE_BUFFER_SIZE
|
#define PVA_R5_OCD_MAX_DATA_SIZE FW_TRACE_BUFFER_SIZE
|
||||||
|
|
||||||
@@ -627,4 +675,11 @@ struct pva_r5_ocd_request {
|
|||||||
//followed by data if any
|
//followed by data if any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PVA_FW_ASYNC_ERROR_STR_MAX_LEN (1024 * 3)
|
||||||
|
struct pva_fw_async_error {
|
||||||
|
struct pva_async_error error_info;
|
||||||
|
uint32_t failure_reason_str_len;
|
||||||
|
char failure_reason[PVA_FW_ASYNC_ERROR_STR_MAX_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
#endif // PVA_FW_H
|
#endif // PVA_FW_H
|
||||||
|
|||||||
@@ -30,36 +30,36 @@
|
|||||||
/**
|
/**
|
||||||
* @brief R5 address of reset exception vector
|
* @brief R5 address of reset exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_RESET_VECTOR 0x60040C00
|
#define PVA_EVP_RESET_VECTOR 0x60040C00
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of undefined instruction exception vector
|
* @brief R5 address of undefined instruction exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_UNDEFINED_INSTRUCTION_VECTOR (EVP_RESET_VECTOR + 0x400 * 1)
|
#define PVA_EVP_UNDEFINED_INSTRUCTION_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 1)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of svc exception vector
|
* @brief R5 address of svc exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_SVC_VECTOR (EVP_RESET_VECTOR + 0x400 * 2)
|
#define PVA_EVP_SVC_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 2)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of prefetch abort exception vector
|
* @brief R5 address of prefetch abort exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_PREFETCH_ABORT_VECTOR (EVP_RESET_VECTOR + 0x400 * 3)
|
#define PVA_EVP_PREFETCH_ABORT_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 3)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of data abort exception vector
|
* @brief R5 address of data abort exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_DATA_ABORT_VECTOR (EVP_RESET_VECTOR + 0x400 * 4)
|
#define PVA_EVP_DATA_ABORT_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 4)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of reserved exception vector.
|
* @brief R5 address of reserved exception vector.
|
||||||
* It points to a dummy handler.
|
* It points to a dummy handler.
|
||||||
*/
|
*/
|
||||||
#define EVP_RESERVED_VECTOR (EVP_RESET_VECTOR + 0x400 * 5)
|
#define PVA_EVP_RESERVED_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 5)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of IRQ exception vector
|
* @brief R5 address of IRQ exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_IRQ_VECTOR (EVP_RESET_VECTOR + 0x400 * 6)
|
#define PVA_EVP_IRQ_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 6)
|
||||||
/**
|
/**
|
||||||
* @brief R5 address of FIQ exception vector
|
* @brief R5 address of FIQ exception vector
|
||||||
*/
|
*/
|
||||||
#define EVP_FIQ_VECTOR (EVP_RESET_VECTOR + 0x400 * 7)
|
#define PVA_EVP_FIQ_VECTOR (PVA_EVP_RESET_VECTOR + 0x400 * 7)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,23 +129,23 @@
|
|||||||
/**
|
/**
|
||||||
* @brief EVP SCR firewall to enable only CCPLEX read/write access.
|
* @brief EVP SCR firewall to enable only CCPLEX read/write access.
|
||||||
*/
|
*/
|
||||||
#define PVA_EVP_SCR_VAL 0x19000202
|
#define PVA_EVP_SCR_VAL 0x19000202U
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PRIV SCR firewall to enable only CCPLEX and R5 read/write access.
|
* @brief PRIV SCR firewall to enable only CCPLEX and R5 read/write access.
|
||||||
*/
|
*/
|
||||||
#define PVA_PRIV_SCR_VAL 0x1F008282
|
#define PVA_PRIV_SCR_VAL 0x1F008282U
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief CCQ SCR firewall to enable only CCPLEX write access and R5 read access.
|
* @brief CCQ SCR firewall to enable only CCPLEX write access and R5 read access.
|
||||||
*/
|
*/
|
||||||
#define PVA_CCQ_SCR_VAL 0x19000280
|
#define PVA_CCQ_SCR_VAL 0x19000280U
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Status Ctl SCR firewall to enable only CCPLEX read access and R5 read/write access.
|
* @brief Status Ctl SCR firewall to enable only CCPLEX read access and R5 read/write access.
|
||||||
*/
|
*/
|
||||||
#define PVA_STATUS_CTL_SCR_VAL 0x1f008082
|
#define PVA_STATUS_CTL_SCR_VAL 0x1f008082U
|
||||||
#define PVA_STATUS_CTL_SCR_VAL_SIM 0x1f008282
|
#define PVA_STATUS_CTL_SCR_VAL_SIM 0x1f008282U
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -105,8 +105,8 @@
|
|||||||
* msg[0] = mailbox 1 -> generate interrupt to R5
|
* msg[0] = mailbox 1 -> generate interrupt to R5
|
||||||
* msg[1] = mailbox 0
|
* msg[1] = mailbox 0
|
||||||
*/
|
*/
|
||||||
#define PVA_FW_MBOX_TO_R5_BASE 0
|
#define PVA_FW_MBOX_TO_R5_BASE 0U
|
||||||
#define PVA_FW_MBOX_TO_R5_LAST 1
|
#define PVA_FW_MBOX_TO_R5_LAST 1U
|
||||||
|
|
||||||
/* When R5 send messages to hypervisor through mailboxes, we use mailbox 2 - 7
|
/* When R5 send messages to hypervisor through mailboxes, we use mailbox 2 - 7
|
||||||
* msg[0] = mailbox 7 -> generate interrupt to hypervisor
|
* msg[0] = mailbox 7 -> generate interrupt to hypervisor
|
||||||
@@ -116,8 +116,8 @@
|
|||||||
* msg[4] = mailbox 5
|
* msg[4] = mailbox 5
|
||||||
* msg[5] = mailbox 6
|
* msg[5] = mailbox 6
|
||||||
*/
|
*/
|
||||||
#define PVA_FW_MBOX_TO_HYP_BASE 2
|
#define PVA_FW_MBOX_TO_HYP_BASE 2U
|
||||||
#define PVA_FW_MBOX_TO_HYP_LAST 7
|
#define PVA_FW_MBOX_TO_HYP_LAST 7U
|
||||||
|
|
||||||
#define PVA_FW_MBOX_FULL_BIT PVA_BIT(31)
|
#define PVA_FW_MBOX_FULL_BIT PVA_BIT(31)
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ static inline uint32_t get_slot_size(struct pva_fw_dma_slot const *slot)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
tmp_size = slot->end_addr - slot->start_addr;
|
tmp_size = slot->end_addr - slot->start_addr;
|
||||||
if (tmp_size > (int64_t)UINT32_MAX) {
|
/* Check for both negative (overflow) and too large values */
|
||||||
|
if ((tmp_size < 0) || (tmp_size > (int64_t)UINT32_MAX)) {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
size = (uint32_t)tmp_size;
|
size = (uint32_t)tmp_size;
|
||||||
@@ -198,7 +199,7 @@ pva_dma_resource_map_add_triggers(struct pva_dma_resource_map *map)
|
|||||||
// If an application is running on VPU, it has access to all the triggers
|
// If an application is running on VPU, it has access to all the triggers
|
||||||
// Only FW and DMA-only workloads can initiate transfers in parallel to
|
// Only FW and DMA-only workloads can initiate transfers in parallel to
|
||||||
// a running VPU application, but they do not require triggers.
|
// a running VPU application, but they do not require triggers.
|
||||||
map->triggers |= 1;
|
map->triggers |= 1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -299,7 +300,7 @@ static inline struct pva_fw_dma_slot *
|
|||||||
pva_dma_config_get_slots(struct pva_dma_config_resource *dma_config)
|
pva_dma_config_get_slots(struct pva_dma_config_resource *dma_config)
|
||||||
{
|
{
|
||||||
return (struct pva_fw_dma_slot
|
return (struct pva_fw_dma_slot
|
||||||
*)((uint8_t *)dma_config +
|
*)(uintptr_t)((uint8_t *)dma_config +
|
||||||
sizeof(struct pva_dma_config_resource));
|
sizeof(struct pva_dma_config_resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +308,8 @@ static inline struct pva_fw_dma_reloc *
|
|||||||
pva_dma_config_get_relocs(struct pva_dma_config_resource *dma_config)
|
pva_dma_config_get_relocs(struct pva_dma_config_resource *dma_config)
|
||||||
{
|
{
|
||||||
return (struct pva_fw_dma_reloc
|
return (struct pva_fw_dma_reloc
|
||||||
*)((uint8_t *)pva_dma_config_get_slots(dma_config) +
|
*)(uintptr_t)((uint8_t *)pva_dma_config_get_slots(
|
||||||
|
dma_config) +
|
||||||
sizeof(struct pva_fw_dma_slot) *
|
sizeof(struct pva_fw_dma_slot) *
|
||||||
dma_config->num_dynamic_slots);
|
dma_config->num_dynamic_slots);
|
||||||
}
|
}
|
||||||
@@ -315,8 +317,8 @@ pva_dma_config_get_relocs(struct pva_dma_config_resource *dma_config)
|
|||||||
static inline struct pva_fw_dma_channel *
|
static inline struct pva_fw_dma_channel *
|
||||||
pva_dma_config_get_channels(struct pva_dma_config_resource *dma_config)
|
pva_dma_config_get_channels(struct pva_dma_config_resource *dma_config)
|
||||||
{
|
{
|
||||||
return (struct pva_fw_dma_channel *)((uint8_t *)
|
return (struct pva_fw_dma_channel
|
||||||
pva_dma_config_get_relocs(
|
*)(uintptr_t)((uint8_t *)pva_dma_config_get_relocs(
|
||||||
dma_config) +
|
dma_config) +
|
||||||
sizeof(struct pva_fw_dma_reloc) *
|
sizeof(struct pva_fw_dma_reloc) *
|
||||||
dma_config->num_relocs);
|
dma_config->num_relocs);
|
||||||
@@ -326,7 +328,8 @@ static inline struct pva_fw_dma_descriptor *
|
|||||||
pva_dma_config_get_descriptors(struct pva_dma_config_resource *dma_config)
|
pva_dma_config_get_descriptors(struct pva_dma_config_resource *dma_config)
|
||||||
{
|
{
|
||||||
return (struct pva_fw_dma_descriptor
|
return (struct pva_fw_dma_descriptor
|
||||||
*)((uint8_t *)pva_dma_config_get_channels(dma_config) +
|
*)(uintptr_t)((uint8_t *)pva_dma_config_get_channels(
|
||||||
|
dma_config) +
|
||||||
sizeof(struct pva_fw_dma_channel) *
|
sizeof(struct pva_fw_dma_channel) *
|
||||||
dma_config->num_channels);
|
dma_config->num_channels);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,15 +105,17 @@ enum pva_error pva_memory_cpu_unmap(struct pva_memory *mem, void *va);
|
|||||||
void pva_memory_free(struct pva_memory *mem);
|
void pva_memory_free(struct pva_memory *mem);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wait for a syncpoint to reach a value.
|
* @brief Wait for a PVA-owned syncpoint to reach a value.
|
||||||
|
*
|
||||||
|
* This function does not work for imported syncpoints.
|
||||||
*
|
*
|
||||||
* @param[in] ctx Pointer to the context.
|
* @param[in] ctx Pointer to the context.
|
||||||
* @param[in] syncpiont_id Syncpoint ID to wait on.
|
* @param[in] syncpoint_id Syncpoint ID to wait on.
|
||||||
* @param[in] value Value to wait for.
|
* @param[in] value Value to wait for.
|
||||||
* @param[in] timeout_us Timeout in microseconds. PVA_SUBMIT_TIMEOUT_INF for infinite.
|
* @param[in] timeout_us Timeout in microseconds. PVA_SUBMIT_TIMEOUT_INF for infinite.
|
||||||
*/
|
*/
|
||||||
enum pva_error pva_syncpoint_wait(struct pva_context *ctx,
|
enum pva_error pva_syncpoint_wait(struct pva_context *ctx,
|
||||||
uint32_t syncpiont_id, uint32_t value,
|
uint32_t syncpoint_id, uint32_t value,
|
||||||
uint64_t timeout_us);
|
uint64_t timeout_us);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,11 +215,70 @@ enum pva_error pva_memory_import_id_create(struct pva_context *ctx,
|
|||||||
*/
|
*/
|
||||||
enum pva_error pva_memory_import_id_destroy(uint64_t import_id);
|
enum pva_error pva_memory_import_id_destroy(uint64_t import_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the asynchronous error for a context.
|
||||||
|
*
|
||||||
|
* Note that other fields are valid only if out_error->error is not PVA_SUCCESS.
|
||||||
|
*
|
||||||
|
* @param[in] ctx Pointer to the context.
|
||||||
|
* @param[out] out_error Pointer to the asynchronous error.
|
||||||
|
* @param[out] out_failure_reason Pointer to a null-terminated string describing the failure reason.
|
||||||
|
*/
|
||||||
|
enum pva_error pva_get_async_error(struct pva_context *ctx,
|
||||||
|
struct pva_async_error *out_error,
|
||||||
|
const char **out_failure_reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Query runtime policy for API usage restrictions.
|
||||||
|
*
|
||||||
|
* Returns the current policy for which categories of the public PVA API are
|
||||||
|
* permitted. Implementations may consult an underlying system-state facility to
|
||||||
|
* determine whether certain API categories (for example, initialization flows)
|
||||||
|
* should be restricted in the current state. If such a facility exists, the
|
||||||
|
* implementation sets api_restrictions accordingly. If no facility exists
|
||||||
|
* or it is unsupported, the implementation returns @ref PVA_API_ALL_ALLOWED.
|
||||||
|
*
|
||||||
|
* @param[out] api_restrictions Pointer that receives the API restriction flags.
|
||||||
|
* On success, set to one of: PVA_API_ALL_ALLOWED
|
||||||
|
* or PVA_API_INIT_NOT_ALLOWED.
|
||||||
|
* @return enum pva_error
|
||||||
|
* - PVA_SUCCESS: Query succeeded and @p api_restrictions is valid
|
||||||
|
* - PVA_ERR_DVMS_GET_VM_STATE_FAILED: Underlying state facility query
|
||||||
|
* failed (when such a facility is used by the implementation)
|
||||||
|
* - PVA_INTERNAL: Internal error when hardware version is not supported
|
||||||
|
*/
|
||||||
|
enum pva_error pva_get_api_restrictions(uint32_t *api_restrictions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of PFSD tests supported by PVA system SW.
|
||||||
|
*
|
||||||
|
* PFSD is not supported on T19x and Linux platforms; in these cases, the function
|
||||||
|
* will indicate that PFSD is not supported by returning zero.
|
||||||
|
* On other supported platforms, it will return the number of PFSD tests supported.
|
||||||
|
*
|
||||||
|
* @param[in] ctx Pointer to the PVA context.
|
||||||
|
* @param[out] pfsd_test_count Pointer to uint32_t to receive the test count.
|
||||||
|
* @return enum pva_error Error status.
|
||||||
|
*/
|
||||||
|
enum pva_error pva_get_pfsd_test_count(struct pva_context *ctx,
|
||||||
|
uint32_t *test_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a PFSD command buffer.
|
||||||
|
*
|
||||||
|
* @param[in] ctx Pointer to the PVA context.
|
||||||
|
* @param[in] test_id Test ID. From 0 to test_count - 1.
|
||||||
|
* @param[out] cmd_buffer_resource_id Command buffer resource ID.
|
||||||
|
* @return enum pva_error Error status.
|
||||||
|
*/
|
||||||
|
enum pva_error pva_get_pfsd_info(struct pva_context *ctx, uint32_t test_id,
|
||||||
|
uint32_t *cmd_buffer_resource_id);
|
||||||
|
|
||||||
/** \brief Specifies the PVA system software major version. */
|
/** \brief Specifies the PVA system software major version. */
|
||||||
#define PVA_SYSSW_MAJOR_VERSION (2U)
|
#define PVA_SYSSW_MAJOR_VERSION (2U)
|
||||||
|
|
||||||
/** \brief Specifies the PVA system software minor version. */
|
/** \brief Specifies the PVA system software minor version. */
|
||||||
#define PVA_SYSSW_MINOR_VERSION (8U)
|
#define PVA_SYSSW_MINOR_VERSION (9U)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ struct pva_dma_misr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pva_user_dma_allowance {
|
struct pva_user_dma_allowance {
|
||||||
#define PVA_USER_DMA_ALLOWANCE_ADB_STEP_SIZE 8
|
#define PVA_USER_DMA_ALLOWANCE_ADB_STEP_SIZE (uint16_t)8
|
||||||
/*desc start index and descriptor count should be multiple of 4*/
|
/*desc start index and descriptor count should be multiple of 4*/
|
||||||
uint32_t channel_idx : 4;
|
uint32_t channel_idx : 4;
|
||||||
uint32_t desc_start_idx : 7;
|
uint32_t desc_start_idx : 7;
|
||||||
@@ -253,7 +253,7 @@ struct pva_cmd_set_vpu_parameter_with_address {
|
|||||||
uint32_t dram_offset_lo;
|
uint32_t dram_offset_lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PVA_MAX_DMA_SETS_PER_DMA_ENGINE 4
|
#define PVA_MAX_DMA_SETS_PER_DMA_ENGINE 4U
|
||||||
|
|
||||||
/** This command first acquires the TCM scratch and then fetches DMA configuration
|
/** This command first acquires the TCM scratch and then fetches DMA configuration
|
||||||
* into the scratch. The command does not modify DMA
|
* into the scratch. The command does not modify DMA
|
||||||
|
|||||||
@@ -82,19 +82,19 @@ struct pva_dma_transfer_attr {
|
|||||||
/** When dynamic slot flag is set, it means the memory location will be
|
/** When dynamic slot flag is set, it means the memory location will be
|
||||||
* relocated by commands.
|
* relocated by commands.
|
||||||
*/
|
*/
|
||||||
#define PVA_DMA_DYNAMIC_SLOT (1 << 15)
|
#define PVA_DMA_DYNAMIC_SLOT ((uint16_t)1U << 15)
|
||||||
#define PVA_DMA_STATIC_SLOT (1 << 14)
|
#define PVA_DMA_STATIC_SLOT ((uint16_t)1U << 14)
|
||||||
#define PVA_DMA_SLOT_INVALID 0
|
#define PVA_DMA_SLOT_INVALID 0
|
||||||
#define PVA_DMA_SLOT_ID_MASK 0xFF
|
#define PVA_DMA_SLOT_ID_MASK 0xFFU
|
||||||
#define PVA_DMA_MAX_NUM_SLOTS 256
|
#define PVA_DMA_MAX_NUM_SLOTS 256
|
||||||
uint16_t slot;
|
uint16_t slot;
|
||||||
/** Line pitch in pixels */
|
/** Line pitch in pixels */
|
||||||
uint16_t line_pitch;
|
uint16_t line_pitch;
|
||||||
uint32_t cb_start;
|
uint32_t cb_start;
|
||||||
uint32_t cb_size;
|
uint32_t cb_size;
|
||||||
int32_t adv1;
|
uint32_t adv1;
|
||||||
int32_t adv2;
|
uint32_t adv2;
|
||||||
int32_t adv3;
|
uint32_t adv3;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ enum pva_dma_static_binding_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Max block height is 32 GOB */
|
/** Max block height is 32 GOB */
|
||||||
#define PVA_DMA_MAX_LOG2_BLOCK_HEIGHT 5
|
#define PVA_DMA_MAX_LOG2_BLOCK_HEIGHT 5U
|
||||||
|
|
||||||
struct pva_dma_dram_binding {
|
struct pva_dma_dram_binding {
|
||||||
/** enum pva_surface_format */
|
/** enum pva_surface_format */
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct pva_ops_memory {
|
|||||||
* until memory->size is reached.
|
* until memory->size is reached.
|
||||||
*/
|
*/
|
||||||
struct pva_ops_buffer {
|
struct pva_ops_buffer {
|
||||||
struct pva_ops_memory *memory; /**< Pointer to buffer memory */
|
struct pva_ops_memory *mem_ptr; /**< Pointer to buffer memory */
|
||||||
uint64_t start_offset; /**< Start offset in buffer memory */
|
uint64_t start_offset; /**< Start offset in buffer memory */
|
||||||
uint64_t end_offset; /**< End offset (exclusive) in buffer memory */
|
uint64_t end_offset; /**< End offset (exclusive) in buffer memory */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,12 +2,18 @@
|
|||||||
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
#ifndef PVA_API_TYPES_H
|
#ifndef PVA_API_TYPES_H
|
||||||
#define PVA_API_TYPES_H
|
#define PVA_API_TYPES_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
/* Use offsetof to avoid INT36-C violation from NULL pointer arithmetic */
|
||||||
#define container_of(ptr, type, member) \
|
#define container_of(ptr, type, member) \
|
||||||
(type *)((char *)(ptr) - (char *)&((type *)0)->member)
|
((type *)((char *)(ptr)-offsetof(type, member)))
|
||||||
#else
|
#else
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
@@ -17,10 +23,6 @@
|
|||||||
#define UINT32_MAX U32_MAX
|
#define UINT32_MAX U32_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL ((void *)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define FOREACH_ERR(ACT) \
|
#define FOREACH_ERR(ACT) \
|
||||||
ACT(PVA_SUCCESS) \
|
ACT(PVA_SUCCESS) \
|
||||||
ACT(PVA_UNKNOWN_ERROR) \
|
ACT(PVA_UNKNOWN_ERROR) \
|
||||||
@@ -135,6 +137,11 @@
|
|||||||
ACT(PVA_ERR_GOLDEN_REG_MISMATCH) \
|
ACT(PVA_ERR_GOLDEN_REG_MISMATCH) \
|
||||||
ACT(PVA_ERR_CRITICAL_REG_MISMATCH) \
|
ACT(PVA_ERR_CRITICAL_REG_MISMATCH) \
|
||||||
ACT(PVA_ERR_CONFIG_REG_MISMATCH) \
|
ACT(PVA_ERR_CONFIG_REG_MISMATCH) \
|
||||||
|
ACT(PVA_ERR_BAD_CONTEXT) \
|
||||||
|
ACT(PVA_ERR_BAD_DEVICE) \
|
||||||
|
ACT(PVA_ERR_FAST_RESET_FAILURE) \
|
||||||
|
ACT(PVA_ERR_DVMS_GET_VM_STATE_FAILED) \
|
||||||
|
ACT(PVA_ERR_INVALID_VPU_SYSCALL) \
|
||||||
ACT(PVA_ERR_CODE_COUNT)
|
ACT(PVA_ERR_CODE_COUNT)
|
||||||
|
|
||||||
enum pva_error {
|
enum pva_error {
|
||||||
@@ -156,6 +163,20 @@ enum pva_hw_gen {
|
|||||||
PVA_HW_GEN3,
|
PVA_HW_GEN3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief API restriction flags reported by @ref pva_get_api_restrictions.
|
||||||
|
*
|
||||||
|
* These flags indicate which categories of the public API are permitted by the
|
||||||
|
* current platform/runtime policy. Implementations currently set exactly one
|
||||||
|
* of the flags below, but the type is defined as bit-flags for forward
|
||||||
|
* compatibility.
|
||||||
|
*/
|
||||||
|
/** No restrictions: all API categories are permitted. */
|
||||||
|
#define PVA_API_ALL_ALLOWED (0U)
|
||||||
|
/** Initialization-related APIs are not permitted in the current state.
|
||||||
|
* Callers must defer creation/initialization flows until allowed. */
|
||||||
|
#define PVA_API_INIT_NOT_ALLOWED (1U)
|
||||||
|
|
||||||
/* Opaque API data types */
|
/* Opaque API data types */
|
||||||
struct pva_context;
|
struct pva_context;
|
||||||
struct pva_queue;
|
struct pva_queue;
|
||||||
@@ -282,10 +303,10 @@ struct pva_symbol_info {
|
|||||||
// unify timeout to uint64_t, in microseconds
|
// unify timeout to uint64_t, in microseconds
|
||||||
#define PVA_SUBMIT_TIMEOUT_INF UINT64_MAX /**< Infinite timeout */
|
#define PVA_SUBMIT_TIMEOUT_INF UINT64_MAX /**< Infinite timeout */
|
||||||
|
|
||||||
#define PVA_MAX_NUM_INPUT_STATUS 2 /**< Maximum number of input statuses */
|
#define PVA_MAX_NUM_INPUT_STATUS 2U /**< Maximum number of input statuses */
|
||||||
#define PVA_MAX_NUM_OUTPUT_STATUS 2 /**< Maximum number of output statuses */
|
#define PVA_MAX_NUM_OUTPUT_STATUS 2U /**< Maximum number of output statuses */
|
||||||
#define PVA_MAX_NUM_PREFENCES 2 /**< Maximum number of pre-fences */
|
#define PVA_MAX_NUM_PREFENCES 2U /**< Maximum number of pre-fences */
|
||||||
#define PVA_MAX_NUM_POSTFENCES 2 /**< Maximum number of post-fences */
|
#define PVA_MAX_NUM_POSTFENCES 2U /**< Maximum number of post-fences */
|
||||||
/** Maximum number of timestamps */
|
/** Maximum number of timestamps */
|
||||||
#define PVA_MAX_NUM_TIMESTAMPS PVA_MAX_NUM_POSTFENCES
|
#define PVA_MAX_NUM_TIMESTAMPS PVA_MAX_NUM_POSTFENCES
|
||||||
|
|
||||||
@@ -296,8 +317,8 @@ struct pva_cmdbuf_submit_info {
|
|||||||
uint8_t num_output_status;
|
uint8_t num_output_status;
|
||||||
uint8_t num_timestamps;
|
uint8_t num_timestamps;
|
||||||
#define PVA_ENGINE_AFFINITY_NONE 0
|
#define PVA_ENGINE_AFFINITY_NONE 0
|
||||||
#define PVA_ENGINE_AFFINITY_ENGINE0 (1 << 0)
|
#define PVA_ENGINE_AFFINITY_ENGINE0 (1U << 0)
|
||||||
#define PVA_ENGINE_AFFINITY_ENGINE1 (1 << 1)
|
#define PVA_ENGINE_AFFINITY_ENGINE1 (1U << 1)
|
||||||
#define PVA_ENGINE_AFFINITY_ANY \
|
#define PVA_ENGINE_AFFINITY_ANY \
|
||||||
(PVA_ENGINE_AFFINITY_ENGINE0 | PVA_ENGINE_AFFINITY_ENGINE1)
|
(PVA_ENGINE_AFFINITY_ENGINE0 | PVA_ENGINE_AFFINITY_ENGINE1)
|
||||||
uint8_t engine_affinity;
|
uint8_t engine_affinity;
|
||||||
@@ -311,7 +332,7 @@ struct pva_cmdbuf_submit_info {
|
|||||||
uint64_t first_chunk_offset;
|
uint64_t first_chunk_offset;
|
||||||
/** Execution timeout is in ms */
|
/** Execution timeout is in ms */
|
||||||
#define PVA_EXEC_TIMEOUT_INF UINT32_MAX
|
#define PVA_EXEC_TIMEOUT_INF UINT32_MAX
|
||||||
#define PVA_EXEC_TIMEOUT_REUSE (UINT32_MAX - 1)
|
#define PVA_EXEC_TIMEOUT_REUSE (UINT32_MAX - 1U)
|
||||||
/** Execution Timeout */
|
/** Execution Timeout */
|
||||||
uint32_t execution_timeout_ms;
|
uint32_t execution_timeout_ms;
|
||||||
struct pva_fence prefences[PVA_MAX_NUM_PREFENCES];
|
struct pva_fence prefences[PVA_MAX_NUM_PREFENCES];
|
||||||
@@ -355,8 +376,8 @@ struct pva_characteristics {
|
|||||||
* !!!! DO NOT MODIFY !!!!!!
|
* !!!! DO NOT MODIFY !!!!!!
|
||||||
* These values are defined as per DriveOS guidelines
|
* These values are defined as per DriveOS guidelines
|
||||||
*/
|
*/
|
||||||
#define PVA_INPUT_STATUS_SUCCESS (0)
|
#define PVA_INPUT_STATUS_SUCCESS ((uint16_t)(0))
|
||||||
#define PVA_INPUT_STATUS_INVALID (0xFFFF)
|
#define PVA_INPUT_STATUS_INVALID ((uint16_t)(0xFFFF))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Context attribute keys.
|
* @brief Context attribute keys.
|
||||||
@@ -374,4 +395,16 @@ struct pva_ctx_attr_max_cmdbuf_chunk_size {
|
|||||||
uint16_t max_size;
|
uint16_t max_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pva_async_error {
|
||||||
|
uint32_t error;
|
||||||
|
uint32_t queue_id;
|
||||||
|
uint32_t cmd_idx;
|
||||||
|
int32_t vpu_retcode;
|
||||||
|
uint64_t submit_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // PVA_API_TYPES_H
|
#endif // PVA_API_TYPES_H
|
||||||
|
|||||||
8192
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.0.csv
Normal file
8192
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.0.csv
Normal file
File diff suppressed because it is too large
Load Diff
2048
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.1.csv
Normal file
2048
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.1.csv
Normal file
File diff suppressed because it is too large
Load Diff
4096
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.2.csv
Normal file
4096
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.2.csv
Normal file
File diff suppressed because it is too large
Load Diff
4096
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.3.csv
Normal file
4096
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/indices.3.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,256 @@
|
|||||||
|
0,
|
||||||
|
10,
|
||||||
|
20,
|
||||||
|
30,
|
||||||
|
40,
|
||||||
|
50,
|
||||||
|
60,
|
||||||
|
70,
|
||||||
|
80,
|
||||||
|
90,
|
||||||
|
100,
|
||||||
|
110,
|
||||||
|
120,
|
||||||
|
130,
|
||||||
|
140,
|
||||||
|
150,
|
||||||
|
160,
|
||||||
|
170,
|
||||||
|
180,
|
||||||
|
190,
|
||||||
|
200,
|
||||||
|
210,
|
||||||
|
220,
|
||||||
|
230,
|
||||||
|
240,
|
||||||
|
250,
|
||||||
|
260,
|
||||||
|
270,
|
||||||
|
280,
|
||||||
|
290,
|
||||||
|
300,
|
||||||
|
310,
|
||||||
|
320,
|
||||||
|
330,
|
||||||
|
340,
|
||||||
|
350,
|
||||||
|
360,
|
||||||
|
370,
|
||||||
|
380,
|
||||||
|
390,
|
||||||
|
400,
|
||||||
|
410,
|
||||||
|
420,
|
||||||
|
430,
|
||||||
|
440,
|
||||||
|
450,
|
||||||
|
460,
|
||||||
|
470,
|
||||||
|
480,
|
||||||
|
490,
|
||||||
|
500,
|
||||||
|
510,
|
||||||
|
520,
|
||||||
|
530,
|
||||||
|
540,
|
||||||
|
550,
|
||||||
|
560,
|
||||||
|
570,
|
||||||
|
580,
|
||||||
|
590,
|
||||||
|
600,
|
||||||
|
610,
|
||||||
|
620,
|
||||||
|
630,
|
||||||
|
640,
|
||||||
|
650,
|
||||||
|
660,
|
||||||
|
670,
|
||||||
|
680,
|
||||||
|
690,
|
||||||
|
700,
|
||||||
|
710,
|
||||||
|
720,
|
||||||
|
730,
|
||||||
|
740,
|
||||||
|
750,
|
||||||
|
760,
|
||||||
|
770,
|
||||||
|
780,
|
||||||
|
790,
|
||||||
|
800,
|
||||||
|
810,
|
||||||
|
820,
|
||||||
|
830,
|
||||||
|
840,
|
||||||
|
850,
|
||||||
|
860,
|
||||||
|
870,
|
||||||
|
880,
|
||||||
|
890,
|
||||||
|
900,
|
||||||
|
910,
|
||||||
|
920,
|
||||||
|
930,
|
||||||
|
940,
|
||||||
|
950,
|
||||||
|
960,
|
||||||
|
970,
|
||||||
|
980,
|
||||||
|
990,
|
||||||
|
1000,
|
||||||
|
1010,
|
||||||
|
1020,
|
||||||
|
1030,
|
||||||
|
1040,
|
||||||
|
1050,
|
||||||
|
1060,
|
||||||
|
1070,
|
||||||
|
1080,
|
||||||
|
1090,
|
||||||
|
1100,
|
||||||
|
1110,
|
||||||
|
1120,
|
||||||
|
1130,
|
||||||
|
1140,
|
||||||
|
1150,
|
||||||
|
1160,
|
||||||
|
1170,
|
||||||
|
1180,
|
||||||
|
1190,
|
||||||
|
1200,
|
||||||
|
1210,
|
||||||
|
1220,
|
||||||
|
1230,
|
||||||
|
1240,
|
||||||
|
1250,
|
||||||
|
1260,
|
||||||
|
1270,
|
||||||
|
1280,
|
||||||
|
1290,
|
||||||
|
1300,
|
||||||
|
1310,
|
||||||
|
1320,
|
||||||
|
1330,
|
||||||
|
1340,
|
||||||
|
1350,
|
||||||
|
1360,
|
||||||
|
1370,
|
||||||
|
1380,
|
||||||
|
1390,
|
||||||
|
1400,
|
||||||
|
1410,
|
||||||
|
1420,
|
||||||
|
1430,
|
||||||
|
1440,
|
||||||
|
1450,
|
||||||
|
1460,
|
||||||
|
1470,
|
||||||
|
1480,
|
||||||
|
1490,
|
||||||
|
1500,
|
||||||
|
1510,
|
||||||
|
1520,
|
||||||
|
1530,
|
||||||
|
1540,
|
||||||
|
1550,
|
||||||
|
1560,
|
||||||
|
1570,
|
||||||
|
1580,
|
||||||
|
1590,
|
||||||
|
1600,
|
||||||
|
1610,
|
||||||
|
1620,
|
||||||
|
1630,
|
||||||
|
1640,
|
||||||
|
1650,
|
||||||
|
1660,
|
||||||
|
1670,
|
||||||
|
1680,
|
||||||
|
1690,
|
||||||
|
1700,
|
||||||
|
1710,
|
||||||
|
1720,
|
||||||
|
1730,
|
||||||
|
1740,
|
||||||
|
1750,
|
||||||
|
1760,
|
||||||
|
1770,
|
||||||
|
1780,
|
||||||
|
1790,
|
||||||
|
1800,
|
||||||
|
1810,
|
||||||
|
1820,
|
||||||
|
1830,
|
||||||
|
1840,
|
||||||
|
1850,
|
||||||
|
1860,
|
||||||
|
1870,
|
||||||
|
1880,
|
||||||
|
1890,
|
||||||
|
1900,
|
||||||
|
1910,
|
||||||
|
1920,
|
||||||
|
1930,
|
||||||
|
1940,
|
||||||
|
1950,
|
||||||
|
1960,
|
||||||
|
1970,
|
||||||
|
1980,
|
||||||
|
1990,
|
||||||
|
2000,
|
||||||
|
2010,
|
||||||
|
2020,
|
||||||
|
2030,
|
||||||
|
2040,
|
||||||
|
2050,
|
||||||
|
2060,
|
||||||
|
2070,
|
||||||
|
2080,
|
||||||
|
2090,
|
||||||
|
2100,
|
||||||
|
2110,
|
||||||
|
2120,
|
||||||
|
2130,
|
||||||
|
2140,
|
||||||
|
2150,
|
||||||
|
2160,
|
||||||
|
2170,
|
||||||
|
2180,
|
||||||
|
2190,
|
||||||
|
2200,
|
||||||
|
2210,
|
||||||
|
2220,
|
||||||
|
2230,
|
||||||
|
2240,
|
||||||
|
2250,
|
||||||
|
2260,
|
||||||
|
2270,
|
||||||
|
2280,
|
||||||
|
2290,
|
||||||
|
2300,
|
||||||
|
2310,
|
||||||
|
2320,
|
||||||
|
2330,
|
||||||
|
2340,
|
||||||
|
2350,
|
||||||
|
2360,
|
||||||
|
2370,
|
||||||
|
2380,
|
||||||
|
2390,
|
||||||
|
2400,
|
||||||
|
2410,
|
||||||
|
2420,
|
||||||
|
2430,
|
||||||
|
2440,
|
||||||
|
2450,
|
||||||
|
2460,
|
||||||
|
2470,
|
||||||
|
2480,
|
||||||
|
2490,
|
||||||
|
2500,
|
||||||
|
2510,
|
||||||
|
2520,
|
||||||
|
2530,
|
||||||
|
2540,
|
||||||
|
2550,
|
||||||
|
28672
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/table.1.csv
Normal file
28672
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/table.1.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
|||||||
|
108U,107U,107U,108U,107U,105U,105U,105U,105U,105U,106U,107U,108U,108U,108U,108U,108U,111U,111U,111U,110U,108U,108U,108U,110U,112U,117U,126U,144U,162U,172U,175U,175U,175U,172U,172U,172U,173U,174U,175U,174U,176U,176U,175U,175U,175U,175U,175U,175U,175U,175U,175U,178U,175U,174U,174U,174U,175U,176U,174U,174U,174U,172U,172U,169U,170U,170U,161U,134U,108U,93U,89U,93U,98U,97U,97U,96U,93U,91U,91U,92U,94U,92U,91U,90U,89U,90U,91U,93U,94U,96U,94U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
113U,112U,113U,114U,113U,112U,112U,111U,111U,111U,111U,112U,112U,112U,112U,112U,112U,114U,114U,116U,117U,117U,114U,116U,116U,121U,133U,147U,160U,169U,174U,175U,175U,175U,174U,173U,174U,175U,174U,174U,175U,174U,174U,175U,175U,175U,175U,175U,175U,175U,175U,175U,176U,175U,174U,176U,176U,175U,174U,173U,173U,173U,172U,171U,169U,168U,167U,151U,126U,109U,102U,102U,104U,105U,106U,105U,103U,102U,103U,103U,102U,102U,100U,98U,98U,99U,100U,102U,103U,103U,104U,103U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
118U,117U,119U,118U,117U,117U,117U,117U,117U,118U,117U,117U,117U,116U,116U,116U,116U,117U,118U,117U,119U,120U,120U,121U,125U,137U,150U,162U,171U,175U,176U,176U,176U,175U,175U,175U,176U,176U,176U,175U,175U,174U,174U,175U,175U,175U,175U,175U,174U,174U,175U,175U,175U,175U,176U,178U,178U,178U,178U,175U,175U,173U,171U,171U,168U,166U,159U,143U,123U,112U,111U,113U,113U,111U,114U,113U,110U,109U,109U,110U,109U,106U,106U,105U,105U,107U,107U,110U,109U,109U,107U,106U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
120U,119U,118U,117U,116U,116U,117U,118U,119U,120U,120U,119U,119U,117U,118U,120U,121U,121U,120U,119U,118U,121U,122U,122U,136U,152U,162U,169U,174U,178U,178U,176U,175U,175U,174U,174U,175U,175U,175U,175U,174U,174U,174U,174U,174U,174U,174U,174U,173U,173U,174U,174U,175U,176U,178U,178U,178U,179U,180U,179U,179U,174U,169U,166U,164U,162U,153U,137U,122U,117U,118U,118U,118U,119U,121U,120U,119U,118U,116U,113U,113U,114U,116U,114U,114U,116U,117U,119U,118U,118U,119U,118U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
122U,122U,122U,121U,121U,122U,124U,125U,125U,126U,129U,127U,127U,129U,130U,129U,130U,132U,131U,131U,132U,133U,134U,136U,147U,161U,167U,173U,175U,175U,178U,178U,174U,175U,177U,177U,175U,177U,175U,175U,174U,175U,177U,174U,174U,174U,174U,174U,174U,174U,174U,174U,176U,178U,178U,178U,179U,179U,181U,181U,179U,174U,171U,165U,161U,160U,154U,143U,134U,134U,134U,134U,134U,136U,137U,138U,139U,139U,136U,131U,132U,136U,137U,136U,132U,132U,132U,134U,134U,136U,143U,143U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
138U,143U,147U,150U,147U,147U,148U,150U,152U,153U,154U,152U,150U,151U,152U,150U,150U,152U,152U,153U,157U,159U,159U,160U,162U,166U,171U,174U,175U,175U,176U,176U,177U,177U,179U,178U,177U,177U,177U,177U,177U,175U,175U,175U,174U,174U,174U,174U,174U,174U,174U,175U,176U,176U,176U,176U,176U,176U,180U,180U,176U,174U,171U,166U,161U,161U,164U,164U,161U,161U,161U,161U,161U,161U,162U,165U,165U,167U,165U,159U,160U,165U,166U,166U,162U,161U,160U,161U,161U,162U,172U,172U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
162U,164U,169U,174U,176U,179U,179U,179U,181U,181U,179U,179U,176U,175U,175U,172U,172U,174U,174U,174U,175U,178U,176U,175U,173U,171U,172U,174U,175U,176U,178U,179U,178U,178U,179U,179U,177U,177U,177U,177U,177U,175U,174U,175U,175U,175U,174U,174U,174U,174U,174U,175U,176U,176U,175U,175U,174U,174U,175U,174U,172U,169U,169U,166U,162U,165U,173U,180U,183U,183U,183U,182U,181U,181U,183U,183U,183U,183U,183U,180U,181U,185U,185U,183U,181U,180U,179U,180U,180U,181U,185U,186U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
168U,161U,169U,179U,189U,195U,195U,193U,192U,190U,189U,192U,192U,190U,188U,187U,188U,188U,189U,186U,184U,183U,179U,176U,175U,173U,173U,174U,174U,177U,178U,178U,178U,178U,179U,179U,179U,179U,177U,178U,177U,174U,175U,177U,177U,174U,174U,174U,174U,174U,175U,177U,176U,174U,173U,173U,172U,172U,171U,169U,168U,167U,168U,166U,164U,168U,178U,185U,187U,188U,188U,188U,187U,188U,189U,189U,187U,188U,189U,188U,186U,187U,187U,186U,186U,185U,182U,183U,185U,185U,185U,186U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
166U,158U,165U,172U,181U,188U,189U,190U,189U,188U,189U,192U,193U,193U,193U,190U,192U,192U,193U,191U,187U,182U,176U,174U,174U,175U,174U,174U,174U,177U,177U,177U,178U,179U,180U,180U,182U,180U,179U,178U,177U,175U,175U,175U,175U,174U,174U,173U,173U,174U,175U,175U,175U,173U,173U,172U,172U,172U,171U,171U,169U,169U,168U,166U,166U,168U,175U,180U,181U,181U,181U,183U,185U,186U,187U,186U,186U,187U,187U,187U,185U,183U,185U,185U,185U,183U,183U,183U,183U,185U,186U,186U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
173U,169U,168U,169U,169U,169U,171U,173U,175U,179U,187U,192U,190U,190U,192U,192U,190U,192U,193U,189U,184U,180U,174U,173U,174U,174U,174U,177U,175U,177U,178U,179U,180U,180U,181U,181U,181U,179U,179U,179U,179U,177U,177U,175U,175U,175U,175U,174U,173U,175U,175U,174U,174U,173U,172U,171U,171U,172U,172U,171U,171U,171U,168U,165U,165U,167U,171U,175U,179U,179U,179U,182U,183U,185U,186U,186U,187U,187U,185U,183U,183U,185U,185U,185U,185U,185U,186U,186U,186U,186U,187U,188U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
183U,183U,181U,178U,171U,161U,155U,154U,161U,169U,183U,193U,192U,190U,192U,193U,192U,192U,193U,187U,182U,179U,174U,173U,174U,174U,177U,178U,178U,179U,179U,180U,181U,182U,182U,181U,181U,180U,179U,180U,180U,178U,177U,177U,176U,175U,175U,176U,177U,178U,177U,174U,174U,174U,173U,172U,172U,172U,173U,172U,169U,168U,168U,168U,167U,168U,172U,176U,180U,181U,182U,185U,186U,186U,187U,188U,189U,188U,185U,185U,186U,187U,188U,187U,186U,187U,189U,188U,189U,188U,189U,190U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
190U,189U,190U,193U,181U,167U,152U,147U,155U,165U,169U,183U,193U,192U,190U,192U,194U,193U,192U,185U,176U,171U,171U,171U,174U,176U,177U,178U,180U,180U,181U,181U,182U,185U,183U,182U,181U,179U,180U,179U,178U,177U,176U,178U,178U,176U,175U,176U,179U,181U,183U,182U,181U,179U,177U,176U,176U,176U,176U,176U,173U,167U,168U,172U,171U,172U,174U,177U,180U,181U,185U,186U,186U,187U,186U,186U,188U,188U,189U,189U,187U,187U,187U,187U,186U,187U,188U,187U,187U,188U,189U,189U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
190U,190U,190U,194U,192U,185U,173U,162U,154U,148U,148U,162U,183U,193U,192U,190U,192U,189U,186U,180U,172U,165U,164U,166U,171U,178U,178U,178U,179U,180U,180U,180U,181U,180U,180U,182U,178U,175U,176U,176U,174U,174U,176U,178U,179U,178U,175U,178U,180U,180U,182U,182U,180U,173U,172U,173U,172U,170U,169U,169U,169U,166U,164U,164U,165U,167U,168U,170U,173U,177U,179U,181U,181U,181U,181U,182U,186U,186U,187U,187U,186U,185U,185U,185U,186U,185U,185U,185U,185U,186U,187U,186U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
194U,194U,195U,197U,197U,194U,193U,182U,159U,139U,141U,157U,179U,195U,199U,197U,194U,190U,188U,181U,178U,174U,174U,174U,178U,180U,180U,180U,181U,181U,181U,180U,178U,176U,178U,180U,177U,178U,180U,181U,180U,178U,180U,179U,181U,185U,185U,182U,181U,180U,179U,176U,173U,171U,171U,169U,167U,165U,164U,162U,164U,160U,157U,158U,163U,165U,168U,172U,174U,178U,178U,179U,182U,185U,185U,184U,182U,182U,182U,184U,186U,187U,189U,192U,192U,192U,192U,192U,193U,192U,193U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
213U,213U,211U,211U,210U,207U,210U,195U,172U,155U,171U,187U,200U,210U,216U,215U,210U,207U,206U,201U,201U,202U,201U,201U,199U,197U,195U,195U,195U,196U,196U,195U,196U,195U,194U,193U,193U,194U,196U,196U,195U,194U,200U,200U,203U,207U,207U,203U,201U,200U,199U,197U,196U,199U,199U,189U,188U,192U,192U,188U,172U,154U,161U,180U,189U,192U,193U,195U,198U,200U,201U,200U,207U,209U,207U,205U,203U,203U,203U,205U,207U,209U,210U,213U,213U,213U,213U,213U,214U,214U,215U,215U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
236U,235U,234U,234U,233U,233U,218U,200U,193U,199U,218U,230U,231U,230U,234U,235U,235U,236U,235U,235U,236U,237U,237U,237U,232U,223U,214U,213U,214U,214U,215U,219U,221U,223U,225U,225U,227U,228U,226U,225U,225U,225U,225U,225U,226U,227U,230U,233U,233U,231U,230U,230U,229U,229U,228U,227U,221U,221U,222U,222U,182U,153U,172U,208U,225U,226U,227U,227U,227U,228U,228U,228U,230U,232U,230U,229U,229U,229U,230U,232U,232U,232U,232U,232U,234U,236U,237U,238U,238U,237U,237U,237U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
239U,239U,240U,240U,240U,240U,221U,200U,207U,223U,240U,243U,240U,238U,238U,240U,241U,240U,240U,237U,236U,236U,235U,233U,223U,214U,199U,199U,200U,201U,203U,208U,214U,220U,221U,221U,223U,223U,222U,221U,220U,220U,219U,220U,221U,221U,223U,226U,227U,229U,228U,228U,227U,226U,226U,226U,226U,224U,220U,213U,183U,159U,184U,223U,239U,238U,238U,238U,238U,238U,237U,238U,235U,233U,230U,230U,230U,229U,230U,230U,232U,233U,233U,234U,236U,238U,238U,238U,237U,236U,235U,233U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
220U,221U,223U,224U,226U,220U,196U,176U,183U,202U,222U,230U,224U,222U,222U,222U,220U,216U,214U,211U,207U,204U,202U,196U,191U,186U,185U,184U,182U,181U,181U,182U,186U,189U,192U,194U,196U,195U,193U,193U,192U,191U,191U,191U,192U,192U,193U,194U,195U,199U,199U,199U,199U,197U,197U,196U,201U,196U,185U,172U,160U,157U,183U,210U,222U,220U,218U,220U,221U,222U,221U,220U,213U,208U,206U,208U,208U,208U,207U,207U,208U,209U,212U,212U,213U,212U,209U,208U,207U,207U,207U,206U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
193U,193U,199U,203U,201U,192U,172U,152U,150U,164U,190U,206U,202U,199U,197U,195U,193U,190U,192U,193U,193U,190U,186U,182U,180U,181U,181U,180U,178U,175U,177U,174U,175U,175U,177U,178U,181U,180U,178U,179U,179U,179U,178U,178U,179U,179U,179U,180U,182U,182U,183U,182U,181U,180U,179U,179U,179U,173U,167U,158U,153U,157U,181U,194U,197U,194U,193U,193U,192U,192U,193U,193U,191U,189U,192U,194U,194U,192U,189U,189U,189U,191U,192U,193U,191U,187U,185U,184U,185U,186U,187U,188U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
181U,182U,186U,189U,187U,179U,158U,141U,133U,143U,164U,186U,190U,188U,186U,181U,179U,179U,178U,181U,183U,183U,186U,186U,186U,187U,187U,186U,185U,184U,180U,182U,181U,180U,180U,179U,180U,181U,181U,183U,183U,185U,183U,183U,182U,182U,181U,181U,182U,181U,181U,180U,180U,179U,178U,174U,171U,164U,161U,161U,164U,171U,181U,189U,192U,189U,188U,187U,185U,185U,187U,188U,188U,189U,189U,191U,188U,186U,185U,184U,184U,184U,185U,185U,185U,185U,185U,185U,186U,187U,188U,189U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
179U,180U,181U,181U,179U,171U,151U,141U,139U,147U,164U,179U,183U,182U,181U,181U,181U,182U,185U,185U,187U,188U,187U,187U,186U,187U,186U,186U,186U,185U,184U,184U,182U,182U,181U,181U,183U,183U,185U,185U,185U,185U,183U,185U,185U,183U,182U,182U,181U,182U,180U,181U,180U,180U,179U,172U,162U,155U,150U,158U,173U,182U,189U,192U,193U,193U,192U,187U,189U,192U,190U,192U,192U,192U,191U,191U,189U,189U,188U,187U,187U,188U,191U,191U,193U,193U,192U,191U,191U,191U,192U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
178U,178U,180U,178U,175U,166U,151U,146U,155U,166U,179U,181U,180U,180U,181U,182U,183U,185U,185U,186U,186U,187U,187U,187U,186U,187U,186U,186U,186U,185U,185U,185U,184U,184U,181U,181U,183U,183U,183U,183U,183U,183U,182U,182U,182U,183U,182U,182U,182U,182U,181U,181U,180U,180U,180U,173U,161U,150U,145U,157U,174U,186U,189U,189U,191U,188U,187U,186U,188U,189U,189U,190U,191U,188U,188U,191U,191U,191U,189U,188U,188U,189U,192U,192U,193U,193U,191U,191U,191U,191U,193U,194U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
176U,176U,178U,175U,172U,165U,159U,159U,165U,173U,186U,181U,178U,178U,181U,181U,183U,185U,186U,187U,188U,188U,188U,187U,186U,187U,186U,186U,186U,186U,186U,185U,185U,184U,182U,181U,183U,183U,183U,182U,182U,183U,182U,182U,182U,183U,182U,182U,182U,182U,182U,181U,180U,181U,182U,176U,162U,150U,146U,158U,176U,187U,189U,191U,191U,187U,187U,188U,187U,187U,189U,193U,191U,188U,189U,192U,191U,189U,189U,189U,189U,191U,189U,192U,193U,193U,192U,193U,193U,193U,194U,195U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
179U,180U,179U,175U,173U,167U,167U,168U,171U,173U,174U,178U,176U,179U,183U,183U,183U,185U,187U,187U,188U,188U,189U,189U,188U,188U,187U,187U,186U,186U,186U,186U,185U,185U,182U,182U,182U,182U,183U,183U,182U,183U,183U,182U,182U,182U,182U,182U,182U,182U,182U,181U,181U,181U,182U,178U,162U,151U,150U,160U,176U,187U,192U,193U,192U,190U,190U,190U,189U,189U,190U,192U,191U,189U,191U,192U,192U,192U,191U,191U,191U,191U,192U,192U,193U,193U,194U,194U,195U,195U,195U,195U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
180U,181U,180U,179U,175U,173U,168U,159U,155U,157U,162U,172U,176U,180U,183U,183U,186U,186U,187U,187U,187U,188U,189U,189U,188U,188U,187U,187U,186U,186U,186U,186U,185U,185U,184U,184U,184U,182U,183U,183U,182U,182U,182U,181U,182U,182U,182U,182U,182U,182U,181U,181U,181U,180U,181U,178U,165U,155U,158U,165U,179U,188U,192U,194U,193U,192U,190U,190U,190U,190U,190U,190U,188U,188U,189U,191U,192U,192U,191U,191U,191U,191U,192U,192U,192U,193U,194U,194U,195U,195U,196U,196U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
181U,181U,181U,181U,179U,175U,171U,154U,138U,137U,146U,165U,176U,181U,183U,183U,186U,188U,186U,186U,187U,188U,188U,188U,188U,188U,187U,187U,186U,186U,186U,186U,186U,185U,184U,184U,185U,184U,185U,183U,182U,182U,182U,181U,182U,182U,182U,182U,182U,182U,181U,181U,180U,180U,179U,175U,172U,164U,168U,173U,180U,186U,192U,193U,192U,192U,190U,190U,190U,189U,188U,189U,187U,188U,192U,191U,191U,192U,192U,192U,192U,192U,192U,192U,192U,193U,194U,194U,195U,196U,196U,196U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
180U,181U,180U,180U,179U,178U,174U,164U,146U,139U,145U,161U,176U,182U,183U,183U,186U,187U,186U,186U,187U,187U,188U,188U,188U,188U,186U,186U,186U,185U,185U,185U,185U,184U,184U,184U,184U,182U,183U,183U,182U,182U,182U,182U,182U,182U,182U,182U,182U,182U,181U,180U,181U,181U,180U,178U,174U,172U,174U,178U,180U,186U,192U,193U,192U,192U,192U,190U,190U,188U,188U,188U,186U,188U,191U,191U,191U,192U,192U,192U,192U,192U,192U,192U,192U,193U,194U,194U,195U,196U,196U,196U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
182U,180U,179U,179U,179U,179U,176U,176U,167U,158U,154U,165U,175U,182U,183U,185U,185U,186U,186U,186U,186U,187U,188U,188U,188U,188U,186U,186U,186U,185U,185U,185U,185U,184U,184U,184U,184U,182U,183U,182U,182U,182U,181U,181U,182U,182U,181U,181U,181U,181U,180U,180U,182U,182U,181U,178U,175U,174U,175U,178U,182U,187U,192U,192U,192U,192U,192U,190U,188U,187U,186U,186U,186U,187U,189U,189U,191U,191U,192U,192U,192U,192U,192U,192U,192U,193U,193U,194U,195U,195U,196U,194U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
183U,182U,180U,179U,180U,181U,179U,179U,173U,166U,165U,168U,178U,185U,185U,185U,185U,185U,186U,186U,187U,187U,187U,187U,187U,187U,186U,186U,185U,185U,185U,185U,185U,184U,184U,184U,184U,182U,183U,182U,182U,182U,181U,181U,181U,181U,181U,181U,181U,181U,181U,182U,181U,181U,181U,180U,176U,176U,178U,179U,183U,189U,192U,192U,192U,190U,189U,188U,187U,186U,185U,186U,186U,187U,188U,189U,191U,191U,192U,192U,192U,192U,192U,192U,192U,192U,193U,193U,194U,194U,194U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
183U,182U,180U,180U,180U,179U,176U,174U,171U,167U,168U,175U,182U,185U,185U,185U,185U,185U,185U,185U,186U,187U,187U,187U,187U,187U,185U,185U,185U,184U,184U,184U,184U,184U,182U,182U,182U,182U,183U,182U,182U,182U,181U,181U,181U,181U,180U,180U,180U,180U,178U,178U,180U,179U,178U,178U,174U,176U,179U,181U,186U,190U,192U,192U,192U,189U,188U,188U,187U,186U,186U,186U,186U,187U,189U,189U,191U,191U,191U,192U,192U,192U,192U,192U,192U,192U,193U,193U,193U,192U,193U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
185U,185U,182U,180U,176U,174U,172U,172U,172U,171U,172U,179U,185U,185U,185U,185U,185U,185U,185U,185U,186U,187U,187U,187U,187U,187U,185U,185U,185U,184U,184U,184U,184U,182U,182U,182U,182U,181U,182U,182U,181U,181U,181U,181U,181U,181U,180U,180U,179U,179U,175U,173U,171U,171U,169U,169U,169U,175U,180U,183U,186U,190U,192U,190U,190U,189U,188U,188U,187U,187U,187U,188U,187U,188U,188U,189U,191U,191U,191U,191U,192U,192U,192U,192U,192U,192U,191U,192U,193U,192U,193U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
187U,185U,181U,178U,172U,169U,169U,172U,173U,174U,179U,181U,185U,185U,185U,185U,185U,185U,185U,186U,186U,186U,187U,187U,187U,187U,185U,185U,185U,184U,184U,184U,184U,182U,182U,182U,182U,181U,182U,182U,181U,181U,181U,181U,180U,180U,179U,179U,178U,175U,173U,171U,167U,161U,162U,164U,167U,175U,182U,186U,187U,188U,189U,189U,189U,189U,189U,189U,189U,189U,188U,188U,188U,188U,191U,191U,191U,191U,191U,191U,191U,192U,191U,191U,192U,191U,191U,191U,192U,192U,192U,193U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
187U,183U,180U,174U,169U,168U,171U,174U,176U,182U,185U,183U,185U,185U,185U,185U,185U,185U,185U,186U,186U,186U,186U,186U,186U,186U,185U,185U,184U,184U,184U,184U,184U,182U,182U,182U,182U,181U,182U,182U,181U,181U,181U,181U,180U,180U,179U,178U,176U,175U,174U,172U,168U,165U,165U,166U,169U,179U,183U,187U,188U,188U,189U,189U,189U,189U,190U,192U,189U,189U,189U,189U,188U,189U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
188U,185U,179U,172U,166U,169U,174U,178U,180U,185U,186U,186U,185U,185U,185U,185U,185U,185U,185U,185U,185U,186U,186U,186U,186U,186U,184U,184U,184U,182U,182U,182U,182U,182U,181U,181U,181U,181U,182U,182U,181U,181U,181U,181U,180U,180U,179U,178U,176U,175U,175U,173U,172U,171U,171U,173U,178U,185U,187U,187U,188U,189U,189U,189U,189U,189U,189U,190U,190U,190U,192U,190U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
190U,185U,176U,166U,165U,169U,179U,183U,183U,186U,187U,187U,185U,185U,185U,185U,185U,185U,185U,185U,185U,186U,186U,186U,186U,186U,184U,184U,184U,182U,182U,182U,182U,181U,181U,181U,181U,180U,181U,181U,181U,181U,181U,181U,180U,180U,179U,178U,176U,176U,175U,174U,174U,175U,175U,179U,182U,186U,188U,188U,189U,189U,189U,189U,189U,189U,190U,190U,190U,192U,193U,192U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
190U,178U,162U,164U,164U,172U,180U,183U,186U,187U,187U,187U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,186U,186U,186U,186U,184U,184U,184U,182U,182U,182U,182U,181U,181U,181U,181U,180U,181U,181U,181U,181U,181U,181U,180U,180U,180U,179U,179U,179U,176U,176U,176U,176U,178U,180U,183U,186U,188U,188U,189U,189U,189U,189U,189U,190U,192U,192U,192U,193U,193U,193U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
185U,168U,154U,161U,172U,179U,182U,183U,187U,187U,187U,187U,186U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,184U,184U,182U,182U,182U,182U,182U,181U,181U,181U,181U,180U,181U,181U,181U,181U,181U,180U,181U,181U,180U,180U,180U,180U,179U,178U,178U,179U,179U,181U,183U,186U,188U,189U,189U,189U,190U,189U,189U,192U,192U,192U,193U,193U,193U,193U,192U,192U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,191U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
175U,161U,155U,166U,176U,180U,182U,183U,186U,185U,185U,186U,186U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,185U,183U,183U,183U,183U,183U,182U,182U,182U,182U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,180U,180U,180U,180U,180U,181U,182U,185U,187U,188U,189U,190U,190U,190U,192U,190U,190U,192U,192U,192U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
167U,157U,160U,173U,180U,181U,181U,182U,185U,183U,183U,185U,185U,185U,185U,185U,185U,185U,185U,185U,183U,183U,185U,185U,185U,185U,183U,183U,183U,183U,183U,182U,182U,182U,182U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,182U,182U,185U,187U,189U,190U,192U,192U,193U,193U,192U,190U,192U,192U,192U,193U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
163U,157U,164U,178U,181U,181U,182U,183U,183U,183U,183U,185U,183U,183U,183U,183U,183U,185U,183U,183U,183U,183U,185U,185U,185U,185U,185U,183U,183U,183U,183U,183U,182U,182U,182U,182U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,182U,182U,182U,182U,182U,183U,187U,187U,188U,190U,192U,193U,193U,193U,193U,192U,190U,192U,192U,193U,193U,193U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
161U,160U,172U,180U,182U,181U,182U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,185U,185U,183U,183U,183U,183U,183U,183U,183U,183U,182U,182U,182U,182U,181U,181U,181U,181U,181U,181U,181U,181U,180U,182U,182U,182U,182U,182U,182U,185U,187U,189U,192U,193U,193U,193U,193U,193U,193U,190U,190U,192U,192U,193U,193U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
161U,166U,175U,180U,181U,182U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,182U,182U,181U,182U,183U,185U,185U,183U,183U,183U,183U,183U,183U,183U,183U,183U,182U,182U,182U,182U,181U,181U,181U,181U,180U,181U,181U,178U,179U,179U,179U,178U,179U,180U,183U,187U,190U,193U,195U,195U,195U,194U,193U,192U,189U,189U,192U,193U,193U,193U,194U,194U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
154U,168U,181U,181U,180U,181U,183U,183U,182U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,183U,183U,183U,183U,183U,183U,183U,183U,183U,183U,182U,182U,182U,181U,182U,182U,181U,181U,181U,179U,180U,180U,179U,174U,172U,173U,173U,172U,171U,178U,185U,187U,190U,194U,196U,199U,199U,196U,194U,192U,188U,189U,190U,193U,195U,195U,194U,194U,194U,193U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
154U,167U,180U,181U,180U,180U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,181U,182U,183U,183U,183U,182U,183U,183U,183U,183U,182U,181U,181U,181U,180U,181U,181U,181U,181U,180U,179U,180U,178U,174U,172U,168U,166U,166U,166U,167U,175U,182U,186U,188U,193U,195U,199U,199U,196U,192U,190U,188U,189U,190U,190U,194U,195U,195U,194U,194U,193U,193U,193U,193U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
175U,175U,178U,179U,179U,180U,180U,181U,181U,181U,180U,181U,181U,180U,180U,180U,180U,180U,180U,180U,181U,181U,181U,181U,181U,182U,182U,182U,181U,182U,182U,181U,181U,181U,181U,181U,180U,180U,179U,179U,179U,176U,174U,174U,174U,171U,167U,164U,160U,159U,159U,164U,172U,179U,183U,187U,192U,194U,196U,199U,196U,193U,192U,189U,190U,190U,192U,194U,195U,195U,194U,192U,192U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
201U,189U,178U,176U,179U,179U,180U,180U,180U,181U,181U,181U,179U,179U,179U,179U,179U,179U,179U,180U,180U,181U,180U,181U,181U,181U,182U,182U,181U,182U,182U,182U,182U,181U,181U,181U,180U,180U,179U,179U,179U,176U,176U,172U,168U,166U,164U,159U,155U,153U,153U,158U,167U,176U,185U,189U,192U,194U,196U,196U,195U,195U,193U,193U,193U,193U,194U,194U,195U,195U,194U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
225U,203U,180U,175U,177U,177U,179U,179U,179U,180U,181U,180U,179U,179U,179U,179U,179U,179U,179U,180U,180U,180U,181U,181U,180U,181U,181U,181U,180U,182U,182U,181U,181U,181U,180U,179U,180U,180U,180U,180U,181U,186U,190U,193U,186U,175U,165U,158U,151U,145U,145U,151U,164U,175U,183U,188U,188U,190U,194U,194U,195U,195U,194U,194U,194U,195U,196U,196U,196U,196U,195U,193U,193U,193U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,190U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
235U,207U,180U,176U,177U,177U,179U,180U,181U,181U,181U,181U,179U,179U,179U,179U,179U,179U,179U,179U,179U,180U,181U,180U,180U,181U,181U,181U,180U,180U,180U,180U,179U,181U,181U,179U,178U,180U,182U,181U,179U,188U,215U,229U,223U,197U,169U,159U,148U,143U,141U,147U,161U,174U,185U,188U,188U,188U,192U,192U,192U,192U,194U,193U,193U,194U,195U,196U,196U,196U,195U,193U,192U,192U,190U,190U,190U,190U,190U,190U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,192U,190U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
227U,202U,179U,175U,176U,177U,179U,181U,182U,182U,181U,182U,180U,178U,179U,179U,179U,179U,179U,180U,179U,180U,182U,181U,180U,180U,181U,181U,179U,179U,179U,179U,178U,180U,181U,181U,179U,180U,181U,181U,176U,187U,208U,224U,220U,196U,178U,160U,147U,138U,137U,146U,161U,176U,185U,189U,190U,190U,190U,192U,192U,192U,192U,190U,189U,188U,189U,192U,195U,194U,192U,193U,192U,192U,188U,188U,189U,190U,189U,190U,192U,192U,190U,190U,190U,190U,190U,190U,190U,192U,192U,190U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
225U,202U,177U,174U,175U,178U,180U,181U,181U,181U,181U,181U,179U,178U,179U,179U,178U,179U,180U,180U,180U,182U,187U,187U,187U,184U,182U,181U,180U,179U,179U,179U,180U,180U,180U,180U,180U,179U,181U,182U,181U,185U,187U,192U,192U,185U,176U,160U,146U,137U,133U,145U,164U,178U,187U,190U,190U,190U,189U,190U,190U,189U,190U,188U,182U,179U,178U,181U,189U,189U,187U,189U,188U,187U,186U,186U,187U,189U,189U,190U,192U,192U,190U,190U,190U,190U,190U,190U,190U,190U,190U,188U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
223U,205U,182U,174U,179U,180U,181U,181U,182U,181U,181U,181U,179U,179U,179U,179U,179U,180U,180U,181U,181U,181U,189U,205U,210U,200U,189U,183U,181U,179U,179U,179U,180U,180U,179U,179U,179U,178U,180U,180U,182U,186U,186U,183U,182U,178U,168U,159U,147U,139U,141U,153U,166U,175U,187U,190U,190U,190U,188U,188U,188U,188U,187U,183U,175U,169U,166U,168U,179U,181U,182U,185U,183U,183U,182U,183U,185U,185U,186U,188U,190U,190U,187U,186U,188U,190U,190U,190U,189U,189U,188U,187U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
221U,205U,184U,177U,180U,181U,181U,182U,182U,182U,181U,181U,180U,179U,179U,180U,180U,180U,181U,181U,182U,184U,191U,207U,212U,204U,193U,185U,181U,179U,178U,179U,179U,178U,178U,176U,176U,175U,176U,176U,180U,190U,196U,203U,201U,190U,186U,170U,152U,146U,151U,160U,166U,174U,177U,181U,182U,182U,182U,185U,187U,186U,182U,178U,173U,165U,160U,161U,168U,174U,178U,179U,181U,181U,182U,182U,181U,179U,180U,182U,182U,182U,179U,179U,182U,185U,185U,186U,186U,186U,186U,185U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
204U,195U,184U,179U,181U,181U,181U,182U,182U,181U,181U,181U,180U,179U,179U,180U,179U,179U,180U,180U,181U,184U,187U,187U,188U,186U,182U,180U,176U,174U,176U,178U,178U,176U,176U,175U,175U,174U,173U,172U,175U,192U,209U,222U,221U,214U,210U,186U,158U,152U,155U,163U,163U,167U,167U,167U,167U,167U,169U,173U,176U,174U,171U,171U,169U,164U,159U,160U,165U,168U,171U,172U,172U,172U,173U,172U,171U,169U,171U,171U,172U,172U,172U,172U,174U,176U,178U,179U,181U,185U,183U,182U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
181U,179U,179U,179U,181U,182U,181U,181U,180U,180U,180U,180U,179U,179U,179U,177U,176U,175U,176U,176U,176U,176U,175U,175U,174U,175U,176U,174U,172U,170U,170U,172U,174U,174U,174U,172U,169U,169U,167U,161U,166U,186U,204U,217U,219U,216U,214U,194U,162U,146U,152U,156U,160U,161U,159U,157U,156U,156U,155U,159U,163U,161U,158U,158U,161U,160U,156U,158U,162U,166U,166U,166U,166U,166U,166U,165U,165U,163U,163U,163U,163U,165U,166U,167U,169U,172U,172U,173U,174U,175U,174U,173U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
176U,175U,174U,175U,177U,180U,178U,178U,175U,176U,175U,175U,175U,176U,175U,172U,170U,170U,170U,168U,166U,166U,165U,164U,165U,165U,166U,163U,161U,160U,158U,158U,161U,162U,160U,160U,162U,161U,155U,148U,153U,172U,189U,203U,204U,194U,191U,184U,160U,138U,145U,148U,151U,153U,151U,148U,148U,149U,149U,149U,151U,152U,149U,148U,153U,155U,152U,153U,156U,159U,160U,162U,162U,162U,161U,161U,161U,160U,160U,161U,159U,159U,158U,159U,160U,163U,163U,163U,163U,163U,161U,162U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
175U,173U,172U,171U,173U,174U,175U,175U,174U,173U,173U,173U,171U,172U,170U,168U,167U,167U,167U,163U,161U,159U,157U,154U,152U,152U,151U,148U,148U,146U,144U,145U,147U,148U,148U,149U,151U,142U,135U,135U,151U,174U,188U,200U,193U,174U,155U,151U,139U,127U,129U,133U,137U,140U,141U,144U,146U,147U,147U,147U,147U,148U,148U,147U,148U,148U,149U,149U,152U,154U,154U,156U,157U,157U,158U,158U,159U,158U,159U,158U,156U,154U,153U,153U,155U,153U,154U,154U,155U,158U,158U,158U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
175U,175U,168U,166U,168U,171U,173U,173U,171U,171U,171U,168U,169U,168U,167U,165U,162U,162U,162U,160U,156U,155U,151U,148U,146U,146U,146U,145U,143U,140U,138U,139U,140U,140U,141U,141U,140U,131U,126U,135U,156U,179U,186U,187U,178U,155U,129U,124U,123U,121U,121U,126U,131U,137U,140U,141U,142U,144U,145U,146U,146U,146U,146U,148U,147U,146U,147U,147U,148U,151U,149U,151U,151U,151U,154U,155U,155U,155U,156U,154U,152U,151U,151U,148U,148U,149U,152U,151U,151U,152U,153U,154U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
190U,182U,168U,163U,162U,164U,165U,164U,166U,166U,165U,163U,163U,161U,159U,156U,155U,155U,153U,151U,150U,146U,144U,141U,139U,139U,139U,139U,138U,135U,134U,134U,133U,133U,133U,133U,130U,125U,124U,135U,156U,173U,170U,163U,154U,137U,119U,115U,119U,121U,121U,125U,131U,135U,138U,139U,139U,141U,143U,144U,144U,143U,144U,145U,144U,143U,144U,144U,146U,148U,146U,147U,147U,148U,151U,152U,151U,152U,152U,150U,148U,148U,148U,147U,147U,148U,148U,148U,150U,150U,151U,153U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
200U,184U,168U,163U,159U,158U,158U,158U,159U,159U,159U,156U,153U,151U,149U,149U,148U,146U,144U,141U,140U,139U,138U,135U,133U,133U,133U,132U,132U,131U,128U,128U,128U,130U,128U,128U,126U,123U,123U,130U,142U,152U,147U,140U,133U,125U,121U,120U,120U,122U,123U,127U,133U,138U,138U,139U,139U,140U,140U,141U,143U,143U,144U,144U,143U,143U,144U,143U,145U,146U,145U,146U,147U,148U,148U,148U,150U,150U,150U,150U,148U,148U,148U,148U,148U,148U,147U,147U,148U,148U,148U,151U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
215U,202U,170U,159U,156U,154U,154U,154U,153U,152U,152U,151U,147U,145U,144U,142U,142U,142U,139U,137U,135U,135U,133U,131U,131U,131U,128U,128U,127U,125U,125U,125U,125U,124U,126U,126U,124U,122U,122U,125U,127U,126U,124U,118U,113U,117U,119U,118U,119U,123U,126U,128U,132U,137U,138U,138U,139U,139U,139U,141U,142U,142U,143U,143U,144U,144U,143U,143U,145U,145U,145U,145U,147U,147U,146U,147U,147U,147U,147U,148U,148U,148U,148U,148U,149U,149U,148U,149U,149U,149U,149U,152U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
204U,193U,172U,155U,151U,149U,148U,146U,145U,143U,145U,144U,139U,137U,138U,138U,137U,137U,135U,133U,131U,131U,131U,128U,128U,128U,126U,126U,125U,123U,122U,123U,123U,123U,125U,125U,123U,121U,120U,121U,122U,119U,112U,106U,103U,104U,105U,108U,117U,123U,124U,125U,130U,134U,134U,135U,137U,137U,137U,139U,140U,141U,140U,140U,141U,141U,141U,141U,142U,144U,143U,144U,145U,145U,145U,145U,146U,146U,146U,147U,147U,147U,147U,147U,148U,148U,148U,149U,149U,149U,151U,151U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
182U,173U,165U,151U,146U,144U,141U,141U,141U,139U,139U,139U,138U,135U,135U,135U,134U,132U,131U,128U,127U,127U,127U,127U,127U,127U,125U,125U,125U,123U,122U,123U,122U,121U,123U,124U,122U,119U,117U,113U,110U,105U,99U,98U,93U,91U,96U,105U,114U,121U,122U,125U,128U,131U,132U,134U,135U,135U,137U,139U,139U,139U,138U,138U,138U,139U,139U,140U,141U,141U,140U,140U,141U,141U,141U,141U,143U,143U,143U,145U,145U,145U,146U,147U,147U,147U,148U,148U,148U,149U,151U,151U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
174U,167U,159U,148U,144U,140U,137U,138U,137U,134U,134U,134U,134U,133U,133U,133U,133U,131U,127U,126U,126U,125U,125U,126U,126U,126U,124U,124U,124U,124U,123U,123U,122U,121U,121U,120U,120U,118U,112U,104U,97U,93U,92U,92U,87U,86U,92U,103U,112U,119U,121U,125U,127U,128U,131U,133U,133U,132U,134U,137U,137U,137U,136U,136U,134U,136U,136U,136U,137U,137U,136U,136U,138U,139U,137U,138U,138U,138U,139U,141U,143U,143U,144U,144U,145U,145U,146U,148U,148U,148U,149U,151U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
179U,163U,153U,146U,141U,134U,132U,130U,130U,130U,128U,130U,130U,130U,130U,130U,130U,128U,125U,124U,124U,123U,123U,124U,124U,124U,124U,124U,124U,124U,124U,123U,121U,120U,120U,119U,115U,112U,107U,99U,93U,91U,90U,90U,89U,90U,92U,103U,111U,115U,118U,124U,127U,128U,128U,130U,131U,131U,130U,132U,135U,135U,133U,133U,134U,134U,134U,134U,133U,133U,133U,133U,134U,135U,134U,134U,137U,137U,137U,139U,139U,139U,139U,140U,140U,141U,144U,146U,146U,146U,147U,148U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
161U,152U,147U,145U,138U,128U,125U,125U,124U,123U,125U,125U,125U,126U,126U,125U,123U,122U,122U,121U,122U,123U,123U,124U,124U,124U,124U,124U,125U,125U,123U,121U,121U,121U,120U,117U,111U,107U,106U,98U,92U,90U,89U,91U,93U,96U,98U,103U,108U,112U,113U,122U,126U,128U,130U,130U,131U,130U,130U,131U,132U,132U,131U,133U,133U,132U,132U,132U,131U,131U,131U,131U,133U,133U,133U,134U,134U,134U,135U,135U,137U,137U,137U,138U,138U,138U,140U,140U,141U,142U,142U,144U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
135U,132U,134U,138U,130U,122U,120U,118U,115U,113U,115U,115U,117U,119U,119U,119U,120U,120U,120U,121U,121U,122U,123U,124U,124U,124U,123U,124U,124U,123U,123U,122U,121U,121U,117U,113U,110U,106U,104U,98U,93U,91U,91U,93U,98U,100U,100U,105U,108U,112U,112U,120U,126U,127U,128U,128U,130U,130U,130U,131U,131U,131U,131U,131U,131U,131U,131U,132U,131U,129U,130U,130U,131U,132U,131U,131U,132U,133U,133U,132U,134U,134U,134U,135U,135U,135U,135U,135U,138U,140U,140U,141U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
119U,117U,117U,122U,119U,113U,111U,110U,106U,104U,105U,107U,112U,113U,114U,114U,115U,115U,118U,118U,118U,119U,120U,122U,122U,122U,122U,122U,121U,121U,121U,119U,119U,119U,114U,111U,107U,105U,103U,97U,93U,92U,96U,99U,101U,104U,106U,107U,110U,112U,114U,122U,126U,126U,127U,127U,128U,128U,128U,130U,130U,128U,128U,128U,128U,128U,130U,130U,129U,129U,127U,126U,126U,127U,127U,127U,130U,130U,128U,128U,130U,130U,131U,131U,131U,131U,131U,132U,134U,135U,135U,138U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
108U,106U,107U,110U,110U,107U,105U,105U,105U,105U,106U,108U,108U,110U,112U,112U,113U,114U,114U,114U,114U,113U,113U,114U,115U,119U,120U,122U,121U,121U,119U,115U,114U,114U,113U,110U,106U,104U,100U,96U,93U,94U,97U,101U,105U,108U,108U,108U,110U,113U,115U,122U,125U,125U,126U,126U,126U,127U,128U,128U,127U,127U,127U,127U,126U,127U,127U,128U,127U,125U,124U,124U,123U,125U,125U,124U,125U,126U,125U,126U,127U,127U,127U,127U,127U,127U,127U,128U,131U,133U,133U,134U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
106U,104U,105U,105U,105U,104U,104U,104U,104U,104U,105U,106U,106U,108U,108U,110U,110U,108U,110U,110U,107U,107U,107U,108U,110U,111U,113U,113U,113U,113U,112U,112U,112U,113U,111U,107U,104U,101U,100U,98U,97U,97U,99U,105U,111U,112U,111U,110U,110U,113U,115U,121U,124U,125U,126U,126U,125U,127U,128U,128U,126U,125U,125U,124U,126U,126U,125U,126U,124U,123U,124U,123U,123U,123U,123U,124U,124U,124U,125U,125U,125U,125U,125U,125U,125U,125U,126U,126U,127U,130U,130U,130U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
105U,104U,103U,103U,103U,100U,101U,103U,104U,106U,106U,104U,105U,105U,106U,106U,106U,105U,105U,104U,103U,104U,105U,106U,106U,107U,107U,108U,110U,111U,111U,112U,112U,112U,110U,107U,105U,103U,101U,100U,100U,101U,104U,107U,113U,113U,112U,110U,110U,113U,115U,120U,122U,123U,125U,125U,125U,126U,126U,126U,124U,123U,123U,123U,125U,125U,124U,124U,123U,123U,124U,123U,123U,123U,123U,122U,123U,123U,124U,124U,124U,124U,123U,124U,124U,124U,123U,125U,125U,125U,125U,126U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
105U,105U,104U,103U,103U,100U,101U,103U,106U,106U,106U,104U,105U,105U,105U,106U,105U,106U,106U,104U,104U,107U,108U,110U,108U,108U,110U,110U,112U,114U,113U,114U,114U,112U,111U,110U,107U,106U,105U,105U,105U,107U,108U,113U,113U,113U,111U,108U,110U,113U,117U,120U,121U,122U,124U,124U,124U,124U,124U,124U,124U,123U,123U,122U,123U,123U,123U,123U,123U,122U,122U,122U,122U,122U,121U,122U,122U,122U,123U,123U,123U,123U,123U,123U,123U,123U,122U,123U,123U,123U,124U,126U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
109U,109U,107U,107U,106U,107U,109U,111U,112U,112U,107U,106U,105U,105U,105U,107U,106U,106U,107U,106U,106U,108U,112U,113U,113U,113U,112U,112U,113U,117U,117U,117U,115U,114U,112U,111U,110U,108U,108U,107U,110U,113U,114U,115U,115U,113U,110U,108U,111U,114U,117U,119U,121U,121U,123U,123U,124U,124U,123U,123U,123U,123U,123U,123U,122U,123U,123U,122U,123U,123U,122U,122U,121U,121U,121U,120U,122U,122U,122U,123U,123U,123U,123U,123U,123U,122U,122U,122U,122U,123U,124U,124U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
112U,112U,113U,113U,113U,112U,114U,117U,115U,114U,112U,110U,108U,107U,107U,108U,108U,110U,110U,108U,110U,112U,114U,118U,118U,118U,115U,115U,117U,119U,119U,118U,118U,117U,114U,113U,111U,111U,111U,111U,113U,115U,118U,118U,118U,114U,113U,112U,113U,117U,119U,120U,121U,122U,122U,123U,124U,124U,123U,123U,123U,123U,123U,123U,122U,123U,123U,122U,123U,123U,121U,121U,121U,121U,120U,121U,122U,122U,122U,123U,123U,123U,123U,123U,123U,122U,122U,123U,123U,123U,124U,124U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
115U,115U,117U,118U,118U,117U,118U,118U,119U,119U,115U,114U,112U,110U,111U,111U,112U,113U,112U,112U,112U,113U,115U,118U,118U,118U,118U,118U,118U,120U,120U,120U,119U,119U,118U,115U,114U,113U,113U,114U,115U,118U,118U,118U,117U,117U,115U,115U,118U,119U,121U,121U,122U,123U,122U,123U,124U,124U,123U,123U,123U,123U,123U,123U,122U,123U,123U,122U,122U,122U,121U,121U,121U,121U,120U,121U,123U,123U,123U,124U,124U,124U,124U,124U,124U,123U,123U,124U,124U,124U,124U,124U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
118U,118U,118U,119U,119U,119U,119U,119U,118U,118U,118U,117U,115U,114U,115U,115U,115U,117U,115U,115U,114U,115U,118U,118U,118U,119U,118U,119U,119U,120U,120U,119U,119U,119U,118U,115U,115U,115U,115U,115U,117U,118U,118U,117U,117U,117U,115U,118U,120U,122U,123U,122U,123U,123U,123U,124U,125U,123U,123U,123U,123U,123U,123U,124U,124U,124U,123U,124U,124U,123U,123U,121U,121U,121U,121U,122U,124U,125U,125U,126U,126U,125U,125U,125U,125U,125U,125U,125U,125U,125U,126U,125U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
122U,121U,119U,120U,120U,120U,120U,120U,119U,120U,119U,119U,118U,118U,118U,119U,118U,118U,117U,117U,117U,118U,118U,118U,118U,119U,119U,119U,120U,120U,120U,120U,119U,120U,119U,117U,117U,118U,118U,118U,118U,118U,118U,118U,118U,115U,117U,118U,121U,122U,123U,124U,124U,124U,125U,126U,126U,125U,125U,125U,125U,125U,125U,125U,125U,125U,125U,125U,125U,123U,123U,123U,122U,123U,123U,123U,125U,126U,126U,126U,126U,126U,126U,126U,126U,125U,125U,126U,126U,126U,127U,126U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
121U,120U,120U,120U,121U,121U,121U,120U,121U,121U,121U,121U,120U,118U,118U,119U,120U,119U,119U,118U,118U,118U,118U,119U,119U,119U,119U,119U,120U,120U,121U,120U,119U,120U,120U,119U,119U,120U,119U,119U,119U,119U,120U,120U,120U,119U,118U,119U,122U,123U,124U,124U,125U,125U,126U,126U,126U,126U,126U,126U,126U,126U,126U,126U,126U,126U,126U,126U,125U,125U,125U,123U,124U,124U,124U,124U,125U,126U,126U,126U,126U,126U,126U,126U,127U,127U,127U,128U,128U,127U,127U,127U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
120U,120U,121U,121U,121U,121U,120U,121U,121U,121U,121U,121U,120U,120U,120U,120U,119U,119U,120U,119U,119U,119U,119U,120U,120U,120U,120U,120U,121U,121U,121U,121U,121U,121U,120U,119U,120U,121U,121U,120U,120U,121U,121U,121U,121U,121U,120U,121U,123U,124U,125U,126U,126U,127U,127U,127U,126U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,126U,126U,126U,125U,125U,125U,127U,127U,126U,128U,128U,128U,128U,128U,130U,130U,128U,130U,130U,128U,128U,128U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
119U,120U,121U,121U,121U,120U,121U,122U,122U,122U,122U,121U,121U,122U,122U,120U,119U,120U,121U,121U,121U,121U,121U,120U,120U,121U,121U,121U,121U,121U,121U,121U,121U,121U,120U,120U,120U,121U,121U,120U,120U,121U,121U,121U,122U,122U,122U,124U,126U,126U,126U,127U,128U,130U,130U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,127U,126U,126U,125U,126U,127U,127U,128U,128U,128U,128U,128U,128U,130U,130U,130U,128U,130U,130U,131U,131U,131U,131U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
119U,120U,119U,120U,121U,121U,121U,122U,122U,122U,122U,122U,120U,120U,120U,119U,119U,120U,121U,121U,121U,121U,121U,121U,121U,122U,121U,122U,122U,121U,121U,121U,121U,121U,121U,121U,121U,121U,121U,122U,121U,121U,121U,122U,123U,123U,124U,126U,127U,127U,128U,128U,128U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,128U,128U,128U,127U,127U,128U,128U,128U,128U,128U,128U,128U,128U,128U,130U,130U,130U,130U,131U,131U,131U,132U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
120U,120U,120U,121U,122U,123U,123U,123U,123U,122U,122U,122U,121U,119U,119U,120U,119U,119U,120U,121U,121U,121U,122U,122U,122U,123U,123U,122U,122U,122U,122U,121U,121U,122U,121U,121U,121U,121U,121U,122U,122U,121U,122U,123U,124U,124U,124U,126U,127U,126U,127U,128U,128U,128U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,130U,128U,128U,128U,127U,128U,128U,128U,127U,128U,131U,131U,131U,131U,131U,131U,131U,131U,131U,131U,132U,132U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
123U,124U,124U,124U,124U,125U,125U,125U,124U,124U,123U,124U,124U,122U,121U,121U,120U,120U,121U,121U,121U,123U,123U,123U,123U,123U,123U,123U,123U,122U,122U,122U,122U,122U,122U,121U,121U,121U,121U,122U,122U,123U,123U,123U,124U,124U,125U,126U,126U,127U,127U,127U,130U,130U,130U,130U,128U,128U,128U,128U,128U,128U,128U,128U,128U,128U,127U,127U,127U,127U,130U,127U,127U,127U,128U,128U,128U,128U,130U,130U,131U,131U,131U,131U,131U,131U,131U,131U,131U,131U,132U,132U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
131U,133U,130U,131U,132U,132U,131U,128U,126U,126U,126U,126U,125U,124U,124U,123U,122U,123U,121U,121U,123U,123U,123U,123U,123U,123U,123U,123U,123U,123U,122U,123U,122U,122U,122U,122U,122U,121U,121U,122U,122U,123U,123U,124U,125U,125U,126U,127U,127U,127U,127U,127U,130U,130U,130U,130U,131U,131U,131U,131U,131U,131U,131U,131U,131U,130U,129U,129U,130U,130U,130U,127U,127U,127U,128U,128U,128U,128U,130U,130U,130U,130U,131U,131U,131U,131U,131U,131U,132U,132U,133U,133U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
141U,138U,138U,135U,137U,137U,134U,132U,128U,127U,127U,127U,127U,126U,126U,125U,123U,123U,122U,123U,124U,123U,123U,124U,124U,124U,123U,123U,123U,124U,124U,123U,123U,122U,122U,122U,122U,122U,121U,121U,122U,123U,123U,124U,126U,126U,125U,127U,127U,127U,127U,128U,130U,130U,130U,131U,131U,131U,131U,131U,131U,131U,131U,131U,131U,130U,129U,130U,129U,129U,128U,127U,127U,127U,127U,127U,128U,128U,130U,130U,131U,131U,133U,133U,133U,133U,133U,133U,133U,134U,135U,135U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
145U,142U,141U,139U,139U,139U,138U,135U,132U,128U,128U,131U,128U,127U,128U,127U,125U,124U,124U,124U,123U,124U,125U,124U,124U,125U,125U,124U,124U,124U,124U,125U,124U,122U,123U,122U,122U,122U,121U,121U,122U,123U,124U,125U,126U,127U,126U,127U,127U,127U,128U,128U,130U,130U,130U,131U,132U,132U,132U,131U,132U,132U,131U,131U,131U,130U,129U,129U,127U,127U,128U,127U,127U,128U,128U,130U,131U,130U,132U,132U,133U,133U,133U,133U,134U,135U,135U,135U,135U,137U,138U,137U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
146U,145U,142U,141U,141U,141U,139U,137U,135U,133U,131U,133U,131U,131U,131U,130U,128U,127U,126U,126U,125U,126U,126U,126U,126U,127U,126U,125U,124U,125U,125U,125U,125U,123U,125U,124U,122U,121U,121U,121U,122U,123U,124U,125U,126U,127U,127U,128U,128U,128U,128U,128U,130U,131U,131U,131U,132U,132U,132U,132U,132U,132U,131U,131U,130U,128U,127U,129U,127U,127U,130U,128U,130U,130U,131U,132U,133U,134U,134U,134U,135U,135U,135U,135U,137U,137U,137U,138U,138U,138U,139U,138U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
146U,147U,146U,144U,144U,141U,139U,139U,139U,138U,133U,134U,133U,133U,133U,132U,131U,130U,128U,127U,127U,127U,127U,128U,128U,130U,128U,127U,126U,126U,127U,126U,125U,125U,125U,125U,124U,123U,122U,122U,123U,123U,125U,125U,126U,127U,127U,130U,130U,130U,130U,130U,131U,132U,132U,132U,132U,132U,132U,132U,132U,132U,131U,131U,131U,130U,129U,130U,129U,127U,130U,130U,131U,132U,132U,133U,135U,137U,137U,138U,138U,138U,139U,139U,139U,139U,139U,139U,139U,139U,139U,139U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
146U,148U,148U,146U,144U,141U,140U,141U,140U,139U,135U,135U,135U,134U,135U,134U,132U,131U,130U,130U,130U,130U,130U,131U,131U,132U,132U,131U,130U,130U,129U,127U,127U,126U,126U,126U,124U,123U,122U,122U,123U,124U,124U,125U,126U,127U,128U,128U,128U,130U,130U,130U,131U,131U,132U,132U,132U,132U,132U,132U,132U,133U,133U,132U,132U,131U,130U,130U,130U,131U,131U,131U,132U,132U,135U,135U,137U,139U,140U,140U,140U,140U,140U,140U,140U,140U,140U,139U,139U,139U,139U,138U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
146U,148U,149U,147U,145U,142U,144U,144U,142U,141U,139U,139U,138U,138U,138U,137U,134U,134U,132U,132U,131U,131U,132U,132U,131U,132U,133U,131U,131U,131U,130U,129U,129U,127U,127U,127U,125U,123U,121U,121U,122U,123U,124U,125U,126U,127U,128U,128U,128U,130U,130U,130U,131U,131U,131U,132U,132U,133U,132U,133U,133U,133U,132U,132U,132U,131U,130U,131U,131U,131U,131U,132U,132U,132U,135U,135U,137U,139U,140U,140U,140U,140U,140U,140U,140U,140U,139U,139U,138U,139U,138U,138U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
147U,150U,151U,149U,147U,146U,146U,145U,142U,141U,141U,141U,140U,140U,140U,138U,138U,138U,135U,135U,134U,134U,134U,134U,133U,133U,133U,131U,130U,130U,130U,129U,129U,129U,129U,127U,125U,123U,122U,122U,123U,124U,124U,125U,127U,128U,128U,127U,128U,130U,130U,131U,131U,131U,131U,132U,132U,133U,133U,133U,133U,133U,132U,132U,132U,132U,132U,132U,132U,132U,132U,133U,133U,133U,132U,133U,134U,135U,135U,135U,138U,139U,139U,139U,139U,139U,138U,138U,138U,138U,138U,138U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
146U,148U,151U,151U,149U,149U,148U,146U,144U,141U,140U,141U,140U,140U,140U,138U,139U,139U,137U,135U,137U,134U,134U,135U,134U,133U,132U,132U,132U,131U,130U,131U,130U,130U,131U,127U,125U,124U,124U,124U,125U,125U,126U,127U,128U,128U,127U,127U,127U,128U,130U,130U,131U,131U,132U,132U,132U,133U,133U,133U,133U,134U,134U,133U,133U,133U,133U,133U,133U,133U,133U,133U,133U,133U,132U,132U,133U,133U,132U,133U,135U,137U,138U,138U,138U,138U,138U,138U,137U,138U,137U,135U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
141U,144U,146U,146U,146U,146U,147U,146U,141U,139U,138U,140U,141U,140U,140U,139U,139U,139U,137U,137U,138U,135U,135U,135U,135U,134U,133U,133U,132U,132U,133U,133U,131U,131U,131U,129U,128U,128U,125U,125U,126U,128U,128U,130U,131U,130U,127U,127U,126U,127U,127U,128U,131U,132U,133U,134U,133U,133U,133U,133U,133U,134U,134U,133U,133U,133U,133U,133U,133U,133U,133U,133U,133U,133U,132U,132U,132U,132U,130U,131U,133U,135U,137U,137U,138U,138U,138U,138U,137U,137U,137U,135U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
139U,138U,139U,140U,139U,139U,141U,140U,139U,138U,137U,138U,139U,139U,139U,138U,138U,138U,137U,135U,135U,135U,135U,134U,135U,134U,134U,133U,132U,132U,133U,133U,132U,131U,131U,130U,131U,131U,128U,130U,131U,131U,132U,133U,134U,133U,130U,127U,126U,126U,127U,128U,132U,134U,135U,135U,135U,135U,135U,134U,134U,134U,133U,133U,133U,134U,134U,133U,133U,133U,134U,134U,135U,135U,134U,134U,134U,132U,130U,131U,133U,134U,135U,137U,137U,137U,137U,137U,137U,137U,135U,134U,65535U,65535U,65535U,65535U,65535U,65535U,
|
||||||
|
2048
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/table.3.csv
Normal file
2048
drivers/video/tegra/host/pva/src/kmd/common/dlut_data/table.3.csv
Normal file
File diff suppressed because it is too large
Load Diff
222468
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_ppe_elf_t26x.csv
Normal file
222468
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_ppe_elf_t26x.csv
Normal file
File diff suppressed because it is too large
Load Diff
1259221
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_vpu_elf_t23x.csv
Normal file
1259221
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_vpu_elf_t23x.csv
Normal file
File diff suppressed because it is too large
Load Diff
1279424
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_vpu_elf_t26x.csv
Normal file
1279424
drivers/video/tegra/host/pva/src/kmd/common/elf/pva_pfsd_vpu_elf_t26x.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,14 +6,15 @@
|
|||||||
#include "pva_kmd_regs.h"
|
#include "pva_kmd_regs.h"
|
||||||
#include "pva_kmd_silicon_utils.h"
|
#include "pva_kmd_silicon_utils.h"
|
||||||
|
|
||||||
void pva_kmd_abort_fw(struct pva_kmd_device *pva, uint32_t error_code)
|
void pva_kmd_abort_fw(struct pva_kmd_device *pva, enum pva_error error_code)
|
||||||
{
|
{
|
||||||
// HW watchdog may fire repeatedly if PVA is hung. Therefore, disable all
|
// HW watchdog may fire repeatedly if PVA is hung. Therefore, disable all
|
||||||
// interrupts to protect KMD from potential interrupt floods.
|
// interrupts to protect KMD from potential interrupt floods.
|
||||||
pva_kmd_disable_all_interrupts_nosync(pva);
|
pva_kmd_disable_all_interrupts_nosync(pva);
|
||||||
|
|
||||||
pva_kmd_report_error_fsi(pva, error_code);
|
pva_kmd_report_error_fsi(pva, (uint32_t)error_code);
|
||||||
// We will handle firmware reboot after all contexts are closed and a new
|
// We will handle firmware reboot after all contexts are closed and a new
|
||||||
// one is re-opened again
|
// one is re-opened again
|
||||||
pva->recovery = true;
|
pva->recovery = true;
|
||||||
|
pva->fw_aborted = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,28 @@
|
|||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
|
|
||||||
void pva_kmd_abort_fw(struct pva_kmd_device *pva, uint32_t error_code);
|
/**
|
||||||
|
* @brief Abort firmware execution and initiate error recovery
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Immediately signals the firmware to abort current operations
|
||||||
|
* - Logs the provided error code using @ref pva_kmd_log_err_hex32()
|
||||||
|
* - Initiates emergency shutdown procedures for the PVA device
|
||||||
|
* - Marks the device as being in recovery mode for subsequent operations
|
||||||
|
* - Notifies platform-specific error handling mechanisms
|
||||||
|
* - Prepares the device for potential firmware restart or reset
|
||||||
|
* - Ensures all pending operations are cancelled safely
|
||||||
|
*
|
||||||
|
* This function is used in critical error scenarios where the firmware
|
||||||
|
* has encountered an unrecoverable error or the system has detected a
|
||||||
|
* condition that requires immediate firmware termination. The error code
|
||||||
|
* is preserved for debugging and diagnostic purposes.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] error_code Error code indicating the reason for abort
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
|
void pva_kmd_abort_fw(struct pva_kmd_device *pva, enum pva_error error_code);
|
||||||
|
|
||||||
#endif //PVA_KMD_ABORT_H
|
#endif //PVA_KMD_ABORT_H
|
||||||
|
|||||||
@@ -4,31 +4,36 @@
|
|||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_api.h"
|
#include "pva_api.h"
|
||||||
|
|
||||||
#define INVALID_ID 0xFFFFFFFF
|
#define INVALID_ID 0xFFFFFFFFU
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_block_allocator_init(struct pva_kmd_block_allocator *allocator,
|
pva_kmd_block_allocator_init(struct pva_kmd_block_allocator *allocator,
|
||||||
void *block_mem, uint32_t base_id,
|
void *chunk_mem, uint32_t base_id,
|
||||||
uint32_t block_size, uint32_t max_num_blocks)
|
uint32_t chunk_size, uint32_t max_num_chunks)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
allocator->free_slot_head = INVALID_ID;
|
allocator->free_slot_head = INVALID_ID;
|
||||||
allocator->next_free_slot = 0;
|
allocator->next_free_slot = 0;
|
||||||
allocator->max_num_blocks = max_num_blocks;
|
allocator->max_num_blocks = max_num_chunks;
|
||||||
allocator->block_size = block_size;
|
allocator->block_size = chunk_size;
|
||||||
allocator->base_id = base_id;
|
allocator->base_id = base_id;
|
||||||
|
|
||||||
allocator->blocks = block_mem;
|
allocator->blocks = chunk_mem;
|
||||||
|
|
||||||
allocator->slot_in_use = pva_kmd_zalloc(
|
allocator->slot_in_use = pva_kmd_zalloc(
|
||||||
sizeof(*allocator->slot_in_use) * max_num_blocks);
|
sizeof(*allocator->slot_in_use) * max_num_chunks);
|
||||||
if (!allocator->slot_in_use) {
|
if (allocator->slot_in_use == NULL) {
|
||||||
err = PVA_NOMEM;
|
err = PVA_NOMEM;
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"pva_kmd_block_allocator_init slot_in_use NULL");
|
"pva_kmd_block_allocator_init slot_in_use NULL");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
pva_kmd_mutex_init(&allocator->allocator_lock);
|
err = pva_kmd_mutex_init(&allocator->allocator_lock);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_block_allocator_init mutex_init failed");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
err_out:
|
err_out:
|
||||||
return err;
|
return err;
|
||||||
@@ -43,9 +48,11 @@ void pva_kmd_block_allocator_deinit(struct pva_kmd_block_allocator *allocator)
|
|||||||
static inline void *get_block(struct pva_kmd_block_allocator *allocator,
|
static inline void *get_block(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t slot)
|
uint32_t slot)
|
||||||
{
|
{
|
||||||
uintptr_t base = (uintptr_t)allocator->blocks;
|
uintptr_t base = (uintptr_t)(void *)allocator->blocks;
|
||||||
uintptr_t addr = base + (slot * allocator->block_size);
|
uint64_t offset =
|
||||||
return (void *)addr;
|
safe_mulu64((uint64_t)slot, (uint64_t)allocator->block_size);
|
||||||
|
uint64_t addr = safe_addu64((uint64_t)base, offset);
|
||||||
|
return (void *)(uintptr_t)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t next_slot(struct pva_kmd_block_allocator *allocator,
|
static inline uint32_t next_slot(struct pva_kmd_block_allocator *allocator,
|
||||||
|
|||||||
@@ -6,53 +6,281 @@
|
|||||||
#include "pva_api.h"
|
#include "pva_api.h"
|
||||||
#include "pva_kmd_mutex.h"
|
#include "pva_kmd_mutex.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing fixed-size memory blocks
|
||||||
|
*
|
||||||
|
* @details This structure provides efficient allocation and deallocation of
|
||||||
|
* fixed-size memory blocks from a pre-allocated memory region. It maintains
|
||||||
|
* a free list of available blocks and provides thread-safe access through
|
||||||
|
* mutex protection. The allocator is particularly useful for managing pools
|
||||||
|
* of objects such as command buffers, resource records, or other frequently
|
||||||
|
* allocated data structures.
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator {
|
struct pva_kmd_block_allocator {
|
||||||
|
/**
|
||||||
|
* @brief Head of the free slot linked list
|
||||||
|
* Valid range: [0 .. max_num_blocks-1] or special sentinel values
|
||||||
|
*/
|
||||||
uint32_t free_slot_head;
|
uint32_t free_slot_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base ID for allocated blocks
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t base_id;
|
uint32_t base_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of blocks that can be allocated
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t max_num_blocks;
|
uint32_t max_num_blocks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Next free slot to be allocated
|
||||||
|
* Valid range: [0 .. max_num_blocks-1]
|
||||||
|
*/
|
||||||
uint32_t next_free_slot;
|
uint32_t next_free_slot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of each block in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t block_size;
|
uint32_t block_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the base of the block memory region
|
||||||
|
*/
|
||||||
void *blocks;
|
void *blocks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array tracking which slots are currently in use
|
||||||
|
*/
|
||||||
bool *slot_in_use;
|
bool *slot_in_use;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mutex protecting allocator operations for thread safety
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t allocator_lock;
|
pva_kmd_mutex_t allocator_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a block allocator with specified memory and parameters
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the allocator structure with provided memory region
|
||||||
|
* - Sets up the free list linking all available blocks
|
||||||
|
* - Configures block size and maximum block count parameters
|
||||||
|
* - Initializes the usage tracking array for allocated blocks
|
||||||
|
* - Sets up mutex for thread-safe allocation operations
|
||||||
|
* - Establishes base ID for block identification
|
||||||
|
* - Prepares the allocator for block allocation and deallocation
|
||||||
|
*
|
||||||
|
* The provided memory region must be large enough to hold max_num_chunks
|
||||||
|
* blocks of chunk_size bytes each. After successful initialization, blocks
|
||||||
|
* can be allocated using @ref pva_kmd_alloc_block() and freed using
|
||||||
|
* @ref pva_kmd_free_block().
|
||||||
|
*
|
||||||
|
* @param[out] allocator Pointer to @ref pva_kmd_block_allocator structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] chunk_mem Pointer to pre-allocated memory for block storage
|
||||||
|
* Valid value: non-null, must be at least
|
||||||
|
* (chunk_size * max_num_chunks) bytes
|
||||||
|
* @param[in] base_id Base identifier for allocated blocks
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
* @param[in] chunk_size Size of each block in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] max_num_chunks Maximum number of blocks that can be allocated
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Allocator initialized successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate memory for slot tracking array
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_block_allocator_init(struct pva_kmd_block_allocator *allocator,
|
pva_kmd_block_allocator_init(struct pva_kmd_block_allocator *allocator,
|
||||||
void *chunk_mem, uint32_t base_id,
|
void *chunk_mem, uint32_t base_id,
|
||||||
uint32_t chunk_size, uint32_t max_num_chunks);
|
uint32_t chunk_size, uint32_t max_num_chunks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a block from the allocator (thread-safe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the allocator mutex for thread-safe operation
|
||||||
|
* - Checks if any blocks are available for allocation
|
||||||
|
* - Removes a block from the free list if available
|
||||||
|
* - Marks the block as in use in the usage tracking array
|
||||||
|
* - Assigns a unique block ID based on the base ID and slot index
|
||||||
|
* - Returns pointer to the allocated block and its ID
|
||||||
|
* - Releases the allocator mutex after completion
|
||||||
|
*
|
||||||
|
* The allocated block remains valid until it is freed using
|
||||||
|
* @ref pva_kmd_free_block(). The block ID can be used to reference
|
||||||
|
* the block in other operations or to free it later.
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] out_id Pointer to store the allocated block ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to allocated block if successful
|
||||||
|
* @retval NULL No blocks available for allocation
|
||||||
|
*/
|
||||||
void *pva_kmd_alloc_block(struct pva_kmd_block_allocator *allocator,
|
void *pva_kmd_alloc_block(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t *out_id);
|
uint32_t *out_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a block from the allocator (unsafe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Checks if any blocks are available for allocation
|
||||||
|
* - Removes a block from the free list if available
|
||||||
|
* - Marks the block as in use in the usage tracking array
|
||||||
|
* - Assigns a unique block ID based on the base ID and slot index
|
||||||
|
* - Returns pointer to the allocated block and its ID
|
||||||
|
*
|
||||||
|
* This function is not thread-safe and requires external synchronization.
|
||||||
|
* The caller must ensure proper locking around calls to this function and
|
||||||
|
* the corresponding @ref pva_kmd_free_block_unsafe().
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] out_id Pointer to store the allocated block ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to allocated block if successful
|
||||||
|
* @retval NULL No blocks available for allocation
|
||||||
|
*/
|
||||||
void *pva_kmd_alloc_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
void *pva_kmd_alloc_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t *out_id);
|
uint32_t *out_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and zero-initialize a block from the allocator
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calls @ref pva_kmd_alloc_block() to allocate a block
|
||||||
|
* - Zero-initializes the entire block using @ref memset()
|
||||||
|
* - Returns pointer to the zero-initialized block
|
||||||
|
* - Provides the allocated block ID through the output parameter
|
||||||
|
*
|
||||||
|
* This inline function provides a convenient way to allocate blocks that
|
||||||
|
* need to be initialized to zero. The zero initialization covers the entire
|
||||||
|
* block size as specified during allocator initialization.
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] out_id Pointer to store the allocated block ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to zero-initialized allocated block if successful
|
||||||
|
* @retval NULL No blocks available for allocation
|
||||||
|
*/
|
||||||
static inline void *
|
static inline void *
|
||||||
pva_kmd_zalloc_block(struct pva_kmd_block_allocator *allocator,
|
pva_kmd_zalloc_block(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t *out_id)
|
uint32_t *out_id)
|
||||||
{
|
{
|
||||||
void *ptr = pva_kmd_alloc_block(allocator, out_id);
|
void *ptr = pva_kmd_alloc_block(allocator, out_id);
|
||||||
if (ptr != NULL) {
|
if (ptr != NULL) {
|
||||||
memset(ptr, 0, allocator->block_size);
|
(void)memset(ptr, 0, allocator->block_size);
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This API is not thread safe and has to be explicitly locked during use of the obtained block.
|
/**
|
||||||
|
* @brief Get pointer to a block by ID without allocation (unsafe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided block ID against the allocator's range
|
||||||
|
* - Calculates the memory address of the block from the ID
|
||||||
|
* - Returns pointer to the block without changing its allocation state
|
||||||
|
* - Does not perform any allocation or reference counting
|
||||||
|
*
|
||||||
|
* This API is not thread safe and has to be explicitly locked during use of the obtained block.
|
||||||
* This is to ensure that a parallel free operation does not result in dangling pointer to obtained block.
|
* This is to ensure that a parallel free operation does not result in dangling pointer to obtained block.
|
||||||
* Correct usage:
|
* Correct usage:
|
||||||
* lock(allocator)
|
* lock(allocator)
|
||||||
* block - pva_kmd_get_block_unsafe();
|
* block - @ref pva_kmd_get_block_unsafe();
|
||||||
* use block
|
* use block
|
||||||
* unlock(allocator)
|
* unlock(allocator)
|
||||||
|
*
|
||||||
|
* @param[in] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] id Block ID to retrieve
|
||||||
|
* Valid range: [base_id .. base_id+max_num_blocks-1]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to the block if ID is valid
|
||||||
|
* @retval NULL Invalid block ID or allocator not properly initialized
|
||||||
*/
|
*/
|
||||||
void *pva_kmd_get_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
void *pva_kmd_get_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t id);
|
uint32_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a previously allocated block (thread-safe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the allocator mutex for thread-safe operation
|
||||||
|
* - Validates the provided block ID against allocated blocks
|
||||||
|
* - Marks the block as no longer in use in the usage tracking array
|
||||||
|
* - Adds the block back to the free list for future allocation
|
||||||
|
* - Updates allocator state to reflect the freed block
|
||||||
|
* - Releases the allocator mutex after completion
|
||||||
|
*
|
||||||
|
* The block ID must correspond to a previously allocated block. After
|
||||||
|
* freeing, the block becomes available for future allocation and the
|
||||||
|
* ID should not be used to access the block.
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] id Block ID to free
|
||||||
|
* Valid range: [base_id .. base_id+max_num_blocks-1]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Block freed successfully
|
||||||
|
* @retval PVA_INVAL Invalid block ID or block not allocated
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_free_block(struct pva_kmd_block_allocator *allocator,
|
enum pva_error pva_kmd_free_block(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t id);
|
uint32_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a previously allocated block (unsafe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided block ID against allocated blocks
|
||||||
|
* - Marks the block as no longer in use in the usage tracking array
|
||||||
|
* - Adds the block back to the free list for future allocation
|
||||||
|
* - Updates allocator state to reflect the freed block
|
||||||
|
*
|
||||||
|
* This function is not thread-safe and requires external synchronization.
|
||||||
|
* The caller must ensure proper locking around calls to this function and
|
||||||
|
* the corresponding @ref pva_kmd_alloc_block_unsafe().
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] id Block ID to free
|
||||||
|
* Valid range: [base_id .. base_id+max_num_blocks-1]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Block freed successfully
|
||||||
|
* @retval PVA_INVAL Invalid block ID or block not allocated
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_free_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
pva_kmd_free_block_unsafe(struct pva_kmd_block_allocator *allocator,
|
||||||
uint32_t id);
|
uint32_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a block allocator and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures no blocks are currently allocated (debugging builds)
|
||||||
|
* - Deinitializes the allocator mutex using @ref pva_kmd_mutex_deinit()
|
||||||
|
* - Cleans up internal allocator state and data structures
|
||||||
|
* - Invalidates the allocator for future use
|
||||||
|
* - Does not free the underlying memory region (caller's responsibility)
|
||||||
|
*
|
||||||
|
* All allocated blocks should be freed before calling this function.
|
||||||
|
* After deinitialization, the allocator cannot be used for block allocation
|
||||||
|
* until it is reinitialized. The underlying memory region provided during
|
||||||
|
* initialization is not freed and remains the caller's responsibility.
|
||||||
|
*
|
||||||
|
* @param[in, out] allocator Pointer to @ref pva_kmd_block_allocator structure to deinitialize
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_block_allocator_deinit(struct pva_kmd_block_allocator *allocator);
|
void pva_kmd_block_allocator_deinit(struct pva_kmd_block_allocator *allocator);
|
||||||
|
|
||||||
#endif // PVA_KMD_BLOCK_ALLOCATOR_H
|
#endif // PVA_KMD_BLOCK_ALLOCATOR_H
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_math_utils.h"
|
#include "pva_math_utils.h"
|
||||||
|
|
||||||
#define CHUNK_STATE_INVALID 0
|
#define CHUNK_STATE_INVALID 0U
|
||||||
#define CHUNK_STATE_FENCE_TRIGGERED 1
|
#define CHUNK_STATE_FENCE_TRIGGERED 1U
|
||||||
|
|
||||||
static uint32_t *
|
static uint32_t *
|
||||||
get_chunk_states(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool)
|
get_chunk_states(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool)
|
||||||
@@ -20,15 +20,21 @@ static void *get_chunk(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
|||||||
uint32_t chunk_id)
|
uint32_t chunk_id)
|
||||||
{
|
{
|
||||||
return pva_offset_pointer(cmdbuf_chunk_pool->mem_base_va,
|
return pva_offset_pointer(cmdbuf_chunk_pool->mem_base_va,
|
||||||
cmdbuf_chunk_pool->chunk_size * chunk_id);
|
(uint64_t)cmdbuf_chunk_pool->chunk_size *
|
||||||
|
chunk_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_chunk_id_from_res_offset(
|
static uint32_t get_chunk_id_from_res_offset(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint64_t offset)
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint64_t offset)
|
||||||
{
|
{
|
||||||
|
uint64_t chunk_id_u64;
|
||||||
|
|
||||||
ASSERT(offset >= cmdbuf_chunk_pool->mem_offset);
|
ASSERT(offset >= cmdbuf_chunk_pool->mem_offset);
|
||||||
offset -= cmdbuf_chunk_pool->mem_offset;
|
offset -= cmdbuf_chunk_pool->mem_offset;
|
||||||
return offset / cmdbuf_chunk_pool->chunk_size;
|
chunk_id_u64 = offset / cmdbuf_chunk_pool->chunk_size;
|
||||||
|
/* chunk_id bounded by pool size and chunk size */
|
||||||
|
ASSERT(chunk_id_u64 <= U32_MAX);
|
||||||
|
return (uint32_t)chunk_id_u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_cmdbuf_chunk_pool_init(
|
enum pva_error pva_kmd_cmdbuf_chunk_pool_init(
|
||||||
@@ -49,41 +55,55 @@ enum pva_error pva_kmd_cmdbuf_chunk_pool_init(
|
|||||||
cmdbuf_chunk_pool->chunk_size = chunk_size;
|
cmdbuf_chunk_pool->chunk_size = chunk_size;
|
||||||
cmdbuf_chunk_pool->num_chunks = num_chunks;
|
cmdbuf_chunk_pool->num_chunks = num_chunks;
|
||||||
cmdbuf_chunk_pool->mem_base_va = mem_base_va;
|
cmdbuf_chunk_pool->mem_base_va = mem_base_va;
|
||||||
cmdbuf_chunk_pool->chunk_states_offset = chunk_size * num_chunks;
|
cmdbuf_chunk_pool->chunk_states_offset =
|
||||||
|
(uint64_t)chunk_size * num_chunks;
|
||||||
chunk_states = get_chunk_states(cmdbuf_chunk_pool);
|
chunk_states = get_chunk_states(cmdbuf_chunk_pool);
|
||||||
for (i = 0; i < num_chunks; i++) {
|
for (i = 0U; i < num_chunks; i++) {
|
||||||
chunk_states[i] = CHUNK_STATE_INVALID;
|
chunk_states[i] = CHUNK_STATE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_block_allocator_init(&cmdbuf_chunk_pool->block_allocator,
|
err = pva_kmd_block_allocator_init(&cmdbuf_chunk_pool->block_allocator,
|
||||||
mem_base_va, 0, chunk_size,
|
mem_base_va, 0, chunk_size,
|
||||||
num_chunks);
|
num_chunks);
|
||||||
pva_kmd_mutex_init(&cmdbuf_chunk_pool->chunk_state_lock);
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to initialize block allocator for cmdbuf chunk pool");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = pva_kmd_mutex_init(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_cmdbuf_chunk_pool_deinit(struct pva_kmd_cmdbuf_chunk_pool *pool)
|
void pva_kmd_cmdbuf_chunk_pool_deinit(
|
||||||
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool)
|
||||||
{
|
{
|
||||||
pva_kmd_mutex_deinit(&pool->chunk_state_lock);
|
pva_kmd_mutex_deinit(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
pva_kmd_block_allocator_deinit(&pool->block_allocator);
|
pva_kmd_block_allocator_deinit(&cmdbuf_chunk_pool->block_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_free_linked_cmdbuf_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool,
|
/* This function assumes locks are already held by caller */
|
||||||
|
static void
|
||||||
|
pva_kmd_free_linked_cmdbuf_chunks_unsafe(struct pva_kmd_cmdbuf_chunk_pool *pool,
|
||||||
uint32_t chunk_id)
|
uint32_t chunk_id)
|
||||||
{
|
{
|
||||||
struct pva_cmd_link_chunk *begin;
|
struct pva_cmd_link_chunk *begin;
|
||||||
uint32_t *chunk_states;
|
uint32_t *chunk_states;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint32_t resource_id;
|
uint32_t resource_id;
|
||||||
|
enum pva_error tmp_err;
|
||||||
|
|
||||||
chunk_states = get_chunk_states(pool);
|
chunk_states = get_chunk_states(pool);
|
||||||
|
/* Caller must hold both allocator_lock and chunk_state_lock */
|
||||||
while (true) {
|
while (true) {
|
||||||
begin = get_chunk(pool, chunk_id);
|
begin = get_chunk(pool, chunk_id);
|
||||||
chunk_states[chunk_id] = CHUNK_STATE_INVALID;
|
chunk_states[chunk_id] = CHUNK_STATE_INVALID;
|
||||||
offset = assemble_addr(begin->next_chunk_offset_hi,
|
offset = assemble_addr(begin->next_chunk_offset_hi,
|
||||||
begin->next_chunk_offset_lo);
|
begin->next_chunk_offset_lo);
|
||||||
resource_id = begin->next_chunk_resource_id;
|
resource_id = begin->next_chunk_resource_id;
|
||||||
pva_kmd_free_block(&pool->block_allocator, chunk_id);
|
/* Use unsafe version since caller already holds allocator_lock */
|
||||||
|
tmp_err = pva_kmd_free_block_unsafe(&pool->block_allocator,
|
||||||
|
chunk_id);
|
||||||
|
ASSERT(tmp_err == PVA_SUCCESS);
|
||||||
if (resource_id == PVA_RESOURCE_ID_INVALID) {
|
if (resource_id == PVA_RESOURCE_ID_INVALID) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -93,6 +113,18 @@ void pva_kmd_free_linked_cmdbuf_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pva_kmd_free_linked_cmdbuf_chunks(
|
||||||
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id)
|
||||||
|
{
|
||||||
|
/* CERT CON35-C: Acquire locks in consistent order to prevent deadlock */
|
||||||
|
pva_kmd_mutex_lock(&cmdbuf_chunk_pool->block_allocator.allocator_lock);
|
||||||
|
pva_kmd_mutex_lock(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
|
pva_kmd_free_linked_cmdbuf_chunks_unsafe(cmdbuf_chunk_pool, chunk_id);
|
||||||
|
pva_kmd_mutex_unlock(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
|
pva_kmd_mutex_unlock(
|
||||||
|
&cmdbuf_chunk_pool->block_allocator.allocator_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static bool recycle_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool)
|
static bool recycle_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool)
|
||||||
{
|
{
|
||||||
uint32_t *chunk_states;
|
uint32_t *chunk_states;
|
||||||
@@ -100,9 +132,10 @@ static bool recycle_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool)
|
|||||||
bool freed = false;
|
bool freed = false;
|
||||||
|
|
||||||
chunk_states = get_chunk_states(pool);
|
chunk_states = get_chunk_states(pool);
|
||||||
for (i = 0; i < pool->num_chunks; i++) {
|
for (i = 0U; i < pool->num_chunks; i++) {
|
||||||
if (chunk_states[i] == CHUNK_STATE_FENCE_TRIGGERED) {
|
if (chunk_states[i] == CHUNK_STATE_FENCE_TRIGGERED) {
|
||||||
pva_kmd_free_linked_cmdbuf_chunks(pool, i);
|
/* Use unsafe version since caller already holds locks */
|
||||||
|
pva_kmd_free_linked_cmdbuf_chunks_unsafe(pool, i);
|
||||||
freed = true;
|
freed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -112,38 +145,47 @@ static bool recycle_chunks(struct pva_kmd_cmdbuf_chunk_pool *pool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_alloc_cmdbuf_chunk(struct pva_kmd_cmdbuf_chunk_pool *pool,
|
pva_kmd_alloc_cmdbuf_chunk(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
||||||
uint32_t *out_chunk_id)
|
uint32_t *out_chunk_id)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
void *chunk;
|
void *chunk;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&pool->chunk_state_lock);
|
/* CERT CON35-C: Acquire locks in consistent order to prevent deadlock.
|
||||||
chunk = pva_kmd_alloc_block(&pool->block_allocator, out_chunk_id);
|
* Lock ordering: allocator_lock before chunk_state_lock
|
||||||
|
*/
|
||||||
|
pva_kmd_mutex_lock(&cmdbuf_chunk_pool->block_allocator.allocator_lock);
|
||||||
|
pva_kmd_mutex_lock(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
|
chunk = pva_kmd_alloc_block_unsafe(&cmdbuf_chunk_pool->block_allocator,
|
||||||
|
out_chunk_id);
|
||||||
if (chunk == NULL) {
|
if (chunk == NULL) {
|
||||||
if (recycle_chunks(pool)) {
|
if (recycle_chunks(cmdbuf_chunk_pool)) {
|
||||||
chunk = pva_kmd_alloc_block(&pool->block_allocator,
|
chunk = pva_kmd_alloc_block_unsafe(
|
||||||
|
&cmdbuf_chunk_pool->block_allocator,
|
||||||
out_chunk_id);
|
out_chunk_id);
|
||||||
ASSERT(chunk != NULL);
|
ASSERT(chunk != NULL);
|
||||||
} else {
|
} else {
|
||||||
err = PVA_NOMEM;
|
err = PVA_NOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pva_kmd_mutex_unlock(&pool->chunk_state_lock);
|
pva_kmd_mutex_unlock(&cmdbuf_chunk_pool->chunk_state_lock);
|
||||||
|
pva_kmd_mutex_unlock(
|
||||||
|
&cmdbuf_chunk_pool->block_allocator.allocator_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_get_free_notifier_fence(struct pva_kmd_cmdbuf_chunk_pool *pool,
|
void pva_kmd_get_free_notifier_fence(
|
||||||
uint32_t chunk_id,
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id,
|
||||||
struct pva_fw_postfence *fence)
|
struct pva_fw_postfence *fence)
|
||||||
{
|
{
|
||||||
uint64_t offset_sum =
|
uint64_t offset_sum =
|
||||||
safe_addu64(pool->mem_offset, pool->chunk_states_offset);
|
safe_addu64(cmdbuf_chunk_pool->mem_offset,
|
||||||
|
cmdbuf_chunk_pool->chunk_states_offset);
|
||||||
uint64_t chunk_size =
|
uint64_t chunk_size =
|
||||||
(uint64_t)safe_mulu32((uint32_t)sizeof(uint32_t), chunk_id);
|
(uint64_t)safe_mulu32((uint32_t)sizeof(uint32_t), chunk_id);
|
||||||
uint64_t state_offset = safe_addu64(offset_sum, chunk_size);
|
uint64_t state_offset = safe_addu64(offset_sum, chunk_size);
|
||||||
memset(fence, 0, sizeof(*fence));
|
(void)memset(fence, 0, sizeof(*fence));
|
||||||
fence->resource_id = pool->mem_resource_id;
|
fence->resource_id = cmdbuf_chunk_pool->mem_resource_id;
|
||||||
fence->offset_lo = iova_lo(state_offset);
|
fence->offset_lo = iova_lo(state_offset);
|
||||||
fence->offset_hi = iova_hi(state_offset);
|
fence->offset_hi = iova_hi(state_offset);
|
||||||
fence->value = CHUNK_STATE_FENCE_TRIGGERED;
|
fence->value = CHUNK_STATE_FENCE_TRIGGERED;
|
||||||
@@ -162,11 +204,12 @@ static void begin_chunk(struct pva_kmd_cmdbuf_builder *builder)
|
|||||||
{
|
{
|
||||||
struct pva_cmd_link_chunk *cmd = pva_kmd_get_cmdbuf_chunk_va(
|
struct pva_cmd_link_chunk *cmd = pva_kmd_get_cmdbuf_chunk_va(
|
||||||
builder->pool, builder->current_chunk_id);
|
builder->pool, builder->current_chunk_id);
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_LINK_CHUNK;
|
cmd->header.opcode = PVA_CMD_OPCODE_LINK_CHUNK;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->next_chunk_resource_id = PVA_RESOURCE_ID_INVALID;
|
cmd->next_chunk_resource_id = PVA_RESOURCE_ID_INVALID;
|
||||||
builder->current_chunk_offset = sizeof(*cmd);
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
builder->current_chunk_offset = (uint16_t)sizeof(*cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void end_chunk(struct pva_kmd_cmdbuf_builder *builder)
|
static void end_chunk(struct pva_kmd_cmdbuf_builder *builder)
|
||||||
@@ -237,7 +280,8 @@ pva_kmd_cmdbuf_builder_init(struct pva_kmd_cmdbuf_builder *builder,
|
|||||||
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool)
|
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
uint32_t const min_chunk_size = sizeof(struct pva_cmd_link_chunk);
|
uint32_t const min_chunk_size =
|
||||||
|
(uint32_t)sizeof(struct pva_cmd_link_chunk);
|
||||||
|
|
||||||
ASSERT(chunk_pool->chunk_size >= min_chunk_size);
|
ASSERT(chunk_pool->chunk_size >= min_chunk_size);
|
||||||
|
|
||||||
|
|||||||
@@ -9,29 +9,94 @@
|
|||||||
#include "pva_api_cmdbuf.h"
|
#include "pva_api_cmdbuf.h"
|
||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
#include "pva_math_utils.h"
|
#include "pva_math_utils.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
struct pva_kmd_queue;
|
struct pva_kmd_queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fixed-size pool of command buffer chunks.
|
* @brief Fixed-size pool of command buffer chunks for efficient allocation
|
||||||
*
|
*
|
||||||
* We can allocate chunks from this pool. When submitting the chunks, we should
|
* @details A fixed-size pool of command buffer chunks designed for efficient
|
||||||
* request a post fence from the pool for the first chunk. When the post fence
|
* command buffer allocation and management. The pool allocates chunks from
|
||||||
* is triggered, the chain of chunks will be considered free by the pool.
|
* a pre-allocated memory region and provides automatic cleanup through post
|
||||||
|
* fence notifications. When submitting chunks, a post fence should be requested
|
||||||
|
* for the first chunk, and when the fence is triggered, the entire chain of
|
||||||
|
* chunks is automatically freed by the pool.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_cmdbuf_chunk_pool {
|
struct pva_kmd_cmdbuf_chunk_pool {
|
||||||
|
/**
|
||||||
|
* @brief Size of each chunk in bytes
|
||||||
|
* Valid range: [1 .. UINT16_MAX]
|
||||||
|
*/
|
||||||
uint16_t chunk_size;
|
uint16_t chunk_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Total number of chunks in the pool
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t num_chunks;
|
uint32_t num_chunks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource ID of the memory used for this pool
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t mem_resource_id;
|
uint32_t mem_resource_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Total size of memory allocated for the pool
|
||||||
|
* Valid range: [chunk_size .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t mem_size;
|
uint64_t mem_size;
|
||||||
uint64_t mem_offset; /**< Starting offset in the resource that can be
|
|
||||||
* used by this pool */
|
/**
|
||||||
|
* @brief Starting offset within the resource for this pool
|
||||||
|
*
|
||||||
|
* @details Starting offset in the resource that can be used by this pool
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
|
uint64_t mem_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Offset to chunk state tracking information
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t chunk_states_offset;
|
uint64_t chunk_states_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Virtual address base pointer for pool memory access
|
||||||
|
*/
|
||||||
void *mem_base_va;
|
void *mem_base_va;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing chunk allocation within the pool
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator block_allocator;
|
struct pva_kmd_block_allocator block_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mutex protecting chunk state modifications
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t chunk_state_lock;
|
pva_kmd_mutex_t chunk_state_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate required memory size for a command buffer chunk pool
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calculates the memory needed for all chunks of the specified size
|
||||||
|
* - Adds storage space required for free notifier fences (uint32_t per chunk)
|
||||||
|
* - Returns the total memory requirement for pool initialization
|
||||||
|
* - Accounts for chunk state tracking and fence notification overhead
|
||||||
|
*
|
||||||
|
* The returned size should be used when allocating memory for pool
|
||||||
|
* initialization with @ref pva_kmd_cmdbuf_chunk_pool_init().
|
||||||
|
*
|
||||||
|
* @param[in] chunk_size Size of each chunk in bytes
|
||||||
|
* Valid range: [1 .. UINT16_MAX]
|
||||||
|
* @param[in] num_chunks Number of chunks in the pool
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval memory_size Total memory size required for the pool in bytes
|
||||||
|
*/
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
pva_kmd_cmdbuf_pool_get_required_mem_size(uint16_t chunk_size,
|
pva_kmd_cmdbuf_pool_get_required_mem_size(uint16_t chunk_size,
|
||||||
uint32_t num_chunks)
|
uint32_t num_chunks)
|
||||||
@@ -41,69 +106,201 @@ pva_kmd_cmdbuf_pool_get_required_mem_size(uint16_t chunk_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the chunk pool.
|
* @brief Initialize a command buffer chunk pool
|
||||||
*
|
*
|
||||||
* @param[out] Pointer to the pool.
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the chunk pool structure with provided memory and parameters
|
||||||
|
* - Sets up the block allocator for managing individual chunk allocation
|
||||||
|
* - Configures chunk size, count, and memory layout parameters
|
||||||
|
* - Establishes virtual address mapping for pool memory access
|
||||||
|
* - Initializes synchronization primitives for thread-safe operations
|
||||||
|
* - Prepares free notifier fence storage for automatic chunk cleanup
|
||||||
|
* - Associates the pool with the specified memory resource
|
||||||
*
|
*
|
||||||
* @param[in] mem_resource_id Resource ID of the memory to be used for the pool.
|
* The chunk pool enables efficient allocation and automatic cleanup of
|
||||||
|
* command buffer chunks. After initialization, chunks can be allocated using
|
||||||
|
* @ref pva_kmd_alloc_cmdbuf_chunk() and will be automatically freed when
|
||||||
|
* their associated fence is triggered.
|
||||||
*
|
*
|
||||||
* @param[in] mem_offset Offset of the memory to be used for the pool.
|
* @param[out] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
* @param[in] mem_size Size of the memory to be used for the pool.
|
* @param[in] mem_resource_id Resource ID of the memory for the pool
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
* @param[in] mem_offset Offset within the resource for pool memory
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
* @param[in] mem_size Size of memory allocated for the pool
|
||||||
|
* Valid range: [required_size .. UINT32_MAX]
|
||||||
|
* @param[in] chunk_size Size of each chunk in bytes
|
||||||
|
* Valid range: [1 .. UINT16_MAX]
|
||||||
|
* @param[in] num_chunks Number of chunks in the pool
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] mem_base_va Virtual address base of the memory resource
|
||||||
|
* Valid value: non-null
|
||||||
*
|
*
|
||||||
* @param[in] chunk_size Size of each chunk in the pool.
|
* @retval PVA_SUCCESS Pool initialized successfully
|
||||||
*
|
* @retval PVA_NOMEM Failed to initialize block allocator
|
||||||
* @param[in] num_chunks Number of chunks in the pool.
|
|
||||||
*
|
|
||||||
* @param[in] mem_base_va Virtual address of the memory to be used for the pool.
|
|
||||||
* The virtual address is the base address of the resource.
|
|
||||||
*/
|
*/
|
||||||
enum pva_error pva_kmd_cmdbuf_chunk_pool_init(
|
enum pva_error pva_kmd_cmdbuf_chunk_pool_init(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
||||||
uint32_t mem_resource_id, uint64_t mem_offset, uint32_t mem_size,
|
uint32_t mem_resource_id, uint64_t mem_offset, uint32_t mem_size,
|
||||||
uint16_t chunk_size, uint32_t num_chunks, void *mem_base_va);
|
uint16_t chunk_size, uint32_t num_chunks, void *mem_base_va);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a command buffer chunk pool and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures all chunks have been properly freed and returned to the pool
|
||||||
|
* - Deinitializes the block allocator used for chunk management
|
||||||
|
* - Destroys synchronization primitives including mutexes
|
||||||
|
* - Cleans up internal pool state and data structures
|
||||||
|
* - Invalidates the pool for future use
|
||||||
|
* - Does not free the underlying memory resource (caller's responsibility)
|
||||||
|
*
|
||||||
|
* All chunks should be freed before calling this function. After
|
||||||
|
* deinitialization, the pool cannot be used for chunk allocation until
|
||||||
|
* it is reinitialized.
|
||||||
|
*
|
||||||
|
* @param[in, out] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* to deinitialize
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_cmdbuf_chunk_pool_deinit(
|
void pva_kmd_cmdbuf_chunk_pool_deinit(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool);
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a chunk from the pool.
|
* @brief Allocate a command buffer chunk from the pool
|
||||||
*
|
*
|
||||||
* If the chunk is submitted, then free will be done automatically when
|
* @details This function performs the following operations:
|
||||||
* free-notifier fence is triggered.
|
* - Allocates a chunk from the pool using the internal block allocator
|
||||||
|
* - Returns a unique chunk ID for referencing the allocated chunk
|
||||||
|
* - Marks the chunk as in use within the pool's tracking system
|
||||||
|
* - Provides chunk memory for command buffer construction
|
||||||
|
* - Enables automatic cleanup when the chunk is submitted with a fence
|
||||||
|
*
|
||||||
|
* If the chunk is submitted with a free-notifier fence, the chunk will be
|
||||||
|
* automatically freed when the fence is triggered. If the chunk is not
|
||||||
|
* submitted, it should be manually freed using @ref pva_kmd_free_linked_cmdbuf_chunks()
|
||||||
|
* to avoid memory leaks.
|
||||||
|
*
|
||||||
|
* @param[in, out] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] out_chunk_id Pointer to store the allocated chunk ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Chunk allocated successfully
|
||||||
|
* @retval PVA_NOMEM No chunks available in the pool
|
||||||
*/
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_alloc_cmdbuf_chunk(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
pva_kmd_alloc_cmdbuf_chunk(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
||||||
uint32_t *out_chunk_id);
|
uint32_t *out_chunk_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free a linked list of chunks.
|
* @brief Free a linked list of command buffer chunks
|
||||||
*
|
*
|
||||||
* We only need to call this function if we decide not to submit the chunks,
|
* @details This function performs the following operations:
|
||||||
* usually in error path.
|
* - Traverses the linked list of chunks starting from the specified chunk ID
|
||||||
|
* - Frees each chunk in the chain back to the pool for reuse
|
||||||
|
* - Updates pool state to reflect the freed chunks
|
||||||
|
* - Handles chunk linking and ensures proper cleanup of the entire chain
|
||||||
|
* - Resets chunk state tracking for the freed chunks
|
||||||
|
*
|
||||||
|
* This function should only be called if the chunks are not submitted,
|
||||||
|
* typically in error paths where command buffer construction fails.
|
||||||
|
* For submitted chunks, automatic cleanup occurs when the free-notifier
|
||||||
|
* fence is triggered, making manual cleanup unnecessary.
|
||||||
|
*
|
||||||
|
* @param[in, out] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_id ID of the first chunk in the linked list to free
|
||||||
|
* Valid range: Valid chunk ID from previous allocation
|
||||||
*/
|
*/
|
||||||
void pva_kmd_free_linked_cmdbuf_chunks(
|
void pva_kmd_free_linked_cmdbuf_chunks(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id);
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the free-notifier fence.
|
* @brief Get the free-notifier fence for automatic chunk cleanup
|
||||||
*
|
*
|
||||||
* @param[in] The first chunk of the command buffer to be submitted.
|
* @details This function performs the following operations:
|
||||||
|
* - Configures a post fence for automatic chunk cleanup upon completion
|
||||||
|
* - Associates the fence with the specified chunk for cleanup tracking
|
||||||
|
* - Sets up the fence to trigger when the command buffer completes execution
|
||||||
|
* - Enables automatic return of chunks to the pool when work is finished
|
||||||
|
* - Configures fence parameters for proper cleanup timing
|
||||||
*
|
*
|
||||||
* @param[out] The free-notifier fence that should be submitted with the command buffer.
|
* The returned fence should be submitted along with the command buffer
|
||||||
|
* to enable automatic cleanup. When the fence is triggered by firmware
|
||||||
|
* upon command completion, all linked chunks starting from the specified
|
||||||
|
* chunk will be automatically freed and returned to the pool.
|
||||||
|
*
|
||||||
|
* @param[in] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_id ID of the first chunk in the command buffer to be submitted
|
||||||
|
* Valid range: Valid chunk ID from previous allocation
|
||||||
|
* @param[out] fence Pointer to @ref pva_fw_postfence structure to configure
|
||||||
|
* Valid value: non-null
|
||||||
*/
|
*/
|
||||||
void pva_kmd_get_free_notifier_fence(
|
void pva_kmd_get_free_notifier_fence(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id,
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id,
|
||||||
struct pva_fw_postfence *fence);
|
struct pva_fw_postfence *fence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get virtual address pointer for a command buffer chunk
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calculates the virtual memory address for the specified chunk
|
||||||
|
* - Uses the chunk ID and pool's base address for address calculation
|
||||||
|
* - Returns a pointer suitable for writing command data
|
||||||
|
* - Provides direct memory access to the chunk's storage area
|
||||||
|
* - Enables efficient command buffer construction in allocated chunks
|
||||||
|
*
|
||||||
|
* The returned pointer can be used to write command data directly into
|
||||||
|
* the chunk memory. The pointer remains valid until the chunk is freed
|
||||||
|
* or the pool is deinitialized.
|
||||||
|
*
|
||||||
|
* @param[in] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_id Chunk ID to get virtual address for
|
||||||
|
* Valid range: Valid chunk ID from previous allocation
|
||||||
|
*
|
||||||
|
* @retval pointer Virtual address pointer to the chunk memory
|
||||||
|
*/
|
||||||
static inline void *
|
static inline void *
|
||||||
pva_kmd_get_cmdbuf_chunk_va(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
pva_kmd_get_cmdbuf_chunk_va(struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool,
|
||||||
uint32_t chunk_id)
|
uint32_t chunk_id)
|
||||||
{
|
{
|
||||||
return (void *)((uintptr_t)cmdbuf_chunk_pool->mem_base_va +
|
/* Use byte pointer arithmetic to avoid INT36-C violation */
|
||||||
chunk_id * cmdbuf_chunk_pool->chunk_size);
|
char *base;
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
/* Verify alignment for proper access */
|
||||||
|
ASSERT(cmdbuf_chunk_pool->chunk_size % sizeof(uint32_t) == 0U);
|
||||||
|
|
||||||
|
base = (char *)cmdbuf_chunk_pool->mem_base_va;
|
||||||
|
offset = (size_t)chunk_id * cmdbuf_chunk_pool->chunk_size;
|
||||||
|
return (void *)(base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get resource offset for a command buffer chunk
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calculates the offset of the chunk within the memory resource
|
||||||
|
* - Uses safe arithmetic to prevent overflow during calculation
|
||||||
|
* - Adds the pool's memory offset to the chunk-specific offset
|
||||||
|
* - Returns the absolute offset for firmware addressing
|
||||||
|
* - Enables proper IOVA calculations for hardware access
|
||||||
|
*
|
||||||
|
* The returned offset can be used by firmware to calculate IOVA addresses
|
||||||
|
* for accessing the chunk memory during command execution. The offset is
|
||||||
|
* relative to the base of the memory resource.
|
||||||
|
*
|
||||||
|
* @param[in] cmdbuf_chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_id Chunk ID to get resource offset for
|
||||||
|
* Valid range: Valid chunk ID from previous allocation
|
||||||
|
*
|
||||||
|
* @retval offset Resource offset of the chunk in bytes
|
||||||
|
*/
|
||||||
static inline uint64_t pva_kmd_get_cmdbuf_chunk_res_offset(
|
static inline uint64_t pva_kmd_get_cmdbuf_chunk_res_offset(
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id)
|
struct pva_kmd_cmdbuf_chunk_pool *cmdbuf_chunk_pool, uint32_t chunk_id)
|
||||||
{
|
{
|
||||||
@@ -113,52 +310,198 @@ static inline uint64_t pva_kmd_get_cmdbuf_chunk_res_offset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility for building a command buffer with multiple chunks.
|
* @brief Utility for building command buffers with automatic chunk management
|
||||||
*
|
*
|
||||||
* The builder will automatically allocate chunks from the pool when the current
|
* @details This structure provides a convenient interface for building command
|
||||||
* chunk is full.
|
* buffers that may span multiple chunks. The builder automatically allocates
|
||||||
|
* new chunks from the pool when the current chunk becomes full, links chunks
|
||||||
|
* together with appropriate commands, and manages the overall command buffer
|
||||||
|
* structure. It simplifies command buffer construction by handling chunk
|
||||||
|
* boundaries and linking transparently.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_cmdbuf_builder {
|
struct pva_kmd_cmdbuf_builder {
|
||||||
|
/**
|
||||||
|
* @brief Size of the first chunk in the command buffer
|
||||||
|
* Valid range: [1 .. UINT16_MAX]
|
||||||
|
*/
|
||||||
uint16_t first_chunk_size;
|
uint16_t first_chunk_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Current write offset within the active chunk
|
||||||
|
* Valid range: [0 .. chunk_size-1]
|
||||||
|
*/
|
||||||
uint16_t current_chunk_offset;
|
uint16_t current_chunk_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Chunk ID of the first chunk in the command buffer
|
||||||
|
* Valid range: Valid chunk ID from pool allocation
|
||||||
|
*/
|
||||||
uint32_t first_chunk_id;
|
uint32_t first_chunk_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Chunk ID of the currently active chunk being written
|
||||||
|
* Valid range: Valid chunk ID from pool allocation
|
||||||
|
*/
|
||||||
uint32_t current_chunk_id;
|
uint32_t current_chunk_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the chunk pool for automatic allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *pool;
|
struct pva_kmd_cmdbuf_chunk_pool *pool;
|
||||||
uint16_t *chunk_size_ptr; /**< Pointer to the chunk size field of the previous link_chunk command */
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to chunk size field of the previous link_chunk command
|
||||||
|
*
|
||||||
|
* @details Pointer to the chunk size field of the previous link_chunk command
|
||||||
|
*/
|
||||||
|
uint16_t *chunk_size_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a command buffer builder with the specified chunk pool
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the builder structure with the provided chunk pool
|
||||||
|
* - Allocates the first chunk from the pool for command buffer construction
|
||||||
|
* - Sets up internal state for tracking chunk usage and linking
|
||||||
|
* - Prepares the builder for command addition through @ref pva_kmd_reserve_cmd_space()
|
||||||
|
* - Configures chunk linking and boundary management
|
||||||
|
* - Establishes the foundation for multi-chunk command buffer construction
|
||||||
|
*
|
||||||
|
* The initialized builder can be used to construct command buffers by
|
||||||
|
* reserving space for commands and writing command data. The builder
|
||||||
|
* automatically handles chunk allocation and linking as needed.
|
||||||
|
*
|
||||||
|
* @param[out] builder Pointer to @ref pva_kmd_cmdbuf_builder structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] chunk_pool Pointer to @ref pva_kmd_cmdbuf_chunk_pool for chunk allocation
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Builder initialized successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate initial chunk from pool
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_cmdbuf_builder_init(struct pva_kmd_cmdbuf_builder *builder,
|
pva_kmd_cmdbuf_builder_init(struct pva_kmd_cmdbuf_builder *builder,
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool);
|
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reserve space in the command buffer for writing command data
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Checks if the current chunk has sufficient space for the requested size
|
||||||
|
* - Allocates a new chunk and links it if the current chunk is insufficient
|
||||||
|
* - Updates chunk linking commands to maintain proper command buffer structure
|
||||||
|
* - Returns a pointer to the reserved memory space for command writing
|
||||||
|
* - Advances internal tracking to account for the reserved space
|
||||||
|
* - Handles chunk boundaries transparently for the caller
|
||||||
|
*
|
||||||
|
* The returned pointer can be used to write command data directly. The
|
||||||
|
* space remains reserved until the next call to this function or until
|
||||||
|
* the builder is finalized or cancelled.
|
||||||
|
*
|
||||||
|
* @param[in, out] builder Pointer to @ref pva_kmd_cmdbuf_builder structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] size Number of bytes to reserve for command data
|
||||||
|
* Valid range: [1 .. chunk_size]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to reserved memory space for command writing
|
||||||
|
* @retval NULL Failed to allocate new chunk or insufficient space
|
||||||
|
*/
|
||||||
void *pva_kmd_reserve_cmd_space(struct pva_kmd_cmdbuf_builder *builder,
|
void *pva_kmd_reserve_cmd_space(struct pva_kmd_cmdbuf_builder *builder,
|
||||||
uint16_t size);
|
uint16_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finalize command buffer construction and get submission parameters
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Completes the command buffer construction process
|
||||||
|
* - Updates the final chunk size for the last chunk used
|
||||||
|
* - Prepares the command buffer for submission to the firmware
|
||||||
|
* - Returns the first chunk ID and size for submission setup
|
||||||
|
* - Ensures proper command buffer termination and linking
|
||||||
|
* - Transfers ownership of chunks from builder to submission system
|
||||||
|
*
|
||||||
|
* After finalization, the builder should not be used for further command
|
||||||
|
* construction. The returned chunk ID and size should be used for command
|
||||||
|
* buffer submission through the queue system.
|
||||||
|
*
|
||||||
|
* @param[in, out] builder Pointer to @ref pva_kmd_cmdbuf_builder structure
|
||||||
|
* Valid value: non-null, must be initialized with commands
|
||||||
|
* @param[out] out_first_chunk_id Pointer to store the first chunk ID
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] out_first_chunk_size Pointer to store the first chunk size
|
||||||
|
* Valid value: non-null
|
||||||
|
*/
|
||||||
void pva_kmd_cmdbuf_builder_finalize(struct pva_kmd_cmdbuf_builder *builder,
|
void pva_kmd_cmdbuf_builder_finalize(struct pva_kmd_cmdbuf_builder *builder,
|
||||||
uint32_t *out_first_chunk_id,
|
uint32_t *out_first_chunk_id,
|
||||||
uint16_t *out_first_chunk_size);
|
uint16_t *out_first_chunk_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cancel command buffer construction and free allocated chunks
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Cancels the command buffer construction process
|
||||||
|
* - Frees all chunks allocated by the builder back to the pool
|
||||||
|
* - Cleans up internal builder state and chunk linking
|
||||||
|
* - Ensures no memory leaks from partially constructed command buffers
|
||||||
|
* - Invalidates the builder for future use without reinitialization
|
||||||
|
*
|
||||||
|
* This function should be called when command buffer construction fails
|
||||||
|
* or is cancelled before completion. It ensures proper cleanup of all
|
||||||
|
* resources allocated during the construction process.
|
||||||
|
*
|
||||||
|
* @param[in, out] builder Pointer to @ref pva_kmd_cmdbuf_builder structure to cancel
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_cmdbuf_builder_cancel(struct pva_kmd_cmdbuf_builder *builder);
|
void pva_kmd_cmdbuf_builder_cancel(struct pva_kmd_cmdbuf_builder *builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a resource table initialization command
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes all fields of the command structure to appropriate values
|
||||||
|
* - Sets the command opcode to @ref PVA_CMD_OPCODE_INIT_RESOURCE_TABLE
|
||||||
|
* - Configures the resource table address using IOVA low and high parts
|
||||||
|
* - Sets the maximum number of entries supported by the resource table
|
||||||
|
* - Calculates and sets the command length based on structure size
|
||||||
|
* - Prepares the command for submission to firmware
|
||||||
|
*
|
||||||
|
* This inline function provides a convenient way to construct resource table
|
||||||
|
* initialization commands with proper field setup and validation. The
|
||||||
|
* command instructs firmware to initialize its resource table handling
|
||||||
|
* for the specified resource table.
|
||||||
|
*
|
||||||
|
* @param[out] cmd Pointer to @ref pva_cmd_init_resource_table command structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] resource_table_id Resource table identifier
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_KMD_RESOURCES-1]
|
||||||
|
* @param[in] iova_addr IOVA address of the resource table
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
* @param[in] max_num_entries Maximum number of entries in the resource table
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
static inline void pva_kmd_set_cmd_init_resource_table(
|
static inline void pva_kmd_set_cmd_init_resource_table(
|
||||||
struct pva_cmd_init_resource_table *cmd, uint8_t resource_table_id,
|
struct pva_cmd_init_resource_table *cmd, uint8_t resource_table_id,
|
||||||
uint64_t iova_addr, uint32_t max_num_entries)
|
uint64_t iova_addr, uint32_t max_num_entries, uint64_t ctx_status_addr)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_INIT_RESOURCE_TABLE;
|
cmd->header.opcode = PVA_CMD_OPCODE_INIT_RESOURCE_TABLE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->resource_table_id = resource_table_id;
|
cmd->resource_table_id = resource_table_id;
|
||||||
cmd->resource_table_addr_lo = iova_lo(iova_addr);
|
cmd->resource_table_addr_lo = iova_lo(iova_addr);
|
||||||
cmd->resource_table_addr_hi = iova_hi(iova_addr);
|
cmd->resource_table_addr_hi = iova_hi(iova_addr);
|
||||||
cmd->max_n_entries = max_num_entries;
|
cmd->max_n_entries = max_num_entries;
|
||||||
|
cmd->ctx_status_addr_lo = iova_lo(ctx_status_addr);
|
||||||
|
cmd->ctx_status_addr_hi = iova_hi(ctx_status_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
pva_kmd_set_cmd_deinit_resource_table(struct pva_cmd_deinit_resource_table *cmd,
|
pva_kmd_set_cmd_deinit_resource_table(struct pva_cmd_deinit_resource_table *cmd,
|
||||||
uint8_t resource_table_id)
|
uint8_t resource_table_id)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_RESOURCE_TABLE;
|
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_RESOURCE_TABLE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->resource_table_id = resource_table_id;
|
cmd->resource_table_id = resource_table_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,9 +512,9 @@ static inline void pva_kmd_set_cmd_init_queue(struct pva_cmd_init_queue *cmd,
|
|||||||
uint32_t syncpt_id,
|
uint32_t syncpt_id,
|
||||||
uint64_t syncpt_addr)
|
uint64_t syncpt_addr)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_INIT_QUEUE;
|
cmd->header.opcode = PVA_CMD_OPCODE_INIT_QUEUE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->ccq_id = ccq_id;
|
cmd->ccq_id = ccq_id;
|
||||||
cmd->queue_id = queue_id;
|
cmd->queue_id = queue_id;
|
||||||
cmd->queue_addr_lo = iova_lo(queue_addr);
|
cmd->queue_addr_lo = iova_lo(queue_addr);
|
||||||
@@ -186,9 +529,9 @@ static inline void
|
|||||||
pva_kmd_set_cmd_deinit_queue(struct pva_cmd_deinit_queue *cmd, uint8_t ccq_id,
|
pva_kmd_set_cmd_deinit_queue(struct pva_cmd_deinit_queue *cmd, uint8_t ccq_id,
|
||||||
uint8_t queue_id)
|
uint8_t queue_id)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_QUEUE;
|
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_QUEUE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->ccq_id = ccq_id;
|
cmd->ccq_id = ccq_id;
|
||||||
cmd->queue_id = queue_id;
|
cmd->queue_id = queue_id;
|
||||||
}
|
}
|
||||||
@@ -198,13 +541,15 @@ static inline void pva_kmd_set_cmd_update_resource_table(
|
|||||||
uint32_t resource_id, struct pva_resource_entry const *entry,
|
uint32_t resource_id, struct pva_resource_entry const *entry,
|
||||||
struct pva_resource_aux_info const *aux_info)
|
struct pva_resource_aux_info const *aux_info)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_UPDATE_RESOURCE_TABLE;
|
cmd->header.opcode = PVA_CMD_OPCODE_UPDATE_RESOURCE_TABLE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->resource_table_id = resource_table_id;
|
/* resource_table_id field is uint8_t - bounded by CCQ ID (max 7) */
|
||||||
|
ASSERT(resource_table_id <= (uint32_t)U8_MAX);
|
||||||
|
cmd->resource_table_id = (uint8_t)resource_table_id;
|
||||||
cmd->resource_id = resource_id;
|
cmd->resource_id = resource_id;
|
||||||
cmd->entry = *entry;
|
cmd->entry = *entry;
|
||||||
if (aux_info) {
|
if (aux_info != NULL) {
|
||||||
cmd->aux_info = *aux_info;
|
cmd->aux_info = *aux_info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,9 +558,9 @@ static inline void
|
|||||||
pva_kmd_set_cmd_unregister_resource(struct pva_cmd_unregister_resource *cmd,
|
pva_kmd_set_cmd_unregister_resource(struct pva_cmd_unregister_resource *cmd,
|
||||||
uint32_t resource_id)
|
uint32_t resource_id)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_UNREGISTER_RESOURCE;
|
cmd->header.opcode = PVA_CMD_OPCODE_UNREGISTER_RESOURCE;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->resource_id = resource_id;
|
cmd->resource_id = resource_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +568,9 @@ static inline void
|
|||||||
pva_kmd_set_cmd_enable_fw_profiling(struct pva_cmd_enable_fw_profiling *cmd,
|
pva_kmd_set_cmd_enable_fw_profiling(struct pva_cmd_enable_fw_profiling *cmd,
|
||||||
uint32_t filter, uint8_t timestamp_type)
|
uint32_t filter, uint8_t timestamp_type)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_ENABLE_FW_PROFILING;
|
cmd->header.opcode = PVA_CMD_OPCODE_ENABLE_FW_PROFILING;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->filter = filter;
|
cmd->filter = filter;
|
||||||
cmd->timestamp_type = timestamp_type;
|
cmd->timestamp_type = timestamp_type;
|
||||||
}
|
}
|
||||||
@@ -233,18 +578,18 @@ pva_kmd_set_cmd_enable_fw_profiling(struct pva_cmd_enable_fw_profiling *cmd,
|
|||||||
static inline void
|
static inline void
|
||||||
pva_kmd_set_cmd_disable_fw_profiling(struct pva_cmd_disable_fw_profiling *cmd)
|
pva_kmd_set_cmd_disable_fw_profiling(struct pva_cmd_disable_fw_profiling *cmd)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_DISABLE_FW_PROFILING;
|
cmd->header.opcode = PVA_CMD_OPCODE_DISABLE_FW_PROFILING;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_get_tegra_stats(
|
static inline void pva_kmd_set_cmd_get_tegra_stats(
|
||||||
struct pva_cmd_get_tegra_stats *cmd, uint32_t buffer_resource_id,
|
struct pva_cmd_get_tegra_stats *cmd, uint32_t buffer_resource_id,
|
||||||
uint32_t buffer_size, uint64_t offset, bool enabled)
|
uint32_t buffer_size, uint64_t offset, bool enabled)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_GET_TEGRA_STATS;
|
cmd->header.opcode = PVA_CMD_OPCODE_GET_TEGRA_STATS;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->buffer_resource_id = buffer_resource_id;
|
cmd->buffer_resource_id = buffer_resource_id;
|
||||||
cmd->buffer_offset_hi = iova_hi(offset);
|
cmd->buffer_offset_hi = iova_hi(offset);
|
||||||
cmd->buffer_offset_lo = iova_lo(offset);
|
cmd->buffer_offset_lo = iova_lo(offset);
|
||||||
@@ -256,45 +601,47 @@ static inline void
|
|||||||
pva_kmd_set_cmd_set_trace_level(struct pva_cmd_set_trace_level *cmd,
|
pva_kmd_set_cmd_set_trace_level(struct pva_cmd_set_trace_level *cmd,
|
||||||
uint32_t trace_level)
|
uint32_t trace_level)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_SET_TRACE_LEVEL;
|
cmd->header.opcode = PVA_CMD_OPCODE_SET_TRACE_LEVEL;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->trace_level = trace_level;
|
cmd->trace_level = trace_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_suspend_fw(struct pva_cmd_suspend_fw *cmd)
|
static inline void pva_kmd_set_cmd_suspend_fw(struct pva_cmd_suspend_fw *cmd)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_SUSPEND_FW;
|
cmd->header.opcode = PVA_CMD_OPCODE_SUSPEND_FW;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_resume_fw(struct pva_cmd_resume_fw *cmd)
|
static inline void pva_kmd_set_cmd_resume_fw(struct pva_cmd_resume_fw *cmd)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_RESUME_FW;
|
cmd->header.opcode = PVA_CMD_OPCODE_RESUME_FW;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_init_shared_dram_buffer(
|
static inline void pva_kmd_set_cmd_init_shared_dram_buffer(
|
||||||
struct pva_cmd_init_shared_dram_buffer *cmd, uint8_t interface,
|
struct pva_cmd_init_shared_dram_buffer *cmd, uint8_t interface,
|
||||||
uint32_t buffer_iova, uint32_t buffer_size)
|
uint64_t buffer_iova, uint64_t buffer_size)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_INIT_SHARED_DRAM_BUFFER;
|
cmd->header.opcode = PVA_CMD_OPCODE_INIT_SHARED_DRAM_BUFFER;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->buffer_iova_hi = iova_hi(buffer_iova);
|
cmd->buffer_iova_hi = iova_hi(buffer_iova);
|
||||||
cmd->buffer_iova_lo = iova_lo(buffer_iova);
|
cmd->buffer_iova_lo = iova_lo(buffer_iova);
|
||||||
cmd->buffer_size = buffer_size;
|
/* CERT INT31-C: Hardware constrains buffer sizes to 32-bit address space */
|
||||||
|
ASSERT(buffer_size <= U32_MAX);
|
||||||
|
cmd->buffer_size = (uint32_t)buffer_size;
|
||||||
cmd->interface = interface;
|
cmd->interface = interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_deinit_shared_dram_buffer(
|
static inline void pva_kmd_set_cmd_deinit_shared_dram_buffer(
|
||||||
struct pva_cmd_deinit_shared_dram_buffer *cmd, uint8_t interface)
|
struct pva_cmd_deinit_shared_dram_buffer *cmd, uint8_t interface)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_SHARED_DRAM_BUFFER;
|
cmd->header.opcode = PVA_CMD_OPCODE_DEINIT_SHARED_DRAM_BUFFER;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->interface = interface;
|
cmd->interface = interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,22 +649,31 @@ static inline void
|
|||||||
pva_kmd_set_cmd_set_profiling_level(struct pva_cmd_set_profiling_level *cmd,
|
pva_kmd_set_cmd_set_profiling_level(struct pva_cmd_set_profiling_level *cmd,
|
||||||
uint32_t level)
|
uint32_t level)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_SET_PROFILING_LEVEL;
|
cmd->header.opcode = PVA_CMD_OPCODE_SET_PROFILING_LEVEL;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->level = level;
|
cmd->level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pva_kmd_set_cmd_get_version(struct pva_cmd_get_version *cmd,
|
static inline void pva_kmd_set_cmd_get_version(struct pva_cmd_get_version *cmd,
|
||||||
uint64_t buffer_iova)
|
uint64_t buffer_iova)
|
||||||
{
|
{
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->header.opcode = PVA_CMD_OPCODE_GET_VERSION;
|
cmd->header.opcode = PVA_CMD_OPCODE_GET_VERSION;
|
||||||
cmd->header.len = sizeof(*cmd) / sizeof(uint32_t);
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
cmd->buffer_iova_hi = iova_hi(buffer_iova);
|
cmd->buffer_iova_hi = iova_hi(buffer_iova);
|
||||||
cmd->buffer_iova_lo = iova_lo(buffer_iova);
|
cmd->buffer_iova_lo = iova_lo(buffer_iova);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void pva_kmd_set_cmd_set_pfsd_cmd_buffer_size(
|
||||||
|
struct pva_cmd_set_pfsd_cmd_buffer_size *cmd, uint32_t cmd_buffer_size)
|
||||||
|
{
|
||||||
|
(void)memset(cmd, 0, sizeof(*cmd));
|
||||||
|
cmd->header.opcode = PVA_CMD_OPCODE_SET_PFSD_CMD_BUFFER_SIZE;
|
||||||
|
cmd->header.len = (uint8_t)(sizeof(*cmd) / sizeof(uint32_t));
|
||||||
|
cmd->cmd_buffer_size = cmd_buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
#define CMD_LEN(cmd_type) (sizeof(cmd_type) / sizeof(uint32_t))
|
#define CMD_LEN(cmd_type) (sizeof(cmd_type) / sizeof(uint32_t))
|
||||||
|
|
||||||
#endif // PVA_KMD_CMDBUF_H
|
#endif // PVA_KMD_CMDBUF_H
|
||||||
|
|||||||
@@ -4,9 +4,32 @@
|
|||||||
#ifndef PVA_KMD_CO_H
|
#ifndef PVA_KMD_CO_H
|
||||||
#define PVA_KMD_CO_H
|
#define PVA_KMD_CO_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute Object information structure
|
||||||
|
*
|
||||||
|
* @details This structure contains memory mapping information for a compute object,
|
||||||
|
* including both virtual and physical address mappings along with size information.
|
||||||
|
* Compute objects represent memory regions or buffers that are used for computation
|
||||||
|
* tasks on the PVA hardware, providing the necessary address translation information
|
||||||
|
* for both software and hardware access.
|
||||||
|
*/
|
||||||
struct pva_co_info {
|
struct pva_co_info {
|
||||||
|
/**
|
||||||
|
* @brief Virtual address base of the compute object
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t base_va;
|
uint64_t base_va;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Physical address base of the compute object
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t base_pa;
|
uint64_t base_pa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of the compute object in bytes
|
||||||
|
* Valid range: [1 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,56 +3,253 @@
|
|||||||
|
|
||||||
#ifndef PVA_KMD_CONSTANTS_H
|
#ifndef PVA_KMD_CONSTANTS_H
|
||||||
#define PVA_KMD_CONSTANTS_H
|
#define PVA_KMD_CONSTANTS_H
|
||||||
|
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
#include "pva_constants.h"
|
#include "pva_constants.h"
|
||||||
/* Limits related to KMD's own submission*/
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of resources that can be managed by KMD internally
|
||||||
|
*
|
||||||
|
* @details This constant defines the upper limit for the number of resources
|
||||||
|
* that the KMD can manage for its own internal operations. These resources
|
||||||
|
* include memory buffers, DMA configurations, and other hardware resources
|
||||||
|
* needed for KMD's privileged operations and communication with firmware.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_KMD_RESOURCES 32
|
#define PVA_KMD_MAX_NUM_KMD_RESOURCES 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of DMA configurations for KMD internal use
|
||||||
|
*
|
||||||
|
* @details This constant defines the maximum number of DMA configuration
|
||||||
|
* objects that the KMD can allocate and manage for its own internal DMA
|
||||||
|
* operations. These configurations are used for transferring data between
|
||||||
|
* system memory and PVA internal memory during KMD operations.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_KMD_DMA_CONFIGS 1
|
#define PVA_KMD_MAX_NUM_KMD_DMA_CONFIGS 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of command buffer chunks for KMD internal submissions
|
||||||
|
*
|
||||||
|
* @details This constant defines the upper limit for the number of command
|
||||||
|
* buffer chunks that the KMD can use for its own internal command submissions.
|
||||||
|
* These chunks are used to build command buffers for privileged operations
|
||||||
|
* such as resource management and device configuration.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_KMD_CHUNKS 32
|
#define PVA_KMD_MAX_NUM_KMD_CHUNKS 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of submissions that KMD can queue internally
|
||||||
|
*
|
||||||
|
* @details This constant defines the maximum number of command buffer
|
||||||
|
* submissions that the KMD can have queued for its own internal operations.
|
||||||
|
* This limits the depth of the internal submission queue to prevent
|
||||||
|
* unbounded resource usage during high-throughput scenarios.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_KMD_SUBMITS 32
|
#define PVA_KMD_MAX_NUM_KMD_SUBMITS 32
|
||||||
|
|
||||||
/* Limits related to User's privileged submission */
|
/**
|
||||||
|
* @brief Maximum number of command buffer chunks for user privileged submissions
|
||||||
|
*
|
||||||
|
* @details This constant defines the upper limit for the number of command
|
||||||
|
* buffer chunks that can be used for user-initiated privileged submissions.
|
||||||
|
* Privileged submissions are those that require elevated permissions and
|
||||||
|
* are processed through the KMD's privileged command path.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_PRIV_CHUNKS 256
|
#define PVA_KMD_MAX_NUM_PRIV_CHUNKS 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of privileged submissions that can be queued
|
||||||
|
*
|
||||||
|
* @details This constant defines the maximum number of privileged command
|
||||||
|
* buffer submissions that can be queued at any given time. This limit
|
||||||
|
* helps manage memory usage and ensures system stability under heavy
|
||||||
|
* privileged operation loads.
|
||||||
|
*/
|
||||||
#define PVA_KMD_MAX_NUM_PRIV_SUBMITS 256
|
#define PVA_KMD_MAX_NUM_PRIV_SUBMITS 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base context ID for user contexts
|
||||||
|
*
|
||||||
|
* @details This constant defines the starting context ID value for user
|
||||||
|
* contexts. Context ID 0 is typically reserved for privileged/system
|
||||||
|
* operations, so user contexts start from this base value. This ensures
|
||||||
|
* proper separation between system and user context namespaces.
|
||||||
|
*/
|
||||||
#define PVA_KMD_USER_CONTEXT_ID_BASE 1u
|
#define PVA_KMD_USER_CONTEXT_ID_BASE 1u
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Physical register base address for PVA0 on T23x silicon
|
||||||
|
*
|
||||||
|
* @details This constant defines the physical memory address where the
|
||||||
|
* PVA0 device registers are mapped on T23x (Tegra23x) silicon platforms.
|
||||||
|
* This address is used for register access and memory mapping operations
|
||||||
|
* specific to the first PVA instance on T23x hardware.
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_T23x_REG_BASE 0x16000000
|
#define PVA_KMD_PVA0_T23x_REG_BASE 0x16000000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of PVA0 register space on T23x silicon
|
||||||
|
*
|
||||||
|
* @details This constant defines the total size in bytes of the PVA0
|
||||||
|
* register address space on T23x (Tegra23x) silicon platforms. This
|
||||||
|
* size covers all register apertures and memory-mapped regions needed
|
||||||
|
* for complete PVA0 device control and operation.
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_T23x_REG_SIZE 0x800000
|
#define PVA_KMD_PVA0_T23x_REG_SIZE 0x800000
|
||||||
|
|
||||||
#define PVA_KMD_TIMEOUT_INF UINT64_MAX
|
/**
|
||||||
|
* @brief Infinite timeout value for operations that should never timeout
|
||||||
|
*
|
||||||
|
* @details This constant represents an infinite timeout value, typically
|
||||||
|
* used for operations that must complete regardless of how long they take.
|
||||||
|
* Set to the maximum value of a 64-bit unsigned integer to effectively
|
||||||
|
* disable timeout checking for critical operations.
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_TIMEOUT_INF U64_MAX
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#if PVA_BUILD_MODE == PVA_BUILD_MODE_SIM
|
#if PVA_BUILD_MODE == PVA_BUILD_MODE_SIM
|
||||||
|
/**
|
||||||
|
* @brief Timeout scaling factor for simulation builds
|
||||||
|
*
|
||||||
|
* @details This constant provides a scaling factor applied to timeout
|
||||||
|
* values when running in simulation mode. Simulation environments
|
||||||
|
* typically run slower than real hardware, so timeouts are scaled up
|
||||||
|
* by this factor to prevent spurious timeout failures during testing.
|
||||||
|
*/
|
||||||
#define PVA_KMD_TIMEOUT_FACTOR 100
|
#define PVA_KMD_TIMEOUT_FACTOR 100
|
||||||
#elif (PVA_BUILD_MODE == PVA_BUILD_MODE_NATIVE)
|
#elif (PVA_BUILD_MODE == PVA_BUILD_MODE_NATIVE)
|
||||||
// On native builds, the FW calls the KMD's shared buffer handler in its
|
/**
|
||||||
// own thread. In debug builds, if there are a large number of messages
|
* @brief Timeout scaling factor for native builds
|
||||||
// (prints, unregister, etc.), this handler might take a while to execute,
|
*
|
||||||
// making the FW and delay the processing of command buffers. This could
|
* @details This constant provides a scaling factor applied to timeout
|
||||||
// lead to submission timeouts in KMD.
|
* values when running in native build mode. On native builds, the FW calls
|
||||||
|
* the KMD's shared buffer handler in its own thread. In debug builds, if
|
||||||
|
* there are a large number of messages (prints, unregister, etc.), this
|
||||||
|
* handler might take a while to execute, making the FW delay the processing
|
||||||
|
* of command buffers. This could lead to submission timeouts in KMD.
|
||||||
|
*/
|
||||||
#define PVA_KMD_TIMEOUT_FACTOR 10
|
#define PVA_KMD_TIMEOUT_FACTOR 10
|
||||||
#else
|
#else
|
||||||
|
/**
|
||||||
|
* @brief Default timeout scaling factor for silicon builds
|
||||||
|
*
|
||||||
|
* @details This constant provides the default scaling factor applied to
|
||||||
|
* timeout values when running on actual silicon hardware. No scaling
|
||||||
|
* is applied (factor of 1) as silicon hardware runs at expected speeds
|
||||||
|
* and timeout values are calibrated for real hardware performance.
|
||||||
|
*/
|
||||||
#define PVA_KMD_TIMEOUT_FACTOR 1
|
#define PVA_KMD_TIMEOUT_FACTOR 1
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define PVA_KMD_TIMEOUT(val) (val * PVA_KMD_TIMEOUT_FACTOR)
|
/**
|
||||||
|
* @brief Macro to apply platform-specific timeout scaling
|
||||||
|
*
|
||||||
|
* @details This macro applies the appropriate timeout scaling factor based
|
||||||
|
* on the build mode. It multiplies the provided timeout value by the
|
||||||
|
* platform-specific timeout factor to account for different execution
|
||||||
|
* speeds in simulation, native, and silicon environments.
|
||||||
|
*
|
||||||
|
* @param val Base timeout value before scaling
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_TIMEOUT(val) ((val)*PVA_KMD_TIMEOUT_FACTOR)
|
||||||
|
|
||||||
#define PVA_KMD_TIMEOUT_RESOURCE_SEMA_MS PVA_KMD_TIMEOUT(400) /*< 100 ms */
|
/**
|
||||||
#define PVA_KMD_WAIT_FW_TIMEOUT_US PVA_KMD_TIMEOUT(100000) /*< 100 ms */
|
* @brief Timeout for resource semaphore operations in milliseconds
|
||||||
|
*
|
||||||
|
* @details This constant defines the timeout value for acquiring resource
|
||||||
|
* semaphores in the KMD. Resource semaphores are used to coordinate access
|
||||||
|
* to shared resources between different contexts and operations. The timeout
|
||||||
|
* is scaled based on the build mode to account for platform differences.
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_TIMEOUT_RESOURCE_SEMA_MS PVA_KMD_TIMEOUT(400)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timeout for waiting on firmware responses in microseconds
|
||||||
|
*
|
||||||
|
* @details This constant defines the timeout value for operations that
|
||||||
|
* wait for firmware responses or completion signals. This timeout ensures
|
||||||
|
* that the KMD doesn't wait indefinitely for firmware operations that
|
||||||
|
* may have failed or stalled. The timeout is scaled for platform differences.
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_WAIT_FW_TIMEOUT_US PVA_KMD_TIMEOUT(100000)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Additional scaling factor for firmware timeouts in simulation
|
||||||
|
*
|
||||||
|
* @details This constant provides an additional scaling factor specifically
|
||||||
|
* for firmware timeout operations when running in simulation mode. This
|
||||||
|
* extra scaling accounts for the significantly slower execution speed
|
||||||
|
* of firmware operations in simulation environments.
|
||||||
|
*/
|
||||||
#define PVA_KMD_WAIT_FW_TIMEOUT_SCALER_SIM 100
|
#define PVA_KMD_WAIT_FW_TIMEOUT_SCALER_SIM 100
|
||||||
#define PVA_KMD_WAIT_FW_POLL_INTERVAL_US PVA_KMD_TIMEOUT(100) /*< 100 us*/
|
|
||||||
#define PVA_KMD_FW_BOOT_TIMEOUT_MS PVA_KMD_TIMEOUT(1000) /*< 1 seconds */
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Polling interval for firmware status checks in microseconds
|
||||||
|
*
|
||||||
|
* @details This constant defines the interval between polling operations
|
||||||
|
* when waiting for firmware status changes or responses. The polling
|
||||||
|
* interval balances responsiveness with CPU usage - too frequent polling
|
||||||
|
* wastes CPU cycles, while too infrequent polling increases response latency.
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_WAIT_FW_POLL_INTERVAL_US PVA_KMD_TIMEOUT(100)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timeout for firmware boot completion in milliseconds
|
||||||
|
*
|
||||||
|
* @details This constant defines the maximum time to wait for firmware
|
||||||
|
* boot completion during device initialization. If the firmware doesn't
|
||||||
|
* complete its boot sequence within this timeout, the initialization
|
||||||
|
* is considered failed. The timeout is scaled for platform differences.
|
||||||
|
*/
|
||||||
|
#define PVA_KMD_FW_BOOT_TIMEOUT_MS PVA_KMD_TIMEOUT(1000)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Total number of read-write syncpoints available across all contexts
|
||||||
|
*
|
||||||
|
* @details This constant calculates the total number of read-write syncpoints
|
||||||
|
* available in the system by multiplying the maximum number of CCQs by the
|
||||||
|
* number of read-write syncpoints per context. This provides the total pool
|
||||||
|
* of syncpoints that can be allocated for user operations requiring both
|
||||||
|
* read and write access to syncpoint values.
|
||||||
|
*/
|
||||||
#define PVA_NUM_RW_SYNCPTS (PVA_MAX_NUM_CCQ * PVA_NUM_RW_SYNCPTS_PER_CONTEXT)
|
#define PVA_NUM_RW_SYNCPTS (PVA_MAX_NUM_CCQ * PVA_NUM_RW_SYNCPTS_PER_CONTEXT)
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#if PVA_DEV_MAIN_COMPATIBLE == 1
|
#if PVA_DEV_MAIN_COMPATIBLE == 1
|
||||||
|
/**
|
||||||
|
* @brief Default setting for loading firmware from GSC in main-compatible builds
|
||||||
|
*
|
||||||
|
* @details This constant defines the default behavior for firmware loading
|
||||||
|
* from GSC (Generic Security Controller) in builds that are compatible with
|
||||||
|
* the main development branch. When true, firmware will be loaded through
|
||||||
|
* the GSC secure path by default, providing enhanced security for production
|
||||||
|
* environments.
|
||||||
|
*/
|
||||||
#define PVA_KMD_LOAD_FROM_GSC_DEFAULT true
|
#define PVA_KMD_LOAD_FROM_GSC_DEFAULT true
|
||||||
#else
|
#else
|
||||||
|
/**
|
||||||
|
* @brief Default setting for loading firmware from GSC in non-main-compatible builds
|
||||||
|
*
|
||||||
|
* @details This constant defines the default behavior for firmware loading
|
||||||
|
* from GSC (Generic Security Controller) in development or testing builds
|
||||||
|
* that are not main-compatible. When false, firmware will be loaded through
|
||||||
|
* conventional paths, which may be more suitable for development and debugging.
|
||||||
|
*/
|
||||||
#define PVA_KMD_LOAD_FROM_GSC_DEFAULT false
|
#define PVA_KMD_LOAD_FROM_GSC_DEFAULT false
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increment size for DMA configuration pool expansion
|
||||||
|
*
|
||||||
|
* @details This constant defines the number of DMA configuration entries
|
||||||
|
* to allocate when expanding the DMA configuration pool. When the pool
|
||||||
|
* becomes full and needs to grow, it will be expanded by this many entries
|
||||||
|
* to provide room for additional DMA configurations while minimizing
|
||||||
|
* the frequency of pool expansion operations.
|
||||||
|
*/
|
||||||
#define PVA_KMD_DMA_CONFIG_POOL_INCR 256
|
#define PVA_KMD_DMA_CONFIG_POOL_INCR 256
|
||||||
|
|
||||||
#endif // PVA_KMD_CONSTANTS_H
|
#endif // PVA_KMD_CONSTANTS_H
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_kmd_device_memory.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_constants.h"
|
#include "pva_constants.h"
|
||||||
#include "pva_api_cmdbuf.h"
|
#include "pva_api_cmdbuf.h"
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include "pva_kmd_context.h"
|
#include "pva_kmd_context.h"
|
||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
#include "pva_kmd_msg.h"
|
#include "pva_kmd_msg.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
struct pva_kmd_context *pva_kmd_context_create(struct pva_kmd_device *pva)
|
struct pva_kmd_context *pva_kmd_context_create(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
@@ -21,28 +23,33 @@ struct pva_kmd_context *pva_kmd_context_create(struct pva_kmd_device *pva)
|
|||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"pva_kmd_context_create pva_kmd_context block alloc failed");
|
"pva_kmd_context_create pva_kmd_context block alloc failed");
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
ctx->ccq_id = alloc_id;
|
/* alloc_id bounded by PVA_MAX_NUM_USER_CONTEXTS (7) from allocator */
|
||||||
|
/* MISRA 10.4: alloc_id is unsigned, only check upper bound */
|
||||||
|
ASSERT(alloc_id <= (uint32_t)U8_MAX);
|
||||||
|
ctx->ccq_id = (uint8_t)alloc_id;
|
||||||
ctx->resource_table_id = ctx->ccq_id;
|
ctx->resource_table_id = ctx->ccq_id;
|
||||||
ctx->smmu_ctx_id = ctx->ccq_id;
|
ctx->smmu_ctx_id = ctx->ccq_id;
|
||||||
ctx->pva = pva;
|
ctx->pva = pva;
|
||||||
ctx->max_n_queues = PVA_MAX_NUM_QUEUES_PER_CONTEXT;
|
ctx->max_n_queues = PVA_MAX_NUM_QUEUES_PER_CONTEXT;
|
||||||
pva_kmd_mutex_init(&ctx->ocb_lock);
|
err = pva_kmd_mutex_init(&ctx->ocb_lock);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("pva_kmd_context_create mutex_init failed");
|
||||||
|
goto free_ctx;
|
||||||
|
}
|
||||||
ctx->queue_allocator_mem = pva_kmd_zalloc(sizeof(struct pva_kmd_queue) *
|
ctx->queue_allocator_mem = pva_kmd_zalloc(sizeof(struct pva_kmd_queue) *
|
||||||
ctx->max_n_queues);
|
ctx->max_n_queues);
|
||||||
if (ctx->queue_allocator_mem == NULL) {
|
if (ctx->queue_allocator_mem == NULL) {
|
||||||
err = PVA_NOMEM;
|
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"pva_kmd_context_create queue_allocator_mem NULL");
|
"pva_kmd_context_create queue_allocator_mem NULL");
|
||||||
goto free_ctx;
|
goto free_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_block_allocator_init(&ctx->queue_allocator,
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
ctx->queue_allocator_mem, 0,
|
err = pva_kmd_block_allocator_init(
|
||||||
sizeof(struct pva_kmd_queue),
|
&ctx->queue_allocator, ctx->queue_allocator_mem, 0,
|
||||||
ctx->max_n_queues);
|
(uint32_t)sizeof(struct pva_kmd_queue), ctx->max_n_queues);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"pva_kmd_context_create block allocator init failed");
|
"pva_kmd_context_create block allocator init failed");
|
||||||
@@ -63,12 +70,93 @@ free_queue_mem:
|
|||||||
pva_kmd_free(ctx->queue_allocator_mem);
|
pva_kmd_free(ctx->queue_allocator_mem);
|
||||||
free_ctx:
|
free_ctx:
|
||||||
pva_kmd_mutex_deinit(&ctx->ocb_lock);
|
pva_kmd_mutex_deinit(&ctx->ocb_lock);
|
||||||
pva_kmd_free_block(&pva->context_allocator, alloc_id);
|
err = pva_kmd_free_block(&pva->context_allocator, alloc_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to free context block");
|
||||||
|
}
|
||||||
err_out:
|
err_out:
|
||||||
pva_kmd_log_err("Failed to create PVA context");
|
pva_kmd_log_err("Failed to create PVA context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum pva_error setup_status_memory(struct pva_kmd_context *ctx,
|
||||||
|
uint64_t status_shm_hdl)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
ctx->status_mem = pva_kmd_device_memory_acquire(
|
||||||
|
status_shm_hdl, 0, sizeof(struct pva_fw_async_error), ctx);
|
||||||
|
if (ctx->status_mem == NULL) {
|
||||||
|
pva_kmd_log_err("Failed to acquire context status memory");
|
||||||
|
err = PVA_INTERNAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_device_memory_iova_map(ctx->status_mem, ctx->pva,
|
||||||
|
PVA_ACCESS_RW,
|
||||||
|
PVA_R5_SMMU_CONTEXT_ID);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to map context status memory");
|
||||||
|
pva_kmd_device_memory_free(ctx->status_mem);
|
||||||
|
ctx->status_mem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
setup_submit_memory_and_chunk_pool(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
uint64_t chunk_mem_size;
|
||||||
|
uint64_t size;
|
||||||
|
|
||||||
|
/* Allocate memory for submission */
|
||||||
|
chunk_mem_size = pva_kmd_cmdbuf_pool_get_required_mem_size(
|
||||||
|
pva_kmd_get_max_cmdbuf_chunk_size(ctx->pva),
|
||||||
|
PVA_KMD_MAX_NUM_PRIV_CHUNKS);
|
||||||
|
/* Allocate one post fence at the end. This memory will be added to
|
||||||
|
* KMD's own resource table. We don't need to explicitly free it. It
|
||||||
|
* will be freed after we drop the resource. */
|
||||||
|
size = safe_addu64(chunk_mem_size, (uint64_t)sizeof(uint32_t));
|
||||||
|
ctx->submit_memory = pva_kmd_device_memory_alloc_map(
|
||||||
|
size, ctx->pva, PVA_ACCESS_RW, PVA_R5_SMMU_CONTEXT_ID);
|
||||||
|
if (ctx->submit_memory == NULL) {
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add submit memory to resource table */
|
||||||
|
err = pva_kmd_add_dram_buffer_resource(&ctx->pva->dev_resource_table,
|
||||||
|
ctx->submit_memory,
|
||||||
|
&ctx->submit_memory_resource_id,
|
||||||
|
false);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
// Ownership of submit memory is transferred to KMD's resource table so
|
||||||
|
// if adding to resource table fails, we need to free it here.
|
||||||
|
pva_kmd_device_memory_free(ctx->submit_memory);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init chunk pool */
|
||||||
|
err = pva_kmd_cmdbuf_chunk_pool_init(
|
||||||
|
&ctx->chunk_pool, ctx->submit_memory_resource_id,
|
||||||
|
0 /* offset */, (uint32_t)chunk_mem_size,
|
||||||
|
pva_kmd_get_max_cmdbuf_chunk_size(ctx->pva),
|
||||||
|
PVA_KMD_MAX_NUM_PRIV_CHUNKS, ctx->submit_memory->va);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_drop_resource(&ctx->pva->dev_resource_table,
|
||||||
|
ctx->submit_memory_resource_id);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init fence */
|
||||||
|
ctx->fence_offset = chunk_mem_size;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static enum pva_error notify_fw_context_init(struct pva_kmd_context *ctx)
|
static enum pva_error notify_fw_context_init(struct pva_kmd_context *ctx)
|
||||||
{
|
{
|
||||||
struct pva_kmd_submitter *dev_submitter = &ctx->pva->submitter;
|
struct pva_kmd_submitter *dev_submitter = &ctx->pva->submitter;
|
||||||
@@ -81,24 +169,26 @@ static enum pva_error notify_fw_context_init(struct pva_kmd_context *ctx)
|
|||||||
uint32_t current_offset = 0;
|
uint32_t current_offset = 0;
|
||||||
uint32_t cmd_scratch[CMD_LEN(struct pva_cmd_init_resource_table) +
|
uint32_t cmd_scratch[CMD_LEN(struct pva_cmd_init_resource_table) +
|
||||||
CMD_LEN(struct pva_cmd_init_queue) +
|
CMD_LEN(struct pva_cmd_init_queue) +
|
||||||
CMD_LEN(struct pva_cmd_update_resource_table)];
|
CMD_LEN(struct pva_cmd_update_resource_table)] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
res_cmd = (struct pva_cmd_init_resource_table *)pva_offset_pointer(
|
res_cmd = (struct pva_cmd_init_resource_table *)pva_offset_pointer(
|
||||||
&cmd_scratch[0], current_offset);
|
&cmd_scratch[0], current_offset);
|
||||||
current_offset += sizeof(*res_cmd);
|
current_offset += (uint32_t)sizeof(*res_cmd);
|
||||||
|
|
||||||
queue_cmd = (struct pva_cmd_init_queue *)pva_offset_pointer(
|
queue_cmd = (struct pva_cmd_init_queue *)pva_offset_pointer(
|
||||||
&cmd_scratch[0], current_offset);
|
&cmd_scratch[0], current_offset);
|
||||||
current_offset += sizeof(*queue_cmd);
|
current_offset += (uint32_t)sizeof(*queue_cmd);
|
||||||
|
|
||||||
update_cmd = (struct pva_cmd_update_resource_table *)pva_offset_pointer(
|
update_cmd = (struct pva_cmd_update_resource_table *)pva_offset_pointer(
|
||||||
&cmd_scratch[0], current_offset);
|
&cmd_scratch[0], current_offset);
|
||||||
current_offset += sizeof(*update_cmd);
|
current_offset += (uint32_t)sizeof(*update_cmd);
|
||||||
|
|
||||||
pva_kmd_set_cmd_init_resource_table(
|
pva_kmd_set_cmd_init_resource_table(
|
||||||
res_cmd, ctx->resource_table_id,
|
res_cmd, ctx->resource_table_id,
|
||||||
ctx->ctx_resource_table.table_mem->iova,
|
ctx->ctx_resource_table.table_mem->iova,
|
||||||
ctx->ctx_resource_table.n_entries);
|
ctx->ctx_resource_table.n_entries, ctx->status_mem->iova);
|
||||||
|
|
||||||
syncpt_info = pva_kmd_queue_get_rw_syncpt_info(
|
syncpt_info = pva_kmd_queue_get_rw_syncpt_info(
|
||||||
ctx->pva, PVA_PRIV_CCQ_ID, ctx->ccq_id);
|
ctx->pva, PVA_PRIV_CCQ_ID, ctx->ccq_id);
|
||||||
@@ -119,9 +209,13 @@ static enum pva_error notify_fw_context_init(struct pva_kmd_context *ctx)
|
|||||||
&entry, NULL);
|
&entry, NULL);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(dev_submitter, cmd_scratch,
|
err = pva_kmd_submit_cmd_sync(dev_submitter, cmd_scratch,
|
||||||
sizeof(cmd_scratch),
|
(uint32_t)sizeof(cmd_scratch),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to submit command for context init notify");
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +225,9 @@ static enum pva_error notify_fw_context_deinit(struct pva_kmd_context *ctx)
|
|||||||
struct pva_cmd_deinit_resource_table *deinit_table_cmd;
|
struct pva_cmd_deinit_resource_table *deinit_table_cmd;
|
||||||
struct pva_cmd_deinit_queue *deinit_queue_cmd;
|
struct pva_cmd_deinit_queue *deinit_queue_cmd;
|
||||||
uint32_t cmd_scratch[CMD_LEN(struct pva_cmd_deinit_queue) +
|
uint32_t cmd_scratch[CMD_LEN(struct pva_cmd_deinit_queue) +
|
||||||
CMD_LEN(struct pva_cmd_deinit_resource_table)];
|
CMD_LEN(struct pva_cmd_deinit_resource_table)] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
|
|
||||||
deinit_queue_cmd = (struct pva_cmd_deinit_queue *)pva_offset_pointer(
|
deinit_queue_cmd = (struct pva_cmd_deinit_queue *)pva_offset_pointer(
|
||||||
@@ -149,20 +245,23 @@ static enum pva_error notify_fw_context_deinit(struct pva_kmd_context *ctx)
|
|||||||
ctx->resource_table_id);
|
ctx->resource_table_id);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(dev_submitter, cmd_scratch,
|
err = pva_kmd_submit_cmd_sync(dev_submitter, cmd_scratch,
|
||||||
sizeof(cmd_scratch),
|
(uint32_t)sizeof(cmd_scratch),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to submit command for context deinit notify");
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
||||||
uint32_t res_table_capacity)
|
uint32_t res_table_capacity,
|
||||||
|
uint64_t status_shm_hdl)
|
||||||
{
|
{
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
uint32_t queue_mem_size;
|
uint32_t queue_mem_size;
|
||||||
uint64_t chunk_mem_size;
|
|
||||||
struct pva_fw_postfence post_fence = { 0 };
|
struct pva_fw_postfence post_fence = { 0 };
|
||||||
uint64_t size;
|
|
||||||
|
|
||||||
if (ctx->inited) {
|
if (ctx->inited) {
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
@@ -175,11 +274,16 @@ enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = setup_status_memory(ctx, status_shm_hdl);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Init resource table for this context */
|
/* Init resource table for this context */
|
||||||
err = pva_kmd_resource_table_init(&ctx->ctx_resource_table, ctx->pva,
|
err = pva_kmd_resource_table_init(&ctx->ctx_resource_table, ctx->pva,
|
||||||
ctx->smmu_ctx_id, res_table_capacity);
|
ctx->smmu_ctx_id, res_table_capacity);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto err_out;
|
goto unmap_status_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init privileged queue for this context */
|
/* Init privileged queue for this context */
|
||||||
@@ -199,48 +303,23 @@ enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
|||||||
ctx->ccq_id, /* Context's PRIV queue ID is identical to CCQ ID */
|
ctx->ccq_id, /* Context's PRIV queue ID is identical to CCQ ID */
|
||||||
ctx->ctx_queue_mem, PVA_KMD_MAX_NUM_PRIV_SUBMITS);
|
ctx->ctx_queue_mem, PVA_KMD_MAX_NUM_PRIV_SUBMITS);
|
||||||
|
|
||||||
/* Allocate memory for submission */
|
err = setup_submit_memory_and_chunk_pool(ctx);
|
||||||
chunk_mem_size = pva_kmd_cmdbuf_pool_get_required_mem_size(
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_get_max_cmdbuf_chunk_size(ctx->pva),
|
|
||||||
PVA_KMD_MAX_NUM_PRIV_CHUNKS);
|
|
||||||
/* Allocate one post fence at the end. This memory will be added to
|
|
||||||
* KMD's own resource table. We don't need to explicitly free it. It
|
|
||||||
* will be freed after we drop the resource. */
|
|
||||||
size = safe_addu64(chunk_mem_size, (uint64_t)sizeof(uint32_t));
|
|
||||||
ctx->submit_memory = pva_kmd_device_memory_alloc_map(
|
|
||||||
size, ctx->pva, PVA_ACCESS_RW, PVA_R5_SMMU_CONTEXT_ID);
|
|
||||||
if (ctx->submit_memory == NULL) {
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto queue_deinit;
|
goto queue_deinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add submit memory to resource table */
|
|
||||||
err = pva_kmd_add_dram_buffer_resource(&ctx->pva->dev_resource_table,
|
|
||||||
ctx->submit_memory,
|
|
||||||
&ctx->submit_memory_resource_id);
|
|
||||||
if (err != PVA_SUCCESS) {
|
|
||||||
// Ownership of submit memory is transferred to KMD's resource table so
|
|
||||||
// if adding to resource table fails, we need to free it here.
|
|
||||||
pva_kmd_device_memory_free(ctx->submit_memory);
|
|
||||||
goto queue_deinit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init chunk pool */
|
|
||||||
err = pva_kmd_cmdbuf_chunk_pool_init(
|
|
||||||
&ctx->chunk_pool, ctx->submit_memory_resource_id,
|
|
||||||
0 /* offset */, chunk_mem_size,
|
|
||||||
pva_kmd_get_max_cmdbuf_chunk_size(ctx->pva),
|
|
||||||
PVA_KMD_MAX_NUM_PRIV_CHUNKS, ctx->submit_memory->va);
|
|
||||||
if (err != PVA_SUCCESS) {
|
|
||||||
goto free_dram_buffer_resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init fence */
|
|
||||||
ctx->fence_offset = chunk_mem_size;
|
|
||||||
|
|
||||||
/* Init submitter */
|
/* Init submitter */
|
||||||
pva_kmd_mutex_init(&ctx->submit_lock);
|
err = pva_kmd_mutex_init(&ctx->submit_lock);
|
||||||
pva_kmd_mutex_init(&ctx->chunk_pool_lock);
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("pva_kmd_context_init submit_lock init failed");
|
||||||
|
goto deinit_chunk_pool;
|
||||||
|
}
|
||||||
|
err = pva_kmd_mutex_init(&ctx->chunk_pool_lock);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_context_init chunk_pool_lock init failed");
|
||||||
|
goto deinit_submit_lock;
|
||||||
|
}
|
||||||
post_fence.resource_id = ctx->submit_memory_resource_id;
|
post_fence.resource_id = ctx->submit_memory_resource_id;
|
||||||
post_fence.offset_lo = iova_lo(ctx->fence_offset);
|
post_fence.offset_lo = iova_lo(ctx->fence_offset);
|
||||||
post_fence.offset_hi = iova_hi(ctx->fence_offset);
|
post_fence.offset_hi = iova_hi(ctx->fence_offset);
|
||||||
@@ -248,7 +327,8 @@ enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
|||||||
pva_kmd_submitter_init(
|
pva_kmd_submitter_init(
|
||||||
&ctx->submitter, &ctx->ctx_queue, &ctx->submit_lock,
|
&ctx->submitter, &ctx->ctx_queue, &ctx->submit_lock,
|
||||||
&ctx->chunk_pool, &ctx->chunk_pool_lock,
|
&ctx->chunk_pool, &ctx->chunk_pool_lock,
|
||||||
pva_offset_pointer(ctx->submit_memory->va, ctx->fence_offset),
|
(uint32_t *)pva_offset_pointer(ctx->submit_memory->va,
|
||||||
|
ctx->fence_offset),
|
||||||
&post_fence);
|
&post_fence);
|
||||||
|
|
||||||
/* Use KMD's queue to inform FW */
|
/* Use KMD's queue to inform FW */
|
||||||
@@ -258,7 +338,7 @@ enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_shared_buffer_init(ctx->pva, ctx->ccq_id,
|
err = pva_kmd_shared_buffer_init(ctx->pva, ctx->ccq_id,
|
||||||
PVA_KMD_FW_BUF_ELEMENT_SIZE,
|
(uint32_t)PVA_KMD_FW_BUF_ELEMENT_SIZE,
|
||||||
res_table_capacity,
|
res_table_capacity,
|
||||||
pva_kmd_resource_table_lock,
|
pva_kmd_resource_table_lock,
|
||||||
pva_kmd_resource_table_unlock);
|
pva_kmd_resource_table_unlock);
|
||||||
@@ -271,18 +351,25 @@ enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
|||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
|
|
||||||
deinit_fw_context:
|
deinit_fw_context:
|
||||||
notify_fw_context_deinit(ctx);
|
if (PVA_SUCCESS != notify_fw_context_deinit(ctx)) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to deinitialize FW context during cleanup");
|
||||||
|
}
|
||||||
deinit_submitter:
|
deinit_submitter:
|
||||||
pva_kmd_mutex_deinit(&ctx->chunk_pool_lock);
|
pva_kmd_mutex_deinit(&ctx->chunk_pool_lock);
|
||||||
|
deinit_submit_lock:
|
||||||
pva_kmd_mutex_deinit(&ctx->submit_lock);
|
pva_kmd_mutex_deinit(&ctx->submit_lock);
|
||||||
|
deinit_chunk_pool:
|
||||||
pva_kmd_cmdbuf_chunk_pool_deinit(&ctx->chunk_pool);
|
pva_kmd_cmdbuf_chunk_pool_deinit(&ctx->chunk_pool);
|
||||||
free_dram_buffer_resource:
|
|
||||||
pva_kmd_drop_resource(&ctx->pva->dev_resource_table,
|
pva_kmd_drop_resource(&ctx->pva->dev_resource_table,
|
||||||
ctx->submit_memory_resource_id);
|
ctx->submit_memory_resource_id);
|
||||||
queue_deinit:
|
queue_deinit:
|
||||||
pva_kmd_device_memory_free(ctx->ctx_queue_mem);
|
pva_kmd_device_memory_free(ctx->ctx_queue_mem);
|
||||||
deinit_table:
|
deinit_table:
|
||||||
pva_kmd_resource_table_deinit(&ctx->ctx_resource_table);
|
pva_kmd_resource_table_deinit(&ctx->ctx_resource_table);
|
||||||
|
unmap_status_mem:
|
||||||
|
pva_kmd_device_memory_iova_unmap(ctx->status_mem);
|
||||||
|
pva_kmd_device_memory_free(ctx->status_mem);
|
||||||
err_out:
|
err_out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -300,6 +387,8 @@ void pva_kmd_free_context(struct pva_kmd_context *ctx)
|
|||||||
ctx->submit_memory_resource_id);
|
ctx->submit_memory_resource_id);
|
||||||
pva_kmd_device_memory_free(ctx->ctx_queue_mem);
|
pva_kmd_device_memory_free(ctx->ctx_queue_mem);
|
||||||
pva_kmd_resource_table_deinit(&ctx->ctx_resource_table);
|
pva_kmd_resource_table_deinit(&ctx->ctx_resource_table);
|
||||||
|
pva_kmd_device_memory_iova_unmap(ctx->status_mem);
|
||||||
|
pva_kmd_device_memory_free(ctx->status_mem);
|
||||||
ctx->inited = false;
|
ctx->inited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,24 +437,24 @@ static enum pva_error notify_fw_context_destroy(struct pva_kmd_context *ctx)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_context_destroy(struct pva_kmd_context *ctx)
|
void pva_kmd_context_destroy(struct pva_kmd_context *client)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
struct pva_kmd_device *pva = ctx->pva;
|
struct pva_kmd_device *pva = client->pva;
|
||||||
bool deferred_free = false;
|
bool deferred_free = false;
|
||||||
|
|
||||||
if (ctx->inited) {
|
if (client->inited) {
|
||||||
err = notify_fw_context_destroy(ctx);
|
err = notify_fw_context_destroy(client);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
deferred_free = true;
|
deferred_free = true;
|
||||||
pva_kmd_add_deferred_context_free(pva, ctx->ccq_id);
|
pva_kmd_add_deferred_context_free(pva, client->ccq_id);
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Failed to notify FW of context destroy; Deferring resource free until PVA is powered off.");
|
"Failed to notify FW of context destroy; Deferring resource free until PVA is powered off.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deferred_free) {
|
if (!deferred_free) {
|
||||||
pva_kmd_free_context(ctx);
|
pva_kmd_free_context(client);
|
||||||
}
|
}
|
||||||
pva_kmd_device_idle(pva);
|
pva_kmd_device_idle(pva);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,87 +10,287 @@
|
|||||||
#include "pva_kmd_queue.h"
|
#include "pva_kmd_queue.h"
|
||||||
#include "pva_kmd_mutex.h"
|
#include "pva_kmd_mutex.h"
|
||||||
#include "pva_kmd_submitter.h"
|
#include "pva_kmd_submitter.h"
|
||||||
|
#include "pva_kmd_pfsd.h"
|
||||||
|
|
||||||
struct pva_kmd_device;
|
struct pva_kmd_device;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This struct manages a user context in KMD.
|
* @brief This struct manages a user context in KMD.
|
||||||
*
|
*
|
||||||
* One KMD user context is uniquely mapped to a UMD user context. Each context
|
* @details One KMD user context is uniquely mapped to a UMD user context. Each context
|
||||||
* is assigned a unique CCQ block and, on QNX and Linux, a unique file
|
* is assigned a unique CCQ block and, on QNX and Linux, a unique file
|
||||||
* descriptor.
|
* descriptor. This structure contains all the resources and state information
|
||||||
|
* needed to manage operations for a specific user context, including resource
|
||||||
|
* tables, command queues, memory allocations, and synchronization primitives.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_context {
|
struct pva_kmd_context {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the parent PVA device
|
||||||
|
* Valid value: non-null
|
||||||
|
*/
|
||||||
struct pva_kmd_device *pva;
|
struct pva_kmd_device *pva;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource table ID assigned to this context
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_KMD_RESOURCES-1]
|
||||||
|
*/
|
||||||
uint8_t resource_table_id;
|
uint8_t resource_table_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ (Command and Control Queue) ID assigned to this context
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*/
|
||||||
uint8_t ccq_id;
|
uint8_t ccq_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SMMU context ID for memory protection
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
*/
|
||||||
uint8_t smmu_ctx_id;
|
uint8_t smmu_ctx_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if context has been initialized
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool inited;
|
bool inited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Context-specific resource table for managing user resources
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_table ctx_resource_table;
|
struct pva_kmd_resource_table ctx_resource_table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Command submission handler for context operations
|
||||||
|
*/
|
||||||
struct pva_kmd_submitter submitter;
|
struct pva_kmd_submitter submitter;
|
||||||
/** The lock protects the submission to the queue, including
|
|
||||||
* incrementing the post fence */
|
/**
|
||||||
|
* @brief Lock protecting submission operations and post fence increment
|
||||||
|
*
|
||||||
|
* @details The lock protects the submission to the queue, including
|
||||||
|
* incrementing the post fence
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t submit_lock;
|
pva_kmd_mutex_t submit_lock;
|
||||||
/** Privileged queue owned by this context. It uses the privileged
|
|
||||||
* resource table (ID 0). */
|
/**
|
||||||
|
* @brief Device memory allocation for context queue operations
|
||||||
|
*
|
||||||
|
* @details Privileged queue owned by this context. It uses the privileged
|
||||||
|
* resource table (ID 0).
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *ctx_queue_mem;
|
struct pva_kmd_device_memory *ctx_queue_mem;
|
||||||
|
|
||||||
/** Privileged queue owned by the context */
|
/**
|
||||||
|
* @brief Context-owned privileged command queue
|
||||||
|
*
|
||||||
|
* @details Privileged queue owned by the context
|
||||||
|
*/
|
||||||
struct pva_kmd_queue ctx_queue;
|
struct pva_kmd_queue ctx_queue;
|
||||||
|
|
||||||
/** memory needed for submission: including command buffer chunks and fences */
|
/**
|
||||||
|
* @brief Memory allocation for context submission operations
|
||||||
|
*
|
||||||
|
* @details Memory needed for submission: including command buffer chunks and fences
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *submit_memory;
|
struct pva_kmd_device_memory *submit_memory;
|
||||||
/** Resource ID of the submission memory, registered with the privileged resource table (ID 0) */
|
|
||||||
uint32_t submit_memory_resource_id;
|
|
||||||
uint64_t fence_offset; /**< fence offset within submit_memory*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource ID of submission memory in privileged resource table
|
||||||
|
*
|
||||||
|
* @details Resource ID of the submission memory, registered with the
|
||||||
|
* privileged resource table (ID 0)
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
|
uint32_t submit_memory_resource_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Offset of fence within submission memory
|
||||||
|
* Valid range: [0 .. submit_memory_size-1]
|
||||||
|
*/
|
||||||
|
uint64_t fence_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock protecting command buffer chunk pool operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t chunk_pool_lock;
|
pva_kmd_mutex_t chunk_pool_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pool of command buffer chunks for efficient allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_cmdbuf_chunk_pool chunk_pool;
|
struct pva_kmd_cmdbuf_chunk_pool chunk_pool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of queues supported by this context
|
||||||
|
* Valid range: [0 .. PVA_MAX_QUEUES_PER_CONTEXT]
|
||||||
|
*/
|
||||||
uint32_t max_n_queues;
|
uint32_t max_n_queues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Memory allocation for queue allocator bookkeeping
|
||||||
|
*/
|
||||||
void *queue_allocator_mem;
|
void *queue_allocator_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing queue allocation within context
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator queue_allocator;
|
struct pva_kmd_block_allocator queue_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Platform-specific private data pointer
|
||||||
|
*/
|
||||||
void *plat_data;
|
void *plat_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shared memory handle for CCQ communication
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t ccq_shm_handle;
|
uint64_t ccq_shm_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock protecting OCB (On-Chip Buffer) operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t ocb_lock;
|
pva_kmd_mutex_t ocb_lock;
|
||||||
|
|
||||||
|
/** Status memory for this context. KMD shares ownership of this memory
|
||||||
|
* with the UMD so that FW can write safely. */
|
||||||
|
struct pva_kmd_device_memory *status_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PFSD (Power Functional Safety Diagnostic) resource IDs
|
||||||
|
*
|
||||||
|
* @details Stores resource IDs for PFSD buffers, executables, and configurations
|
||||||
|
* that are registered with the resource table for this context
|
||||||
|
*/
|
||||||
|
struct pva_pfsd_resource_ids pfsd_resource_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocate a KMD context.
|
* @brief Allocate a KMD context.
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates memory for a new @ref pva_kmd_context structure
|
||||||
|
* - Initializes basic context fields including device pointer
|
||||||
|
* - Allocates a unique CCQ ID from the device's available CCQ pool
|
||||||
|
* - Sets up initial resource table and queue allocator configurations
|
||||||
|
* - Initializes synchronization primitives including mutexes
|
||||||
|
* - Configures platform-specific context data if required
|
||||||
|
* - Prepares the context for initialization via @ref pva_kmd_context_init()
|
||||||
|
*
|
||||||
|
* The allocated context must be initialized using @ref pva_kmd_context_init()
|
||||||
|
* before it can be used for operations. The context should be destroyed using
|
||||||
|
* @ref pva_kmd_context_destroy() when no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to successfully allocated @ref pva_kmd_context
|
||||||
|
* @retval NULL Context allocation failed due to memory shortage,
|
||||||
|
* CCQ unavailability, or initialization failure
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_context *pva_kmd_context_create(struct pva_kmd_device *pva);
|
struct pva_kmd_context *pva_kmd_context_create(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy a KMD context.
|
* @brief Destroy a KMD context.
|
||||||
*
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Notifies firmware of context destruction using appropriate messaging
|
||||||
|
* - Waits for firmware acknowledgment of context cleanup
|
||||||
|
* - If firmware notification succeeds, calls @ref pva_kmd_free_context()
|
||||||
|
* to immediately free context resources
|
||||||
|
* - If firmware notification fails, adds context to deferred free list
|
||||||
|
* using @ref pva_kmd_add_deferred_context_free()
|
||||||
|
* - Ensures proper cleanup of context resources and CCQ assignment
|
||||||
|
*
|
||||||
* This function first notify FW of context destruction. If successful, it
|
* This function first notify FW of context destruction. If successful, it
|
||||||
* calls pva_kmd_free_context() to free the context. Otherwise, the
|
* calls @ref pva_kmd_free_context() to free the context. Otherwise, the
|
||||||
* free is deferred until PVA is powered off.
|
* free is deferred until PVA is powered off. Deferred cleanup ensures
|
||||||
|
* that contexts are properly cleaned up even when firmware communication
|
||||||
|
* is not possible.
|
||||||
|
*
|
||||||
|
* @param[in] client Pointer to @ref pva_kmd_context structure to destroy
|
||||||
|
* Valid value: non-null, must be a valid context created by
|
||||||
|
* @ref pva_kmd_context_create()
|
||||||
*/
|
*/
|
||||||
void pva_kmd_context_destroy(struct pva_kmd_context *client);
|
void pva_kmd_context_destroy(struct pva_kmd_context *client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free a KMD context.
|
* @brief Free a KMD context.
|
||||||
*
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Frees all context-allocated memory including queues and resource tables
|
||||||
|
* - Releases the assigned CCQ ID back to the device's available pool
|
||||||
|
* - Destroys synchronization primitives including mutexes and semaphores
|
||||||
|
* - Cleans up platform-specific context resources
|
||||||
|
* - Deallocates command buffer chunks and submission memory
|
||||||
|
* - Frees the context structure itself
|
||||||
|
*
|
||||||
* This function frees the context without notifying FW. We need to make sure FW
|
* This function frees the context without notifying FW. We need to make sure FW
|
||||||
* will not access any context resources before calling this function.
|
* will not access any context resources before calling this function. This
|
||||||
|
* function is typically called either after successful firmware notification
|
||||||
|
* or during device shutdown when firmware communication is not required.
|
||||||
|
*
|
||||||
|
* @param[in] ctx Pointer to @ref pva_kmd_context structure to free
|
||||||
|
* Valid value: non-null, firmware must not be accessing
|
||||||
|
* context resources
|
||||||
*/
|
*/
|
||||||
void pva_kmd_free_context(struct pva_kmd_context *ctx);
|
void pva_kmd_free_context(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize a KMD context.
|
* @brief Initialize a KMD context.
|
||||||
*
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates and configures the context's resource table with specified capacity
|
||||||
|
* - Sets up context-specific command queues and submission infrastructure
|
||||||
|
* - Initializes memory allocations for command buffers and synchronization
|
||||||
|
* - Configures SMMU context for memory protection and isolation
|
||||||
|
* - Establishes communication channels with firmware for this context
|
||||||
|
* - Sets up queue allocator for managing multiple queues within the context
|
||||||
|
* - Marks the context as initialized and ready for operation
|
||||||
|
*
|
||||||
* The user provides a CCQ range (inclusive on both ends) and the KMD will pick
|
* The user provides a CCQ range (inclusive on both ends) and the KMD will pick
|
||||||
* one CCQ from this range.
|
* one CCQ from this range. The context must be created using
|
||||||
|
* @ref pva_kmd_context_create() before calling this function. After successful
|
||||||
|
* initialization, the context is ready to accept command submissions and
|
||||||
|
* resource registrations.
|
||||||
|
*
|
||||||
|
* @param[in, out] ctx Pointer to @ref pva_kmd_context structure
|
||||||
|
* Valid value: non-null, created but not yet initialized
|
||||||
|
* @param[in] res_table_capacity Maximum number of resources the context can manage
|
||||||
|
* Valid range: [1 .. PVA_MAX_RESOURCE_TABLE_ENTRIES]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Context initialized successfully
|
||||||
|
* @retval PVA_INVAL Context is already initialized
|
||||||
|
* @retval PVA_BAD_PARAMETER_ERROR Invalid resource table capacity (zero)
|
||||||
|
* @retval PVA_NOMEM Memory allocation failed for context resources
|
||||||
|
* @retval PVA_NO_RESOURCE_ID No available resource IDs for memory registration
|
||||||
*/
|
*/
|
||||||
enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
enum pva_error pva_kmd_context_init(struct pva_kmd_context *ctx,
|
||||||
uint32_t res_table_capacity);
|
uint32_t res_table_capacity,
|
||||||
|
uint64_t status_shm_hdl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve a context by its allocation ID from the device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided allocation ID against the device's context pool
|
||||||
|
* - Uses the device's context allocator to locate the corresponding context
|
||||||
|
* - Performs bounds checking to ensure the allocation ID is valid
|
||||||
|
* - Returns the context pointer if found, or NULL if invalid
|
||||||
|
* - Provides safe access to contexts using their allocation identifiers
|
||||||
|
*
|
||||||
|
* This function provides a safe way to retrieve context pointers using
|
||||||
|
* allocation IDs, which are used internally by the KMD to track and
|
||||||
|
* manage contexts. The allocation ID is typically assigned during context
|
||||||
|
* creation and remains valid until context destruction.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] alloc_id Allocation ID of the context to retrieve
|
||||||
|
* Valid range: [0 .. max_n_contexts-1]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_kmd_context if allocation ID is valid
|
||||||
|
* @retval NULL Invalid allocation ID or context not found
|
||||||
|
*/
|
||||||
struct pva_kmd_context *pva_kmd_get_context(struct pva_kmd_device *pva,
|
struct pva_kmd_context *pva_kmd_get_context(struct pva_kmd_device *pva,
|
||||||
uint8_t alloc_id);
|
uint8_t alloc_id);
|
||||||
|
|
||||||
|
|||||||
@@ -10,24 +10,33 @@
|
|||||||
#include "pva_kmd_vpu_app_auth.h"
|
#include "pva_kmd_vpu_app_auth.h"
|
||||||
#include "pva_kmd_shared_buffer.h"
|
#include "pva_kmd_shared_buffer.h"
|
||||||
#include "pva_kmd_r5_ocd.h"
|
#include "pva_kmd_r5_ocd.h"
|
||||||
|
#include "pva_kmd_fw_tracepoints.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
uint64_t pva_kmd_read_from_buffer_to_user(void *to, uint64_t count,
|
int64_t pva_kmd_read_from_buffer_to_user(void *to, uint64_t count,
|
||||||
uint64_t offset, const void *from,
|
uint64_t offset, const void *from,
|
||||||
uint64_t available)
|
uint64_t available)
|
||||||
{
|
{
|
||||||
if (offset >= available || !count) {
|
uint64_t bytes_copied;
|
||||||
|
|
||||||
|
if ((offset >= available) || (count == 0U)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (count > available - offset) {
|
if (count > available - offset) {
|
||||||
count = available - offset;
|
count = available - offset;
|
||||||
}
|
}
|
||||||
if (pva_kmd_copy_data_to_user(to, (uint8_t *)from + offset, count)) {
|
if (pva_kmd_copy_data_to_user(to, (const uint8_t *)from + offset,
|
||||||
|
count) != 0UL) {
|
||||||
pva_kmd_log_err("failed to copy read buffer to user");
|
pva_kmd_log_err("failed to copy read buffer to user");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return count;
|
bytes_copied = count;
|
||||||
|
/* Ensure result fits in int64_t for debugfs interface */
|
||||||
|
ASSERT(bytes_copied <= (uint64_t)S64_MAX);
|
||||||
|
return (int64_t)bytes_copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
static int64_t profiling_level_read(struct pva_kmd_device *dev, void *file_data,
|
static int64_t profiling_level_read(struct pva_kmd_device *dev, void *file_data,
|
||||||
uint8_t *out_buffer, uint64_t offset,
|
uint8_t *out_buffer, uint64_t offset,
|
||||||
uint64_t size)
|
uint64_t size)
|
||||||
@@ -46,7 +55,8 @@ static int64_t profiling_level_read(struct pva_kmd_device *dev, void *file_data,
|
|||||||
formatted_len++; // Account for null terminator
|
formatted_len++; // Account for null terminator
|
||||||
|
|
||||||
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset,
|
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset,
|
||||||
kernel_buffer, formatted_len);
|
kernel_buffer,
|
||||||
|
(uint64_t)formatted_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t profiling_level_write(struct pva_kmd_device *dev,
|
static int64_t profiling_level_write(struct pva_kmd_device *dev,
|
||||||
@@ -91,120 +101,84 @@ static int64_t profiling_level_write(struct pva_kmd_device *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return (int64_t)size;
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t print_vpu_stats(struct pva_kmd_tegrastats *kmd_tegra_stats,
|
|
||||||
uint8_t *out_buffer, uint64_t offset,
|
|
||||||
uint64_t len)
|
|
||||||
{
|
|
||||||
char kernel_buffer[256];
|
|
||||||
int64_t formatted_len;
|
|
||||||
|
|
||||||
formatted_len = snprintf(
|
|
||||||
kernel_buffer, sizeof(kernel_buffer),
|
|
||||||
"%llu\n%llu\n%llu\n%llu\n",
|
|
||||||
(long long unsigned int)(kmd_tegra_stats->window_start_time),
|
|
||||||
(long long unsigned int)(kmd_tegra_stats->window_end_time),
|
|
||||||
(long long unsigned int)
|
|
||||||
kmd_tegra_stats->average_vpu_utilization[0],
|
|
||||||
(long long unsigned int)
|
|
||||||
kmd_tegra_stats->average_vpu_utilization[1]);
|
|
||||||
|
|
||||||
if (formatted_len <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatted_len++; //accounting for null terminating character
|
|
||||||
|
|
||||||
if (len < (uint64_t)formatted_len) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the formatted string from kernel buffer to user buffer
|
|
||||||
return pva_kmd_read_from_buffer_to_user(out_buffer, len, offset,
|
|
||||||
kernel_buffer, formatted_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t get_vpu_stats(struct pva_kmd_device *dev, void *file_data,
|
|
||||||
uint8_t *out_buffer, uint64_t offset,
|
|
||||||
uint64_t size)
|
|
||||||
{
|
|
||||||
struct pva_kmd_tegrastats kmd_tegra_stats;
|
|
||||||
|
|
||||||
// We don't support partial reads for vpu stats because we cannot mix two
|
|
||||||
// reads at different times together.
|
|
||||||
if (offset != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
kmd_tegra_stats.window_start_time = 0;
|
|
||||||
kmd_tegra_stats.window_end_time = 0;
|
|
||||||
kmd_tegra_stats.average_vpu_utilization[0] = 0;
|
|
||||||
kmd_tegra_stats.average_vpu_utilization[1] = 0;
|
|
||||||
|
|
||||||
if (pva_kmd_device_maybe_on(dev))
|
|
||||||
pva_kmd_notify_fw_get_tegra_stats(dev, &kmd_tegra_stats);
|
|
||||||
|
|
||||||
return print_vpu_stats(&kmd_tegra_stats, out_buffer, offset, size);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int64_t get_vpu_allowlist_enabled(struct pva_kmd_device *pva,
|
static int64_t get_vpu_allowlist_enabled(struct pva_kmd_device *pva,
|
||||||
void *file_data, uint8_t *out_buffer,
|
void *file_data, uint8_t *out_buffer,
|
||||||
uint64_t offset, uint64_t size)
|
uint64_t offset, uint64_t size)
|
||||||
{
|
{
|
||||||
// 1 byte for '0' or '1' and another 1 byte for the Null character
|
char out_str[2]; // 1 byte for '0' or '1' and another 1 byte for the Null character
|
||||||
char out_str[2];
|
int ret;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
||||||
snprintf(out_str, sizeof(out_str), "%d",
|
ret = snprintf(out_str, sizeof(out_str), "%d",
|
||||||
(int)pva->pva_auth->pva_auth_enable);
|
(int)pva->pva_auth->pva_auth_enable);
|
||||||
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
||||||
|
|
||||||
|
if ((ret < 0) || ((size_t)ret >= sizeof(out_str))) {
|
||||||
|
pva_kmd_log_err("snprintf failed or truncated");
|
||||||
|
return (int64_t)PVA_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the formatted string from kernel buffer to user buffer
|
// Copy the formatted string from kernel buffer to user buffer
|
||||||
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset,
|
return pva_kmd_read_from_buffer_to_user(
|
||||||
out_str, sizeof(out_str));
|
out_buffer, size, offset, out_str, (uint64_t)sizeof(out_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t update_vpu_allowlist(struct pva_kmd_device *pva, void *file_data,
|
static int64_t update_vpu_allowlist(struct pva_kmd_device *pva, void *file_data,
|
||||||
const uint8_t *in_buffer, uint64_t offset,
|
const uint8_t *in_buffer, uint64_t offset,
|
||||||
uint64_t size)
|
uint64_t size)
|
||||||
{
|
{
|
||||||
char strbuf[2]; // 1 byte for '0' or '1' and another 1 byte for the Null character
|
char input_buf
|
||||||
|
[2]; // 1 byte for '0' or '1' and another 1 byte for the Null character
|
||||||
uint32_t base = 10;
|
uint32_t base = 10;
|
||||||
uint32_t pva_auth_enable;
|
uint32_t pva_auth_enable;
|
||||||
unsigned long retval;
|
unsigned long retval;
|
||||||
|
unsigned long strtol_result;
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0U) {
|
||||||
pva_kmd_log_err("Write failed, no data provided");
|
pva_kmd_log_err("Write failed, no data provided");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy a single character, ignore the rest
|
// Copy a single character, ignore the rest
|
||||||
retval = pva_kmd_copy_data_from_user(strbuf, in_buffer + offset, 1);
|
retval = pva_kmd_copy_data_from_user(input_buf, in_buffer + offset, 1);
|
||||||
if (retval != 0u) {
|
if (retval != 0UL) {
|
||||||
pva_kmd_log_err("Failed to copy write buffer from user");
|
pva_kmd_log_err("Failed to copy write buffer from user");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly null terminate the string for conversion
|
// Explicitly null terminate the string for conversion
|
||||||
strbuf[1] = '\0';
|
input_buf[1] = '\0';
|
||||||
pva_auth_enable = pva_kmd_strtol(strbuf, base);
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
strtol_result = pva_kmd_strtol(input_buf, (int32_t)base);
|
||||||
|
/* Validate result fits in uint32_t */
|
||||||
|
if (strtol_result > U32_MAX) {
|
||||||
|
pva_kmd_log_err("pva_kmd_debugfs: Value exceeds U32_MAX");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* CERT INT31-C: strtol_result validated to fit in uint32_t, safe to cast */
|
||||||
|
pva_auth_enable = (uint32_t)strtol_result;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
||||||
pva->pva_auth->pva_auth_enable = (pva_auth_enable == 1) ? true : false;
|
pva->pva_auth->pva_auth_enable = (pva_auth_enable == 1U) ? true : false;
|
||||||
|
|
||||||
if (pva->pva_auth->pva_auth_enable)
|
if (pva->pva_auth->pva_auth_enable) {
|
||||||
pva->pva_auth->pva_auth_allow_list_parsed = false;
|
pva->pva_auth->pva_auth_allow_list_parsed = false;
|
||||||
|
}
|
||||||
|
|
||||||
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
||||||
return size;
|
return (int64_t)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t get_vpu_allowlist_path(struct pva_kmd_device *pva,
|
static int64_t get_vpu_allowlist_path(struct pva_kmd_device *pva,
|
||||||
void *file_data, uint8_t *out_buffer,
|
void *file_data, uint8_t *out_buffer,
|
||||||
uint64_t offset, uint64_t size)
|
uint64_t offset, uint64_t size)
|
||||||
{
|
{
|
||||||
uint64_t len;
|
int64_t len;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_lock(&(pva->pva_auth->allow_list_lock));
|
||||||
len = pva_kmd_read_from_buffer_to_user(
|
len = pva_kmd_read_from_buffer_to_user(
|
||||||
out_buffer, size, offset,
|
out_buffer, size, offset,
|
||||||
@@ -223,7 +197,7 @@ static int64_t update_vpu_allowlist_path(struct pva_kmd_device *pva,
|
|||||||
char buffer[ALLOWLIST_FILE_LEN];
|
char buffer[ALLOWLIST_FILE_LEN];
|
||||||
unsigned long retval;
|
unsigned long retval;
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0U) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +209,7 @@ static int64_t update_vpu_allowlist_path(struct pva_kmd_device *pva,
|
|||||||
}
|
}
|
||||||
|
|
||||||
retval = pva_kmd_copy_data_from_user(buffer, in_buffer, size);
|
retval = pva_kmd_copy_data_from_user(buffer, in_buffer, size);
|
||||||
if (retval != 0u) {
|
if (retval != 0UL) {
|
||||||
pva_kmd_log_err("Failed to copy write buffer from user");
|
pva_kmd_log_err("Failed to copy write buffer from user");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -247,79 +221,7 @@ static int64_t update_vpu_allowlist_path(struct pva_kmd_device *pva,
|
|||||||
pva_kmd_update_allowlist_path(pva, buffer);
|
pva_kmd_update_allowlist_path(pva, buffer);
|
||||||
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
pva_kmd_mutex_unlock(&(pva->pva_auth->allow_list_lock));
|
||||||
|
|
||||||
return size;
|
return (int64_t)size;
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t update_fw_trace_level(struct pva_kmd_device *pva,
|
|
||||||
void *file_data, const uint8_t *in_buffer,
|
|
||||||
uint64_t offset, uint64_t size)
|
|
||||||
{
|
|
||||||
uint32_t trace_level;
|
|
||||||
unsigned long retval;
|
|
||||||
size_t copy_size;
|
|
||||||
uint32_t base = 10;
|
|
||||||
char strbuf[11]; // 10 bytes for the highest 32bit value and another 1 byte for the Null character
|
|
||||||
strbuf[10] = '\0';
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
pva_kmd_log_err("Write failed, no data provided");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy minimum of buffer size and input size */
|
|
||||||
copy_size = (size < (sizeof(strbuf) - 1)) ? size : (sizeof(strbuf) - 1);
|
|
||||||
|
|
||||||
retval = pva_kmd_copy_data_from_user(strbuf, in_buffer + offset,
|
|
||||||
copy_size);
|
|
||||||
if (retval != 0u) {
|
|
||||||
pva_kmd_log_err("Failed to copy write buffer from user");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace_level = pva_kmd_strtol(strbuf, base);
|
|
||||||
|
|
||||||
pva->fw_trace_level = trace_level;
|
|
||||||
|
|
||||||
/* If device is on, busy the device and set the debug log level */
|
|
||||||
if (pva_kmd_device_maybe_on(pva) == true) {
|
|
||||||
enum pva_error err;
|
|
||||||
err = pva_kmd_device_busy(pva);
|
|
||||||
if (err != PVA_SUCCESS) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"pva_kmd_device_busy failed when submitting set debug log level cmd");
|
|
||||||
goto err_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pva_kmd_notify_fw_set_trace_level(pva, trace_level);
|
|
||||||
|
|
||||||
pva_kmd_device_idle(pva);
|
|
||||||
|
|
||||||
if (err != PVA_SUCCESS) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"Failed to notify FW about debug log level change");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err_end:
|
|
||||||
return copy_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t get_fw_trace_level(struct pva_kmd_device *dev, void *file_data,
|
|
||||||
uint8_t *out_buffer, uint64_t offset,
|
|
||||||
uint64_t size)
|
|
||||||
{
|
|
||||||
char print_buffer[64];
|
|
||||||
int formatted_len;
|
|
||||||
|
|
||||||
formatted_len = snprintf(print_buffer, sizeof(print_buffer), "%u\n",
|
|
||||||
dev->fw_trace_level);
|
|
||||||
|
|
||||||
if (formatted_len <= 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset,
|
|
||||||
print_buffer,
|
|
||||||
(uint64_t)formatted_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t write_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
static int64_t write_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
||||||
@@ -330,32 +232,32 @@ static int64_t write_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
|||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
|
|
||||||
if ((offset != 0) || (size < 1)) {
|
if ((offset != 0U) || (size < 1U)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pva_kmd_copy_data_from_user(&buf, in_buffer, 1);
|
ret = pva_kmd_copy_data_from_user(&buf, in_buffer, 1);
|
||||||
if (ret != 0) {
|
if (ret != 0U) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"SC7 simulation: failed to copy data from user");
|
"SC7 simulation: failed to copy data from user");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf == '1') {
|
if (buf == (uint8_t)'1') {
|
||||||
if (pva->debugfs_context.entered_sc7 == 0) {
|
if (pva->debugfs_context.entered_sc7 == false) {
|
||||||
err = pva_kmd_simulate_enter_sc7(pva);
|
err = pva_kmd_simulate_enter_sc7(pva);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
pva->debugfs_context.entered_sc7 = 1;
|
pva->debugfs_context.entered_sc7 = true;
|
||||||
}
|
}
|
||||||
} else if (buf == '0') {
|
} else if (buf == (uint8_t)'0') {
|
||||||
if (pva->debugfs_context.entered_sc7 == 1) {
|
if (pva->debugfs_context.entered_sc7 == true) {
|
||||||
err = pva_kmd_simulate_exit_sc7(pva);
|
err = pva_kmd_simulate_exit_sc7(pva);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
pva->debugfs_context.entered_sc7 = 0;
|
pva->debugfs_context.entered_sc7 = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
@@ -363,7 +265,7 @@ static int64_t write_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return (int64_t)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t read_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
static int64_t read_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
||||||
@@ -374,20 +276,15 @@ static int64_t read_simulate_sc7(struct pva_kmd_device *pva, void *file_data,
|
|||||||
buf = pva->debugfs_context.entered_sc7 ? '1' : '0';
|
buf = pva->debugfs_context.entered_sc7 ? '1' : '0';
|
||||||
|
|
||||||
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset, &buf,
|
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset, &buf,
|
||||||
1);
|
(uint64_t)1);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *pva)
|
enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
static const char *vpu_ocd_names[NUM_VPU_BLOCKS] = { "ocd_vpu0_v3",
|
|
||||||
"ocd_vpu1_v3" };
|
|
||||||
struct pva_kmd_file_ops *profiling_fops;
|
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
|
|
||||||
pva_kmd_debugfs_create_bool(pva, "stats_enabled",
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
&pva->debugfs_context.stats_enable);
|
struct pva_kmd_file_ops *profiling_fops;
|
||||||
pva_kmd_debugfs_create_bool(pva, "vpu_debug",
|
|
||||||
&pva->debugfs_context.vpu_debug);
|
|
||||||
|
|
||||||
// Create profiling_level file operations
|
// Create profiling_level file operations
|
||||||
profiling_fops = &pva->debugfs_context.profiling_level_fops;
|
profiling_fops = &pva->debugfs_context.profiling_level_fops;
|
||||||
@@ -396,6 +293,7 @@ enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *pva)
|
|||||||
profiling_fops->open = NULL;
|
profiling_fops->open = NULL;
|
||||||
profiling_fops->release = NULL;
|
profiling_fops->release = NULL;
|
||||||
profiling_fops->pdev = pva;
|
profiling_fops->pdev = pva;
|
||||||
|
|
||||||
err = pva_kmd_debugfs_create_file(pva, "profiling_level",
|
err = pva_kmd_debugfs_create_file(pva, "profiling_level",
|
||||||
profiling_fops);
|
profiling_fops);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -403,38 +301,18 @@ enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *pva)
|
|||||||
"Failed to create profiling_level debugfs file");
|
"Failed to create profiling_level debugfs file");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pva->debugfs_context.vpu_fops.read = &get_vpu_stats;
|
err = pva_kmd_tegrastats_init_debugfs(pva);
|
||||||
pva->debugfs_context.vpu_fops.write = NULL;
|
|
||||||
pva->debugfs_context.vpu_fops.pdev = pva;
|
|
||||||
err = pva_kmd_debugfs_create_file(pva, "vpu_stats",
|
|
||||||
&pva->debugfs_context.vpu_fops);
|
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Failed to create vpu_stats debugfs file");
|
pva_kmd_log_err("Failed to create tegrastats debugfs file");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < NUM_VPU_BLOCKS; i++) {
|
err = pva_kmd_vpu_ocd_init_debugfs(pva);
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].open =
|
|
||||||
&pva_kmd_vpu_ocd_open;
|
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].release =
|
|
||||||
&pva_kmd_vpu_ocd_release;
|
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].read =
|
|
||||||
&pva_kmd_vpu_ocd_read;
|
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].write =
|
|
||||||
&pva_kmd_vpu_ocd_write;
|
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].pdev = pva;
|
|
||||||
pva->debugfs_context.vpu_ocd_fops[i].file_data =
|
|
||||||
(void *)&pva->regspec.vpu_dbg_instr_reg_offset[i];
|
|
||||||
err = pva_kmd_debugfs_create_file(
|
|
||||||
pva, vpu_ocd_names[i],
|
|
||||||
&pva->debugfs_context.vpu_ocd_fops[i]);
|
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
|
||||||
"Failed to create vpu_ocd debugfs file");
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pva->debugfs_context.allowlist_ena_fops.read =
|
pva->debugfs_context.allowlist_ena_fops.read =
|
||||||
&get_vpu_allowlist_enabled;
|
&get_vpu_allowlist_enabled;
|
||||||
@@ -461,12 +339,7 @@ enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *pva)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pva->debugfs_context.fw_trace_level_fops.write = &update_fw_trace_level;
|
err = pva_kmd_fw_tracepoints_init_debugfs(pva);
|
||||||
pva->debugfs_context.fw_trace_level_fops.read = &get_fw_trace_level;
|
|
||||||
pva->debugfs_context.fw_trace_level_fops.pdev = pva;
|
|
||||||
err = pva_kmd_debugfs_create_file(
|
|
||||||
pva, "fw_trace_level",
|
|
||||||
&pva->debugfs_context.fw_trace_level_fops);
|
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Failed to create fw_trace_level debugfs file");
|
pva_kmd_log_err("Failed to create fw_trace_level debugfs file");
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -7,44 +7,246 @@
|
|||||||
#include "pva_kmd_shim_debugfs.h"
|
#include "pva_kmd_shim_debugfs.h"
|
||||||
#include "pva_kmd_fw_profiler.h"
|
#include "pva_kmd_fw_profiler.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of VPU blocks supported for debugging
|
||||||
|
*
|
||||||
|
* @details Number of VPU blocks supported for debugging operations.
|
||||||
|
* This constant defines the maximum number of VPU debugging interfaces
|
||||||
|
* that can be created in the debug system.
|
||||||
|
*/
|
||||||
#define NUM_VPU_BLOCKS 2U
|
#define NUM_VPU_BLOCKS 2U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations structure for debug interfaces
|
||||||
|
*
|
||||||
|
* @details This structure defines the callback functions for debug file
|
||||||
|
* operations including open, close, read, and write operations. It provides
|
||||||
|
* a platform-agnostic interface for accessing debug information through
|
||||||
|
* file-like operations, supporting both reading and writing of debug data.
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops {
|
struct pva_kmd_file_ops {
|
||||||
|
/**
|
||||||
|
* @brief Open callback for debug file
|
||||||
|
* Valid value: non-null function pointer or NULL if not supported
|
||||||
|
*/
|
||||||
int (*open)(struct pva_kmd_device *dev);
|
int (*open)(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release/close callback for debug file
|
||||||
|
* Valid value: non-null function pointer or NULL if not supported
|
||||||
|
*/
|
||||||
int (*release)(struct pva_kmd_device *dev);
|
int (*release)(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read callback for debug file
|
||||||
|
* Valid value: non-null function pointer or NULL if not supported
|
||||||
|
*/
|
||||||
int64_t (*read)(struct pva_kmd_device *dev, void *file_data,
|
int64_t (*read)(struct pva_kmd_device *dev, void *file_data,
|
||||||
uint8_t *data, uint64_t offset, uint64_t size);
|
uint8_t *data, uint64_t offset, uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write callback for debug file
|
||||||
|
* Valid value: non-null function pointer or NULL if not supported
|
||||||
|
*/
|
||||||
int64_t (*write)(struct pva_kmd_device *dev, void *file_data,
|
int64_t (*write)(struct pva_kmd_device *dev, void *file_data,
|
||||||
const uint8_t *data, uint64_t offset, uint64_t size);
|
const uint8_t *data, uint64_t offset, uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Platform-specific device pointer
|
||||||
|
*/
|
||||||
void *pdev;
|
void *pdev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File-specific data pointer
|
||||||
|
*/
|
||||||
void *file_data;
|
void *file_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug context for PVA device debugging
|
||||||
|
*
|
||||||
|
* @details This structure maintains the complete debug context
|
||||||
|
* for a PVA device, including various debug interfaces, configuration
|
||||||
|
* settings, and file operation handlers. It provides comprehensive debugging
|
||||||
|
* capabilities including VPU debugging, profiling, allowlist management,
|
||||||
|
* hardware performance monitoring, and firmware tracing.
|
||||||
|
*/
|
||||||
struct pva_kmd_debugfs_context {
|
struct pva_kmd_debugfs_context {
|
||||||
|
/**
|
||||||
|
* @brief Enable flag for statistics collection
|
||||||
|
* Valid values: true (enabled), false (disabled)
|
||||||
|
*/
|
||||||
bool stats_enable;
|
bool stats_enable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable flag for VPU debugging
|
||||||
|
* Valid values: true (enabled), false (disabled)
|
||||||
|
*/
|
||||||
bool vpu_debug;
|
bool vpu_debug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable flag for VPU print output
|
||||||
|
* Valid values: true (enabled), false (disabled)
|
||||||
|
*/
|
||||||
bool vpu_print_enable;
|
bool vpu_print_enable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if system entered SC7 state
|
||||||
|
* Valid values: true (entered), false (not entered)
|
||||||
|
*/
|
||||||
bool entered_sc7;
|
bool entered_sc7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Path to allowlist configuration file
|
||||||
|
* Valid value: null-terminated string or NULL
|
||||||
|
*/
|
||||||
char *allowlist_path;
|
char *allowlist_path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Current profiling level setting
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t profiling_level;
|
uint32_t profiling_level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for VPU debugging interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops vpu_fops;
|
struct pva_kmd_file_ops vpu_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for allowlist enable interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops allowlist_ena_fops;
|
struct pva_kmd_file_ops allowlist_ena_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for allowlist path interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops allowlist_path_fops;
|
struct pva_kmd_file_ops allowlist_path_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for hardware performance monitoring interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops hwpm_fops;
|
struct pva_kmd_file_ops hwpm_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for profiling level interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops profiling_level_fops;
|
struct pva_kmd_file_ops profiling_level_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Data pointer for hardware performance monitoring
|
||||||
|
*/
|
||||||
void *data_hwpm;
|
void *data_hwpm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of file operations for VPU on-chip debugging interfaces
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops vpu_ocd_fops[NUM_VPU_BLOCKS];
|
struct pva_kmd_file_ops vpu_ocd_fops[NUM_VPU_BLOCKS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Global firmware profiling configuration
|
||||||
|
*/
|
||||||
struct pva_kmd_fw_profiling_config g_fw_profiling_config;
|
struct pva_kmd_fw_profiling_config g_fw_profiling_config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for firmware trace level interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops fw_trace_level_fops;
|
struct pva_kmd_file_ops fw_trace_level_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for SC7 simulation interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops simulate_sc7_fops;
|
struct pva_kmd_file_ops simulate_sc7_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief File operations for R5 on-chip debugging interface
|
||||||
|
*/
|
||||||
struct pva_kmd_file_ops r5_ocd_fops;
|
struct pva_kmd_file_ops r5_ocd_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Buffer for R5 OCD staging operations
|
||||||
|
*/
|
||||||
void *r5_ocd_stage_buffer;
|
void *r5_ocd_stage_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create debug nodes for PVA device debugging
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Creates debug nodes for various PVA debugging interfaces
|
||||||
|
* - Sets up file operation callbacks for each debug interface
|
||||||
|
* - Initializes VPU debugging interfaces for all VPU blocks
|
||||||
|
* - Creates hardware performance monitoring debug nodes
|
||||||
|
* - Sets up firmware profiling and tracing interfaces
|
||||||
|
* - Configures allowlist management debug interfaces
|
||||||
|
* - Establishes R5 and VPU on-chip debugging capabilities
|
||||||
|
* - Provides comprehensive debugging infrastructure for the PVA device
|
||||||
|
*
|
||||||
|
* The created debug nodes enable access to various PVA debugging features
|
||||||
|
* through the debug interface, supporting development, debugging,
|
||||||
|
* and performance analysis workflows.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Debug nodes created successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate memory for debug infrastructure
|
||||||
|
* @retval PVA_INVAL Invalid parameters for debug node creation
|
||||||
|
* @retval PVA_INTERNAL Platform-specific debug creation failed
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *dev);
|
enum pva_error pva_kmd_debugfs_create_nodes(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy debug nodes and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Removes all debug nodes created for the PVA device
|
||||||
|
* - Cleans up file operation callbacks and associated data structures
|
||||||
|
* - Frees memory allocated for debug interfaces and buffers
|
||||||
|
* - Destroys VPU and R5 on-chip debugging interfaces
|
||||||
|
* - Cleans up hardware performance monitoring debug nodes
|
||||||
|
* - Removes firmware profiling and tracing interfaces
|
||||||
|
* - Ensures proper cleanup of all debugging infrastructure
|
||||||
|
*
|
||||||
|
* This function should be called during device cleanup to ensure
|
||||||
|
* proper removal of all debug interfaces and prevent resource leaks.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must have been initialized with debug nodes
|
||||||
|
*/
|
||||||
void pva_kmd_debugfs_destroy_nodes(struct pva_kmd_device *dev);
|
void pva_kmd_debugfs_destroy_nodes(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
uint64_t pva_kmd_read_from_buffer_to_user(void *to, uint64_t count,
|
/**
|
||||||
|
* @brief Copy data from buffer to user space with bounds checking
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the requested read parameters against buffer bounds
|
||||||
|
* - Calculates the actual amount of data available for reading
|
||||||
|
* - Handles offset positioning within the source buffer
|
||||||
|
* - Copies data from the source buffer to the destination
|
||||||
|
* - Ensures no buffer overruns or invalid memory access
|
||||||
|
* - Returns the actual number of bytes copied to user space
|
||||||
|
* - Validates result fits in int64_t for debugfs interface compatibility
|
||||||
|
*
|
||||||
|
* This utility function provides safe buffer-to-user copying for debug
|
||||||
|
* file read operations, preventing buffer overruns and ensuring proper
|
||||||
|
* bounds checking for all debug interface data transfers.
|
||||||
|
*
|
||||||
|
* @param[out] to Destination buffer for copied data
|
||||||
|
* Valid value: non-null, min size count bytes
|
||||||
|
* @param[in] count Maximum number of bytes to copy
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
* @param[in] offset Offset within source buffer to start reading
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
* @param[in] from Source buffer containing data to copy
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] available Total size of available data in source buffer
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*
|
||||||
|
* @retval bytes_copied Number of bytes actually copied to destination
|
||||||
|
* Range: [0 .. min(count, available-offset, INT64_MAX)]
|
||||||
|
*/
|
||||||
|
int64_t pva_kmd_read_from_buffer_to_user(void *to, uint64_t count,
|
||||||
uint64_t offset, const void *from,
|
uint64_t offset, const void *from,
|
||||||
uint64_t available);
|
uint64_t available);
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,13 @@
|
|||||||
#include "pva_kmd_regs.h"
|
#include "pva_kmd_regs.h"
|
||||||
#include "pva_kmd_device_memory.h"
|
#include "pva_kmd_device_memory.h"
|
||||||
#include "pva_kmd_fw_profiler.h"
|
#include "pva_kmd_fw_profiler.h"
|
||||||
#include "pva_kmd_fw_debug.h"
|
|
||||||
#include "pva_kmd_vpu_app_auth.h"
|
#include "pva_kmd_vpu_app_auth.h"
|
||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
#include "pva_kmd_debugfs.h"
|
#include "pva_kmd_debugfs.h"
|
||||||
#include "pva_kmd_tegra_stats.h"
|
#include "pva_kmd_tegra_stats.h"
|
||||||
#include "pva_kmd_shim_silicon.h"
|
#include "pva_kmd_shim_silicon.h"
|
||||||
#include "pva_kmd_shared_buffer.h"
|
#include "pva_kmd_shared_buffer.h"
|
||||||
|
#include "pva_kmd_fw_tracepoints.h"
|
||||||
|
|
||||||
#include "pva_kmd_abort.h"
|
#include "pva_kmd_abort.h"
|
||||||
#include "pva_version.h"
|
#include "pva_version.h"
|
||||||
@@ -130,22 +130,27 @@ static void pva_kmd_device_init_submission(struct pva_kmd_device *pva)
|
|||||||
/* Add submit memory to resource table */
|
/* Add submit memory to resource table */
|
||||||
err = pva_kmd_add_dram_buffer_resource(&pva->dev_resource_table,
|
err = pva_kmd_add_dram_buffer_resource(&pva->dev_resource_table,
|
||||||
pva->submit_memory,
|
pva->submit_memory,
|
||||||
&pva->submit_memory_resource_id);
|
&pva->submit_memory_resource_id,
|
||||||
|
false);
|
||||||
ASSERT(err == PVA_SUCCESS);
|
ASSERT(err == PVA_SUCCESS);
|
||||||
pva_kmd_update_fw_resource_table(&pva->dev_resource_table);
|
pva_kmd_update_fw_resource_table(&pva->dev_resource_table);
|
||||||
|
|
||||||
/* Init chunk pool */
|
/* Init chunk pool */
|
||||||
pva_kmd_cmdbuf_chunk_pool_init(
|
err = pva_kmd_cmdbuf_chunk_pool_init(
|
||||||
&pva->chunk_pool, pva->submit_memory_resource_id, 0,
|
&pva->chunk_pool, pva->submit_memory_resource_id, 0,
|
||||||
chunk_mem_size, pva_kmd_get_max_cmdbuf_chunk_size(pva),
|
(uint32_t)chunk_mem_size,
|
||||||
|
pva_kmd_get_max_cmdbuf_chunk_size(pva),
|
||||||
PVA_KMD_MAX_NUM_KMD_CHUNKS, pva->submit_memory->va);
|
PVA_KMD_MAX_NUM_KMD_CHUNKS, pva->submit_memory->va);
|
||||||
|
ASSERT(err == PVA_SUCCESS);
|
||||||
|
|
||||||
/* Init fence */
|
/* Init fence */
|
||||||
pva->fence_offset = chunk_mem_size;
|
pva->fence_offset = chunk_mem_size;
|
||||||
|
|
||||||
/* Init submitter */
|
/* Init submitter */
|
||||||
pva_kmd_mutex_init(&pva->submit_lock);
|
err = pva_kmd_mutex_init(&pva->submit_lock);
|
||||||
pva_kmd_mutex_init(&pva->chunk_pool_lock);
|
ASSERT(err == PVA_SUCCESS);
|
||||||
|
err = pva_kmd_mutex_init(&pva->chunk_pool_lock);
|
||||||
|
ASSERT(err == PVA_SUCCESS);
|
||||||
post_fence.resource_id = pva->submit_memory_resource_id;
|
post_fence.resource_id = pva->submit_memory_resource_id;
|
||||||
post_fence.offset_lo = iova_lo(pva->fence_offset);
|
post_fence.offset_lo = iova_lo(pva->fence_offset);
|
||||||
post_fence.offset_hi = iova_hi(pva->fence_offset);
|
post_fence.offset_hi = iova_hi(pva->fence_offset);
|
||||||
@@ -153,7 +158,8 @@ static void pva_kmd_device_init_submission(struct pva_kmd_device *pva)
|
|||||||
pva_kmd_submitter_init(
|
pva_kmd_submitter_init(
|
||||||
&pva->submitter, &pva->dev_queue, &pva->submit_lock,
|
&pva->submitter, &pva->dev_queue, &pva->submit_lock,
|
||||||
&pva->chunk_pool, &pva->chunk_pool_lock,
|
&pva->chunk_pool, &pva->chunk_pool_lock,
|
||||||
pva_offset_pointer(pva->submit_memory->va, pva->fence_offset),
|
(uint32_t *)pva_offset_pointer(pva->submit_memory->va,
|
||||||
|
pva->fence_offset),
|
||||||
&post_fence);
|
&post_fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,14 +178,14 @@ static void pva_kmd_device_deinit_submission(struct pva_kmd_device *pva)
|
|||||||
struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
||||||
uint32_t device_index,
|
uint32_t device_index,
|
||||||
bool app_authenticate,
|
bool app_authenticate,
|
||||||
bool test_mode)
|
bool test_mode, void *plat_data)
|
||||||
{
|
{
|
||||||
struct pva_kmd_device *pva;
|
struct pva_kmd_device *pva;
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
if (test_mode) {
|
if (test_mode) {
|
||||||
pva_kmd_log_err("Test mode is enabled");
|
pva_kmd_log_info("Test mode is enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
pva = pva_kmd_zalloc_nofail(sizeof(*pva));
|
pva = pva_kmd_zalloc_nofail(sizeof(*pva));
|
||||||
@@ -189,18 +195,23 @@ struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
|||||||
pva->load_from_gsc = false;
|
pva->load_from_gsc = false;
|
||||||
pva->is_hv_mode = true;
|
pva->is_hv_mode = true;
|
||||||
pva->max_n_contexts = PVA_MAX_NUM_USER_CONTEXTS;
|
pva->max_n_contexts = PVA_MAX_NUM_USER_CONTEXTS;
|
||||||
pva_kmd_mutex_init(&pva->powercycle_lock);
|
err = pva_kmd_mutex_init(&pva->powercycle_lock);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_device_init powercycle_lock init failed");
|
||||||
|
pva_kmd_free(pva);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pva_kmd_sema_init(&pva->fw_boot_sema, 0);
|
pva_kmd_sema_init(&pva->fw_boot_sema, 0);
|
||||||
size = safe_mulu32((uint32_t)sizeof(struct pva_kmd_context),
|
size = safe_mulu32((uint32_t)sizeof(struct pva_kmd_context),
|
||||||
pva->max_n_contexts);
|
pva->max_n_contexts);
|
||||||
pva->context_mem = pva_kmd_zalloc(size);
|
pva->context_mem = pva_kmd_zalloc(size);
|
||||||
ASSERT(pva->context_mem != NULL);
|
ASSERT(pva->context_mem != NULL);
|
||||||
|
|
||||||
err = pva_kmd_block_allocator_init(&pva->context_allocator,
|
err = pva_kmd_block_allocator_init(
|
||||||
pva->context_mem,
|
&pva->context_allocator, pva->context_mem,
|
||||||
PVA_KMD_USER_CONTEXT_ID_BASE,
|
PVA_KMD_USER_CONTEXT_ID_BASE,
|
||||||
sizeof(struct pva_kmd_context),
|
(uint32_t)sizeof(struct pva_kmd_context), pva->max_n_contexts);
|
||||||
pva->max_n_contexts);
|
|
||||||
ASSERT(err == PVA_SUCCESS);
|
ASSERT(err == PVA_SUCCESS);
|
||||||
|
|
||||||
if (chip_id == PVA_CHIP_T23X) {
|
if (chip_id == PVA_CHIP_T23X) {
|
||||||
@@ -211,6 +222,8 @@ struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
|||||||
FAULT("SOC not supported");
|
FAULT("SOC not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set platform data before calling platform init */
|
||||||
|
pva->plat_data = plat_data;
|
||||||
pva_kmd_device_plat_init(pva);
|
pva_kmd_device_plat_init(pva);
|
||||||
|
|
||||||
pva_kmd_device_init_submission(pva);
|
pva_kmd_device_init_submission(pva);
|
||||||
@@ -236,7 +249,7 @@ static void pva_kmd_wait_for_active_contexts(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
ctx = pva_kmd_alloc_block(&pva->context_allocator, &unused_id);
|
ctx = pva_kmd_alloc_block(&pva->context_allocator, &unused_id);
|
||||||
if (ctx != NULL) {
|
if (ctx != NULL) {
|
||||||
allocated = safe_addu32(allocated, 1U);
|
allocated = safe_addu8(allocated, 1U);
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_sleep_us(1000);
|
pva_kmd_sleep_us(1000);
|
||||||
}
|
}
|
||||||
@@ -256,29 +269,48 @@ void pva_kmd_device_destroy(struct pva_kmd_device *pva)
|
|||||||
pva_kmd_free(pva);
|
pva_kmd_free(pva);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
|
enum pva_error pva_kmd_notify_fw_set_profiling_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t level)
|
||||||
|
{
|
||||||
|
struct pva_cmd_set_profiling_level cmd = { 0 };
|
||||||
|
pva_kmd_set_cmd_set_profiling_level(&cmd, level);
|
||||||
|
|
||||||
|
return pva_kmd_submit_cmd_sync(&pva->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static enum pva_error config_fw_by_cmds(struct pva_kmd_device *pva)
|
static enum pva_error config_fw_by_cmds(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
#if PVA_ENABLE_FW_PROFILING == 1
|
||||||
err = pva_kmd_notify_fw_enable_profiling(pva);
|
err = pva_kmd_notify_fw_enable_profiling(pva);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto err_out;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PVA_ENABLE_FW_TRACEPOINTS == 1
|
||||||
/* Set FW trace level */
|
/* Set FW trace level */
|
||||||
err = pva_kmd_notify_fw_set_trace_level(pva, pva->fw_trace_level);
|
err = pva_kmd_notify_fw_set_trace_level(pva, pva->fw_trace_level);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto err_out;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
// If the user had set profiling level before power-on, send the update to FW
|
// If the user had set profiling level before power-on, send the update to FW
|
||||||
err = pva_kmd_notify_fw_set_profiling_level(
|
err = pva_kmd_notify_fw_set_profiling_level(
|
||||||
pva, pva->debugfs_context.profiling_level);
|
pva, pva->debugfs_context.profiling_level);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto err_out;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
err_out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,8 +328,8 @@ static void pva_kmd_print_version_info(struct pva_kmd_device *pva)
|
|||||||
/* Query and print firmware version */
|
/* Query and print firmware version */
|
||||||
const char *prefix = "PVA FW version: ";
|
const char *prefix = "PVA FW version: ";
|
||||||
const char *kmd_prefix = "PVA KMD version: ";
|
const char *kmd_prefix = "PVA KMD version: ";
|
||||||
uint32_t prefix_len = strlen(prefix);
|
uint32_t prefix_len = (uint32_t)strlen(prefix);
|
||||||
uint32_t kmd_prefix_len = strlen(kmd_prefix);
|
uint32_t kmd_prefix_len = (uint32_t)strlen(kmd_prefix);
|
||||||
/* Store initial string */
|
/* Store initial string */
|
||||||
(void)memcpy(fw_version, prefix, prefix_len);
|
(void)memcpy(fw_version, prefix, prefix_len);
|
||||||
|
|
||||||
@@ -306,7 +338,7 @@ static void pva_kmd_print_version_info(struct pva_kmd_device *pva)
|
|||||||
safe_subu32(PVA_VERSION_BUFFER_SIZE,
|
safe_subu32(PVA_VERSION_BUFFER_SIZE,
|
||||||
prefix_len));
|
prefix_len));
|
||||||
if (err == PVA_SUCCESS) {
|
if (err == PVA_SUCCESS) {
|
||||||
pva_kmd_log_err(fw_version);
|
pva_kmd_log_info(fw_version);
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_log_err("Failed to query firmware version");
|
pva_kmd_log_err("Failed to query firmware version");
|
||||||
}
|
}
|
||||||
@@ -316,7 +348,7 @@ static void pva_kmd_print_version_info(struct pva_kmd_device *pva)
|
|||||||
(void)memcpy(kmd_version + kmd_prefix_len, PVA_SYSSW_COMMIT_ID,
|
(void)memcpy(kmd_version + kmd_prefix_len, PVA_SYSSW_COMMIT_ID,
|
||||||
sizeof(PVA_SYSSW_COMMIT_ID));
|
sizeof(PVA_SYSSW_COMMIT_ID));
|
||||||
kmd_version[kmd_prefix_len + sizeof(PVA_SYSSW_COMMIT_ID)] = '\0';
|
kmd_version[kmd_prefix_len + sizeof(PVA_SYSSW_COMMIT_ID)] = '\0';
|
||||||
pva_kmd_log_err(kmd_version);
|
pva_kmd_log_info(kmd_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum pva_error pva_kmd_config_fw_after_boot(struct pva_kmd_device *pva)
|
static enum pva_error pva_kmd_config_fw_after_boot(struct pva_kmd_device *pva)
|
||||||
@@ -331,7 +363,7 @@ static enum pva_error pva_kmd_config_fw_after_boot(struct pva_kmd_device *pva)
|
|||||||
pva_kmd_send_queue_info_by_ccq(pva, &pva->dev_queue);
|
pva_kmd_send_queue_info_by_ccq(pva, &pva->dev_queue);
|
||||||
|
|
||||||
err = pva_kmd_shared_buffer_init(pva, PVA_PRIV_CCQ_ID,
|
err = pva_kmd_shared_buffer_init(pva, PVA_PRIV_CCQ_ID,
|
||||||
PVA_KMD_FW_BUF_ELEMENT_SIZE,
|
(uint32_t)PVA_KMD_FW_BUF_ELEMENT_SIZE,
|
||||||
PVA_KMD_FW_PROFILING_BUF_NUM_ELEMENTS,
|
PVA_KMD_FW_PROFILING_BUF_NUM_ELEMENTS,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -386,10 +418,15 @@ void pva_kmd_add_deferred_context_free(struct pva_kmd_device *pva,
|
|||||||
|
|
||||||
static void free_deferred_contexts(struct pva_kmd_device *pva)
|
static void free_deferred_contexts(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
uint32_t n_deferred_context_free =
|
uint32_t n_deferred_context_free;
|
||||||
(uint32_t)pva_kmd_atomic_load(&pva->n_deferred_context_free);
|
uint32_t i;
|
||||||
|
int n_deferred;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < n_deferred_context_free; i++) {
|
n_deferred = pva_kmd_atomic_load(&pva->n_deferred_context_free);
|
||||||
|
ASSERT(n_deferred >= 0);
|
||||||
|
n_deferred_context_free = (uint32_t)n_deferred;
|
||||||
|
|
||||||
|
for (i = 0; i < n_deferred_context_free; i++) {
|
||||||
uint8_t ccq_id = pva->deferred_context_free_ids[i];
|
uint8_t ccq_id = pva->deferred_context_free_ids[i];
|
||||||
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, ccq_id);
|
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, ccq_id);
|
||||||
ASSERT(ctx != NULL);
|
ASSERT(ctx != NULL);
|
||||||
@@ -419,6 +456,7 @@ enum pva_error pva_kmd_deinit_fw(struct pva_kmd_device *pva)
|
|||||||
/* No longer in recovery state */
|
/* No longer in recovery state */
|
||||||
pva->recovery = false;
|
pva->recovery = false;
|
||||||
pva->fw_inited = false;
|
pva->fw_inited = false;
|
||||||
|
pva->fw_aborted = false;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,7 +469,7 @@ enum pva_error pva_kmd_query_fw_version(struct pva_kmd_device *pva,
|
|||||||
struct pva_cmd_get_version get_version_cmd = { 0 };
|
struct pva_cmd_get_version get_version_cmd = { 0 };
|
||||||
uint32_t version_buffer_size = PVA_VERSION_BUFFER_SIZE;
|
uint32_t version_buffer_size = PVA_VERSION_BUFFER_SIZE;
|
||||||
|
|
||||||
if (version_buffer == NULL || buffer_size <= 1) {
|
if (version_buffer == NULL || buffer_size <= 1U) {
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,14 +482,14 @@ enum pva_error pva_kmd_query_fw_version(struct pva_kmd_device *pva,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the buffer */
|
/* Clear the buffer */
|
||||||
memset(device_memory->va, 0, version_buffer_size);
|
(void)memset(device_memory->va, 0, version_buffer_size);
|
||||||
|
|
||||||
/* Set up the command */
|
/* Set up the command */
|
||||||
pva_kmd_set_cmd_get_version(&get_version_cmd, device_memory->iova);
|
pva_kmd_set_cmd_get_version(&get_version_cmd, device_memory->iova);
|
||||||
|
|
||||||
/* Submit the command synchronously */
|
/* Submit the command synchronously */
|
||||||
err = pva_kmd_submit_cmd_sync(&pva->submitter, &get_version_cmd,
|
err = pva_kmd_submit_cmd_sync(&pva->submitter, &get_version_cmd,
|
||||||
sizeof(get_version_cmd),
|
(uint32_t)sizeof(get_version_cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -460,8 +498,8 @@ enum pva_error pva_kmd_query_fw_version(struct pva_kmd_device *pva,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(void)memcpy(version_buffer, (char *)device_memory->va,
|
(void)memcpy(version_buffer, (char *)device_memory->va,
|
||||||
(buffer_size - 1));
|
(size_t)buffer_size - 1U);
|
||||||
version_buffer[buffer_size - 1] = '\0'; /* Ensure null termination */
|
version_buffer[buffer_size - 1U] = '\0'; /* Ensure null termination */
|
||||||
|
|
||||||
free_memory:
|
free_memory:
|
||||||
pva_kmd_device_memory_free(device_memory);
|
pva_kmd_device_memory_free(device_memory);
|
||||||
|
|||||||
@@ -14,193 +14,771 @@
|
|||||||
#include "pva_kmd_submitter.h"
|
#include "pva_kmd_submitter.h"
|
||||||
#include "pva_kmd_regs.h"
|
#include "pva_kmd_regs.h"
|
||||||
#include "pva_kmd_thread_sema.h"
|
#include "pva_kmd_thread_sema.h"
|
||||||
#include "pva_kmd_fw_debug.h"
|
|
||||||
#include "pva_kmd_shim_init.h"
|
#include "pva_kmd_shim_init.h"
|
||||||
#include "pva_kmd_shim_ccq.h"
|
#include "pva_kmd_shim_ccq.h"
|
||||||
#include "pva_kmd_fw_profiler.h"
|
#include "pva_kmd_fw_profiler.h"
|
||||||
#include "pva_kmd_fw_debug.h"
|
#include "pva_kmd_fw_debug_printf.h"
|
||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
#include "pva_kmd_debugfs.h"
|
#include "pva_kmd_debugfs.h"
|
||||||
#include "pva_kmd_co.h"
|
#include "pva_kmd_co.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class ID for PVA device 0
|
||||||
|
*
|
||||||
|
* @details This macro defines the unique class identifier used to identify
|
||||||
|
* the first PVA device (PVA0) in the system. The class ID is used by various
|
||||||
|
* hardware and software components to distinguish between different PVA
|
||||||
|
* instances and route operations to the correct device.
|
||||||
|
*/
|
||||||
#define NV_PVA0_CLASS_ID 0xF1
|
#define NV_PVA0_CLASS_ID 0xF1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class ID for PVA device 1
|
||||||
|
*
|
||||||
|
* @details This macro defines the unique class identifier used to identify
|
||||||
|
* the second PVA device (PVA1) in the system. The class ID is used by various
|
||||||
|
* hardware and software components to distinguish between different PVA
|
||||||
|
* instances and route operations to the correct device.
|
||||||
|
*/
|
||||||
#define NV_PVA1_CLASS_ID 0xF2
|
#define NV_PVA1_CLASS_ID 0xF2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure for syncpoint read/write information
|
||||||
|
*
|
||||||
|
* @details This structure contains information needed to access a specific
|
||||||
|
* syncpoint for read and write operations. It includes both the syncpoint
|
||||||
|
* identifier and its corresponding IOVA address for hardware access.
|
||||||
|
*/
|
||||||
struct pva_syncpt_rw_info {
|
struct pva_syncpt_rw_info {
|
||||||
|
/**
|
||||||
|
* @brief Syncpoint identifier
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t syncpt_id;
|
uint32_t syncpt_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief IOVA address of the syncpoint for hardware access
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t syncpt_iova;
|
uint64_t syncpt_iova;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A struct to maintain start and end address of vmem region */
|
/**
|
||||||
|
* @brief Structure to maintain start and end address of vmem region
|
||||||
|
*
|
||||||
|
* @details This structure defines a contiguous region of vector memory (VMEM)
|
||||||
|
* by specifying its start and end addresses. VMEM is the fast on-chip memory
|
||||||
|
* used by the VPU for storing data being actively processed.
|
||||||
|
*/
|
||||||
struct vmem_region {
|
struct vmem_region {
|
||||||
/**! Start address of vmem region */
|
/**
|
||||||
|
* @brief Start address of vmem region
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t start;
|
uint32_t start;
|
||||||
/**! End address of vmem region */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of vmem region
|
||||||
|
* Valid range: [start .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t end;
|
uint32_t end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure containing hardware-specific constants for PVA
|
||||||
|
*
|
||||||
|
* @details This structure holds various hardware configuration parameters
|
||||||
|
* that are specific to different PVA hardware generations. These constants
|
||||||
|
* are used throughout the KMD to adapt behavior based on the underlying
|
||||||
|
* hardware capabilities and limitations.
|
||||||
|
*/
|
||||||
struct pva_kmd_hw_constants {
|
struct pva_kmd_hw_constants {
|
||||||
|
/**
|
||||||
|
* @brief PVA hardware generation identifier
|
||||||
|
* Valid values: @ref pva_hw_gen enumeration values
|
||||||
|
*/
|
||||||
enum pva_hw_gen hw_gen;
|
enum pva_hw_gen hw_gen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of VMEM regions available
|
||||||
|
* Valid range: [0 .. UINT8_MAX]
|
||||||
|
*/
|
||||||
uint8_t n_vmem_regions;
|
uint8_t n_vmem_regions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of DMA descriptors available
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_dma_descriptors;
|
uint32_t n_dma_descriptors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of user-accessible DMA channels
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_user_dma_channels;
|
uint32_t n_user_dma_channels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of hardware sequencer words
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_hwseq_words;
|
uint32_t n_hwseq_words;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of dynamic ADB buffers
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_dynamic_adb_buffs;
|
uint32_t n_dynamic_adb_buffs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of SMMU contexts available
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_smmu_contexts;
|
uint32_t n_smmu_contexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pva_kmd_pfsd_info {
|
||||||
|
const uint8_t *vpu_elf_data;
|
||||||
|
uint32_t vpu_elf_size;
|
||||||
|
const uint8_t *ppe_elf_data;
|
||||||
|
uint32_t ppe_elf_size;
|
||||||
|
struct pva_dma_config pfsd_dma_cfg;
|
||||||
|
enum pva_error (*register_cmd_buffer)(struct pva_kmd_context *ctx);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This struct manages a single PVA cluster.
|
* @brief This struct manages a single PVA cluster.
|
||||||
*
|
*
|
||||||
* Fields in this struct should be common across all platforms. Platform
|
* @details Fields in this struct should be common across all platforms. Platform
|
||||||
* specific data is stored in plat_data field.
|
* specific data is stored in plat_data field. This structure represents the
|
||||||
|
* complete state of a PVA device instance and contains all the resources,
|
||||||
|
* configuration, and runtime state needed to manage the device.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_device {
|
struct pva_kmd_device {
|
||||||
|
/**
|
||||||
|
* @brief Device index identifying this PVA instance
|
||||||
|
* Valid range: [0 .. PVA_MAX_DEVICES-1]
|
||||||
|
*/
|
||||||
uint32_t device_index;
|
uint32_t device_index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SMMU context ID for R5 firmware image
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t r5_image_smmu_context_id;
|
uint32_t r5_image_smmu_context_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of stream IDs for SMMU contexts
|
||||||
|
* Valid range: Each element [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t stream_ids[PVA_MAX_NUM_SMMU_CONTEXTS];
|
uint32_t stream_ids[PVA_MAX_NUM_SMMU_CONTEXTS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Hardware constants specific to this PVA instance
|
||||||
|
*/
|
||||||
struct pva_kmd_hw_constants hw_consts;
|
struct pva_kmd_hw_constants hw_consts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Physical base addresses for device register apertures
|
||||||
|
* Valid range: Each element [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t reg_phy_base[PVA_KMD_APERTURE_COUNT];
|
uint64_t reg_phy_base[PVA_KMD_APERTURE_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sizes of device register apertures
|
||||||
|
* Valid range: Each element [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t reg_size[PVA_KMD_APERTURE_COUNT];
|
uint64_t reg_size[PVA_KMD_APERTURE_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register specification structure for device access
|
||||||
|
*/
|
||||||
struct pva_kmd_regspec regspec;
|
struct pva_kmd_regspec regspec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of contexts supported by this device
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_USER_CONTEXTS]
|
||||||
|
*/
|
||||||
uint8_t max_n_contexts;
|
uint8_t max_n_contexts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to allocated memory for context storage
|
||||||
|
* Valid value: non-null when contexts are allocated
|
||||||
|
*/
|
||||||
void *context_mem;
|
void *context_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing context allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator context_allocator;
|
struct pva_kmd_block_allocator context_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device-level resource table for privileged operations
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_table dev_resource_table;
|
struct pva_kmd_resource_table dev_resource_table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Command submission handler for device-level operations
|
||||||
|
*/
|
||||||
struct pva_kmd_submitter submitter;
|
struct pva_kmd_submitter submitter;
|
||||||
/** The lock protects the submission to the queue, including
|
|
||||||
* incrementing the post fence */
|
/**
|
||||||
|
* @brief Lock protecting submission operations and post fence increment
|
||||||
|
*
|
||||||
|
* @details The lock protects the submission to the queue, including
|
||||||
|
* incrementing the post fence
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t submit_lock;
|
pva_kmd_mutex_t submit_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for queue operations
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *queue_memory;
|
struct pva_kmd_device_memory *queue_memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device-level command queue
|
||||||
|
*/
|
||||||
struct pva_kmd_queue dev_queue;
|
struct pva_kmd_queue dev_queue;
|
||||||
|
|
||||||
/** memory needed for submission: including command buffer chunks and fences */
|
/**
|
||||||
|
* @brief Memory allocation for submission operations
|
||||||
|
*
|
||||||
|
* @details Memory needed for submission: including command buffer chunks and fences
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *submit_memory;
|
struct pva_kmd_device_memory *submit_memory;
|
||||||
uint32_t submit_memory_resource_id;
|
|
||||||
uint64_t fence_offset; /**< fence offset within submit_memory*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource ID for submission memory in resource table
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
|
uint32_t submit_memory_resource_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Offset of fence within submission memory
|
||||||
|
* Valid range: [0 .. submit_memory_size-1]
|
||||||
|
*/
|
||||||
|
uint64_t fence_offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock protecting command buffer chunk pool operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t chunk_pool_lock;
|
pva_kmd_mutex_t chunk_pool_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pool of command buffer chunks for efficient allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_cmdbuf_chunk_pool chunk_pool;
|
struct pva_kmd_cmdbuf_chunk_pool chunk_pool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock protecting power cycle operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t powercycle_lock;
|
pva_kmd_mutex_t powercycle_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reference count for device usage tracking
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t refcount;
|
uint32_t refcount;
|
||||||
|
|
||||||
/** ISR post this semaphore when FW completes boot */
|
/**
|
||||||
|
* @brief Semaphore posted by ISR when FW completes boot
|
||||||
|
*
|
||||||
|
* @details ISR post this semaphore when FW completes boot
|
||||||
|
*/
|
||||||
pva_kmd_sema_t fw_boot_sema;
|
pva_kmd_sema_t fw_boot_sema;
|
||||||
bool recovery;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if device is in recovery mode
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
|
bool recovery;
|
||||||
|
/** Firmware is aborted and won't respond */
|
||||||
|
bool fw_aborted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for firmware debug information
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *fw_debug_mem;
|
struct pva_kmd_device_memory *fw_debug_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for firmware binary
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *fw_bin_mem;
|
struct pva_kmd_device_memory *fw_bin_mem;
|
||||||
|
|
||||||
// 'kmd_fw_buffers' holds DRAM buffers shared between KMD and FW
|
/**
|
||||||
// - Today, we have 1 buffer per CCQ. This may need to be extended in future
|
* @brief DRAM buffers shared between KMD and FW
|
||||||
// to support buffered communication through mailbox
|
*
|
||||||
// - Buffers will be used for the following purposes
|
* @details 'kmd_fw_buffers' holds DRAM buffers shared between KMD and FW
|
||||||
// - CCQ 0: Communications common to a VM
|
* - Today, we have 1 buffer per CCQ. This may need to be extended in future
|
||||||
// -- example, FW profiling data and NSIGHT data
|
* to support buffered communication through mailbox
|
||||||
// - CCQ 1-8: Communications specific to each context
|
* - Buffers will be used for the following purposes
|
||||||
// -- example, resource unregistration requests
|
* - CCQ 0: Communications common to a VM
|
||||||
// In the future, we may want to extend this to support communications between
|
* -- example, FW profiling data and NSIGHT data
|
||||||
// FW and Hypervisor
|
* - CCQ 1-8: Communications specific to each context
|
||||||
|
* -- example, resource unregistration requests
|
||||||
|
* In the future, we may want to extend this to support communications between
|
||||||
|
* FW and Hypervisor
|
||||||
|
*/
|
||||||
struct pva_kmd_shared_buffer kmd_fw_buffers[PVA_MAX_NUM_CCQ];
|
struct pva_kmd_shared_buffer kmd_fw_buffers[PVA_MAX_NUM_CCQ];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Current firmware trace level setting
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t fw_trace_level;
|
uint32_t fw_trace_level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Buffer for firmware print/debug output
|
||||||
|
*/
|
||||||
struct pva_kmd_fw_print_buffer fw_print_buffer;
|
struct pva_kmd_fw_print_buffer fw_print_buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for Tegra statistics collection
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *tegra_stats_memory;
|
struct pva_kmd_device_memory *tegra_stats_memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource ID for Tegra statistics memory
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t tegra_stats_resource_id;
|
uint32_t tegra_stats_resource_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of Tegra statistics buffer
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t tegra_stats_buf_size;
|
uint32_t tegra_stats_buf_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if firmware should be loaded from GSC
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool load_from_gsc;
|
bool load_from_gsc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if device is running in hypervisor mode
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool is_hv_mode;
|
bool is_hv_mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if device is running on silicon hardware
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool is_silicon;
|
bool is_silicon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Debug filesystem context for development and debugging
|
||||||
|
*/
|
||||||
struct pva_kmd_debugfs_context debugfs_context;
|
struct pva_kmd_debugfs_context debugfs_context;
|
||||||
/** Sector packing format for block linear surfaces */
|
|
||||||
|
/**
|
||||||
|
* @brief Sector packing format for block linear surfaces
|
||||||
|
* Valid range: [0 .. UINT8_MAX]
|
||||||
|
*/
|
||||||
uint8_t bl_sector_pack_format;
|
uint8_t bl_sector_pack_format;
|
||||||
|
|
||||||
/** Offset between 2 syncpoints */
|
/**
|
||||||
|
* @brief Size offset between consecutive syncpoints
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t syncpt_page_size;
|
uint32_t syncpt_page_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base IOVA for read-only syncpoints
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t ro_syncpt_base_iova;
|
uint64_t ro_syncpt_base_iova;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of read-only syncpoints available
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t num_ro_syncpts;
|
uint32_t num_ro_syncpts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base IOVA for read-write syncpoints
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t rw_syncpt_base_iova;
|
uint64_t rw_syncpt_base_iova;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of read-write syncpoint region
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t rw_syncpt_region_size;
|
uint32_t rw_syncpt_region_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of read-write syncpoint information
|
||||||
|
*/
|
||||||
struct pva_syncpt_rw_info rw_syncpts[PVA_NUM_RW_SYNCPTS];
|
struct pva_syncpt_rw_info rw_syncpts[PVA_NUM_RW_SYNCPTS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to table of VMEM region definitions
|
||||||
|
*/
|
||||||
struct vmem_region *vmem_regions_tab;
|
struct vmem_region *vmem_regions_tab;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating support for hardware sequencer frame linking
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool support_hwseq_frame_linking;
|
bool support_hwseq_frame_linking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Platform-specific private data pointer
|
||||||
|
*/
|
||||||
void *plat_data;
|
void *plat_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to VPU authentication context
|
||||||
|
*/
|
||||||
struct pva_vpu_auth *pva_auth;
|
struct pva_vpu_auth *pva_auth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if firmware has been initialized
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool fw_inited;
|
bool fw_inited;
|
||||||
|
|
||||||
/** Carveout info for FW */
|
/**
|
||||||
|
* @brief Carveout memory information for firmware
|
||||||
|
*/
|
||||||
struct pva_co_info fw_carveout;
|
struct pva_co_info fw_carveout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if device is in test mode
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool test_mode;
|
bool test_mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Atomic counter for deferred context free operations
|
||||||
|
*/
|
||||||
pva_kmd_atomic_t n_deferred_context_free;
|
pva_kmd_atomic_t n_deferred_context_free;
|
||||||
uint32_t deferred_context_free_ids[PVA_MAX_NUM_USER_CONTEXTS];
|
|
||||||
|
|
||||||
uint64_t tsc_to_ns_multiplier; /**< TSC to nanoseconds multiplier */
|
/**
|
||||||
|
* @brief Array of context IDs pending deferred free
|
||||||
|
*/
|
||||||
|
uint8_t deferred_context_free_ids[PVA_MAX_NUM_USER_CONTEXTS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Multiplier to convert TSC ticks to nanoseconds
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
|
uint64_t tsc_to_ns_multiplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PFSD information
|
||||||
|
*/
|
||||||
|
struct pva_kmd_pfsd_info pfsd_info;
|
||||||
|
|
||||||
|
#if PVA_ENABLE_R5_OCD == 1
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating if R5 on-chip debugging is enabled
|
||||||
|
* Valid values: true, false
|
||||||
|
*/
|
||||||
bool r5_ocd_on;
|
bool r5_ocd_on;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create and initialize a new PVA KMD device instance
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates memory for a new @ref pva_kmd_device structure
|
||||||
|
* - Initializes the device based on the specified chip ID and configuration
|
||||||
|
* - Sets up hardware constants and register mappings for the device
|
||||||
|
* - Configures authentication settings based on the app_authenticate parameter
|
||||||
|
* - Initializes internal data structures including resource tables, queues,
|
||||||
|
* and memory allocators
|
||||||
|
* - Sets up platform-specific components using @ref pva_kmd_device_plat_init()
|
||||||
|
* - Configures test mode settings if requested
|
||||||
|
* - Prepares the device for firmware loading and initialization
|
||||||
|
*
|
||||||
|
* The created device must be destroyed using @ref pva_kmd_device_destroy()
|
||||||
|
* when no longer needed to prevent resource leaks. The device will be in
|
||||||
|
* an uninitialized state until @ref pva_kmd_init_fw() is called.
|
||||||
|
*
|
||||||
|
* @param[in] chip_id Chip identifier specifying the target hardware
|
||||||
|
* Valid values: @ref pva_chip_id enumeration values
|
||||||
|
* @param[in] device_index Index of the PVA device instance to create
|
||||||
|
* Valid range: [0 .. PVA_MAX_DEVICES-1]
|
||||||
|
* @param[in] app_authenticate Flag to enable application authentication
|
||||||
|
* Valid values: true, false
|
||||||
|
* @param[in] test_mode Flag to enable test mode configuration
|
||||||
|
* Valid values: true, false
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to successfully created @ref pva_kmd_device
|
||||||
|
* @retval NULL Device creation failed due to memory allocation failure,
|
||||||
|
* invalid parameters, or platform initialization failure
|
||||||
|
*/
|
||||||
struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
struct pva_kmd_device *pva_kmd_device_create(enum pva_chip_id chip_id,
|
||||||
uint32_t device_index,
|
uint32_t device_index,
|
||||||
bool app_authenticate,
|
bool app_authenticate,
|
||||||
bool test_mode);
|
bool test_mode, void *plat_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy a PVA KMD device instance and free all resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Deinitializes the firmware using @ref pva_kmd_deinit_fw() if initialized
|
||||||
|
* - Stops and cleans up all active contexts and their associated resources
|
||||||
|
* - Frees all allocated device memory including command buffers, queues,
|
||||||
|
* and shared buffers
|
||||||
|
* - Releases hardware resources and register mappings
|
||||||
|
* - Cleans up platform-specific resources through platform callbacks
|
||||||
|
* - Destroys synchronization primitives including mutexes and semaphores
|
||||||
|
* - Frees the device structure itself
|
||||||
|
*
|
||||||
|
* After calling this function, the device pointer becomes invalid and must
|
||||||
|
* not be used. Any ongoing operations on the device should be completed
|
||||||
|
* or cancelled before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure to destroy
|
||||||
|
* Valid value: non-null, must be a valid device created by
|
||||||
|
* @ref pva_kmd_device_create()
|
||||||
|
*/
|
||||||
void pva_kmd_device_destroy(struct pva_kmd_device *pva);
|
void pva_kmd_device_destroy(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a context ID to the deferred free list
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Atomically increments the count of deferred context free operations
|
||||||
|
* - Adds the specified CCQ ID to the deferred context free array
|
||||||
|
* - Ensures thread-safe access to the deferred free list
|
||||||
|
* - Marks the context for cleanup during the next power cycle
|
||||||
|
*
|
||||||
|
* This function is used when a context cannot be freed immediately,
|
||||||
|
* typically because the firmware is still processing commands for that
|
||||||
|
* context. The context will be freed when the device is next powered off
|
||||||
|
* and reinitialized.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] ccq_id CCQ ID of the context to defer free
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*/
|
||||||
void pva_kmd_add_deferred_context_free(struct pva_kmd_device *pva,
|
void pva_kmd_add_deferred_context_free(struct pva_kmd_device *pva,
|
||||||
uint8_t ccq_id);
|
uint8_t ccq_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize firmware on the PVA device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Loads the firmware binary into device memory using platform-specific loaders
|
||||||
|
* - Sets up firmware execution environment including memory mappings
|
||||||
|
* - Initializes communication channels between KMD and firmware
|
||||||
|
* - Configures hardware resources needed by the firmware
|
||||||
|
* - Starts the firmware execution and waits for boot completion
|
||||||
|
* - Sets up shared buffers for KMD-FW communication
|
||||||
|
* - Initializes firmware debug and profiling capabilities
|
||||||
|
* - Establishes resource tables for hardware resource management
|
||||||
|
*
|
||||||
|
* The device must be created using @ref pva_kmd_device_create() before
|
||||||
|
* calling this function. After successful initialization, the device is
|
||||||
|
* ready to accept and process user commands.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Firmware initialized successfully
|
||||||
|
* @retval PVA_TIMEDOUT Firmware boot timeout occurred
|
||||||
|
* @retval PVA_NOMEM Memory allocation for FW resources failed
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Firmware operation aborted during recovery
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_init_fw(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_init_fw(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize firmware and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Stops firmware execution and waits for graceful shutdown
|
||||||
|
* - Frees all firmware-related memory allocations
|
||||||
|
* - Cleans up communication channels and shared buffers
|
||||||
|
* - Releases hardware resources allocated to firmware
|
||||||
|
* - Deinitializes debug and profiling subsystems
|
||||||
|
* - Resets device hardware to a known state
|
||||||
|
* - Marks the device as uninitialized for future use
|
||||||
|
*
|
||||||
|
* After calling this function, the device can be reinitialized using
|
||||||
|
* @ref pva_kmd_init_fw() or destroyed using @ref pva_kmd_device_destroy().
|
||||||
|
* Any ongoing operations should be completed before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Firmware deinitialized successfully
|
||||||
|
* @retval PVA_INTERNAL Failed to properly deinitialize firmware
|
||||||
|
* @retval PVA_TIMEDOUT Firmware shutdown timeout occurred
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_deinit_fw(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_deinit_fw(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the PVA device might be powered on
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Checks device power state indicators to determine if device is active
|
||||||
|
* - Reads hardware registers to verify device accessibility
|
||||||
|
* - Uses platform-specific power management information if available
|
||||||
|
* - Returns a best-effort assessment of device power state
|
||||||
|
* - Does not guarantee definitive power state due to timing considerations
|
||||||
|
*
|
||||||
|
* This function provides a quick check for device availability without
|
||||||
|
* performing operations that might cause side effects. The result should
|
||||||
|
* be treated as a hint rather than a definitive power state.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval true Device appears to be powered on and accessible
|
||||||
|
* @retval false Device appears to be powered off or inaccessible
|
||||||
|
*/
|
||||||
bool pva_kmd_device_maybe_on(struct pva_kmd_device *pva);
|
bool pva_kmd_device_maybe_on(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Query the firmware version string from the device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Sends a version query command to the firmware
|
||||||
|
* - Waits for the firmware response containing version information
|
||||||
|
* - Copies the version string to the provided buffer
|
||||||
|
* - Ensures null-termination of the version string
|
||||||
|
* - Handles buffer size limitations gracefully
|
||||||
|
* - Returns error if firmware is not responsive or accessible
|
||||||
|
*
|
||||||
|
* The version information includes firmware build details, version numbers,
|
||||||
|
* and other identification data useful for debugging and compatibility
|
||||||
|
* checking. The device must be initialized before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] version_buffer Buffer to store the firmware version string
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] buffer_size Size of the version buffer in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Version retrieved successfully
|
||||||
|
* @retval PVA_INVAL Invalid buffer pointer or buffer size <= 1
|
||||||
|
* @retval PVA_NOMEM Failed to allocate device memory for version query
|
||||||
|
* @retval PVA_TIMEDOUT Firmware did not respond within timeout
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Firmware operation aborted during recovery
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_query_fw_version(struct pva_kmd_device *pva,
|
enum pva_error pva_kmd_query_fw_version(struct pva_kmd_device *pva,
|
||||||
char *version_buffer,
|
char *version_buffer,
|
||||||
uint32_t buffer_size);
|
uint32_t buffer_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the device class ID for the specified PVA device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Examines the device index to determine which PVA instance this represents
|
||||||
|
* - Returns the appropriate class ID for device identification
|
||||||
|
* - Maps device index 0 to @ref NV_PVA0_CLASS_ID
|
||||||
|
* - Maps device index 1 to @ref NV_PVA1_CLASS_ID
|
||||||
|
* - Provides consistent class ID mapping for hardware identification
|
||||||
|
*
|
||||||
|
* The class ID is used by various hardware and software components to
|
||||||
|
* route operations to the correct PVA device instance in multi-device
|
||||||
|
* systems.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval NV_PVA0_CLASS_ID If device index is 0
|
||||||
|
* @retval NV_PVA1_CLASS_ID If device index is 1 or any other value
|
||||||
|
*/
|
||||||
static inline uint32_t pva_kmd_get_device_class_id(struct pva_kmd_device *pva)
|
static inline uint32_t pva_kmd_get_device_class_id(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
if (pva->device_index == 0) {
|
if (pva->device_index == 0U) {
|
||||||
return NV_PVA0_CLASS_ID;
|
return NV_PVA0_CLASS_ID;
|
||||||
} else {
|
} else {
|
||||||
return NV_PVA1_CLASS_ID;
|
return NV_PVA1_CLASS_ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the maximum command buffer chunk size for the device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Checks if the device is configured for test mode operation
|
||||||
|
* - Returns @ref PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE for test mode
|
||||||
|
* - Returns @ref PVA_MAX_CMDBUF_CHUNK_SIZE for normal operation
|
||||||
|
* - Provides appropriate chunk size limits based on device configuration
|
||||||
|
*
|
||||||
|
* The chunk size determines the maximum size of individual command buffer
|
||||||
|
* segments that can be processed by the firmware. Test mode may use smaller
|
||||||
|
* chunks for validation and debugging purposes.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE If device is in test mode
|
||||||
|
* @retval PVA_MAX_CMDBUF_CHUNK_SIZE If device is in normal mode
|
||||||
|
*/
|
||||||
static inline uint16_t
|
static inline uint16_t
|
||||||
pva_kmd_get_max_cmdbuf_chunk_size(struct pva_kmd_device *pva)
|
pva_kmd_get_max_cmdbuf_chunk_size(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
uint16_t max_chunk_size = (uint16_t)PVA_MAX_CMDBUF_CHUNK_SIZE;
|
||||||
|
#if SYSTEM_TESTS_ENABLED == 1
|
||||||
if (pva->test_mode) {
|
if (pva->test_mode) {
|
||||||
return PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE;
|
max_chunk_size = (uint16_t)PVA_TEST_MODE_MAX_CMDBUF_CHUNK_SIZE;
|
||||||
} else {
|
|
||||||
return PVA_MAX_CMDBUF_CHUNK_SIZE;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return max_chunk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert TSC (Time Stamp Counter) value to nanoseconds
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Multiplies the TSC value by the device-specific conversion multiplier
|
||||||
|
* - Uses @ref safe_mulu64() to prevent overflow during multiplication
|
||||||
|
* - Returns the equivalent time value in nanoseconds
|
||||||
|
* - Provides high-precision timing conversion for performance measurement
|
||||||
|
*
|
||||||
|
* The TSC is a hardware counter that increments at a fixed frequency.
|
||||||
|
* The conversion multiplier is calibrated based on the device's clock
|
||||||
|
* configuration to provide accurate nanosecond timing.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] tsc TSC value to convert
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*
|
||||||
|
* @retval converted_time TSC value converted to nanoseconds
|
||||||
|
*/
|
||||||
static inline uint64_t pva_kmd_tsc_to_ns(struct pva_kmd_device *pva,
|
static inline uint64_t pva_kmd_tsc_to_ns(struct pva_kmd_device *pva,
|
||||||
uint64_t tsc)
|
uint64_t tsc)
|
||||||
{
|
{
|
||||||
// Convert TSC to nanoseconds using the multiplier
|
// Convert TSC to nanoseconds using the multiplier
|
||||||
return safe_mulu64(tsc, pva->tsc_to_ns_multiplier);
|
return safe_mulu64(tsc, pva->tsc_to_ns_multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert TSC (Time Stamp Counter) value to microseconds
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Converts the TSC value to nanoseconds using @ref safe_mulu64()
|
||||||
|
* - Divides the nanosecond result by 1000 to get microseconds
|
||||||
|
* - Returns the equivalent time value in microseconds
|
||||||
|
* - Provides medium-precision timing conversion for performance measurement
|
||||||
|
*
|
||||||
|
* The TSC is a hardware counter that increments at a fixed frequency.
|
||||||
|
* This function combines nanosecond conversion with division to provide
|
||||||
|
* microsecond precision timing suitable for most timing measurements.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] tsc TSC value to convert
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*
|
||||||
|
* @retval converted_time TSC value converted to microseconds
|
||||||
|
*/
|
||||||
static inline uint64_t pva_kmd_tsc_to_us(struct pva_kmd_device *pva,
|
static inline uint64_t pva_kmd_tsc_to_us(struct pva_kmd_device *pva,
|
||||||
uint64_t tsc)
|
uint64_t tsc)
|
||||||
{
|
{
|
||||||
// Convert TSC to microseconds using the multiplier
|
// Convert TSC to microseconds using the multiplier
|
||||||
return safe_mulu64(tsc, pva->tsc_to_ns_multiplier) / 1000;
|
return safe_mulu64(tsc, pva->tsc_to_ns_multiplier) / 1000U;
|
||||||
}
|
}
|
||||||
#endif // PVA_KMD_DEVICE_H
|
#endif // PVA_KMD_DEVICE_H
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
#include "pva_kmd_devmem_pool.h"
|
#include "pva_kmd_devmem_pool.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
#include "pva_api.h"
|
#include "pva_api.h"
|
||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
|
|
||||||
@@ -86,10 +88,11 @@ enum pva_error pva_kmd_devmem_pool_init(struct pva_kmd_devmem_pool *pool,
|
|||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
/* Initialize the pool structure */
|
/* Initialize the pool structure */
|
||||||
memset(pool, 0, sizeof(*pool));
|
(void)memset(pool, 0, sizeof(*pool));
|
||||||
pool->smmu_ctx_idx = smmu_ctx_idx;
|
pool->smmu_ctx_idx = smmu_ctx_idx;
|
||||||
pool->element_size =
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
safe_pow2_roundup_u32(element_size, sizeof(uint64_t));
|
pool->element_size = (uint32_t)safe_pow2_roundup_u32(
|
||||||
|
element_size, (uint32_t)sizeof(uint64_t));
|
||||||
pool->n_element_incr = ele_incr_count;
|
pool->n_element_incr = ele_incr_count;
|
||||||
pool->n_free_element = 0;
|
pool->n_free_element = 0;
|
||||||
pool->segment_list_head = NULL;
|
pool->segment_list_head = NULL;
|
||||||
@@ -121,13 +124,14 @@ pva_kmd_devmem_pool_alloc(struct pva_kmd_devmem_pool *pool,
|
|||||||
{
|
{
|
||||||
struct pva_kmd_devmem_pool_segment *segment = NULL;
|
struct pva_kmd_devmem_pool_segment *segment = NULL;
|
||||||
struct pva_kmd_devmem_pool_segment *new_segment = NULL;
|
struct pva_kmd_devmem_pool_segment *new_segment = NULL;
|
||||||
uint32_t ele_idx = (uint32_t)-1;
|
/* Use U32_MAX instead of casting -1 */
|
||||||
|
uint32_t ele_idx = U32_MAX;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&pool->pool_lock);
|
pva_kmd_mutex_lock(&pool->pool_lock);
|
||||||
|
|
||||||
/* Check if we have any free elements */
|
/* Check if we have any free elements */
|
||||||
if (pool->n_free_element == 0) {
|
if (pool->n_free_element == 0U) {
|
||||||
/* Need to allocate a new segment */
|
/* Need to allocate a new segment */
|
||||||
new_segment = allocate_segment(pool);
|
new_segment = allocate_segment(pool);
|
||||||
if (new_segment == NULL) {
|
if (new_segment == NULL) {
|
||||||
@@ -169,7 +173,7 @@ enum pva_error pva_kmd_devmem_pool_zalloc(struct pva_kmd_devmem_pool *pool,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(pva_kmd_get_devmem_va(devmem), 0, pool->element_size);
|
(void)memset(pva_kmd_get_devmem_va(devmem), 0, pool->element_size);
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,12 +220,14 @@ void pva_kmd_devmem_pool_free(struct pva_kmd_devmem_element *devmem)
|
|||||||
struct pva_kmd_devmem_pool *pool = devmem->segment->owner_pool;
|
struct pva_kmd_devmem_pool *pool = devmem->segment->owner_pool;
|
||||||
struct pva_kmd_devmem_pool_segment *current_segment = devmem->segment;
|
struct pva_kmd_devmem_pool_segment *current_segment = devmem->segment;
|
||||||
uint32_t threshold;
|
uint32_t threshold;
|
||||||
|
enum pva_error tmp_err;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&pool->pool_lock);
|
pva_kmd_mutex_lock(&pool->pool_lock);
|
||||||
|
|
||||||
/* Free the element */
|
/* Free the element */
|
||||||
pva_kmd_free_block_unsafe(¤t_segment->elem_allocator,
|
tmp_err = pva_kmd_free_block_unsafe(¤t_segment->elem_allocator,
|
||||||
devmem->ele_idx);
|
devmem->ele_idx);
|
||||||
|
ASSERT(tmp_err == PVA_SUCCESS);
|
||||||
pool->n_free_element = safe_addu32(pool->n_free_element, 1);
|
pool->n_free_element = safe_addu32(pool->n_free_element, 1);
|
||||||
current_segment->n_free_ele =
|
current_segment->n_free_ele =
|
||||||
safe_addu32(current_segment->n_free_ele, 1);
|
safe_addu32(current_segment->n_free_ele, 1);
|
||||||
|
|||||||
@@ -6,79 +6,189 @@
|
|||||||
#include "pva_kmd_block_allocator.h"
|
#include "pva_kmd_block_allocator.h"
|
||||||
#include "pva_kmd_device_memory.h"
|
#include "pva_kmd_device_memory.h"
|
||||||
|
|
||||||
/** @brief A segment of a device memory pool.
|
/**
|
||||||
|
* @brief A segment of a device memory pool
|
||||||
*
|
*
|
||||||
* It holds a fixed size array of device memory blocks. A pool is a linked list
|
* @details A segment holds a fixed size array of device memory blocks within
|
||||||
* of segments.
|
* a device memory pool. The pool is implemented as a linked list of segments,
|
||||||
|
* allowing dynamic expansion of the pool capacity as needed. Each segment
|
||||||
|
* manages its own allocation state and provides efficient block allocation
|
||||||
|
* and deallocation within the segment.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_devmem_pool_segment {
|
struct pva_kmd_devmem_pool_segment {
|
||||||
/** The owner pool. */
|
/**
|
||||||
|
* @brief Pointer to the owner pool
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_pool *owner_pool;
|
struct pva_kmd_devmem_pool *owner_pool;
|
||||||
/** The next segment in the pool. */
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the next segment in the pool linked list
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_pool_segment *next;
|
struct pva_kmd_devmem_pool_segment *next;
|
||||||
/** The device memory for the segment. */
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for this segment
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *mem;
|
struct pva_kmd_device_memory *mem;
|
||||||
/** The allocator for the elements in the segment. */
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing elements within this segment
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator elem_allocator;
|
struct pva_kmd_block_allocator elem_allocator;
|
||||||
/** The number of free elements in the segment. */
|
|
||||||
|
/**
|
||||||
|
* @brief Number of free elements currently available in this segment
|
||||||
|
* Valid range: [0 .. n_element_incr]
|
||||||
|
*/
|
||||||
uint32_t n_free_ele;
|
uint32_t n_free_ele;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief A device memory pool that holds fixed size elements.
|
/**
|
||||||
|
* @brief A device memory pool that manages fixed-size elements
|
||||||
*
|
*
|
||||||
* It allocates memory in segments, each segment contains n_element_incr
|
* @details A device memory pool that holds fixed size elements with automatic
|
||||||
* elements.
|
* capacity expansion. The pool allocates memory in segments, each segment
|
||||||
* - element_size will be rounded up to the nearest 8 bytes for alignment.
|
* containing n_element_incr elements. Key features include:
|
||||||
* - The pool is initialized with element_size * n_element_incr capacity.
|
* - element_size is rounded up to nearest 8 bytes for alignment
|
||||||
* - Once exhausted, the pool will allocate a new segment of memory and increase
|
* - Pool initialized with element_size * n_element_incr capacity
|
||||||
* the capacity by n_element_incr.
|
* - Automatic segment allocation when pool exhausted
|
||||||
* - When an element is freed, the pool does not immediately release the whole
|
* - Intelligent segment deallocation to maintain efficiency
|
||||||
* segment even if the whole segment is empty. However, if there are 2 *
|
* - Thread-safe operations with mutex protection
|
||||||
* n_element_incr free elements, the pool will release a whole segment, so
|
* - SMMU context-aware memory allocation
|
||||||
* that there's still at least n_element_incr free elements.
|
|
||||||
* - The pool is thread safe.
|
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_devmem_pool {
|
struct pva_kmd_devmem_pool {
|
||||||
/** The SMMU context index for the pool. */
|
/**
|
||||||
|
* @brief SMMU context index for memory allocation
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
*/
|
||||||
uint8_t smmu_ctx_idx;
|
uint8_t smmu_ctx_idx;
|
||||||
/** The size of each element in the pool. */
|
|
||||||
|
/**
|
||||||
|
* @brief Size of each element in the pool in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX], rounded up to 8-byte alignment
|
||||||
|
*/
|
||||||
uint32_t element_size;
|
uint32_t element_size;
|
||||||
/** The number of elements to allocate in each segment. */
|
|
||||||
|
/**
|
||||||
|
* @brief Number of elements to allocate in each segment
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_element_incr;
|
uint32_t n_element_incr;
|
||||||
/** The total number of free elements in the pool, across all segments. */
|
|
||||||
|
/**
|
||||||
|
* @brief Total number of free elements across all segments
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_free_element;
|
uint32_t n_free_element;
|
||||||
/** The head of the segment list. */
|
|
||||||
|
/**
|
||||||
|
* @brief Head of the segment linked list
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_pool_segment *segment_list_head;
|
struct pva_kmd_devmem_pool_segment *segment_list_head;
|
||||||
/** The PVA device. */
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the PVA device
|
||||||
|
*/
|
||||||
struct pva_kmd_device *pva;
|
struct pva_kmd_device *pva;
|
||||||
/** The mutex for the pool. */
|
|
||||||
|
/**
|
||||||
|
* @brief Mutex for thread-safe pool operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t pool_lock;
|
pva_kmd_mutex_t pool_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Device memory from a pool.
|
/**
|
||||||
|
* @brief Device memory element from a pool
|
||||||
*
|
*
|
||||||
* It is an element in a segment of a pool.
|
* @details Represents a single element allocated from a device memory pool.
|
||||||
|
* The element is contained within a specific segment of the pool and can
|
||||||
|
* be used to access the allocated memory through IOVA addresses or virtual
|
||||||
|
* addresses as needed by the application.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_devmem_element {
|
struct pva_kmd_devmem_element {
|
||||||
/** The segment that contains the element. */
|
/**
|
||||||
|
* @brief Pointer to the segment containing this element
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_pool_segment *segment;
|
struct pva_kmd_devmem_pool_segment *segment;
|
||||||
/** The index of the element in the segment. */
|
|
||||||
|
/**
|
||||||
|
* @brief Index of this element within the segment
|
||||||
|
* Valid range: [0 .. n_element_incr-1]
|
||||||
|
*/
|
||||||
uint32_t ele_idx;
|
uint32_t ele_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Get the IOVA of a device memory element. */
|
/**
|
||||||
|
* @brief Get the IOVA address of a device memory element
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calculates the IOVA address for the specified device memory element
|
||||||
|
* - Uses the segment's device memory base address and element index
|
||||||
|
* - Accounts for element size and alignment requirements
|
||||||
|
* - Returns hardware-accessible address for DMA operations
|
||||||
|
* - Provides address suitable for programming hardware registers
|
||||||
|
*
|
||||||
|
* The returned IOVA can be used by hardware to access the element
|
||||||
|
* memory directly through the SMMU context associated with the pool.
|
||||||
|
*
|
||||||
|
* @param[in] devmem Pointer to @ref pva_kmd_devmem_element structure
|
||||||
|
* Valid value: non-null, must be allocated from pool
|
||||||
|
*
|
||||||
|
* @retval iova_address IOVA address of the device memory element
|
||||||
|
*/
|
||||||
uint64_t pva_kmd_get_devmem_iova(struct pva_kmd_devmem_element const *devmem);
|
uint64_t pva_kmd_get_devmem_iova(struct pva_kmd_devmem_element const *devmem);
|
||||||
|
|
||||||
/** @brief Get the virtual address of a device memory element. */
|
/**
|
||||||
|
* @brief Get the virtual address of a device memory element
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calculates the virtual address for the specified device memory element
|
||||||
|
* - Uses the segment's device memory base virtual address and element index
|
||||||
|
* - Accounts for element size and alignment requirements
|
||||||
|
* - Returns CPU-accessible virtual address for software operations
|
||||||
|
* - Provides address suitable for direct memory access by CPU
|
||||||
|
*
|
||||||
|
* The returned virtual address can be used by software to read and write
|
||||||
|
* the element memory directly using normal memory operations.
|
||||||
|
*
|
||||||
|
* @param[in] devmem Pointer to @ref pva_kmd_devmem_element structure
|
||||||
|
* Valid value: non-null, must be allocated from pool
|
||||||
|
*
|
||||||
|
* @retval virtual_address Virtual address pointer to the device memory element
|
||||||
|
*/
|
||||||
void *pva_kmd_get_devmem_va(struct pva_kmd_devmem_element const *devmem);
|
void *pva_kmd_get_devmem_va(struct pva_kmd_devmem_element const *devmem);
|
||||||
|
|
||||||
/** @brief Initialize a device memory pool.
|
/**
|
||||||
|
* @brief Initialize a device memory pool
|
||||||
*
|
*
|
||||||
* @param pool The device memory pool to initialize.
|
* @details This function performs the following operations:
|
||||||
* @param pva The PVA device.
|
* - Initializes the device memory pool structure with specified parameters
|
||||||
* @param smmu_ctx_idx The SMMU context index for the pool.
|
* - Rounds element_size up to 8-byte alignment for optimal access
|
||||||
* @param element_size The size of each element in the pool.
|
* - Allocates initial segment with n_element_incr elements
|
||||||
* @param ele_incr_count The number of elements to allocate in each segment.
|
* - Sets up SMMU context for memory allocation and mapping
|
||||||
|
* - Initializes mutex for thread-safe pool operations
|
||||||
|
* - Configures automatic segment management policies
|
||||||
|
* - Prepares pool for element allocation and deallocation
|
||||||
|
*
|
||||||
|
* The initialized pool is ready for element allocation using
|
||||||
|
* @ref pva_kmd_devmem_pool_zalloc() and will automatically expand
|
||||||
|
* capacity by adding new segments as needed.
|
||||||
|
*
|
||||||
|
* @param[out] pool Pointer to @ref pva_kmd_devmem_pool structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] smmu_ctx_idx SMMU context index for memory allocation
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
* @param[in] element_size Size of each element in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] ele_incr_count Number of elements per segment
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Pool initialized successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate initial segment
|
||||||
|
* @retval PVA_INTERNAL Failed to initialize pool mutex
|
||||||
|
* @retval PVA_INVAL Failed to map memory to SMMU context
|
||||||
*/
|
*/
|
||||||
enum pva_error pva_kmd_devmem_pool_init(struct pva_kmd_devmem_pool *pool,
|
enum pva_error pva_kmd_devmem_pool_init(struct pva_kmd_devmem_pool *pool,
|
||||||
struct pva_kmd_device *pva,
|
struct pva_kmd_device *pva,
|
||||||
@@ -86,15 +196,76 @@ enum pva_error pva_kmd_devmem_pool_init(struct pva_kmd_devmem_pool *pool,
|
|||||||
uint32_t element_size,
|
uint32_t element_size,
|
||||||
uint32_t ele_incr_count);
|
uint32_t ele_incr_count);
|
||||||
|
|
||||||
/** @brief Allocate a device memory element from a pool and zero-initialize it. */
|
/**
|
||||||
|
* @brief Allocate and zero-initialize a device memory element from pool
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Searches for available element in existing segments
|
||||||
|
* - Allocates new segment if all existing segments are full
|
||||||
|
* - Assigns element from segment using block allocator
|
||||||
|
* - Zero-initializes the allocated element memory
|
||||||
|
* - Updates pool statistics and segment free counts
|
||||||
|
* - Returns element information for subsequent use
|
||||||
|
* - Ensures thread-safe allocation through mutex protection
|
||||||
|
*
|
||||||
|
* The allocated element is zero-initialized and ready for use. The
|
||||||
|
* element remains allocated until freed using @ref pva_kmd_devmem_pool_free().
|
||||||
|
*
|
||||||
|
* @param[in] pool Pointer to @ref pva_kmd_devmem_pool structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] devmem Pointer to @ref pva_kmd_devmem_element to populate
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Element allocated successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate new segment
|
||||||
|
* @retval PVA_ENOSPC Pool limits exceeded
|
||||||
|
* @retval PVA_INVAL Failed to map new segment memory
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_devmem_pool_zalloc(struct pva_kmd_devmem_pool *pool,
|
pva_kmd_devmem_pool_zalloc(struct pva_kmd_devmem_pool *pool,
|
||||||
struct pva_kmd_devmem_element *devmem);
|
struct pva_kmd_devmem_element *devmem);
|
||||||
|
|
||||||
/** @brief Free a device memory element from a pool. */
|
/**
|
||||||
|
* @brief Free a device memory element back to its pool
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the element belongs to a valid segment and pool
|
||||||
|
* - Returns the element to its segment's block allocator
|
||||||
|
* - Updates segment and pool free element counts
|
||||||
|
* - Checks for segment deallocation opportunities
|
||||||
|
* - Frees empty segments if pool has excess capacity
|
||||||
|
* - Maintains optimal pool memory usage
|
||||||
|
* - Ensures thread-safe deallocation through mutex protection
|
||||||
|
*
|
||||||
|
* The pool automatically manages segment deallocation to maintain
|
||||||
|
* efficiency while avoiding unnecessary memory fragmentation.
|
||||||
|
* Segments are freed when there are more than 2 * n_element_incr
|
||||||
|
* free elements, ensuring at least n_element_incr remain available.
|
||||||
|
*
|
||||||
|
* @param[in] devmem Pointer to @ref pva_kmd_devmem_element to free
|
||||||
|
* Valid value: non-null, must be allocated from pool
|
||||||
|
*/
|
||||||
void pva_kmd_devmem_pool_free(struct pva_kmd_devmem_element *devmem);
|
void pva_kmd_devmem_pool_free(struct pva_kmd_devmem_element *devmem);
|
||||||
|
|
||||||
/** @brief Deinitialize a device memory pool. */
|
/**
|
||||||
|
* @brief Deinitialize a device memory pool and free all resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures all elements have been freed back to the pool
|
||||||
|
* - Traverses segment linked list and frees all segments
|
||||||
|
* - Unmaps device memory from SMMU contexts
|
||||||
|
* - Releases all allocated device memory
|
||||||
|
* - Destroys mutex and synchronization primitives
|
||||||
|
* - Cleans up pool data structures and state
|
||||||
|
* - Invalidates pool for future use
|
||||||
|
*
|
||||||
|
* All elements must be freed before calling this function. After
|
||||||
|
* deinitialization, the pool cannot be used for further operations
|
||||||
|
* and any remaining element references become invalid.
|
||||||
|
*
|
||||||
|
* @param[in, out] pool Pointer to @ref pva_kmd_devmem_pool structure to deinitialize
|
||||||
|
* Valid value: non-null, must be initialized, all elements freed
|
||||||
|
*/
|
||||||
void pva_kmd_devmem_pool_deinit(struct pva_kmd_devmem_pool *pool);
|
void pva_kmd_devmem_pool_deinit(struct pva_kmd_devmem_pool *pool);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
#include "pva_kmd_resource_table.h"
|
#include "pva_kmd_resource_table.h"
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
#define PVA_KMD_INVALID_CH_IDX 0xFF
|
#define PVA_KMD_INVALID_CH_IDX 0xFFU
|
||||||
|
|
||||||
void pva_kmd_unload_dma_config_unsafe(struct pva_kmd_dma_resource_aux *dma_aux)
|
void pva_kmd_unload_dma_config_unsafe(struct pva_kmd_dma_resource_aux *dma_aux)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < dma_aux->dram_res_count; i++) {
|
for (i = 0U; i < dma_aux->dram_res_count; i++) {
|
||||||
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
||||||
dma_aux->static_dram_res_ids[i]);
|
dma_aux->static_dram_res_ids[i]);
|
||||||
}
|
}
|
||||||
@@ -31,31 +31,33 @@ static void trace_dma_channels(struct pva_dma_config const *dma_config,
|
|||||||
const struct pva_dma_channel *channel;
|
const struct pva_dma_channel *channel;
|
||||||
uint32_t num_descs = dma_config->header.num_descriptors;
|
uint32_t num_descs = dma_config->header.num_descriptors;
|
||||||
|
|
||||||
for (ch_index = 0; ch_index < cfg_hdr->num_channels; ch_index++) {
|
for (ch_index = 0U; ch_index < cfg_hdr->num_channels; ch_index++) {
|
||||||
uint8_t desc_index;
|
uint8_t desc_index;
|
||||||
|
|
||||||
channel = &dma_config->channels[ch_index];
|
channel = &dma_config->channels[ch_index];
|
||||||
desc_index = channel->desc_index;
|
desc_index = channel->desc_index;
|
||||||
for (uint32_t i = 0; i < PVA_MAX_NUM_DMA_DESC; i++) {
|
for (uint32_t i = 0U; i < PVA_MAX_NUM_DMA_DESC; i++) {
|
||||||
desc_index = array_index_nospec(desc_index, num_descs);
|
desc_index = (uint8_t)array_index_nospec(desc_index,
|
||||||
|
num_descs);
|
||||||
if (desc_to_ch[desc_index] != PVA_KMD_INVALID_CH_IDX) {
|
if (desc_to_ch[desc_index] != PVA_KMD_INVALID_CH_IDX) {
|
||||||
//Already traced this descriptor
|
//Already traced this descriptor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
desc_to_ch[desc_index] = ch_index;
|
desc_to_ch[desc_index] = (uint8_t)ch_index;
|
||||||
desc_index = sat_sub8(
|
desc_index = sat_sub8(
|
||||||
dma_config->descriptors[desc_index].link_desc_id,
|
dma_config->descriptors[desc_index].link_desc_id,
|
||||||
1);
|
1);
|
||||||
|
desc_index =
|
||||||
|
sat_sub8(desc_index, cfg_hdr->base_descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error pva_kmd_load_dma_config(
|
||||||
pva_kmd_load_dma_config(struct pva_kmd_resource_table *resource_table,
|
struct pva_kmd_resource_table *resource_table,
|
||||||
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
||||||
uint32_t dma_config_size,
|
uint32_t dma_config_size, struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
struct pva_kmd_dma_resource_aux *dma_aux,
|
void *fw_dma_cfg, uint32_t *out_fw_fetch_size, bool skip_validation)
|
||||||
void *fw_dma_cfg, uint32_t *out_fw_fetch_size)
|
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
uint32_t fw_fetch_size;
|
uint32_t fw_fetch_size;
|
||||||
@@ -72,24 +74,27 @@ pva_kmd_load_dma_config(struct pva_kmd_resource_table *resource_table,
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < PVA_MAX_NUM_DMA_DESC; i++) {
|
for (uint32_t i = 0U; i < PVA_MAX_NUM_DMA_DESC; i++) {
|
||||||
desc_to_ch[i] = PVA_KMD_INVALID_CH_IDX;
|
desc_to_ch[i] = PVA_KMD_INVALID_CH_IDX;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_parse_dma_config(dma_cfg_hdr, dma_config_size,
|
err = pva_kmd_parse_dma_config(dma_cfg_hdr, dma_config_size,
|
||||||
&dma_config,
|
&dma_config,
|
||||||
&resource_table->pva->hw_consts);
|
&resource_table->pva->hw_consts,
|
||||||
|
skip_validation);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto free_scratch_buf;
|
goto free_scratch_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_validate_dma_config(&dma_config,
|
if (!skip_validation) { // Skip validation for PFSD and test mode
|
||||||
&resource_table->pva->hw_consts,
|
err = pva_kmd_validate_dma_config(
|
||||||
|
&dma_config, &resource_table->pva->hw_consts,
|
||||||
scratch_buf->access_sizes,
|
scratch_buf->access_sizes,
|
||||||
scratch_buf->hw_dma_descs_mask);
|
scratch_buf->hw_dma_descs_mask);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto free_scratch_buf;
|
goto free_scratch_buf;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace_dma_channels(&dma_config, desc_to_ch);
|
trace_dma_channels(&dma_config, desc_to_ch);
|
||||||
|
|
||||||
@@ -123,9 +128,10 @@ pva_kmd_load_dma_config(struct pva_kmd_resource_table *resource_table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_bind_static_buffers(
|
err = pva_kmd_bind_static_buffers(
|
||||||
fw_dma_cfg, dma_aux, scratch_buf->static_slots,
|
(struct pva_dma_config_resource *)fw_dma_cfg, dma_aux,
|
||||||
dma_config.header.num_static_slots, scratch_buf->static_relocs,
|
scratch_buf->static_slots, dma_config.header.num_static_slots,
|
||||||
dma_config.static_bindings, dma_config.header.num_static_slots);
|
scratch_buf->static_relocs, dma_config.static_bindings,
|
||||||
|
dma_config.header.num_static_slots);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto drop_res;
|
goto drop_res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,80 +7,330 @@
|
|||||||
#include "pva_kmd.h"
|
#include "pva_kmd.h"
|
||||||
#include "pva_resource.h"
|
#include "pva_resource.h"
|
||||||
|
|
||||||
/* Mask to extract the GOB offset from the Surface address */
|
/**
|
||||||
|
* @brief Mask to extract the GOB offset from the Surface address
|
||||||
|
*
|
||||||
|
* @details Mask to extract the GOB offset from the Surface address
|
||||||
|
* Used for block linear DMA configuration processing.
|
||||||
|
* Value: 0x3E00
|
||||||
|
*/
|
||||||
#define PVA_DMA_BL_GOB_OFFSET_MASK 0x3E00U
|
#define PVA_DMA_BL_GOB_OFFSET_MASK 0x3E00U
|
||||||
|
|
||||||
/* Right shift value for moving GOB offset value extracted from surface address to LSB */
|
/**
|
||||||
|
* @brief Right shift value for moving GOB offset to LSB
|
||||||
|
*
|
||||||
|
* @details Right shift value for moving GOB offset value extracted from surface address to LSB
|
||||||
|
* Used in conjunction with PVA_DMA_BL_GOB_OFFSET_MASK for block linear addressing.
|
||||||
|
* Value: 6
|
||||||
|
*/
|
||||||
#define PVA_DMA_BL_GOB_OFFSET_MASK_RSH 6U
|
#define PVA_DMA_BL_GOB_OFFSET_MASK_RSH 6U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum descriptor ID value supported by hardware
|
||||||
|
*
|
||||||
|
* @details Maximum descriptor ID value supported by hardware
|
||||||
|
* Used for DMA descriptor validation and range checking.
|
||||||
|
* Value: 0x3F (63 decimal)
|
||||||
|
*/
|
||||||
#define MAX_DESC_ID 0x3FU
|
#define MAX_DESC_ID 0x3FU
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enumeration of DMA frame replication modes
|
||||||
|
*
|
||||||
|
* @details Defines the different frame replication modes supported by the DMA engine.
|
||||||
|
* Frame replication allows efficient broadcasting of data to multiple destinations
|
||||||
|
* or processing paths, optimizing memory bandwidth usage for certain algorithms.
|
||||||
|
*/
|
||||||
enum pva_dma_frame_rep {
|
enum pva_dma_frame_rep {
|
||||||
|
/** @brief No replication - single copy operation */
|
||||||
REPLICATION_NONE = 0,
|
REPLICATION_NONE = 0,
|
||||||
|
/** @brief Two-way replication - data copied to 2 destinations */
|
||||||
REPLICATION_TWO_WAY,
|
REPLICATION_TWO_WAY,
|
||||||
|
/** @brief Four-way replication - data copied to 4 destinations */
|
||||||
REPLICATION_FOUR_WAY,
|
REPLICATION_FOUR_WAY,
|
||||||
|
/** @brief Eight-way replication - data copied to 8 destinations */
|
||||||
REPLICATION_EIGHT_WAY,
|
REPLICATION_EIGHT_WAY,
|
||||||
|
/** @brief Sixteen-way replication - data copied to 16 destinations */
|
||||||
REPLICATION_SIXTEEN_WAY,
|
REPLICATION_SIXTEEN_WAY,
|
||||||
|
/** @brief Thirty-two-way replication - data copied to 32 destinations */
|
||||||
REPLICATION_THIRTYTWO_WAY,
|
REPLICATION_THIRTYTWO_WAY,
|
||||||
|
/** @brief Full replication - maximum supported replication */
|
||||||
REPLICATION_FULL
|
REPLICATION_FULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DMA access range entry for validation
|
||||||
|
*
|
||||||
|
* @details This structure defines a memory access range with start and end addresses
|
||||||
|
* used for DMA validation. It ensures that DMA operations do not access memory
|
||||||
|
* outside of allocated and mapped regions, providing memory protection and
|
||||||
|
* preventing buffer overruns.
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_access_entry {
|
struct pva_kmd_dma_access_entry {
|
||||||
|
/**
|
||||||
|
* @brief Starting address of the access range
|
||||||
|
* Valid range: [INT64_MIN .. INT64_MAX]
|
||||||
|
*/
|
||||||
int64_t start_addr;
|
int64_t start_addr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ending address of the access range (inclusive)
|
||||||
|
* Valid range: [start_addr .. INT64_MAX]
|
||||||
|
*/
|
||||||
int64_t end_addr;
|
int64_t end_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Complete DMA access information for validation
|
||||||
|
*
|
||||||
|
* @details This structure contains access range information for all potential
|
||||||
|
* DMA targets including source, primary destination, and secondary destination.
|
||||||
|
* It is used during DMA configuration validation to ensure all memory accesses
|
||||||
|
* are within valid ranges and properly bounded.
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_access {
|
struct pva_kmd_dma_access {
|
||||||
|
/** @brief Source buffer access range */
|
||||||
struct pva_kmd_dma_access_entry src;
|
struct pva_kmd_dma_access_entry src;
|
||||||
|
/** @brief Primary destination buffer access range */
|
||||||
struct pva_kmd_dma_access_entry dst;
|
struct pva_kmd_dma_access_entry dst;
|
||||||
|
/** @brief Secondary destination buffer access range */
|
||||||
struct pva_kmd_dma_access_entry dst2;
|
struct pva_kmd_dma_access_entry dst2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pva_kmd_resource_table;
|
struct pva_kmd_resource_table;
|
||||||
struct pva_kmd_hw_constants;
|
struct pva_kmd_hw_constants;
|
||||||
|
|
||||||
/** Auxiliary information needed for managing DMA resources:
|
/**
|
||||||
|
* @brief Auxiliary information for DMA resource management
|
||||||
*
|
*
|
||||||
* - Hold references to DRAM buffers and VPU bin used by the DMA configuration.
|
* @details Auxiliary information needed for managing DMA resources including
|
||||||
* - Scratch buffers needed during DMA configuration loading.
|
* holding references to DRAM buffers and VPU binaries used by DMA configuration,
|
||||||
|
* and providing scratch buffers needed during DMA configuration loading.
|
||||||
|
* This structure maintains resource lifetime and dependency tracking.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_dma_resource_aux {
|
struct pva_kmd_dma_resource_aux {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the resource table for resource management
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_table *res_table;
|
struct pva_kmd_resource_table *res_table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource ID of the VPU binary used by this DMA configuration
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t vpu_bin_res_id;
|
uint32_t vpu_bin_res_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of DRAM resources referenced by this DMA configuration
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_DMA_DRAM_SLOTS]
|
||||||
|
*/
|
||||||
uint32_t dram_res_count;
|
uint32_t dram_res_count;
|
||||||
/** DRAM buffers statically referenced by the DMA configuration */
|
|
||||||
|
/**
|
||||||
|
* @brief Array of DRAM buffer resource IDs statically referenced by DMA configuration
|
||||||
|
*
|
||||||
|
* @details DRAM buffers statically referenced by the DMA configuration
|
||||||
|
*/
|
||||||
uint32_t static_dram_res_ids[PVA_KMD_MAX_NUM_DMA_DRAM_SLOTS];
|
uint32_t static_dram_res_ids[PVA_KMD_MAX_NUM_DMA_DRAM_SLOTS];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Scratch buffers needed during DMA configuration loading. They don't fit on stack. */
|
/**
|
||||||
|
* @brief Scratch buffers for DMA configuration processing
|
||||||
|
*
|
||||||
|
* @details Scratch buffers needed during DMA configuration loading that don't fit on stack.
|
||||||
|
* These buffers provide temporary storage for parsing, validation, and conversion
|
||||||
|
* operations during DMA configuration setup. They help avoid stack overflow issues
|
||||||
|
* and provide efficient memory management for DMA operations.
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_scratch_buffer {
|
struct pva_kmd_dma_scratch_buffer {
|
||||||
|
/**
|
||||||
|
* @brief Static slot definitions for firmware
|
||||||
|
*/
|
||||||
struct pva_fw_dma_slot static_slots[PVA_KMD_MAX_NUM_DMA_SLOTS];
|
struct pva_fw_dma_slot static_slots[PVA_KMD_MAX_NUM_DMA_SLOTS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Static relocation information for firmware
|
||||||
|
*/
|
||||||
struct pva_fw_dma_reloc static_relocs[PVA_KMD_MAX_NUM_DMA_SLOTS];
|
struct pva_fw_dma_reloc static_relocs[PVA_KMD_MAX_NUM_DMA_SLOTS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Access size validation information for each descriptor
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_access access_sizes[PVA_MAX_NUM_DMA_DESC];
|
struct pva_kmd_dma_access access_sizes[PVA_MAX_NUM_DMA_DESC];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bitmask for hardware DMA descriptors tracking
|
||||||
|
*/
|
||||||
uint64_t hw_dma_descs_mask[((PVA_MAX_NUM_DMA_DESC / 64ULL) + 1ULL)];
|
uint64_t hw_dma_descs_mask[((PVA_MAX_NUM_DMA_DESC / 64ULL) + 1ULL)];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pva_error
|
/**
|
||||||
pva_kmd_parse_dma_config(const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
* @brief Parse and validate user-provided DMA configuration
|
||||||
uint32_t dma_config_size,
|
*
|
||||||
struct pva_dma_config *out_cfg,
|
* @details This function performs the following operations:
|
||||||
struct pva_kmd_hw_constants const *hw_consts);
|
* - Parses the user-provided DMA configuration data structure
|
||||||
|
* - Validates configuration parameters against hardware constants
|
||||||
|
* - Converts user format to internal representation for processing
|
||||||
|
* - Checks descriptor counts, slot assignments, and parameter ranges
|
||||||
|
* - Ensures configuration compatibility with hardware capabilities
|
||||||
|
* - Prepares configuration for further validation and loading steps
|
||||||
|
*
|
||||||
|
* The parsing includes validation of DMA descriptors, slot configurations,
|
||||||
|
* addressing modes, and other parameters required for safe DMA operation.
|
||||||
|
* Any invalid parameters or unsupported configurations will result in
|
||||||
|
* appropriate error codes.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg_hdr Pointer to user DMA configuration header
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] dma_config_size Size of the DMA configuration data in bytes
|
||||||
|
* Valid range: [sizeof(header) .. UINT32_MAX]
|
||||||
|
* @param[out] out_cfg Pointer to parsed DMA configuration output
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] hw_consts Pointer to hardware constants for validation
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] skip_validation Skip DMA validation if true
|
||||||
|
* Valid value: true, false
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS DMA configuration parsed successfully
|
||||||
|
* @retval PVA_INVALID_DMA_CONFIG Invalid configuration parameters
|
||||||
|
* @retval PVA_NOT_IMPL Unsupported DMA configuration feature
|
||||||
|
* @retval PVA_INVAL Invalid input parameters
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_parse_dma_config(
|
||||||
|
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
||||||
|
uint32_t dma_config_size, struct pva_dma_config *out_cfg,
|
||||||
|
struct pva_kmd_hw_constants const *hw_consts, bool skip_validation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire references to resources used by DMA configuration
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Identifies all resources (DRAM buffers, VPU binaries) used by DMA config
|
||||||
|
* - Acquires reference counts for these resources to prevent premature cleanup
|
||||||
|
* - Updates the auxiliary structure with resource tracking information
|
||||||
|
* - Ensures resource lifetime extends through DMA configuration usage
|
||||||
|
* - Provides dependency management for proper resource cleanup ordering
|
||||||
|
*
|
||||||
|
* This function must be called before using a DMA configuration to ensure
|
||||||
|
* all referenced resources remain valid. The references should be released
|
||||||
|
* using @ref pva_kmd_unload_dma_config_unsafe() when the configuration is
|
||||||
|
* no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg Pointer to parsed DMA configuration
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in, out] dma_aux Pointer to DMA auxiliary structure to update
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Resources acquired successfully
|
||||||
|
* @retval PVA_INVALID_RESOURCE Resource in invalid state for acquisition
|
||||||
|
* @retval PVA_INVAL Invalid configuration or auxiliary pointer
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_dma_resource_aux *dma_aux);
|
struct pva_kmd_dma_resource_aux *dma_aux);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate DMA configuration against hardware constraints
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates DMA configuration parameters against hardware capabilities
|
||||||
|
* - Checks descriptor limits, slot usage, and addressing constraints
|
||||||
|
* - Computes access ranges for memory validation
|
||||||
|
* - Builds hardware descriptor usage masks for tracking
|
||||||
|
* - Ensures configuration will execute safely on hardware
|
||||||
|
* - Verifies memory access patterns and alignment requirements
|
||||||
|
*
|
||||||
|
* The validation covers all aspects of DMA operation including transfer
|
||||||
|
* sizes, addressing modes, descriptor linking, and hardware resource usage.
|
||||||
|
* This comprehensive validation prevents runtime errors and ensures
|
||||||
|
* reliable DMA operation.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg Pointer to DMA configuration to validate
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] hw_consts Pointer to hardware constants for validation
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] access_sizes Array to store computed access size information
|
||||||
|
* Valid value: non-null, min size PVA_MAX_NUM_DMA_DESC
|
||||||
|
* @param[out] hw_dma_descs_mask Bitmask for tracking hardware descriptor usage
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS DMA configuration validated successfully
|
||||||
|
* @retval PVA_INVALID_DMA_CONFIG Configuration violates hardware constraints
|
||||||
|
* @retval PVA_ENOSPC Configuration exceeds hardware limits
|
||||||
|
* @retval PVA_INVAL Invalid configuration or output pointers
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_validate_dma_config(struct pva_dma_config const *dma_cfg,
|
pva_kmd_validate_dma_config(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_hw_constants const *hw_consts,
|
struct pva_kmd_hw_constants const *hw_consts,
|
||||||
struct pva_kmd_dma_access *access_sizes,
|
struct pva_kmd_dma_access *access_sizes,
|
||||||
uint64_t *hw_dma_descs_mask);
|
uint64_t *hw_dma_descs_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute memory access patterns for DMA configuration
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Analyzes DMA descriptors to determine memory access patterns
|
||||||
|
* - Computes source and destination address ranges for each operation
|
||||||
|
* - Builds hardware descriptor usage masks for resource tracking
|
||||||
|
* - Calculates total memory footprint and access requirements
|
||||||
|
* - Provides information needed for memory validation and protection
|
||||||
|
* - Determines optimal memory layout and access strategies
|
||||||
|
*
|
||||||
|
* The computed access information is used for memory validation, SMMU
|
||||||
|
* programming, and ensuring DMA operations remain within allocated
|
||||||
|
* buffer boundaries. This analysis is critical for memory protection
|
||||||
|
* and system stability.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg Pointer to DMA configuration to analyze
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] access_sizes Array to store computed access information
|
||||||
|
* Valid value: non-null, min size PVA_MAX_NUM_DMA_DESC
|
||||||
|
* @param[out] hw_dma_descs_mask Bitmask for tracking hardware descriptor usage
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Access patterns computed successfully
|
||||||
|
* @retval PVA_INVALID_DMA_CONFIG Invalid DMA configuration for analysis
|
||||||
|
* @retval PVA_INVAL Invalid configuration or output pointers
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_compute_dma_access(struct pva_dma_config const *dma_cfg,
|
pva_kmd_compute_dma_access(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_dma_access *access_sizes,
|
struct pva_kmd_dma_access *access_sizes,
|
||||||
uint64_t *hw_dma_descs_mask);
|
uint64_t *hw_dma_descs_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Collect relocation information for firmware DMA configuration
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Extracts static and dynamic slot information from DMA configuration
|
||||||
|
* - Builds relocation tables for firmware address patching
|
||||||
|
* - Separates static slots (bound at load time) from dynamic slots
|
||||||
|
* - Generates firmware-compatible slot and relocation structures
|
||||||
|
* - Maps descriptor channels to slots for proper address resolution
|
||||||
|
* - Prepares data needed for firmware DMA setup and execution
|
||||||
|
*
|
||||||
|
* The relocation information enables firmware to properly patch addresses
|
||||||
|
* in DMA descriptors at runtime, supporting both static (pre-bound) and
|
||||||
|
* dynamic (runtime-bound) memory slots for flexible DMA operation.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg Pointer to DMA configuration
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] access_sizes Array of access size information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] out_static_slots Array to store static slot information
|
||||||
|
* Valid value: non-null, min size num_static_slots
|
||||||
|
* @param[in] num_static_slots Number of static slots to process
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_DMA_SLOTS]
|
||||||
|
* @param[out] out_static_relocs Array to store static relocation information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] out_dyn_slots Array to store dynamic slot information
|
||||||
|
* Valid value: non-null, min size num_dyn_slots
|
||||||
|
* @param[in] num_dyn_slots Number of dynamic slots to process
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_DMA_SLOTS]
|
||||||
|
* @param[out] out_dyn_relocs Array to store dynamic relocation information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] desc_to_ch Array mapping descriptors to channels
|
||||||
|
* Valid value: non-null
|
||||||
|
*/
|
||||||
void pva_kmd_collect_relocs(struct pva_dma_config const *dma_cfg,
|
void pva_kmd_collect_relocs(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_dma_access const *access_sizes,
|
struct pva_kmd_dma_access const *access_sizes,
|
||||||
struct pva_fw_dma_slot *out_static_slots,
|
struct pva_fw_dma_slot *out_static_slots,
|
||||||
@@ -92,13 +342,39 @@ void pva_kmd_collect_relocs(struct pva_dma_config const *dma_cfg,
|
|||||||
uint8_t const *desc_to_ch);
|
uint8_t const *desc_to_ch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Bind static buffers to the DMA configuration.
|
* @brief Bind static buffers to the DMA configuration
|
||||||
*
|
*
|
||||||
* When binding static buffers, we edit pva_dma_config in-place and replace the
|
* @details This function performs the following operations:
|
||||||
* offset field with the final addresses of static buffers.
|
* - Edits @ref pva_dma_config in-place to replace offset fields with final addresses
|
||||||
|
* - Resolves static buffer addresses from resource table entries
|
||||||
|
* - Validates that DMA configuration does not access static buffers out of range
|
||||||
|
* - Updates firmware DMA configuration with bound address information
|
||||||
|
* - Ensures memory protection by validating all access patterns
|
||||||
|
* - Prepares configuration for safe execution with static buffer bindings
|
||||||
*
|
*
|
||||||
* We also validate that the DMA configuration does not access those static
|
* When binding static buffers, this function modifies the DMA configuration
|
||||||
* buffers out of range.
|
* to embed actual memory addresses, enabling efficient firmware execution
|
||||||
|
* without runtime address resolution for static resources.
|
||||||
|
*
|
||||||
|
* @param[in, out] fw_dma_cfg Pointer to firmware DMA configuration to update
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] dma_aux Pointer to DMA auxiliary resource information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] static_slots Array of static slot definitions
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] num_static_slots Number of static slots to bind
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_DMA_SLOTS]
|
||||||
|
* @param[in] static_relocs Array of static relocation information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] static_bindings Array of static binding specifications
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] num_static_bindings Number of static bindings to process
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Static buffers bound successfully
|
||||||
|
* @retval PVA_INVALID_BINDING Invalid binding specification
|
||||||
|
* @retval PVA_BUF_OUT_OF_RANGE Buffer access would exceed valid range
|
||||||
|
* @retval PVA_INVALID_RESOURCE Resource in invalid state for binding
|
||||||
*/
|
*/
|
||||||
enum pva_error pva_kmd_bind_static_buffers(
|
enum pva_error pva_kmd_bind_static_buffers(
|
||||||
struct pva_dma_config_resource *fw_dma_cfg,
|
struct pva_dma_config_resource *fw_dma_cfg,
|
||||||
@@ -109,7 +385,28 @@ enum pva_error pva_kmd_bind_static_buffers(
|
|||||||
uint32_t num_static_bindings);
|
uint32_t num_static_bindings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert user DMA configuration to firmware format.
|
* @brief Convert user DMA configuration to firmware format
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Converts parsed DMA configuration to firmware-compatible format
|
||||||
|
* - Serializes configuration data for efficient firmware consumption
|
||||||
|
* - Calculates the size of configuration data needed in firmware memory
|
||||||
|
* - Optimizes configuration layout for firmware execution performance
|
||||||
|
* - Handles hardware-specific formatting and alignment requirements
|
||||||
|
* - Prepares configuration for transfer to firmware execution environment
|
||||||
|
*
|
||||||
|
* The firmware format is optimized for efficient parsing and execution
|
||||||
|
* by the PVA firmware, with proper alignment and layout for direct
|
||||||
|
* hardware register programming.
|
||||||
|
*
|
||||||
|
* @param[in] dma_cfg Pointer to parsed DMA configuration
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] fw_dma_config Buffer for firmware DMA configuration output
|
||||||
|
* Valid value: non-null, sufficient size
|
||||||
|
* @param[out] out_fw_fetch_size Pointer to store firmware fetch size
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] support_hwseq_frame_linking Whether hardware sequence frame linking is supported
|
||||||
|
* Valid values: true, false
|
||||||
*/
|
*/
|
||||||
void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
||||||
void *fw_dma_config,
|
void *fw_dma_config,
|
||||||
@@ -117,31 +414,62 @@ void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
|||||||
bool support_hwseq_frame_linking);
|
bool support_hwseq_frame_linking);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load DMA configuration into firmware format.
|
* @brief Load DMA configuration into firmware format
|
||||||
*
|
*
|
||||||
* This function mostly does the following things:
|
* @details This function performs comprehensive DMA configuration loading including:
|
||||||
|
* - Validates the DMA configuration against hardware constraints
|
||||||
|
* - Binds static resources (buffers) and embeds their addresses in firmware configuration
|
||||||
|
* - Holds references to DRAM buffers and VPU binaries used by the configuration
|
||||||
|
* - Converts the DMA configuration into optimized firmware format
|
||||||
|
* - Computes memory requirements and access patterns
|
||||||
|
* - Ensures proper resource lifetime management and dependency tracking
|
||||||
|
* - Provides complete configuration ready for firmware execution
|
||||||
*
|
*
|
||||||
* - Validate the DMA configuration.
|
* This function integrates all aspects of DMA configuration processing
|
||||||
* - Bind static resources (buffers) and embed their addresses directly in the
|
* into a single operation, producing a validated and optimized configuration
|
||||||
* firmware DMA configuration.
|
* that can be safely executed by the firmware.
|
||||||
* - Hold references to DRAM buffers and VPU bin used by the DMA configuration.
|
|
||||||
* - Convert the DMA configuration into firmware format.
|
|
||||||
*
|
*
|
||||||
* @param resource_table the resource table for the context.
|
* @param[in] resource_table Pointer to resource table for the context
|
||||||
* @param dma_config DMA configuration from user space.
|
* Valid value: non-null, must be initialized
|
||||||
* @param dma_config_size Size of the dma_config buffer.
|
* @param[in] dma_cfg_hdr Pointer to user DMA configuration header
|
||||||
* @param dma_aux Auxiliary information needed for loading the DMA
|
* Valid value: non-null
|
||||||
* configuration.
|
* @param[in] dma_config_size Size of the dma_config buffer in bytes
|
||||||
* @param fw_dma_cfg Output buffer for the firmware DMA configuration.
|
* Valid range: [sizeof(header) .. UINT32_MAX]
|
||||||
* @param out_fw_fetch_size Size of the firmware DMA configuration that needs to
|
* @param[in, out] dma_aux Pointer to auxiliary information for DMA loading
|
||||||
* be fetched into TCM.
|
* Valid value: non-null
|
||||||
|
* @param[out] fw_dma_cfg Output buffer for firmware DMA configuration
|
||||||
|
* Valid value: non-null, sufficient size
|
||||||
|
* @param[out] out_fw_fetch_size Pointer to store size of configuration to fetch into TCM
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS DMA configuration loaded successfully
|
||||||
|
* @retval PVA_INVALID_DMA_CONFIG Invalid or unsupported DMA configuration
|
||||||
|
* @retval PVA_INVALID_RESOURCE Resource in invalid state for loading
|
||||||
|
* @retval PVA_NOMEM Failed to allocate required memory
|
||||||
|
* @retval PVA_BUF_OUT_OF_RANGE Configuration would violate memory protection
|
||||||
*/
|
*/
|
||||||
enum pva_error
|
enum pva_error pva_kmd_load_dma_config(
|
||||||
pva_kmd_load_dma_config(struct pva_kmd_resource_table *resource_table,
|
struct pva_kmd_resource_table *resource_table,
|
||||||
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
||||||
uint32_t dma_config_size,
|
uint32_t dma_config_size, struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
struct pva_kmd_dma_resource_aux *dma_aux,
|
void *fw_dma_cfg, uint32_t *out_fw_fetch_size, bool priv);
|
||||||
void *fw_dma_cfg, uint32_t *out_fw_fetch_size);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unload DMA configuration and release associated resources (unsafe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Releases all resource references held by the DMA configuration
|
||||||
|
* - Cleans up auxiliary resource tracking information
|
||||||
|
* - Frees memory allocations associated with the configuration
|
||||||
|
* - Invalidates the DMA auxiliary structure for future use
|
||||||
|
* - Does not perform thread-safe locking (caller's responsibility)
|
||||||
|
*
|
||||||
|
* This function is not thread-safe and requires external synchronization.
|
||||||
|
* It should be called when a DMA configuration is no longer needed to
|
||||||
|
* ensure proper resource cleanup and prevent memory leaks.
|
||||||
|
*
|
||||||
|
* @param[in, out] dma_aux Pointer to DMA auxiliary structure to clean up
|
||||||
|
* Valid value: non-null, must have been initialized
|
||||||
|
*/
|
||||||
void pva_kmd_unload_dma_config_unsafe(struct pva_kmd_dma_resource_aux *dma_aux);
|
void pva_kmd_unload_dma_config_unsafe(struct pva_kmd_dma_resource_aux *dma_aux);
|
||||||
#endif // PVA_KMD_DMA_CFG_H
|
#endif // PVA_KMD_DMA_CFG_H
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/* DMA channels per engine (matches PVA_NUM_DMA_CHANNELS in pva_fw_constants.h) */
|
||||||
|
#define PVA_KMD_DMA_CHANNELS_PER_ENGINE 16U
|
||||||
|
|
||||||
static uint32_t get_slot_line_pitch(struct pva_fw_dma_descriptor *descs,
|
static uint32_t get_slot_line_pitch(struct pva_fw_dma_descriptor *descs,
|
||||||
struct pva_fw_dma_reloc const *relocs,
|
struct pva_fw_dma_reloc const *relocs,
|
||||||
struct pva_fw_dma_slot const *slot)
|
struct pva_fw_dma_slot const *slot)
|
||||||
@@ -20,9 +23,15 @@ static uint32_t get_slot_line_pitch(struct pva_fw_dma_descriptor *descs,
|
|||||||
PVA_EXTRACT(first_desc->transfer_control1, 1, 0, uint8_t);
|
PVA_EXTRACT(first_desc->transfer_control1, 1, 0, uint8_t);
|
||||||
|
|
||||||
if (reloc->field == PVA_FW_DMA_RELOC_FIELD_SRC) {
|
if (reloc->field == PVA_FW_DMA_RELOC_FIELD_SRC) {
|
||||||
return first_desc->slp_adv << log2_bpp;
|
/* MISRA 10.8, INT31-C: Cast and shift in separate steps */
|
||||||
|
uint16_t slp_adv_u16 = (uint16_t)first_desc->slp_adv;
|
||||||
|
uint32_t result = (uint32_t)slp_adv_u16 << log2_bpp;
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return first_desc->dlp_adv << log2_bpp;
|
/* MISRA 10.8, INT31-C: Cast and shift in separate steps */
|
||||||
|
uint16_t dlp_adv_u16 = (uint16_t)first_desc->dlp_adv;
|
||||||
|
uint32_t result = (uint32_t)dlp_adv_u16 << log2_bpp;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,9 +48,12 @@ set_channel_block_height(struct pva_dma_config_resource *dma_config,
|
|||||||
return PVA_ERR_CMD_INVALID_BLOCK_HEIGHT;
|
return PVA_ERR_CMD_INVALID_BLOCK_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ch_mask > 0) {
|
while (ch_mask > 0U) {
|
||||||
uint8_t ch_index = __builtin_ctz(ch_mask);
|
uint8_t ch_index = (uint8_t)__builtin_ctz(ch_mask);
|
||||||
if (dma_config->ch_block_height_fixed_mask & (1 << ch_index)) {
|
/* CERT INT34-C: ch_index from ctz(uint16_t) is guaranteed < 16 DMA channels */
|
||||||
|
ASSERT(ch_index < PVA_KMD_DMA_CHANNELS_PER_ENGINE);
|
||||||
|
if ((dma_config->ch_block_height_fixed_mask &
|
||||||
|
((uint16_t)1U << ch_index)) != 0U) {
|
||||||
/* If this bit is already set, it means block height cannot be changed. */
|
/* If this bit is already set, it means block height cannot be changed. */
|
||||||
uint8_t set_bh = PVA_EXTRACT(channels[ch_index].cntl0,
|
uint8_t set_bh = PVA_EXTRACT(channels[ch_index].cntl0,
|
||||||
27, 25, uint8_t);
|
27, 25, uint8_t);
|
||||||
@@ -55,50 +67,24 @@ set_channel_block_height(struct pva_dma_config_resource *dma_config,
|
|||||||
PVA_INSERT(log2_block_height, 27, 25);
|
PVA_INSERT(log2_block_height, 27, 25);
|
||||||
|
|
||||||
dma_config->ch_block_height_fixed_mask |=
|
dma_config->ch_block_height_fixed_mask |=
|
||||||
(1 << ch_index);
|
((uint16_t)1U << ch_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ch_mask &= ~(1 << ch_index);
|
ch_mask &= ~((uint16_t)1U << ch_index);
|
||||||
}
|
}
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
validate_dram_slot_flags(struct pva_fw_dma_slot const *slot,
|
||||||
struct pva_kmd_dma_resource_aux *dma_aux,
|
struct pva_kmd_dram_resource *dram_res)
|
||||||
struct pva_fw_dma_slot const *slot,
|
|
||||||
struct pva_fw_dma_reloc const *static_relocs,
|
|
||||||
struct pva_dma_dram_binding const *dram_bd)
|
|
||||||
{
|
{
|
||||||
struct pva_fw_dma_descriptor *descs =
|
|
||||||
pva_dma_config_get_descriptors(dma_config);
|
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
struct pva_fw_dma_reloc const *relocs;
|
|
||||||
bool is_block_linear =
|
|
||||||
(dram_bd->surface_format == PVA_SURF_FMT_BLOCK_LINEAR);
|
|
||||||
uint32_t line_pitch = get_slot_line_pitch(descs, static_relocs, slot);
|
|
||||||
uint8_t log2_block_height = dram_bd->log2_block_height;
|
|
||||||
struct pva_kmd_dram_resource *dram_res =
|
|
||||||
&pva_kmd_peek_resource(dma_aux->res_table, dram_bd->resource_id)
|
|
||||||
->dram;
|
|
||||||
uint64_t slot_offset_pl = dram_bd->slot_offset;
|
|
||||||
uint64_t surface_base_addr =
|
|
||||||
sat_add64(dram_bd->surface_base_offset, dram_res->mem->iova);
|
|
||||||
/* When binding a buffer, we add the binding->surface_base_offset to the
|
|
||||||
* buffer base address. Therefore, the effective buffer size is
|
|
||||||
* reduced by the offset. */
|
|
||||||
uint64_t max_surface_size =
|
|
||||||
sat_sub64(dram_res->mem->size, dram_bd->surface_base_offset);
|
|
||||||
uint64_t sector_pack_format = 0;
|
|
||||||
int64_t slot_access_start_addr = 0LL;
|
|
||||||
int64_t slot_access_end_addr = 0LL;
|
|
||||||
uint64_t slot_surface_combined_offset = 0ULL;
|
|
||||||
pva_math_error math_error = MATH_OP_SUCCESS;
|
|
||||||
uint8_t slot_access_flags =
|
uint8_t slot_access_flags =
|
||||||
PVA_EXTRACT16(slot->flags, PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
PVA_EXTRACT16(slot->flags, PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
||||||
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB, uint8_t);
|
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB, uint8_t);
|
||||||
|
|
||||||
if ((slot->flags & PVA_FW_DMA_SLOT_FLAG_DRAM) == 0) {
|
if ((slot->flags & PVA_FW_DMA_SLOT_FLAG_DRAM) == 0U) {
|
||||||
pva_kmd_log_err("Binding DRAM buffer to incompatible slot");
|
pva_kmd_log_err("Binding DRAM buffer to incompatible slot");
|
||||||
err = PVA_INVALID_BINDING;
|
err = PVA_INVALID_BINDING;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -109,20 +95,34 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"DRAM buffer does not have the required access permissions");
|
"DRAM buffer does not have the required access permissions");
|
||||||
err = PVA_INVALID_BINDING;
|
err = PVA_INVALID_BINDING;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_block_linear) {
|
out:
|
||||||
if (slot->flags & PVA_FW_DMA_SLOT_FLAG_CB) {
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
setup_block_linear_params(struct pva_dma_config_resource *dma_config,
|
||||||
|
struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
|
struct pva_fw_dma_slot const *slot,
|
||||||
|
struct pva_dma_dram_binding const *dram_bd,
|
||||||
|
uint64_t surface_base_addr, uint32_t line_pitch,
|
||||||
|
uint64_t *max_surface_size,
|
||||||
|
uint64_t *sector_pack_format)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
pva_math_error math_error = MATH_OP_SUCCESS;
|
||||||
|
|
||||||
|
if ((slot->flags & PVA_FW_DMA_SLOT_FLAG_CB) != 0U) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Block linear surface is not compatible with circular buffer");
|
"Block linear surface is not compatible with circular buffer");
|
||||||
err = PVA_INVALID_BINDING;
|
err = PVA_INVALID_BINDING;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
max_surface_size =
|
|
||||||
pva_max_bl_surface_size(max_surface_size,
|
*max_surface_size = pva_max_bl_surface_size(*max_surface_size,
|
||||||
log2_block_height, line_pitch,
|
dram_bd->log2_block_height,
|
||||||
&math_error);
|
line_pitch, &math_error);
|
||||||
if (math_error != MATH_OP_SUCCESS) {
|
if (math_error != MATH_OP_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"bind_static_dram_slot pva_max_bl_surface_size triggered a math error");
|
"bind_static_dram_slot pva_max_bl_surface_size triggered a math error");
|
||||||
@@ -131,8 +131,7 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pva_is_512B_aligned(surface_base_addr)) {
|
if (!pva_is_512B_aligned(surface_base_addr)) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err("BL surface base address is not 512B aligned");
|
||||||
"BL surface base address is not 512B aligned");
|
|
||||||
err = PVA_BAD_SURFACE_BASE_ALIGNMENT;
|
err = PVA_BAD_SURFACE_BASE_ALIGNMENT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -142,57 +141,104 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sector_pack_format =
|
*sector_pack_format = dma_aux->res_table->pva->bl_sector_pack_format;
|
||||||
dma_aux->res_table->pva->bl_sector_pack_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
slot_surface_combined_offset = addu64(
|
out:
|
||||||
slot_offset_pl, dram_bd->surface_base_offset, &math_error);
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (slot_surface_combined_offset >= (uint64_t)MAX_INT64) {
|
static enum pva_error calculate_slot_offsets(
|
||||||
|
struct pva_fw_dma_slot const *slot,
|
||||||
|
struct pva_dma_dram_binding const *dram_bd, uint64_t max_surface_size,
|
||||||
|
int64_t *slot_access_start_addr, int64_t *slot_access_end_addr,
|
||||||
|
uint64_t *slot_surface_combined_offset,
|
||||||
|
uint64_t *adjusted_max_surface_size, pva_math_error *math_error)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
*slot_surface_combined_offset = addu64(
|
||||||
|
dram_bd->slot_offset, dram_bd->surface_base_offset, math_error);
|
||||||
|
|
||||||
|
if (*slot_surface_combined_offset >= (uint64_t)MAX_INT64) {
|
||||||
pva_kmd_log_err("Slot surface offset too large");
|
pva_kmd_log_err("Slot surface offset too large");
|
||||||
return PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
err = PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot_access_start_addr =
|
*slot_access_start_addr =
|
||||||
adds64(slot->start_addr, (int64_t)slot_surface_combined_offset,
|
adds64(slot->start_addr, (int64_t)*slot_surface_combined_offset,
|
||||||
&math_error);
|
math_error);
|
||||||
|
|
||||||
slot_access_end_addr =
|
*slot_access_end_addr =
|
||||||
adds64(slot->end_addr, (int64_t)slot_surface_combined_offset,
|
adds64(slot->end_addr, (int64_t)*slot_surface_combined_offset,
|
||||||
&math_error);
|
math_error);
|
||||||
|
|
||||||
max_surface_size = addu64(max_surface_size,
|
*adjusted_max_surface_size = addu64(
|
||||||
dram_bd->surface_base_offset, &math_error);
|
max_surface_size, dram_bd->surface_base_offset, math_error);
|
||||||
|
|
||||||
if (max_surface_size >= (uint64_t)MAX_INT64) {
|
out:
|
||||||
pva_kmd_log_err("DRAM buffer too large for slot binding");
|
return err;
|
||||||
return PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
}
|
||||||
|
|
||||||
|
static enum pva_error validate_slot_access_bounds(
|
||||||
|
int64_t slot_access_start_addr, int64_t slot_access_end_addr,
|
||||||
|
uint64_t adjusted_max_surface_size, pva_math_error math_error)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
if (adjusted_max_surface_size >= (uint64_t)MAX_INT64) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"bind_static_dram_slot: DRAM buffer too large for slot binding");
|
||||||
|
err = PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (math_error != MATH_OP_SUCCESS) {
|
if (math_error != MATH_OP_SUCCESS) {
|
||||||
pva_kmd_log_err("Math error during slot binding");
|
pva_kmd_log_err(
|
||||||
return PVA_ERR_MATH_OP;
|
"bind_static_dram_slot: Math error during slot binding");
|
||||||
|
err = PVA_ERR_MATH_OP;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot_access_start_addr < 0LL) {
|
if (slot_access_start_addr < 0LL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"DRAM buffer offset underflows for slot binding");
|
"bind_static_dram_slot: DRAM buffer offset underflows for slot binding");
|
||||||
return PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
err = PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot_access_end_addr > (int64_t)max_surface_size) {
|
if (slot_access_end_addr > (int64_t)adjusted_max_surface_size) {
|
||||||
pva_kmd_log_err("DRAM buffer too small for slot binding");
|
pva_kmd_log_err(
|
||||||
return PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
"bind_static_dram_slot: DRAM buffer too small for slot binding");
|
||||||
|
err = PVA_ERR_CMD_DRAM_BUF_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
process_slot_relocations(struct pva_dma_config_resource *dma_config,
|
||||||
|
struct pva_fw_dma_slot const *slot,
|
||||||
|
struct pva_fw_dma_reloc const *static_relocs,
|
||||||
|
struct pva_dma_dram_binding const *dram_bd,
|
||||||
|
uint64_t surface_base_addr, uint64_t slot_offset_pl,
|
||||||
|
uint64_t sector_pack_format, uint32_t line_pitch,
|
||||||
|
bool is_block_linear)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_fw_dma_descriptor *descs =
|
||||||
|
pva_dma_config_get_descriptors(dma_config);
|
||||||
|
struct pva_fw_dma_reloc const *relocs;
|
||||||
|
pva_math_error math_error = MATH_OP_SUCCESS;
|
||||||
|
|
||||||
relocs = &static_relocs[slot->reloc_start_idx];
|
relocs = &static_relocs[slot->reloc_start_idx];
|
||||||
for (uint32_t i = 0; i < slot->reloc_count; i++) {
|
for (uint32_t i = 0; i < slot->reloc_count; i++) {
|
||||||
struct pva_fw_dma_reloc const *reloc = &relocs[i];
|
struct pva_fw_dma_reloc const *reloc = &relocs[i];
|
||||||
struct pva_fw_dma_descriptor *desc = &descs[reloc->desc_index];
|
struct pva_fw_dma_descriptor *desc = &descs[reloc->desc_index];
|
||||||
uint8_t *addr_hi_ptr;
|
uint8_t *addr_hi_ptr;
|
||||||
uint32_t *addr_lo_ptr;
|
uint32_t *addr_lo_ptr;
|
||||||
uint32_t format_field_shift = 0;
|
uint8_t format_field_shift = 0;
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint64_t desc_offset_pl;
|
uint64_t desc_offset_pl;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
@@ -200,11 +246,11 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
if (reloc->field == PVA_FW_DMA_RELOC_FIELD_SRC) {
|
if (reloc->field == PVA_FW_DMA_RELOC_FIELD_SRC) {
|
||||||
addr_hi_ptr = &desc->src_adr1;
|
addr_hi_ptr = &desc->src_adr1;
|
||||||
addr_lo_ptr = &desc->src_adr0;
|
addr_lo_ptr = &desc->src_adr0;
|
||||||
format_field_shift = 3; //SRC_TF in TRANSFER_CONTROL0
|
format_field_shift = 3U; //SRC_TF in TRANSFER_CONTROL0
|
||||||
} else if (reloc->field == PVA_FW_DMA_RELOC_FIELD_DST) {
|
} else if (reloc->field == PVA_FW_DMA_RELOC_FIELD_DST) {
|
||||||
addr_hi_ptr = &desc->dst_adr1;
|
addr_hi_ptr = &desc->dst_adr1;
|
||||||
addr_lo_ptr = &desc->dst_adr0;
|
addr_lo_ptr = &desc->dst_adr0;
|
||||||
format_field_shift = 7; //DST_TF in TRANSFER_CONTROL0
|
format_field_shift = 7U; //DST_TF in TRANSFER_CONTROL0
|
||||||
} else { /* PVA_FW_DMA_RELOC_FIELD_DST2 */
|
} else { /* PVA_FW_DMA_RELOC_FIELD_DST2 */
|
||||||
pva_kmd_log_err("Binding DRAM buffer to DST2 slot");
|
pva_kmd_log_err("Binding DRAM buffer to DST2 slot");
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
@@ -212,20 +258,24 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
}
|
}
|
||||||
desc_offset_pl = assemble_addr(*addr_hi_ptr, *addr_lo_ptr);
|
desc_offset_pl = assemble_addr(*addr_hi_ptr, *addr_lo_ptr);
|
||||||
offset = sat_add64(slot_offset_pl, desc_offset_pl);
|
offset = sat_add64(slot_offset_pl, desc_offset_pl);
|
||||||
desc->transfer_control0 &= ~(1 << format_field_shift);
|
/* CERT INT31-C: Bitwise NOT of shifted value, result masked by uint8_t cast,
|
||||||
|
* safe as only lower 8 bits are used in bitwise AND */
|
||||||
|
desc->transfer_control0 &=
|
||||||
|
(uint8_t) ~(1U << format_field_shift);
|
||||||
if (is_block_linear) {
|
if (is_block_linear) {
|
||||||
/* We need to insert bits surface_base_addr[13, 9] to
|
/* We need to insert bits surface_base_addr[13, 9] to
|
||||||
* transfer_control2[7:3] as specified by DMA IAS. This helps the
|
* transfer_control2[7:3] as specified by DMA IAS. This helps the
|
||||||
* HW identify starting GOB index inside a block. */
|
* HW identify starting GOB index inside a block. */
|
||||||
desc->transfer_control2 &= ~PVA_MASK(7, 3);
|
desc->transfer_control2 &= ~PVA_MASK8(7U, 3U);
|
||||||
desc->transfer_control2 |=
|
desc->transfer_control2 |=
|
||||||
PVA_INSERT8(PVA_EXTRACT64(surface_base_addr, 13,
|
PVA_INSERT8(PVA_EXTRACT64(surface_base_addr, 13,
|
||||||
9, uint8_t),
|
9, uint8_t),
|
||||||
7, 3);
|
7, 3);
|
||||||
desc->transfer_control0 |= 1 << format_field_shift;
|
desc->transfer_control0 |=
|
||||||
|
(uint8_t)(1U << format_field_shift);
|
||||||
|
|
||||||
offset = pva_pl_to_bl_offset(offset, line_pitch,
|
offset = pva_pl_to_bl_offset(offset, line_pitch,
|
||||||
log2_block_height,
|
dram_bd->log2_block_height,
|
||||||
&math_error);
|
&math_error);
|
||||||
if (math_error != MATH_OP_SUCCESS) {
|
if (math_error != MATH_OP_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
@@ -245,6 +295,92 @@ bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
*addr_hi_ptr = iova_hi(addr);
|
*addr_hi_ptr = iova_hi(addr);
|
||||||
*addr_lo_ptr = iova_lo(addr);
|
*addr_lo_ptr = iova_lo(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
bind_static_dram_slot(struct pva_dma_config_resource *dma_config,
|
||||||
|
struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
|
struct pva_fw_dma_slot const *slot,
|
||||||
|
struct pva_fw_dma_reloc const *static_relocs,
|
||||||
|
struct pva_dma_dram_binding const *dram_bd)
|
||||||
|
{
|
||||||
|
struct pva_fw_dma_descriptor *descs =
|
||||||
|
pva_dma_config_get_descriptors(dma_config);
|
||||||
|
bool is_block_linear =
|
||||||
|
(dram_bd->surface_format == (uint8_t)PVA_SURF_FMT_BLOCK_LINEAR);
|
||||||
|
uint32_t line_pitch = get_slot_line_pitch(descs, static_relocs, slot);
|
||||||
|
struct pva_kmd_resource_record *resource_record =
|
||||||
|
pva_kmd_peek_resource(dma_aux->res_table, dram_bd->resource_id);
|
||||||
|
struct pva_kmd_dram_resource *dram_res;
|
||||||
|
uint64_t slot_offset_pl;
|
||||||
|
uint64_t surface_base_addr;
|
||||||
|
uint64_t max_surface_size;
|
||||||
|
uint64_t sector_pack_format = 0;
|
||||||
|
int64_t slot_access_start_addr = 0LL;
|
||||||
|
int64_t slot_access_end_addr = 0LL;
|
||||||
|
uint64_t slot_surface_combined_offset = 0ULL;
|
||||||
|
uint64_t adjusted_max_surface_size = 0ULL;
|
||||||
|
pva_math_error math_error = MATH_OP_SUCCESS;
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
if (resource_record == NULL) {
|
||||||
|
return PVA_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dram_res = &resource_record->dram;
|
||||||
|
slot_offset_pl = dram_bd->slot_offset;
|
||||||
|
surface_base_addr =
|
||||||
|
sat_add64(dram_bd->surface_base_offset, dram_res->mem->iova);
|
||||||
|
/* When binding a buffer, we add the binding->surface_base_offset to the
|
||||||
|
* buffer base address. Therefore, the effective buffer size is
|
||||||
|
* reduced by the offset. */
|
||||||
|
max_surface_size =
|
||||||
|
sat_sub64(dram_res->mem->size, dram_bd->surface_base_offset);
|
||||||
|
|
||||||
|
/* Validate slot flags and access permissions */
|
||||||
|
err = validate_dram_slot_flags(slot, dram_res);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle block linear specific setup if needed */
|
||||||
|
if (is_block_linear) {
|
||||||
|
err = setup_block_linear_params(dma_config, dma_aux, slot,
|
||||||
|
dram_bd, surface_base_addr,
|
||||||
|
line_pitch, &max_surface_size,
|
||||||
|
§or_pack_format);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate and validate slot offsets and ranges */
|
||||||
|
|
||||||
|
err = calculate_slot_offsets(slot, dram_bd, max_surface_size,
|
||||||
|
&slot_access_start_addr,
|
||||||
|
&slot_access_end_addr,
|
||||||
|
&slot_surface_combined_offset,
|
||||||
|
&adjusted_max_surface_size, &math_error);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate_slot_access_bounds(slot_access_start_addr,
|
||||||
|
slot_access_end_addr,
|
||||||
|
adjusted_max_surface_size,
|
||||||
|
math_error);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = process_slot_relocations(dma_config, slot, static_relocs, dram_bd,
|
||||||
|
surface_base_addr, slot_offset_pl,
|
||||||
|
sector_pack_format, line_pitch,
|
||||||
|
is_block_linear);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -256,18 +392,21 @@ bind_static_vmem_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
struct pva_fw_dma_reloc const *static_relocs,
|
struct pva_fw_dma_reloc const *static_relocs,
|
||||||
struct pva_dma_vmem_binding const *vmem_bd)
|
struct pva_dma_vmem_binding const *vmem_bd)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
|
||||||
struct pva_fw_dma_descriptor *descs =
|
struct pva_fw_dma_descriptor *descs =
|
||||||
pva_dma_config_get_descriptors(dma_config);
|
pva_dma_config_get_descriptors(dma_config);
|
||||||
struct pva_kmd_vpu_bin_resource *vpu_bin;
|
struct pva_kmd_vpu_bin_resource *vpu_bin;
|
||||||
struct pva_symbol_info *sym;
|
struct pva_symbol_info *sym;
|
||||||
uint32_t buffer_size, buffer_addr;
|
uint32_t buffer_size;
|
||||||
|
uint32_t buffer_addr;
|
||||||
struct pva_fw_dma_reloc const *relocs;
|
struct pva_fw_dma_reloc const *relocs;
|
||||||
enum pva_symbol_type needed_sym_type;
|
enum pva_symbol_type needed_sym_type;
|
||||||
|
struct pva_kmd_resource_record *vpu_res;
|
||||||
|
uint32_t i;
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
if (slot->flags & PVA_FW_DMA_SLOT_FLAG_VMEM_DATA) {
|
if ((slot->flags & PVA_FW_DMA_SLOT_FLAG_VMEM_DATA) != 0U) {
|
||||||
needed_sym_type = PVA_SYM_TYPE_DATA;
|
needed_sym_type = PVA_SYM_TYPE_DATA;
|
||||||
} else if (slot->flags & PVA_FW_DMA_SLOT_FLAG_VMEM_VPUC_TABLE) {
|
} else if ((slot->flags & PVA_FW_DMA_SLOT_FLAG_VMEM_VPUC_TABLE) != 0U) {
|
||||||
needed_sym_type = PVA_SYM_TYPE_VPUC_TABLE;
|
needed_sym_type = PVA_SYM_TYPE_VPUC_TABLE;
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_log_err("Unexpected VMEM slot flags");
|
pva_kmd_log_err("Unexpected VMEM slot flags");
|
||||||
@@ -275,13 +414,16 @@ bind_static_vmem_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WAR_PVAAS16267)
|
vpu_res = pva_kmd_peek_resource(dma_aux->res_table,
|
||||||
needed_sym_type = PVA_SYM_TYPE_DATA;
|
dma_aux->vpu_bin_res_id);
|
||||||
#endif
|
|
||||||
|
|
||||||
vpu_bin = &pva_kmd_peek_resource(dma_aux->res_table,
|
if (vpu_res == NULL) {
|
||||||
dma_aux->vpu_bin_res_id)
|
pva_kmd_log_err("Failed to get VPU resource");
|
||||||
->vpu_bin;
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpu_bin = &vpu_res->vpu_bin;
|
||||||
sym = pva_kmd_get_symbol_with_type(&vpu_bin->symbol_table,
|
sym = pva_kmd_get_symbol_with_type(&vpu_bin->symbol_table,
|
||||||
vmem_bd->addr.symbol_id,
|
vmem_bd->addr.symbol_id,
|
||||||
needed_sym_type);
|
needed_sym_type);
|
||||||
@@ -300,7 +442,7 @@ bind_static_vmem_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
relocs = &static_relocs[slot->reloc_start_idx];
|
relocs = &static_relocs[slot->reloc_start_idx];
|
||||||
for (uint32_t i = 0; i < slot->reloc_count; i++) {
|
for (i = 0; i < slot->reloc_count; i++) {
|
||||||
struct pva_fw_dma_reloc const *reloc = &relocs[i];
|
struct pva_fw_dma_reloc const *reloc = &relocs[i];
|
||||||
struct pva_fw_dma_descriptor *desc = &descs[reloc->desc_index];
|
struct pva_fw_dma_descriptor *desc = &descs[reloc->desc_index];
|
||||||
|
|
||||||
@@ -316,9 +458,12 @@ bind_static_vmem_slot(struct pva_dma_config_resource *dma_config,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CERT INT31-C: buffer_addr >> 6 cast to uint16_t then masked with 0x7FFF.
|
||||||
|
* The uint16_t cast naturally truncates to 16 bits, then mask keeps 15 bits.
|
||||||
|
* This is intentional for VMEM address computation. */
|
||||||
desc->frda =
|
desc->frda =
|
||||||
((uint16_t)(buffer_addr >> 6U) + desc->frda) &
|
((uint16_t)(buffer_addr >> 6U) + desc->frda) &
|
||||||
0x7FFF;
|
0x7FFFU;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +496,7 @@ enum pva_error pva_kmd_bind_static_buffers(
|
|||||||
struct pva_dma_static_binding const *binding =
|
struct pva_dma_static_binding const *binding =
|
||||||
&static_bindings[slot_id];
|
&static_bindings[slot_id];
|
||||||
|
|
||||||
if (binding->type == PVA_DMA_STATIC_BINDING_DRAM) {
|
if (binding->type == (uint8_t)PVA_DMA_STATIC_BINDING_DRAM) {
|
||||||
err = bind_static_dram_slot(fw_dma_cfg_hdr, dma_aux,
|
err = bind_static_dram_slot(fw_dma_cfg_hdr, dma_aux,
|
||||||
st_slot, static_relocs,
|
st_slot, static_relocs,
|
||||||
&binding->dram);
|
&binding->dram);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
#include "pva_math_utils.h"
|
#include "pva_math_utils.h"
|
||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
struct pva_fw_dma_reloc_slot_info {
|
struct pva_fw_dma_reloc_slot_info {
|
||||||
struct pva_fw_dma_slot *slots;
|
struct pva_fw_dma_slot *slots;
|
||||||
@@ -51,7 +52,9 @@ validate_channel_mapping(struct pva_dma_config const *out_cfg,
|
|||||||
for (uint8_t i = 0U; i < cfg_hdr->num_channels; i++) {
|
for (uint8_t i = 0U; i < cfg_hdr->num_channels; i++) {
|
||||||
channel = &out_cfg->channels[i];
|
channel = &out_cfg->channels[i];
|
||||||
if ((channel->desc_index >= out_cfg->header.num_descriptors) ||
|
if ((channel->desc_index >= out_cfg->header.num_descriptors) ||
|
||||||
(pva_is_reserved_desc(channel->desc_index))) {
|
(pva_is_reserved_desc(addu8(channel->desc_index,
|
||||||
|
cfg_hdr->base_descriptor,
|
||||||
|
&math_err)))) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"ERR: Invalid Channel Descriptor Index");
|
"ERR: Invalid Channel Descriptor Index");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
@@ -98,22 +101,22 @@ static bool is_valid_vpu_trigger_mode(const struct pva_dma_descriptor *desc)
|
|||||||
bool valid = true;
|
bool valid = true;
|
||||||
if (desc->trig_event_mode != 0U) {
|
if (desc->trig_event_mode != 0U) {
|
||||||
switch (desc->trig_vpu_events) {
|
switch (desc->trig_vpu_events) {
|
||||||
case PVA_DMA_NO_TRIG:
|
case (uint8_t)PVA_DMA_NO_TRIG:
|
||||||
//HW Sequencer check
|
//HW Sequencer check
|
||||||
break;
|
break;
|
||||||
case PVA_DMA_TRIG_VPU_CFG:
|
case (uint8_t)PVA_DMA_TRIG_VPU_CFG:
|
||||||
if (desc->src.transfer_mode !=
|
if (desc->src.transfer_mode !=
|
||||||
PVA_DMA_TRANS_MODE_VPUCFG) {
|
(uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PVA_DMA_TRIG_READ0:
|
case (uint8_t)PVA_DMA_TRIG_READ0:
|
||||||
case PVA_DMA_TRIG_READ1:
|
case (uint8_t)PVA_DMA_TRIG_READ1:
|
||||||
case PVA_DMA_TRIG_READ2:
|
case (uint8_t)PVA_DMA_TRIG_READ2:
|
||||||
case PVA_DMA_TRIG_READ3:
|
case (uint8_t)PVA_DMA_TRIG_READ3:
|
||||||
case PVA_DMA_TRIG_READ4:
|
case (uint8_t)PVA_DMA_TRIG_READ4:
|
||||||
case PVA_DMA_TRIG_READ5:
|
case (uint8_t)PVA_DMA_TRIG_READ5:
|
||||||
case PVA_DMA_TRIG_READ6:
|
case (uint8_t)PVA_DMA_TRIG_READ6:
|
||||||
if ((desc->src.transfer_mode !=
|
if ((desc->src.transfer_mode !=
|
||||||
(uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) &&
|
(uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) &&
|
||||||
(desc->dst.transfer_mode !=
|
(desc->dst.transfer_mode !=
|
||||||
@@ -121,13 +124,13 @@ static bool is_valid_vpu_trigger_mode(const struct pva_dma_descriptor *desc)
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PVA_DMA_TRIG_WRITE0:
|
case (uint8_t)PVA_DMA_TRIG_WRITE0:
|
||||||
case PVA_DMA_TRIG_WRITE1:
|
case (uint8_t)PVA_DMA_TRIG_WRITE1:
|
||||||
case PVA_DMA_TRIG_WRITE2:
|
case (uint8_t)PVA_DMA_TRIG_WRITE2:
|
||||||
case PVA_DMA_TRIG_WRITE3:
|
case (uint8_t)PVA_DMA_TRIG_WRITE3:
|
||||||
case PVA_DMA_TRIG_WRITE4:
|
case (uint8_t)PVA_DMA_TRIG_WRITE4:
|
||||||
case PVA_DMA_TRIG_WRITE5:
|
case (uint8_t)PVA_DMA_TRIG_WRITE5:
|
||||||
case PVA_DMA_TRIG_WRITE6:
|
case (uint8_t)PVA_DMA_TRIG_WRITE6:
|
||||||
if ((desc->src.transfer_mode !=
|
if ((desc->src.transfer_mode !=
|
||||||
(uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) &&
|
(uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) &&
|
||||||
(desc->src.transfer_mode !=
|
(desc->src.transfer_mode !=
|
||||||
@@ -173,6 +176,88 @@ static bool validate_src_dst_adv_val(const struct pva_dma_descriptor *desc,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate DMA descriptor transfer control modes
|
||||||
|
*
|
||||||
|
* @details This function validates the source and destination transfer modes
|
||||||
|
* for a DMA descriptor to ensure they form a valid combination according to
|
||||||
|
* hardware constraints. It performs the following operations:
|
||||||
|
* - Validates source transfer mode (VMEM, DRAM, L2SRAM, VPUCFG)
|
||||||
|
* - For VPUCFG sources, skips destination validation (VPUCFG is special case)
|
||||||
|
* - For non-VPUCFG sources, validates destination transfer mode
|
||||||
|
* - Enforces MMIO destination only with VPUCFG source
|
||||||
|
* - Restricts TCM destination to test mode only
|
||||||
|
* - Ensures transfer mode combinations are hardware-compatible
|
||||||
|
*
|
||||||
|
* Valid transfer mode combinations:
|
||||||
|
* - VMEM/DRAM/L2SRAM -> VMEM/DRAM/L2SRAM (standard transfers)
|
||||||
|
* - VPUCFG -> Any (VPU configuration transfers - validated separately)
|
||||||
|
* - Non-VPUCFG -> MMIO (rejected as invalid)
|
||||||
|
* - Any -> TCM (only in test mode)
|
||||||
|
*
|
||||||
|
* @param[in] desc Pointer to DMA descriptor to validate
|
||||||
|
* Valid value: non-null, properly initialized descriptor
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Transfer modes validated successfully
|
||||||
|
* @retval PVA_INVAL Invalid transfer mode or unsupported combination
|
||||||
|
*/
|
||||||
|
static enum pva_error
|
||||||
|
validate_dma_desc_trans_cntl0(const struct pva_dma_descriptor *desc)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
bool valid_src = false;
|
||||||
|
|
||||||
|
/* Validate source transfer mode */
|
||||||
|
switch (desc->src.transfer_mode) {
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_VMEM:
|
||||||
|
valid_src = true;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_DRAM:
|
||||||
|
valid_src = true;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_L2SRAM:
|
||||||
|
valid_src = true;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_VPUCFG:
|
||||||
|
valid_src = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
valid_src = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid_src) {
|
||||||
|
err = PVA_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For VPUCFG source, skip destination validation (early exit) */
|
||||||
|
if ((err != PVA_SUCCESS) ||
|
||||||
|
(desc->src.transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_VPUCFG)) {
|
||||||
|
/* Function exit point for VPUCFG or error cases */
|
||||||
|
} else {
|
||||||
|
/* Validate destination transfer mode for non-VPUCFG sources */
|
||||||
|
switch (desc->dst.transfer_mode) {
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_L2SRAM:
|
||||||
|
err = PVA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_VMEM:
|
||||||
|
err = PVA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_DRAM:
|
||||||
|
err = PVA_SUCCESS;
|
||||||
|
break;
|
||||||
|
case (uint8_t)PVA_DMA_TRANS_MODE_MMIO:
|
||||||
|
/* MMIO only valid with VPUCFG source (already filtered out) */
|
||||||
|
err = PVA_INVAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = PVA_INVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
validate_dma_desc_trans_cntl2(const struct pva_dma_descriptor *desc)
|
validate_dma_desc_trans_cntl2(const struct pva_dma_descriptor *desc)
|
||||||
{
|
{
|
||||||
@@ -187,12 +272,13 @@ validate_dma_desc_trans_cntl2(const struct pva_dma_descriptor *desc)
|
|||||||
|
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
validate_descriptor(const struct pva_dma_descriptor *desc,
|
validate_descriptor(const struct pva_dma_descriptor *desc,
|
||||||
struct pva_dma_config_header const *cfg_hdr)
|
struct pva_dma_config_header const *cfg_hdr,
|
||||||
|
bool relax_dim3_check)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
err = validate_padding(desc);
|
err = validate_padding(desc);
|
||||||
if ((desc->dst.transfer_mode == PVA_DMA_TRANS_MODE_VMEM) &&
|
if ((desc->dst.transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_VMEM) &&
|
||||||
(err != PVA_SUCCESS)) {
|
(err != PVA_SUCCESS)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -203,12 +289,16 @@ validate_descriptor(const struct pva_dma_descriptor *desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Check src/dstADV values with respect to ECET bits */
|
/** Check src/dstADV values with respect to ECET bits */
|
||||||
if (false == validate_src_dst_adv_val(desc, false)) {
|
if (false == validate_src_dst_adv_val(desc, relax_dim3_check)) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Invalid src/dst ADV values with respect to ECET");
|
"Invalid src/dst ADV values with respect to ECET");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PVA_SUCCESS != validate_dma_desc_trans_cntl0(desc)) {
|
||||||
|
pva_kmd_log_err("Bad trans cntl 0");
|
||||||
|
return PVA_INVAL;
|
||||||
|
}
|
||||||
/* DMA_DESC_TRANS CNTL2 */
|
/* DMA_DESC_TRANS CNTL2 */
|
||||||
if (PVA_SUCCESS != validate_dma_desc_trans_cntl2(desc)) {
|
if (PVA_SUCCESS != validate_dma_desc_trans_cntl2(desc)) {
|
||||||
pva_kmd_log_err("Bad trans cntl 2");
|
pva_kmd_log_err("Bad trans cntl 2");
|
||||||
@@ -216,9 +306,11 @@ validate_descriptor(const struct pva_dma_descriptor *desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* DMA_DESC_LDID */
|
/* DMA_DESC_LDID */
|
||||||
if ((desc->link_desc_id > cfg_hdr->num_descriptors) ||
|
if ((desc->link_desc_id - cfg_hdr->base_descriptor >
|
||||||
((desc->link_desc_id != 0) &&
|
cfg_hdr->num_descriptors) ||
|
||||||
pva_is_reserved_desc(desc->link_desc_id - PVA_DMA_DESC_ID_BASE))) {
|
((desc->link_desc_id != 0U) &&
|
||||||
|
pva_is_reserved_desc(desc->link_desc_id -
|
||||||
|
(uint8_t)PVA_DMA_DESC_ID_BASE))) {
|
||||||
pva_kmd_log_err("ERR: Invalid linker Desc ID");
|
pva_kmd_log_err("ERR: Invalid linker Desc ID");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
@@ -233,6 +325,57 @@ struct pva_kmd_offset_pairs {
|
|||||||
|
|
||||||
#define PVA_KMD_DMA_CONFIG_ARRAY_COUNT 4U
|
#define PVA_KMD_DMA_CONFIG_ARRAY_COUNT 4U
|
||||||
|
|
||||||
|
static bool
|
||||||
|
validate_dma_config_bounds(struct pva_dma_config_header const *cfg_hdr,
|
||||||
|
struct pva_kmd_hw_constants const *hw_consts)
|
||||||
|
{
|
||||||
|
bool is_valid = true;
|
||||||
|
|
||||||
|
if ((((uint32_t)cfg_hdr->base_descriptor +
|
||||||
|
(uint32_t)cfg_hdr->num_descriptors) >
|
||||||
|
hw_consts->n_dma_descriptors) ||
|
||||||
|
(((uint32_t)cfg_hdr->base_channel +
|
||||||
|
(uint32_t)cfg_hdr->num_channels) >
|
||||||
|
(hw_consts->n_user_dma_channels + 1U)) ||
|
||||||
|
(((uint32_t)cfg_hdr->base_hwseq_word +
|
||||||
|
(uint32_t)cfg_hdr->num_hwseq_words) > hw_consts->n_hwseq_words) ||
|
||||||
|
(cfg_hdr->num_static_slots > PVA_KMD_MAX_NUM_DMA_SLOTS) ||
|
||||||
|
(cfg_hdr->num_dynamic_slots > PVA_KMD_MAX_NUM_DMA_RELOCS) ||
|
||||||
|
(cfg_hdr->base_channel == 0U)) {
|
||||||
|
is_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool validate_dma_offsets(struct pva_kmd_offset_pairs const *offsets,
|
||||||
|
uint32_t dma_config_size)
|
||||||
|
{
|
||||||
|
bool is_valid = true;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
//Validate:
|
||||||
|
// 1. All start offsets are aligned to 8 bytes
|
||||||
|
// 2. All end offsets are within the dma_config_size
|
||||||
|
// Note: We do not check if the ranges overlap because we do not modify the buffer in place.
|
||||||
|
for (i = 0; i < PVA_KMD_DMA_CONFIG_ARRAY_COUNT; i++) {
|
||||||
|
if ((offsets[i].start % 8U) != 0U) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"DMA config field offset is not aligned to 8 bytes");
|
||||||
|
is_valid = false;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (offsets[i].end > dma_config_size) {
|
||||||
|
pva_kmd_log_err("DMA config field is out of bounds");
|
||||||
|
is_valid = false;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
is_dma_config_header_valid(struct pva_ops_dma_config_register const *ops_hdr,
|
is_dma_config_header_valid(struct pva_ops_dma_config_register const *ops_hdr,
|
||||||
uint32_t dma_config_size,
|
uint32_t dma_config_size,
|
||||||
@@ -241,31 +384,27 @@ is_dma_config_header_valid(struct pva_ops_dma_config_register const *ops_hdr,
|
|||||||
struct pva_kmd_offset_pairs offsets[PVA_KMD_DMA_CONFIG_ARRAY_COUNT];
|
struct pva_kmd_offset_pairs offsets[PVA_KMD_DMA_CONFIG_ARRAY_COUNT];
|
||||||
struct pva_dma_config_header const *cfg_hdr;
|
struct pva_dma_config_header const *cfg_hdr;
|
||||||
pva_math_error math_err = MATH_OP_SUCCESS;
|
pva_math_error math_err = MATH_OP_SUCCESS;
|
||||||
|
bool is_valid = true;
|
||||||
|
|
||||||
if (dma_config_size < sizeof(*ops_hdr)) {
|
if (dma_config_size < sizeof(*ops_hdr)) {
|
||||||
pva_kmd_log_err("DMA configuration too small");
|
pva_kmd_log_err("DMA configuration too small");
|
||||||
return PVA_INVAL;
|
is_valid = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_hdr = &ops_hdr->dma_config_header;
|
cfg_hdr = &ops_hdr->dma_config_header;
|
||||||
|
|
||||||
if (((cfg_hdr->base_descriptor + cfg_hdr->num_descriptors) >
|
if (!validate_dma_config_bounds(cfg_hdr, hw_consts)) {
|
||||||
hw_consts->n_dma_descriptors) ||
|
is_valid = false;
|
||||||
((cfg_hdr->base_channel + cfg_hdr->num_channels) >
|
goto out;
|
||||||
(hw_consts->n_user_dma_channels + 1U)) ||
|
|
||||||
((cfg_hdr->base_hwseq_word + cfg_hdr->num_hwseq_words) >
|
|
||||||
hw_consts->n_hwseq_words) ||
|
|
||||||
(cfg_hdr->num_static_slots > PVA_KMD_MAX_NUM_DMA_SLOTS) ||
|
|
||||||
(cfg_hdr->num_dynamic_slots > PVA_KMD_MAX_NUM_DMA_RELOCS) ||
|
|
||||||
(cfg_hdr->base_channel == 0U)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets[0].start = ops_hdr->channels_offset;
|
offsets[0].start = ops_hdr->channels_offset;
|
||||||
offsets[0].end = addu32(
|
offsets[0].end = addu32(
|
||||||
ops_hdr->channels_offset,
|
ops_hdr->channels_offset,
|
||||||
align8_u32(mulu32(cfg_hdr->num_channels,
|
align8_u32(mulu32(cfg_hdr->num_channels,
|
||||||
sizeof(struct pva_dma_channel), &math_err),
|
(uint32_t)sizeof(struct pva_dma_channel),
|
||||||
|
&math_err),
|
||||||
&math_err),
|
&math_err),
|
||||||
&math_err);
|
&math_err);
|
||||||
|
|
||||||
@@ -273,14 +412,16 @@ is_dma_config_header_valid(struct pva_ops_dma_config_register const *ops_hdr,
|
|||||||
offsets[1].end = addu32(
|
offsets[1].end = addu32(
|
||||||
ops_hdr->descriptors_offset,
|
ops_hdr->descriptors_offset,
|
||||||
align8_u32(mulu32(cfg_hdr->num_descriptors,
|
align8_u32(mulu32(cfg_hdr->num_descriptors,
|
||||||
sizeof(struct pva_dma_descriptor), &math_err),
|
(uint32_t)sizeof(struct pva_dma_descriptor),
|
||||||
|
&math_err),
|
||||||
&math_err),
|
&math_err),
|
||||||
&math_err);
|
&math_err);
|
||||||
|
|
||||||
offsets[2].start = ops_hdr->hwseq_words_offset;
|
offsets[2].start = ops_hdr->hwseq_words_offset;
|
||||||
offsets[2].end = addu32(ops_hdr->hwseq_words_offset,
|
offsets[2].end =
|
||||||
|
addu32(ops_hdr->hwseq_words_offset,
|
||||||
align8_u32(mulu32(cfg_hdr->num_hwseq_words,
|
align8_u32(mulu32(cfg_hdr->num_hwseq_words,
|
||||||
sizeof(uint32_t), &math_err),
|
(uint32_t)sizeof(uint32_t), &math_err),
|
||||||
&math_err),
|
&math_err),
|
||||||
&math_err);
|
&math_err);
|
||||||
|
|
||||||
@@ -288,45 +429,38 @@ is_dma_config_header_valid(struct pva_ops_dma_config_register const *ops_hdr,
|
|||||||
offsets[3].end =
|
offsets[3].end =
|
||||||
addu32(ops_hdr->static_bindings_offset,
|
addu32(ops_hdr->static_bindings_offset,
|
||||||
align8_u32(mulu32(cfg_hdr->num_static_slots,
|
align8_u32(mulu32(cfg_hdr->num_static_slots,
|
||||||
sizeof(struct pva_dma_static_binding),
|
(uint32_t)sizeof(
|
||||||
|
struct pva_dma_static_binding),
|
||||||
&math_err),
|
&math_err),
|
||||||
&math_err),
|
&math_err),
|
||||||
&math_err);
|
&math_err);
|
||||||
|
|
||||||
if (math_err != MATH_OP_SUCCESS) {
|
if (math_err != MATH_OP_SUCCESS) {
|
||||||
pva_kmd_log_err("DMA config field offset math error");
|
pva_kmd_log_err("DMA config field offset math error");
|
||||||
return false;
|
is_valid = false;
|
||||||
}
|
goto out;
|
||||||
//Validate:
|
|
||||||
// 1. All start offsets are aligned to 8 bytes
|
|
||||||
// 2. All end offsets are within the dma_config_size
|
|
||||||
// Note: We do not check if the ranges overlap because we do not modify the buffer in place.
|
|
||||||
for (uint32_t i = 0; i < PVA_KMD_DMA_CONFIG_ARRAY_COUNT; i++) {
|
|
||||||
if (offsets[i].start % 8 != 0) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"DMA config field offset is not aligned to 8 bytes");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (offsets[i].end > dma_config_size) {
|
|
||||||
pva_kmd_log_err("DMA config field is out of bounds");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (!validate_dma_offsets(offsets, dma_config_size)) {
|
||||||
|
is_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error pva_kmd_parse_dma_config(
|
||||||
pva_kmd_parse_dma_config(const struct pva_ops_dma_config_register *ops_hdr,
|
const struct pva_ops_dma_config_register *ops_hdr,
|
||||||
uint32_t dma_config_size,
|
uint32_t dma_config_size, struct pva_dma_config *out_cfg,
|
||||||
struct pva_dma_config *out_cfg,
|
struct pva_kmd_hw_constants const *hw_consts, bool skip_validation)
|
||||||
struct pva_kmd_hw_constants const *hw_consts)
|
|
||||||
{
|
{
|
||||||
|
if (!skip_validation) { // Skip validation for PFSD and test mode
|
||||||
if (!(is_dma_config_header_valid(ops_hdr, dma_config_size,
|
if (!(is_dma_config_header_valid(ops_hdr, dma_config_size,
|
||||||
hw_consts))) {
|
hw_consts))) {
|
||||||
pva_kmd_log_err("Invalid PVA DMA Configuration Header");
|
pva_kmd_log_err("Invalid PVA DMA Configuration Header");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out_cfg->header = ops_hdr->dma_config_header;
|
out_cfg->header = ops_hdr->dma_config_header;
|
||||||
|
|
||||||
@@ -346,46 +480,59 @@ pva_kmd_parse_dma_config(const struct pva_ops_dma_config_register *ops_hdr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
validate_descriptors(const struct pva_dma_config *dma_config)
|
validate_descriptors(const struct pva_dma_config *dma_config,
|
||||||
|
uint64_t const *hw_dma_descs_mask)
|
||||||
{
|
{
|
||||||
uint32_t i = 0U;
|
uint8_t i = 0U;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
const struct pva_dma_config_header *cfg_hdr = &dma_config->header;
|
const struct pva_dma_config_header *cfg_hdr = &dma_config->header;
|
||||||
const struct pva_dma_descriptor *desc;
|
const struct pva_dma_descriptor *desc;
|
||||||
|
bool relax_dim3_check = true;
|
||||||
|
uint8_t desc_id;
|
||||||
|
pva_math_error math_err = MATH_OP_SUCCESS;
|
||||||
|
|
||||||
for (i = 0; i < cfg_hdr->num_descriptors; i++) {
|
for (i = 0U; i < cfg_hdr->num_descriptors; i++) {
|
||||||
if (pva_is_reserved_desc(i)) {
|
desc_id = addu8(i, cfg_hdr->base_descriptor, &math_err);
|
||||||
|
if (pva_is_reserved_desc(desc_id)) {
|
||||||
// skip over the reserved descriptor range
|
// skip over the reserved descriptor range
|
||||||
i = PVA_RESERVED_DESCRIPTORS_END;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relax_dim3_check =
|
||||||
|
((hw_dma_descs_mask[desc_id / 64ULL] &
|
||||||
|
(1ULL << (desc_id & MAX_DESC_ID))) != 0ULL);
|
||||||
|
|
||||||
desc = &dma_config->descriptors[i];
|
desc = &dma_config->descriptors[i];
|
||||||
err = validate_descriptor(desc, cfg_hdr);
|
err = validate_descriptor(desc, cfg_hdr, relax_dim3_check);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (math_err != MATH_OP_SUCCESS) {
|
||||||
|
pva_kmd_log_err("validate_descriptors math error");
|
||||||
|
return PVA_ERR_MATH_OP;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_validate_dma_config(struct pva_dma_config const *dma_config,
|
pva_kmd_validate_dma_config(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_hw_constants const *hw_consts,
|
struct pva_kmd_hw_constants const *hw_consts,
|
||||||
struct pva_kmd_dma_access *access_sizes,
|
struct pva_kmd_dma_access *access_sizes,
|
||||||
uint64_t *hw_dma_descs_mask)
|
uint64_t *hw_dma_descs_mask)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
err = validate_channel_mapping(dma_config, hw_consts);
|
err = validate_channel_mapping(dma_cfg, hw_consts);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Bad Channels");
|
pva_kmd_log_err("Bad Channels");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dma_config->header.num_hwseq_words != 0U) {
|
if (dma_cfg->header.num_hwseq_words != 0U) {
|
||||||
err = validate_hwseq(dma_config, hw_consts, access_sizes,
|
err = validate_hwseq(dma_cfg, hw_consts, access_sizes,
|
||||||
hw_dma_descs_mask);
|
hw_dma_descs_mask);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Bad HW Sequencer Blob");
|
pva_kmd_log_err("Bad HW Sequencer Blob");
|
||||||
@@ -393,7 +540,7 @@ pva_kmd_validate_dma_config(struct pva_dma_config const *dma_config,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validate_descriptors(dma_config);
|
err = validate_descriptors(dma_cfg, hw_dma_descs_mask);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Bad Descriptors");
|
pva_kmd_log_err("Bad Descriptors");
|
||||||
return err;
|
return err;
|
||||||
@@ -402,6 +549,98 @@ pva_kmd_validate_dma_config(struct pva_dma_config const *dma_config,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
use_vpu_bin_resource(struct pva_dma_config const *dma_cfg,
|
||||||
|
struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
|
struct pva_kmd_vpu_bin_resource **vpu_bin)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_kmd_resource_record *vpu_bin_rec;
|
||||||
|
|
||||||
|
*vpu_bin = NULL;
|
||||||
|
|
||||||
|
if (dma_cfg->header.vpu_exec_resource_id == PVA_RESOURCE_ID_INVALID) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpu_bin_rec = pva_kmd_use_resource_unsafe(
|
||||||
|
dma_aux->res_table, dma_cfg->header.vpu_exec_resource_id);
|
||||||
|
if (vpu_bin_rec == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"VPU exec resource id used by DMA config does not exist");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_aux->vpu_bin_res_id = dma_cfg->header.vpu_exec_resource_id;
|
||||||
|
|
||||||
|
if (vpu_bin_rec->type != PVA_RESOURCE_TYPE_EXEC_BIN) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Invalid VPU exec resource id used by DMA config");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
||||||
|
dma_aux->vpu_bin_res_id);
|
||||||
|
dma_aux->vpu_bin_res_id = PVA_RESOURCE_ID_INVALID;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*vpu_bin = &vpu_bin_rec->vpu_bin;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
process_static_dram_binding(struct pva_kmd_dma_resource_aux *dma_aux,
|
||||||
|
struct pva_dma_static_binding const *slot_buf)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_kmd_resource_record *rec;
|
||||||
|
|
||||||
|
rec = pva_kmd_use_resource_unsafe(dma_aux->res_table,
|
||||||
|
slot_buf->dram.resource_id);
|
||||||
|
if (rec == NULL) {
|
||||||
|
pva_kmd_log_err("DRAM buffers used by DMA config do not exist");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_aux->static_dram_res_ids[dma_aux->dram_res_count] =
|
||||||
|
slot_buf->dram.resource_id;
|
||||||
|
dma_aux->dram_res_count = safe_addu32(dma_aux->dram_res_count, 1U);
|
||||||
|
|
||||||
|
if (rec->type != PVA_RESOURCE_TYPE_DRAM) {
|
||||||
|
pva_kmd_log_err("Invalid DRAM resource id used DMA config");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
process_static_vmem_binding(struct pva_kmd_vpu_bin_resource *vpu_bin,
|
||||||
|
struct pva_dma_static_binding const *slot_buf)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
if (vpu_bin == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"VPU bin resource not found for static VMEM buffer");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pva_kmd_get_symbol(&vpu_bin->symbol_table,
|
||||||
|
slot_buf->vmem.addr.symbol_id) == NULL) {
|
||||||
|
pva_kmd_log_err("Invalid VMEM symbol ID");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_kmd_dma_resource_aux *dma_aux)
|
struct pva_kmd_dma_resource_aux *dma_aux)
|
||||||
@@ -411,28 +650,10 @@ pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
/* Increment reference count for VPU bin */
|
/* Increment reference count for VPU bin */
|
||||||
if (dma_cfg->header.vpu_exec_resource_id != PVA_RESOURCE_ID_INVALID) {
|
err = use_vpu_bin_resource(dma_cfg, dma_aux, &vpu_bin);
|
||||||
struct pva_kmd_resource_record *vpu_bin_rec;
|
if (err != PVA_SUCCESS) {
|
||||||
|
|
||||||
vpu_bin_rec = pva_kmd_use_resource_unsafe(
|
|
||||||
dma_aux->res_table,
|
|
||||||
dma_cfg->header.vpu_exec_resource_id);
|
|
||||||
if (vpu_bin_rec == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"VPU exec resource id used by DMA config does not exist");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
dma_aux->vpu_bin_res_id = dma_cfg->header.vpu_exec_resource_id;
|
|
||||||
|
|
||||||
if (vpu_bin_rec->type != PVA_RESOURCE_TYPE_EXEC_BIN) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"Invalid VPU exec resource id used by DMA config");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto drop_vpu_bin;
|
|
||||||
}
|
|
||||||
vpu_bin = &vpu_bin_rec->vpu_bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment reference count for all static DRAM buffers; For static
|
/* Increment reference count for all static DRAM buffers; For static
|
||||||
* VMEM buffers, check that symbol ID is valid. */
|
* VMEM buffers, check that symbol ID is valid. */
|
||||||
@@ -440,58 +661,31 @@ pva_kmd_dma_use_resources(struct pva_dma_config const *dma_cfg,
|
|||||||
struct pva_dma_static_binding const *slot_buf =
|
struct pva_dma_static_binding const *slot_buf =
|
||||||
&dma_cfg->static_bindings[i];
|
&dma_cfg->static_bindings[i];
|
||||||
|
|
||||||
if (slot_buf->type == PVA_DMA_STATIC_BINDING_DRAM) {
|
if (slot_buf->type == (uint8_t)PVA_DMA_STATIC_BINDING_DRAM) {
|
||||||
struct pva_kmd_resource_record *rec;
|
err = process_static_dram_binding(dma_aux, slot_buf);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
rec = pva_kmd_use_resource_unsafe(
|
goto drop_resources;
|
||||||
dma_aux->res_table, slot_buf->dram.resource_id);
|
|
||||||
if (rec == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"DRAM buffers used by DMA config do not exist");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto drop_dram;
|
|
||||||
}
|
}
|
||||||
|
} else if (slot_buf->type ==
|
||||||
dma_aux->static_dram_res_ids[dma_aux->dram_res_count] =
|
(uint8_t)PVA_DMA_STATIC_BINDING_VMEM) {
|
||||||
slot_buf->dram.resource_id;
|
err = process_static_vmem_binding(vpu_bin, slot_buf);
|
||||||
dma_aux->dram_res_count =
|
if (err != PVA_SUCCESS) {
|
||||||
safe_addu32(dma_aux->dram_res_count, 1U);
|
goto drop_resources;
|
||||||
|
|
||||||
if (rec->type != PVA_RESOURCE_TYPE_DRAM) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"Invalid DRAM resource id used DMA config");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto drop_dram;
|
|
||||||
}
|
|
||||||
} else if (slot_buf->type == PVA_DMA_STATIC_BINDING_VMEM) {
|
|
||||||
if (vpu_bin == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"VPU bin resource not found for static VMEM buffer");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto drop_dram;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pva_kmd_get_symbol(&vpu_bin->symbol_table,
|
|
||||||
slot_buf->vmem.addr.symbol_id) ==
|
|
||||||
NULL) {
|
|
||||||
pva_kmd_log_err("Invalid VMEM symbol ID");
|
|
||||||
err = PVA_INVAL;
|
|
||||||
goto drop_dram;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_log_err("Invalid slot buffer type");
|
pva_kmd_log_err("Invalid slot buffer type");
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
goto drop_dram;
|
goto drop_resources;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
drop_dram:
|
drop_resources:
|
||||||
for (i = 0; i < dma_aux->dram_res_count; i++) {
|
for (i = 0; i < dma_aux->dram_res_count; i++) {
|
||||||
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
||||||
dma_aux->static_dram_res_ids[i]);
|
dma_aux->static_dram_res_ids[i]);
|
||||||
}
|
}
|
||||||
drop_vpu_bin:
|
/* Drop VPU bin if it was acquired */
|
||||||
if (dma_aux->vpu_bin_res_id != PVA_RESOURCE_ID_INVALID) {
|
if (dma_aux->vpu_bin_res_id != PVA_RESOURCE_ID_INVALID) {
|
||||||
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
pva_kmd_drop_resource_unsafe(dma_aux->res_table,
|
||||||
dma_aux->vpu_bin_res_id);
|
dma_aux->vpu_bin_res_id);
|
||||||
@@ -509,13 +703,13 @@ static uint16_t get_slot_flag(uint8_t transfer_mode, bool cb_enable,
|
|||||||
bool is_dst)
|
bool is_dst)
|
||||||
{
|
{
|
||||||
uint16_t flags = 0;
|
uint16_t flags = 0;
|
||||||
if (transfer_mode == PVA_DMA_TRANS_MODE_VMEM) {
|
if (transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_VMEM) {
|
||||||
flags |= PVA_FW_DMA_SLOT_FLAG_VMEM_DATA;
|
flags |= PVA_FW_DMA_SLOT_FLAG_VMEM_DATA;
|
||||||
} else if (transfer_mode == PVA_DMA_TRANS_MODE_L2SRAM) {
|
} else if (transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_L2SRAM) {
|
||||||
flags |= PVA_FW_DMA_SLOT_FLAG_L2SRAM;
|
flags |= PVA_FW_DMA_SLOT_FLAG_L2SRAM;
|
||||||
} else if (transfer_mode == PVA_DMA_TRANS_MODE_DRAM) {
|
} else if (transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_DRAM) {
|
||||||
flags |= PVA_FW_DMA_SLOT_FLAG_DRAM;
|
flags |= PVA_FW_DMA_SLOT_FLAG_DRAM;
|
||||||
} else if (transfer_mode == PVA_DMA_TRANS_MODE_VPUCFG) {
|
} else if (transfer_mode == (uint8_t)PVA_DMA_TRANS_MODE_VPUCFG) {
|
||||||
flags |= PVA_FW_DMA_SLOT_FLAG_VMEM_VPUC_TABLE;
|
flags |= PVA_FW_DMA_SLOT_FLAG_VMEM_VPUC_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,11 +717,11 @@ static uint16_t get_slot_flag(uint8_t transfer_mode, bool cb_enable,
|
|||||||
flags |= PVA_FW_DMA_SLOT_FLAG_CB;
|
flags |= PVA_FW_DMA_SLOT_FLAG_CB;
|
||||||
}
|
}
|
||||||
if (is_dst) {
|
if (is_dst) {
|
||||||
flags |= PVA_INSERT(PVA_ACCESS_WO,
|
flags |= PVA_INSERT((uint32_t)PVA_ACCESS_WO,
|
||||||
PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
||||||
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB);
|
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB);
|
||||||
} else {
|
} else {
|
||||||
flags |= PVA_INSERT(PVA_ACCESS_RO,
|
flags |= PVA_INSERT((uint32_t)PVA_ACCESS_RO,
|
||||||
PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
PVA_FW_DMA_SLOT_FLAG_ACCESS_MSB,
|
||||||
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB);
|
PVA_FW_DMA_SLOT_FLAG_ACCESS_LSB);
|
||||||
}
|
}
|
||||||
@@ -541,14 +735,14 @@ static void update_reloc_count(uint16_t slot, uint8_t transfer_mode,
|
|||||||
struct pva_fw_dma_slot *out_dyn_slots,
|
struct pva_fw_dma_slot *out_dyn_slots,
|
||||||
uint16_t num_dyn_slots, bool is_dst)
|
uint16_t num_dyn_slots, bool is_dst)
|
||||||
{
|
{
|
||||||
uint8_t slot_id = get_slot_id(slot);
|
uint16_t slot_id = get_slot_id(slot);
|
||||||
|
|
||||||
if (slot & PVA_DMA_DYNAMIC_SLOT) {
|
if ((slot & PVA_DMA_DYNAMIC_SLOT) != 0U) {
|
||||||
out_dyn_slots[slot_id].reloc_count =
|
out_dyn_slots[slot_id].reloc_count =
|
||||||
safe_addu16(out_dyn_slots[slot_id].reloc_count, 1U);
|
safe_addu16(out_dyn_slots[slot_id].reloc_count, 1U);
|
||||||
out_dyn_slots[slot_id].flags |=
|
out_dyn_slots[slot_id].flags |=
|
||||||
get_slot_flag(transfer_mode, cb_enable, is_dst);
|
get_slot_flag(transfer_mode, cb_enable, is_dst);
|
||||||
} else if (slot & PVA_DMA_STATIC_SLOT) {
|
} else if ((slot & PVA_DMA_STATIC_SLOT) != 0U) {
|
||||||
out_static_slots[slot_id].reloc_count =
|
out_static_slots[slot_id].reloc_count =
|
||||||
safe_addu16(out_static_slots[slot_id].reloc_count, 1U);
|
safe_addu16(out_static_slots[slot_id].reloc_count, 1U);
|
||||||
out_static_slots[slot_id].flags |=
|
out_static_slots[slot_id].flags |=
|
||||||
@@ -562,31 +756,41 @@ static void count_relocs(struct pva_dma_config const *dma_cfg,
|
|||||||
struct pva_fw_dma_slot *out_dyn_slots,
|
struct pva_fw_dma_slot *out_dyn_slots,
|
||||||
uint16_t num_dyn_slots)
|
uint16_t num_dyn_slots)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i = 0U;
|
||||||
const struct pva_dma_descriptor *desc;
|
const struct pva_dma_descriptor *desc;
|
||||||
|
|
||||||
for (i = 0U; i < dma_cfg->header.num_descriptors; i++) {
|
/* CERT INT30-C: Use safe arithmetic to prevent potential wrap */
|
||||||
if (pva_is_reserved_desc(i)) {
|
while (i < dma_cfg->header.num_descriptors) {
|
||||||
|
uint8_t desc_id =
|
||||||
|
safe_addu8(i, dma_cfg->header.base_descriptor);
|
||||||
|
if (pva_is_reserved_desc(desc_id)) {
|
||||||
// skip over the reserved descriptor range
|
// skip over the reserved descriptor range
|
||||||
i = PVA_RESERVED_DESCRIPTORS_END;
|
/* CERT INT31-C: Use safe subtract to handle underflow gracefully */
|
||||||
|
i = safe_subu8(PVA_RESERVED_DESCRIPTORS_END,
|
||||||
|
dma_cfg->header.base_descriptor);
|
||||||
|
/* Skip to first descriptor after reserved range */
|
||||||
|
i = safe_addu8(i, 1U);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
desc = &dma_cfg->descriptors[i];
|
desc = &dma_cfg->descriptors[i];
|
||||||
|
|
||||||
update_reloc_count(desc->src.slot, desc->src.transfer_mode,
|
update_reloc_count(desc->src.slot, desc->src.transfer_mode,
|
||||||
desc->src.cb_enable, out_static_slots,
|
(bool)desc->src.cb_enable, out_static_slots,
|
||||||
num_static_slots, out_dyn_slots,
|
num_static_slots, out_dyn_slots,
|
||||||
num_dyn_slots, false);
|
num_dyn_slots, false);
|
||||||
|
|
||||||
update_reloc_count(desc->dst.slot, desc->dst.transfer_mode,
|
update_reloc_count(desc->dst.slot, desc->dst.transfer_mode,
|
||||||
desc->dst.cb_enable, out_static_slots,
|
(bool)desc->dst.cb_enable, out_static_slots,
|
||||||
num_static_slots, out_dyn_slots,
|
num_static_slots, out_dyn_slots,
|
||||||
num_dyn_slots, true);
|
num_dyn_slots, true);
|
||||||
|
|
||||||
update_reloc_count(desc->dst2_slot, desc->dst.transfer_mode,
|
update_reloc_count(desc->dst2_slot, desc->dst.transfer_mode,
|
||||||
desc->dst.cb_enable, out_static_slots,
|
(bool)desc->dst.cb_enable, out_static_slots,
|
||||||
num_static_slots, out_dyn_slots,
|
num_static_slots, out_dyn_slots,
|
||||||
num_dyn_slots, true);
|
num_dyn_slots, true);
|
||||||
|
|
||||||
|
/* CERT INT30-C: Use safe addition to prevent wrap */
|
||||||
|
i = safe_addu8(i, 1U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,18 +803,26 @@ static void write_one_reloc(uint8_t ch_index, uint32_t desc_index,
|
|||||||
uint16_t slot_id = get_slot_id(slot);
|
uint16_t slot_id = get_slot_id(slot);
|
||||||
uint16_t reloc_id = safe_addu16(info->slots[slot_id].reloc_start_idx,
|
uint16_t reloc_id = safe_addu16(info->slots[slot_id].reloc_start_idx,
|
||||||
info->reloc_off[slot_id]);
|
info->reloc_off[slot_id]);
|
||||||
|
|
||||||
int64_t old_start_addr = info->slots[slot_id].start_addr;
|
int64_t old_start_addr = info->slots[slot_id].start_addr;
|
||||||
int64_t old_end_addr = info->slots[slot_id].end_addr;
|
int64_t old_end_addr = info->slots[slot_id].end_addr;
|
||||||
|
uint32_t shift_amount = (uint32_t)ch_index & 0x0FU;
|
||||||
|
uint32_t shift_result = (uint32_t)1U << shift_amount;
|
||||||
|
uint16_t ch_mask_u16;
|
||||||
|
uint16_t new_mask;
|
||||||
|
|
||||||
info->slots[slot_id].start_addr =
|
info->slots[slot_id].start_addr =
|
||||||
mins64(access_entry->start_addr, old_start_addr);
|
mins64(access_entry->start_addr, old_start_addr);
|
||||||
info->slots[slot_id].end_addr =
|
info->slots[slot_id].end_addr =
|
||||||
maxs64(access_entry->end_addr, old_end_addr);
|
maxs64(access_entry->end_addr, old_end_addr);
|
||||||
|
|
||||||
info->slots[slot_id].ch_use_mask |= (1U << (ch_index & 0x1FU));
|
ASSERT(shift_result <= (uint32_t)U16_MAX);
|
||||||
|
ch_mask_u16 = (uint16_t)shift_result;
|
||||||
|
new_mask = info->slots[slot_id].ch_use_mask | ch_mask_u16;
|
||||||
|
info->slots[slot_id].ch_use_mask = new_mask;
|
||||||
|
|
||||||
info->relocs[reloc_id].desc_index = desc_index;
|
/* desc_index field is uint8_t - validated by DMA config validation */
|
||||||
|
ASSERT(desc_index <= (uint32_t)U8_MAX);
|
||||||
|
info->relocs[reloc_id].desc_index = (uint8_t)desc_index;
|
||||||
info->relocs[reloc_id].field = reloc_field;
|
info->relocs[reloc_id].field = reloc_field;
|
||||||
info->reloc_off[slot_id] = safe_addu8(info->reloc_off[slot_id], 1U);
|
info->reloc_off[slot_id] = safe_addu8(info->reloc_off[slot_id], 1U);
|
||||||
}
|
}
|
||||||
@@ -621,10 +833,10 @@ static void handle_reloc(uint16_t slot, uint8_t transfer_mode,
|
|||||||
uint8_t reloc_field, uint8_t ch_index,
|
uint8_t reloc_field, uint8_t ch_index,
|
||||||
uint8_t desc_index)
|
uint8_t desc_index)
|
||||||
{
|
{
|
||||||
if (slot & PVA_DMA_DYNAMIC_SLOT) {
|
if ((slot & PVA_DMA_DYNAMIC_SLOT) != 0U) {
|
||||||
write_one_reloc(ch_index, desc_index, slot, transfer_mode,
|
write_one_reloc(ch_index, desc_index, slot, transfer_mode,
|
||||||
reloc_field, &rel_info->dyn_slot, access_entry);
|
reloc_field, &rel_info->dyn_slot, access_entry);
|
||||||
} else if (slot & PVA_DMA_STATIC_SLOT) {
|
} else if ((slot & PVA_DMA_STATIC_SLOT) != 0U) {
|
||||||
write_one_reloc(ch_index, desc_index, slot, transfer_mode,
|
write_one_reloc(ch_index, desc_index, slot, transfer_mode,
|
||||||
reloc_field, &rel_info->static_slot,
|
reloc_field, &rel_info->static_slot,
|
||||||
access_entry);
|
access_entry);
|
||||||
@@ -636,7 +848,7 @@ static void write_relocs(const struct pva_dma_config *dma_cfg,
|
|||||||
struct pva_fw_dma_reloc_slots *rel_info,
|
struct pva_fw_dma_reloc_slots *rel_info,
|
||||||
uint8_t const *desc_to_ch)
|
uint8_t const *desc_to_ch)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint8_t i;
|
||||||
uint16_t start_idx = 0U;
|
uint16_t start_idx = 0U;
|
||||||
const struct pva_dma_descriptor *desc = NULL;
|
const struct pva_dma_descriptor *desc = NULL;
|
||||||
uint8_t ch_index = 0U;
|
uint8_t ch_index = 0U;
|
||||||
@@ -653,9 +865,9 @@ static void write_relocs(const struct pva_dma_config *dma_cfg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0U; i < dma_cfg->header.num_descriptors; i++) {
|
for (i = 0U; i < dma_cfg->header.num_descriptors; i++) {
|
||||||
if (pva_is_reserved_desc(i)) {
|
if (pva_is_reserved_desc(
|
||||||
|
safe_addu8(i, dma_cfg->header.base_descriptor))) {
|
||||||
// skip over the reserved descriptor range
|
// skip over the reserved descriptor range
|
||||||
i = PVA_RESERVED_DESCRIPTORS_END;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
desc = &dma_cfg->descriptors[i];
|
desc = &dma_cfg->descriptors[i];
|
||||||
@@ -763,16 +975,20 @@ static enum pva_error get_access_size(const struct pva_dma_descriptor *desc,
|
|||||||
end += adds64((int64_t)dim_offset_U, (int64_t)tx, &math_err);
|
end += adds64((int64_t)dim_offset_U, (int64_t)tx, &math_err);
|
||||||
|
|
||||||
// 3rd dim
|
// 3rd dim
|
||||||
// 3rd dim
|
dim_offset =
|
||||||
dim_offset = muls32((attr->adv1), (int32_t)(attr->rpt1), &math_err);
|
muls32((int32_t)(attr->adv1), (int32_t)(attr->rpt1), &math_err);
|
||||||
start += mins32(dim_offset, 0);
|
start += mins32(dim_offset, 0);
|
||||||
end += maxs32(dim_offset, 0);
|
end += maxs32(dim_offset, 0);
|
||||||
|
|
||||||
// 4th dim
|
// 4th dim
|
||||||
dim_offset = muls32((attr->adv2), (int32_t)(attr->rpt2), &math_err);
|
dim_offset =
|
||||||
|
muls32((int32_t)(attr->adv2), (int32_t)(attr->rpt2), &math_err);
|
||||||
start += mins32(dim_offset, 0);
|
start += mins32(dim_offset, 0);
|
||||||
end += maxs32(dim_offset, 0);
|
end += maxs32(dim_offset, 0);
|
||||||
|
|
||||||
// 5th dim
|
// 5th dim
|
||||||
dim_offset = muls32((attr->adv3), (int32_t)(attr->rpt3), &math_err);
|
dim_offset =
|
||||||
|
muls32((int32_t)(attr->adv3), (int32_t)(attr->rpt3), &math_err);
|
||||||
start += mins32(dim_offset, 0);
|
start += mins32(dim_offset, 0);
|
||||||
end += maxs32(dim_offset, 0);
|
end += maxs32(dim_offset, 0);
|
||||||
// convert to byte range
|
// convert to byte range
|
||||||
@@ -813,12 +1029,12 @@ pva_kmd_compute_dma_access(struct pva_dma_config const *dma_cfg,
|
|||||||
struct pva_kmd_dma_access *access_sizes,
|
struct pva_kmd_dma_access *access_sizes,
|
||||||
uint64_t *hw_dma_descs_mask)
|
uint64_t *hw_dma_descs_mask)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint8_t i;
|
||||||
const struct pva_dma_descriptor *desc = NULL;
|
const struct pva_dma_descriptor *desc = NULL;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
bool skip_swseq_size_compute = false;
|
bool skip_swseq_size_compute = false;
|
||||||
|
|
||||||
for (i = 0; i < dma_cfg->header.num_descriptors; i++) {
|
for (i = 0U; i < dma_cfg->header.num_descriptors; i++) {
|
||||||
/**
|
/**
|
||||||
* Check if DMA descriptor has been used in HW Sequencer.
|
* Check if DMA descriptor has been used in HW Sequencer.
|
||||||
* If used, skip_swseq_size_compute = true
|
* If used, skip_swseq_size_compute = true
|
||||||
@@ -829,9 +1045,11 @@ pva_kmd_compute_dma_access(struct pva_dma_config const *dma_cfg,
|
|||||||
*/
|
*/
|
||||||
skip_swseq_size_compute = ((hw_dma_descs_mask[i / 64ULL] &
|
skip_swseq_size_compute = ((hw_dma_descs_mask[i / 64ULL] &
|
||||||
(1ULL << (i & 0x3FU))) == 1U);
|
(1ULL << (i & 0x3FU))) == 1U);
|
||||||
if (pva_is_reserved_desc(i)) {
|
if (pva_is_reserved_desc(
|
||||||
|
safe_addu8(i, dma_cfg->header.base_descriptor))) {
|
||||||
// skip over the reserved descriptor range
|
// skip over the reserved descriptor range
|
||||||
i = PVA_RESERVED_DESCRIPTORS_END;
|
i = safe_subu8(PVA_RESERVED_DESCRIPTORS_END,
|
||||||
|
dma_cfg->header.base_descriptor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,8 +1096,8 @@ void pva_kmd_collect_relocs(struct pva_dma_config const *dma_cfg,
|
|||||||
count_relocs(dma_cfg, out_static_slots, num_static_slots, out_dyn_slots,
|
count_relocs(dma_cfg, out_static_slots, num_static_slots, out_dyn_slots,
|
||||||
num_dyn_slots);
|
num_dyn_slots);
|
||||||
|
|
||||||
memset(static_reloc_off, 0U, sizeof(static_reloc_off));
|
(void)memset(static_reloc_off, 0, sizeof(static_reloc_off));
|
||||||
memset(dyn_reloc_off, 0U, sizeof(dyn_reloc_off));
|
(void)memset(dyn_reloc_off, 0, sizeof(dyn_reloc_off));
|
||||||
|
|
||||||
rel_info.dyn_slot.slots = out_dyn_slots;
|
rel_info.dyn_slot.slots = out_dyn_slots;
|
||||||
rel_info.dyn_slot.relocs = out_dyn_relocs;
|
rel_info.dyn_slot.relocs = out_dyn_relocs;
|
||||||
|
|||||||
@@ -16,48 +16,55 @@ static void write_dma_channel(struct pva_dma_channel const *ch,
|
|||||||
bool support_hwseq_frame_linking)
|
bool support_hwseq_frame_linking)
|
||||||
{
|
{
|
||||||
/* DMA_CHANNEL_CNTL0_CHSDID: DMA_CHANNEL_CNTL0[0] = descIndex + 1;*/
|
/* DMA_CHANNEL_CNTL0_CHSDID: DMA_CHANNEL_CNTL0[0] = descIndex + 1;*/
|
||||||
fw_ch->cntl0 =
|
uint8_t desc_sum_u8 =
|
||||||
(((ch->desc_index + base_desc_index + 1U) & 0xFFU) << 0U);
|
safe_addu8(safe_addu8(ch->desc_index, base_desc_index), 1U);
|
||||||
|
uint8_t cntl1_val;
|
||||||
|
uint16_t hwseqcntl_val;
|
||||||
|
|
||||||
|
fw_ch->cntl0 = (uint32_t)desc_sum_u8;
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL0_CHVMEMOREQ */
|
/* DMA_CHANNEL_CNTL0_CHVMEMOREQ */
|
||||||
fw_ch->cntl0 |= ((ch->vdb_count & 0xFFU) << 8U);
|
fw_ch->cntl0 |= (((uint32_t)ch->vdb_count & 0xFFU) << 8U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL0_CHBH */
|
/* DMA_CHANNEL_CNTL0_CHBH */
|
||||||
fw_ch->cntl0 |= ((ch->adb_count & 0x1FFU) << 16U);
|
fw_ch->cntl0 |= (((uint32_t)ch->adb_count & 0x1FFU) << 16U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL0_CHPREF */
|
/* DMA_CHANNEL_CNTL0_CHPREF */
|
||||||
fw_ch->cntl0 |= ((ch->prefetch_enable & 1U) << 30U);
|
fw_ch->cntl0 |= (((uint32_t)ch->prefetch_enable & 1U) << 30U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL1_CHPWT */
|
/* DMA_CHANNEL_CNTL1_CHPWT */
|
||||||
fw_ch->cntl1 = ((ch->req_per_grant & 0x7U) << 2U);
|
cntl1_val = (ch->req_per_grant & 0x7U) << 2U;
|
||||||
|
fw_ch->cntl1 = (uint32_t)cntl1_val;
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL1_CHVDBSTART */
|
/* DMA_CHANNEL_CNTL1_CHVDBSTART */
|
||||||
fw_ch->cntl1 |= ((ch->vdb_offset & 0x7FU) << 16U);
|
fw_ch->cntl1 |= (((uint32_t)ch->vdb_offset & 0x7FU) << 16U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_CNTL1_CHADBSTART */
|
/* DMA_CHANNEL_CNTL1_CHADBSTART */
|
||||||
fw_ch->cntl1 |= ((ch->adb_offset & 0x1FFU) << 23U);
|
fw_ch->cntl1 |= (((uint32_t)ch->adb_offset & 0x1FFU) << 23U);
|
||||||
|
|
||||||
fw_ch->boundary_pad = ch->pad_value;
|
fw_ch->boundary_pad = ch->pad_value;
|
||||||
|
|
||||||
fw_ch->cntl1 |= ((ch->ch_rep_factor & 0x7U) << 8U);
|
fw_ch->cntl1 |= (((uint32_t)ch->ch_rep_factor & 0x7U) << 8U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQSTART */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQSTART */
|
||||||
fw_ch->hwseqcntl = ((ch->hwseq_start & 0x1FFU) << 0U);
|
hwseqcntl_val = (ch->hwseq_start & 0x1FFU) << 0U;
|
||||||
|
fw_ch->hwseqcntl = (uint32_t)hwseqcntl_val;
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQEND */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQEND */
|
||||||
fw_ch->hwseqcntl |= ((ch->hwseq_end & 0x1FFU) << 12U);
|
fw_ch->hwseqcntl |= (((uint32_t)ch->hwseq_end & 0x1FFU) << 12U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTD */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTD */
|
||||||
fw_ch->hwseqcntl |= ((ch->hwseq_trigger_done & 0x3U) << 24U);
|
fw_ch->hwseqcntl |= (((uint32_t)ch->hwseq_trigger_done & 0x3U) << 24U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTS */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTS */
|
||||||
fw_ch->hwseqcntl |= ((ch->hwseq_tx_select & 0x1U) << 27U);
|
fw_ch->hwseqcntl |= (((uint32_t)ch->hwseq_tx_select & 0x1U) << 27U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTO */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQTO */
|
||||||
fw_ch->hwseqcntl |= ((ch->hwseq_traversal_order & 0x1U) << 30U);
|
fw_ch->hwseqcntl |=
|
||||||
|
(((uint32_t)ch->hwseq_traversal_order & 0x1U) << 30U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQEN */
|
/* DMA_CHANNEL_HWSEQCNTL_CHHWSEQEN */
|
||||||
fw_ch->hwseqcntl |= ((ch->hwseq_enable & 0x1U) << 31U);
|
fw_ch->hwseqcntl |= (((uint32_t)ch->hwseq_enable & 0x1U) << 31U);
|
||||||
|
|
||||||
/* DMA_CHANNEL_HWSEQFSCNTL_CHHWSEQFCNT*/
|
/* DMA_CHANNEL_HWSEQFSCNTL_CHHWSEQFCNT*/
|
||||||
fw_ch->hwseqfscntl |=
|
fw_ch->hwseqfscntl |=
|
||||||
@@ -86,20 +93,24 @@ static void write_dma_descriptor(struct pva_dma_descriptor const *desc,
|
|||||||
fw_desc->dst_adr1 = iova_hi(desc->dst.offset);
|
fw_desc->dst_adr1 = iova_hi(desc->dst.offset);
|
||||||
|
|
||||||
/* DMA_DESC_TRANS CNTL0 */
|
/* DMA_DESC_TRANS CNTL0 */
|
||||||
fw_desc->transfer_control0 = PVA_INSERT(desc->src.transfer_mode, 2, 0) |
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
PVA_INSERT(desc->dst.transfer_mode, 6, 4);
|
fw_desc->transfer_control0 =
|
||||||
|
(uint8_t)(PVA_INSERT((uint8_t)desc->src.transfer_mode, 2, 0) |
|
||||||
|
PVA_INSERT((uint8_t)desc->dst.transfer_mode, 6, 4));
|
||||||
/* DMA_DESC_TRANS CNTL1 */
|
/* DMA_DESC_TRANS CNTL1 */
|
||||||
fw_desc->transfer_control1 =
|
fw_desc->transfer_control1 =
|
||||||
PVA_INSERT(desc->log2_pixel_size, 1, 0) |
|
(uint8_t)(PVA_INSERT((uint8_t)desc->log2_pixel_size, 1, 0) |
|
||||||
PVA_INSERT(desc->px_direction, 2, 2) |
|
PVA_INSERT((uint8_t)desc->px_direction, 2, 2) |
|
||||||
PVA_INSERT(desc->py_direction, 3, 3) |
|
PVA_INSERT((uint8_t)desc->py_direction, 3, 3) |
|
||||||
PVA_INSERT(desc->boundary_pixel_extension, 4, 4) |
|
PVA_INSERT((uint8_t)desc->boundary_pixel_extension, 4,
|
||||||
PVA_INSERT(desc->tts, 5, 5) |
|
4) |
|
||||||
PVA_INSERT(desc->trigger_completion, 7, 7);
|
PVA_INSERT((uint8_t)desc->tts, 5, 5) |
|
||||||
|
PVA_INSERT((uint8_t)desc->trigger_completion, 7, 7));
|
||||||
/* DMA_DESC_TRANS CNTL2 */
|
/* DMA_DESC_TRANS CNTL2 */
|
||||||
fw_desc->transfer_control2 = PVA_INSERT(desc->prefetch_enable, 0, 0) |
|
fw_desc->transfer_control2 =
|
||||||
PVA_INSERT(desc->dst.cb_enable, 1, 1) |
|
(uint8_t)(PVA_INSERT((uint8_t)desc->prefetch_enable, 0, 0) |
|
||||||
PVA_INSERT(desc->src.cb_enable, 2, 2);
|
PVA_INSERT((uint8_t)desc->dst.cb_enable, 1, 1) |
|
||||||
|
PVA_INSERT((uint8_t)desc->src.cb_enable, 2, 2));
|
||||||
|
|
||||||
fw_desc->link_did = desc->link_desc_id;
|
fw_desc->link_did = desc->link_desc_id;
|
||||||
|
|
||||||
@@ -111,71 +122,85 @@ static void write_dma_descriptor(struct pva_dma_descriptor const *desc,
|
|||||||
fw_desc->dlp_adv = desc->dst.line_pitch;
|
fw_desc->dlp_adv = desc->dst.line_pitch;
|
||||||
/* DMA_DESC_SLP_ADV */
|
/* DMA_DESC_SLP_ADV */
|
||||||
fw_desc->slp_adv = desc->src.line_pitch;
|
fw_desc->slp_adv = desc->src.line_pitch;
|
||||||
/* DMA_DESC_DB_START */
|
/* DMA_DESC_DB_START - lower 16 bits, bit 16 stored in cb_ext */
|
||||||
fw_desc->db_start = desc->dst.cb_start;
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
/* DMA_DESC_DB_SIZE */
|
fw_desc->db_start = (uint16_t)(desc->dst.cb_start & 0xFFFFU);
|
||||||
fw_desc->db_size = desc->dst.cb_size;
|
|
||||||
/* DMA_DESC_SB_START */
|
/* DMA_DESC_DB_SIZE - lower 16 bits, bit 16 stored in cb_ext */
|
||||||
fw_desc->sb_start = desc->src.cb_start;
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
/* DMA_DESC_SB_SIZE */
|
fw_desc->db_size = (uint16_t)(desc->dst.cb_size & 0xFFFFU);
|
||||||
fw_desc->sb_size = desc->src.cb_size;
|
|
||||||
|
/* DMA_DESC_SB_START - lower 16 bits, bit 16 stored in cb_ext */
|
||||||
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
fw_desc->sb_start = (uint16_t)(desc->src.cb_start & 0xFFFFU);
|
||||||
|
|
||||||
|
/* DMA_DESC_SB_SIZE - lower 16 bits, bit 16 stored in cb_ext */
|
||||||
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
fw_desc->sb_size = (uint16_t)(desc->src.cb_size & 0xFFFFU);
|
||||||
/* DMA_DESC_TRIG_CH */
|
/* DMA_DESC_TRIG_CH */
|
||||||
/* Channel events are not supported */
|
/* Channel events are not supported */
|
||||||
fw_desc->trig_ch_events = 0U;
|
fw_desc->trig_ch_events = 0U;
|
||||||
/* DMA_DESC_HW_SW_TRIG */
|
/* DMA_DESC_HW_SW_TRIG */
|
||||||
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
fw_desc->hw_sw_trig_events =
|
fw_desc->hw_sw_trig_events =
|
||||||
PVA_INSERT(desc->trig_event_mode, 1, 0) |
|
(uint16_t)(PVA_INSERT((uint8_t)desc->trig_event_mode, 1, 0) |
|
||||||
PVA_INSERT(desc->trig_vpu_events, 5, 2) |
|
PVA_INSERT((uint8_t)desc->trig_vpu_events, 5, 2) |
|
||||||
PVA_INSERT(desc->desc_reload_enable, 12, 12);
|
PVA_INSERT((uint8_t)desc->desc_reload_enable, 12,
|
||||||
|
12));
|
||||||
/* DMA_DESC_PX */
|
/* DMA_DESC_PX */
|
||||||
fw_desc->px = desc->px;
|
fw_desc->px = desc->px;
|
||||||
/* DMA_DESC_PY */
|
/* DMA_DESC_PY */
|
||||||
fw_desc->py = desc->py;
|
fw_desc->py = desc->py;
|
||||||
/* DMA_DESC_FRDA */
|
/* DMA_DESC_FRDA */
|
||||||
fw_desc->frda = ((desc->dst2_offset >> 6U) & 0x7FFF);
|
fw_desc->frda = (uint16_t)((desc->dst2_offset >> 6U) & 0x7FFFU);
|
||||||
|
|
||||||
/* DMA_DESC_NDTM_CNTL0 */
|
/* DMA_DESC_NDTM_CNTL0 */
|
||||||
fw_desc->cb_ext = (((desc->src.cb_start >> 16) & 0x1) << 0) |
|
fw_desc->cb_ext = (uint8_t)((((desc->src.cb_start >> 16) & 0x1U) << 0) |
|
||||||
(((desc->dst.cb_start >> 16) & 0x1) << 2) |
|
(((desc->dst.cb_start >> 16) & 0x1U) << 2) |
|
||||||
(((desc->src.cb_size >> 16) & 0x1) << 4) |
|
(((desc->src.cb_size >> 16) & 0x1U) << 4) |
|
||||||
(((desc->dst.cb_size >> 16) & 0x1) << 6);
|
(((desc->dst.cb_size >> 16) & 0x1U) << 6));
|
||||||
|
|
||||||
/* DMA_DESC_NS1_ADV & DMA_DESC_ST1_ADV */
|
/* DMA_DESC_NS1_ADV & DMA_DESC_ST1_ADV */
|
||||||
|
/* adv fields are signed int32_t, cast to uint32_t for bit packing */
|
||||||
fw_desc->srcpt1_cntl =
|
fw_desc->srcpt1_cntl =
|
||||||
assemble_rpt_cntl(desc->src.rpt1, desc->src.adv1);
|
assemble_rpt_cntl(desc->src.rpt1, (uint32_t)desc->src.adv1);
|
||||||
fw_desc->srcpt2_cntl =
|
fw_desc->srcpt2_cntl =
|
||||||
assemble_rpt_cntl(desc->src.rpt2, desc->src.adv2);
|
assemble_rpt_cntl(desc->src.rpt2, (uint32_t)desc->src.adv2);
|
||||||
fw_desc->srcpt3_cntl =
|
fw_desc->srcpt3_cntl =
|
||||||
assemble_rpt_cntl(desc->src.rpt3, desc->src.adv3);
|
assemble_rpt_cntl(desc->src.rpt3, (uint32_t)desc->src.adv3);
|
||||||
fw_desc->dstpt1_cntl =
|
fw_desc->dstpt1_cntl =
|
||||||
assemble_rpt_cntl(desc->dst.rpt1, desc->dst.adv1);
|
assemble_rpt_cntl(desc->dst.rpt1, (uint32_t)desc->dst.adv1);
|
||||||
fw_desc->dstpt2_cntl =
|
fw_desc->dstpt2_cntl =
|
||||||
assemble_rpt_cntl(desc->dst.rpt2, desc->dst.adv2);
|
assemble_rpt_cntl(desc->dst.rpt2, (uint32_t)desc->dst.adv2);
|
||||||
fw_desc->dstpt3_cntl =
|
fw_desc->dstpt3_cntl =
|
||||||
assemble_rpt_cntl(desc->dst.rpt3, desc->dst.adv3);
|
assemble_rpt_cntl(desc->dst.rpt3, (uint32_t)desc->dst.adv3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_triggers(struct pva_dma_config const *dma_cfg,
|
static void write_triggers(struct pva_dma_config const *dma_cfg,
|
||||||
struct pva_dma_config_resource *fw_cfg,
|
struct pva_dma_config_resource *fw_cfg,
|
||||||
struct pva_dma_resource_map *dma_resource_map)
|
struct pva_dma_resource_map *dma_resource_map)
|
||||||
{
|
{
|
||||||
uint32_t i, j;
|
uint8_t i, j;
|
||||||
bool trigger_required = false;
|
bool trigger_required = false;
|
||||||
|
|
||||||
memset(fw_cfg->output_enable, 0, sizeof(fw_cfg->output_enable));
|
(void)memset(fw_cfg->output_enable, 0, sizeof(fw_cfg->output_enable));
|
||||||
|
|
||||||
for (i = 0; i < dma_cfg->header.num_channels; i++) {
|
for (i = 0; i < dma_cfg->header.num_channels; i++) {
|
||||||
struct pva_dma_channel const *ch = &dma_cfg->channels[i];
|
struct pva_dma_channel const *ch;
|
||||||
uint8_t ch_num = i + dma_cfg->header.base_channel;
|
uint8_t ch_num;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
|
||||||
|
ch = &dma_cfg->channels[i];
|
||||||
|
/* CERT INT31-C: Hardware constraints ensure num_channels and base_channel
|
||||||
|
* are bounded such that their sum always fits in uint8_t, safe to cast */
|
||||||
|
ch_num = safe_addu8(i, dma_cfg->header.base_channel);
|
||||||
mask = ch->output_enable_mask;
|
mask = ch->output_enable_mask;
|
||||||
/* READ/STORE triggers */
|
/* READ/STORE triggers */
|
||||||
for (j = 0; j < 7; j++) {
|
for (j = 0U; j < 7U; j++) {
|
||||||
fw_cfg->output_enable[j] |=
|
fw_cfg->output_enable[j] |=
|
||||||
(((mask >> 2 * j) & 1U) << ch_num);
|
(((mask >> (2U * j)) & 1U) << ch_num);
|
||||||
fw_cfg->output_enable[j] |=
|
fw_cfg->output_enable[j] |=
|
||||||
(((mask >> (2 * j + 1)) & 1U)
|
(((mask >> ((2U * j) + 1U)) & 1U)
|
||||||
<< (ch_num + 16U));
|
<< (ch_num + 16U));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +211,7 @@ static void write_triggers(struct pva_dma_config const *dma_cfg,
|
|||||||
fw_cfg->output_enable[8] |=
|
fw_cfg->output_enable[8] |=
|
||||||
(((mask >> 16) & 1U) << (ch_num + 16U));
|
(((mask >> 16) & 1U) << (ch_num + 16U));
|
||||||
|
|
||||||
if (mask != 0) {
|
if (mask != 0U) {
|
||||||
trigger_required = true;
|
trigger_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +233,7 @@ void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
|||||||
struct pva_dma_resource_map *dma_resource_map;
|
struct pva_dma_resource_map *dma_resource_map;
|
||||||
uint32_t *hwseq_words;
|
uint32_t *hwseq_words;
|
||||||
uintptr_t offset;
|
uintptr_t offset;
|
||||||
uint32_t i;
|
uint8_t i;
|
||||||
|
|
||||||
hdr = fw_dma_config;
|
hdr = fw_dma_config;
|
||||||
hdr->base_channel = dma_cfg->header.base_channel;
|
hdr->base_channel = dma_cfg->header.base_channel;
|
||||||
@@ -235,8 +260,8 @@ void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
|||||||
offset = sizeof(*hdr);
|
offset = sizeof(*hdr);
|
||||||
fw_slots = pva_offset_pointer(fw_dma_config, offset);
|
fw_slots = pva_offset_pointer(fw_dma_config, offset);
|
||||||
|
|
||||||
if (hdr->num_dynamic_slots > 0) {
|
if (hdr->num_dynamic_slots > 0U) {
|
||||||
last_slot = &fw_slots[hdr->num_dynamic_slots - 1];
|
last_slot = &fw_slots[hdr->num_dynamic_slots - 1U];
|
||||||
|
|
||||||
hdr->num_relocs = safe_addu16(last_slot->reloc_start_idx,
|
hdr->num_relocs = safe_addu16(last_slot->reloc_start_idx,
|
||||||
last_slot->reloc_count);
|
last_slot->reloc_count);
|
||||||
@@ -251,36 +276,40 @@ void pva_kmd_write_fw_dma_config(struct pva_dma_config const *dma_cfg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fw_channels = pva_offset_pointer(fw_dma_config, offset);
|
fw_channels = pva_offset_pointer(fw_dma_config, offset);
|
||||||
offset += sizeof(*fw_channels) * hdr->num_channels;
|
/* MISRA C-2023 Rule 10.3: Explicit cast for narrowing conversion */
|
||||||
|
offset += (uint32_t)(sizeof(*fw_channels) * hdr->num_channels);
|
||||||
|
|
||||||
fw_descs = pva_offset_pointer(fw_dma_config, offset);
|
fw_descs = pva_offset_pointer(fw_dma_config, offset);
|
||||||
offset += sizeof(*fw_descs) * hdr->num_descriptors;
|
offset += sizeof(*fw_descs) * hdr->num_descriptors;
|
||||||
|
|
||||||
/* Do not include fields beyond descriptors as they are not fetched to
|
/* Do not include fields beyond descriptors as they are not fetched to
|
||||||
* TCM */
|
* TCM */
|
||||||
*out_fw_fetch_size = offset;
|
*out_fw_fetch_size = (uint32_t)offset;
|
||||||
|
|
||||||
for (i = 0; i < hdr->num_channels; i++) {
|
for (i = 0U; i < hdr->num_channels; i++) {
|
||||||
write_dma_channel(&dma_cfg->channels[i],
|
write_dma_channel(&dma_cfg->channels[i],
|
||||||
dma_cfg->header.base_descriptor,
|
dma_cfg->header.base_descriptor,
|
||||||
&fw_channels[i], dma_resource_map,
|
&fw_channels[i], dma_resource_map,
|
||||||
support_hwseq_frame_linking);
|
support_hwseq_frame_linking);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < dma_cfg->header.num_descriptors; i++) {
|
for (i = 0U; i < dma_cfg->header.num_descriptors; i++) {
|
||||||
if (pva_is_reserved_desc(i)) {
|
if (pva_is_reserved_desc(
|
||||||
|
safe_addu8(i, dma_cfg->header.base_descriptor))) {
|
||||||
// skip over the reserved descriptor range
|
// skip over the reserved descriptor range
|
||||||
i = PVA_RESERVED_DESCRIPTORS_END;
|
i = safe_subu8(PVA_RESERVED_DESCRIPTORS_END,
|
||||||
|
dma_cfg->header.base_descriptor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
write_dma_descriptor(&dma_cfg->descriptors[i], &fw_descs[i]);
|
write_dma_descriptor(&dma_cfg->descriptors[i], &fw_descs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_triggers(dma_cfg, fw_dma_config, dma_resource_map);
|
write_triggers(dma_cfg, (struct pva_dma_config_resource *)fw_dma_config,
|
||||||
|
dma_resource_map);
|
||||||
|
|
||||||
hwseq_words = pva_offset_pointer(fw_dma_config, offset);
|
hwseq_words = pva_offset_pointer(fw_dma_config, offset);
|
||||||
|
|
||||||
memcpy(hwseq_words, dma_cfg->hwseq_words,
|
(void)memcpy(hwseq_words, dma_cfg->hwseq_words,
|
||||||
sizeof(*hwseq_words) * hdr->num_hwseq_words);
|
sizeof(*hwseq_words) * hdr->num_hwseq_words);
|
||||||
|
|
||||||
/*TODO: write hdr->common_config for hwseq and MISR*/
|
/*TODO: write hdr->common_config for hwseq and MISR*/
|
||||||
|
|||||||
@@ -9,11 +9,51 @@
|
|||||||
struct pva_kmd_device;
|
struct pva_kmd_device;
|
||||||
struct pva_kmd_device_memory;
|
struct pva_kmd_device_memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Symbol table for executable debugging and runtime information
|
||||||
|
*
|
||||||
|
* @details This structure maintains a symbol table for a loaded executable,
|
||||||
|
* providing access to symbol information used for debugging, profiling, and
|
||||||
|
* runtime symbol resolution. The symbol table contains metadata about functions,
|
||||||
|
* variables, and other symbols within the executable that can be referenced
|
||||||
|
* during execution or debugging operations.
|
||||||
|
*/
|
||||||
struct pva_kmd_exec_symbol_table {
|
struct pva_kmd_exec_symbol_table {
|
||||||
|
/**
|
||||||
|
* @brief Number of symbols in the symbol table
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_symbols;
|
uint32_t n_symbols;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of symbol information structures
|
||||||
|
* Valid value: non-null if n_symbols > 0, null if n_symbols == 0
|
||||||
|
*/
|
||||||
struct pva_symbol_info *symbols;
|
struct pva_symbol_info *symbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get symbol information by symbol ID
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the symbol ID against the symbol table bounds
|
||||||
|
* - Converts external symbol ID to internal array index
|
||||||
|
* - Retrieves the symbol information structure for the specified symbol
|
||||||
|
* - Provides access to symbol metadata for debugging and runtime operations
|
||||||
|
* - Returns null for invalid or out-of-range symbol IDs
|
||||||
|
*
|
||||||
|
* The symbol ID is expected to be in the external format with PVA_SYMBOL_ID_BASE
|
||||||
|
* offset. This function handles the conversion to internal array indexing
|
||||||
|
* automatically.
|
||||||
|
*
|
||||||
|
* @param[in] symbol_table Pointer to @ref pva_kmd_exec_symbol_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] symbol_id External symbol ID to retrieve
|
||||||
|
* Valid range: [PVA_SYMBOL_ID_BASE .. PVA_SYMBOL_ID_BASE+n_symbols-1]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_symbol_info if symbol exists
|
||||||
|
* @retval NULL Invalid symbol ID or symbol not found
|
||||||
|
*/
|
||||||
static inline struct pva_symbol_info *
|
static inline struct pva_symbol_info *
|
||||||
pva_kmd_get_symbol(struct pva_kmd_exec_symbol_table *symbol_table,
|
pva_kmd_get_symbol(struct pva_kmd_exec_symbol_table *symbol_table,
|
||||||
uint32_t symbol_id)
|
uint32_t symbol_id)
|
||||||
@@ -30,6 +70,30 @@ pva_kmd_get_symbol(struct pva_kmd_exec_symbol_table *symbol_table,
|
|||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get symbol information with type validation
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Calls @ref pva_kmd_get_symbol() to retrieve symbol information
|
||||||
|
* - Validates that the symbol has the expected type
|
||||||
|
* - Returns the symbol information only if type matches
|
||||||
|
* - Provides type-safe access to symbol information
|
||||||
|
* - Logs error for type mismatches to aid debugging
|
||||||
|
*
|
||||||
|
* This function provides additional type safety when accessing symbols
|
||||||
|
* by ensuring the symbol type matches expectations before returning
|
||||||
|
* the symbol information.
|
||||||
|
*
|
||||||
|
* @param[in] symbol_table Pointer to @ref pva_kmd_exec_symbol_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] symbol_id External symbol ID to retrieve
|
||||||
|
* Valid range: [PVA_SYMBOL_ID_BASE .. PVA_SYMBOL_ID_BASE+n_symbols-1]
|
||||||
|
* @param[in] symbol_type Expected symbol type for validation
|
||||||
|
* Valid values: @ref pva_symbol_type enumeration values
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_symbol_info if symbol exists and type matches
|
||||||
|
* @retval NULL Invalid symbol ID, symbol not found, or type mismatch
|
||||||
|
*/
|
||||||
static inline struct pva_symbol_info *
|
static inline struct pva_symbol_info *
|
||||||
pva_kmd_get_symbol_with_type(struct pva_kmd_exec_symbol_table *symbol_table,
|
pva_kmd_get_symbol_with_type(struct pva_kmd_exec_symbol_table *symbol_table,
|
||||||
uint32_t symbol_id,
|
uint32_t symbol_id,
|
||||||
@@ -38,20 +102,56 @@ pva_kmd_get_symbol_with_type(struct pva_kmd_exec_symbol_table *symbol_table,
|
|||||||
struct pva_symbol_info *symbol = NULL;
|
struct pva_symbol_info *symbol = NULL;
|
||||||
|
|
||||||
symbol = pva_kmd_get_symbol(symbol_table, symbol_id);
|
symbol = pva_kmd_get_symbol(symbol_table, symbol_id);
|
||||||
if (!symbol) {
|
if (symbol == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(PVA_SKIP_SYMBOL_TYPE_CHECK)
|
|
||||||
if (symbol->symbol_type != symbol_type) {
|
if (symbol->symbol_type != symbol_type) {
|
||||||
pva_kmd_log_err("Unexpected symbol type\n");
|
pva_kmd_log_err("Unexpected symbol type\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load and prepare VPU executable for execution
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the executable format and structure
|
||||||
|
* - Parses executable sections including code, data, and metadata
|
||||||
|
* - Allocates device memory for executable storage
|
||||||
|
* - Maps executable sections to appropriate SMMU contexts
|
||||||
|
* - Extracts and builds symbol table for debugging support
|
||||||
|
* - Sets up memory permissions for code and data sections
|
||||||
|
* - Prepares executable for hardware execution by the VPU
|
||||||
|
* - Returns all necessary information for executable management
|
||||||
|
*
|
||||||
|
* The loaded executable is stored in device memory accessible by the VPU
|
||||||
|
* hardware, with proper memory protection and SMMU mapping. The symbol
|
||||||
|
* table provides debugging and profiling capabilities.
|
||||||
|
*
|
||||||
|
* @param[in] executable_data Pointer to executable binary data
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] executable_size Size of executable binary in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] dma_smmu_id SMMU context ID for DMA operations
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
* @param[out] out_symbol_table Pointer to store symbol table information
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] out_metainfo Pointer to store executable metadata memory
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] out_sections Pointer to store executable sections memory
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Executable loaded successfully
|
||||||
|
* @retval PVA_INVALID_SYMBOL Executable format is invalid or corrupted
|
||||||
|
* @retval PVA_NOMEM Failed to allocate device memory
|
||||||
|
* @retval PVA_INVAL Failed to map executable to SMMU context
|
||||||
|
* @retval PVA_NOT_IMPL Executable uses unsupported features
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
||||||
struct pva_kmd_device *pva, uint8_t dma_smmu_id,
|
struct pva_kmd_device *pva, uint8_t dma_smmu_id,
|
||||||
@@ -59,6 +159,28 @@ pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
|||||||
struct pva_kmd_device_memory **out_metainfo,
|
struct pva_kmd_device_memory **out_metainfo,
|
||||||
struct pva_kmd_device_memory **out_sections);
|
struct pva_kmd_device_memory **out_sections);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unload executable and free associated resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Frees the symbol table and all symbol information
|
||||||
|
* - Unmaps executable sections from SMMU contexts
|
||||||
|
* - Releases device memory allocated for executable metadata
|
||||||
|
* - Releases device memory allocated for executable code and data sections
|
||||||
|
* - Cleans up all resources associated with the executable
|
||||||
|
* - Invalidates all pointers and structures for the executable
|
||||||
|
*
|
||||||
|
* This function should be called when an executable is no longer needed
|
||||||
|
* to ensure proper cleanup of all associated resources. After calling
|
||||||
|
* this function, the executable cannot be used for further operations.
|
||||||
|
*
|
||||||
|
* @param[in, out] symbol_table Pointer to symbol table to clean up
|
||||||
|
* Valid value: non-null, must have been initialized
|
||||||
|
* @param[in] metainfo Pointer to executable metadata memory to free
|
||||||
|
* Valid value: non-null, must have been allocated
|
||||||
|
* @param[in] sections Pointer to executable sections memory to free
|
||||||
|
* Valid value: non-null, must have been allocated
|
||||||
|
*/
|
||||||
void pva_kmd_unload_executable(struct pva_kmd_exec_symbol_table *symbol_table,
|
void pva_kmd_unload_executable(struct pva_kmd_exec_symbol_table *symbol_table,
|
||||||
struct pva_kmd_device_memory *metainfo,
|
struct pva_kmd_device_memory *metainfo,
|
||||||
struct pva_kmd_device_memory *sections);
|
struct pva_kmd_device_memory *sections);
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
|
|
||||||
#include "pva_kmd_utils.h"
|
|
||||||
#include "pva_api.h"
|
|
||||||
#include "pva_api_cmdbuf.h"
|
|
||||||
#include "pva_api_types.h"
|
|
||||||
#include "pva_bit.h"
|
|
||||||
#include "pva_fw.h"
|
|
||||||
#include "pva_kmd_cmdbuf.h"
|
|
||||||
#include "pva_kmd_device.h"
|
|
||||||
#include "pva_kmd_fw_debug.h"
|
|
||||||
#include "pva_kmd_constants.h"
|
|
||||||
#include "pva_utils.h"
|
|
||||||
|
|
||||||
enum pva_error pva_kmd_notify_fw_set_trace_level(struct pva_kmd_device *pva,
|
|
||||||
uint32_t trace_level)
|
|
||||||
{
|
|
||||||
struct pva_cmd_set_trace_level cmd = { 0 };
|
|
||||||
pva_kmd_set_cmd_set_trace_level(&cmd, trace_level);
|
|
||||||
|
|
||||||
return pva_kmd_submit_cmd_sync(&pva->submitter, &cmd, sizeof(cmd),
|
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum pva_error pva_kmd_notify_fw_set_profiling_level(struct pva_kmd_device *pva,
|
|
||||||
uint32_t level)
|
|
||||||
{
|
|
||||||
struct pva_cmd_set_profiling_level cmd = { 0 };
|
|
||||||
pva_kmd_set_cmd_set_profiling_level(&cmd, level);
|
|
||||||
|
|
||||||
return pva_kmd_submit_cmd_sync(&pva->submitter, &cmd, sizeof(cmd),
|
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pva_kmd_drain_fw_print(struct pva_kmd_fw_print_buffer *print_buffer)
|
|
||||||
{
|
|
||||||
struct pva_fw_print_buffer_header *buf_info = print_buffer->buffer_info;
|
|
||||||
uint32_t tail = buf_info->tail;
|
|
||||||
|
|
||||||
if (tail > buf_info->size) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"Firmware print tail is out of bounds! Refusing to print\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_info->head > buf_info->size) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"Firmware print head is out of bounds! Refusing to print\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (buf_info->head != tail) {
|
|
||||||
uint32_t max_len;
|
|
||||||
uint32_t head = buf_info->head;
|
|
||||||
const char *str = print_buffer->content + head;
|
|
||||||
uint32_t print_size;
|
|
||||||
|
|
||||||
if ((head + PVA_MAX_DEBUG_LOG_MSG_CHARACTERS) >
|
|
||||||
buf_info->size) {
|
|
||||||
buf_info->head = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (head < tail) {
|
|
||||||
max_len = tail - head;
|
|
||||||
} else {
|
|
||||||
max_len = buf_info->size - head;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_size = strnlen(str, max_len);
|
|
||||||
pva_kmd_print_str(str);
|
|
||||||
|
|
||||||
/* +1 for null terminator */
|
|
||||||
head = (head + print_size + 1);
|
|
||||||
if (head >= buf_info->size) {
|
|
||||||
head = 0;
|
|
||||||
}
|
|
||||||
buf_info->head = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print_buffer->buffer_info->flags & PVA_FW_PRINT_BUFFER_OVERFLOWED) {
|
|
||||||
pva_kmd_log_err("Firmware print buffer overflowed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print_buffer->buffer_info->flags & PVA_FW_PRINT_FAILURE) {
|
|
||||||
pva_kmd_log_err("Firmware print failed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
|
||||||
|
|
||||||
#ifndef PVA_KMD_FW_DEBUG_H
|
|
||||||
#define PVA_KMD_FW_DEBUG_H
|
|
||||||
#include "pva_api.h"
|
|
||||||
#include "pva_fw.h"
|
|
||||||
#include "pva_kmd_device.h"
|
|
||||||
|
|
||||||
struct pva_kmd_fw_print_buffer {
|
|
||||||
struct pva_fw_print_buffer_header *buffer_info;
|
|
||||||
char const *content;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum pva_error pva_kmd_notify_fw_set_trace_level(struct pva_kmd_device *pva,
|
|
||||||
uint32_t trace_level);
|
|
||||||
|
|
||||||
enum pva_error pva_kmd_notify_fw_set_profiling_level(struct pva_kmd_device *pva,
|
|
||||||
uint32_t level);
|
|
||||||
|
|
||||||
void pva_kmd_drain_fw_print(struct pva_kmd_fw_print_buffer *print_buffer);
|
|
||||||
|
|
||||||
#endif // PVA_KMD_FW_DEBUG_H
|
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
#include "pva_kmd_utils.h"
|
||||||
|
#include "pva_api.h"
|
||||||
|
#include "pva_api_cmdbuf.h"
|
||||||
|
#include "pva_api_types.h"
|
||||||
|
#include "pva_bit.h"
|
||||||
|
#include "pva_fw.h"
|
||||||
|
#include "pva_kmd_cmdbuf.h"
|
||||||
|
#include "pva_kmd_device.h"
|
||||||
|
#include "pva_kmd_fw_debug_printf.h"
|
||||||
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_utils.h"
|
||||||
|
|
||||||
|
void pva_kmd_init_fw_print_buffer(struct pva_kmd_device *pva,
|
||||||
|
void *debug_buffer_va)
|
||||||
|
{
|
||||||
|
struct pva_kmd_fw_print_buffer *print_buffer = &pva->fw_print_buffer;
|
||||||
|
print_buffer->buffer_info = pva_offset_pointer(
|
||||||
|
debug_buffer_va,
|
||||||
|
FW_TRACE_BUFFER_SIZE + FW_CODE_COVERAGE_BUFFER_SIZE);
|
||||||
|
print_buffer->buffer_info->size =
|
||||||
|
(uint32_t)((uint32_t)FW_DEBUG_LOG_BUFFER_SIZE -
|
||||||
|
(uint32_t)sizeof(*print_buffer->buffer_info));
|
||||||
|
print_buffer->buffer_info->head = 0;
|
||||||
|
print_buffer->buffer_info->tail = 0;
|
||||||
|
print_buffer->buffer_info->flags = 0;
|
||||||
|
print_buffer->content = pva_offset_pointer(
|
||||||
|
print_buffer->buffer_info, sizeof(*print_buffer->buffer_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
void pva_kmd_drain_fw_print(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
struct pva_kmd_fw_print_buffer *print_buffer = &pva->fw_print_buffer;
|
||||||
|
struct pva_fw_print_buffer_header *buf_info = print_buffer->buffer_info;
|
||||||
|
uint32_t tail = buf_info->tail;
|
||||||
|
|
||||||
|
if (tail > buf_info->size) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Firmware print tail is out of bounds! Refusing to print\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_info->head > buf_info->size) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Firmware print head is out of bounds! Refusing to print\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (buf_info->head != tail) {
|
||||||
|
uint32_t max_len;
|
||||||
|
uint32_t head = buf_info->head;
|
||||||
|
const char *str = print_buffer->content + head;
|
||||||
|
uint32_t print_size;
|
||||||
|
size_t strnlen_result;
|
||||||
|
|
||||||
|
if ((head + PVA_MAX_DEBUG_LOG_MSG_CHARACTERS) >
|
||||||
|
buf_info->size) {
|
||||||
|
buf_info->head = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head < tail) {
|
||||||
|
max_len = tail - head;
|
||||||
|
} else {
|
||||||
|
max_len = buf_info->size - head;
|
||||||
|
}
|
||||||
|
|
||||||
|
strnlen_result = strnlen(str, max_len);
|
||||||
|
/* Validate strnlen result fits in uint32_t */
|
||||||
|
if (strnlen_result > U32_MAX) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"FW debug print string length exceeds U32_MAX");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* CERT INT31-C: strnlen_result validated to fit in uint32_t, safe to cast */
|
||||||
|
print_size = (uint32_t)strnlen_result;
|
||||||
|
pva_kmd_log_err(str);
|
||||||
|
|
||||||
|
/* +1 for null terminator - use safe addition to prevent overflow */
|
||||||
|
head = safe_addu32(head, safe_addu32(print_size, 1U));
|
||||||
|
if (head >= buf_info->size) {
|
||||||
|
head = 0;
|
||||||
|
}
|
||||||
|
buf_info->head = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((print_buffer->buffer_info->flags &
|
||||||
|
PVA_FW_PRINT_BUFFER_OVERFLOWED) != 0U) {
|
||||||
|
pva_kmd_log_err("Firmware print buffer overflowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((print_buffer->buffer_info->flags & PVA_FW_PRINT_FAILURE) != 0U) {
|
||||||
|
pva_kmd_log_err("Firmware print failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
|
#ifndef PVA_KMD_FW_DEBUG_PRINTF_H
|
||||||
|
#define PVA_KMD_FW_DEBUG_PRINTF_H
|
||||||
|
#include "pva_api.h"
|
||||||
|
#include "pva_fw.h"
|
||||||
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure for managing firmware print buffer access
|
||||||
|
*
|
||||||
|
* @details This structure provides access to the firmware's print/debug output
|
||||||
|
* buffer, which is used for collecting debug messages, trace information, and
|
||||||
|
* other diagnostic output from the firmware. The structure maintains pointers
|
||||||
|
* to both the buffer header (containing metadata) and the actual content data.
|
||||||
|
*/
|
||||||
|
struct pva_kmd_fw_print_buffer {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to firmware print buffer header containing metadata
|
||||||
|
* Valid value: non-null when buffer is active
|
||||||
|
*/
|
||||||
|
struct pva_fw_print_buffer_header *buffer_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the actual print buffer content data
|
||||||
|
* Valid value: non-null when buffer is active
|
||||||
|
*/
|
||||||
|
char const *content;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Drain and process firmware print buffer contents
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Reads new content from the firmware print buffer
|
||||||
|
* - Processes and formats the debug output for display or logging
|
||||||
|
* - Updates buffer read pointers to mark content as consumed
|
||||||
|
* - Handles buffer wraparound and overflow conditions
|
||||||
|
* - Outputs firmware messages to appropriate debug/log channels
|
||||||
|
* - Maintains proper synchronization with firmware buffer updates
|
||||||
|
*
|
||||||
|
* This function is typically called periodically or in response to firmware
|
||||||
|
* notifications to collect and display debug output from the firmware. The
|
||||||
|
* print buffer must be properly initialized before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in, out] print_buffer Pointer to @ref pva_kmd_fw_print_buffer structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
|
void pva_kmd_drain_fw_print(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
void pva_kmd_init_fw_print_buffer(struct pva_kmd_device *pva,
|
||||||
|
void *debug_buffer_va);
|
||||||
|
#endif // PVA_KMD_FW_DEBUG_PRINTF_H
|
||||||
@@ -60,7 +60,8 @@ static const char *priv_cmd_names[PVA_CMD_PRIV_OPCODE_COUNT] = {
|
|||||||
CMD(ENABLE_FW_PROFILING),
|
CMD(ENABLE_FW_PROFILING),
|
||||||
CMD(DISABLE_FW_PROFILING),
|
CMD(DISABLE_FW_PROFILING),
|
||||||
CMD(SUSPEND_FW),
|
CMD(SUSPEND_FW),
|
||||||
CMD(RESUME_FW)
|
CMD(RESUME_FW),
|
||||||
|
CMD(SET_PFSD_CMD_BUFFER_SIZE),
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const char *pva_fw_get_cmd_name(uint32_t opcode)
|
static inline const char *pva_fw_get_cmd_name(uint32_t opcode)
|
||||||
@@ -91,13 +92,13 @@ static inline const char *pva_fw_get_cmd_name(uint32_t opcode)
|
|||||||
|
|
||||||
void pva_kmd_device_init_profiler(struct pva_kmd_device *pva)
|
void pva_kmd_device_init_profiler(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
pva->debugfs_context.g_fw_profiling_config.enabled = false;
|
pva->debugfs_context.g_fw_profiling_config.enabled = (uint8_t) false;
|
||||||
pva->debugfs_context.g_fw_profiling_config.filter = 0x0;
|
pva->debugfs_context.g_fw_profiling_config.filter = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_device_deinit_profiler(struct pva_kmd_device *pva)
|
void pva_kmd_device_deinit_profiler(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
pva->debugfs_context.g_fw_profiling_config.enabled = false;
|
pva->debugfs_context.g_fw_profiling_config.enabled = (uint8_t) false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
||||||
@@ -105,8 +106,11 @@ enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
|||||||
struct pva_kmd_submitter *dev_submitter = &pva->submitter;
|
struct pva_kmd_submitter *dev_submitter = &pva->submitter;
|
||||||
struct pva_cmd_enable_fw_profiling cmd = { 0 };
|
struct pva_cmd_enable_fw_profiling cmd = { 0 };
|
||||||
uint32_t filter = 0U;
|
uint32_t filter = 0U;
|
||||||
uint8_t timestamp_type = TIMESTAMP_TYPE_CYCLE_COUNT;
|
uint8_t timestamp_type = (uint8_t)TIMESTAMP_TYPE_CYCLE_COUNT;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
enum pva_fw_timestamp_t tse_type = TIMESTAMP_TYPE_TSE;
|
||||||
|
uint8_t size_8 = (uint8_t)8U;
|
||||||
|
uint8_t size_4 = (uint8_t)4U;
|
||||||
|
|
||||||
struct pva_kmd_shared_buffer *profiling_buffer =
|
struct pva_kmd_shared_buffer *profiling_buffer =
|
||||||
&pva->kmd_fw_buffers[PVA_PRIV_CCQ_ID];
|
&pva->kmd_fw_buffers[PVA_PRIV_CCQ_ID];
|
||||||
@@ -124,7 +128,8 @@ enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
pva_kmd_set_cmd_enable_fw_profiling(&cmd, filter, timestamp_type);
|
pva_kmd_set_cmd_enable_fw_profiling(&cmd, filter, timestamp_type);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(dev_submitter, &cmd, sizeof(cmd),
|
err = pva_kmd_submit_cmd_sync(dev_submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -132,15 +137,19 @@ enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pva->debugfs_context.g_fw_profiling_config.enabled = true;
|
pva->debugfs_context.g_fw_profiling_config.enabled = (uint8_t) true;
|
||||||
pva->debugfs_context.g_fw_profiling_config.filter = filter;
|
pva->debugfs_context.g_fw_profiling_config.filter = filter;
|
||||||
pva->debugfs_context.g_fw_profiling_config.timestamp_type =
|
pva->debugfs_context.g_fw_profiling_config.timestamp_type =
|
||||||
timestamp_type;
|
timestamp_type;
|
||||||
|
|
||||||
|
if (pva->debugfs_context.g_fw_profiling_config.timestamp_type ==
|
||||||
|
tse_type) {
|
||||||
pva->debugfs_context.g_fw_profiling_config.timestamp_size =
|
pva->debugfs_context.g_fw_profiling_config.timestamp_size =
|
||||||
(pva->debugfs_context.g_fw_profiling_config.timestamp_type ==
|
size_8;
|
||||||
TIMESTAMP_TYPE_TSE) ?
|
} else {
|
||||||
8 :
|
pva->debugfs_context.g_fw_profiling_config.timestamp_size =
|
||||||
4;
|
size_4;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
@@ -161,7 +170,7 @@ enum pva_error pva_kmd_notify_fw_disable_profiling(struct pva_kmd_device *pva)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pva->debugfs_context.g_fw_profiling_config.enabled = false;
|
pva->debugfs_context.g_fw_profiling_config.enabled = (uint8_t) false;
|
||||||
pva->debugfs_context.g_fw_profiling_config.filter = 0x0;
|
pva->debugfs_context.g_fw_profiling_config.filter = 0x0;
|
||||||
|
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
@@ -173,36 +182,54 @@ err_out:
|
|||||||
static void decode_and_print_event(unsigned long walltime,
|
static void decode_and_print_event(unsigned long walltime,
|
||||||
unsigned long relative_time,
|
unsigned long relative_time,
|
||||||
struct pva_fw_event_message message,
|
struct pva_fw_event_message message,
|
||||||
char *msg_string)
|
char *msg_string, size_t msg_size)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
switch (PVA_BIT(message.event)) {
|
switch (PVA_BIT(message.event)) {
|
||||||
case PVA_FW_EVENT_DO_CMD: {
|
case PVA_FW_EVENT_DO_CMD: {
|
||||||
sprintf(msg_string,
|
ret = snprintf(
|
||||||
|
msg_string, msg_size,
|
||||||
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s slot=%u idx=%-5u opcode=%s",
|
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s slot=%u idx=%-5u opcode=%s",
|
||||||
walltime, relative_time, "DO_CMD",
|
walltime, relative_time, "DO_CMD",
|
||||||
event_type_to_string(message.type), message.arg2,
|
event_type_to_string(message.type), message.arg2,
|
||||||
message.arg3, pva_fw_get_cmd_name(message.arg1));
|
message.arg3, pva_fw_get_cmd_name(message.arg1));
|
||||||
|
if (ret < 0 || (size_t)ret >= msg_size) {
|
||||||
|
pva_kmd_log_err("snprintf failed or truncated");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case PVA_FW_EVENT_SCAN_QUEUES: {
|
case PVA_FW_EVENT_SCAN_QUEUES: {
|
||||||
sprintf(msg_string,
|
ret = snprintf(
|
||||||
|
msg_string, msg_size,
|
||||||
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s found=%u ccq_id=%-5u queue_id=%u",
|
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s found=%u ccq_id=%-5u queue_id=%u",
|
||||||
walltime, relative_time, "SCAN_QUEUES",
|
walltime, relative_time, "SCAN_QUEUES",
|
||||||
event_type_to_string(message.type), message.arg1,
|
event_type_to_string(message.type), message.arg1,
|
||||||
message.arg2, message.arg3);
|
message.arg2, message.arg3);
|
||||||
|
if (ret < 0 || (size_t)ret >= msg_size) {
|
||||||
|
pva_kmd_log_err("snprintf failed or truncated");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case PVA_FW_EVENT_SCAN_SLOTS: {
|
case PVA_FW_EVENT_SCAN_SLOTS: {
|
||||||
sprintf(msg_string,
|
ret = snprintf(
|
||||||
|
msg_string, msg_size,
|
||||||
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s state=%u slot=%u",
|
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s state=%u slot=%u",
|
||||||
walltime, relative_time, "SCAN_SLOTS",
|
walltime, relative_time, "SCAN_SLOTS",
|
||||||
event_type_to_string(message.type), message.arg1,
|
event_type_to_string(message.type), message.arg1,
|
||||||
message.arg2);
|
message.arg2);
|
||||||
|
if (ret < 0 || (size_t)ret >= msg_size) {
|
||||||
|
pva_kmd_log_err("snprintf failed or truncated");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case PVA_FW_EVENT_RUN_VPU: {
|
case PVA_FW_EVENT_RUN_VPU: {
|
||||||
sprintf(msg_string,
|
ret = snprintf(
|
||||||
|
msg_string, msg_size,
|
||||||
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s slot=%u idx=%-5u opcode=%s",
|
"pva_fw@%lu: [%8lu] event=%-12s type=%-7s slot=%u idx=%-5u opcode=%s",
|
||||||
walltime, relative_time, "RUN_VPU",
|
walltime, relative_time, "RUN_VPU",
|
||||||
event_type_to_string(message.type), message.arg2,
|
event_type_to_string(message.type),
|
||||||
message.arg3, pva_fw_get_cmd_name(message.arg1));
|
(unsigned int)message.arg2, (unsigned int)message.arg3,
|
||||||
|
pva_fw_get_cmd_name(message.arg1));
|
||||||
|
if (ret < 0 || (size_t)ret >= msg_size) {
|
||||||
|
pva_kmd_log_err("snprintf failed or truncated");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
pva_dbg_printf("Unknown event type\n");
|
pva_dbg_printf("Unknown event type\n");
|
||||||
@@ -210,7 +237,7 @@ static void decode_and_print_event(unsigned long walltime,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_process_fw_event(struct pva_kmd_device *pva,
|
static enum pva_error process_fw_event(struct pva_kmd_device *pva,
|
||||||
uint8_t *data, uint32_t data_size)
|
uint8_t *data, uint32_t data_size)
|
||||||
{
|
{
|
||||||
uint64_t timestamp = 0;
|
uint64_t timestamp = 0;
|
||||||
@@ -247,27 +274,28 @@ enum pva_error pva_kmd_process_fw_event(struct pva_kmd_device *pva,
|
|||||||
0U :
|
0U :
|
||||||
safe_subu64(walltime, prev_walltime);
|
safe_subu64(walltime, prev_walltime);
|
||||||
decode_and_print_event(walltime, relative_time, event_header,
|
decode_and_print_event(walltime, relative_time, event_header,
|
||||||
&msg_string[0]);
|
&msg_string[0], sizeof(msg_string));
|
||||||
pva_kmd_print_str(msg_string);
|
pva_kmd_log_info(msg_string);
|
||||||
prev_walltime = walltime;
|
prev_walltime = walltime;
|
||||||
|
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_process_fw_tracepoint(struct pva_kmd_device *pva,
|
void pva_kmd_process_fw_event(struct pva_kmd_device *pva, uint8_t *msg_body,
|
||||||
struct pva_fw_tracepoint *tp)
|
uint32_t msg_size)
|
||||||
{
|
{
|
||||||
char msg_string[200] = { '\0' };
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
snprintf(
|
// TODO: This must be updated once profiler config is exposed through debugfs.
|
||||||
msg_string, sizeof(msg_string),
|
// KMD must use the same timestamp size as the FW. It is possible that the user
|
||||||
"pva fw tracepoint: type=%s flags=%s slot=%s ccq=%u queue=%u engine=%u arg1=0x%x arg2=0x%x",
|
// changes the timestamp size through debugfs after FW logged the event.
|
||||||
pva_fw_tracepoint_type_to_string(PVA_BIT(tp->type)),
|
// FW must log the type of timestamp it used to capture the event.
|
||||||
pva_fw_tracepoint_flags_to_string(tp->flags),
|
ASSERT(msg_size == sizeof(struct pva_fw_event_message) +
|
||||||
pva_fw_tracepoint_slot_id_to_string(tp->slot_id),
|
pva->debugfs_context.g_fw_profiling_config
|
||||||
(uint32_t)tp->ccq_id, (uint32_t)tp->queue_id,
|
.timestamp_size);
|
||||||
(uint32_t)tp->engine_id, (uint32_t)tp->arg1,
|
|
||||||
(uint32_t)tp->arg2);
|
|
||||||
|
|
||||||
pva_kmd_print_str(msg_string);
|
err = process_fw_event(pva, msg_body, msg_size);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to process FW event");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,217 @@
|
|||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
#include "pva_kmd_shared_buffer.h"
|
#include "pva_kmd_shared_buffer.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of elements in firmware profiling buffer
|
||||||
|
*
|
||||||
|
* @details Number of elements allocated for the firmware profiling buffer.
|
||||||
|
* This constant defines the total capacity of the profiling buffer used
|
||||||
|
* to store firmware profiling events and tracepoints.
|
||||||
|
* Value: 409,600 (4096 * 100)
|
||||||
|
*/
|
||||||
#define PVA_KMD_FW_PROFILING_BUF_NUM_ELEMENTS (4096 * 100)
|
#define PVA_KMD_FW_PROFILING_BUF_NUM_ELEMENTS (4096 * 100)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configuration structure for firmware profiling
|
||||||
|
*
|
||||||
|
* @details This structure contains the configuration parameters for firmware
|
||||||
|
* profiling including filtering criteria, timestamp format, and enable state.
|
||||||
|
* It controls how profiling data is collected and formatted by the firmware
|
||||||
|
* for analysis and debugging purposes.
|
||||||
|
*/
|
||||||
struct pva_kmd_fw_profiling_config {
|
struct pva_kmd_fw_profiling_config {
|
||||||
|
/**
|
||||||
|
* @brief Filter mask for profiling events
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t filter;
|
uint32_t filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of timestamp to use for profiling events
|
||||||
|
* Valid values: @ref pva_fw_timestamp_t enumeration values
|
||||||
|
*/
|
||||||
enum pva_fw_timestamp_t timestamp_type;
|
enum pva_fw_timestamp_t timestamp_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of timestamp data in bytes
|
||||||
|
* Valid range: [1 .. 16]
|
||||||
|
*/
|
||||||
uint8_t timestamp_size;
|
uint8_t timestamp_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable flag for profiling
|
||||||
|
* Valid values: 0 (disabled), 1 (enabled)
|
||||||
|
*/
|
||||||
uint8_t enabled;
|
uint8_t enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if PVA_ENABLE_FW_PROFILING == 1
|
||||||
|
/**
|
||||||
|
* @brief Initialize firmware profiler for a PVA device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Sets up profiling buffer infrastructure for firmware events
|
||||||
|
* - Initializes shared buffer communication for profiling data
|
||||||
|
* - Configures profiling event filtering and formatting parameters
|
||||||
|
* - Prepares the profiler for collecting firmware execution data
|
||||||
|
* - Establishes communication channels between firmware and KMD
|
||||||
|
* - Allocates necessary memory resources for profiling operations
|
||||||
|
*
|
||||||
|
* The profiler enables collection of detailed firmware execution information
|
||||||
|
* including timing data, event sequences, and performance metrics that are
|
||||||
|
* essential for debugging and optimization.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_device_init_profiler(struct pva_kmd_device *pva);
|
void pva_kmd_device_init_profiler(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize firmware profiler and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Disables firmware profiling if currently active
|
||||||
|
* - Releases shared buffer resources used for profiling data
|
||||||
|
* - Frees memory allocated for profiling buffer management
|
||||||
|
* - Cleans up profiling event processing infrastructure
|
||||||
|
* - Ensures proper cleanup of all profiler-related resources
|
||||||
|
* - Invalidates profiler state for the device
|
||||||
|
*
|
||||||
|
* This function should be called during device shutdown to ensure
|
||||||
|
* proper cleanup of all profiling resources and prevent memory leaks.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must have been initialized with profiler
|
||||||
|
*/
|
||||||
void pva_kmd_device_deinit_profiler(struct pva_kmd_device *pva);
|
void pva_kmd_device_deinit_profiler(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
enum pva_error pva_kmd_process_fw_event(struct pva_kmd_device *pva,
|
/**
|
||||||
uint8_t *data, uint32_t data_size);
|
* @brief Process firmware profiling event data
|
||||||
|
*
|
||||||
void pva_kmd_process_fw_tracepoint(struct pva_kmd_device *pva,
|
* @details This function performs the following operations:
|
||||||
struct pva_fw_tracepoint *tp);
|
* - Validates incoming firmware event data format and size
|
||||||
|
* - Parses event data to extract profiling information
|
||||||
|
* - Processes different types of firmware events and tracepoints
|
||||||
|
* - Updates profiling statistics and event counters
|
||||||
|
* - Stores processed events in appropriate data structures
|
||||||
|
* - Handles event filtering based on configuration settings
|
||||||
|
* - Provides event data to profiling analysis tools
|
||||||
|
*
|
||||||
|
* This function is called when firmware sends profiling event data
|
||||||
|
* through the shared buffer communication mechanism, enabling real-time
|
||||||
|
* processing of firmware execution information.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] data Pointer to firmware event data buffer
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] data_size Size of event data in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Event processed successfully
|
||||||
|
* @retval PVA_INVAL Invalid or corrupted event data
|
||||||
|
* @retval PVA_ENOSPC Profiling buffer is full
|
||||||
|
* @retval PVA_BAD_PARAMETER_ERROR Invalid parameters provided
|
||||||
|
*/
|
||||||
|
void pva_kmd_process_fw_event(struct pva_kmd_device *pva, uint8_t *data,
|
||||||
|
uint32_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Notify firmware to enable profiling
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Sends enable profiling command to firmware
|
||||||
|
* - Configures firmware profiling parameters and filters
|
||||||
|
* - Activates profiling data collection in firmware
|
||||||
|
* - Sets up profiling buffer management in firmware
|
||||||
|
* - Establishes profiling event reporting mechanisms
|
||||||
|
* - Validates firmware acknowledgment of profiling enable
|
||||||
|
*
|
||||||
|
* After successful completion, firmware will begin collecting and
|
||||||
|
* reporting profiling events according to the configured parameters.
|
||||||
|
* The profiling data will be available through the shared buffer
|
||||||
|
* communication interface.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Profiling enabled successfully
|
||||||
|
* @retval PVA_TIMEDOUT Failed to communicate with firmware
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Firmware did not respond within timeout
|
||||||
|
* @retval PVA_INTERNAL Firmware in invalid state for profiling
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Notify firmware to disable profiling
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Sends disable profiling command to firmware
|
||||||
|
* - Stops firmware profiling data collection
|
||||||
|
* - Flushes any remaining profiling events from firmware buffers
|
||||||
|
* - Deactivates profiling event reporting mechanisms
|
||||||
|
* - Cleans up firmware profiling state and resources
|
||||||
|
* - Validates firmware acknowledgment of profiling disable
|
||||||
|
*
|
||||||
|
* After successful completion, firmware will stop collecting profiling
|
||||||
|
* events and the profiling overhead will be eliminated. Any remaining
|
||||||
|
* profiling data in buffers will be processed before disabling.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Profiling disabled successfully
|
||||||
|
* @retval PVA_TIMEDOUT Failed to communicate with firmware
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Firmware did not respond within timeout
|
||||||
|
* @retval PVA_INTERNAL Firmware in invalid state for profiling
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_notify_fw_disable_profiling(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_notify_fw_disable_profiling(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline void pva_kmd_device_init_profiler(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pva_kmd_device_deinit_profiler(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pva_kmd_process_fw_event(struct pva_kmd_device *pva,
|
||||||
|
uint8_t *data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_notify_fw_enable_profiling(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_notify_fw_disable_profiling(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* PVA_ENABLE_FW_PROFILING == 1 */
|
||||||
|
|
||||||
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
|
enum pva_error pva_kmd_notify_fw_set_profiling_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t level);
|
||||||
|
#else
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_notify_fw_set_profiling_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t level)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
(void)level;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* PVA_ENABLE_NSYS_PROFILING == 1 */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_api_types.h"
|
||||||
|
#include "pva_fw.h"
|
||||||
|
#include "pva_kmd_cmdbuf.h"
|
||||||
|
#include "pva_kmd_device.h"
|
||||||
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_kmd_fw_tracepoints.h"
|
||||||
|
|
||||||
|
static int64_t update_fw_trace_level(struct pva_kmd_device *pva,
|
||||||
|
void *file_data, const uint8_t *in_buffer,
|
||||||
|
uint64_t offset, uint64_t size)
|
||||||
|
{
|
||||||
|
uint32_t trace_level;
|
||||||
|
unsigned long retval;
|
||||||
|
size_t copy_size;
|
||||||
|
uint32_t base = 10;
|
||||||
|
char strbuf[11]; // 10 bytes for the highest 32bit value and another 1 byte for the Null character
|
||||||
|
strbuf[10] = '\0';
|
||||||
|
|
||||||
|
if (size == 0U) {
|
||||||
|
pva_kmd_log_err("Write failed, no data provided");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy minimum of buffer size and input size */
|
||||||
|
copy_size =
|
||||||
|
(size < (sizeof(strbuf) - 1U)) ? size : (sizeof(strbuf) - 1U);
|
||||||
|
|
||||||
|
retval = pva_kmd_copy_data_from_user(strbuf, in_buffer + offset,
|
||||||
|
copy_size);
|
||||||
|
if (retval != 0UL) {
|
||||||
|
pva_kmd_log_err("Failed to copy write buffer from user");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_level = (uint32_t)pva_kmd_strtol(strbuf, base);
|
||||||
|
|
||||||
|
pva->fw_trace_level = trace_level;
|
||||||
|
|
||||||
|
/* If device is on, busy the device and set the debug log level */
|
||||||
|
if (pva_kmd_device_maybe_on(pva) == true) {
|
||||||
|
enum pva_error err;
|
||||||
|
err = pva_kmd_device_busy(pva);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_device_busy failed when submitting set debug log level cmd");
|
||||||
|
goto err_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_notify_fw_set_trace_level(pva, trace_level);
|
||||||
|
|
||||||
|
pva_kmd_device_idle(pva);
|
||||||
|
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to notify FW about debug log level change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err_end:
|
||||||
|
return (int64_t)copy_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t get_fw_trace_level(struct pva_kmd_device *dev, void *file_data,
|
||||||
|
uint8_t *out_buffer, uint64_t offset,
|
||||||
|
uint64_t size)
|
||||||
|
{
|
||||||
|
char print_buffer[64];
|
||||||
|
int formatted_len;
|
||||||
|
|
||||||
|
formatted_len = snprintf(print_buffer, sizeof(print_buffer), "%u\n",
|
||||||
|
dev->fw_trace_level);
|
||||||
|
|
||||||
|
if (formatted_len <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pva_kmd_read_from_buffer_to_user(out_buffer, size, offset,
|
||||||
|
print_buffer,
|
||||||
|
(uint64_t)formatted_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_fw_tracepoints_init_debugfs(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
enum pva_error err;
|
||||||
|
|
||||||
|
pva->debugfs_context.fw_trace_level_fops.write = &update_fw_trace_level;
|
||||||
|
pva->debugfs_context.fw_trace_level_fops.read = &get_fw_trace_level;
|
||||||
|
pva->debugfs_context.fw_trace_level_fops.pdev = pva;
|
||||||
|
err = pva_kmd_debugfs_create_file(
|
||||||
|
pva, "fw_trace_level",
|
||||||
|
&pva->debugfs_context.fw_trace_level_fops);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to create fw_trace_level debugfs file");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_notify_fw_set_trace_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t trace_level)
|
||||||
|
{
|
||||||
|
struct pva_cmd_set_trace_level cmd = { 0 };
|
||||||
|
pva_kmd_set_cmd_set_trace_level(&cmd, trace_level);
|
||||||
|
|
||||||
|
return pva_kmd_submit_cmd_sync(&pva->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pva_kmd_process_fw_tracepoint(struct pva_kmd_device *pva,
|
||||||
|
struct pva_fw_tracepoint *tp)
|
||||||
|
{
|
||||||
|
char msg_string[200] = { '\0' };
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
msg_string, sizeof(msg_string),
|
||||||
|
"pva fw tracepoint: type=%s flags=%s slot=%s ccq=%u queue=%u engine=%u arg1=0x%x arg2=0x%x",
|
||||||
|
pva_fw_tracepoint_type_to_string(PVA_BIT(tp->type)),
|
||||||
|
pva_fw_tracepoint_flags_to_string(tp->flags),
|
||||||
|
pva_fw_tracepoint_slot_id_to_string(tp->slot_id),
|
||||||
|
(uint32_t)tp->ccq_id, (uint32_t)tp->queue_id,
|
||||||
|
(uint32_t)tp->engine_id, (uint32_t)tp->arg1,
|
||||||
|
(uint32_t)tp->arg2);
|
||||||
|
|
||||||
|
pva_kmd_print_str(msg_string);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
|
#ifndef PVA_KMD_FW_TRACEPOINTS_H
|
||||||
|
#define PVA_KMD_FW_TRACEPOINTS_H
|
||||||
|
|
||||||
|
#include "pva_fw.h"
|
||||||
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
#if PVA_ENABLE_FW_TRACEPOINTS == 1
|
||||||
|
enum pva_error pva_kmd_fw_tracepoints_init_debugfs(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_notify_fw_set_trace_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t trace_level);
|
||||||
|
|
||||||
|
void pva_kmd_process_fw_tracepoint(struct pva_kmd_device *pva,
|
||||||
|
struct pva_fw_tracepoint *tp);
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_fw_tracepoints_init_debugfs(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_notify_fw_set_trace_level(struct pva_kmd_device *pva,
|
||||||
|
uint32_t trace_level)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
(void)trace_level;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pva_kmd_process_fw_tracepoint(struct pva_kmd_device *pva,
|
||||||
|
struct pva_fw_tracepoint *tp)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
(void)tp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // PVA_KMD_FW_TRACEPOINTS_H
|
||||||
@@ -73,12 +73,12 @@ static inline uint8_t get_head_desc_did(struct pva_hwseq_priv const *hwseq)
|
|||||||
return hwseq->dma_descs[0].did;
|
return hwseq->dma_descs[0].did;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline enum pva_error check_adv_params(int32_t adv1, int32_t adv2,
|
static inline enum pva_error check_adv_params(uint32_t adv1, uint32_t adv2,
|
||||||
int32_t adv3, uint8_t rpt1,
|
uint32_t adv3, uint8_t rpt1,
|
||||||
uint8_t rpt2, uint8_t rpt3,
|
uint8_t rpt2, uint8_t rpt3,
|
||||||
bool has_dim3)
|
bool has_dim3)
|
||||||
{
|
{
|
||||||
if (!has_dim3 && ((adv1 != 0) || (adv2 != 0) || (adv3 != 0) ||
|
if (!has_dim3 && ((adv1 != 0U) || (adv2 != 0U) || (adv3 != 0U) ||
|
||||||
((rpt1 + rpt2 + rpt3) != 0U))) {
|
((rpt1 + rpt2 + rpt3) != 0U))) {
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
@@ -114,13 +114,10 @@ validate_adv_params(struct pva_dma_transfer_attr const *attr, bool has_dim3)
|
|||||||
pva_kmd_log_err("descriptor source tile looping not allowed");
|
pva_kmd_log_err("descriptor source tile looping not allowed");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (attr->adv1 < 0) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"source advance amount on dim1 can not be negative");
|
|
||||||
return PVA_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((attr->adv1 * ((int32_t)(attr->rpt1) + 1)) != attr->adv2) {
|
/* Use 64-bit arithmetic to avoid overflow in multiplication */
|
||||||
|
if (((uint64_t)attr->adv1 * ((uint64_t)attr->rpt1 + 1ULL)) !=
|
||||||
|
(uint64_t)attr->adv2) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Invalid source advance amount on dim1 or dim2");
|
"Invalid source advance amount on dim1 or dim2");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
@@ -260,7 +257,7 @@ check_vmem_setup(struct pva_dma_transfer_attr const *attr,
|
|||||||
uint32_t vmem_tile_count, bool has_dim3)
|
uint32_t vmem_tile_count, bool has_dim3)
|
||||||
{
|
{
|
||||||
if ((!has_dim3) && (vmem_tile_count > 1U) &&
|
if ((!has_dim3) && (vmem_tile_count > 1U) &&
|
||||||
((attr->adv1 != 0) || (attr->adv2 != 0) || (attr->adv3 != 0))) {
|
((attr->adv1 != 0U) || (attr->adv2 != 0U) || (attr->adv3 != 0U))) {
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
@@ -426,11 +423,6 @@ static enum pva_error validate_dst_vmem(struct pva_hwseq_priv *hwseq,
|
|||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_desc->src.adv1 < 0) {
|
|
||||||
pva_kmd_log_err("Source adv1 can not be negative");
|
|
||||||
return PVA_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tx = maxu32(head_desc->tx, tail_desc->tx);
|
tx = maxu32(head_desc->tx, tail_desc->tx);
|
||||||
ty = maxu32(head_desc->ty, tail_desc->ty);
|
ty = maxu32(head_desc->ty, tail_desc->ty);
|
||||||
end_addr =
|
end_addr =
|
||||||
@@ -438,8 +430,9 @@ static enum pva_error validate_dst_vmem(struct pva_hwseq_priv *hwseq,
|
|||||||
subs64((int64_t)ty, 1LL, &math_err), &math_err);
|
subs64((int64_t)ty, 1LL, &math_err), &math_err);
|
||||||
|
|
||||||
end_addr = adds64(end_addr, (int64_t)tx, &math_err);
|
end_addr = adds64(end_addr, (int64_t)tx, &math_err);
|
||||||
end_addr = adds64(muls64((int64_t)head_desc->src.rpt1,
|
end_addr =
|
||||||
head_desc->dst.adv1, &math_err),
|
adds64(muls64((int64_t)head_desc->src.rpt1,
|
||||||
|
(int64_t)head_desc->dst.adv1, &math_err),
|
||||||
end_addr, &math_err);
|
end_addr, &math_err);
|
||||||
|
|
||||||
end_addr = adds64(muls64(end_addr, num_bytes, &math_err),
|
end_addr = adds64(muls64(end_addr, num_bytes, &math_err),
|
||||||
@@ -573,8 +566,9 @@ static enum pva_error validate_src_vmem(struct pva_hwseq_priv *hwseq,
|
|||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
end_addr = adds64(muls64((int64_t)head_desc->dst.rpt1,
|
end_addr =
|
||||||
head_desc->src.adv1, &math_err),
|
adds64(muls64((int64_t)head_desc->dst.rpt1,
|
||||||
|
(int64_t)head_desc->src.adv1, &math_err),
|
||||||
end_addr, &math_err);
|
end_addr, &math_err);
|
||||||
|
|
||||||
end_addr = adds64(muls64(end_addr, num_bytes, &math_err),
|
end_addr = adds64(muls64(end_addr, num_bytes, &math_err),
|
||||||
@@ -986,9 +980,12 @@ validate_frame_buffer_addr(struct pva_hwseq_priv *hwseq,
|
|||||||
uint8_t head_desc_id = get_head_desc_did(hwseq);
|
uint8_t head_desc_id = get_head_desc_did(hwseq);
|
||||||
const struct pva_dma_descriptor *head_desc = hwseq->head_desc;
|
const struct pva_dma_descriptor *head_desc = hwseq->head_desc;
|
||||||
pva_math_error math_err = MATH_OP_SUCCESS;
|
pva_math_error math_err = MATH_OP_SUCCESS;
|
||||||
|
uint32_t adv_value =
|
||||||
frame_plane_size =
|
|
||||||
sequencing_to_vmem ? head_desc->src.adv1 : head_desc->dst.adv1;
|
sequencing_to_vmem ? head_desc->src.adv1 : head_desc->dst.adv1;
|
||||||
|
|
||||||
|
/* adv1 is uint32_t but limited to 24-bit range (max 0xFFFFFF < INT32_MAX) */
|
||||||
|
ASSERT(adv_value <= 0x7FFFFFFFU);
|
||||||
|
frame_plane_size = (int32_t)adv_value;
|
||||||
frame_buffer_start =
|
frame_buffer_start =
|
||||||
adds64(muls64(frame_info->start_y, (int64_t)frame_line_pitch,
|
adds64(muls64(frame_info->start_y, (int64_t)frame_line_pitch,
|
||||||
&math_err),
|
&math_err),
|
||||||
@@ -1061,12 +1058,12 @@ static void get_sequencing_and_dim3(struct pva_hwseq_priv *hwseq,
|
|||||||
*has_dim3 = ((head_desc->src.rpt1 == head_desc->dst.rpt1) &&
|
*has_dim3 = ((head_desc->src.rpt1 == head_desc->dst.rpt1) &&
|
||||||
(head_desc->src.rpt2 == head_desc->dst.rpt2));
|
(head_desc->src.rpt2 == head_desc->dst.rpt2));
|
||||||
*has_dim3 = *has_dim3 &&
|
*has_dim3 = *has_dim3 &&
|
||||||
((*sequencing_to_vmem) ? ((head_desc->src.adv1 > 0) &&
|
((*sequencing_to_vmem) ? ((head_desc->src.adv1 > 0U) &&
|
||||||
(head_desc->src.adv2 > 0) &&
|
(head_desc->src.adv2 > 0U) &&
|
||||||
(head_desc->dst.adv1 > 0)) :
|
(head_desc->dst.adv1 > 0U)) :
|
||||||
((head_desc->dst.adv1 > 0) &&
|
((head_desc->dst.adv1 > 0U) &&
|
||||||
(head_desc->dst.adv2 > 0) &&
|
(head_desc->dst.adv2 > 0U) &&
|
||||||
(head_desc->src.adv1 > 0)));
|
(head_desc->src.adv1 > 0U)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1147,6 +1144,48 @@ validate_dma_boundaries(struct pva_hwseq_priv *hwseq,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
process_frame_descriptors(struct pva_hwseq_priv *hwseq_info,
|
||||||
|
struct pva_dma_hwseq_desc_entry *desc_entries,
|
||||||
|
uint32_t num_descs, uint64_t *hw_dma_descs_mask)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
const struct pva_dma_hwseq_desc_entry *desc_entry = NULL;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_descs; i++) {
|
||||||
|
desc_entry = (const struct pva_dma_hwseq_desc_entry
|
||||||
|
*)(read_hwseq_blob(
|
||||||
|
&hwseq_info->blob,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_hwseq_desc_entry)));
|
||||||
|
|
||||||
|
if (validate_desc_entry(
|
||||||
|
desc_entry,
|
||||||
|
safe_addu8(hwseq_info->dma_config->header
|
||||||
|
.base_descriptor,
|
||||||
|
hwseq_info->dma_config->header
|
||||||
|
.num_descriptors)) !=
|
||||||
|
PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Invalid DMA Descriptor Entry");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
desc_entries[i].did = desc_entry->did - 1U;
|
||||||
|
//TODO enable nv_array_index_no_speculate later
|
||||||
|
// desc_entries[i].did = (uint8_t) nv_array_index_no_speculate_u32(
|
||||||
|
// desc_entries[i].did, max_num_descs);
|
||||||
|
|
||||||
|
desc_entries[i].dr = desc_entry->dr;
|
||||||
|
hw_dma_descs_mask[(desc_entries[i].did / 64ULL)] |=
|
||||||
|
1ULL << (desc_entries[i].did & MAX_DESC_ID);
|
||||||
|
|
||||||
|
hwseq_info->tiles_per_packet += ((uint32_t)desc_entry->dr + 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Validates the HW Sequener when it is in Frame Addressing Mode
|
* \brief Validates the HW Sequener when it is in Frame Addressing Mode
|
||||||
*
|
*
|
||||||
@@ -1184,10 +1223,8 @@ validate_dma_boundaries(struct pva_hwseq_priv *hwseq,
|
|||||||
static enum pva_error validate_frame_mode(struct pva_hwseq_priv *hwseq_info,
|
static enum pva_error validate_frame_mode(struct pva_hwseq_priv *hwseq_info,
|
||||||
uint64_t *hw_dma_descs_mask)
|
uint64_t *hw_dma_descs_mask)
|
||||||
{
|
{
|
||||||
struct pva_dma_hwseq_desc_entry *desc_entry = NULL;
|
|
||||||
struct pva_dma_hwseq_desc_entry *desc_entries = hwseq_info->dma_descs;
|
struct pva_dma_hwseq_desc_entry *desc_entries = hwseq_info->dma_descs;
|
||||||
uint32_t num_descs = 0U;
|
uint32_t num_descs = 0U;
|
||||||
uint32_t i = 0U;
|
|
||||||
uint32_t num_cr = 0U;
|
uint32_t num_cr = 0U;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
struct pva_hwseq_per_frame_info fr_info = { 0 };
|
struct pva_hwseq_per_frame_info fr_info = { 0 };
|
||||||
@@ -1197,21 +1234,22 @@ static enum pva_error validate_frame_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
pva_kmd_log_err_u64(
|
pva_kmd_log_err_u64(
|
||||||
"Cannot have more than 1 col/row header in GEN2",
|
"Cannot have more than 1 col/row header in GEN2",
|
||||||
hwseq_info->hdr->nocr);
|
hwseq_info->hdr->nocr);
|
||||||
return PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (num_cr = 0; num_cr <= hwseq_info->hdr->nocr; num_cr++) {
|
for (num_cr = 0; num_cr <= hwseq_info->hdr->nocr; num_cr++) {
|
||||||
hwseq_info->tiles_per_packet = 0;
|
hwseq_info->tiles_per_packet = 0;
|
||||||
hwseq_info->colrow =
|
hwseq_info->colrow = (const struct pva_dma_hwseq_colrow_hdr
|
||||||
(struct pva_dma_hwseq_colrow_hdr *)(read_hwseq_blob(
|
*)(read_hwseq_blob(
|
||||||
&hwseq_info->blob,
|
&hwseq_info->blob,
|
||||||
(uint32_t)sizeof(
|
(uint32_t)sizeof(struct pva_dma_hwseq_colrow_hdr)));
|
||||||
struct pva_dma_hwseq_colrow_hdr)));
|
|
||||||
|
|
||||||
if (hwseq_info->colrow == NULL) {
|
if (hwseq_info->colrow == NULL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Cannot read HW sequencer col/row header");
|
"Cannot read HW sequencer col/row header");
|
||||||
return PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_descs = hwseq_info->colrow->dec + (uint32_t)1U;
|
num_descs = hwseq_info->colrow->dec + (uint32_t)1U;
|
||||||
@@ -1219,39 +1257,17 @@ static enum pva_error validate_frame_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
if (num_descs > 2U) {
|
if (num_descs > 2U) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Cannot have more than 2 descriptors in HW Sequencer");
|
"Cannot have more than 2 descriptors in HW Sequencer");
|
||||||
return PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_descs; i++) {
|
err = process_frame_descriptors(hwseq_info, desc_entries,
|
||||||
desc_entry = (struct pva_dma_hwseq_desc_entry
|
num_descs, hw_dma_descs_mask);
|
||||||
*)(read_hwseq_blob(
|
if (err != PVA_SUCCESS) {
|
||||||
&hwseq_info->blob,
|
goto out;
|
||||||
(uint32_t)sizeof(
|
|
||||||
struct pva_dma_hwseq_desc_entry)));
|
|
||||||
|
|
||||||
if (validate_desc_entry(
|
|
||||||
desc_entry,
|
|
||||||
safe_addu8(hwseq_info->dma_config->header
|
|
||||||
.base_descriptor,
|
|
||||||
hwseq_info->dma_config->header
|
|
||||||
.num_descriptors)) !=
|
|
||||||
PVA_SUCCESS) {
|
|
||||||
pva_kmd_log_err("Invalid DMA Descriptor Entry");
|
|
||||||
return PVA_INVAL;
|
|
||||||
}
|
}
|
||||||
desc_entries[i].did = desc_entry->did - 1U;
|
|
||||||
//TODO enable nv_array_index_no_speculate later
|
|
||||||
// desc_entries[i].did = (uint8_t) nv_array_index_no_speculate_u32(
|
|
||||||
// desc_entries[i].did, max_num_descs);
|
|
||||||
|
|
||||||
desc_entries[i].dr = desc_entry->dr;
|
if ((num_descs % 2U) != 0U) {
|
||||||
hw_dma_descs_mask[(desc_entries[i].did / 64ULL)] |=
|
|
||||||
1ULL << (desc_entries[i].did & MAX_DESC_ID);
|
|
||||||
|
|
||||||
hwseq_info->tiles_per_packet +=
|
|
||||||
((uint32_t)desc_entry->dr + 1U);
|
|
||||||
}
|
|
||||||
if ((i == num_descs) && ((i % 2U) != 0U)) {
|
|
||||||
(void)read_hwseq_blob(
|
(void)read_hwseq_blob(
|
||||||
&hwseq_info->blob,
|
&hwseq_info->blob,
|
||||||
(uint32_t)sizeof(
|
(uint32_t)sizeof(
|
||||||
@@ -1275,17 +1291,18 @@ static enum pva_error validate_frame_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
|
|
||||||
err = validate_dma_boundaries(hwseq_info, &fr_info, num_cr);
|
err = validate_dma_boundaries(hwseq_info, &fr_info, num_cr);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum pva_error validate_rra_mode(struct pva_hwseq_priv *hwseq_info,
|
static enum pva_error validate_rra_mode(struct pva_hwseq_priv *hwseq_info,
|
||||||
uint64_t *hw_dma_descs_mask)
|
uint64_t *hw_dma_descs_mask)
|
||||||
{
|
{
|
||||||
const uint8_t *column = 0U;
|
const uint8_t *column = NULL;
|
||||||
uint32_t i = 0U;
|
uint32_t i = 0U;
|
||||||
uint32_t num_columns = 0U;
|
uint32_t num_columns = 0U;
|
||||||
uint32_t end = hwseq_info->entry.ch->hwseq_end;
|
uint32_t end = hwseq_info->entry.ch->hwseq_end;
|
||||||
@@ -1306,24 +1323,31 @@ static enum pva_error validate_rra_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hwseq_info->hdr->fr != 0) {
|
if (hwseq_info->hdr->fr != 0U) {
|
||||||
pva_kmd_log_err("Invalid HWSEQ repetition factor");
|
pva_kmd_log_err("Invalid HWSEQ repetition factor");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_columns = hwseq_info->hdr->nocr + 1U;
|
num_columns = (uint32_t)hwseq_info->hdr->nocr + 1U;
|
||||||
column = hwseq_info->blob.data + sizeof(struct pva_dma_hwseq_hdr);
|
column = hwseq_info->blob.data + sizeof(struct pva_dma_hwseq_hdr);
|
||||||
|
|
||||||
// Ensure there are sufficient CRO and Desc ID entries in the HWSEQ blob
|
// Ensure there are sufficient CRO and Desc ID entries in the HWSEQ blob
|
||||||
if (((blob_end - column) / column_entry_size) < num_columns) {
|
{
|
||||||
pva_kmd_log_err("HWSEQ Program does not have enough columns");
|
ptrdiff_t blob_diff = blob_end - column;
|
||||||
|
size_t blob_size = (blob_diff >= 0) ? (size_t)blob_diff : 0U;
|
||||||
|
if ((blob_end < column) ||
|
||||||
|
((blob_size / (size_t)column_entry_size) < num_columns)) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"HWSEQ Program does not have enough columns");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0U; i < num_columns; i++) {
|
for (i = 0U; i < num_columns; i++) {
|
||||||
struct pva_dma_hwseq_desc_entry desc_entry;
|
struct pva_dma_hwseq_desc_entry desc_entry;
|
||||||
uint32_t *desc_read_data = (uint32_t *)(read_hwseq_blob(
|
const uint32_t *desc_read_data =
|
||||||
&hwseq_info->blob, column_entry_size));
|
(const uint32_t *)(read_hwseq_blob(&hwseq_info->blob,
|
||||||
|
column_entry_size));
|
||||||
if (desc_read_data == NULL) {
|
if (desc_read_data == NULL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Failed to read descriptor data from HWSEQ blob");
|
"Failed to read descriptor data from HWSEQ blob");
|
||||||
@@ -1335,9 +1359,13 @@ static enum pva_error validate_rra_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
// In RRA mode, each HWSEQ column has only 1 descriptor
|
// In RRA mode, each HWSEQ column has only 1 descriptor
|
||||||
// Hence, we validate the first descriptor and ignore the second
|
// Hence, we validate the first descriptor and ignore the second
|
||||||
// descriptor in each column
|
// descriptor in each column
|
||||||
desc_entry.did = (desc_read_data[1U] & 0x000000FFU);
|
desc_entry.did = (uint8_t)(desc_read_data[1U] & 0x000000FFU);
|
||||||
desc_entry.dr = ((desc_read_data[1U] & 0x0000FF00U) >> 8U);
|
desc_entry.dr =
|
||||||
if (validate_desc_entry(&desc_entry, PVA_MAX_NUM_DMA_DESC) !=
|
(uint8_t)((desc_read_data[1U] & 0x0000FF00U) >> 8U);
|
||||||
|
/* CERT INT31-C: PVA_MAX_NUM_DMA_DESC is compile-time constant <= 96,
|
||||||
|
* always fits in uint8_t, safe to cast */
|
||||||
|
if (validate_desc_entry(&desc_entry,
|
||||||
|
(uint8_t)PVA_MAX_NUM_DMA_DESC) !=
|
||||||
PVA_SUCCESS) {
|
PVA_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"Invalid Descriptor ID found in HW Sequencer");
|
"Invalid Descriptor ID found in HW Sequencer");
|
||||||
@@ -1348,7 +1376,7 @@ static enum pva_error validate_rra_mode(struct pva_hwseq_priv *hwseq_info,
|
|||||||
1ULL << (desc_entry.did & MAX_DESC_ID);
|
1ULL << (desc_entry.did & MAX_DESC_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return PVA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1436,21 +1464,27 @@ check_for_valid_hwseq_type(struct pva_hwseq_priv *hwseq_info,
|
|||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
//Populate hwseq_info header
|
//Populate hwseq_info header
|
||||||
hwseq_info->hdr = (struct pva_dma_hwseq_hdr *)(read_hwseq_blob(
|
hwseq_info->hdr = (const struct pva_dma_hwseq_hdr *)(read_hwseq_blob(
|
||||||
&hwseq_info->blob, (uint32_t)sizeof(struct pva_dma_hwseq_hdr)));
|
&hwseq_info->blob, (uint32_t)sizeof(struct pva_dma_hwseq_hdr)));
|
||||||
if (hwseq_info->hdr == NULL) {
|
if (hwseq_info->hdr == NULL) {
|
||||||
pva_kmd_log_err("HW sequencer buffer does not contain header");
|
pva_kmd_log_err("HW sequencer buffer does not contain header");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hwseq_info->hdr->fr != 0U) || (hwseq_info->hdr->fo != 0U)) {
|
if ((hwseq_info->hdr->fr != 0U) || (hwseq_info->hdr->fo != 0)) {
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_DESC_MODE) {
|
if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_DESC_MODE) {
|
||||||
err = validate_desc_mode(hwseq_info);
|
err = validate_desc_mode(hwseq_info);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Descriptor mode validation failed");
|
||||||
|
}
|
||||||
} else if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_FRAME_MODE) {
|
} else if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_FRAME_MODE) {
|
||||||
err = validate_frame_mode(hwseq_info, hw_dma_descs_mask);
|
err = validate_frame_mode(hwseq_info, hw_dma_descs_mask);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Frame mode validation failed");
|
||||||
|
}
|
||||||
} else if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_RRA_MODE) {
|
} else if (hwseq_info->hdr->fid == (uint16_t)PVA_DMA_HWSEQ_RRA_MODE) {
|
||||||
if (hwseq_info->hw_gen < PVA_HW_GEN3) {
|
if (hwseq_info->hw_gen < PVA_HW_GEN3) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
@@ -1458,6 +1492,9 @@ check_for_valid_hwseq_type(struct pva_hwseq_priv *hwseq_info,
|
|||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
}
|
}
|
||||||
err = validate_rra_mode(hwseq_info, hw_dma_descs_mask);
|
err = validate_rra_mode(hwseq_info, hw_dma_descs_mask);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("RRA mode validation failed");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pva_kmd_log_err("Invalid Header in HW Sequencer Blob");
|
pva_kmd_log_err("Invalid Header in HW Sequencer Blob");
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
@@ -1517,7 +1554,7 @@ validate_channel_accesses(const struct pva_dma_channel *ch,
|
|||||||
entry->hwseq_end = ch->hwseq_end;
|
entry->hwseq_end = ch->hwseq_end;
|
||||||
entry->num_frames = 1U;
|
entry->num_frames = 1U;
|
||||||
if (hw_gen == PVA_HW_GEN3) {
|
if (hw_gen == PVA_HW_GEN3) {
|
||||||
entry->num_frames = ch->hwseq_frame_count + 1U;
|
entry->num_frames = (uint32_t)ch->hwseq_frame_count + 1U;
|
||||||
}
|
}
|
||||||
entry->ch = ch;
|
entry->ch = ch;
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
@@ -1542,7 +1579,7 @@ enum pva_error validate_hwseq(struct pva_dma_config const *dma_config,
|
|||||||
|
|
||||||
for (i = 0U; i < num_channels; i++) {
|
for (i = 0U; i < num_channels; i++) {
|
||||||
ch = &dma_config->channels[i];
|
ch = &dma_config->channels[i];
|
||||||
if (ch->hwseq_enable == 1) {
|
if (ch->hwseq_enable == 1U) {
|
||||||
err = validate_channel_accesses(ch, &dma_config->header,
|
err = validate_channel_accesses(ch, &dma_config->header,
|
||||||
hwseq_info.hw_gen,
|
hwseq_info.hw_gen,
|
||||||
&entries[num_hwseqs]);
|
&entries[num_hwseqs]);
|
||||||
@@ -1555,13 +1592,15 @@ enum pva_error validate_hwseq(struct pva_dma_config const *dma_config,
|
|||||||
|
|
||||||
for (i = 0U; i < num_hwseqs; i++) {
|
for (i = 0U; i < num_hwseqs; i++) {
|
||||||
uint32_t start_index = entries[i].hwseq_start;
|
uint32_t start_index = entries[i].hwseq_start;
|
||||||
uint32_t end_index = entries[i].hwseq_end + 1U;
|
uint32_t end_index = (uint32_t)entries[i].hwseq_end + 1U;
|
||||||
uint32_t curr_offset = start_index << 2U;
|
uint32_t curr_offset = start_index << 2U;
|
||||||
uint32_t len = 0U;
|
uint32_t len = 0U;
|
||||||
|
const uint8_t *base;
|
||||||
|
|
||||||
//Populate hwseq blob
|
//Populate hwseq blob
|
||||||
hwseq_info.blob.data =
|
/* Use byte pointer arithmetic for offset calculation */
|
||||||
(uint8_t *)((uintptr_t)(dma_config->hwseq_words) +
|
base = (const uint8_t *)dma_config->hwseq_words;
|
||||||
(curr_offset));
|
hwseq_info.blob.data = base + curr_offset;
|
||||||
|
|
||||||
len = safe_subu32(end_index, start_index);
|
len = safe_subu32(end_index, start_index);
|
||||||
hwseq_info.blob.bytes_left = (len << 2U);
|
hwseq_info.blob.bytes_left = (len << 2U);
|
||||||
|
|||||||
@@ -6,320 +6,536 @@
|
|||||||
#include "pva_api_dma.h"
|
#include "pva_api_dma.h"
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of column/row descriptors in RRA mode
|
||||||
|
*
|
||||||
|
* @details Maximum allowed value for Number of Column/Row descriptors
|
||||||
|
* in RRA (Rectangular Region Access) addressing mode.
|
||||||
|
* This constant defines the upper bound for column/row descriptor
|
||||||
|
* validation in hardware sequencer configurations.
|
||||||
|
*/
|
||||||
#define PVA_HWSEQ_RRA_MAX_NOCR 31U
|
#define PVA_HWSEQ_RRA_MAX_NOCR 31U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum frame count in hardware sequencer
|
||||||
|
*
|
||||||
|
* @details Maximum allowed frame count for hardware sequencer operations.
|
||||||
|
* This limits the number of frames that can be processed in a single
|
||||||
|
* hardware sequencer configuration to ensure proper resource management
|
||||||
|
* and validation.
|
||||||
|
*/
|
||||||
#define PVA_HWSEQ_RRA_MAX_FRAME_COUNT 63U
|
#define PVA_HWSEQ_RRA_MAX_FRAME_COUNT 63U
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of valid Addressing Modes in HW Sequencer Header
|
* @brief Enumeration of hardware sequencer addressing modes
|
||||||
|
*
|
||||||
|
* @details This enumeration defines the valid addressing modes supported
|
||||||
|
* by the hardware sequencer for DMA operations. Each mode uses a specific
|
||||||
|
* Frame ID (FID) value to identify the addressing type in the hardware
|
||||||
|
* sequencer header. The addressing mode determines how the hardware
|
||||||
|
* sequencer processes and organizes DMA operations.
|
||||||
*/
|
*/
|
||||||
enum pva_dma_hwseq_fid {
|
enum pva_dma_hwseq_fid {
|
||||||
PVA_DMA_HWSEQ_RRA_MODE = 0xC0DA, /*!< RRA addressing */
|
/** @brief RRA (Rectangular Region Access) addressing mode */
|
||||||
PVA_DMA_HWSEQ_FRAME_MODE = 0xC0DE, /*!< frame addressing */
|
PVA_DMA_HWSEQ_RRA_MODE = 0xC0DA,
|
||||||
PVA_DMA_HWSEQ_DESC_MODE = 0xDEAD /*!< descriptor addressing */
|
/** @brief Frame-based addressing mode */
|
||||||
|
PVA_DMA_HWSEQ_FRAME_MODE = 0xC0DE,
|
||||||
|
/** @brief Descriptor-based addressing mode */
|
||||||
|
PVA_DMA_HWSEQ_DESC_MODE = 0xDEAD
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combine three headers common in HW Sequencer
|
* @brief Hardware sequencer header structure
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* @details This structure contains the header information for hardware
|
||||||
* | | byte 3 | byte 2 | byte 1 | byte 0 |
|
* sequencer configurations. The header defines addressing type, repetition
|
||||||
* |--------|---------------|--------------|-----------------|----------------|
|
* factors, offsets, and padding values that control DMA operation patterns.
|
||||||
* | Head 1 | NOCR | FR | FID1 | FID0 |
|
* The structure provides the necessary metadata for hardware sequencer
|
||||||
* | Head 2 | FO in LP 15:8 | FO in LP 7:0 | TO in P/LP 15:8 | TO in P/LP 7:0 |
|
* operation configuration and validation.
|
||||||
* | Head 3 | padB | padL | padT | padR |
|
*/
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
**/
|
|
||||||
struct pva_dma_hwseq_hdr {
|
struct pva_dma_hwseq_hdr {
|
||||||
//hdr_1
|
/**
|
||||||
uint16_t fid; /*!< addressing type: frame or descriptor */
|
* @brief Frame ID indicating addressing type
|
||||||
uint8_t fr; /*!< frame repetition factor */
|
* Valid values: @ref pva_dma_hwseq_fid enumeration values
|
||||||
uint8_t nocr; /*!< number of descriptor column/row */
|
*/
|
||||||
//hdr_2
|
uint16_t fid;
|
||||||
int16_t to; /*!< tile offset in pixel/Line Pitch */
|
|
||||||
int16_t fo; /*!< frame offset in Line Pitch */
|
/**
|
||||||
//hdr_3
|
* @brief Frame repetition factor
|
||||||
uint8_t padr; /*!< pad right */
|
* Valid range: [1 .. 255]
|
||||||
uint8_t padt; /*!< pad top */
|
*/
|
||||||
uint8_t padl; /*!< pad left */
|
uint8_t fr;
|
||||||
uint8_t padb; /*!< pad bottom */
|
|
||||||
|
/**
|
||||||
|
* @brief Number of descriptor columns/rows
|
||||||
|
* Valid range: [0 .. PVA_HWSEQ_RRA_MAX_NOCR]
|
||||||
|
*/
|
||||||
|
uint8_t nocr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tile offset in pixels or line pitch
|
||||||
|
* Valid range: [INT16_MIN .. INT16_MAX]
|
||||||
|
*/
|
||||||
|
int16_t to;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Frame offset in line pitch
|
||||||
|
* Valid range: [INT16_MIN .. INT16_MAX]
|
||||||
|
*/
|
||||||
|
int16_t fo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Padding for right edge
|
||||||
|
* Valid range: [0 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t padr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Padding for top edge
|
||||||
|
* Valid range: [0 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t padt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Padding for left edge
|
||||||
|
* Valid range: [0 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t padl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Padding for bottom edge
|
||||||
|
* Valid range: [0 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t padb;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct which represents Column/Row Header in HW Sequencer
|
* @brief Hardware sequencer column/row header structure
|
||||||
|
*
|
||||||
|
* @details This structure represents the column/row header information
|
||||||
|
* in hardware sequencer configurations. It controls descriptor entry
|
||||||
|
* counts, repetition factors, and offset values for column/row operations
|
||||||
|
* within the hardware sequencer processing pipeline.
|
||||||
*/
|
*/
|
||||||
struct pva_dma_hwseq_colrow_hdr {
|
struct pva_dma_hwseq_colrow_hdr {
|
||||||
uint8_t dec; /*!< descriptor entry count */
|
/**
|
||||||
uint8_t crr; /*!< col/row repetition factor */
|
* @brief Descriptor entry count
|
||||||
int16_t cro; /*!< col/row ofst in pixel/line pitch */
|
* Valid range: [1 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t dec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Column/row repetition factor
|
||||||
|
* Valid range: [1 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t crr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Column/row offset in pixels or line pitch
|
||||||
|
* Valid range: [INT16_MIN .. INT16_MAX]
|
||||||
|
*/
|
||||||
|
int16_t cro;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct which represents a DMA Descriptor Header in HW Sequencer
|
* @brief Hardware sequencer DMA descriptor entry
|
||||||
|
*
|
||||||
|
* @details This structure represents a single DMA descriptor entry
|
||||||
|
* in the hardware sequencer. It contains the descriptor ID and its
|
||||||
|
* repetition count for the DMA operation, enabling efficient
|
||||||
|
* descriptor reuse and pattern-based DMA processing.
|
||||||
*/
|
*/
|
||||||
struct pva_dma_hwseq_desc_entry {
|
struct pva_dma_hwseq_desc_entry {
|
||||||
uint8_t did; /*!< desc id */
|
/**
|
||||||
uint8_t dr; /*!< desc repetition */
|
* @brief Descriptor ID referencing a DMA descriptor
|
||||||
|
* Valid range: [0 .. MAX_DESC_ID]
|
||||||
|
*/
|
||||||
|
uint8_t did;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Descriptor repetition count
|
||||||
|
* Valid range: [1 .. 255]
|
||||||
|
*/
|
||||||
|
uint8_t dr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct which represents a Column/Row Header Entry in HW Sequencer
|
* @brief Hardware sequencer column/row entry header
|
||||||
|
*
|
||||||
|
* @details This structure wraps the column/row header to represent
|
||||||
|
* a complete column/row entry in the hardware sequencer configuration.
|
||||||
|
* It provides structural organization for column/row operations
|
||||||
|
* within the hardware sequencer processing pipeline.
|
||||||
*/
|
*/
|
||||||
struct pva_dma_hwseq_colrow_entry_hdr {
|
struct pva_dma_hwseq_colrow_entry_hdr {
|
||||||
struct pva_dma_hwseq_colrow_hdr hdr; /*!< Col/Row Header */
|
/** @brief Column/row header information */
|
||||||
|
struct pva_dma_hwseq_colrow_hdr hdr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct representing Grid Information
|
* @brief Hardware sequencer grid information structure
|
||||||
|
*
|
||||||
|
* @details This structure contains comprehensive grid information for
|
||||||
|
* hardware sequencer operations. It includes tile coordinates, padding
|
||||||
|
* values, grid dimensions, and processing modes. The interpretation
|
||||||
|
* of coordinates varies between different processing modes to support
|
||||||
|
* various data layout patterns and access patterns.
|
||||||
*/
|
*/
|
||||||
struct pva_hwseq_grid_info {
|
struct pva_hwseq_grid_info {
|
||||||
/**
|
/**
|
||||||
* tile co-ordinates
|
* @brief Tile X-coordinates for first and last tiles
|
||||||
* In Raster Mode:
|
*
|
||||||
* - tile_x[0] = Tile width of the first tile in HW Seq DMA Transfer
|
* @details Interpretation varies by processing mode:
|
||||||
* - tile_x[1] = Tile width of the last tile in HW Seq DMA Transfer
|
* - Raster Mode: tile_x[0] = first tile width, tile_x[1] = last tile width
|
||||||
* In Vertical Mining Mode:
|
* - Vertical Mining Mode: tile_x[0] = first tile height, tile_x[1] = last tile height
|
||||||
* - tile_x[0] = Tile height of the first tile in HW Seq DMA Transfer
|
* Valid range for each element: [INT32_MIN .. INT32_MAX]
|
||||||
* - tile_x[1] = Tile height of the last tile in HW Seq DMA Transfer
|
|
||||||
*/
|
*/
|
||||||
int32_t tile_x[2];
|
int32_t tile_x[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tile co-ordinates
|
* @brief Tile Y-coordinates for first and last tiles
|
||||||
* In Raster Mode:
|
*
|
||||||
* - tile_y[0] = Tile height of the first tile in HW Seq DMA Transfer
|
* @details Interpretation varies by processing mode:
|
||||||
* - tile_y[1] = Tile height of the last tile in HW Seq DMA Transfer
|
* - Raster Mode: tile_y[0] = first tile height, tile_y[1] = last tile height
|
||||||
* In Vertical Mining Mode:
|
* - Vertical Mining Mode: tile_y[0] = first tile width, tile_y[1] = last tile width
|
||||||
* - tile_y[0] = Tile width of the first tile in HW Seq DMA Transfer
|
* Valid range for each element: [INT32_MIN .. INT32_MAX]
|
||||||
* - tile_y[1] = Tile width of the last tile in HW Seq DMA Transfer
|
|
||||||
*/
|
*/
|
||||||
int32_t tile_y[2];
|
int32_t tile_y[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tile co-ordinates
|
* @brief Tile Z-coordinate for Tensor Data Flow Mode
|
||||||
* In Tensor Data Flow Mode:
|
* Valid range: [INT32_MIN .. INT32_MAX]
|
||||||
*/
|
*/
|
||||||
int32_t tile_z;
|
int32_t tile_z;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Padding values
|
* @brief X-direction padding values
|
||||||
* In Raster Mode:
|
*
|
||||||
* - pad_x[0] = Left Padding
|
* @details Interpretation varies by processing mode:
|
||||||
* - pad_x[1] = Right Padding
|
* - Raster Mode: pad_x[0] = left padding, pad_x[1] = right padding
|
||||||
* In Vertical Mining Mode:
|
* - Vertical Mining Mode: pad_x[0] = top padding, pad_x[1] = bottom padding
|
||||||
* - pad_x[0] = Top Padding
|
* Valid range for each element: [0 .. INT32_MAX]
|
||||||
* - pad_x[1] = Bottom Padding
|
|
||||||
*/
|
*/
|
||||||
int32_t pad_x[2];
|
int32_t pad_x[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Padding values
|
* @brief Y-direction padding values
|
||||||
* In Raster Mode:
|
*
|
||||||
* - pad_y[0] = Top Padding
|
* @details Interpretation varies by processing mode:
|
||||||
* - pad_y[1] = Bottom Padding
|
* - Raster Mode: pad_y[0] = top padding, pad_y[1] = bottom padding
|
||||||
* In Vertical Mining Mode:
|
* - Vertical Mining Mode: pad_y[0] = left padding, pad_y[1] = right padding
|
||||||
* - pad_y[0] = Left Padding
|
* Valid range for each element: [0 .. INT32_MAX]
|
||||||
* - pad_y[1] = Right Padding
|
|
||||||
*/
|
*/
|
||||||
int32_t pad_y[2];
|
int32_t pad_y[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tiles per packet. Grid size in X dimension
|
* @brief Grid size in X dimension (tiles per packet)
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t grid_size_x;
|
uint32_t grid_size_x;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repeat Count
|
* @brief Grid size in Y dimension (repeat count)
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t grid_size_y;
|
uint32_t grid_size_y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid Size in Z dimension for Tensor Data Flow
|
* @brief Grid size in Z dimension for Tensor Data Flow
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t grid_size_z;
|
uint32_t grid_size_z;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tile Offset as specified in the HW Sequencer Header
|
* @brief Tile offset as specified in hardware sequencer header
|
||||||
|
* Valid range: [INT32_MIN .. INT32_MAX]
|
||||||
*/
|
*/
|
||||||
int32_t grid_step_x;
|
int32_t grid_step_x;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Col/Row Offset as specified in the HW Sequencer Col/Row Header
|
* @brief Column/row offset as specified in hardware sequencer header
|
||||||
|
* Valid range: [INT32_MIN .. INT32_MAX]
|
||||||
*/
|
*/
|
||||||
int32_t grid_step_y;
|
int32_t grid_step_y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repetition factor for Head Descriptor in HW Sequencer Blob
|
* @brief Repetition factor for head descriptor in hardware sequencer
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t head_tile_count;
|
uint32_t head_tile_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean value to indicate if HW Sequencer has split padding
|
* @brief Flag indicating if hardware sequencer has split padding
|
||||||
|
* Valid values: true (has split padding), false (no split padding)
|
||||||
*/
|
*/
|
||||||
bool is_split_padding;
|
bool is_split_padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct representing a valid Frame Information
|
* @brief Hardware sequencer frame information structure
|
||||||
|
*
|
||||||
|
* @details This structure represents the valid frame information including
|
||||||
|
* start and end coordinates in three-dimensional space. It defines the
|
||||||
|
* bounding box of the frame being processed by the hardware sequencer,
|
||||||
|
* enabling proper frame boundary validation and processing.
|
||||||
*/
|
*/
|
||||||
struct pva_hwseq_frame_info {
|
struct pva_hwseq_frame_info {
|
||||||
/**
|
/**
|
||||||
* X co-ordinate of start of Frame
|
* @brief X-coordinate of frame start
|
||||||
|
* Valid range: [INT64_MIN .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t start_x;
|
int64_t start_x;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Y co-ordinate of start of Frame
|
* @brief Y-coordinate of frame start
|
||||||
|
* Valid range: [INT64_MIN .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t start_y;
|
int64_t start_y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Z co-ordinates of starte of Frame
|
* @brief Z-coordinate of frame start
|
||||||
|
* Valid range: [INT64_MIN .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t start_z;
|
int64_t start_z;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* X co-ordinate of end of Frame
|
* @brief X-coordinate of frame end
|
||||||
|
* Valid range: [start_x .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t end_x;
|
int64_t end_x;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Y co-ordinate of end of Frame
|
* @brief Y-coordinate of frame end
|
||||||
|
* Valid range: [start_y .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t end_y;
|
int64_t end_y;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Z co-ordinate of end of Frame
|
* @brief Z-coordinate of frame end
|
||||||
|
* Valid range: [start_z .. INT64_MAX]
|
||||||
*/
|
*/
|
||||||
int64_t end_z;
|
int64_t end_z;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct which holds the HW Sequencer Buffer as received from User Space
|
* @brief Hardware sequencer buffer structure
|
||||||
|
*
|
||||||
|
* @details This structure holds the hardware sequencer buffer data
|
||||||
|
* as received from user space. It provides access to the raw sequencer
|
||||||
|
* blob data and tracks the remaining bytes to be processed during
|
||||||
|
* hardware sequencer parsing and validation operations.
|
||||||
*/
|
*/
|
||||||
struct pva_hwseq_buffer {
|
struct pva_hwseq_buffer {
|
||||||
/**
|
/**
|
||||||
* Pointer to HW Sequencer Blob in Buffer
|
* @brief Pointer to hardware sequencer blob data
|
||||||
|
* Valid value: non-null if bytes_left > 0
|
||||||
*/
|
*/
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of bytes left to be read from the data buffer
|
* @brief Number of bytes remaining in the buffer
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t bytes_left;
|
uint32_t bytes_left;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct hw_seq_blob_entry
|
* @brief Hardware sequence blob entry information structure
|
||||||
* @brief Structure to hold information about a hardware sequence blob entry.
|
|
||||||
*
|
*
|
||||||
* This structure is used to store the details of a DMA channel and the range of hardware sequencer
|
* @details This structure stores information about a hardware sequence blob entry,
|
||||||
* associated with it, along with the number of frames involved.
|
* including the associated DMA channel, hardware sequencer range, and frame count.
|
||||||
|
* It provides the necessary context for processing hardware sequencer operations
|
||||||
|
* within a specific DMA channel configuration.
|
||||||
*/
|
*/
|
||||||
struct hw_seq_blob_entry {
|
struct hw_seq_blob_entry {
|
||||||
/**
|
/**
|
||||||
* Pointer to a const \ref pva_dma_channel which holds the current DMA Channel Information
|
* @brief Pointer to DMA channel containing this hardware sequencer blob
|
||||||
* in which current HW Sequencer Blob is present
|
|
||||||
*/
|
*/
|
||||||
struct pva_dma_channel const *ch;
|
struct pva_dma_channel const *ch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The starting index of the hardware sequencer.
|
* @brief Starting index of the hardware sequencer range
|
||||||
|
* Valid range: [0 .. UINT16_MAX]
|
||||||
*/
|
*/
|
||||||
uint16_t hwseq_start;
|
uint16_t hwseq_start;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ending index of the hardware sequencer.
|
* @brief Ending index of the hardware sequencer range
|
||||||
|
* Valid range: [hwseq_start .. UINT16_MAX]
|
||||||
*/
|
*/
|
||||||
uint16_t hwseq_end;
|
uint16_t hwseq_end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of frames associated with the hardware sequencer.
|
* @brief Number of frames associated with the hardware sequencer
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t num_frames;
|
uint32_t num_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Separate out pva_hwseq_priv to be more modular
|
* @brief Hardware sequencer private data structure
|
||||||
*
|
*
|
||||||
* Items in pva_hwseq_main
|
* @details This structure holds comprehensive private data for hardware sequencer
|
||||||
* - dma_config
|
* blob parsing and validation. It contains descriptor counts, tile information,
|
||||||
* - hw_gen
|
* blob entry details, parsing state, mode flags, and references to related
|
||||||
* - blob
|
* DMA configuration data. This structure enables thorough validation and
|
||||||
* - num_hwseq_words
|
* processing of hardware sequencer operations while maintaining proper
|
||||||
* Items per segment of main i.e. pva_hwseq_segment
|
* abstraction from hardware-specific implementation details.
|
||||||
* - hwseq_start, hwseq_end
|
|
||||||
* - channel id
|
|
||||||
* - hwseq_header,
|
|
||||||
* - desc_count
|
|
||||||
* - num_frames
|
|
||||||
* - head_desc, tail_desc
|
|
||||||
* - is_split_padding
|
|
||||||
* - is_raster_scan
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A struct holding private data to HW Sequencer Blob being parsed
|
|
||||||
*/
|
*/
|
||||||
struct pva_hwseq_priv {
|
struct pva_hwseq_priv {
|
||||||
/**
|
/**
|
||||||
* Number of descriptors in the HW Sequencer Blob
|
* @brief Number of descriptors in the hardware sequencer blob
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t desc_count;
|
uint32_t desc_count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of tiles in the packet
|
* @brief Total number of tiles in the packet
|
||||||
* This is the sum total of descriptor repetition factors
|
*
|
||||||
* present in the HW Sequencer Blob
|
* @details Sum total of descriptor repetition factors present in the
|
||||||
|
* hardware sequencer blob, representing the total tile processing load.
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
*/
|
*/
|
||||||
uint32_t tiles_per_packet;
|
uint32_t tiles_per_packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum tile X coordinate
|
||||||
|
* Valid range: [INT32_MIN .. INT32_MAX]
|
||||||
|
*/
|
||||||
int32_t max_tx;
|
int32_t max_tx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum tile Y coordinate
|
||||||
|
* Valid range: [INT32_MIN .. INT32_MAX]
|
||||||
|
*/
|
||||||
int32_t max_ty;
|
int32_t max_ty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct that holds the entry info of HW Sequencer Blob
|
* @brief Hardware sequencer blob entry information
|
||||||
*/
|
*/
|
||||||
struct hw_seq_blob_entry entry;
|
struct hw_seq_blob_entry entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct that holds HW Sequencer Blob to be read
|
* @brief Hardware sequencer buffer for blob parsing
|
||||||
*/
|
*/
|
||||||
struct pva_hwseq_buffer blob;
|
struct pva_hwseq_buffer blob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean to indicate if split padding is present in the HW Sequener Blob
|
* @brief Flag indicating presence of split padding
|
||||||
|
* Valid values: true (split padding present), false (no split padding)
|
||||||
*/
|
*/
|
||||||
bool is_split_padding;
|
bool is_split_padding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bool to indicate if HW Sequencer uses raster scan or Vertical mining
|
* @brief Flag indicating scan mode type
|
||||||
* TRUE: Raster Scan
|
*
|
||||||
* FALSE: Vertical Mining
|
* @details Indicates hardware sequencer scan mode:
|
||||||
|
* - true: Raster scan mode
|
||||||
|
* - false: Vertical mining mode
|
||||||
*/
|
*/
|
||||||
bool is_raster_scan;
|
bool is_raster_scan;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Indicates the generation of PVA HW.
|
* @brief PVA hardware generation
|
||||||
* Allowed values: 0 (GEN 1), 1 (GEN 2), 2 (GEN 3)
|
*
|
||||||
|
* @details Hardware generation identifier for platform-specific
|
||||||
|
* behavior adaptation
|
||||||
|
* Valid values: @ref pva_hw_gen enumeration values
|
||||||
*/
|
*/
|
||||||
enum pva_hw_gen hw_gen;
|
enum pva_hw_gen hw_gen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pointer to the DMA configuration header.
|
* @brief Pointer to DMA configuration header
|
||||||
*/
|
*/
|
||||||
const struct pva_dma_config *dma_config;
|
const struct pva_dma_config *dma_config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to \ref pva_dma_hwseq_hdr_t which holds the HW Sequencer Header
|
* @brief Pointer to hardware sequencer header
|
||||||
*/
|
*/
|
||||||
const struct pva_dma_hwseq_hdr *hdr;
|
const struct pva_dma_hwseq_hdr *hdr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to \ref pva_dma_hwseq_colrow_hdr_t which holds the Header of the
|
* @brief Pointer to column/row header in hardware sequencer
|
||||||
* Col/Row inside HW Sequencer
|
|
||||||
*/
|
*/
|
||||||
const struct pva_dma_hwseq_colrow_hdr *colrow;
|
const struct pva_dma_hwseq_colrow_hdr *colrow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the Head Descriptor of type \ref nvpva_dma_descriptor in the HW Sequencer
|
* @brief Pointer to head descriptor in the hardware sequencer
|
||||||
*/
|
*/
|
||||||
const struct pva_dma_descriptor *head_desc;
|
const struct pva_dma_descriptor *head_desc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the Tail Descriptor of type \ref nvpva_dma_descriptor in the HW Sequencer
|
* @brief Pointer to tail descriptor in the hardware sequencer
|
||||||
*/
|
*/
|
||||||
const struct pva_dma_descriptor *tail_desc;
|
const struct pva_dma_descriptor *tail_desc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DMA Descriptor information obtained from HW Sequencer Blob of type
|
* @brief Array of DMA descriptor entries from hardware sequencer blob
|
||||||
* \ref pva_dma_hwseq_desc_entry_t
|
|
||||||
*/
|
*/
|
||||||
struct pva_dma_hwseq_desc_entry dma_descs[2];
|
struct pva_dma_hwseq_desc_entry dma_descs[2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access Sizes are calculated and stored here from HW Sequencer Blob
|
* @brief Pointer to calculated access sizes from hardware sequencer blob
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_dma_access *access_sizes;
|
struct pva_kmd_dma_access *access_sizes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Per-frame information for hardware sequencer processing
|
||||||
|
*
|
||||||
|
* @details This structure contains frame-specific information for hardware
|
||||||
|
* sequencer operations, including sequence tile counts and VMEM tile
|
||||||
|
* requirements per frame. It enables proper resource allocation and
|
||||||
|
* validation for frame-based processing operations.
|
||||||
|
*/
|
||||||
struct pva_hwseq_per_frame_info {
|
struct pva_hwseq_per_frame_info {
|
||||||
|
/**
|
||||||
|
* @brief Number of tiles in the sequence for this frame
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t seq_tile_count;
|
uint32_t seq_tile_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of VMEM tiles required per frame
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t vmem_tiles_per_frame;
|
uint32_t vmem_tiles_per_frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate hardware sequencer configuration
|
||||||
|
*
|
||||||
|
* @details This function performs comprehensive validation of hardware sequencer
|
||||||
|
* configurations including:
|
||||||
|
* - Parsing and validating hardware sequencer blob structure
|
||||||
|
* - Checking descriptor references and repetition factors
|
||||||
|
* - Validating frame boundaries and addressing modes
|
||||||
|
* - Computing memory access patterns and requirements
|
||||||
|
* - Ensuring hardware constraints are satisfied
|
||||||
|
* - Building descriptor usage masks for resource tracking
|
||||||
|
* - Verifying grid parameters and tile arrangements
|
||||||
|
*
|
||||||
|
* The validation ensures that the hardware sequencer configuration is
|
||||||
|
* safe for execution and will not violate hardware constraints or
|
||||||
|
* memory protection boundaries. The function provides platform-agnostic
|
||||||
|
* validation that can be adapted to different hardware implementations.
|
||||||
|
*
|
||||||
|
* @param[in] dma_config Pointer to DMA configuration containing hardware sequencer
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] hw_consts Pointer to hardware constants for validation
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] access_sizes Array to store computed access size information
|
||||||
|
* Valid value: non-null, min size PVA_MAX_NUM_DMA_DESC
|
||||||
|
* @param[out] hw_dma_descs_mask Bitmask for tracking hardware descriptor usage
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Hardware sequencer blob validated successfully
|
||||||
|
* @retval PVA_ERR_HWSEQ_INVALID Invalid hardware sequencer configuration
|
||||||
|
* @retval PVA_ERANGE Hardware sequencer configuration exceeds bounds or limits
|
||||||
|
* @retval PVA_INVAL Invalid descriptor reference in hardware sequencer
|
||||||
|
* @retval PVA_BAD_PARAMETER_ERROR Invalid grid parameters in hardware sequencer
|
||||||
|
* @retval PVA_INVALID_RESOURCE Invalid input parameters
|
||||||
|
*/
|
||||||
enum pva_error validate_hwseq(struct pva_dma_config const *dma_config,
|
enum pva_error validate_hwseq(struct pva_dma_config const *dma_config,
|
||||||
struct pva_kmd_hw_constants const *hw_consts,
|
struct pva_kmd_hw_constants const *hw_consts,
|
||||||
struct pva_kmd_dma_access *access_sizes,
|
struct pva_kmd_dma_access *access_sizes,
|
||||||
|
|||||||
70
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_limits.h
Normal file
70
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_limits.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
/**
|
||||||
|
* @file pva_kmd_limits.h
|
||||||
|
* @brief Platform-independent type limit definitions
|
||||||
|
*
|
||||||
|
* @details This header provides portable definitions for integer type limits
|
||||||
|
* that work across different platforms (Linux kernel, QNX, Native x86, Simulation).
|
||||||
|
*
|
||||||
|
* Linux kernel does not have <stdint.h> but provides its own limit macros.
|
||||||
|
* Other platforms (QNX, Native, SIM) use standard <stdint.h> definitions.
|
||||||
|
*
|
||||||
|
* This header abstracts these platform differences, allowing common code to use
|
||||||
|
* consistent macro names across all platforms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PVA_KMD_LIMITS_H
|
||||||
|
#define PVA_KMD_LIMITS_H
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
/* Linux kernel build - use kernel-provided limit macros */
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
/*
|
||||||
|
* Linux kernel provides:
|
||||||
|
* U8_MAX, U16_MAX, U32_MAX, U64_MAX for unsigned types
|
||||||
|
* S8_MAX, S8_MIN, S16_MAX, S16_MIN, S32_MAX, S32_MIN, S64_MAX, S64_MIN for signed types
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
/* QNX/Native/SIM builds - use standard C definitions */
|
||||||
|
#include <stdint.h>
|
||||||
|
/* Map standard C names to kernel-style names for consistency */
|
||||||
|
#ifndef U8_MAX
|
||||||
|
#define U8_MAX UINT8_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef U16_MAX
|
||||||
|
#define U16_MAX UINT16_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef U32_MAX
|
||||||
|
#define U32_MAX UINT32_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef U64_MAX
|
||||||
|
#define U64_MAX UINT64_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef S8_MAX
|
||||||
|
#define S8_MAX INT8_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef S8_MIN
|
||||||
|
#define S8_MIN INT8_MIN
|
||||||
|
#endif
|
||||||
|
#ifndef S16_MAX
|
||||||
|
#define S16_MAX INT16_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef S16_MIN
|
||||||
|
#define S16_MIN INT16_MIN
|
||||||
|
#endif
|
||||||
|
#ifndef S32_MAX
|
||||||
|
#define S32_MAX INT32_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef S32_MIN
|
||||||
|
#define S32_MIN INT32_MIN
|
||||||
|
#endif
|
||||||
|
#ifndef S64_MAX
|
||||||
|
#define S64_MAX INT64_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef S64_MIN
|
||||||
|
#define S64_MIN INT64_MIN
|
||||||
|
#endif
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
#endif /* PVA_KMD_LIMITS_H */
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
#include "pva_kmd_msg.h"
|
#include "pva_kmd_msg.h"
|
||||||
|
#include "pva_api_types.h"
|
||||||
#include "pva_fw.h"
|
#include "pva_fw.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_kmd_thread_sema.h"
|
#include "pva_kmd_thread_sema.h"
|
||||||
@@ -11,8 +12,8 @@
|
|||||||
|
|
||||||
static uint8_t get_msg_type(uint32_t hdr)
|
static uint8_t get_msg_type(uint32_t hdr)
|
||||||
{
|
{
|
||||||
return PVA_EXTRACT(hdr, PVA_FW_MSG_TYPE_MSB, PVA_FW_MSG_TYPE_LSB,
|
return (uint8_t)PVA_EXTRACT(hdr, PVA_FW_MSG_TYPE_MSB,
|
||||||
uint32_t);
|
PVA_FW_MSG_TYPE_LSB, uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len)
|
void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len)
|
||||||
@@ -31,10 +32,10 @@ void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len)
|
|||||||
pack64(data[PVA_FW_MSG_R5_READY_TIME_HI_IDX],
|
pack64(data[PVA_FW_MSG_R5_READY_TIME_HI_IDX],
|
||||||
data[PVA_FW_MSG_R5_READY_TIME_LO_IDX]);
|
data[PVA_FW_MSG_R5_READY_TIME_LO_IDX]);
|
||||||
|
|
||||||
pva_kmd_log_err("Firmware boot completes");
|
pva_kmd_log_info("Firmware boot completes");
|
||||||
pva_kmd_log_err_u64("R5 start time (us)",
|
pva_kmd_log_info_u64("R5 start time (us)",
|
||||||
pva_kmd_tsc_to_us(pva, r5_start_time));
|
pva_kmd_tsc_to_us(pva, r5_start_time));
|
||||||
pva_kmd_log_err_u64("R5 ready time (us)",
|
pva_kmd_log_info_u64("R5 ready time (us)",
|
||||||
pva_kmd_tsc_to_us(pva, r5_ready_time));
|
pva_kmd_tsc_to_us(pva, r5_ready_time));
|
||||||
|
|
||||||
pva_kmd_sema_post(&pva->fw_boot_sema);
|
pva_kmd_sema_post(&pva->fw_boot_sema);
|
||||||
@@ -42,21 +43,31 @@ void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len)
|
|||||||
case PVA_FW_MSG_TYPE_ABORT: {
|
case PVA_FW_MSG_TYPE_ABORT: {
|
||||||
char abort_msg[PVA_FW_MSG_ABORT_STR_MAX_LEN + 1];
|
char abort_msg[PVA_FW_MSG_ABORT_STR_MAX_LEN + 1];
|
||||||
|
|
||||||
pva_kmd_drain_fw_print(&pva->fw_print_buffer);
|
pva_kmd_drain_fw_print(pva);
|
||||||
|
|
||||||
pva_kmd_log_err("Firmware aborted! The abort message is: ");
|
pva_kmd_log_err("Firmware aborted! The abort message is: ");
|
||||||
abort_msg[0] = PVA_EXTRACT(data[0], 7, 0, uint32_t);
|
/* CERT INT31-C: PVA_EXTRACT returns 8-bit value, safe to cast to char */
|
||||||
abort_msg[1] = PVA_EXTRACT(data[0], 15, 8, uint32_t);
|
abort_msg[0] = (char)PVA_EXTRACT(data[0], 7, 0, uint32_t);
|
||||||
memcpy(abort_msg + 2, &data[1], size);
|
abort_msg[1] = (char)PVA_EXTRACT(data[0], 15, 8, uint32_t);
|
||||||
|
(void)memcpy((void *)(abort_msg + 2), (const void *)&data[1],
|
||||||
|
(size_t)size);
|
||||||
abort_msg[PVA_FW_MSG_ABORT_STR_MAX_LEN] = '\0';
|
abort_msg[PVA_FW_MSG_ABORT_STR_MAX_LEN] = '\0';
|
||||||
pva_kmd_log_err(abort_msg);
|
pva_kmd_log_err(abort_msg);
|
||||||
pva_kmd_abort_fw(pva, PVA_ERR_FW_ABORTED);
|
pva_kmd_abort_fw(pva, PVA_ERR_FW_ABORTED);
|
||||||
} break;
|
} break;
|
||||||
case PVA_FW_MSG_TYPE_FLUSH_PRINT:
|
case PVA_FW_MSG_TYPE_FLUSH_PRINT:
|
||||||
pva_kmd_drain_fw_print(&pva->fw_print_buffer);
|
pva_kmd_drain_fw_print(pva);
|
||||||
|
break;
|
||||||
|
case PVA_FW_MSG_TYPE_FAST_RESET_FAILURE:
|
||||||
|
pva_kmd_log_err("Fast reset failure");
|
||||||
|
pva_kmd_report_error_fsi(pva,
|
||||||
|
(uint32_t)PVA_ERR_FAST_RESET_FAILURE);
|
||||||
|
pva->recovery = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FAULT("Unknown message type from firmware");
|
FAULT("Unknown message type from firmware");
|
||||||
|
/* MISRA Rule 16.3 requires break; Rule 2.1: break is unreachable but required by MISRA 16.3 */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,51 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Handle messages from FW to hypervisor.
|
* @brief Handle messages from FW to hypervisor.
|
||||||
*
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Receives message data from firmware intended for hypervisor processing
|
||||||
|
* - Validates the message format and length for correctness
|
||||||
|
* - Routes the message to appropriate hypervisor handling mechanisms
|
||||||
|
* - Processes mailbox-based communication from firmware
|
||||||
|
* - Handles future hypervisor support infrastructure
|
||||||
|
* - Ensures proper message acknowledgment back to firmware
|
||||||
|
*
|
||||||
* This is just a provision for future hypervisor support. For now, this just
|
* This is just a provision for future hypervisor support. For now, this just
|
||||||
* handles all messages from mailboxes.
|
* handles all messages from mailboxes. The function provides a foundation
|
||||||
|
* for hypervisor communication that can be extended when full hypervisor
|
||||||
|
* support is implemented in the system.
|
||||||
|
*
|
||||||
|
* @param[in] pva_dev Pointer to PVA device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] data Pointer to message data array received from firmware
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] len Length of the message data in 32-bit words
|
||||||
|
* Valid range: [1 .. 255]
|
||||||
*/
|
*/
|
||||||
void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len);
|
void pva_kmd_handle_hyp_msg(void *pva_dev, uint32_t const *data, uint8_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle messages from FW to KMD.
|
* @brief Handle messages from FW to KMD.
|
||||||
*
|
*
|
||||||
* These messages come from CCQ0 statues registers.
|
* @details This function performs the following operations:
|
||||||
|
* - Receives message data from firmware via CCQ0 status registers
|
||||||
|
* - Parses the message header to determine message type and routing
|
||||||
|
* - Dispatches messages to appropriate KMD subsystem handlers
|
||||||
|
* - Processes firmware status updates, error notifications, and responses
|
||||||
|
* - Handles resource management messages and completion notifications
|
||||||
|
* - Updates internal KMD state based on firmware messages
|
||||||
|
* - Manages communication flow control with firmware
|
||||||
|
*
|
||||||
|
* These messages come from CCQ0 status registers and represent the primary
|
||||||
|
* communication channel between firmware and KMD for system-level operations.
|
||||||
|
* The function ensures proper message processing and maintains synchronization
|
||||||
|
* between firmware and KMD state.
|
||||||
|
*
|
||||||
|
* @param[in] pva_dev Pointer to PVA device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] data Pointer to message data array received from firmware
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] len Length of the message data in 32-bit words
|
||||||
|
* Valid range: [1 .. 255]
|
||||||
*/
|
*/
|
||||||
void pva_kmd_handle_msg(void *pva_dev, uint32_t const *data, uint8_t len);
|
void pva_kmd_handle_msg(void *pva_dev, uint32_t const *data, uint8_t len);
|
||||||
#endif // PVA_KMD_MSG_H
|
#endif // PVA_KMD_MSG_H
|
||||||
|
|||||||
@@ -9,19 +9,113 @@
|
|||||||
#if defined(__KERNEL__) /* For Linux */
|
#if defined(__KERNEL__) /* For Linux */
|
||||||
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
/**
|
||||||
|
* @brief Mutex type alias for Linux kernel space
|
||||||
|
*
|
||||||
|
* @details Platform-specific mutex implementation that maps to the Linux
|
||||||
|
* kernel mutex structure. This provides cross-platform abstraction for
|
||||||
|
* mutex operations in the PVA KMD, allowing the same code to work across
|
||||||
|
* different operating system environments.
|
||||||
|
*/
|
||||||
typedef struct mutex pva_kmd_mutex_t;
|
typedef struct mutex pva_kmd_mutex_t;
|
||||||
|
|
||||||
#else /* For user space code, including QNX KMD */
|
#else /* For user space code, including QNX KMD */
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
/* Mutex */
|
/**
|
||||||
|
* @brief Mutex type alias for user space (QNX and other platforms)
|
||||||
|
*
|
||||||
|
* @details Platform-specific mutex implementation that maps to POSIX
|
||||||
|
* pthread mutex for user space environments including QNX KMD. This
|
||||||
|
* provides cross-platform abstraction for mutex operations, enabling
|
||||||
|
* consistent synchronization primitives across different platforms.
|
||||||
|
*/
|
||||||
typedef pthread_mutex_t pva_kmd_mutex_t;
|
typedef pthread_mutex_t pva_kmd_mutex_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a PVA KMD mutex
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the platform-specific mutex structure
|
||||||
|
* - Sets up appropriate mutex attributes for the target platform
|
||||||
|
* - Configures the mutex for proper operation in kernel or user space
|
||||||
|
* - Ensures the mutex is ready for lock/unlock operations
|
||||||
|
* - Handles platform-specific initialization requirements
|
||||||
|
*
|
||||||
|
* The mutex must be initialized before it can be used for synchronization.
|
||||||
|
* After successful initialization, the mutex can be used with
|
||||||
|
* @ref pva_kmd_mutex_lock() and @ref pva_kmd_mutex_unlock(). The mutex
|
||||||
|
* should be deinitialized using @ref pva_kmd_mutex_deinit() when no
|
||||||
|
* longer needed.
|
||||||
|
*
|
||||||
|
* @param[in, out] m Pointer to @ref pva_kmd_mutex_t structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Mutex initialized successfully
|
||||||
|
* @retval PVA_INTERNAL Platform-specific mutex initialization failed
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_mutex_init(pva_kmd_mutex_t *m);
|
enum pva_error pva_kmd_mutex_init(pva_kmd_mutex_t *m);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire a lock on the PVA KMD mutex
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Attempts to acquire an exclusive lock on the specified mutex
|
||||||
|
* - Blocks the calling thread if the mutex is already locked by another thread
|
||||||
|
* - Provides mutual exclusion for critical sections of code
|
||||||
|
* - Uses platform-appropriate locking mechanisms (kernel or user space)
|
||||||
|
* - Ensures atomic access to shared resources protected by the mutex
|
||||||
|
*
|
||||||
|
* The calling thread will block until the mutex becomes available. Once
|
||||||
|
* acquired, the thread has exclusive access to resources protected by this
|
||||||
|
* mutex until @ref pva_kmd_mutex_unlock() is called. The mutex must be
|
||||||
|
* initialized using @ref pva_kmd_mutex_init() before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in, out] m Pointer to @ref pva_kmd_mutex_t structure to lock
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_mutex_lock(pva_kmd_mutex_t *m);
|
void pva_kmd_mutex_lock(pva_kmd_mutex_t *m);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release a lock on the PVA KMD mutex
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Releases the exclusive lock on the specified mutex
|
||||||
|
* - Allows other waiting threads to acquire the mutex
|
||||||
|
* - Signals completion of the critical section protected by the mutex
|
||||||
|
* - Uses platform-appropriate unlocking mechanisms
|
||||||
|
* - Maintains proper synchronization state for subsequent operations
|
||||||
|
*
|
||||||
|
* This function must only be called by the thread that currently holds
|
||||||
|
* the mutex lock. After unlocking, other threads waiting on the mutex
|
||||||
|
* may acquire the lock. The mutex must have been previously locked using
|
||||||
|
* @ref pva_kmd_mutex_lock() before calling this function.
|
||||||
|
*
|
||||||
|
* @param[in, out] m Pointer to @ref pva_kmd_mutex_t structure to unlock
|
||||||
|
* Valid value: non-null, must be currently locked by calling thread
|
||||||
|
*/
|
||||||
void pva_kmd_mutex_unlock(pva_kmd_mutex_t *m);
|
void pva_kmd_mutex_unlock(pva_kmd_mutex_t *m);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a PVA KMD mutex and free resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Deinitializes the platform-specific mutex structure
|
||||||
|
* - Frees any resources allocated during mutex initialization
|
||||||
|
* - Ensures proper cleanup of platform-specific mutex state
|
||||||
|
* - Marks the mutex as invalid for future use
|
||||||
|
* - Handles platform-specific deinitialization requirements
|
||||||
|
*
|
||||||
|
* The mutex must not be locked when this function is called, and no
|
||||||
|
* threads should be waiting on the mutex. After deinitialization, the
|
||||||
|
* mutex cannot be used for synchronization until it is reinitialized
|
||||||
|
* using @ref pva_kmd_mutex_init().
|
||||||
|
*
|
||||||
|
* @param[in, out] m Pointer to @ref pva_kmd_mutex_t structure to deinitialize
|
||||||
|
* Valid value: non-null, must be initialized and unlocked
|
||||||
|
*/
|
||||||
void pva_kmd_mutex_deinit(pva_kmd_mutex_t *m);
|
void pva_kmd_mutex_deinit(pva_kmd_mutex_t *m);
|
||||||
|
|
||||||
#endif // PVA_KMD_MUTEX_H
|
#endif // PVA_KMD_MUTEX_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,32 +8,65 @@
|
|||||||
#include "pva_fw.h"
|
#include "pva_fw.h"
|
||||||
#include "pva_kmd.h"
|
#include "pva_kmd.h"
|
||||||
|
|
||||||
/** @brief Handler for PVA KMD operations.
|
/**
|
||||||
*
|
* @brief Handler for PVA KMD operations.
|
||||||
* This function implements the only runtime interface with UMD. Shim layers
|
*
|
||||||
* receive the input data from UMD and call this function to execute the
|
* @details This function performs the following operations:
|
||||||
* operations. Then, shim layers send the response back to UMD.
|
* - Receives operation requests from UMD through platform-specific shim layers
|
||||||
*
|
* - Validates the operation buffer format and size for correctness
|
||||||
* @param ctx The KMD context.
|
* - Parses the operations buffer to extract individual operation commands
|
||||||
* @param ops Pointer to the input buffer containing the operations to be
|
* - Executes the requested operations using the provided KMD context
|
||||||
* executed. The common layer assumes that this buffer is private to
|
* - Manages submission mode (synchronous or asynchronous) based on parameters
|
||||||
* KMD and will dereference it directly without making a copy.
|
* - Handles postfence configuration for operation completion signaling
|
||||||
* Specifically on Linux, this parameter should point to a private
|
* - Generates appropriate response data for successful operations
|
||||||
* kernel space buffer instead of the user space buffer.
|
* - Handles error conditions and generates error responses
|
||||||
* @param ops_size Size of the input buffer.
|
* - Ensures proper resource cleanup in case of operation failures
|
||||||
* @param response Pointer to the buffer where the response will be written.
|
* - Maintains operation isolation and security within the context
|
||||||
* @param response_buffer_size Size of the response buffer.
|
*
|
||||||
* @param out_response_size Pointer to a variable where the actual size of the
|
* This function implements the only runtime interface with UMD. Shim layers
|
||||||
* response will be written.
|
* receive the input data from UMD and call this function to execute the
|
||||||
*
|
* operations. Then, shim layers send the response back to UMD. The function
|
||||||
* @return pva_error indicating the success or failure of the operation.
|
* assumes that the operations buffer is private to KMD and will dereference
|
||||||
*
|
* it directly without making a copy. On Linux platforms, the operations
|
||||||
* @Note that the input buffer and output buffer should never alias.
|
* buffer should point to a private kernel space buffer rather than user
|
||||||
*/
|
* space to ensure memory safety and security.
|
||||||
enum pva_error
|
*
|
||||||
pva_kmd_ops_handler(struct pva_kmd_context *ctx, enum pva_ops_submit_mode mode,
|
* @param[in] ctx Pointer to @ref pva_kmd_context structure
|
||||||
struct pva_fw_postfence *postfence, void const *ops_buffer,
|
* Valid value: non-null, must be initialized
|
||||||
uint32_t ops_size, void *response,
|
* @param[in] mode Submission mode for operation execution
|
||||||
uint32_t response_buffer_size, uint32_t *out_response_size);
|
* Valid values: @ref pva_ops_submit_mode enumeration values
|
||||||
|
* @param[in, out] postfence Pointer to @ref pva_fw_postfence structure for
|
||||||
|
* completion signaling
|
||||||
|
* Valid value: can be null if no postfence required
|
||||||
|
* @param[in] ops_buffer Pointer to operations buffer containing commands to execute
|
||||||
|
* Valid value: non-null, must point to KMD-private buffer
|
||||||
|
* @param[in] ops_size Size of the operations buffer in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[out] response Pointer to buffer where response will be written
|
||||||
|
* Valid value: non-null, must not alias ops_buffer
|
||||||
|
* @param[in] response_buffer_size Size of the response buffer in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[out] out_response_size Pointer to variable for actual response size
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] priv Flag indicating privileged operation mode
|
||||||
|
* Valid values: true for privileged operations, false otherwise
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Operations executed successfully
|
||||||
|
* @retval PVA_INVAL Invalid parameter values or buffer pointers
|
||||||
|
* @retval PVA_ENOSPC Response buffer too small for result data
|
||||||
|
* @retval PVA_NOT_IMPL Invalid or unsupported operation in buffer
|
||||||
|
* @retval PVA_INTERNAL Context not properly initialized
|
||||||
|
* @retval PVA_TIMEDOUT Communication with firmware failed
|
||||||
|
* @retval PVA_AGAIN Required resources are not available
|
||||||
|
*
|
||||||
|
* @note The input buffer and output buffer should never alias.
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_ops_handler(struct pva_kmd_context *ctx,
|
||||||
|
enum pva_ops_submit_mode mode,
|
||||||
|
struct pva_fw_postfence *postfence,
|
||||||
|
void const *ops_buffer, uint32_t ops_size,
|
||||||
|
void *response,
|
||||||
|
uint32_t response_buffer_size,
|
||||||
|
uint32_t *out_response_size, bool priv);
|
||||||
|
|
||||||
#endif // PVA_KMD_OP_HANDLER_H
|
#endif // PVA_KMD_OP_HANDLER_H
|
||||||
|
|||||||
875
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd.c
Normal file
875
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd.c
Normal file
@@ -0,0 +1,875 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_kmd_pfsd.h"
|
||||||
|
#include "pva_kmd_op_handler.h"
|
||||||
|
#include "pva_kmd_device_memory.h"
|
||||||
|
#include "pva_kmd_device.h"
|
||||||
|
#include "pva_kmd_utils.h"
|
||||||
|
#include "pva_kmd_context.h"
|
||||||
|
#include "pva_kmd_cmdbuf.h"
|
||||||
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_utils.h"
|
||||||
|
#include "pva_kmd.h"
|
||||||
|
#include "pva_api_types.h"
|
||||||
|
#include "pva_api_ops.h"
|
||||||
|
#include "pva_kmd_submitter.h"
|
||||||
|
#include "pva_kmd_resource_table.h"
|
||||||
|
|
||||||
|
// Helper structure to pass multiple source buffers
|
||||||
|
struct pva_buffer_source {
|
||||||
|
const void *data_ptr;
|
||||||
|
uint64_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to register a buffer from multiple sources
|
||||||
|
static enum pva_error pva_kmd_pfsd_register_buffer(
|
||||||
|
struct pva_kmd_context *ctx, const struct pva_buffer_source *sources,
|
||||||
|
uint32_t num_sources, enum pva_memory_segment segment,
|
||||||
|
uint32_t *resource_id_out)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_kmd_device_memory *mem = NULL;
|
||||||
|
struct pva_cmd_update_resource_table update_cmd = { 0 };
|
||||||
|
struct pva_resource_entry entry = { 0 };
|
||||||
|
uint32_t resource_id = 0;
|
||||||
|
uint8_t smmu_ctx_id;
|
||||||
|
struct pva_kmd_submitter *dev_submitter;
|
||||||
|
uint64_t total_size = 0;
|
||||||
|
uint64_t offset = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_sources; i++) {
|
||||||
|
total_size = safe_addu64(total_size, sources[i].size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segment == PVA_MEMORY_SEGMENT_R5) {
|
||||||
|
smmu_ctx_id = PVA_R5_SMMU_CONTEXT_ID;
|
||||||
|
} else {
|
||||||
|
smmu_ctx_id = ctx->smmu_ctx_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem = pva_kmd_device_memory_alloc_map(total_size, ctx->pva,
|
||||||
|
PVA_ACCESS_RO, smmu_ctx_id);
|
||||||
|
if (mem == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to allocate and map device memory for buffer");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_sources; i++) {
|
||||||
|
(void)memcpy((void *)((uint8_t *)mem->va + offset),
|
||||||
|
(const void *)sources[i].data_ptr,
|
||||||
|
sources[i].size);
|
||||||
|
offset = safe_addu64(offset, sources[i].size);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_add_dram_buffer_resource(&ctx->ctx_resource_table, mem,
|
||||||
|
&resource_id, true);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to add buffer to resource table");
|
||||||
|
goto free_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_make_resource_entry(&ctx->ctx_resource_table, resource_id,
|
||||||
|
&entry);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to make resource entry");
|
||||||
|
goto free_dram_buffer_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
pva_kmd_set_cmd_update_resource_table(
|
||||||
|
&update_cmd, ctx->resource_table_id, resource_id, &entry, NULL);
|
||||||
|
|
||||||
|
dev_submitter = &ctx->pva->submitter;
|
||||||
|
err = pva_kmd_submit_cmd_sync(dev_submitter, &update_cmd,
|
||||||
|
(uint32_t)sizeof(update_cmd),
|
||||||
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("PFSD buffer memory registration to FW failed");
|
||||||
|
goto free_dram_buffer_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
*resource_id_out = resource_id;
|
||||||
|
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
|
||||||
|
free_dram_buffer_resource:
|
||||||
|
pva_kmd_drop_resource(&ctx->ctx_resource_table, resource_id);
|
||||||
|
free_memory:
|
||||||
|
pva_kmd_device_memory_free(mem);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_pfsd_register_input_buffers(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_buffer_source sources[4];
|
||||||
|
|
||||||
|
// Register in1 buffer
|
||||||
|
sources[0].data_ptr = in1;
|
||||||
|
sources[0].size = sizeof(in1);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 1, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.in1_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register in2 buffer
|
||||||
|
sources[0].data_ptr = in2;
|
||||||
|
sources[0].size = sizeof(in2);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 1, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.in2_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register in3 buffer
|
||||||
|
sources[0].data_ptr = in3;
|
||||||
|
sources[0].size = sizeof(in3);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 1, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.in3_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register hist_a buffer (hist_short_a followed by hist_int_a)
|
||||||
|
sources[0].data_ptr = hist_short_a;
|
||||||
|
sources[0].size = sizeof(hist_short_a);
|
||||||
|
sources[1].data_ptr = hist_int_a;
|
||||||
|
sources[1].size = sizeof(hist_int_a);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 2, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.hist_a_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register hist_b buffer (hist_short_b followed by hist_int_b)
|
||||||
|
sources[0].data_ptr = hist_short_b;
|
||||||
|
sources[0].size = sizeof(hist_short_b);
|
||||||
|
sources[1].data_ptr = hist_int_b;
|
||||||
|
sources[1].size = sizeof(hist_int_b);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 2, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.hist_b_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register hist_c buffer (hist_short_c followed by hist_int_c)
|
||||||
|
sources[0].data_ptr = hist_short_c;
|
||||||
|
sources[0].size = sizeof(hist_short_c);
|
||||||
|
sources[1].data_ptr = hist_int_c;
|
||||||
|
sources[1].size = sizeof(hist_int_c);
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 2, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.hist_c_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register dlut_tbl_buf (all 4 DLUT tables combined)
|
||||||
|
sources[0].data_ptr = pva_pfsd_data_dlut_tbl0;
|
||||||
|
sources[0].size = PVA_PFSD_DLUT_TBL0_SIZE;
|
||||||
|
sources[1].data_ptr = pva_pfsd_data_dlut_tbl1;
|
||||||
|
sources[1].size = PVA_PFSD_DLUT_TBL1_SIZE;
|
||||||
|
sources[2].data_ptr = pva_pfsd_data_dlut_tbl2;
|
||||||
|
sources[2].size = PVA_PFSD_DLUT_TBL2_SIZE;
|
||||||
|
sources[3].data_ptr = pva_pfsd_data_dlut_tbl3;
|
||||||
|
sources[3].size = PVA_PFSD_DLUT_TBL3_SIZE;
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 4, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.dlut_tbl_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register dlut_indices_buf (all 4 DLUT indices combined)
|
||||||
|
sources[0].data_ptr = pva_pfsd_data_dlut_indices0;
|
||||||
|
sources[0].size = PVA_PFSD_DLUT_INDICES0_SIZE;
|
||||||
|
sources[1].data_ptr = pva_pfsd_data_dlut_indices1;
|
||||||
|
sources[1].size = PVA_PFSD_DLUT_INDICES1_SIZE;
|
||||||
|
sources[2].data_ptr = pva_pfsd_data_dlut_indices2;
|
||||||
|
sources[2].size = PVA_PFSD_DLUT_INDICES2_SIZE;
|
||||||
|
sources[3].data_ptr = pva_pfsd_data_dlut_indices3;
|
||||||
|
sources[3].size = PVA_PFSD_DLUT_INDICES3_SIZE;
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, sources, 4, PVA_MEMORY_SEGMENT_DMA,
|
||||||
|
&ctx->pfsd_resource_ids.dlut_indices_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_pfsd_register_elf(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_ops_executable_register exec_register = { 0 };
|
||||||
|
struct pva_ops_response_executable_register response = { 0 };
|
||||||
|
uint32_t response_size = 0;
|
||||||
|
uint32_t total_size = 0;
|
||||||
|
uint8_t *vpu_exec_buffer = NULL;
|
||||||
|
const uint8_t *vpu_elf_data = NULL;
|
||||||
|
uint32_t vpu_elf_size = 0;
|
||||||
|
uint8_t *ppe_exec_buffer = NULL;
|
||||||
|
const uint8_t *ppe_elf_data = NULL;
|
||||||
|
uint32_t ppe_elf_size = 0;
|
||||||
|
|
||||||
|
vpu_elf_data = ctx->pva->pfsd_info.vpu_elf_data;
|
||||||
|
vpu_elf_size = ctx->pva->pfsd_info.vpu_elf_size;
|
||||||
|
ppe_elf_data = ctx->pva->pfsd_info.ppe_elf_data;
|
||||||
|
ppe_elf_size = ctx->pva->pfsd_info.ppe_elf_size;
|
||||||
|
|
||||||
|
total_size = safe_addu32(
|
||||||
|
(uint32_t)sizeof(struct pva_ops_executable_register),
|
||||||
|
vpu_elf_size);
|
||||||
|
// Align total size to 8 bytes as required by PVA operation handler
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
|
||||||
|
vpu_exec_buffer = pva_kmd_zalloc(total_size);
|
||||||
|
if (vpu_exec_buffer == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to allocate buffer for PFSD ELF registration");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_register.header.opcode = PVA_OPS_OPCODE_EXECUTABLE_REGISTER;
|
||||||
|
exec_register.header.size = total_size;
|
||||||
|
exec_register.exec_size = vpu_elf_size;
|
||||||
|
|
||||||
|
(void)memcpy((void *)vpu_exec_buffer, (const void *)&exec_register,
|
||||||
|
sizeof(exec_register));
|
||||||
|
(void)memcpy((void *)(vpu_exec_buffer + sizeof(exec_register)),
|
||||||
|
(const void *)vpu_elf_data, vpu_elf_size);
|
||||||
|
|
||||||
|
err = pva_kmd_ops_handler(ctx, PVA_OPS_SUBMIT_MODE_SYNC, NULL,
|
||||||
|
vpu_exec_buffer, total_size, &response,
|
||||||
|
(uint32_t)sizeof(response), &response_size,
|
||||||
|
true);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("PFSD ELF executable registration failed");
|
||||||
|
goto free_vpu_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.error != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("PFSD ELF executable registration failed");
|
||||||
|
err = response.error;
|
||||||
|
goto free_vpu_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->pfsd_resource_ids.vpu_elf_resource_id = response.resource_id;
|
||||||
|
|
||||||
|
if (ppe_elf_data != NULL) {
|
||||||
|
total_size = safe_addu32(
|
||||||
|
(uint32_t)sizeof(struct pva_ops_executable_register),
|
||||||
|
ppe_elf_size);
|
||||||
|
// Align total size to 8 bytes as required by PVA operation handler
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
|
||||||
|
ppe_exec_buffer = pva_kmd_zalloc(total_size);
|
||||||
|
if (ppe_exec_buffer == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to allocate buffer for PFSD PPE ELF registration");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto free_ppe_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_register.header.opcode =
|
||||||
|
PVA_OPS_OPCODE_EXECUTABLE_REGISTER;
|
||||||
|
exec_register.header.size = total_size;
|
||||||
|
exec_register.exec_size = ppe_elf_size;
|
||||||
|
|
||||||
|
(void)memcpy((void *)ppe_exec_buffer,
|
||||||
|
(const void *)&exec_register,
|
||||||
|
sizeof(exec_register));
|
||||||
|
(void)memcpy((void *)(ppe_exec_buffer + sizeof(exec_register)),
|
||||||
|
(const void *)ppe_elf_data, ppe_elf_size);
|
||||||
|
|
||||||
|
err = pva_kmd_ops_handler(ctx, PVA_OPS_SUBMIT_MODE_SYNC, NULL,
|
||||||
|
ppe_exec_buffer, total_size,
|
||||||
|
&response, (uint32_t)sizeof(response),
|
||||||
|
&response_size, true);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PFSD PPE ELF executable registration failed");
|
||||||
|
goto free_ppe_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.error != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PFSD PPE ELF executable registration failed");
|
||||||
|
err = response.error;
|
||||||
|
goto free_ppe_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->pfsd_resource_ids.ppe_elf_resource_id =
|
||||||
|
response.resource_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_ppe_buffer:
|
||||||
|
pva_kmd_free(ppe_exec_buffer);
|
||||||
|
free_vpu_buffer:
|
||||||
|
pva_kmd_free(vpu_exec_buffer);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_pfsd_register_dma_config(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
struct pva_ops_response_register response = { 0 };
|
||||||
|
uint32_t response_size = 0;
|
||||||
|
uint32_t total_size = 0;
|
||||||
|
uint8_t *dma_buffer = NULL;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t i;
|
||||||
|
struct pva_dma_config pfsd_dma_cfg = { 0 };
|
||||||
|
struct pva_dma_static_binding static_bindings[8];
|
||||||
|
struct pva_ops_dma_config_register dma_register = { 0 };
|
||||||
|
|
||||||
|
pfsd_dma_cfg = ctx->pva->pfsd_info.pfsd_dma_cfg;
|
||||||
|
total_size = (uint32_t)sizeof(struct pva_ops_dma_config_register);
|
||||||
|
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
total_size = safe_addu32(
|
||||||
|
total_size,
|
||||||
|
safe_mulu32((uint32_t)pfsd_dma_cfg.header.num_channels,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_channel)));
|
||||||
|
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
total_size = safe_addu32(
|
||||||
|
total_size,
|
||||||
|
safe_mulu32((uint32_t)pfsd_dma_cfg.header.num_descriptors,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_descriptor)));
|
||||||
|
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
total_size = safe_addu32(
|
||||||
|
total_size,
|
||||||
|
safe_mulu32((uint32_t)pfsd_dma_cfg.header.num_hwseq_words,
|
||||||
|
(uint32_t)sizeof(uint32_t)));
|
||||||
|
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
total_size = safe_addu32(
|
||||||
|
total_size,
|
||||||
|
safe_mulu32((uint32_t)pfsd_dma_cfg.header.num_static_slots,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_static_binding)));
|
||||||
|
|
||||||
|
total_size = safe_pow2_roundup_u32(total_size, 8U);
|
||||||
|
|
||||||
|
dma_buffer = pva_kmd_zalloc(total_size);
|
||||||
|
if (dma_buffer == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Failed to allocate buffer for PFSD DMA config registration");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfsd_dma_cfg.header.vpu_exec_resource_id =
|
||||||
|
ctx->pfsd_resource_ids.vpu_elf_resource_id;
|
||||||
|
|
||||||
|
// Build dma_register structure locally and copy to buffer
|
||||||
|
dma_register.header.opcode = PVA_OPS_OPCODE_DMA_CONFIG_REGISTER;
|
||||||
|
dma_register.header.size = total_size;
|
||||||
|
dma_register.dma_config_header = pfsd_dma_cfg.header;
|
||||||
|
|
||||||
|
offset = (uint32_t)sizeof(struct pva_ops_dma_config_register);
|
||||||
|
|
||||||
|
offset = safe_pow2_roundup_u32(offset, 8U);
|
||||||
|
dma_register.channels_offset = offset;
|
||||||
|
(void)memcpy((void *)(dma_buffer + offset),
|
||||||
|
(const void *)pfsd_dma_cfg.channels,
|
||||||
|
pfsd_dma_cfg.header.num_channels *
|
||||||
|
sizeof(struct pva_dma_channel));
|
||||||
|
offset = safe_addu32(
|
||||||
|
offset, safe_mulu32(pfsd_dma_cfg.header.num_channels,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_channel)));
|
||||||
|
|
||||||
|
offset = safe_pow2_roundup_u32(offset, 8U);
|
||||||
|
dma_register.descriptors_offset = offset;
|
||||||
|
(void)memcpy((void *)(dma_buffer + offset),
|
||||||
|
(const void *)pfsd_dma_cfg.descriptors,
|
||||||
|
pfsd_dma_cfg.header.num_descriptors *
|
||||||
|
sizeof(struct pva_dma_descriptor));
|
||||||
|
offset = safe_addu32(
|
||||||
|
offset,
|
||||||
|
safe_mulu32(pfsd_dma_cfg.header.num_descriptors,
|
||||||
|
(uint32_t)sizeof(struct pva_dma_descriptor)));
|
||||||
|
|
||||||
|
offset = safe_pow2_roundup_u32(offset, 8U);
|
||||||
|
dma_register.hwseq_words_offset = offset;
|
||||||
|
if (pfsd_dma_cfg.header.num_hwseq_words > 0U &&
|
||||||
|
pfsd_dma_cfg.hwseq_words != NULL) {
|
||||||
|
(void)memcpy((void *)(dma_buffer + offset),
|
||||||
|
(const void *)pfsd_dma_cfg.hwseq_words,
|
||||||
|
pfsd_dma_cfg.header.num_hwseq_words *
|
||||||
|
sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
offset = safe_addu32(offset,
|
||||||
|
safe_mulu32(pfsd_dma_cfg.header.num_hwseq_words,
|
||||||
|
(uint32_t)sizeof(uint32_t)));
|
||||||
|
|
||||||
|
for (i = 0U; i < pfsd_dma_cfg.header.num_static_slots && i < 8U; i++) {
|
||||||
|
(void)memcpy(&static_bindings[i],
|
||||||
|
&pfsd_dma_cfg.static_bindings[i],
|
||||||
|
sizeof(struct pva_dma_static_binding));
|
||||||
|
}
|
||||||
|
|
||||||
|
static_bindings[0].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.in1_resource_id;
|
||||||
|
static_bindings[1].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.in2_resource_id;
|
||||||
|
static_bindings[2].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.in3_resource_id;
|
||||||
|
static_bindings[3].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.hist_a_resource_id;
|
||||||
|
static_bindings[4].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.hist_b_resource_id;
|
||||||
|
static_bindings[5].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.hist_c_resource_id;
|
||||||
|
static_bindings[6].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.dlut_tbl_resource_id;
|
||||||
|
static_bindings[7].dram.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.dlut_indices_resource_id;
|
||||||
|
|
||||||
|
offset = safe_pow2_roundup_u32(offset, 8U);
|
||||||
|
dma_register.static_bindings_offset = offset;
|
||||||
|
(void)memcpy((void *)(dma_buffer + offset),
|
||||||
|
(const void *)static_bindings,
|
||||||
|
pfsd_dma_cfg.header.num_static_slots *
|
||||||
|
sizeof(struct pva_dma_static_binding));
|
||||||
|
|
||||||
|
(void)memcpy((void *)dma_buffer, (const void *)&dma_register,
|
||||||
|
sizeof(dma_register));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MISRA C-2023 Directive 4.14: Validate values from external sources
|
||||||
|
* Note: dma_buffer is constructed internally from pfsd_dma_cfg which has
|
||||||
|
* been validated during PFSD initialization. All resource IDs are from
|
||||||
|
* internal driver state (ctx->pfsd_resource_ids), not direct user input.
|
||||||
|
* The buffer size and structure are validated by pva_kmd_ops_handler.
|
||||||
|
*/
|
||||||
|
err = pva_kmd_ops_handler(ctx, PVA_OPS_SUBMIT_MODE_SYNC, NULL,
|
||||||
|
dma_buffer, total_size, &response,
|
||||||
|
(uint32_t)sizeof(response), &response_size,
|
||||||
|
true);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("PFSD DMA config registration failed");
|
||||||
|
goto free_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.error != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("PFSD DMA config registration failed");
|
||||||
|
err = response.error;
|
||||||
|
goto free_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->pfsd_resource_ids.dma_config_resource_id = response.resource_id;
|
||||||
|
|
||||||
|
free_buffer:
|
||||||
|
pva_kmd_free(dma_buffer);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_pfsd_t23x_register_cmdbuf(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
uint8_t *cmd_buffer = NULL;
|
||||||
|
uint32_t cmd_buffer_size = 0;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
struct pva_buffer_source cmd_source;
|
||||||
|
struct pva_cmd_acquire_engine acquire_cmd = { 0 };
|
||||||
|
struct pva_cmd_set_vpu_executable set_vpu_exec_cmd = { 0 };
|
||||||
|
struct pva_cmd_prefetch_vpu_code prefetch_cmd = { 0 };
|
||||||
|
struct pva_cmd_fetch_dma_configuration fetch_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_init_vpu_executable init_vpu_cmd = { 0 };
|
||||||
|
struct pva_cmd_set_vpu_instance_parameter set_vpu_param_cmd = { 0 };
|
||||||
|
struct pva_cmd_setup_misr setup_misr_cmd = { 0 };
|
||||||
|
struct pva_cmd_setup_dma setup_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_run_dma run_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_run_vpu run_vpu_cmd = { 0 };
|
||||||
|
struct pva_cmd_release_engine release_cmd = { 0 };
|
||||||
|
|
||||||
|
// Calculate command buffer size
|
||||||
|
cmd_buffer_size =
|
||||||
|
(uint32_t)(sizeof(struct pva_cmd_acquire_engine) +
|
||||||
|
sizeof(struct pva_cmd_set_vpu_executable) +
|
||||||
|
sizeof(struct pva_cmd_prefetch_vpu_code) +
|
||||||
|
sizeof(struct pva_cmd_fetch_dma_configuration) +
|
||||||
|
sizeof(struct pva_cmd_init_vpu_executable) +
|
||||||
|
sizeof(struct pva_cmd_set_vpu_instance_parameter) +
|
||||||
|
sizeof(struct pva_cmd_setup_misr) +
|
||||||
|
sizeof(struct pva_cmd_setup_dma) +
|
||||||
|
sizeof(struct pva_cmd_run_dma) +
|
||||||
|
sizeof(struct pva_cmd_run_vpu) +
|
||||||
|
sizeof(struct pva_cmd_release_engine));
|
||||||
|
|
||||||
|
// Allocate command buffer
|
||||||
|
cmd_buffer = pva_kmd_zalloc(cmd_buffer_size);
|
||||||
|
if (cmd_buffer == NULL) {
|
||||||
|
pva_kmd_log_err("Failed to allocate command buffer");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build command sequence
|
||||||
|
|
||||||
|
// 1. pva_cmd_acquire_engine
|
||||||
|
acquire_cmd.header.opcode = PVA_CMD_OPCODE_ACQUIRE_ENGINE;
|
||||||
|
acquire_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_acquire_engine) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
acquire_cmd.engine_count = 1;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&acquire_cmd,
|
||||||
|
sizeof(acquire_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_acquire_engine);
|
||||||
|
|
||||||
|
// 2. pva_cmd_set_vpu_executable
|
||||||
|
set_vpu_exec_cmd.header.opcode = PVA_CMD_OPCODE_SET_VPU_EXECUTABLE;
|
||||||
|
set_vpu_exec_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_set_vpu_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
set_vpu_exec_cmd.vpu_exec_resource_id =
|
||||||
|
ctx->pfsd_resource_ids.vpu_elf_resource_id;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&set_vpu_exec_cmd, sizeof(set_vpu_exec_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_set_vpu_executable);
|
||||||
|
|
||||||
|
// 3. pva_cmd_prefetch_vpu_code
|
||||||
|
prefetch_cmd.header.opcode = PVA_CMD_OPCODE_PREFETCH_VPU_CODE;
|
||||||
|
prefetch_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_prefetch_vpu_code) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
prefetch_cmd.entry_point_index = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&prefetch_cmd,
|
||||||
|
sizeof(prefetch_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_prefetch_vpu_code);
|
||||||
|
|
||||||
|
// 4. pva_cmd_fetch_dma_configuration
|
||||||
|
fetch_dma_cmd.header.opcode = PVA_CMD_OPCODE_FETCH_DMA_CONFIGURATION;
|
||||||
|
fetch_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_fetch_dma_configuration) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
fetch_dma_cmd.dma_set_id = 0;
|
||||||
|
fetch_dma_cmd.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.dma_config_resource_id;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&fetch_dma_cmd, sizeof(fetch_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_fetch_dma_configuration);
|
||||||
|
|
||||||
|
// 5. pva_cmd_init_vpu_executable
|
||||||
|
init_vpu_cmd.header.opcode = PVA_CMD_OPCODE_INIT_VPU_EXECUTABLE;
|
||||||
|
init_vpu_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_init_vpu_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&init_vpu_cmd,
|
||||||
|
sizeof(init_vpu_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_init_vpu_executable);
|
||||||
|
|
||||||
|
// 6. pva_cmd_set_vpu_instance_parameter
|
||||||
|
set_vpu_param_cmd.header.opcode =
|
||||||
|
PVA_CMD_OPCODE_SET_VPU_INSTANCE_PARAMETER;
|
||||||
|
set_vpu_param_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_set_vpu_instance_parameter) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
set_vpu_param_cmd.symbol_id = 0x40U;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&set_vpu_param_cmd,
|
||||||
|
sizeof(set_vpu_param_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_set_vpu_instance_parameter);
|
||||||
|
|
||||||
|
// 7. pva_cmd_setup_misr
|
||||||
|
setup_misr_cmd.header.opcode = PVA_CMD_OPCODE_SETUP_MISR;
|
||||||
|
setup_misr_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_setup_misr) / sizeof(uint32_t));
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_low0 = 0xFFFFFFFFU;
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_low1 = 0x000007FFU;
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_high = 0;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.seed_crc0 = MISR_SEED_0_T23X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.seed_crc1 = MISR_SEED_1_T23X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_addr = MISR_REF_0_T23X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_data_1 = MISR_REF_1_T23X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_data_2 = MISR_REF_2_T23X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.misr_timeout = MISR_TIMEOUT_T23X;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&setup_misr_cmd, sizeof(setup_misr_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_setup_misr);
|
||||||
|
|
||||||
|
// 8. pva_cmd_setup_dma
|
||||||
|
setup_dma_cmd.header.opcode = PVA_CMD_OPCODE_SETUP_DMA;
|
||||||
|
setup_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_setup_dma) / sizeof(uint32_t));
|
||||||
|
setup_dma_cmd.dma_set_id = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&setup_dma_cmd, sizeof(setup_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_setup_dma);
|
||||||
|
|
||||||
|
// 9. pva_cmd_run_dma
|
||||||
|
run_dma_cmd.header.opcode = PVA_CMD_OPCODE_RUN_DMA;
|
||||||
|
run_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_run_dma) / sizeof(uint32_t));
|
||||||
|
run_dma_cmd.dma_set_id = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&run_dma_cmd,
|
||||||
|
sizeof(run_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_run_dma);
|
||||||
|
|
||||||
|
// 10. pva_cmd_run_vpu
|
||||||
|
run_vpu_cmd.header.opcode = PVA_CMD_OPCODE_RUN_VPU;
|
||||||
|
run_vpu_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_run_vpu) / sizeof(uint32_t));
|
||||||
|
run_vpu_cmd.entry_point_index = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&run_vpu_cmd,
|
||||||
|
sizeof(run_vpu_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_run_vpu);
|
||||||
|
|
||||||
|
// 11. pva_cmd_release_engine
|
||||||
|
release_cmd.header.opcode = PVA_CMD_OPCODE_RELEASE_ENGINE;
|
||||||
|
release_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_release_engine) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&release_cmd,
|
||||||
|
sizeof(release_cmd));
|
||||||
|
|
||||||
|
// Register the command buffer with R5 segment so firmware can access it
|
||||||
|
cmd_source.data_ptr = cmd_buffer;
|
||||||
|
cmd_source.size = cmd_buffer_size;
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, &cmd_source, 1, PVA_MEMORY_SEGMENT_R5,
|
||||||
|
&ctx->pfsd_resource_ids.cmd_buffer_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to register PFSD command buffer");
|
||||||
|
goto free_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the command buffer size in the global structure
|
||||||
|
ctx->pfsd_resource_ids.cmd_buffer_size = cmd_buffer_size;
|
||||||
|
|
||||||
|
free_buffer:
|
||||||
|
pva_kmd_free(cmd_buffer);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_pfsd_t26x_register_cmdbuf(struct pva_kmd_context *ctx)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
uint8_t *cmd_buffer = NULL;
|
||||||
|
uint32_t cmd_buffer_size = 0;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
struct pva_buffer_source cmd_source;
|
||||||
|
struct pva_cmd_acquire_engine acquire_cmd = { 0 };
|
||||||
|
struct pva_cmd_set_vpu_executable set_vpu_exec_cmd = { 0 };
|
||||||
|
struct pva_cmd_set_ppe_executable set_ppe_exec_cmd = { 0 };
|
||||||
|
struct pva_cmd_prefetch_vpu_code prefetch_cmd = { 0 };
|
||||||
|
struct pva_cmd_fetch_dma_configuration fetch_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_init_vpu_executable init_vpu_cmd = { 0 };
|
||||||
|
struct pva_cmd_init_ppe_executable init_ppe_cmd = { 0 };
|
||||||
|
struct pva_cmd_set_vpu_instance_parameter set_vpu_param_cmd = { 0 };
|
||||||
|
struct pva_cmd_setup_misr setup_misr_cmd = { 0 };
|
||||||
|
struct pva_cmd_setup_dma setup_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_run_dma run_dma_cmd = { 0 };
|
||||||
|
struct pva_cmd_run_vpu run_vpu_cmd = { 0 };
|
||||||
|
struct pva_cmd_run_ppe run_ppe_cmd = { 0 };
|
||||||
|
struct pva_cmd_release_engine release_cmd = { 0 };
|
||||||
|
|
||||||
|
// Calculate command buffer size
|
||||||
|
cmd_buffer_size =
|
||||||
|
(uint32_t)(sizeof(struct pva_cmd_acquire_engine) +
|
||||||
|
sizeof(struct pva_cmd_set_vpu_executable) +
|
||||||
|
sizeof(struct pva_cmd_set_ppe_executable) +
|
||||||
|
sizeof(struct pva_cmd_prefetch_vpu_code) +
|
||||||
|
sizeof(struct pva_cmd_fetch_dma_configuration) +
|
||||||
|
sizeof(struct pva_cmd_init_vpu_executable) +
|
||||||
|
sizeof(struct pva_cmd_init_ppe_executable) +
|
||||||
|
sizeof(struct pva_cmd_set_vpu_instance_parameter) +
|
||||||
|
sizeof(struct pva_cmd_setup_misr) +
|
||||||
|
sizeof(struct pva_cmd_setup_dma) +
|
||||||
|
sizeof(struct pva_cmd_run_dma) +
|
||||||
|
sizeof(struct pva_cmd_run_vpu) +
|
||||||
|
sizeof(struct pva_cmd_run_ppe) +
|
||||||
|
sizeof(struct pva_cmd_release_engine));
|
||||||
|
|
||||||
|
// Allocate command buffer
|
||||||
|
cmd_buffer = pva_kmd_zalloc(cmd_buffer_size);
|
||||||
|
if (cmd_buffer == NULL) {
|
||||||
|
pva_kmd_log_err("Failed to allocate command buffer");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build command sequence
|
||||||
|
|
||||||
|
// 1. pva_cmd_acquire_engine
|
||||||
|
acquire_cmd.header.opcode = PVA_CMD_OPCODE_ACQUIRE_ENGINE;
|
||||||
|
acquire_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_acquire_engine) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
acquire_cmd.engine_count = 1;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&acquire_cmd,
|
||||||
|
sizeof(acquire_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_acquire_engine);
|
||||||
|
|
||||||
|
// 2. pva_cmd_set_vpu_executable
|
||||||
|
set_vpu_exec_cmd.header.opcode = PVA_CMD_OPCODE_SET_VPU_EXECUTABLE;
|
||||||
|
set_vpu_exec_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_set_vpu_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
set_vpu_exec_cmd.vpu_exec_resource_id =
|
||||||
|
ctx->pfsd_resource_ids.vpu_elf_resource_id;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&set_vpu_exec_cmd, sizeof(set_vpu_exec_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_set_vpu_executable);
|
||||||
|
|
||||||
|
// 3. pva_cmd_set_ppe_executable
|
||||||
|
set_ppe_exec_cmd.header.opcode = PVA_CMD_OPCODE_SET_PPE_EXECUTABLE;
|
||||||
|
set_ppe_exec_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_set_ppe_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
set_ppe_exec_cmd.ppe_exec_resource_id =
|
||||||
|
ctx->pfsd_resource_ids.ppe_elf_resource_id;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&set_ppe_exec_cmd, sizeof(set_ppe_exec_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_set_ppe_executable);
|
||||||
|
|
||||||
|
// 4. pva_cmd_prefetch_vpu_code
|
||||||
|
prefetch_cmd.header.opcode = PVA_CMD_OPCODE_PREFETCH_VPU_CODE;
|
||||||
|
prefetch_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_prefetch_vpu_code) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
prefetch_cmd.entry_point_index = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&prefetch_cmd,
|
||||||
|
sizeof(prefetch_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_prefetch_vpu_code);
|
||||||
|
|
||||||
|
// 5. pva_cmd_fetch_dma_configuration
|
||||||
|
fetch_dma_cmd.header.opcode = PVA_CMD_OPCODE_FETCH_DMA_CONFIGURATION;
|
||||||
|
fetch_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_fetch_dma_configuration) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
fetch_dma_cmd.dma_set_id = 0;
|
||||||
|
fetch_dma_cmd.resource_id =
|
||||||
|
ctx->pfsd_resource_ids.dma_config_resource_id;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&fetch_dma_cmd, sizeof(fetch_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_fetch_dma_configuration);
|
||||||
|
|
||||||
|
// 6. pva_cmd_init_vpu_executable
|
||||||
|
init_vpu_cmd.header.opcode = PVA_CMD_OPCODE_INIT_VPU_EXECUTABLE;
|
||||||
|
init_vpu_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_init_vpu_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&init_vpu_cmd,
|
||||||
|
sizeof(init_vpu_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_init_vpu_executable);
|
||||||
|
|
||||||
|
// 7. pva_cmd_init_ppe_executable
|
||||||
|
init_ppe_cmd.header.opcode = PVA_CMD_OPCODE_INIT_PPE_EXECUTABLE;
|
||||||
|
init_ppe_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_init_ppe_executable) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&init_ppe_cmd,
|
||||||
|
sizeof(init_ppe_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_init_ppe_executable);
|
||||||
|
|
||||||
|
// 8. pva_cmd_set_vpu_instance_parameter
|
||||||
|
set_vpu_param_cmd.header.opcode =
|
||||||
|
PVA_CMD_OPCODE_SET_VPU_INSTANCE_PARAMETER;
|
||||||
|
set_vpu_param_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_set_vpu_instance_parameter) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
set_vpu_param_cmd.symbol_id = 0x40U;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&set_vpu_param_cmd,
|
||||||
|
sizeof(set_vpu_param_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_set_vpu_instance_parameter);
|
||||||
|
|
||||||
|
// 9. pva_cmd_setup_misr
|
||||||
|
setup_misr_cmd.header.opcode = PVA_CMD_OPCODE_SETUP_MISR;
|
||||||
|
setup_misr_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_setup_misr) / sizeof(uint32_t));
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_low0 = 0xFFFFFFFFU;
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_low1 = 0xFFFFFFFFU;
|
||||||
|
setup_misr_cmd.misr_params.slot_mask_high = 0x1FU;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.seed_crc0 = MISR_SEED_0_T26X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.seed_crc1 = MISR_SEED_1_T26X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_addr = MISR_REF_0_T26X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_data_1 = MISR_REF_1_T26X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.ref_data_2 = MISR_REF_2_T26X;
|
||||||
|
setup_misr_cmd.misr_params.misr_config.misr_timeout = MISR_TIMEOUT_T26X;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&setup_misr_cmd, sizeof(setup_misr_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_setup_misr);
|
||||||
|
|
||||||
|
// 10. pva_cmd_setup_dma
|
||||||
|
setup_dma_cmd.header.opcode = PVA_CMD_OPCODE_SETUP_DMA;
|
||||||
|
setup_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_setup_dma) / sizeof(uint32_t));
|
||||||
|
setup_dma_cmd.dma_set_id = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset),
|
||||||
|
(const void *)&setup_dma_cmd, sizeof(setup_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_setup_dma);
|
||||||
|
|
||||||
|
// 11. pva_cmd_run_dma
|
||||||
|
run_dma_cmd.header.opcode = PVA_CMD_OPCODE_RUN_DMA;
|
||||||
|
run_dma_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_run_dma) / sizeof(uint32_t));
|
||||||
|
run_dma_cmd.dma_set_id = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&run_dma_cmd,
|
||||||
|
sizeof(run_dma_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_run_dma);
|
||||||
|
|
||||||
|
// 12. pva_cmd_run_vpu
|
||||||
|
run_vpu_cmd.header.opcode = PVA_CMD_OPCODE_RUN_VPU;
|
||||||
|
run_vpu_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_run_vpu) / sizeof(uint32_t));
|
||||||
|
run_vpu_cmd.entry_point_index = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&run_vpu_cmd,
|
||||||
|
sizeof(run_vpu_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_run_vpu);
|
||||||
|
|
||||||
|
// 13. pva_cmd_run_ppe
|
||||||
|
run_ppe_cmd.header.opcode = PVA_CMD_OPCODE_RUN_PPE;
|
||||||
|
run_ppe_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_run_ppe) / sizeof(uint32_t));
|
||||||
|
run_ppe_cmd.entry_point_index = 0;
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&run_ppe_cmd,
|
||||||
|
sizeof(run_ppe_cmd));
|
||||||
|
offset += (uint32_t)sizeof(struct pva_cmd_run_ppe);
|
||||||
|
|
||||||
|
// 14. pva_cmd_release_engine
|
||||||
|
release_cmd.header.opcode = PVA_CMD_OPCODE_RELEASE_ENGINE;
|
||||||
|
release_cmd.header.len =
|
||||||
|
(uint8_t)(sizeof(struct pva_cmd_release_engine) /
|
||||||
|
sizeof(uint32_t));
|
||||||
|
(void)memcpy((void *)(cmd_buffer + offset), (const void *)&release_cmd,
|
||||||
|
sizeof(release_cmd));
|
||||||
|
|
||||||
|
// Register the command buffer with R5 segment so firmware can access it
|
||||||
|
cmd_source.data_ptr = cmd_buffer;
|
||||||
|
cmd_source.size = cmd_buffer_size;
|
||||||
|
err = pva_kmd_pfsd_register_buffer(
|
||||||
|
ctx, &cmd_source, 1, PVA_MEMORY_SEGMENT_R5,
|
||||||
|
&ctx->pfsd_resource_ids.cmd_buffer_resource_id);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to register PFSD command buffer");
|
||||||
|
goto free_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the command buffer size in the global structure
|
||||||
|
ctx->pfsd_resource_ids.cmd_buffer_size = cmd_buffer_size;
|
||||||
|
|
||||||
|
free_buffer:
|
||||||
|
pva_kmd_free(cmd_buffer);
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
146
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd.h
Normal file
146
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
|
#ifndef PVA_KMD_PFSD_H
|
||||||
|
#define PVA_KMD_PFSD_H
|
||||||
|
|
||||||
|
#include "pva_kmd_cmdbuf.h"
|
||||||
|
#include "pva_api_dma.h"
|
||||||
|
#include "pva_utils.h"
|
||||||
|
|
||||||
|
struct pva_kmd_context;
|
||||||
|
|
||||||
|
#define PVA_PFSD_DATA_ARRAY_IN_LEN (512U)
|
||||||
|
#define PVA_PFSD_DATA_ARRAY_HIST_SHORT_LEN (512U)
|
||||||
|
#define PVA_PFSD_DATA_ARRAY_HIST_INT_LEN (256U)
|
||||||
|
|
||||||
|
extern const uint32_t in1[PVA_PFSD_DATA_ARRAY_IN_LEN];
|
||||||
|
extern const uint32_t in2[PVA_PFSD_DATA_ARRAY_IN_LEN];
|
||||||
|
extern const uint32_t in3[PVA_PFSD_DATA_ARRAY_IN_LEN];
|
||||||
|
extern const uint16_t hist_short_a[PVA_PFSD_DATA_ARRAY_HIST_SHORT_LEN];
|
||||||
|
extern const uint16_t hist_short_b[PVA_PFSD_DATA_ARRAY_HIST_SHORT_LEN];
|
||||||
|
extern const uint16_t hist_short_c[PVA_PFSD_DATA_ARRAY_HIST_SHORT_LEN];
|
||||||
|
extern const uint32_t hist_int_a[PVA_PFSD_DATA_ARRAY_HIST_INT_LEN];
|
||||||
|
extern const uint32_t hist_int_b[PVA_PFSD_DATA_ARRAY_HIST_INT_LEN];
|
||||||
|
extern const uint32_t hist_int_c[PVA_PFSD_DATA_ARRAY_HIST_INT_LEN];
|
||||||
|
|
||||||
|
#define DLUT_TBL0_NUM_ENTRIES (256U)
|
||||||
|
#define DLUT_TBL1_NUM_ENTRIES (28672U)
|
||||||
|
#define DLUT_TBL2_NUM_ENTRIES (9114U)
|
||||||
|
#define DLUT_TBL3_NUM_ENTRIES (2048U)
|
||||||
|
#define PVA_PFSD_DLUT_TBL0_SIZE (DLUT_TBL0_NUM_ENTRIES * sizeof(int16_t))
|
||||||
|
#define PVA_PFSD_DLUT_TBL1_SIZE (DLUT_TBL1_NUM_ENTRIES * sizeof(uint16_t))
|
||||||
|
#define PVA_PFSD_DLUT_TBL2_SIZE \
|
||||||
|
PVA_ROUND_UP((DLUT_TBL2_NUM_ENTRIES * sizeof(uint16_t)), 64U)
|
||||||
|
#define PVA_PFSD_DLUT_TBL3_SIZE (DLUT_TBL3_NUM_ENTRIES * sizeof(uint8_t))
|
||||||
|
|
||||||
|
extern const int16_t pva_pfsd_data_dlut_tbl0[];
|
||||||
|
extern const uint16_t pva_pfsd_data_dlut_tbl1[];
|
||||||
|
extern const uint16_t pva_pfsd_data_dlut_tbl2[];
|
||||||
|
extern const uint8_t pva_pfsd_data_dlut_tbl3[];
|
||||||
|
|
||||||
|
#define DLUT_IDX0_NUM_ENTRIES (8192U)
|
||||||
|
#define DLUT_IDX1_NUM_ENTRIES (4096U)
|
||||||
|
#define DLUT_IDX2_NUM_ENTRIES (8192U)
|
||||||
|
#define DLUT_IDX3_NUM_ENTRIES (4096U)
|
||||||
|
#define PVA_PFSD_DLUT_INDICES0_SIZE (DLUT_IDX0_NUM_ENTRIES * sizeof(int16_t))
|
||||||
|
#define PVA_PFSD_DLUT_INDICES1_SIZE (DLUT_IDX1_NUM_ENTRIES * sizeof(int32_t))
|
||||||
|
#define PVA_PFSD_DLUT_INDICES2_SIZE (DLUT_IDX2_NUM_ENTRIES * sizeof(int32_t))
|
||||||
|
#define PVA_PFSD_DLUT_INDICES3_SIZE (DLUT_IDX3_NUM_ENTRIES * sizeof(int32_t))
|
||||||
|
|
||||||
|
extern const int16_t pva_pfsd_data_dlut_indices0[];
|
||||||
|
extern const int32_t pva_pfsd_data_dlut_indices1[];
|
||||||
|
extern const int32_t pva_pfsd_data_dlut_indices2[];
|
||||||
|
extern const int32_t pva_pfsd_data_dlut_indices3[];
|
||||||
|
|
||||||
|
#define MISR_SEED_0_T23X 0xA5A5A5A5U
|
||||||
|
#define MISR_SEED_1_T23X 0x5A5A5A5AU
|
||||||
|
#define MISR_REF_0_T23X 0xFF9DB35CU
|
||||||
|
#define MISR_REF_1_T23X 0x9840285EU
|
||||||
|
#define MISR_REF_2_T23X 0x2035EA07U
|
||||||
|
#define MISR_TIMEOUT_T23X 0x1C9C38U
|
||||||
|
|
||||||
|
#define MISR_SEED_0_T26X 0xA5A5A5A5U
|
||||||
|
#define MISR_SEED_1_T26X 0x5A5A5A5AU
|
||||||
|
#define MISR_REF_0_T26X 0x31E64312U
|
||||||
|
#define MISR_REF_1_T26X 0x585AAACDU
|
||||||
|
#define MISR_REF_2_T26X 0x065AFA90U
|
||||||
|
#define MISR_TIMEOUT_T26X 0x2DC6C0U
|
||||||
|
|
||||||
|
struct pva_pfsd_resource_ids {
|
||||||
|
// Input buffer resource IDs
|
||||||
|
uint32_t in1_resource_id;
|
||||||
|
uint32_t in2_resource_id;
|
||||||
|
uint32_t in3_resource_id;
|
||||||
|
uint32_t hist_a_resource_id;
|
||||||
|
uint32_t hist_b_resource_id;
|
||||||
|
uint32_t hist_c_resource_id;
|
||||||
|
uint32_t dlut_tbl_resource_id;
|
||||||
|
uint32_t dlut_indices_resource_id;
|
||||||
|
// VPU executable resource ID
|
||||||
|
uint32_t vpu_elf_resource_id;
|
||||||
|
// PPE executable resource ID
|
||||||
|
uint32_t ppe_elf_resource_id;
|
||||||
|
// DMA configuration resource ID
|
||||||
|
uint32_t dma_config_resource_id;
|
||||||
|
// Command buffer resource ID
|
||||||
|
uint32_t cmd_buffer_resource_id;
|
||||||
|
// Command buffer size
|
||||||
|
uint32_t cmd_buffer_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PVA_PFSD_VPU_ELF_SIZE_T23X (1259220U)
|
||||||
|
extern const uint8_t pva_pfsd_vpu_elf_t23x[];
|
||||||
|
|
||||||
|
#define PVA_PFSD_VPU_ELF_SIZE_T26X (1279424U)
|
||||||
|
extern const uint8_t pva_pfsd_vpu_elf_t26x[];
|
||||||
|
|
||||||
|
#define PVA_PFSD_PPE_ELF_SIZE_T26X (222468U)
|
||||||
|
extern const uint8_t pva_pfsd_ppe_elf_t26x[];
|
||||||
|
|
||||||
|
extern const struct pva_dma_config pfsd_dma_cfg_t23x;
|
||||||
|
extern const struct pva_dma_config pfsd_dma_cfg_t26x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PFSD input buffers with the resource table
|
||||||
|
*
|
||||||
|
* @param ctx PVA KMD context
|
||||||
|
* @return PVA_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_pfsd_register_input_buffers(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PFSD ELF executables with the resource table
|
||||||
|
*
|
||||||
|
* @param ctx PVA KMD context
|
||||||
|
* @param chip_id Chip ID to determine which ELF to register
|
||||||
|
* @return PVA_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_pfsd_register_elf(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PFSD DMA configuration with the resource table
|
||||||
|
*
|
||||||
|
* @param ctx PVA KMD context
|
||||||
|
* @param chip_id Chip ID to determine which DMA config to register
|
||||||
|
* @return PVA_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_pfsd_register_dma_config(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PFSD command buffer for T23X with the resource table
|
||||||
|
*
|
||||||
|
* @param ctx PVA KMD context
|
||||||
|
* @return PVA_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_pfsd_t23x_register_cmdbuf(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PFSD command buffer for T26X with the resource table
|
||||||
|
*
|
||||||
|
* @param ctx PVA KMD context
|
||||||
|
* @return PVA_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
enum pva_error pva_kmd_pfsd_t26x_register_cmdbuf(struct pva_kmd_context *ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
732
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd_data.c
Normal file
732
drivers/video/tegra/host/pva/src/kmd/common/pva_kmd_pfsd_data.c
Normal file
@@ -0,0 +1,732 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_kmd_pfsd.h"
|
||||||
|
|
||||||
|
const uint32_t in1[] = {
|
||||||
|
0x03020100U, 0x07060504U, 0x0B0A0908U, 0x0F0E0D0CU, 0x13121110U,
|
||||||
|
0x17161514U, 0x1B1A1918U, 0x1F1E1D1CU, 0x23222120U, 0x27262524U,
|
||||||
|
0x2B2A2928U, 0x2F2E2D2CU, 0x33323130U, 0x37363534U, 0x3B3A3938U,
|
||||||
|
0x3F3E3D3CU, 0x43424140U, 0x47464544U, 0x4B4A4948U, 0x4F4E4D4CU,
|
||||||
|
0x53525150U, 0x57565554U, 0x5B5A5958U, 0x5F5E5D5CU, 0x63626160U,
|
||||||
|
0x67666564U, 0x6B6A6968U, 0x6F6E6D6CU, 0x73727170U, 0x77767574U,
|
||||||
|
0x7B7A7978U, 0x7F7E7D7CU, 0x83828180U, 0x87868584U, 0x8B8A8988U,
|
||||||
|
0x8F8E8D8CU, 0x93929190U, 0x97969594U, 0x9B9A9998U, 0x9F9E9D9CU,
|
||||||
|
0xA3A2A1A0U, 0xA7A6A5A4U, 0xABAAA9A8U, 0xAFAEADACU, 0xB3B2B1B0U,
|
||||||
|
0xB7B6B5B4U, 0xBBBAB9B8U, 0xBFBEBDBCU, 0xC3C2C1C0U, 0xC7C6C5C4U,
|
||||||
|
0xCBCAC9C8U, 0xCFCECDCCU, 0xD3D2D1D0U, 0xD7D6D5D4U, 0xDBDAD9D8U,
|
||||||
|
0xDFDEDDDCU, 0xE3E2E1E0U, 0xE7E6E5E4U, 0xEBEAE9E8U, 0xEFEEEDECU,
|
||||||
|
0xF3F2F1F0U, 0xF7F6F5F4U, 0xFBFAF9F8U, 0xFFFEFDFCU, 0x03020100U,
|
||||||
|
0x07060504U, 0x0B0A0908U, 0x0F0E0D0CU, 0x13121110U, 0x17161514U,
|
||||||
|
0x1B1A1918U, 0x1F1E1D1CU, 0x23222120U, 0x27262524U, 0x2B2A2928U,
|
||||||
|
0x2F2E2D2CU, 0x33323130U, 0x37363534U, 0x3B3A3938U, 0x3F3E3D3CU,
|
||||||
|
0x43424140U, 0x47464544U, 0x4B4A4948U, 0x4F4E4D4CU, 0x53525150U,
|
||||||
|
0x57565554U, 0x5B5A5958U, 0x5F5E5D5CU, 0x63626160U, 0x67666564U,
|
||||||
|
0x6B6A6968U, 0x6F6E6D6CU, 0x73727170U, 0x77767574U, 0x7B7A7978U,
|
||||||
|
0x7F7E7D7CU, 0x83828180U, 0x87868584U, 0x8B8A8988U, 0x8F8E8D8CU,
|
||||||
|
0x93929190U, 0x97969594U, 0x9B9A9998U, 0x9F9E9D9CU, 0xA3A2A1A0U,
|
||||||
|
0xA7A6A5A4U, 0xABAAA9A8U, 0xAFAEADACU, 0xB3B2B1B0U, 0xB7B6B5B4U,
|
||||||
|
0xBBBAB9B8U, 0xBFBEBDBCU, 0xC3C2C1C0U, 0xC7C6C5C4U, 0xCBCAC9C8U,
|
||||||
|
0xCFCECDCCU, 0xD3D2D1D0U, 0xD7D6D5D4U, 0xDBDAD9D8U, 0xDFDEDDDCU,
|
||||||
|
0xE3E2E1E0U, 0xE7E6E5E4U, 0xEBEAE9E8U, 0xEFEEEDECU, 0xF3F2F1F0U,
|
||||||
|
0xF7F6F5F4U, 0xFBFAF9F8U, 0xFFFEFDFCU, 0x00FF0000U, 0x02FD01FEU,
|
||||||
|
0x04FB03FCU, 0x06F905FAU, 0x08F707F8U, 0x0AF509F6U, 0x0CF30BF4U,
|
||||||
|
0x0EF10DF2U, 0x10EF0FF0U, 0x12ED11EEU, 0x14EB13ECU, 0x16E915EAU,
|
||||||
|
0x18E717E8U, 0x1AE519E6U, 0x1CE31BE4U, 0x1EE11DE2U, 0x20DF1FE0U,
|
||||||
|
0x22DD21DEU, 0x24DB23DCU, 0x26D925DAU, 0x28D727D8U, 0x2AD529D6U,
|
||||||
|
0x2CD32BD4U, 0x2ED12DD2U, 0x30CF2FD0U, 0x32CD31CEU, 0x34CB33CCU,
|
||||||
|
0x36C935CAU, 0x38C737C8U, 0x3AC539C6U, 0x3CC33BC4U, 0x3EC13DC2U,
|
||||||
|
0x40BF3FC0U, 0x42BD41BEU, 0x44BB43BCU, 0x46B945BAU, 0x48B747B8U,
|
||||||
|
0x4AB549B6U, 0x4CB34BB4U, 0x4EB14DB2U, 0x50AF4FB0U, 0x52AD51AEU,
|
||||||
|
0x54AB53ACU, 0x56A955AAU, 0x58A757A8U, 0x5AA559A6U, 0x5CA35BA4U,
|
||||||
|
0x5EA15DA2U, 0x609F5FA0U, 0x629D619EU, 0x649B639CU, 0x6699659AU,
|
||||||
|
0x68976798U, 0x6A956996U, 0x6C936B94U, 0x6E916D92U, 0x708F6F90U,
|
||||||
|
0x728D718EU, 0x748B738CU, 0x7689758AU, 0x78877788U, 0x7A857986U,
|
||||||
|
0x7C837B84U, 0x7E817D82U, 0x807F7F80U, 0x827D817EU, 0x847B837CU,
|
||||||
|
0x8679857AU, 0x88778778U, 0x8A758976U, 0x8C738B74U, 0x8E718D72U,
|
||||||
|
0x906F8F70U, 0x926D916EU, 0x946B936CU, 0x9669956AU, 0x98679768U,
|
||||||
|
0x9A659966U, 0x9C639B64U, 0x9E619D62U, 0xA05F9F60U, 0xA25DA15EU,
|
||||||
|
0xA45BA35CU, 0xA659A55AU, 0xA857A758U, 0xAA55A956U, 0xAC53AB54U,
|
||||||
|
0xAE51AD52U, 0xB04FAF50U, 0xB24DB14EU, 0xB44BB34CU, 0xB649B54AU,
|
||||||
|
0xB847B748U, 0xBA45B946U, 0xBC43BB44U, 0xBE41BD42U, 0xC03FBF40U,
|
||||||
|
0xC23DC13EU, 0xC43BC33CU, 0xC639C53AU, 0xC837C738U, 0xCA35C936U,
|
||||||
|
0xCC33CB34U, 0xCE31CD32U, 0xD02FCF30U, 0xD22DD12EU, 0xD42BD32CU,
|
||||||
|
0xD629D52AU, 0xD827D728U, 0xDA25D926U, 0xDC23DB24U, 0xDE21DD22U,
|
||||||
|
0xE01FDF20U, 0xE21DE11EU, 0xE41BE31CU, 0xE619E51AU, 0xE817E718U,
|
||||||
|
0xEA15E916U, 0xEC13EB14U, 0xEE11ED12U, 0xF00FEF10U, 0xF20DF10EU,
|
||||||
|
0xF40BF30CU, 0xF609F50AU, 0xF807F708U, 0xFA05F906U, 0xFC03FB04U,
|
||||||
|
0xFFFFFF00U, 0x00000000U, 0x0000000FU, 0x000000F0U, 0x000000FFU,
|
||||||
|
0x00000F00U, 0x00000F0FU, 0x00000FF0U, 0x00000FFFU, 0x0000F000U,
|
||||||
|
0x0000F00FU, 0x0000F0F0U, 0x0000F0FFU, 0x0000FF00U, 0x0000FF0FU,
|
||||||
|
0x0000FFF0U, 0x0000FFFFU, 0x000F0000U, 0x000F000FU, 0x000F00F0U,
|
||||||
|
0x000F00FFU, 0x000F0F00U, 0x000F0F0FU, 0x000F0FF0U, 0x000F0FFFU,
|
||||||
|
0x000FF000U, 0x000FF00FU, 0x000FF0F0U, 0x000FF0FFU, 0x000FFF00U,
|
||||||
|
0x000FFF0FU, 0x000FFFF0U, 0x000FFFFFU, 0x00F00000U, 0x00F0000FU,
|
||||||
|
0x00F000F0U, 0x00F000FFU, 0x00F00F00U, 0x00F00F0FU, 0x00F00FF0U,
|
||||||
|
0x00F00FFFU, 0x00F0F000U, 0x00F0F00FU, 0x00F0F0F0U, 0x00F0F0FFU,
|
||||||
|
0x00F0FF00U, 0x00F0FF0FU, 0x00F0FFF0U, 0x00F0FFFFU, 0x00FF0000U,
|
||||||
|
0x00FF000FU, 0x00FF00F0U, 0x00FF00FFU, 0x00FF0F00U, 0x00FF0F0FU,
|
||||||
|
0x00FF0FF0U, 0x00FF0FFFU, 0x00FFF000U, 0x00FFF00FU, 0x00FFF0F0U,
|
||||||
|
0x00FFF0FFU, 0x00FFFF00U, 0x00FFFF0FU, 0x00FFFFF0U, 0x00FFFFFFU,
|
||||||
|
0x0F000000U, 0x0F00000FU, 0x0F0000F0U, 0x0F0000FFU, 0x0F000F00U,
|
||||||
|
0x0F000F0FU, 0x0F000FF0U, 0x0F000FFFU, 0x0F00F000U, 0x0F00F00FU,
|
||||||
|
0x0F00F0F0U, 0x0F00F0FFU, 0x0F00FF00U, 0x0F00FF0FU, 0x0F00FFF0U,
|
||||||
|
0x0F00FFFFU, 0x0F0F0000U, 0x0F0F000FU, 0x0F0F00F0U, 0x0F0F00FFU,
|
||||||
|
0x0F0F0F00U, 0x0F0F0F0FU, 0x0F0F0FF0U, 0x0F0F0FFFU, 0x0F0FF000U,
|
||||||
|
0x0F0FF00FU, 0x0F0FF0F0U, 0x0F0FF0FFU, 0x0F0FFF00U, 0x0F0FFF0FU,
|
||||||
|
0x0F0FFFF0U, 0x0F0FFFFFU, 0x0FF00000U, 0x0FF0000FU, 0x0FF000F0U,
|
||||||
|
0x0FF000FFU, 0x0FF00F00U, 0x0FF00F0FU, 0x0FF00FF0U, 0x0FF00FFFU,
|
||||||
|
0x0FF0F000U, 0x0FF0F00FU, 0x0FF0F0F0U, 0x0FF0F0FFU, 0x0FF0FF00U,
|
||||||
|
0x0FF0FF0FU, 0x0FF0FFF0U, 0x0FF0FFFFU, 0x0FFF0000U, 0x0FFF000FU,
|
||||||
|
0x0FFF00F0U, 0x0FFF00FFU, 0x0FFF0F00U, 0x0FFF0F0FU, 0x0FFF0FF0U,
|
||||||
|
0x0FFF0FFFU, 0x0FFFF000U, 0x0FFFF00FU, 0x0FFFF0F0U, 0x0FFFF0FFU,
|
||||||
|
0x0FFFFF00U, 0x0FFFFF0FU, 0x0FFFFFF0U, 0x0FFFFFFFU, 0xF0000000U,
|
||||||
|
0xF000000FU, 0xF00000F0U, 0xF00000FFU, 0xF0000F00U, 0xF0000F0FU,
|
||||||
|
0xF0000FF0U, 0xF0000FFFU, 0xF000F000U, 0xF000F00FU, 0xF000F0F0U,
|
||||||
|
0xF000F0FFU, 0xF000FF00U, 0xF000FF0FU, 0xF000FFF0U, 0xF000FFFFU,
|
||||||
|
0xF00F0000U, 0xF00F000FU, 0xF00F00F0U, 0xF00F00FFU, 0xF00F0F00U,
|
||||||
|
0xF00F0F0FU, 0xF00F0FF0U, 0xF00F0FFFU, 0xF00FF000U, 0xF00FF00FU,
|
||||||
|
0xF00FF0F0U, 0xF00FF0FFU, 0xF00FFF00U, 0xF00FFF0FU, 0xF00FFFF0U,
|
||||||
|
0xF00FFFFFU, 0xF0F00000U, 0xF0F0000FU, 0xF0F000F0U, 0xF0F000FFU,
|
||||||
|
0xF0F00F00U, 0xF0F00F0FU, 0xF0F00FF0U, 0xF0F00FFFU, 0xF0F0F000U,
|
||||||
|
0xF0F0F00FU, 0xF0F0F0F0U, 0xF0F0F0FFU, 0xF0F0FF00U, 0xF0F0FF0FU,
|
||||||
|
0xF0F0FFF0U, 0xF0F0FFFFU, 0xF0FF0000U, 0xF0FF000FU, 0xF0FF00F0U,
|
||||||
|
0xF0FF00FFU, 0xF0FF0F00U, 0xF0FF0F0FU, 0xF0FF0FF0U, 0xF0FF0FFFU,
|
||||||
|
0xF0FFF000U, 0xF0FFF00FU, 0xF0FFF0F0U, 0xF0FFF0FFU, 0xF0FFFF00U,
|
||||||
|
0xF0FFFF0FU, 0xF0FFFFF0U, 0xF0FFFFFFU, 0xFF000000U, 0xFF00000FU,
|
||||||
|
0xFF0000F0U, 0xFF0000FFU, 0xFF000F00U, 0xFF000F0FU, 0xFF000FF0U,
|
||||||
|
0xFF000FFFU, 0xFF00F000U, 0xFF00F00FU, 0xFF00F0F0U, 0xFF00F0FFU,
|
||||||
|
0xFF00FF00U, 0xFF00FF0FU, 0xFF00FFF0U, 0xFF00FFFFU, 0xFF0F0000U,
|
||||||
|
0xFF0F000FU, 0xFF0F00F0U, 0xFF0F00FFU, 0xFF0F0F00U, 0xFF0F0F0FU,
|
||||||
|
0xFF0F0FF0U, 0xFF0F0FFFU, 0xFF0FF000U, 0xFF0FF00FU, 0xFF0FF0F0U,
|
||||||
|
0xFF0FF0FFU, 0xFF0FFF00U, 0xFF0FFF0FU, 0xFF0FFFF0U, 0xFF0FFFFFU,
|
||||||
|
0xFFF00000U, 0xFFF0000FU, 0xFFF000F0U, 0xFFF000FFU, 0xFFF00F00U,
|
||||||
|
0xFFF00F0FU, 0xFFF00FF0U, 0xFFF00FFFU, 0xFFF0F000U, 0xFFF0F00FU,
|
||||||
|
0xFFF0F0F0U, 0xFFF0F0FFU, 0xFFF0FF00U, 0xFFF0FF0FU, 0xFFF0FFF0U,
|
||||||
|
0xFFF0FFFFU, 0xFFFF0000U, 0xFFFF000FU, 0xFFFF00F0U, 0xFFFF00FFU,
|
||||||
|
0xFFFF0F00U, 0xFFFF0F0FU, 0xFFFF0FF0U, 0xFFFF0FFFU, 0xFFFFF000U,
|
||||||
|
0xFFFFF00FU, 0xFFFFF0F0U, 0xFFFFF0FFU, 0xFFFFFF00U, 0xFFFFFF0FU,
|
||||||
|
0xFFFFFFF0U, 0xFFFFFFFFU,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t in2[] = {
|
||||||
|
0xC695AE95U, 0xF77A4EAAU, 0xBF48B982U, 0xC6BA8FCAU, 0xF835626CU,
|
||||||
|
0xE65ACA49U, 0xE835B2AEU, 0xCC187C90U, 0xD41F28CDU, 0xFF65FD16U,
|
||||||
|
0xF7C9FD68U, 0xA98A92BAU, 0xEFE95EACU, 0xCB697C7AU, 0xD1A27AA6U,
|
||||||
|
0xE13183F2U, 0xE34102B4U, 0xE5BF9DA8U, 0xA1A2ECCAU, 0xCD5C4899U,
|
||||||
|
0xBC3B72B2U, 0x955EC4C2U, 0xE5D2A137U, 0xEEBB1F2AU, 0xEFBF29CBU,
|
||||||
|
0xD50B8808U, 0xB4CC3ACFU, 0xCE556261U, 0xCC672FC9U, 0xD2A311C3U,
|
||||||
|
0xC4EF6B80U, 0x92FCDE5EU, 0xCA1D606EU, 0x84382503U, 0xD9B76E28U,
|
||||||
|
0xC252C2DAU, 0xEA92EF4CU, 0xC1ED20D7U, 0x8E6B3F6AU, 0xBEB21819U,
|
||||||
|
0xC1531DEDU, 0x86353CD2U, 0xE83CAAD3U, 0xB13C7C99U, 0xD19EB94CU,
|
||||||
|
0xB9DF2579U, 0x926E008BU, 0xB4DFBC00U, 0x9F9EC322U, 0xB410ED56U,
|
||||||
|
0x823C049AU, 0xDBDA35D4U, 0xC96FB218U, 0xE80EA5D1U, 0xCA9554FEU,
|
||||||
|
0xB92EDBE4U, 0xBD1A2DD9U, 0xFF618FCDU, 0x87843E45U, 0x89815DA3U,
|
||||||
|
0xD204A191U, 0xCC73A9C6U, 0x9C7E3C01U, 0x9C2201FFU, 0xD0ABCEC9U,
|
||||||
|
0xF635AA2AU, 0xDE74C4D9U, 0xBB3EBE15U, 0xB822CB01U, 0xECE00443U,
|
||||||
|
0xF9F0D62FU, 0xF975E8EEU, 0xF3154115U, 0xE22D8102U, 0xAAB26587U,
|
||||||
|
0xC4B3FA61U, 0x9C0CA67CU, 0xBD206613U, 0xF993B662U, 0xBBAB699EU,
|
||||||
|
0xF1315369U, 0xFBCFBAFCU, 0x97859F72U, 0xBAA10581U, 0xE3DE60CDU,
|
||||||
|
0xE21AF471U, 0xF3CFE165U, 0xA0F88EA6U, 0xE17C843EU, 0xFB541FABU,
|
||||||
|
0xAA79EC49U, 0xB38125CFU, 0xC7C7C971U, 0xC6F8284BU, 0xCFA327CEU,
|
||||||
|
0x9873983AU, 0xBD2DD275U, 0xAE17ECA7U, 0xD3B2564FU, 0xF5509D76U,
|
||||||
|
0x9AF7F0EAU, 0xCDA32C7EU, 0xEEC68664U, 0x8E0D31FFU, 0xAFD0AD81U,
|
||||||
|
0x9978EBEBU, 0xD2C12C61U, 0xCBDD53FDU, 0xD69951FEU, 0xCC54E2C3U,
|
||||||
|
0x8788BD9BU, 0xC7CAA567U, 0xC8249DBFU, 0x9F0E5D0DU, 0x826BAAE9U,
|
||||||
|
0xAC02FE8CU, 0x8129517EU, 0xF63B8C4EU, 0xCCFB8D32U, 0xE2A5D5BDU,
|
||||||
|
0xF18FABF9U, 0xF775797CU, 0x9626FB8CU, 0xB957756AU, 0xBE6DA1C7U,
|
||||||
|
0xE5CA235BU, 0xD1CB0DA4U, 0xFB9B743CU, 0x93E21002U, 0xA57D63F4U,
|
||||||
|
0xF0EC11B2U, 0xAEDA00EDU, 0xF3209072U, 0xDFB29816U, 0xBCE732ECU,
|
||||||
|
0xA2F13DF3U, 0xF92B8401U, 0x8FA85F4DU, 0xEECE91F0U, 0xCFC4D600U,
|
||||||
|
0xDBFD4210U, 0xF6574F8BU, 0x978F7B67U, 0xA421DFCFU, 0x9565AC99U,
|
||||||
|
0x99FB2650U, 0xD024DE5BU, 0x968EFE17U, 0x9036B29FU, 0x9D206B8EU,
|
||||||
|
0xF934D3D4U, 0x81C65E98U, 0x9495E50AU, 0x8F5BCF61U, 0xBB1DD403U,
|
||||||
|
0xD30386D1U, 0xF525F2BCU, 0x8CE8E1A7U, 0xCE9EFB0DU, 0x890802BEU,
|
||||||
|
0xB266459BU, 0xBF8B0CBFU, 0xB7E203ABU, 0xA586D60EU, 0x9F3DA4D5U,
|
||||||
|
0xF4C93698U, 0xC8781401U, 0x986928D6U, 0x847195E5U, 0xB746A5F2U,
|
||||||
|
0xE82DFED6U, 0xE06ED7F6U, 0xAD9DF57DU, 0xFFBD7A3EU, 0x8490B7C5U,
|
||||||
|
0xC303A216U, 0x99B8A08EU, 0xD4B59621U, 0xD992A02EU, 0xA9EF532DU,
|
||||||
|
0xF1D601AFU, 0xD2C77402U, 0xABB5B1C6U, 0x866BE6B9U, 0xE2234363U,
|
||||||
|
0xE6D385C9U, 0xD96F6D8AU, 0xD749361FU, 0xF3BC6770U, 0xA80E6897U,
|
||||||
|
0xE05138DEU, 0xA622AD0CU, 0xE7997556U, 0x98333C89U, 0xCBA9831AU,
|
||||||
|
0x86D71A2BU, 0x8CFC7321U, 0x9421971BU, 0x9F404301U, 0x916E0907U,
|
||||||
|
0xCB683D0DU, 0x876E41D8U, 0xF1DCE0FDU, 0xF906328BU, 0x872BBC16U,
|
||||||
|
0xF66D98C2U, 0xBC09D4A1U, 0xA0E45CA4U, 0xCB232EE3U, 0x959C74CFU,
|
||||||
|
0xCAD3AFD2U, 0xBCF93092U, 0xE863E8D2U, 0xF6896198U, 0xC365174BU,
|
||||||
|
0xCA872C35U, 0xDD5CE761U, 0x9CD484D5U, 0xA1D06255U, 0xD1194ED1U,
|
||||||
|
0xC4E2ED6CU, 0x82219B33U, 0xF73BFBDDU, 0xAC7C62C2U, 0x9A54D7BCU,
|
||||||
|
0xC2E57EF7U, 0xB3537CEDU, 0xA7514ADEU, 0xD7071613U, 0xD293BFEFU,
|
||||||
|
0xB8BF53E5U, 0xA26F5320U, 0xDA0201C7U, 0xAA9C34E2U, 0x9B7585ABU,
|
||||||
|
0xE12DBDDDU, 0xA109CDA4U, 0xD77F5A4DU, 0x82121A81U, 0xEC2CFC88U,
|
||||||
|
0xED1BCF1CU, 0xCCE5CA53U, 0xA9262D1AU, 0xD57FB7EEU, 0xC36F2BEBU,
|
||||||
|
0xEC8B4466U, 0xA006E424U, 0xA0CC134CU, 0x895FC93BU, 0xC1D74679U,
|
||||||
|
0xF1E5621EU, 0xCE42B6A8U, 0xC3F8E1ACU, 0xE9215DFBU, 0xFABF196AU,
|
||||||
|
0xDE4DB968U, 0xAC06DCF3U, 0xAE129658U, 0x859F0446U, 0x830DF306U,
|
||||||
|
0x80A65647U, 0xBE5E582BU, 0xA57D4626U, 0xDAA8580EU, 0xE8FA8D0DU,
|
||||||
|
0xC0F2CBD2U, 0xBBD615EBU, 0x8A045AB2U, 0x9872261FU, 0xBDE8306CU,
|
||||||
|
0xF631573AU, 0x858DF53BU, 0x8ACDFAC0U, 0x9F578454U, 0xDB0DAD2AU,
|
||||||
|
0xCE3D26ABU, 0x8BE2C8BAU, 0xFB14914EU, 0xEF0939F8U, 0x954291F6U,
|
||||||
|
0xBCEBD7C7U, 0xE0EE9C16U, 0xE385489EU, 0x80E4B973U, 0xCA0FFA11U,
|
||||||
|
0xDE446208U, 0xDF3272DBU, 0xF616D704U, 0x8C56F860U, 0xE4D17722U,
|
||||||
|
0xF924CA0AU, 0x8CFD4EA7U, 0xA32FCF4DU, 0x9EA21031U, 0xE7A5A6B5U,
|
||||||
|
0x8C2A5C5BU, 0xDF94DC03U, 0xA37BBCA0U, 0x962EB70DU, 0xF8070222U,
|
||||||
|
0xE163ED0DU, 0x8C600E47U, 0xFD94F75DU, 0xEC31E7CDU, 0xABB7929BU,
|
||||||
|
0xD8A2A487U, 0xBA6F0E78U, 0xB79A5B56U, 0xD3B735D5U, 0xA9784870U,
|
||||||
|
0xCCDCED4CU, 0x90A30D9CU, 0x8A66E486U, 0xB06235EAU, 0x9187C70FU,
|
||||||
|
0xD476DE98U, 0x8EA697F2U, 0xF0BA39EBU, 0xCA8DB59CU, 0x9AFD9053U,
|
||||||
|
0xD58BB10DU, 0xC3B27FA7U, 0xA7FADEFAU, 0xF8BB805AU, 0xE2548FD8U,
|
||||||
|
0x8FA085B0U, 0x84E5DCB5U, 0xC1E96BDBU, 0xB31C4250U, 0x9B1493C2U,
|
||||||
|
0xB9F06DFDU, 0x94802F5DU, 0xA774A209U, 0xB785655AU, 0x80B2172AU,
|
||||||
|
0xD32C34A5U, 0x902809E2U, 0xBB2125A3U, 0x8AC68FFBU, 0xE3DF3FB7U,
|
||||||
|
0xE4996E13U, 0xD7A37D47U, 0xF4824D54U, 0xEF00529AU, 0x8805B331U,
|
||||||
|
0x860A1463U, 0xC3773132U, 0x96AC4B23U, 0xF6C44E4EU, 0x8E04E6CEU,
|
||||||
|
0xB1A9DB76U, 0xCC4FFF5BU, 0xD1B76675U, 0xD9A4BA71U, 0xC50B7FB6U,
|
||||||
|
0xB40BF64DU, 0xE9454021U, 0xC9F15C6BU, 0xF5F56228U, 0x9C618271U,
|
||||||
|
0xE505F02EU, 0xAFE5D025U, 0xB0E1B1CFU, 0x8C7A9237U, 0xE76B3580U,
|
||||||
|
0xB193C8F9U, 0xDFA6C6DCU, 0xF7933F62U, 0xECB4EE9CU, 0xEA6D56D7U,
|
||||||
|
0xDB727F19U, 0xD14E5CB0U, 0xC210D41EU, 0xCFF4CC6DU, 0xC04EAF4AU,
|
||||||
|
0xCA16874FU, 0xD5FEE0D1U, 0x83C5E07CU, 0xE0C2D273U, 0xCCC32F1FU,
|
||||||
|
0x91CAC74AU, 0x926CADE9U, 0x99132E7BU, 0xE3822DC0U, 0xEC11685AU,
|
||||||
|
0xDE1EAE31U, 0x978E240DU, 0xD556A87BU, 0xA8100A9CU, 0x8D838636U,
|
||||||
|
0xF1B82AEDU, 0x8D15FACAU, 0xBD69565BU, 0xA299DCBCU, 0x99908D02U,
|
||||||
|
0xA4D48BDBU, 0xD42DA5B5U, 0xF93753DEU, 0x9C67CB3DU, 0xC0E29452U,
|
||||||
|
0xE3A4AAB6U, 0xF7DA4A57U, 0x9230F102U, 0xA5B57ED4U, 0xC7CF16C4U,
|
||||||
|
0xD27FA04CU, 0xEFCC0624U, 0x9DCDF795U, 0xD64580C8U, 0xD08ED897U,
|
||||||
|
0xEA9126B5U, 0xE8104812U, 0xE2FB8680U, 0x83A45530U, 0xCB9275D2U,
|
||||||
|
0xCF0CEEDBU, 0xE1C30361U, 0xE32099E0U, 0xA4639756U, 0x89D30DFDU,
|
||||||
|
0xF0A42016U, 0x961BC243U, 0x96E908C8U, 0xAE0D7671U, 0xB8B59EFFU,
|
||||||
|
0xB07995CAU, 0xD2E2024DU, 0x8CE344B5U, 0xA9B0E9A8U, 0xEF49CD8AU,
|
||||||
|
0xCDC5D907U, 0x8D55945EU, 0xE72417E1U, 0xDFF6CA09U, 0xB30B1333U,
|
||||||
|
0xAEF32EA6U, 0xB2766A55U, 0xA2D71957U, 0xCCC1263BU, 0x88BBEB1DU,
|
||||||
|
0xF365F1EEU, 0xB7524CF0U, 0xF0CC332FU, 0xD661786EU, 0xBAF6A220U,
|
||||||
|
0xBC5EA902U, 0xA56E6749U, 0x9CB9A581U, 0x9F7F42E2U, 0xC9D1FEA0U,
|
||||||
|
0xA68CB37FU, 0x902362F8U, 0xDFEDC0E3U, 0xBD75BC47U, 0xBE30D969U,
|
||||||
|
0x98A35FE3U, 0xEDEF5211U, 0x9112DBB6U, 0xA586A498U, 0x97A03BB9U,
|
||||||
|
0x805CA941U, 0xF34C7D9FU, 0xA4F5D018U, 0xE780C122U, 0xD34347A8U,
|
||||||
|
0xD800E34BU, 0x9673EFC8U, 0x85B9B1FDU, 0xFAD7FCA2U, 0xE3351604U,
|
||||||
|
0x8E759D1AU, 0xEE3DEE90U, 0x9A8762F4U, 0xFF41D049U, 0xC49F66FEU,
|
||||||
|
0xD57E0515U, 0xBBA0794BU, 0xEA0DCE48U, 0xF237AA96U, 0xDB1FBC2DU,
|
||||||
|
0xB3DFCCE8U, 0x98C45E15U, 0xEB431F25U, 0x93CD8DCBU, 0xD63A1A5CU,
|
||||||
|
0xA973F88FU, 0xAC70EDAEU, 0xC4296C6DU, 0xBA86D445U, 0xD1F79246U,
|
||||||
|
0xDBC9A827U, 0xBAE37D86U, 0xC5440FE5U, 0x80BF783FU, 0xA2643EA9U,
|
||||||
|
0x9887578DU, 0xD8C05B8AU, 0xB8D82E71U, 0x9E41098AU, 0xD398582CU,
|
||||||
|
0x9C0D4475U, 0xACB6A6A4U, 0xC1D646BCU, 0xB694A76AU, 0xABF876EEU,
|
||||||
|
0x8675ADBAU, 0x8C12AC7FU, 0xE798F039U, 0xF0837C02U, 0xFE4A5715U,
|
||||||
|
0xC2B8AC67U, 0xA46348EAU,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t in3[] = {
|
||||||
|
0x970EB52BU, 0xADFBCB8CU, 0xB830D6B6U, 0xED48CF87U, 0xD76FC41BU,
|
||||||
|
0xE4A1C464U, 0xB1723BF5U, 0x91F69861U, 0xB69956ABU, 0x8D3BE41CU,
|
||||||
|
0xCCDA15E7U, 0xFBDD6690U, 0x8DFB5C5BU, 0xEF3E5490U, 0x9464BE1EU,
|
||||||
|
0xE6BBB7E5U, 0xA8168302U, 0xB2A5C7A8U, 0xBA541011U, 0xC423C777U,
|
||||||
|
0xDF5C6E4DU, 0xFC2A56CDU, 0xFAB86EE1U, 0x8B54E53BU, 0x82A00487U,
|
||||||
|
0x86CB1B60U, 0xF2EDD574U, 0xF323808AU, 0x85157276U, 0xB5A681DBU,
|
||||||
|
0x9786C974U, 0x9C2427A1U, 0xE3A24D68U, 0xCFB7A02AU, 0x896CF728U,
|
||||||
|
0xBB121183U, 0xB459648FU, 0xBADF331DU, 0xCD08A9E4U, 0xEAF2BB3AU,
|
||||||
|
0xC81B1739U, 0x99E2BFCCU, 0xE6D021CAU, 0xD6167394U, 0x8921145CU,
|
||||||
|
0xFB34DFE8U, 0xBCD22B79U, 0xB137975EU, 0xADDAA791U, 0xF7263B8AU,
|
||||||
|
0xF55B5ED6U, 0x8D3715DEU, 0xF3509257U, 0xF013CDB7U, 0x988BFB19U,
|
||||||
|
0xF5F096DFU, 0xF6DEE918U, 0x8B79D08DU, 0xE9141769U, 0xFBF45B8EU,
|
||||||
|
0xC1205269U, 0x809AE0DDU, 0x9818832FU, 0xA4C29FD1U, 0xD0528108U,
|
||||||
|
0xA1857A57U, 0xDFD4B154U, 0x84ABE597U, 0xDC64AD75U, 0xACDD5B39U,
|
||||||
|
0xEF9EA0D1U, 0xA47FC4AEU, 0xC6C01B05U, 0xD66EC29BU, 0xFA963843U,
|
||||||
|
0xCFE12F61U, 0xD1A3A284U, 0xB76863BCU, 0x8118C6C0U, 0xFF7E4A15U,
|
||||||
|
0xAE8E9F47U, 0xF6742596U, 0x8CB55FF3U, 0xA1DF319EU, 0xE687F34DU,
|
||||||
|
0xA5415B0CU, 0x97CFC87DU, 0xDD66DC65U, 0xB0BB2B99U, 0x80E3DFE6U,
|
||||||
|
0xD95B37F3U, 0xF1DB7E02U, 0x817EC0C4U, 0xF173BB22U, 0x969E1DD3U,
|
||||||
|
0xD1D141CCU, 0x92F9357AU, 0xF672CF28U, 0xD67D2763U, 0xEF5DE2EFU,
|
||||||
|
0xA3502A61U, 0xC61BC834U, 0x93DDA79DU, 0xEA104566U, 0x9C8A8ACFU,
|
||||||
|
0x8E73DFE0U, 0xB9F174C7U, 0xEE2E2D53U, 0xC5DC439DU, 0xBB0A3B87U,
|
||||||
|
0xEDAC7768U, 0xF46AE2E4U, 0xB17E611DU, 0xFA61D75BU, 0x964A1482U,
|
||||||
|
0x9806546BU, 0x9FA33267U, 0xAE19DD00U, 0xF56D30D0U, 0xD05E5E01U,
|
||||||
|
0xAEFDBCE6U, 0xCEC868C4U, 0xC239DC03U, 0xB07C7DAAU, 0xC03C23E6U,
|
||||||
|
0xD8D7F9D7U, 0x824DBF76U, 0xD3355960U, 0xCF4AC8FFU, 0xD8CAE6D9U,
|
||||||
|
0xC2933C4FU, 0xF29AF360U, 0x9EE6AF0DU, 0xD670E3EDU, 0xDCAB38C6U,
|
||||||
|
0xBB7139DDU, 0xE4E4C3CDU, 0x969CAD8DU, 0xA99F6730U, 0xAAC1076AU,
|
||||||
|
0xD1A6E915U, 0x974BDE99U, 0x9F2BEA4EU, 0x83254A32U, 0x91ADB5F4U,
|
||||||
|
0xB575FED1U, 0x9B2B9E9DU, 0xB150E85CU, 0xE38FDBD1U, 0x9098CF6EU,
|
||||||
|
0x81AF465DU, 0x928D98B7U, 0xDF613832U, 0xC3E92260U, 0xC30A1662U,
|
||||||
|
0x9F9D5C18U, 0x9CC11C37U, 0xC557D5D8U, 0xF2D2B579U, 0xEC0BE536U,
|
||||||
|
0x9E22BCB2U, 0xB565F1C8U, 0xDEA6D896U, 0xBD096BBFU, 0x8BD6D5B5U,
|
||||||
|
0xBB52115CU, 0xF87AA59CU, 0xF0BB9983U, 0xD1EEBEEAU, 0xA21A0CCDU,
|
||||||
|
0x9B7CA0EDU, 0xA395A7FFU, 0xB965EB66U, 0xBAA88B3CU, 0xA6BAF231U,
|
||||||
|
0xCB13A15AU, 0xF01E8A0DU, 0xC1E690CFU, 0xFC6489B6U, 0xD3AE65DEU,
|
||||||
|
0xD27F603DU, 0xFE13D013U, 0xE63BFE95U, 0xB1E0986FU, 0xC1FCF274U,
|
||||||
|
0xA94614F7U, 0xD17DF487U, 0xDEBE0EABU, 0xEE9DEAD0U, 0xC450AA00U,
|
||||||
|
0xCAC9F3E2U, 0x8CC0A782U, 0xF9B69BC9U, 0xA970CC78U, 0xC9CA1341U,
|
||||||
|
0x858D717EU, 0xE4C2DDD5U, 0xC244B8DEU, 0xF6490B01U, 0xB6B19CBFU,
|
||||||
|
0xE45EC5ABU, 0x91C5ABEFU, 0xDA4744BEU, 0x9DC4B111U, 0xCC6E372BU,
|
||||||
|
0x810236EFU, 0xE8D8526BU, 0xBC8CC138U, 0xC2E8C7BEU, 0xE53CDC22U,
|
||||||
|
0x903B2716U, 0x956827FBU, 0xE350AC35U, 0xF67725ABU, 0xC748C06AU,
|
||||||
|
0xA54D9EA9U, 0x9FBD3AA3U, 0x98C6B4F2U, 0x840BAD55U, 0x8E5B2573U,
|
||||||
|
0xDD175EF2U, 0xCED5A137U, 0x9B1BCCF5U, 0xD6CDFABBU, 0xF8466DAFU,
|
||||||
|
0xE4E5E036U, 0xDC5B6C3AU, 0xDD094B84U, 0xA72A9914U, 0xD2A4773BU,
|
||||||
|
0x93BAE843U, 0x8B895EBFU, 0xE46A232AU, 0xEE022D01U, 0xA94E0FD0U,
|
||||||
|
0xB0D85A55U, 0xEF0463F1U, 0x9226623CU, 0xED651B8DU, 0xB1ED2BAFU,
|
||||||
|
0xF7633E5EU, 0xFDA042A3U, 0xC75553ABU, 0xDAB3EA93U, 0xF417684FU,
|
||||||
|
0x8E9E1415U, 0x8001893DU, 0x93D4A2F2U, 0xA764C907U, 0x840D3692U,
|
||||||
|
0xA22FC865U, 0x847C27FAU, 0xD2E2D7C9U, 0xBD4B955AU, 0xDB4A22B5U,
|
||||||
|
0xCB294578U, 0xA2317590U, 0xB7A58EEFU, 0xA83290FDU, 0xC95C0EA5U,
|
||||||
|
0x8A4A062BU, 0xBBED7940U, 0xD4E56D64U, 0xEEB42955U, 0xA9EFA642U,
|
||||||
|
0xFE337D35U, 0x9F8C83ABU, 0x98F40A33U, 0x9059DF71U, 0x8CF19F38U,
|
||||||
|
0xCAE135E2U, 0x87BD1DCFU, 0x8A91E1DCU, 0x9236898DU, 0xE2710862U,
|
||||||
|
0xFEA94A2BU, 0xA0D49DA3U, 0xE272919FU, 0x927DED1DU, 0xC83966AAU,
|
||||||
|
0xE67FC831U, 0xB4ADB582U, 0xCCB58EA4U, 0xB9629FFAU, 0xF1F94ADCU,
|
||||||
|
0xA7FFB15AU, 0x848BE573U, 0x942AC06CU, 0xDFA54049U, 0xACBE7670U,
|
||||||
|
0xDD86CF11U, 0xE9EF4674U, 0xE8ABEFB0U, 0xB26C3C76U, 0xD8A36FCAU,
|
||||||
|
0x929B95F2U, 0xB09FB9ABU, 0xF82FF375U, 0xAB8FA025U, 0xC0F9991CU,
|
||||||
|
0x852192ADU, 0xF670D608U, 0xC8B6B6EBU, 0x8FB37489U, 0x88A75F95U,
|
||||||
|
0xAB27BF4DU, 0x8E5CBEB4U, 0xA97BFD38U, 0x8D9A50EDU, 0xA0DAABD1U,
|
||||||
|
0xF1B563E3U, 0xF41A191EU, 0xD5886153U, 0xBE6AF287U, 0xAD7CB919U,
|
||||||
|
0xC781AC2FU, 0xE66AA3E1U, 0xB2089E8CU, 0xDBAC6C9CU, 0xC60FE42BU,
|
||||||
|
0xDEC714FCU, 0xB9333BADU, 0xAFFF2A9FU, 0xC77304ACU, 0xEB9F7823U,
|
||||||
|
0x88A29A69U, 0xDA0E9A9FU, 0x9C3F31CEU, 0x80D28DDEU, 0x859E3AC4U,
|
||||||
|
0xDD38CAEAU, 0x85F4208CU, 0xFC0F10CCU, 0xA5EF81D5U, 0x95A79515U,
|
||||||
|
0x84B67062U, 0xD1174123U, 0xA40453CAU, 0xAE326D9AU, 0xDEB19210U,
|
||||||
|
0xC4DEFF9BU, 0x9FE7D17DU, 0xD2CBAB2EU, 0x9A6760EFU, 0xDE52C405U,
|
||||||
|
0x80486447U, 0xE1E90D1EU, 0xC4BD67E6U, 0xB25102D3U, 0xBD9579BAU,
|
||||||
|
0x8ACD4C11U, 0x911817CFU, 0xF6C8B568U, 0xBACC76B1U, 0xD88B1C7CU,
|
||||||
|
0xE2682D8BU, 0xC36F111AU, 0xB299B71BU, 0xFEA75F5AU, 0xC4419EF9U,
|
||||||
|
0xB837F1DFU, 0xDBE02A44U, 0xCA35BF85U, 0xB44702ACU, 0x81CFAC1AU,
|
||||||
|
0xDFDD549AU, 0xB8FD730EU, 0xD2E6ED3DU, 0x83E1A864U, 0xE72FE0A8U,
|
||||||
|
0xB1987F4DU, 0xC8C0A800U, 0x8717B226U, 0x84642A7BU, 0xE32808EFU,
|
||||||
|
0xE56A762BU, 0x84AC8EC3U, 0xC511160DU, 0xAA27DE11U, 0xB6FD9196U,
|
||||||
|
0x82A68FC8U, 0xB4F52A23U, 0xC815A966U, 0xF96F4530U, 0xEFC1A0D4U,
|
||||||
|
0xA0A0C5E2U, 0xDBD772BBU, 0xB330B1EEU, 0xD33A7CFDU, 0xDA7ED215U,
|
||||||
|
0xF77250E7U, 0x8B726EDCU, 0xB65EFC5AU, 0xC1A8106CU, 0xBFB97188U,
|
||||||
|
0xB82EA874U, 0xA1856507U, 0xF8B6E496U, 0x8B1595B1U, 0xA5670D6BU,
|
||||||
|
0xDFE6C53FU, 0xBCAE14FEU, 0xEE27B56BU, 0xE6FE7765U, 0xC1123F79U,
|
||||||
|
0xD14FBE5AU, 0xCC68ED90U, 0xC5BECE3CU, 0x9660D468U, 0xF690CBA1U,
|
||||||
|
0xFCBC5FD3U, 0x99076430U, 0xAB85F5C4U, 0xC4D20939U, 0x9276A960U,
|
||||||
|
0x9B479698U, 0xE572CF1BU, 0xEE4E1C1BU, 0xCE784887U, 0xB8AD4C18U,
|
||||||
|
0xC8CCEE31U, 0xC5EA996EU, 0xC41FBAF4U, 0xFF2BEA8BU, 0x8792A9DBU,
|
||||||
|
0x83D92C7DU, 0xB75A92FFU, 0xA9180EE2U, 0xFC901113U, 0xC27028B0U,
|
||||||
|
0xCE7F1C4DU, 0xDC76D652U, 0xFF1E3DAEU, 0xBCA6D1B9U, 0xC3754DB7U,
|
||||||
|
0xC0307D27U, 0x8DF69013U, 0x8FDE3B47U, 0x85EF4B64U, 0xA457647BU,
|
||||||
|
0x866F06E9U, 0x82ABAB37U, 0xBD5EC8ABU, 0xB1F4FCADU, 0xC77DB470U,
|
||||||
|
0xCFD5720BU, 0xCD3C9346U, 0xACF0838BU, 0xBE238E27U, 0x9BB4DBCDU,
|
||||||
|
0xE59DCFA3U, 0x86F07C58U, 0xE19F753BU, 0xA9BD8A97U, 0x861C66E3U,
|
||||||
|
0xE9321F16U, 0xAD96B714U, 0xBD76F9E2U, 0x924A2DF8U, 0xAA26C828U,
|
||||||
|
0xFFE72292U, 0xE0C94A46U, 0x869D9E7AU, 0xFF056040U, 0x9D701BFFU,
|
||||||
|
0xCA12EC32U, 0xBF35DD67U, 0xAB66AC12U, 0xD9F12779U, 0xC52528CBU,
|
||||||
|
0xCFBE108EU, 0xE0602E62U, 0xC7D0D402U, 0x8D1CD939U, 0x92552B10U,
|
||||||
|
0x8F4E8872U, 0xDCF24B45U, 0xDF91BE56U, 0xBC3F0BFDU, 0x9B15D96CU,
|
||||||
|
0xFB469A23U, 0xA1DCDBA0U, 0xA20655C4U, 0xDCE60F5EU, 0xCB9A6638U,
|
||||||
|
0xA822BCA7U, 0xC6182E75U, 0xF9311D4CU, 0xE599B689U, 0xD8625C6DU,
|
||||||
|
0xA357E574U, 0xE580D91BU, 0xB92BA6B3U, 0xA9F583EFU, 0xE486395BU,
|
||||||
|
0xD69BC2B2U, 0xF4087021U, 0xA3BC16C2U, 0x82026EC5U, 0xCDF9979AU,
|
||||||
|
0xE8E13F8EU, 0xD1C07F53U, 0xAE59C5FDU, 0xB0B21390U, 0xDEDD588CU,
|
||||||
|
0xC0AEF10DU, 0xC0009C03U, 0xBBCFA3D1U, 0xA040AF63U, 0xFC3FA800U,
|
||||||
|
0xD6E57D3DU, 0x9B874986U,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t hist_short_a[] = {
|
||||||
|
0x4C7BU, 0xBF75U, 0xA1D6U, 0xE10FU, 0xB22CU, 0xD048U, 0x73DBU, 0xA572U,
|
||||||
|
0x2CFDU, 0xBB19U, 0xE622U, 0xA707U, 0xAB8CU, 0x91ACU, 0xD4C7U, 0xA486U,
|
||||||
|
0x92D3U, 0x9997U, 0x58BBU, 0xA0A6U, 0x7C90U, 0xC9CCU, 0x2CB0U, 0xE2F2U,
|
||||||
|
0x0C80U, 0x8CE4U, 0x6C56U, 0xCA22U, 0x6B48U, 0xBAEBU, 0x15ACU, 0xA49EU,
|
||||||
|
0x6D68U, 0x9109U, 0xA33FU, 0xEE92U, 0x792FU, 0xB314U, 0x323EU, 0xC44EU,
|
||||||
|
0xCC2DU, 0xCCBEU, 0x8C6EU, 0xBCC2U, 0xAF2DU, 0xE8CBU, 0xD84EU, 0x9094U,
|
||||||
|
0xF4ECU, 0xD29FU, 0x8AC2U, 0xF5A1U, 0x77E8U, 0xC5EBU, 0xE822U, 0xC69BU,
|
||||||
|
0xD516U, 0xE18EU, 0xDD6DU, 0xD869U, 0xE411U, 0x9826U, 0x2191U, 0xA104U,
|
||||||
|
0x7F44U, 0xB979U, 0x963DU, 0xE86FU, 0x956CU, 0xC676U, 0xAC41U, 0xF492U,
|
||||||
|
0x7C5FU, 0x8F77U, 0x40F8U, 0xD823U, 0x8108U, 0x9919U, 0x0F32U, 0xA90FU,
|
||||||
|
0x99B4U, 0xF8C9U, 0xFD99U, 0xE2E5U, 0x3BE2U, 0x8C01U, 0xA634U, 0x85ADU,
|
||||||
|
0x69EFU, 0xAD08U, 0xA72AU, 0xC6ECU, 0xBBE0U, 0xAA4BU, 0xD757U, 0xBE11U,
|
||||||
|
0x4A69U, 0xB57FU, 0x3510U, 0xDD60U, 0x0995U, 0x8260U, 0x1696U, 0x823EU,
|
||||||
|
0xC17EU, 0x9A22U, 0xB8C2U, 0xEB2BU, 0xEEE5U, 0x92D2U, 0xB66AU, 0xECC2U,
|
||||||
|
0x4385U, 0xE0CDU, 0x66CDU, 0xD8BEU, 0x9E8DU, 0xB35EU, 0x189BU, 0xC25CU,
|
||||||
|
0x443AU, 0xB128U, 0x829EU, 0xCB85U, 0x3A2CU, 0xE360U, 0xC37EU, 0xEAA1U,
|
||||||
|
0x18DBU, 0xB3F5U, 0xCF99U, 0xA9D6U, 0x6FC0U, 0xDF34U, 0x953AU, 0xC36CU,
|
||||||
|
0x1091U, 0x81FAU, 0xF0C8U, 0xF84DU, 0xA46CU, 0xEC7BU, 0xAA45U, 0xFAC3U,
|
||||||
|
0xEE61U, 0xDB33U, 0xE04FU, 0xF87CU, 0x5079U, 0x8071U, 0x5851U, 0x883CU,
|
||||||
|
0x8779U, 0xBF69U, 0x0C5AU, 0xAABDU, 0x2FA8U, 0xC64EU, 0xD1E3U, 0xF4E8U,
|
||||||
|
0x416AU, 0x881DU, 0x393EU, 0xC8AEU, 0xE879U, 0xF726U, 0x02E8U, 0xA240U,
|
||||||
|
0xF200U, 0xB3D9U, 0xD75EU, 0x89F9U, 0xB952U, 0x8F02U, 0x3585U, 0x94A7U,
|
||||||
|
0x3E2BU, 0xE2B8U, 0x57DFU, 0xC261U, 0x4E20U, 0xD703U, 0x8266U, 0x93E0U,
|
||||||
|
0xDA7DU, 0x8DE6U, 0x884DU, 0xBA63U, 0x45E4U, 0xFE82U, 0xF358U, 0xC1DBU,
|
||||||
|
0x57E6U, 0xE43AU, 0xB5A4U, 0xDDB6U, 0x8892U, 0x8548U, 0x6877U, 0xE634U,
|
||||||
|
0xA66DU, 0xD604U, 0x2CFFU, 0xF1C4U, 0x12BDU, 0xE0F8U, 0x94CEU, 0xB138U,
|
||||||
|
0x0D4EU, 0xEA41U, 0x6336U, 0xE169U, 0xED1FU, 0xB974U, 0x94C7U, 0xA9AAU,
|
||||||
|
0x6F90U, 0x8C26U, 0x1CC8U, 0xFFC3U, 0x66AAU, 0x9E93U, 0xB0FAU, 0x9443U,
|
||||||
|
0x5606U, 0xC871U, 0x4F24U, 0x95BAU, 0xB3E2U, 0xB683U, 0x4806U, 0xFC4BU,
|
||||||
|
0x2682U, 0x9FB4U, 0x6D35U, 0xC586U, 0x7D8CU, 0x90F2U, 0x64AEU, 0x826CU,
|
||||||
|
0xC514U, 0x87E7U, 0xCBACU, 0xE7F5U, 0xE714U, 0x964CU, 0x9F92U, 0x95CEU,
|
||||||
|
0x53F9U, 0xA259U, 0x2CF8U, 0x94CFU, 0x92EAU, 0xD7AAU, 0xABDFU, 0x8693U,
|
||||||
|
0xE29DU, 0xF285U, 0x1B7DU, 0xDCF3U, 0x1457U, 0xECC8U, 0x890AU, 0xC88AU,
|
||||||
|
0x487CU, 0xCEB7U, 0x2714U, 0xCDC0U, 0x1DD8U, 0xF9C3U, 0x55CAU, 0xB8F8U,
|
||||||
|
0x8A4AU, 0xAF29U, 0x0AF8U, 0xB338U, 0xEA91U, 0xE2A2U, 0xF9DBU, 0xBB4FU,
|
||||||
|
0x27C0U, 0xB2FBU, 0x513CU, 0x8136U, 0xAAD5U, 0xCF93U, 0x7DC6U, 0xFB6CU,
|
||||||
|
0xA060U, 0x96F0U, 0x5EB8U, 0x8617U, 0xC5CCU, 0xF7B7U, 0xC6E2U, 0xB6A4U,
|
||||||
|
0xCBEDU, 0xCB9DU, 0x4358U, 0x88AAU, 0x2B90U, 0xB911U, 0x9101U, 0xD385U,
|
||||||
|
0x0F05U, 0xF0A0U, 0x12A4U, 0xCF5EU, 0x3093U, 0xE954U, 0x62FEU, 0x92F9U,
|
||||||
|
0x3F9DU, 0xE42DU, 0xC37EU, 0xC0FEU, 0x0EDEU, 0x998DU, 0x223AU, 0xD6B3U,
|
||||||
|
0xDEFBU, 0x9DF1U, 0x2335U, 0x8655U, 0xAB44U, 0x9F3DU, 0x2777U, 0xECA9U,
|
||||||
|
0x4A49U, 0xD415U, 0xC91CU, 0x9900U, 0x7D41U, 0xA5A1U, 0xD493U, 0x833EU,
|
||||||
|
0xD414U, 0xCC38U, 0x67D2U, 0x8844U, 0xCE6EU, 0xBE8EU, 0xFBD4U, 0xFF33U,
|
||||||
|
0xB90EU, 0x897AU, 0x7944U, 0x8E22U, 0x799AU, 0xFAA0U, 0x596EU, 0xA06BU,
|
||||||
|
0xD7FCU, 0x9439U, 0x3F67U, 0xF258U, 0x2051U, 0xD710U, 0xA3E9U, 0xDFD7U,
|
||||||
|
0x82BFU, 0xFB02U, 0x4BE1U, 0x9021U, 0x34EAU, 0xB35DU, 0x91C4U, 0xEBA2U,
|
||||||
|
0x5E86U, 0xDF7FU, 0x657EU, 0x9CB1U, 0xF4C3U, 0xFE9BU, 0x9E23U, 0xC3ACU,
|
||||||
|
0x28FCU, 0xDDB0U, 0x03A1U, 0x9829U, 0xC05DU, 0x9A5FU, 0x07F7U, 0xFBA2U,
|
||||||
|
0x26D6U, 0x9E7EU, 0x6BA1U, 0xB99DU, 0x2F6EU, 0xE84BU, 0x711FU, 0xF293U,
|
||||||
|
0x34BDU, 0xD29EU, 0xACAFU, 0x8DECU, 0x45B2U, 0xF5D2U, 0x08D2U, 0x9ED7U,
|
||||||
|
0x1481U, 0x9631U, 0x1421U, 0xB461U, 0x04A6U, 0x9E0BU, 0xCD90U, 0x9FABU,
|
||||||
|
0x8D65U, 0xC283U, 0x7E41U, 0x98ABU, 0x26FEU, 0xC017U, 0x6561U, 0xD6BDU,
|
||||||
|
0xBDA8U, 0x8B03U, 0x474FU, 0x9727U, 0x094AU, 0xB695U, 0x4067U, 0x8606U,
|
||||||
|
0x9331U, 0xA748U, 0x3E34U, 0xE9F2U, 0xD22CU, 0xF1A8U, 0xF1B7U, 0x86C7U,
|
||||||
|
0xA3B2U, 0x86A3U, 0xC6EFU, 0xF044U, 0x8FDAU, 0xCA74U, 0xCCAEU, 0xE453U,
|
||||||
|
0xCA90U, 0x886DU, 0x5037U, 0xE4D4U, 0xD4A5U, 0xDFF5U, 0xF166U, 0xA6EBU,
|
||||||
|
0xBBD8U, 0x9E71U, 0x0413U, 0xC841U, 0x6285U, 0x997FU, 0xF095U, 0xF10FU,
|
||||||
|
0xB0C2U, 0xD62DU, 0xA837U, 0x8F51U, 0xF967U, 0x8FE6U, 0xC544U, 0xEC5EU,
|
||||||
|
0xBC58U, 0xC3B2U, 0xFE0EU, 0xADF1U, 0x92D4U, 0x8C0AU, 0x49BDU, 0x8636U,
|
||||||
|
0x7C4FU, 0xC69DU, 0xB9D2U, 0xCC21U, 0xAF1EU, 0xDCF3U, 0x39F7U, 0xD1A1U,
|
||||||
|
0x0122U, 0xE349U, 0xB868U, 0x9388U, 0x7A5EU, 0xD7A7U, 0x9453U, 0x8A91U,
|
||||||
|
0xF69DU, 0xFD7AU, 0x4C8AU, 0xC950U, 0x860AU, 0x9159U, 0x9A4FU, 0x841EU,
|
||||||
|
0x1379U, 0xB995U, 0x15E4U, 0xDBCEU, 0x66FEU, 0xE872U, 0xDE09U, 0xC202U,
|
||||||
|
0x661BU, 0xC0A2U, 0x3BA3U, 0xC868U, 0xCF6FU, 0xE8EEU, 0x21F3U, 0xDF14U,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t hist_int_a[] = {
|
||||||
|
0x9E1C83A1U, 0xF8EBD301U, 0xF86D58E4U, 0xE9B6E9D9U, 0xA10E8FA8U,
|
||||||
|
0xBE858759U, 0xE2E80725U, 0x86A84631U, 0x96E7E3C7U, 0x863FEC9AU,
|
||||||
|
0xEC291F4CU, 0xD0138A7AU, 0xB0357089U, 0xD0AF58A7U, 0xA6AF4D2DU,
|
||||||
|
0xA43DE0AAU, 0xF46B6F6AU, 0xA8B1BBF2U, 0xF2377844U, 0xDD4CAEF8U,
|
||||||
|
0xFA723B45U, 0xA0913E41U, 0x8DFEC288U, 0xD94F93D1U, 0xE1402F4EU,
|
||||||
|
0xCDFF5E8BU, 0x951F37A3U, 0x8180DEB1U, 0xCA3F068CU, 0xEC04B4E0U,
|
||||||
|
0x9D082837U, 0xE85B8A2DU, 0xE4F087E2U, 0x9575811CU, 0xD2127406U,
|
||||||
|
0x85FF178AU, 0xD3FB0875U, 0xB4FA7B2BU, 0x8CA75DBCU, 0xEAE2EC3CU,
|
||||||
|
0xBB3A67C5U, 0xF8D07D08U, 0xBAF676B7U, 0xEB6FD84EU, 0xC97FD5B0U,
|
||||||
|
0xE1A5C3E4U, 0x8FADB8F8U, 0xBDEB451AU, 0x8A577FD6U, 0x81E5313DU,
|
||||||
|
0x9B37F412U, 0x84C9BB1BU, 0xA2766F7EU, 0xA936B69AU, 0xDE194EECU,
|
||||||
|
0x83B69ECDU, 0xF7361526U, 0xF338868FU, 0x85377D7EU, 0xC1751BB2U,
|
||||||
|
0xDF3D3B70U, 0xA23FA5B6U, 0xA9D0A5DFU, 0xC42DC352U, 0xB7B526D2U,
|
||||||
|
0xFBE319E5U, 0xCA2CDADCU, 0x8BB02F47U, 0xB0DD9510U, 0xD6D43898U,
|
||||||
|
0xF6931B84U, 0xEC17FCD6U, 0xCFA4B5A1U, 0xB189923BU, 0xD787D524U,
|
||||||
|
0x99248B51U, 0x932F561FU, 0xE7358E1DU, 0xD70FD06BU, 0x9D86D5F5U,
|
||||||
|
0xE91ABF5AU, 0xF247C47DU, 0xA2509110U, 0x8B912ED8U, 0x9B7E7B17U,
|
||||||
|
0x8069DFFCU, 0x8F47CDA5U, 0x92B4903DU, 0xF3A2668CU, 0x947F4B24U,
|
||||||
|
0xD429ABEFU, 0xD2DFA1FCU, 0xB6BEF0DAU, 0xFDFA51CEU, 0x970D654EU,
|
||||||
|
0xEE7417ACU, 0xF9DD6BB3U, 0xE13A402AU, 0xFA2446F3U, 0xAABB00C4U,
|
||||||
|
0xB80E78C3U, 0xF0B76277U, 0x96D2FD9AU, 0x87B32E64U, 0xA240F4B2U,
|
||||||
|
0xEE5AD2BEU, 0xA0D7B9B5U, 0xB5704AD1U, 0xD59060DBU, 0xF7E78A20U,
|
||||||
|
0xD2F720C6U, 0xBEAB2035U, 0xEA2F4E9DU, 0xF547B1D6U, 0xCA3C4F0EU,
|
||||||
|
0x85ADC9B4U, 0xF5B191D3U, 0xD9841CB3U, 0x986259F2U, 0xE953F85FU,
|
||||||
|
0xEE0367D7U, 0xEC8C05E1U, 0xBC339A5BU, 0xA4C258B1U, 0xEA8657B0U,
|
||||||
|
0xD340FFA9U, 0x9336705DU, 0xE463C363U, 0xB47B3FD3U, 0x8D5AB751U,
|
||||||
|
0x8F1EC427U, 0xEC89B896U, 0xFE1219C8U, 0xA5F1C1C1U, 0xF43CE6FAU,
|
||||||
|
0xA0530E7BU, 0x944C9480U, 0x9514A0AFU, 0xD5C3594CU, 0xE9DCF55BU,
|
||||||
|
0x8CFC2ACFU, 0xA8BA7A13U, 0xA8881591U, 0xF72B796CU, 0x9E022BE9U,
|
||||||
|
0xF2C4649FU, 0xFCD94321U, 0x93B3BDBCU, 0xCC488152U, 0x953B9D13U,
|
||||||
|
0xFD07B61BU, 0xBA4BE92AU, 0x81C7A2F4U, 0xB93B5076U, 0xDF0E41DBU,
|
||||||
|
0xEC4DFAA4U, 0x8C7C501FU, 0xF244B239U, 0xD0B1BE08U, 0xC0F78FF3U,
|
||||||
|
0xFF9F698AU, 0xDFD0822FU, 0xAD814889U, 0xFDB18352U, 0x85C243F1U,
|
||||||
|
0xA1BE2F84U, 0x9E0491CDU, 0x9A0ED871U, 0xB6D2D033U, 0xF3C7EB1AU,
|
||||||
|
0x83EBCDCCU, 0xC3CEFB03U, 0x9C82652DU, 0xAC73E35DU, 0xBAFA746FU,
|
||||||
|
0xBA849116U, 0x9F3847FCU, 0xB7D3B790U, 0xCE384ED3U, 0xEB80C94FU,
|
||||||
|
0xCD0F54A3U, 0xCB4004EEU, 0xA5CCB279U, 0xCED6F798U, 0x847B5565U,
|
||||||
|
0x84DAF454U, 0xBB24F23CU, 0x90F7A584U, 0xF71FA68DU, 0x8BD6B044U,
|
||||||
|
0xD1EF3577U, 0xF6BF1017U, 0xEBA73274U, 0xFF707E01U, 0xF470936AU,
|
||||||
|
0xF1697665U, 0xA12EAD85U, 0x92752537U, 0x8B784ED6U, 0xD8017DB8U,
|
||||||
|
0x863D1051U, 0x8F641CA2U, 0x9BD078BBU, 0xA2BF757EU, 0xBBD80000U,
|
||||||
|
0xD6CAED2BU, 0xDD440695U, 0xDB1047FCU, 0x8E9EA4BBU, 0xAB7C5568U,
|
||||||
|
0xC691114BU, 0xDBADF95FU, 0xF6BC5A56U, 0xEC5DC3C4U, 0xAA84F0F7U,
|
||||||
|
0xFB37AFBBU, 0xF138B819U, 0xE5A9E333U, 0x8C2F5540U, 0xE8585EA6U,
|
||||||
|
0xF1809378U, 0xDE1E8AB7U, 0xDF176EBEU, 0xDD27C5ECU, 0xDD8F08B8U,
|
||||||
|
0xD3880228U, 0xCE913C51U, 0xFEBDB63DU, 0xE5FD275FU, 0xDA098B27U,
|
||||||
|
0xD6BF33F6U, 0xEC3A37B1U, 0xE96DA7C9U, 0xF28FACB1U, 0x8EF9AD2FU,
|
||||||
|
0xA545A7C9U, 0xC95A99DCU, 0xEC3DB3C4U, 0x8055EFC6U, 0xD7F93E98U,
|
||||||
|
0x97BA092CU, 0xC6E70111U, 0xB3A737F7U, 0x8E766383U, 0xB344C4D6U,
|
||||||
|
0xDE2C28EEU, 0x89AE133EU, 0xA47D7CEFU, 0xC3D60C21U, 0x95DD687EU,
|
||||||
|
0x8CD5DB95U, 0xB5569F99U, 0xF3FBF336U, 0xEBED4A53U, 0x927E6585U,
|
||||||
|
0xD18AFBEEU,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t hist_short_b[] = {
|
||||||
|
0x0ECAU, 0x9213U, 0x170CU, 0xB702U, 0xFDE4U, 0x9FE7U, 0xB8CEU, 0xDAFBU,
|
||||||
|
0xFF02U, 0xC818U, 0x778DU, 0xC795U, 0x17A9U, 0xBEE0U, 0x1A40U, 0x999FU,
|
||||||
|
0x6C62U, 0xE1EDU, 0x53F5U, 0xACEAU, 0x1193U, 0x8797U, 0xB8FFU, 0xDCA6U,
|
||||||
|
0xBE42U, 0xA956U, 0x7F08U, 0xEC6BU, 0x872EU, 0xA4ECU, 0x07C9U, 0xEEA6U,
|
||||||
|
0xBFDBU, 0xB59AU, 0x7E76U, 0xF87CU, 0x6605U, 0xFF8BU, 0x81DBU, 0xAB12U,
|
||||||
|
0xC4B7U, 0xAFECU, 0xE954U, 0xBD18U, 0xFB4FU, 0x832FU, 0xFE3AU, 0xD34BU,
|
||||||
|
0xC8D6U, 0xC2D4U, 0x8AB0U, 0xD398U, 0x2824U, 0xC067U, 0xBA00U, 0x8A4AU,
|
||||||
|
0x55DAU, 0xC568U, 0x896EU, 0xF350U, 0x551EU, 0xED07U, 0x64A5U, 0xD77BU,
|
||||||
|
0xA07AU, 0xAA52U, 0x5302U, 0x8CEFU, 0x1D73U, 0xB277U, 0x9F7CU, 0xF26BU,
|
||||||
|
0xCA8FU, 0xD484U, 0x351DU, 0xF157U, 0xB9BDU, 0x8C0AU, 0x36F1U, 0xB672U,
|
||||||
|
0x8912U, 0x9E41U, 0xCB50U, 0x93A1U, 0xEFF0U, 0x9318U, 0x4755U, 0xC798U,
|
||||||
|
0x4A58U, 0x800DU, 0x771FU, 0xB805U, 0x4F1EU, 0xB63EU, 0x0A34U, 0xB5A8U,
|
||||||
|
0xF595U, 0xB081U, 0xB524U, 0xB5C9U, 0x8C0FU, 0xE0BAU, 0xBA4CU, 0xE06EU,
|
||||||
|
0x9E78U, 0xF2E2U, 0x875EU, 0xE3EAU, 0xB887U, 0xB3BAU, 0x674FU, 0xB5B7U,
|
||||||
|
0x120EU, 0xB783U, 0xE0ABU, 0xF421U, 0x214FU, 0xC002U, 0x67E9U, 0xFCEBU,
|
||||||
|
0x6A1AU, 0xE772U, 0x766DU, 0xAD09U, 0xCC8EU, 0xD466U, 0x0A94U, 0x91C5U,
|
||||||
|
0xC96FU, 0xB9F8U, 0xEA01U, 0x86DDU, 0xAA11U, 0x8430U, 0x93FFU, 0x8E7DU,
|
||||||
|
0x1F1EU, 0xF835U, 0x63CEU, 0x903BU, 0xCAF0U, 0xC4EFU, 0xA831U, 0x9676U,
|
||||||
|
0x2F1EU, 0xA3DDU, 0xBAE1U, 0xD808U, 0xEF86U, 0xDE0EU, 0x7976U, 0xA3EAU,
|
||||||
|
0x3200U, 0x900EU, 0x3EA4U, 0x944DU, 0x83AAU, 0xD992U, 0x2795U, 0xC090U,
|
||||||
|
0xF3C8U, 0xCA16U, 0x0FB9U, 0xBA4DU, 0xE1E2U, 0xA0FEU, 0x9241U, 0xBCF9U,
|
||||||
|
0x9717U, 0x9E37U, 0x9A69U, 0xD4B9U, 0xF990U, 0xF2B0U, 0xA926U, 0xD5BAU,
|
||||||
|
0x7B14U, 0xC8DBU, 0x1ADFU, 0xB2B3U, 0x110FU, 0xD2A6U, 0xE52EU, 0xB04DU,
|
||||||
|
0x914DU, 0xDFBCU, 0xDD9DU, 0xA70CU, 0xEFC3U, 0xC212U, 0x5ABCU, 0x99B5U,
|
||||||
|
0xC79EU, 0xADEAU, 0x99D4U, 0xC643U, 0xEEBBU, 0xA832U, 0xE6BDU, 0xA61FU,
|
||||||
|
0xFDA2U, 0xD67EU, 0xB9ACU, 0xED22U, 0x8EEEU, 0xBC96U, 0x2CC0U, 0xFA5CU,
|
||||||
|
0x748DU, 0xC52BU, 0x7E74U, 0x9AA5U, 0xA636U, 0x9E46U, 0xA68DU, 0xD539U,
|
||||||
|
0xBD18U, 0xAEF2U, 0x29E1U, 0xF7D9U, 0xCE22U, 0x95C9U, 0xB0E1U, 0xF909U,
|
||||||
|
0x399AU, 0xB226U, 0xB004U, 0xB6C8U, 0x4322U, 0xB603U, 0xD0B2U, 0xD05DU,
|
||||||
|
0x4A6DU, 0x8B82U, 0x3CB2U, 0xA8B4U, 0x79D8U, 0xA618U, 0xC582U, 0xD45DU,
|
||||||
|
0x5791U, 0xDB67U, 0x8AE7U, 0xF8BEU, 0xAAB0U, 0x84ABU, 0xE8DEU, 0xBB23U,
|
||||||
|
0x6884U, 0x9FCBU, 0x9A73U, 0xC6BEU, 0x439BU, 0xD4D9U, 0x3022U, 0xCDB6U,
|
||||||
|
0x3447U, 0x8D02U, 0x3256U, 0xFD0CU, 0x16DFU, 0xF3D6U, 0x31E9U, 0xE381U,
|
||||||
|
0xEC02U, 0xEA2EU, 0xA5CDU, 0xB06CU, 0x5EA9U, 0xDDDDU, 0x608FU, 0xAF5AU,
|
||||||
|
0x2441U, 0xCB12U, 0x04E0U, 0xFC24U, 0x071CU, 0x8494U, 0xE15AU, 0xFA04U,
|
||||||
|
0x2EC1U, 0xF3FDU, 0xD53FU, 0x9A5DU, 0x923BU, 0xF30EU, 0x685BU, 0xA623U,
|
||||||
|
0x8543U, 0xD126U, 0xD55DU, 0xA911U, 0x390DU, 0xF681U, 0xCFB1U, 0xDCA8U,
|
||||||
|
0x120FU, 0xD1C6U, 0xB2E5U, 0x9C99U, 0x9533U, 0xB106U, 0x69A0U, 0xAD2DU,
|
||||||
|
0x3DCCU, 0x9558U, 0x3FE3U, 0xB5B2U, 0x527FU, 0xE851U, 0xA650U, 0xB523U,
|
||||||
|
0xDA57U, 0xFC70U, 0x961AU, 0xBD2AU, 0xD673U, 0x82D9U, 0x0E9EU, 0x8973U,
|
||||||
|
0xC870U, 0xBA36U, 0xED52U, 0xF6AFU, 0x4088U, 0xECF4U, 0xB473U, 0xA465U,
|
||||||
|
0x9320U, 0xA71CU, 0x9F31U, 0xCAD1U, 0x1502U, 0xD3C0U, 0xB761U, 0xF22EU,
|
||||||
|
0xA411U, 0xC6F5U, 0x1C1FU, 0xD854U, 0x98BBU, 0xEC33U, 0xD2D2U, 0xBAF2U,
|
||||||
|
0xF15EU, 0xF2B1U, 0x2AF6U, 0xDF42U, 0x3B2EU, 0xE116U, 0x76A1U, 0xC3D8U,
|
||||||
|
0x0053U, 0x8854U, 0x743BU, 0xD797U, 0x4652U, 0xA081U, 0x1262U, 0xDA1AU,
|
||||||
|
0x2721U, 0xF431U, 0xDB85U, 0xD187U, 0x7C03U, 0x8747U, 0x64EDU, 0x8989U,
|
||||||
|
0x1B69U, 0x873AU, 0xCE82U, 0xEF98U, 0x0B3EU, 0xBEADU, 0xF5C0U, 0x83AAU,
|
||||||
|
0x649CU, 0xACC3U, 0xE1B1U, 0xC186U, 0x045EU, 0x8D1EU, 0x2D0CU, 0xE6FAU,
|
||||||
|
0xCF03U, 0xB836U, 0x44E6U, 0xFA12U, 0xE17FU, 0x8B5FU, 0x6223U, 0xDF53U,
|
||||||
|
0xE418U, 0xC4E3U, 0xF682U, 0xDF1FU, 0x1985U, 0xD182U, 0x8829U, 0x8BD9U,
|
||||||
|
0x12A1U, 0xB774U, 0xB240U, 0xBDB5U, 0x5AFCU, 0xC6CCU, 0x03FFU, 0xAA26U,
|
||||||
|
0xDD37U, 0x9CF7U, 0x962AU, 0xA7E2U, 0x7AA0U, 0xEDFEU, 0xDD8AU, 0xA54BU,
|
||||||
|
0x0A65U, 0xFF7AU, 0xC0F3U, 0x8E7FU, 0xEFEDU, 0xFF65U, 0x3186U, 0xF3ABU,
|
||||||
|
0x9C78U, 0xE007U, 0x6BF0U, 0x86ADU, 0x9674U, 0xFD34U, 0xB7E1U, 0xE741U,
|
||||||
|
0x3A72U, 0xF646U, 0xA1B2U, 0xBBE1U, 0xADA1U, 0xEAECU, 0x9F0EU, 0xA309U,
|
||||||
|
0x8363U, 0xFD68U, 0xB200U, 0xF80AU, 0xCC1AU, 0x8A03U, 0x5266U, 0xB59FU,
|
||||||
|
0xF6E6U, 0xF21CU, 0xAD9AU, 0x9563U, 0xB48AU, 0x94F2U, 0xDAFEU, 0xB700U,
|
||||||
|
0xA41CU, 0xF483U, 0xCE0FU, 0xE674U, 0x6328U, 0xC2DAU, 0xB6BDU, 0xABF7U,
|
||||||
|
0x804FU, 0xA42AU, 0xBE24U, 0x89A6U, 0xBABCU, 0xD61DU, 0x5D86U, 0xC122U,
|
||||||
|
0x544EU, 0xB189U, 0x355CU, 0xC41CU, 0x3B11U, 0xE66EU, 0x5EB3U, 0xB103U,
|
||||||
|
0xF64FU, 0xD29BU, 0x2AFEU, 0xE5D4U, 0x903AU, 0xA4AEU, 0x92C8U, 0xB2A3U,
|
||||||
|
0x96EEU, 0xEC81U, 0x26AEU, 0xA1E3U, 0x4AA9U, 0x99E5U, 0xD160U, 0xE2C7U,
|
||||||
|
0xC860U, 0xDDC4U, 0xF84BU, 0x84D1U, 0x706EU, 0x85D1U, 0x4BC3U, 0xDB2DU,
|
||||||
|
0xAA4BU, 0xFCDCU, 0x3C88U, 0x8FD5U, 0x9E29U, 0x90CCU, 0xA131U, 0xEEF9U,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t hist_int_b[] = {
|
||||||
|
0x90A93FB7U, 0x826E31F4U, 0xD0241288U, 0xE6D6F079U, 0x91BFDA2CU,
|
||||||
|
0xE00B0BF0U, 0xD335B5BDU, 0xD5729684U, 0x8DFD09FEU, 0xDF404891U,
|
||||||
|
0xDBA8E042U, 0xD49A864DU, 0xAB620264U, 0xB89C8F60U, 0xA63BC044U,
|
||||||
|
0x8EAB0386U, 0xCC2547C9U, 0xFDE33AA2U, 0x993C97D9U, 0xC9A03E66U,
|
||||||
|
0xC733872DU, 0xAA961DE3U, 0xCDBED8B5U, 0x80C89AA6U, 0x866433C7U,
|
||||||
|
0xB6313FB3U, 0xC2CB78B0U, 0xC70699E2U, 0xFE997B57U, 0xABBA481FU,
|
||||||
|
0xA61ABBD5U, 0x8F42BB0EU, 0xAE287A14U, 0xF63ECE5DU, 0xF619AB87U,
|
||||||
|
0xBFE85440U, 0xD649DA4DU, 0xC94F6145U, 0x955AEAC4U, 0xE446E44BU,
|
||||||
|
0xA88FA9D6U, 0xF103CB06U, 0xB8E16A98U, 0xD3F1AC3AU, 0xA9A05A67U,
|
||||||
|
0xDF1D2ADCU, 0xE29CAFC0U, 0xF5C5A230U, 0xDD00657FU, 0xFBD94799U,
|
||||||
|
0xBF65E096U, 0xA433ECACU, 0xA66F657CU, 0x8D24B94BU, 0xA4FC8752U,
|
||||||
|
0xACD39943U, 0xC355F8FFU, 0xE7C80002U, 0xF3DA3325U, 0xC1EF7456U,
|
||||||
|
0x93824822U, 0x99F4EEFAU, 0xD1322F64U, 0xC1AAC236U, 0x9033BD58U,
|
||||||
|
0xC74BDAEBU, 0x81931676U, 0xE67D97A5U, 0x909B3C30U, 0x96EE013AU,
|
||||||
|
0xCAC47BF1U, 0xB92AE607U, 0x87F1CC41U, 0x83A5E689U, 0x8D1C9241U,
|
||||||
|
0xB19226A8U, 0xE2C31166U, 0xEFB94202U, 0xA757C8D8U, 0xBFC376E5U,
|
||||||
|
0xEB92899BU, 0xE6BDA96EU, 0xE3F76391U, 0x9201EF18U, 0xF3E262B9U,
|
||||||
|
0x88F3EAE3U, 0xBED5885BU, 0xB7385BB8U, 0xF0BBEAE6U, 0xB2AFBB81U,
|
||||||
|
0xF927D00EU, 0x843E3308U, 0xCCA4AA7BU, 0xCA59FF72U, 0xC5E8F53EU,
|
||||||
|
0xDCD867D3U, 0x91A5DA5EU, 0xC77C0BB4U, 0xC355FF79U, 0xA241168EU,
|
||||||
|
0xDE6A0CEEU, 0x8E1A7B6AU, 0xDB6BFC95U, 0xE65BD92FU, 0x91C061F3U,
|
||||||
|
0xE8888ED7U, 0x97EDFFD7U, 0xF4837359U, 0xD841D0D9U, 0xBF45C8AFU,
|
||||||
|
0xB446EA3EU, 0xC3D45A74U, 0xA603721DU, 0x983E4DCFU, 0xD5D6498CU,
|
||||||
|
0x99E5D4D7U, 0xA13238B3U, 0x94ABD1E8U, 0xD11E308FU, 0x91EE2399U,
|
||||||
|
0xC75B8D69U, 0xCA46009EU, 0x962C56A1U, 0x940037E4U, 0x94A00010U,
|
||||||
|
0xDC154BDFU, 0xF0D89FB8U, 0xA645DA6EU, 0xA3915793U, 0xB42E9F31U,
|
||||||
|
0xC886F0FDU, 0x81FB6481U, 0xC2491A9BU, 0xA3F2ED92U, 0xE8573DB1U,
|
||||||
|
0xD4097C8EU, 0x8C7B7C69U, 0x80453D88U, 0xC88CEFE8U, 0xE4BD4D42U,
|
||||||
|
0xBF8B0638U, 0xFCD3DA26U, 0xA891A7B7U, 0xE58E7855U, 0x951227F6U,
|
||||||
|
0xFE67F143U, 0xFF744D2CU, 0xB64460A9U, 0x9313C32BU, 0xD0927DBCU,
|
||||||
|
0xC8328442U, 0xDA6F5094U, 0x9AD87E5AU, 0xDE5EDAE3U, 0xEE6F8879U,
|
||||||
|
0xAF787E6AU, 0xBA7426C2U, 0xDF482831U, 0xD5BE58D9U, 0xDE057E55U,
|
||||||
|
0x9376C762U, 0x9E4549D6U, 0xE000E2D6U, 0xD5BFE1FDU, 0xC2383768U,
|
||||||
|
0xC8582087U, 0xA9C95E8BU, 0xCEB3B3D2U, 0xC89D5E10U, 0xF2564E73U,
|
||||||
|
0xB3710114U, 0x88286448U, 0xEF2A289AU, 0xDC02A8CBU, 0xEDB6DC9DU,
|
||||||
|
0x843C5090U, 0xDA6A9A0FU, 0xED2B29CAU, 0xBA80B139U, 0xED7E5D3AU,
|
||||||
|
0xBDBDA786U, 0x82B3357BU, 0xC7EDADCFU, 0xD89625E0U, 0xE112105EU,
|
||||||
|
0xB65D3648U, 0x880EA44AU, 0x9B863720U, 0x95A55E79U, 0xDDCCFD23U,
|
||||||
|
0xF98BB575U, 0xA91C25DBU, 0xFC1246F9U, 0xD98C984BU, 0xFEDC07D8U,
|
||||||
|
0xBE4A7E62U, 0xA1E4B8D3U, 0xA8A56663U, 0x8CFE3234U, 0xEA8216E3U,
|
||||||
|
0x9AFBB4D7U, 0xC06F3348U, 0xF2AA7B2BU, 0x8A25DD71U, 0x9C71DC14U,
|
||||||
|
0xE06157C8U, 0x8E622E01U, 0xF6DC7623U, 0xCD8C8192U, 0xC8E2DF3AU,
|
||||||
|
0xE45AD35DU, 0x8B4A2918U, 0xCB9614B5U, 0xAC48812CU, 0xE3E04EF8U,
|
||||||
|
0xACA82513U, 0xE2A5B774U, 0xEBEEF343U, 0xC82E5C33U, 0xF84B15EDU,
|
||||||
|
0xC9BBF066U, 0xC1BA11A8U, 0xA1673BC8U, 0xC5CE3760U, 0x9B46A9F3U,
|
||||||
|
0xA04343A0U, 0x8418B5C2U, 0xBD2B62C6U, 0xC8E8AA04U, 0x9116E7F6U,
|
||||||
|
0xA7AD79A9U, 0xE3E45EDBU, 0xD1861B3EU, 0x9A57F4D4U, 0xEE0A3C4CU,
|
||||||
|
0xEDF7F752U, 0xFAB94C9DU, 0xFC6C6A4DU, 0xE4D46D75U, 0xC845CE2FU,
|
||||||
|
0xC54F4987U, 0xC92F40D3U, 0xD38FF748U, 0x90E55E3CU, 0xF577C1FFU,
|
||||||
|
0xB7704640U, 0xBD8D834FU, 0xD81D7974U, 0xA35F3983U, 0x85BBDF82U,
|
||||||
|
0xD0688F61U, 0xED1B29EAU, 0xC775F12AU, 0xF1CFCB2AU, 0xB2E9614AU,
|
||||||
|
0xE2BC9B1DU,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t hist_short_c[] = {
|
||||||
|
0xE1B7U, 0x88CEU, 0x414CU, 0xAA7CU, 0x7B31U, 0xB012U, 0xC76FU, 0xBF67U,
|
||||||
|
0xB688U, 0xF69FU, 0xB07DU, 0xEB31U, 0x1618U, 0xB055U, 0x14F8U, 0x846AU,
|
||||||
|
0xCCAAU, 0xA7ACU, 0x4BB7U, 0xD3AFU, 0x75B4U, 0x8132U, 0xD541U, 0xCE0BU,
|
||||||
|
0x8339U, 0xCD85U, 0x8CB2U, 0x807EU, 0xC9B5U, 0xEA68U, 0x6A85U, 0xC64DU,
|
||||||
|
0xB903U, 0xC362U, 0xD9C2U, 0x8FB7U, 0x79CCU, 0x9F44U, 0xE6F6U, 0xB9A4U,
|
||||||
|
0xED8AU, 0xC50FU, 0x8126U, 0xB56AU, 0x9BB6U, 0xEAECU, 0xCE6BU, 0x80A1U,
|
||||||
|
0xADE6U, 0xF0D5U, 0x4AE4U, 0x8C00U, 0x31F6U, 0x95B5U, 0x5631U, 0xF56CU,
|
||||||
|
0xBEA1U, 0x829AU, 0x1FA6U, 0xA260U, 0xA7ABU, 0x91BBU, 0xA058U, 0x8B69U,
|
||||||
|
0x60F2U, 0xCCDCU, 0x22DCU, 0xC1CEU, 0x67C7U, 0xCAD1U, 0x177AU, 0xC37CU,
|
||||||
|
0xD35AU, 0xACFFU, 0x7DE0U, 0xFB26U, 0x2C72U, 0xC7E6U, 0xA004U, 0xD4ACU,
|
||||||
|
0xC997U, 0xCED5U, 0xA226U, 0xC918U, 0x7546U, 0xA2B8U, 0x4CD0U, 0x9C5BU,
|
||||||
|
0x2ED8U, 0xC997U, 0x3EFBU, 0x8D21U, 0xB755U, 0xE2A8U, 0xE7DCU, 0x8CF9U,
|
||||||
|
0x18BDU, 0x9CD9U, 0x3121U, 0x81EDU, 0xCED2U, 0xC69EU, 0x0648U, 0xE1E9U,
|
||||||
|
0xB247U, 0xB757U, 0x6A88U, 0xB18BU, 0xD4B3U, 0xE28AU, 0x602EU, 0xA82DU,
|
||||||
|
0xB56CU, 0xBD8BU, 0x06A9U, 0xF840U, 0xB65FU, 0x9D99U, 0x740EU, 0xC026U,
|
||||||
|
0x264FU, 0x9AA0U, 0x5E0AU, 0xAF55U, 0x1466U, 0xCB90U, 0x8741U, 0xE77CU,
|
||||||
|
0x80E7U, 0xF123U, 0x7C2EU, 0x9661U, 0x9EBCU, 0xAAF8U, 0x5441U, 0x9E23U,
|
||||||
|
0xFA0EU, 0x9187U, 0xCB2EU, 0xF2DEU, 0xF445U, 0xF2CFU, 0xC3A5U, 0xE05DU,
|
||||||
|
0x6D55U, 0xBBF7U, 0x698BU, 0x9588U, 0x1075U, 0xFCB9U, 0x9C2DU, 0x858EU,
|
||||||
|
0xA886U, 0xA2A9U, 0xC7CAU, 0xDF61U, 0x8409U, 0x9288U, 0xC144U, 0xBF82U,
|
||||||
|
0xF8EBU, 0xE14EU, 0x52DBU, 0xD927U, 0xC78CU, 0xA16BU, 0xAB32U, 0x98A6U,
|
||||||
|
0xBD64U, 0x8AB2U, 0x9C3FU, 0x83F6U, 0x0B60U, 0xC0D4U, 0x72D0U, 0xC83EU,
|
||||||
|
0xA2E8U, 0xFC36U, 0xC1BFU, 0xDE6DU, 0xE6DEU, 0x8864U, 0xC937U, 0x96D6U,
|
||||||
|
0x1FCAU, 0x8DC3U, 0xFB45U, 0xD3F4U, 0x5078U, 0xFE53U, 0xA0B1U, 0xFEE6U,
|
||||||
|
0x7773U, 0xEA56U, 0xEF34U, 0xA94BU, 0xF4F2U, 0x9D09U, 0x7181U, 0xFBDEU,
|
||||||
|
0xBA63U, 0x9C2AU, 0xE937U, 0x8FD9U, 0x3526U, 0xDC3CU, 0x27B8U, 0xD822U,
|
||||||
|
0x52C3U, 0xA562U, 0x459BU, 0xD8F5U, 0xC3E5U, 0xDDB0U, 0xFB49U, 0xC80BU,
|
||||||
|
0x0D65U, 0xB857U, 0x47EFU, 0xF039U, 0xBC8DU, 0x878EU, 0x0650U, 0x99A6U,
|
||||||
|
0x9ACAU, 0xC960U, 0x8419U, 0xA8FAU, 0xB182U, 0xB24CU, 0x582EU, 0xD413U,
|
||||||
|
0x2058U, 0xACF1U, 0xBCE3U, 0xF320U, 0xCAFFU, 0x9C51U, 0xC340U, 0xA927U,
|
||||||
|
0x7EA2U, 0xD18EU, 0xB1DDU, 0xA4B6U, 0x8C77U, 0xBFFEU, 0x9E6CU, 0xDF51U,
|
||||||
|
0xAD22U, 0xF8ABU, 0xDCF0U, 0xBE51U, 0x3F1DU, 0xDE38U, 0x2495U, 0xE302U,
|
||||||
|
0xCC24U, 0xE79DU, 0x340FU, 0xFB42U, 0x9616U, 0xDEE0U, 0x8687U, 0x83C8U,
|
||||||
|
0x1D47U, 0x8B1CU, 0xCB3CU, 0xBB1CU, 0xAE3FU, 0xDBEAU, 0x700AU, 0xB07EU,
|
||||||
|
0x10D7U, 0x9412U, 0x7225U, 0xB99BU, 0x6B53U, 0xF88AU, 0x1E3CU, 0xCC69U,
|
||||||
|
0xBA14U, 0xA9D4U, 0x27E1U, 0x8019U, 0x248CU, 0xE60FU, 0x54DEU, 0xF335U,
|
||||||
|
0xABFAU, 0xA913U, 0xD60FU, 0x985BU, 0xAD0DU, 0xC748U, 0xCC53U, 0xD604U,
|
||||||
|
0x92F2U, 0x8B7CU, 0x780CU, 0xE39AU, 0x8F93U, 0xFF2CU, 0x1194U, 0xDD0BU,
|
||||||
|
0x29E9U, 0x8851U, 0x1C0BU, 0xBF2BU, 0xB001U, 0xBC5CU, 0xD70CU, 0x80FCU,
|
||||||
|
0xF8FBU, 0xFD7CU, 0xEF1EU, 0x9A94U, 0xFBA1U, 0xE3FEU, 0xC51FU, 0xE51AU,
|
||||||
|
0x232EU, 0x95D7U, 0x91B8U, 0xC2DFU, 0x4BA7U, 0xE8E3U, 0x4075U, 0xA0F3U,
|
||||||
|
0x5CF4U, 0xFDFCU, 0xF9E6U, 0xC4CDU, 0xB07FU, 0xD171U, 0x6DCCU, 0x920EU,
|
||||||
|
0x6C0BU, 0xFE69U, 0x1BD2U, 0xC9FCU, 0x8C08U, 0xDE77U, 0x261FU, 0xA83EU,
|
||||||
|
0x43B3U, 0xCA15U, 0xB095U, 0xC486U, 0x7AFEU, 0x9B73U, 0xEFAEU, 0xF328U,
|
||||||
|
0x86A4U, 0xDCE2U, 0x280BU, 0xE2BCU, 0xBC01U, 0xC92DU, 0x1996U, 0xE85FU,
|
||||||
|
0xA017U, 0xC656U, 0x4B94U, 0xC85AU, 0x2B2AU, 0xC56AU, 0xCA00U, 0xCEA7U,
|
||||||
|
0x679FU, 0x8785U, 0xDB2BU, 0x81C6U, 0xA10CU, 0xCFA4U, 0x609AU, 0x8502U,
|
||||||
|
0xCA4AU, 0x9C5BU, 0x9CAEU, 0xB3A3U, 0x25BAU, 0xEA1DU, 0xED78U, 0xB232U,
|
||||||
|
0x2E66U, 0xF683U, 0x7161U, 0xD300U, 0x2DEDU, 0xD326U, 0x8B5AU, 0xF47FU,
|
||||||
|
0x6B47U, 0x97CEU, 0xDE6CU, 0xA497U, 0xF926U, 0x868DU, 0xD753U, 0x9637U,
|
||||||
|
0xFA3EU, 0xEE93U, 0x852FU, 0xE505U, 0xFD72U, 0xBE75U, 0x3DF2U, 0xB8A9U,
|
||||||
|
0x35C4U, 0xA98CU, 0x7870U, 0xD9E9U, 0x2DA0U, 0xABD2U, 0xBC68U, 0x866EU,
|
||||||
|
0xA07BU, 0xBCA5U, 0xE9A1U, 0xF4FFU, 0xD5FEU, 0xEECDU, 0x4092U, 0x82FCU,
|
||||||
|
0x3535U, 0xBD5AU, 0x0128U, 0xB438U, 0x0A93U, 0xD1A4U, 0x9CD5U, 0xC4DFU,
|
||||||
|
0xDC54U, 0xB5FEU, 0xAB9FU, 0xA148U, 0xFD6FU, 0xC9E1U, 0xA69EU, 0xD25AU,
|
||||||
|
0x484DU, 0xD4ECU, 0x2329U, 0xB3FFU, 0x9416U, 0x848DU, 0x76B3U, 0xCB6FU,
|
||||||
|
0x948AU, 0x86FFU, 0xC203U, 0xD7B3U, 0x020EU, 0xBFEFU, 0xFFD2U, 0x9ECDU,
|
||||||
|
0xA06FU, 0xFC4BU, 0xFB34U, 0xC67CU, 0xD725U, 0xB505U, 0x9AADU, 0xEADFU,
|
||||||
|
0x8063U, 0xAB82U, 0xD497U, 0xF37BU, 0xD89FU, 0xA388U, 0xB627U, 0xD50EU,
|
||||||
|
0x4D08U, 0xCD65U, 0x063FU, 0xCF5BU, 0x728FU, 0xDB7DU, 0xED83U, 0x8A0AU,
|
||||||
|
0xEFE0U, 0xC45AU, 0x488DU, 0xCA4BU, 0x2E16U, 0x8D07U, 0x2516U, 0x81B5U,
|
||||||
|
0x49B6U, 0xFE83U, 0x38A9U, 0xDEABU, 0xC1EBU, 0xC694U, 0x260AU, 0xB482U,
|
||||||
|
0xE448U, 0xFFF3U, 0xBF5AU, 0x9076U, 0xCCA8U, 0x86DCU, 0x2C96U, 0xD4E0U,
|
||||||
|
0xE284U, 0xC475U, 0x60BEU, 0x8B6AU, 0xA349U, 0xA04FU, 0x770EU, 0xCB75U,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t hist_int_c[] = {
|
||||||
|
0xA538EA22U, 0xA5BF52B3U, 0xA5FA7C30U, 0x99BC8E3EU, 0x8C3420C2U,
|
||||||
|
0xE8D4DF58U, 0xC5B444FBU, 0xB05EA112U, 0xF27B9D7CU, 0x9BD1FFB7U,
|
||||||
|
0xF180FE98U, 0xA404F1CAU, 0xDFEE3514U, 0xD7EF39A9U, 0xD508507DU,
|
||||||
|
0xB28A2B63U, 0xBDC364A7U, 0xF9B6E0B7U, 0xE52DBE2BU, 0xAA44FB95U,
|
||||||
|
0x9B9A0765U, 0xFF1308D5U, 0x8D0CCCF5U, 0xF95ECFC5U, 0x83E50120U,
|
||||||
|
0x92DE3D63U, 0xD48C1B88U, 0x80C1AB6BU, 0xA2B379ECU, 0xE558B9B2U,
|
||||||
|
0xEFBB4C9CU, 0xC7EC640EU, 0x8B180C65U, 0x95B5C8CCU, 0xE1A8F24DU,
|
||||||
|
0x974C2D28U, 0xFE8AA824U, 0xA75D3748U, 0xC7AACE3AU, 0xF10645A0U,
|
||||||
|
0xC32F3700U, 0xB92BCCD2U, 0x950B376AU, 0xA31D6C14U, 0x911B067CU,
|
||||||
|
0xEA1387E8U, 0xD5A79777U, 0xCEDE6B23U, 0xE3CA689FU, 0xBAD555A3U,
|
||||||
|
0xF92366B9U, 0xFF647005U, 0xB9E85E78U, 0x863033AEU, 0xF8C33FCAU,
|
||||||
|
0xBDCD5F98U, 0x990E7112U, 0xCD4F5B53U, 0xBE8F0B03U, 0xBBC1EAFEU,
|
||||||
|
0xB2A81505U, 0xAE4A579FU, 0x83AE4F0CU, 0xBDC0216AU, 0xC400206CU,
|
||||||
|
0xE5574159U, 0xD50C4E92U, 0xC28AC890U, 0x8CB478A2U, 0x9CB71CCCU,
|
||||||
|
0xB3910E31U, 0xCFE3AFA2U, 0xD5E2E99FU, 0xC89C459BU, 0xF3011BB6U,
|
||||||
|
0xE6FDF01BU, 0xB2AFCD83U, 0xC8A8B32DU, 0xB5DC5B3EU, 0x967A3623U,
|
||||||
|
0x837E08D0U, 0xAEFFC1F7U, 0x95DEA628U, 0xBD666748U, 0xB52FF5A6U,
|
||||||
|
0x8EA1E5F2U, 0xFB33C6E0U, 0xCE3E66B8U, 0xDBF14145U, 0xB9C2D1E3U,
|
||||||
|
0x8A0051B6U, 0x8E99564AU, 0xE80D2983U, 0x8DAEA0C2U, 0xCC5977B5U,
|
||||||
|
0xAC0D49EFU, 0xF305E21CU, 0xA165C647U, 0xEE98127FU, 0xFFBA5ABEU,
|
||||||
|
0xBE1CE314U, 0xA22920B0U, 0xCF9E0A60U, 0x93FFCCB3U, 0xEAC5664CU,
|
||||||
|
0xC29F2616U, 0xFAFDBCCEU, 0x9D7533CFU, 0x8B47D943U, 0xB0DA180CU,
|
||||||
|
0xB3EF69F2U, 0x8EC5E214U, 0xDFD9DA04U, 0xC9CE101AU, 0xCC2C495CU,
|
||||||
|
0x9509CFAAU, 0xD86FF60DU, 0xC760103DU, 0xE3483662U, 0xB4613752U,
|
||||||
|
0x8122E220U, 0xED488818U, 0xC2FA8D9DU, 0xE9300BA3U, 0xFAF728DAU,
|
||||||
|
0x8F540552U, 0x953D5592U, 0xEDFD0AF6U, 0xB0B9CB99U, 0x83D56812U,
|
||||||
|
0xEDB765B4U, 0xEED6AEADU, 0xA5FE88C2U, 0xBD557014U, 0x82D67B60U,
|
||||||
|
0x90C3EF0EU, 0xFFF4962AU, 0xFDD4382EU, 0xAE3922DEU, 0x8B3C6F6EU,
|
||||||
|
0xAEAE503BU, 0xE2288CD0U, 0x9A025182U, 0x8E882A3FU, 0xABF69CEBU,
|
||||||
|
0xE62E9ADEU, 0xA391F9E9U, 0x846692F8U, 0xAD8EAB1BU, 0x86DA304BU,
|
||||||
|
0xB8C7CA4AU, 0xAEB18D3CU, 0xF422B863U, 0xFBC257E7U, 0x97E198DFU,
|
||||||
|
0xEF19E13DU, 0x8B165D39U, 0xAD1EEE72U, 0xDD16EC34U, 0xBBD028D3U,
|
||||||
|
0xB0F45684U, 0xCACE51E8U, 0xAAA6D780U, 0xD6F2DF46U, 0x8823C1FDU,
|
||||||
|
0xAD7D52E1U, 0xE7B6CE55U, 0x88185827U, 0xAB518B0FU, 0x95EFF133U,
|
||||||
|
0x9354C795U, 0xD9FFDB4AU, 0xF8187E03U, 0xAD571917U, 0xE8880589U,
|
||||||
|
0xA40F1AEEU, 0x9385B3F6U, 0x8C19FF72U, 0xA875ADE6U, 0xC1145F11U,
|
||||||
|
0x92F42FBDU, 0xE13D7831U, 0xEFC5EC4DU, 0x8716E820U, 0xDCFFD018U,
|
||||||
|
0x87A7852DU, 0xF630C95EU, 0xE8162D52U, 0xB4C6739FU, 0xD347B592U,
|
||||||
|
0xA3E65625U, 0xE5BACA23U, 0x9E16077AU, 0xCE8D2DA5U, 0xBCADA969U,
|
||||||
|
0xA639C977U, 0xFC0A8086U, 0xA46477BEU, 0xAE52219FU, 0xA75C0B96U,
|
||||||
|
0xBA5468F1U, 0xC1A6E934U, 0x815BE6E0U, 0xB26CE6F5U, 0xEEFE024CU,
|
||||||
|
0xE9E3EC6AU, 0xD67C01E3U, 0x8283B642U, 0xF5FDEBDCU, 0xFEF1AFCAU,
|
||||||
|
0xC3981553U, 0x88F21B9AU, 0xE02F27FBU, 0xB35E01A1U, 0x900903BAU,
|
||||||
|
0xBD2EF813U, 0xBB0586CEU, 0x8639CD18U, 0xA5452565U, 0xEFCBFA6DU,
|
||||||
|
0xD98182AAU, 0xC92B7B8AU, 0xD586C490U, 0xF7978A25U, 0x97B8A930U,
|
||||||
|
0x92346DF9U, 0x9DD1539CU, 0x93C329B6U, 0xB698E5B8U, 0xCC23753BU,
|
||||||
|
0xBB1F354CU, 0xF0ED4EA9U, 0x8DCA5E70U, 0xBC7B1C2DU, 0xA35A359EU,
|
||||||
|
0xFCC860BCU, 0xA65F0897U, 0xF9D63782U, 0xFF4C16FEU, 0x9C5CF473U,
|
||||||
|
0xF8C7E74CU, 0xC2E42C51U, 0xA54F100DU, 0xD8F70F47U, 0xF6422DF2U,
|
||||||
|
0xB55813C8U, 0x9626075AU, 0xB147B4C0U, 0xBB91E0E0U, 0xBB6B2CC0U,
|
||||||
|
0xA113AF2DU, 0x9513638BU, 0x8496A84AU, 0xF69A73BDU, 0x8CAAEDB0U,
|
||||||
|
0x9C4F517AU
|
||||||
|
};
|
||||||
|
|
||||||
|
const int16_t pva_pfsd_data_dlut_tbl0[] = {
|
||||||
|
#include "dlut_data/table.0.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t pva_pfsd_data_dlut_tbl1[] = {
|
||||||
|
#include "dlut_data/table.1.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t pva_pfsd_data_dlut_tbl2[] = {
|
||||||
|
#include "dlut_data/table.2.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pva_pfsd_data_dlut_tbl3[] = {
|
||||||
|
#include "dlut_data/table.3.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int16_t pva_pfsd_data_dlut_indices0[] = {
|
||||||
|
#include "dlut_data/indices.0.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int32_t pva_pfsd_data_dlut_indices1[] = {
|
||||||
|
#include "dlut_data/indices.1.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int32_t pva_pfsd_data_dlut_indices2[] = {
|
||||||
|
#include "dlut_data/indices.2.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int32_t pva_pfsd_data_dlut_indices3[] = {
|
||||||
|
#include "dlut_data/indices.3.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pva_pfsd_vpu_elf_t23x[] = {
|
||||||
|
#include "elf/pva_pfsd_vpu_elf_t23x.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pva_pfsd_vpu_elf_t26x[] = {
|
||||||
|
#include "elf/pva_pfsd_vpu_elf_t26x.csv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t pva_pfsd_ppe_elf_t26x[] = {
|
||||||
|
#include "elf/pva_pfsd_ppe_elf_t26x.csv"
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_fw.h"
|
#include "pva_fw.h"
|
||||||
#include "pva_kmd_device_memory.h"
|
#include "pva_kmd_device_memory.h"
|
||||||
@@ -20,7 +21,8 @@ enum pva_error pva_kmd_prepare_suspend(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
pva_kmd_set_cmd_suspend_fw(&cmd);
|
pva_kmd_set_cmd_suspend_fw(&cmd);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&pva->submitter, &cmd, sizeof(cmd),
|
err = pva_kmd_submit_cmd_sync(&pva->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -32,18 +34,168 @@ err_out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
init_context_resources(struct pva_kmd_cmdbuf_builder *builder,
|
||||||
|
struct pva_kmd_device *pva, struct pva_kmd_context *ctx,
|
||||||
|
struct pva_cmd_init_queue **queue_cmd_out,
|
||||||
|
const struct pva_syncpt_rw_info **syncpt_info_out)
|
||||||
|
{
|
||||||
|
struct pva_cmd_init_resource_table *res_cmd;
|
||||||
|
struct pva_cmd_init_queue *queue_cmd;
|
||||||
|
struct pva_cmd_init_shared_dram_buffer *shared_buf_cmd;
|
||||||
|
const struct pva_syncpt_rw_info *syncpt_info;
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
/**Initialize resource table */
|
||||||
|
res_cmd =
|
||||||
|
pva_kmd_reserve_cmd_space(builder, (uint16_t)sizeof(*res_cmd));
|
||||||
|
if (res_cmd == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PVA: Memory alloc for context registration in FW resume command failed\n");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pva_dbg_printf("PVA: Resume init resource table for context %d\n",
|
||||||
|
ctx->ccq_id);
|
||||||
|
pva_kmd_set_cmd_init_resource_table(
|
||||||
|
res_cmd, ctx->resource_table_id,
|
||||||
|
ctx->ctx_resource_table.table_mem->iova,
|
||||||
|
ctx->ctx_resource_table.n_entries, ctx->status_mem->iova);
|
||||||
|
|
||||||
|
queue_cmd = pva_kmd_reserve_cmd_space(builder,
|
||||||
|
(uint16_t)sizeof(*queue_cmd));
|
||||||
|
if (queue_cmd == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PVA: Memory alloc for queue registration in FW resume command failed\n");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize shared buffer */
|
||||||
|
shared_buf_cmd = pva_kmd_reserve_cmd_space(
|
||||||
|
builder, (uint16_t)sizeof(*shared_buf_cmd));
|
||||||
|
if (shared_buf_cmd == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PVA: Memory alloc for shared buffer registration in FW resume command failed\n");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pva_dbg_printf("PVA: Resume shared buffer for context %d\n",
|
||||||
|
ctx->ccq_id);
|
||||||
|
/* Validate resource memory size and iova fit in uint32_t */
|
||||||
|
if ((pva->kmd_fw_buffers[ctx->ccq_id].resource_memory->size >
|
||||||
|
U32_MAX) ||
|
||||||
|
(pva->kmd_fw_buffers[ctx->ccq_id].resource_memory->iova >
|
||||||
|
U32_MAX)) {
|
||||||
|
pva_kmd_log_err("Resource memory size or iova exceeds U32_MAX");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
/* CERT INT31-C: iova and size validated to fit in uint32_t, safe to cast */
|
||||||
|
pva_kmd_set_cmd_init_shared_dram_buffer(
|
||||||
|
shared_buf_cmd, ctx->ccq_id,
|
||||||
|
pva->kmd_fw_buffers[ctx->ccq_id].resource_memory->iova,
|
||||||
|
pva->kmd_fw_buffers[ctx->ccq_id].resource_memory->size);
|
||||||
|
|
||||||
|
pva_dbg_printf("PVA: Resume priv queue for context %d\n", ctx->ccq_id);
|
||||||
|
syncpt_info = pva_kmd_queue_get_rw_syncpt_info(pva, PVA_PRIV_CCQ_ID,
|
||||||
|
ctx->ccq_id);
|
||||||
|
*queue_cmd_out = queue_cmd;
|
||||||
|
*syncpt_info_out = syncpt_info;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error init_context_user_queues(
|
||||||
|
struct pva_kmd_cmdbuf_builder *builder, struct pva_kmd_device *pva,
|
||||||
|
struct pva_kmd_context *ctx, struct pva_cmd_init_queue *priv_queue_cmd,
|
||||||
|
const struct pva_syncpt_rw_info *priv_syncpt_info)
|
||||||
|
{
|
||||||
|
struct pva_cmd_init_queue *queue_cmd;
|
||||||
|
struct pva_kmd_queue *queue;
|
||||||
|
const struct pva_syncpt_rw_info *syncpt_info;
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
pva_dbg_printf("PVA: Resume priv queue for context %d\n", ctx->ccq_id);
|
||||||
|
pva_kmd_set_cmd_init_queue(
|
||||||
|
priv_queue_cmd, PVA_PRIV_CCQ_ID,
|
||||||
|
ctx->ccq_id, /* For privileged queues, queue ID == user CCQ ID*/
|
||||||
|
ctx->ctx_queue.queue_memory->iova,
|
||||||
|
ctx->ctx_queue.max_num_submit, priv_syncpt_info->syncpt_id,
|
||||||
|
priv_syncpt_info->syncpt_iova);
|
||||||
|
|
||||||
|
/**Initialize resource table */
|
||||||
|
for (uint32_t j = 0; j < ctx->max_n_queues; j++) {
|
||||||
|
pva_kmd_mutex_lock(&ctx->queue_allocator.allocator_lock);
|
||||||
|
queue = pva_kmd_get_block_unsafe(&ctx->queue_allocator, j);
|
||||||
|
if (queue != NULL) {
|
||||||
|
pva_dbg_printf(
|
||||||
|
"PVA: Resume queue for context %d, queue %d\n",
|
||||||
|
queue->ccq_id, queue->queue_id);
|
||||||
|
queue_cmd = pva_kmd_reserve_cmd_space(
|
||||||
|
builder, (uint16_t)sizeof(*queue_cmd));
|
||||||
|
if (queue_cmd == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PVA: Memory alloc for queue registration in FW resume command failed\n");
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
pva_kmd_mutex_unlock(
|
||||||
|
&ctx->queue_allocator.allocator_lock);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncpt_info = pva_kmd_queue_get_rw_syncpt_info(
|
||||||
|
pva, ctx->ccq_id, queue->queue_id);
|
||||||
|
pva_kmd_set_cmd_init_queue(queue_cmd, queue->ccq_id,
|
||||||
|
queue->queue_id,
|
||||||
|
queue->queue_memory->iova,
|
||||||
|
queue->max_num_submit,
|
||||||
|
syncpt_info->syncpt_id,
|
||||||
|
syncpt_info->syncpt_iova);
|
||||||
|
}
|
||||||
|
pva_kmd_mutex_unlock(&ctx->queue_allocator.allocator_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum pva_error
|
||||||
|
handle_submit_and_wait(struct pva_kmd_device *pva,
|
||||||
|
struct pva_kmd_cmdbuf_builder *builder)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
uint32_t fence_val;
|
||||||
|
|
||||||
|
err = pva_kmd_submitter_submit(&pva->submitter, builder, &fence_val);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
// Error is either QUEUE_FULL or TIMEDOUT
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"PVA: Submission for FW resume command failed\n");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_submitter_wait(&pva->submitter, fence_val,
|
||||||
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"Waiting for FW timed out when resuming from suspend state");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva)
|
enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
struct pva_kmd_cmdbuf_builder builder;
|
struct pva_kmd_cmdbuf_builder builder;
|
||||||
struct pva_kmd_submitter *dev_submitter = &pva->submitter;
|
struct pva_kmd_submitter *dev_submitter = &pva->submitter;
|
||||||
struct pva_cmd_init_resource_table *res_cmd;
|
|
||||||
struct pva_cmd_init_queue *queue_cmd;
|
|
||||||
struct pva_cmd_resume_fw *fw_resume;
|
struct pva_cmd_resume_fw *fw_resume;
|
||||||
struct pva_cmd_init_shared_dram_buffer *shared_buf_cmd;
|
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
uint32_t fence_val;
|
|
||||||
struct pva_kmd_queue *queue;
|
|
||||||
const struct pva_syncpt_rw_info *syncpt_info;
|
|
||||||
|
|
||||||
err = pva_kmd_submitter_prepare(dev_submitter, &builder);
|
err = pva_kmd_submitter_prepare(dev_submitter, &builder);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -52,7 +204,8 @@ enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fw_resume = pva_kmd_reserve_cmd_space(&builder, sizeof(*fw_resume));
|
fw_resume = pva_kmd_reserve_cmd_space(&builder,
|
||||||
|
(uint16_t)sizeof(*fw_resume));
|
||||||
if (fw_resume == NULL) {
|
if (fw_resume == NULL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"PVA: Memory alloc for FW resume command failed\n");
|
"PVA: Memory alloc for FW resume command failed\n");
|
||||||
@@ -66,117 +219,27 @@ enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva)
|
|||||||
struct pva_kmd_context *ctx = pva_kmd_get_context(
|
struct pva_kmd_context *ctx = pva_kmd_get_context(
|
||||||
pva, sat_add8(i, PVA_KMD_USER_CONTEXT_ID_BASE));
|
pva, sat_add8(i, PVA_KMD_USER_CONTEXT_ID_BASE));
|
||||||
if (ctx != NULL) {
|
if (ctx != NULL) {
|
||||||
/**Initialize resource table */
|
struct pva_cmd_init_queue *priv_queue_cmd;
|
||||||
res_cmd = pva_kmd_reserve_cmd_space(&builder,
|
const struct pva_syncpt_rw_info *priv_syncpt_info;
|
||||||
sizeof(*res_cmd));
|
|
||||||
if (res_cmd == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"PVA: Memory alloc for context registration in FW resume command failed\n");
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto cancel_builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
pva_dbg_printf(
|
err = init_context_resources(&builder, pva, ctx,
|
||||||
"PVA: Resume init resource table for context %d\n",
|
&priv_queue_cmd,
|
||||||
ctx->ccq_id);
|
&priv_syncpt_info);
|
||||||
pva_kmd_set_cmd_init_resource_table(
|
|
||||||
res_cmd, ctx->resource_table_id,
|
|
||||||
ctx->ctx_resource_table.table_mem->iova,
|
|
||||||
ctx->ctx_resource_table.n_entries);
|
|
||||||
|
|
||||||
queue_cmd = pva_kmd_reserve_cmd_space(
|
|
||||||
&builder, sizeof(*queue_cmd));
|
|
||||||
if (queue_cmd == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"PVA: Memory alloc for queue registration in FW resume command failed\n");
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto cancel_builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize shared buffer */
|
|
||||||
shared_buf_cmd = pva_kmd_reserve_cmd_space(
|
|
||||||
&builder, sizeof(*shared_buf_cmd));
|
|
||||||
if (shared_buf_cmd == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"PVA: Memory alloc for shared buffer registration in FW resume command failed\n");
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto cancel_builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
pva_dbg_printf(
|
|
||||||
"PVA: Resume shared buffer for context %d\n",
|
|
||||||
ctx->ccq_id);
|
|
||||||
pva_kmd_set_cmd_init_shared_dram_buffer(
|
|
||||||
shared_buf_cmd, ctx->ccq_id,
|
|
||||||
pva->kmd_fw_buffers[ctx->ccq_id]
|
|
||||||
.resource_memory->iova,
|
|
||||||
pva->kmd_fw_buffers[ctx->ccq_id]
|
|
||||||
.resource_memory->size);
|
|
||||||
|
|
||||||
pva_dbg_printf(
|
|
||||||
"PVA: Resume priv queue for context %d\n",
|
|
||||||
ctx->ccq_id);
|
|
||||||
syncpt_info = pva_kmd_queue_get_rw_syncpt_info(
|
|
||||||
pva, PVA_PRIV_CCQ_ID, ctx->ccq_id);
|
|
||||||
pva_kmd_set_cmd_init_queue(
|
|
||||||
queue_cmd, PVA_PRIV_CCQ_ID,
|
|
||||||
ctx->ccq_id, /* For privileged queues, queue ID == user CCQ ID*/
|
|
||||||
ctx->ctx_queue.queue_memory->iova,
|
|
||||||
ctx->ctx_queue.max_num_submit,
|
|
||||||
syncpt_info->syncpt_id,
|
|
||||||
syncpt_info->syncpt_iova);
|
|
||||||
|
|
||||||
/**Initialize resource table */
|
|
||||||
for (uint32_t j = 0; j < ctx->max_n_queues; j++) {
|
|
||||||
pva_kmd_mutex_lock(
|
|
||||||
&ctx->queue_allocator.allocator_lock);
|
|
||||||
queue = pva_kmd_get_block_unsafe(
|
|
||||||
&ctx->queue_allocator, j);
|
|
||||||
if (queue != NULL) {
|
|
||||||
pva_dbg_printf(
|
|
||||||
"PVA: Resume queue for context %d, queue %d\n",
|
|
||||||
queue->ccq_id, queue->queue_id);
|
|
||||||
queue_cmd = pva_kmd_reserve_cmd_space(
|
|
||||||
&builder, sizeof(*queue_cmd));
|
|
||||||
if (queue_cmd == NULL) {
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"PVA: Memory alloc for queue registration in FW resume command failed\n");
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto cancel_builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
syncpt_info =
|
|
||||||
pva_kmd_queue_get_rw_syncpt_info(
|
|
||||||
pva, ctx->ccq_id,
|
|
||||||
queue->queue_id);
|
|
||||||
pva_kmd_set_cmd_init_queue(
|
|
||||||
queue_cmd, queue->ccq_id,
|
|
||||||
queue->queue_id,
|
|
||||||
queue->queue_memory->iova,
|
|
||||||
queue->max_num_submit,
|
|
||||||
syncpt_info->syncpt_id,
|
|
||||||
syncpt_info->syncpt_iova);
|
|
||||||
}
|
|
||||||
pva_kmd_mutex_unlock(
|
|
||||||
&ctx->queue_allocator.allocator_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pva_kmd_submitter_submit(dev_submitter, &builder, &fence_val);
|
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
// Error is either QUEUE_FULL or TIMEDOUT
|
|
||||||
pva_kmd_log_err(
|
|
||||||
"PVA: Submission for FW resume command failed\n");
|
|
||||||
goto cancel_builder;
|
goto cancel_builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_submitter_wait(dev_submitter, fence_val,
|
err = init_context_user_queues(&builder, pva, ctx,
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
priv_queue_cmd,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
priv_syncpt_info);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto cancel_builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = handle_submit_and_wait(pva, &builder);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err(
|
|
||||||
"Waiting for FW timed out when resuming from suspend state");
|
|
||||||
goto cancel_builder;
|
goto cancel_builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,60 @@
|
|||||||
#define PVA_KMD_PM_H
|
#define PVA_KMD_PM_H
|
||||||
|
|
||||||
struct pva_kmd_device;
|
struct pva_kmd_device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepare PVA device for system suspend operation
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures all pending commands are completed or properly handled
|
||||||
|
* - Saves critical device state information for resume
|
||||||
|
* - Gracefully halts firmware execution in preparation for suspend
|
||||||
|
* - Configures hardware for low-power suspend state
|
||||||
|
* - Validates that device is ready for power state transition
|
||||||
|
* - Prepares synchronization mechanisms for suspend/resume cycle
|
||||||
|
* - Ensures proper resource cleanup before suspend
|
||||||
|
*
|
||||||
|
* This function is called as part of the system suspend sequence to ensure
|
||||||
|
* the PVA device can safely enter a suspended state without losing critical
|
||||||
|
* information or leaving the hardware in an inconsistent state.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Device prepared for suspend successfully
|
||||||
|
* @retval PVA_AGAIN Device has pending operations preventing suspend
|
||||||
|
* @retval PVA_INTERNAL Firmware in invalid state for suspend
|
||||||
|
* @retval PVA_TIMEDOUT Timeout waiting for operations to complete
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Power management operation failed
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_prepare_suspend(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_prepare_suspend(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Complete PVA device resume operation after system wake
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Restores hardware configuration and register state
|
||||||
|
* - Reinitializes firmware and brings it to operational state
|
||||||
|
* - Restores saved device context and operational parameters
|
||||||
|
* - Re-establishes communication channels with firmware
|
||||||
|
* - Validates device functionality after resume
|
||||||
|
* - Restores resource tables and memory mappings
|
||||||
|
* - Ensures device is fully operational for command processing
|
||||||
|
*
|
||||||
|
* This function is called as part of the system resume sequence to restore
|
||||||
|
* the PVA device to full operational state after waking from suspend.
|
||||||
|
* It ensures that all device functionality is restored and available.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Device resumed successfully
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Failed to boot or initialize firmware
|
||||||
|
* @retval PVA_INTERNAL Failed to initialize hardware after resume
|
||||||
|
* @retval PVA_TIMEDOUT Failed to establish firmware communication
|
||||||
|
* @retval PVA_UNKNOWN_ERROR Power management operation failed
|
||||||
|
* @retval PVA_INVAL Device in invalid state after resume
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva);
|
enum pva_error pva_kmd_complete_resume(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
void pva_kmd_queue_init(struct pva_kmd_queue *queue, struct pva_kmd_device *pva,
|
void pva_kmd_queue_init(struct pva_kmd_queue *queue, struct pva_kmd_device *pva,
|
||||||
uint8_t ccq_id, uint8_t queue_id,
|
uint8_t ccq_id, uint8_t queue_id,
|
||||||
@@ -43,7 +44,7 @@ pva_kmd_queue_submit(struct pva_kmd_queue *queue,
|
|||||||
struct pva_fw_cmdbuf_submit_info *items = pva_offset_pointer(
|
struct pva_fw_cmdbuf_submit_info *items = pva_offset_pointer(
|
||||||
queue->queue_header, sizeof(*queue->queue_header));
|
queue->queue_header, sizeof(*queue->queue_header));
|
||||||
|
|
||||||
if (pva_fw_queue_space(head, tail, size) == 0) {
|
if (pva_fw_queue_space(head, tail, size) == 0U) {
|
||||||
return PVA_QUEUE_FULL;
|
return PVA_QUEUE_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +66,8 @@ static enum pva_error notify_fw_queue_deinit(struct pva_kmd_context *ctx,
|
|||||||
|
|
||||||
pva_kmd_set_cmd_deinit_queue(&cmd, queue->ccq_id, queue->queue_id);
|
pva_kmd_set_cmd_deinit_queue(&cmd, queue->ccq_id, queue->queue_id);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&ctx->submitter, &cmd, sizeof(cmd),
|
err = pva_kmd_submit_cmd_sync(&ctx->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -105,7 +107,16 @@ enum pva_error pva_kmd_queue_create(struct pva_kmd_context *ctx,
|
|||||||
goto err_free_queue;
|
goto err_free_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pva_kmd_queue_init(queue, ctx->pva, ctx->ccq_id, *queue_id,
|
/* Validate queue_id fits in uint8_t */
|
||||||
|
/* MISRA C-2023 Rule 10.4: Both operands must have same essential type */
|
||||||
|
if (*queue_id > (uint32_t)U8_MAX) {
|
||||||
|
pva_kmd_log_err("Queue ID exceeds U8_MAX");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto err_free_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CERT INT31-C: queue_id validated to fit in uint8_t, safe to cast */
|
||||||
|
pva_kmd_queue_init(queue, ctx->pva, ctx->ccq_id, (uint8_t)*queue_id,
|
||||||
submission_mem_kmd, in_args->max_submission_count);
|
submission_mem_kmd, in_args->max_submission_count);
|
||||||
|
|
||||||
/* Get device mapped IOVA to share with FW */
|
/* Get device mapped IOVA to share with FW */
|
||||||
@@ -124,7 +135,8 @@ enum pva_error pva_kmd_queue_create(struct pva_kmd_context *ctx,
|
|||||||
syncpt_info->syncpt_id,
|
syncpt_info->syncpt_id,
|
||||||
syncpt_info->syncpt_iova);
|
syncpt_info->syncpt_iova);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&ctx->submitter, &cmd, sizeof(cmd),
|
err = pva_kmd_submit_cmd_sync(&ctx->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -182,9 +194,15 @@ const struct pva_syncpt_rw_info *
|
|||||||
pva_kmd_queue_get_rw_syncpt_info(struct pva_kmd_device *pva, uint8_t ccq_id,
|
pva_kmd_queue_get_rw_syncpt_info(struct pva_kmd_device *pva, uint8_t ccq_id,
|
||||||
uint8_t queue_id)
|
uint8_t queue_id)
|
||||||
{
|
{
|
||||||
uint8_t ctx_offset =
|
uint8_t ctx_offset;
|
||||||
safe_mulu32(ccq_id, PVA_NUM_RW_SYNCPTS_PER_CONTEXT);
|
uint8_t syncpt_index_u8;
|
||||||
uint32_t syncpt_index = safe_addu32(ctx_offset, queue_id);
|
uint32_t syncpt_index;
|
||||||
|
|
||||||
|
/* Use uint8_t arithmetic - all values fit in uint8_t range */
|
||||||
|
ctx_offset =
|
||||||
|
safe_mulu8(ccq_id, (uint8_t)PVA_NUM_RW_SYNCPTS_PER_CONTEXT);
|
||||||
|
syncpt_index_u8 = safe_addu8(ctx_offset, queue_id);
|
||||||
|
syncpt_index = (uint32_t)syncpt_index_u8;
|
||||||
|
|
||||||
ASSERT(syncpt_index < PVA_NUM_RW_SYNCPTS);
|
ASSERT(syncpt_index < PVA_NUM_RW_SYNCPTS);
|
||||||
return &pva->rw_syncpts[syncpt_index];
|
return &pva->rw_syncpts[syncpt_index];
|
||||||
|
|||||||
@@ -7,32 +7,220 @@
|
|||||||
#include "pva_kmd_device_memory.h"
|
#include "pva_kmd_device_memory.h"
|
||||||
#include "pva_kmd_mutex.h"
|
#include "pva_kmd_mutex.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure for managing PVA command submission queues
|
||||||
|
*
|
||||||
|
* @details This structure represents a command queue used for submitting
|
||||||
|
* command buffers to the PVA firmware. Each queue is associated with a
|
||||||
|
* specific CCQ (Command and Control Queue) and maintains submission state,
|
||||||
|
* memory management, and synchronization mechanisms for thread-safe operation.
|
||||||
|
*/
|
||||||
struct pva_kmd_queue {
|
struct pva_kmd_queue {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the parent PVA device
|
||||||
|
* Valid value: non-null
|
||||||
|
*/
|
||||||
struct pva_kmd_device *pva;
|
struct pva_kmd_device *pva;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for queue data structures
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *queue_memory;
|
struct pva_kmd_device_memory *queue_memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to firmware queue header for submission tracking
|
||||||
|
*/
|
||||||
struct pva_fw_submit_queue_header *queue_header;
|
struct pva_fw_submit_queue_header *queue_header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ (Command and Control Queue) identifier
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*/
|
||||||
uint8_t ccq_id;
|
uint8_t ccq_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue identifier within the CCQ
|
||||||
|
* Valid range: [0 .. PVA_MAX_QUEUES_PER_CCQ-1]
|
||||||
|
*/
|
||||||
uint8_t queue_id;
|
uint8_t queue_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of submissions this queue can hold
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t max_num_submit;
|
uint32_t max_num_submit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a PVA command queue structure
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes all fields of the queue structure with provided parameters
|
||||||
|
* - Associates the queue with the specified PVA device and CCQ
|
||||||
|
* - Sets up queue memory and header pointers for submission tracking
|
||||||
|
* - Configures synchronization mechanisms using the provided CCQ lock
|
||||||
|
* - Prepares the queue for command buffer submissions
|
||||||
|
*
|
||||||
|
* The queue structure must be allocated before calling this function.
|
||||||
|
* After initialization, the queue is ready to accept command submissions
|
||||||
|
* using @ref pva_kmd_queue_submit().
|
||||||
|
*
|
||||||
|
* @param[out] queue Pointer to @ref pva_kmd_queue structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] ccq_id CCQ identifier for this queue
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
* @param[in] queue_id Queue identifier within the CCQ
|
||||||
|
* Valid range: [0 .. PVA_MAX_QUEUES_PER_CCQ-1]
|
||||||
|
* @param[in] ccq_lock Pointer to mutex for CCQ synchronization
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] queue_memory Pointer to allocated queue memory
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] max_num_submit Maximum number of submissions for this queue
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
void pva_kmd_queue_init(struct pva_kmd_queue *queue, struct pva_kmd_device *pva,
|
void pva_kmd_queue_init(struct pva_kmd_queue *queue, struct pva_kmd_device *pva,
|
||||||
uint8_t ccq_id, uint8_t queue_id,
|
uint8_t ccq_id, uint8_t queue_id,
|
||||||
struct pva_kmd_device_memory *queue_memory,
|
struct pva_kmd_device_memory *queue_memory,
|
||||||
uint32_t max_num_submit);
|
uint32_t max_num_submit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new user queue within a context
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the queue creation parameters provided by the user
|
||||||
|
* - Allocates a new queue identifier from the context's queue pool
|
||||||
|
* - Initializes queue data structures and memory allocations
|
||||||
|
* - Sets up the queue for the specified context and configuration
|
||||||
|
* - Registers the queue with the firmware for operation
|
||||||
|
* - Returns the allocated queue identifier to the caller
|
||||||
|
*
|
||||||
|
* The created queue can be used for submitting command buffers within
|
||||||
|
* the specified context. The queue should be destroyed using
|
||||||
|
* @ref pva_kmd_queue_destroy() when no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in, out] ctx Pointer to @ref pva_kmd_context structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] in_args Pointer to queue creation parameters
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[out] queue_id Pointer to store the allocated queue identifier
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Queue created successfully
|
||||||
|
* @retval PVA_INVAL Invalid parameters or context
|
||||||
|
* @retval PVA_NOMEM Failed to allocate queue resources
|
||||||
|
* @retval PVA_NO_RESOURCE_ID No available queue identifiers
|
||||||
|
* @retval PVA_TIMEDOUT Failed to register queue with firmware
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_queue_create(struct pva_kmd_context *ctx,
|
enum pva_error pva_kmd_queue_create(struct pva_kmd_context *ctx,
|
||||||
const struct pva_ops_queue_create *in_args,
|
const struct pva_ops_queue_create *in_args,
|
||||||
uint32_t *queue_id);
|
uint32_t *queue_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy a user queue and free associated resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates that the queue identifier is valid for the context
|
||||||
|
* - Ensures no pending submissions remain in the queue
|
||||||
|
* - Unregisters the queue from firmware operation
|
||||||
|
* - Frees allocated memory and data structures for the queue
|
||||||
|
* - Returns the queue identifier to the context's available pool
|
||||||
|
* - Cleans up synchronization mechanisms and state
|
||||||
|
*
|
||||||
|
* All pending operations on the queue should be completed before
|
||||||
|
* calling this function. After destruction, the queue identifier
|
||||||
|
* becomes invalid and cannot be used for further operations.
|
||||||
|
*
|
||||||
|
* @param[in, out] ctx Pointer to @ref pva_kmd_context structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] queue_id Queue identifier to destroy
|
||||||
|
* Valid range: [0 .. max_queues-1]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Queue destroyed successfully
|
||||||
|
* @retval PVA_INVAL Invalid queue identifier or context
|
||||||
|
* @retval PVA_AGAIN Queue has pending operations
|
||||||
|
* @retval PVA_TIMEDOUT Failed to unregister queue from firmware
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_queue_destroy(struct pva_kmd_context *ctx,
|
enum pva_error pva_kmd_queue_destroy(struct pva_kmd_context *ctx,
|
||||||
uint32_t queue_id);
|
uint32_t queue_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit a command buffer to the specified queue
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the submission information and queue state
|
||||||
|
* - Acquires the queue's CCQ lock for thread-safe submission
|
||||||
|
* - Adds the submission to the queue's submission ring buffer
|
||||||
|
* - Updates queue pointers and submission tracking information
|
||||||
|
* - Notifies firmware of the new submission via CCQ mechanism
|
||||||
|
* - Releases the CCQ lock after successful submission
|
||||||
|
* - Handles submission errors and queue overflow conditions
|
||||||
|
*
|
||||||
|
* The command buffer must be properly prepared and all referenced
|
||||||
|
* resources must be registered before calling this function. The
|
||||||
|
* submission is processed asynchronously by the firmware.
|
||||||
|
*
|
||||||
|
* @param[in, out] queue Pointer to @ref pva_kmd_queue structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] submit_info Pointer to command buffer submission information
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Submission completed successfully
|
||||||
|
* @retval PVA_INVAL Invalid queue or submission parameters
|
||||||
|
* @retval PVA_QUEUE_FULL Queue has no space for new submissions
|
||||||
|
* @retval PVA_TIMEDOUT Failed to notify firmware of submission
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_queue_submit(struct pva_kmd_queue *queue,
|
pva_kmd_queue_submit(struct pva_kmd_queue *queue,
|
||||||
struct pva_fw_cmdbuf_submit_info const *submit_info);
|
struct pva_fw_cmdbuf_submit_info const *submit_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get available space in the submission queue
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Reads the current queue head and tail pointers
|
||||||
|
* - Calculates the number of available submission slots
|
||||||
|
* - Accounts for queue wraparound and boundary conditions
|
||||||
|
* - Returns the number of submissions that can be queued
|
||||||
|
* - Provides thread-safe access to queue state information
|
||||||
|
*
|
||||||
|
* This function can be used to check if the queue has space for
|
||||||
|
* additional submissions before attempting to submit command buffers.
|
||||||
|
* The returned value represents an instantaneous snapshot and may
|
||||||
|
* change if other threads are also submitting to the queue.
|
||||||
|
*
|
||||||
|
* @param[in] queue Pointer to @ref pva_kmd_queue structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval space_count Number of available submission slots in the queue
|
||||||
|
*/
|
||||||
uint32_t pva_kmd_queue_space(struct pva_kmd_queue *queue);
|
uint32_t pva_kmd_queue_space(struct pva_kmd_queue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get read-write syncpoint information for a specific queue
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided CCQ and queue identifiers
|
||||||
|
* - Looks up the syncpoint information for the specified queue
|
||||||
|
* - Returns the syncpoint configuration including ID and IOVA address
|
||||||
|
* - Provides access to queue-specific synchronization mechanisms
|
||||||
|
* - Ensures proper mapping between queues and their assigned syncpoints
|
||||||
|
*
|
||||||
|
* The returned syncpoint information can be used for synchronization
|
||||||
|
* operations and fence management specific to the queue. Each queue
|
||||||
|
* is assigned dedicated syncpoint resources for independent operation.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] ccq_id CCQ identifier
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
* @param[in] queue_id Queue identifier within the CCQ
|
||||||
|
* Valid range: [0 .. PVA_MAX_QUEUES_PER_CCQ-1]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_syncpt_rw_info structure
|
||||||
|
* @retval NULL Invalid CCQ/queue identifier or not configured
|
||||||
|
*/
|
||||||
const struct pva_syncpt_rw_info *
|
const struct pva_syncpt_rw_info *
|
||||||
pva_kmd_queue_get_rw_syncpt_info(struct pva_kmd_device *pva, uint8_t ccq_id,
|
pva_kmd_queue_get_rw_syncpt_info(struct pva_kmd_device *pva, uint8_t ccq_id,
|
||||||
uint8_t queue_id);
|
uint8_t queue_id);
|
||||||
|
|||||||
@@ -7,12 +7,105 @@
|
|||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
#include "pva_kmd.h"
|
#include "pva_kmd.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from R5 on-chip debug (OCD) interface
|
||||||
|
*
|
||||||
|
* @details This function performs read operations from the R5 processor's
|
||||||
|
* on-chip debug interface. It provides access to R5 debug registers, memory,
|
||||||
|
* and other debug-accessible resources for debugging and development purposes.
|
||||||
|
* The function reads data from the specified offset within the R5 debug space
|
||||||
|
* and copies it to the provided buffer.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] file_data Pointer to file-specific data context
|
||||||
|
* Valid value: platform-specific pointer or NULL
|
||||||
|
* @param[out] data Buffer to store read data
|
||||||
|
* Valid value: non-null, must have capacity >= size
|
||||||
|
* @param[in] offset Byte offset within R5 debug space to read from
|
||||||
|
* Valid range: [0 .. R5_DEBUG_SPACE_SIZE-1]
|
||||||
|
* @param[in] size Number of bytes to read
|
||||||
|
* Valid range: [1 .. remaining_space_from_offset]
|
||||||
|
*
|
||||||
|
* @retval >=0 Number of bytes successfully read
|
||||||
|
* @retval PVA_INVAL Invalid argument provided
|
||||||
|
* @retval PVA_INTERNAL Device not in proper state for debug access
|
||||||
|
* @retval PVA_EACCES Debug access not permitted
|
||||||
|
* @retval PVA_TIMEDOUT Timeout during debug operation
|
||||||
|
* @retval PVA_INTERNAL Hardware error during debug access
|
||||||
|
*/
|
||||||
int64_t pva_kmd_r5_ocd_read(struct pva_kmd_device *dev, void *file_data,
|
int64_t pva_kmd_r5_ocd_read(struct pva_kmd_device *dev, void *file_data,
|
||||||
uint8_t *data, uint64_t offset, uint64_t size);
|
uint8_t *data, uint64_t offset, uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to R5 on-chip debug (OCD) interface
|
||||||
|
*
|
||||||
|
* @details This function performs write operations to the R5 processor's
|
||||||
|
* on-chip debug interface. It provides access to write to R5 debug registers,
|
||||||
|
* memory, and other debug-accessible resources for debugging and development
|
||||||
|
* purposes. The function writes data from the provided buffer to the specified
|
||||||
|
* offset within the R5 debug space.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] file_data Pointer to file-specific data context
|
||||||
|
* Valid value: platform-specific pointer or NULL
|
||||||
|
* @param[in] data Buffer containing data to write
|
||||||
|
* Valid value: non-null, must contain valid data
|
||||||
|
* @param[in] offset Byte offset within R5 debug space to write to
|
||||||
|
* Valid range: [0 .. R5_DEBUG_SPACE_SIZE-1]
|
||||||
|
* @param[in] size Number of bytes to write
|
||||||
|
* Valid range: [1 .. remaining_space_from_offset]
|
||||||
|
*
|
||||||
|
* @retval >=0 Number of bytes successfully written
|
||||||
|
* @retval PVA_INVAL Invalid argument provided
|
||||||
|
* @retval PVA_INTERNAL Device not in proper state for debug access
|
||||||
|
* @retval PVA_EACCES Debug access not permitted
|
||||||
|
* @retval PVA_TIMEDOUT Timeout during debug operation
|
||||||
|
* @retval PVA_INTERNAL Hardware error during debug access
|
||||||
|
*/
|
||||||
int64_t pva_kmd_r5_ocd_write(struct pva_kmd_device *dev, void *file_data,
|
int64_t pva_kmd_r5_ocd_write(struct pva_kmd_device *dev, void *file_data,
|
||||||
const uint8_t *data, uint64_t offset,
|
const uint8_t *data, uint64_t offset,
|
||||||
uint64_t size);
|
uint64_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open R5 on-chip debug (OCD) interface for access
|
||||||
|
*
|
||||||
|
* @details This function initializes and opens the R5 processor's on-chip
|
||||||
|
* debug interface for subsequent debug operations. It performs necessary
|
||||||
|
* hardware setup, validation checks, and prepares the debug interface for
|
||||||
|
* read/write operations. This function must be called before any debug
|
||||||
|
* access operations can be performed.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS R5 OCD interface opened successfully
|
||||||
|
* @retval PVA_INVAL Invalid device pointer provided
|
||||||
|
* @retval PVA_INTERNAL Device not in proper state for debug access
|
||||||
|
* @retval PVA_EACCES Debug access not permitted
|
||||||
|
* @retval PVA_AGAIN Debug interface already in use
|
||||||
|
* @retval PVA_INTERNAL Hardware initialization failure
|
||||||
|
*/
|
||||||
int pva_kmd_r5_ocd_open(struct pva_kmd_device *dev);
|
int pva_kmd_r5_ocd_open(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release R5 on-chip debug (OCD) interface and cleanup resources
|
||||||
|
*
|
||||||
|
* @details This function releases the R5 processor's on-chip debug interface
|
||||||
|
* and performs necessary cleanup operations. It ensures proper shutdown of
|
||||||
|
* the debug interface, releases any allocated resources, and restores the
|
||||||
|
* device to normal operation mode. This function should be called when debug
|
||||||
|
* access is no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS R5 OCD interface released successfully
|
||||||
|
* @retval PVA_INVAL Invalid device pointer provided
|
||||||
|
* @retval PVA_INTERNAL Device not in proper state for release
|
||||||
|
* @retval PVA_INTERNAL Hardware shutdown failure
|
||||||
|
*/
|
||||||
int pva_kmd_r5_ocd_release(struct pva_kmd_device *dev);
|
int pva_kmd_r5_ocd_release(struct pva_kmd_device *dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -7,147 +7,832 @@
|
|||||||
#include "pva_api.h"
|
#include "pva_api.h"
|
||||||
#include "pva_constants.h"
|
#include "pva_constants.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC (Security) subsystem base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for SEC subsystem registers within PVA aperture.
|
||||||
|
* The SEC subsystem handles security-related functionality including
|
||||||
|
* error monitoring and interrupt management.
|
||||||
|
* Value: 0x20000 (128KB offset)
|
||||||
|
*/
|
||||||
#define PVA0_SEC_OFFSET 0x20000
|
#define PVA0_SEC_OFFSET 0x20000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PROC (Processor) subsystem base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for PROC subsystem registers within PVA aperture.
|
||||||
|
* The PROC subsystem manages the R5 processor control and status.
|
||||||
|
* Value: 0x30000 (192KB offset)
|
||||||
|
*/
|
||||||
#define PVA0_PROC_OFFSET 0x30000
|
#define PVA0_PROC_OFFSET 0x30000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PM (Power Management) subsystem base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for PM subsystem registers within PVA aperture.
|
||||||
|
* The PM subsystem handles power management and clock control.
|
||||||
|
* Value: 0x200000 (2MB offset)
|
||||||
|
*/
|
||||||
#define PVA0_PM_OFFSET 0x200000
|
#define PVA0_PM_OFFSET 0x200000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG SID (Stream ID) configuration base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for CFG SID registers within PVA aperture.
|
||||||
|
* These registers configure Stream IDs for SMMU translation.
|
||||||
|
* Value: 0x240000 (2.25MB offset)
|
||||||
|
*/
|
||||||
#define PVA0_CFG_SID_OFFSET 0x240000
|
#define PVA0_CFG_SID_OFFSET 0x240000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG CCQ (Command and Control Queue) configuration base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for CFG CCQ registers within PVA aperture.
|
||||||
|
* These registers configure the CCQ interfaces for command submission.
|
||||||
|
* Value: 0x260000 (2.375MB offset)
|
||||||
|
*/
|
||||||
#define PVA0_CFG_CCQ_OFFSET 0x260000
|
#define PVA0_CFG_CCQ_OFFSET 0x260000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP (Hardware Synchronization Primitives) base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for HSP registers within PVA aperture.
|
||||||
|
* HSP provides hardware synchronization mechanisms including
|
||||||
|
* semaphores and shared mailboxes.
|
||||||
|
* Value: 0x160000 (1.375MB offset)
|
||||||
|
*/
|
||||||
#define PVA0_HSP_OFFSET 0x160000
|
#define PVA0_HSP_OFFSET 0x160000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EVP (Exception Vector Processor) base offset
|
||||||
|
*
|
||||||
|
* @details Base offset for EVP registers within PVA aperture.
|
||||||
|
* EVP manages exception vectors and interrupt handling for the R5.
|
||||||
|
* Value: 0x0 (base of aperture)
|
||||||
|
*/
|
||||||
#define PVA0_EVP_OFFSET 0x0
|
#define PVA0_EVP_OFFSET 0x0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC subsystem aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the SEC subsystem register aperture.
|
||||||
|
* Value: 0x10000 (64KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_SEC_SIZE 0x10000 // 64KB
|
#define PVA_KMD_PVA0_SEC_SIZE 0x10000 // 64KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PROC subsystem aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the PROC subsystem register aperture.
|
||||||
|
* Value: 0x10000 (64KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_PROC_SIZE 0x10000 // 64KB
|
#define PVA_KMD_PVA0_PROC_SIZE 0x10000 // 64KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PM subsystem aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the PM subsystem register aperture.
|
||||||
|
* Value: 0x10000 (64KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_PM_SIZE 0x10000 // 64KB
|
#define PVA_KMD_PVA0_PM_SIZE 0x10000 // 64KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG SID configuration aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the CFG SID register aperture.
|
||||||
|
* Value: 0x20000 (128KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_CFG_SID_SIZE 0x20000 // 128KB
|
#define PVA_KMD_PVA0_CFG_SID_SIZE 0x20000 // 128KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG CCQ configuration aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the CFG CCQ register aperture.
|
||||||
|
* Value: 0x80000 (512KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_CFG_CCQ_SIZE 0x80000 // 512KB
|
#define PVA_KMD_PVA0_CFG_CCQ_SIZE 0x80000 // 512KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the HSP register aperture.
|
||||||
|
* Value: 0x90000 (576KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_HSP_SIZE 0x90000 // 576KB
|
#define PVA_KMD_PVA0_HSP_SIZE 0x90000 // 576KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EVP aperture size
|
||||||
|
*
|
||||||
|
* @details Size of the EVP register aperture.
|
||||||
|
* Value: 0x10000 (64KB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_EVP_SIZE 0x10000 // 64KB
|
#define PVA_KMD_PVA0_EVP_SIZE 0x10000 // 64KB
|
||||||
|
|
||||||
/* Exception vectors */
|
/**
|
||||||
|
* @brief Reset exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the reset exception vector entry point.
|
||||||
|
* This vector is executed when the R5 processor is reset.
|
||||||
|
* Value: 0x20
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_RESET_ADDR 0x20
|
#define PVA_REG_EVP_RESET_ADDR 0x20
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Undefined instruction exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the undefined instruction exception vector.
|
||||||
|
* This vector is executed when an undefined instruction is encountered.
|
||||||
|
* Value: 0x24
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_UNDEF_ADDR 0x24
|
#define PVA_REG_EVP_UNDEF_ADDR 0x24
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Software interrupt exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the software interrupt exception vector.
|
||||||
|
* This vector is executed for software-generated interrupts (SWI).
|
||||||
|
* Value: 0x28
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_SWI_ADDR 0x28
|
#define PVA_REG_EVP_SWI_ADDR 0x28
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prefetch abort exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the prefetch abort exception vector.
|
||||||
|
* This vector is executed when a prefetch abort occurs.
|
||||||
|
* Value: 0x2c
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_PREFETCH_ABORT_ADDR 0x2c
|
#define PVA_REG_EVP_PREFETCH_ABORT_ADDR 0x2c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Data abort exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the data abort exception vector.
|
||||||
|
* This vector is executed when a data abort occurs.
|
||||||
|
* Value: 0x30
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_DATA_ABORT_ADDR 0x30
|
#define PVA_REG_EVP_DATA_ABORT_ADDR 0x30
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reserved exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the reserved exception vector slot.
|
||||||
|
* This vector is reserved for future use.
|
||||||
|
* Value: 0x34
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_RSVD_ADDR 0x34
|
#define PVA_REG_EVP_RSVD_ADDR 0x34
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief IRQ exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the IRQ exception vector.
|
||||||
|
* This vector is executed for interrupt requests (IRQ).
|
||||||
|
* Value: 0x38
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_IRQ_ADDR 0x38
|
#define PVA_REG_EVP_IRQ_ADDR 0x38
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief FIQ exception vector address
|
||||||
|
*
|
||||||
|
* @details Register address for the FIQ exception vector.
|
||||||
|
* This vector is executed for fast interrupt requests (FIQ).
|
||||||
|
* Value: 0x3c
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_FIQ_ADDR 0x3c
|
#define PVA_REG_EVP_FIQ_ADDR 0x3c
|
||||||
|
|
||||||
/* R5 */
|
/**
|
||||||
|
* @brief R5 processor CPU halt control register address
|
||||||
|
*
|
||||||
|
* @details Register address for controlling R5 processor halt state.
|
||||||
|
* Writing to this register can halt or resume the R5 processor.
|
||||||
|
* Value: 0x30000
|
||||||
|
*/
|
||||||
#define PVA_REG_PROC_CPUHALT_ADDR 0x30000
|
#define PVA_REG_PROC_CPUHALT_ADDR 0x30000
|
||||||
|
|
||||||
/* SCRs */
|
/**
|
||||||
|
* @brief SEC external interrupt event SCR address
|
||||||
|
*
|
||||||
|
* @details Register address for SEC external interrupt event control.
|
||||||
|
* This SCR (Secure Configuration Register) manages external interrupts.
|
||||||
|
* Value: 0x28804
|
||||||
|
*/
|
||||||
#define PVA_SEC_SCR_SECEXT_INTR_EVENT 0x28804
|
#define PVA_SEC_SCR_SECEXT_INTR_EVENT 0x28804
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PROC subsystem SCR address
|
||||||
|
*
|
||||||
|
* @details Register address for PROC subsystem control.
|
||||||
|
* This SCR manages processor-related security configuration.
|
||||||
|
* Value: 0x30800
|
||||||
|
*/
|
||||||
#define PVA_PROC_SCR_PROC 0x30800
|
#define PVA_PROC_SCR_PROC 0x30800
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EVP SCR register address
|
||||||
|
*
|
||||||
|
* @details Register address for EVP (Exception Vector Processor) control.
|
||||||
|
* Corresponds to PVA_EVP_SCR_EVP_0 hardware register.
|
||||||
|
* Value: 0x40
|
||||||
|
*/
|
||||||
#define PVA_REG_EVP_SCR_ADDR 0x40 //PVA_EVP_SCR_EVP_0
|
#define PVA_REG_EVP_SCR_ADDR 0x40 //PVA_EVP_SCR_EVP_0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG status control SCR address
|
||||||
|
*
|
||||||
|
* @details Register address for configuration status control.
|
||||||
|
* Corresponds to PVA_CFG_SCR_STATUS_CNTL_0 hardware register.
|
||||||
|
* Value: 0x258000
|
||||||
|
*/
|
||||||
#define PVA_CFG_SCR_STATUS_CNTL 0x258000 //PVA_CFG_SCR_STATUS_CNTL_0
|
#define PVA_CFG_SCR_STATUS_CNTL 0x258000 //PVA_CFG_SCR_STATUS_CNTL_0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege control SCR address
|
||||||
|
*
|
||||||
|
* @details Register address for configuration privilege control.
|
||||||
|
* Corresponds to PVA_CFG_SCR_PRIV_0 hardware register.
|
||||||
|
* Value: 0x258008
|
||||||
|
*/
|
||||||
#define PVA_CFG_SCR_PRIV 0x258008 //PVA_CFG_SCR_PRIV_0
|
#define PVA_CFG_SCR_PRIV 0x258008 //PVA_CFG_SCR_PRIV_0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG CCQ control SCR address
|
||||||
|
*
|
||||||
|
* @details Register address for CCQ (Command and Control Queue) control.
|
||||||
|
* Corresponds to PVA_CFG_SCR_CCQ_CNTL_0 hardware register.
|
||||||
|
* Value: 0x258010
|
||||||
|
*/
|
||||||
#define PVA_CFG_SCR_CCQ_CNTL 0x258010 //PVA_CFG_SCR_CCQ_CNTL_0
|
#define PVA_CFG_SCR_CCQ_CNTL 0x258010 //PVA_CFG_SCR_CCQ_CNTL_0
|
||||||
|
|
||||||
/* HSP */
|
/**
|
||||||
|
* @brief HSP common control register address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP common control functionality.
|
||||||
|
* This controls overall HSP operation and configuration.
|
||||||
|
* Value: 0x160000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_COMMON_ADDR 0x160000
|
#define PVA_REG_HSP_COMMON_ADDR 0x160000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP interrupt enable 0 register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP interrupt enable control (channel 0).
|
||||||
|
* Controls which HSP interrupts are enabled.
|
||||||
|
* Value: 0x160100
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_IE0_ADDR 0x160100
|
#define PVA_REG_HSP_INT_IE0_ADDR 0x160100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP interrupt enable 1 register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP interrupt enable control (channel 1).
|
||||||
|
* Value: 0x160104
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_IE1_ADDR 0x160104
|
#define PVA_REG_HSP_INT_IE1_ADDR 0x160104
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP interrupt enable 2 register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP interrupt enable control (channel 2).
|
||||||
|
* Value: 0x160108
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_IE2_ADDR 0x160108
|
#define PVA_REG_HSP_INT_IE2_ADDR 0x160108
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP interrupt enable 3 register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP interrupt enable control (channel 3).
|
||||||
|
* Value: 0x16010c
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_IE3_ADDR 0x16010c
|
#define PVA_REG_HSP_INT_IE3_ADDR 0x16010c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP interrupt enable 4 register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP interrupt enable control (channel 4).
|
||||||
|
* Value: 0x160110
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_IE4_ADDR 0x160110
|
#define PVA_REG_HSP_INT_IE4_ADDR 0x160110
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP external interrupt register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP external interrupt status and control.
|
||||||
|
* Value: 0x160300
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_EXTERNAL_ADDR 0x160300
|
#define PVA_REG_HSP_INT_EXTERNAL_ADDR 0x160300
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP internal interrupt register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP internal interrupt status and control.
|
||||||
|
* Value: 0x160304
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_INT_INTERNAL_ADDR 0x160304
|
#define PVA_REG_HSP_INT_INTERNAL_ADDR 0x160304
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 0 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 0.
|
||||||
|
* Used for inter-processor communication.
|
||||||
|
* Value: 0x170000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM0_ADDR 0x170000
|
#define PVA_REG_HSP_SM0_ADDR 0x170000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 1 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 1.
|
||||||
|
* Value: 0x178000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM1_ADDR 0x178000
|
#define PVA_REG_HSP_SM1_ADDR 0x178000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 2 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 2.
|
||||||
|
* Value: 0x180000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM2_ADDR 0x180000
|
#define PVA_REG_HSP_SM2_ADDR 0x180000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 3 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 3.
|
||||||
|
* Value: 0x188000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM3_ADDR 0x188000
|
#define PVA_REG_HSP_SM3_ADDR 0x188000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 4 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 4.
|
||||||
|
* Value: 0x190000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM4_ADDR 0x190000
|
#define PVA_REG_HSP_SM4_ADDR 0x190000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 5 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 5.
|
||||||
|
* Value: 0x198000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM5_ADDR 0x198000
|
#define PVA_REG_HSP_SM5_ADDR 0x198000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 6 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 6.
|
||||||
|
* Value: 0x1a0000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM6_ADDR 0x1a0000
|
#define PVA_REG_HSP_SM6_ADDR 0x1a0000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared mailbox 7 base address
|
||||||
|
*
|
||||||
|
* @details Base register address for HSP shared mailbox 7.
|
||||||
|
* Value: 0x1a8000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SM7_ADDR 0x1a8000
|
#define PVA_REG_HSP_SM7_ADDR 0x1a8000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 0 state register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP shared semaphore 0 state.
|
||||||
|
* Used for hardware synchronization between processors.
|
||||||
|
* Value: 0x1b0000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS0_STATE_ADDR 0x1b0000
|
#define PVA_REG_HSP_SS0_STATE_ADDR 0x1b0000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 0 set register address
|
||||||
|
*
|
||||||
|
* @details Register address for setting HSP shared semaphore 0.
|
||||||
|
* Value: 0x1b0004
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS0_SET_ADDR 0x1b0004
|
#define PVA_REG_HSP_SS0_SET_ADDR 0x1b0004
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 0 clear register address
|
||||||
|
*
|
||||||
|
* @details Register address for clearing HSP shared semaphore 0.
|
||||||
|
* Value: 0x1b0008
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS0_CLR_ADDR 0x1b0008
|
#define PVA_REG_HSP_SS0_CLR_ADDR 0x1b0008
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 1 state register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP shared semaphore 1 state.
|
||||||
|
* Value: 0x1c0000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS1_STATE_ADDR 0x1c0000
|
#define PVA_REG_HSP_SS1_STATE_ADDR 0x1c0000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 1 set register address
|
||||||
|
*
|
||||||
|
* @details Register address for setting HSP shared semaphore 1.
|
||||||
|
* Value: 0x1c0004
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS1_SET_ADDR 0x1c0004
|
#define PVA_REG_HSP_SS1_SET_ADDR 0x1c0004
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 1 clear register address
|
||||||
|
*
|
||||||
|
* @details Register address for clearing HSP shared semaphore 1.
|
||||||
|
* Value: 0x1c0008
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS1_CLR_ADDR 0x1c0008
|
#define PVA_REG_HSP_SS1_CLR_ADDR 0x1c0008
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 2 state register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP shared semaphore 2 state.
|
||||||
|
* Value: 0x1d0000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS2_STATE_ADDR 0x1d0000
|
#define PVA_REG_HSP_SS2_STATE_ADDR 0x1d0000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 2 set register address
|
||||||
|
*
|
||||||
|
* @details Register address for setting HSP shared semaphore 2.
|
||||||
|
* Value: 0x1d0004
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS2_SET_ADDR 0x1d0004
|
#define PVA_REG_HSP_SS2_SET_ADDR 0x1d0004
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 2 clear register address
|
||||||
|
*
|
||||||
|
* @details Register address for clearing HSP shared semaphore 2.
|
||||||
|
* Value: 0x1d0008
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS2_CLR_ADDR 0x1d0008
|
#define PVA_REG_HSP_SS2_CLR_ADDR 0x1d0008
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 3 state register address
|
||||||
|
*
|
||||||
|
* @details Register address for HSP shared semaphore 3 state.
|
||||||
|
* Value: 0x1e0000
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS3_STATE_ADDR 0x1e0000
|
#define PVA_REG_HSP_SS3_STATE_ADDR 0x1e0000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 3 set register address
|
||||||
|
*
|
||||||
|
* @details Register address for setting HSP shared semaphore 3.
|
||||||
|
* Value: 0x1e0004
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS3_SET_ADDR 0x1e0004
|
#define PVA_REG_HSP_SS3_SET_ADDR 0x1e0004
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HSP shared semaphore 3 clear register address
|
||||||
|
*
|
||||||
|
* @details Register address for clearing HSP shared semaphore 3.
|
||||||
|
* Value: 0x1e0008
|
||||||
|
*/
|
||||||
#define PVA_REG_HSP_SS3_CLR_ADDR 0x1e0008
|
#define PVA_REG_HSP_SS3_CLR_ADDR 0x1e0008
|
||||||
|
|
||||||
/* SEC */
|
/**
|
||||||
|
* @brief SEC error slice 0 mission error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling mission-critical error detection
|
||||||
|
* on SEC error slice 0. Mission errors are critical system errors.
|
||||||
|
* Value: 0x20030
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE0_MISSIONERR_ENABLE_ADDR 0x20030
|
#define PVA_REG_SEC_ERRSLICE0_MISSIONERR_ENABLE_ADDR 0x20030
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 1 mission error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling mission-critical error detection
|
||||||
|
* on SEC error slice 1.
|
||||||
|
* Value: 0x20060
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE1_MISSIONERR_ENABLE_ADDR 0x20060
|
#define PVA_REG_SEC_ERRSLICE1_MISSIONERR_ENABLE_ADDR 0x20060
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 2 mission error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling mission-critical error detection
|
||||||
|
* on SEC error slice 2.
|
||||||
|
* Value: 0x20090
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE2_MISSIONERR_ENABLE_ADDR 0x20090
|
#define PVA_REG_SEC_ERRSLICE2_MISSIONERR_ENABLE_ADDR 0x20090
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 3 mission error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling mission-critical error detection
|
||||||
|
* on SEC error slice 3.
|
||||||
|
* Value: 0x200c0
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE3_MISSIONERR_ENABLE_ADDR 0x200c0
|
#define PVA_REG_SEC_ERRSLICE3_MISSIONERR_ENABLE_ADDR 0x200c0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 0 latent error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling latent error detection
|
||||||
|
* on SEC error slice 0. Latent errors are non-critical but monitored.
|
||||||
|
* Value: 0x20040
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE0_LATENTERR_ENABLE_ADDR 0x20040
|
#define PVA_REG_SEC_ERRSLICE0_LATENTERR_ENABLE_ADDR 0x20040
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 1 latent error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling latent error detection
|
||||||
|
* on SEC error slice 1.
|
||||||
|
* Value: 0x20070
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE1_LATENTERR_ENABLE_ADDR 0x20070
|
#define PVA_REG_SEC_ERRSLICE1_LATENTERR_ENABLE_ADDR 0x20070
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 2 latent error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling latent error detection
|
||||||
|
* on SEC error slice 2.
|
||||||
|
* Value: 0x200a0
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE2_LATENTERR_ENABLE_ADDR 0x200a0
|
#define PVA_REG_SEC_ERRSLICE2_LATENTERR_ENABLE_ADDR 0x200a0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC error slice 3 latent error enable register address
|
||||||
|
*
|
||||||
|
* @details Register address for enabling latent error detection
|
||||||
|
* on SEC error slice 3.
|
||||||
|
* Value: 0x200d0
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_ERRSLICE3_LATENTERR_ENABLE_ADDR 0x200d0
|
#define PVA_REG_SEC_ERRSLICE3_LATENTERR_ENABLE_ADDR 0x200d0
|
||||||
|
|
||||||
/* SEC_LIC_INTR_STATUS */
|
/**
|
||||||
|
* @brief SEC LIC INTR H1X field MSB bit position
|
||||||
|
*
|
||||||
|
* @details Most significant bit position for H1X interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 7
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_H1X_MSB 7
|
#define PVA_REG_SEC_LIC_INTR_H1X_MSB 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC INTR H1X field LSB bit position
|
||||||
|
*
|
||||||
|
* @details Least significant bit position for H1X interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 5
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_H1X_LSB 5
|
#define PVA_REG_SEC_LIC_INTR_H1X_LSB 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC INTR HSP field MSB bit position
|
||||||
|
*
|
||||||
|
* @details Most significant bit position for HSP interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 4
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_HSP_MSB 4
|
#define PVA_REG_SEC_LIC_INTR_HSP_MSB 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC INTR HSP field LSB bit position
|
||||||
|
*
|
||||||
|
* @details Least significant bit position for HSP interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 1
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_HSP_LSB 1
|
#define PVA_REG_SEC_LIC_INTR_HSP_LSB 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC INTR WDT field MSB bit position
|
||||||
|
*
|
||||||
|
* @details Most significant bit position for watchdog timer interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 0
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_WDT_MSB 0
|
#define PVA_REG_SEC_LIC_INTR_WDT_MSB 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC INTR WDT field LSB bit position
|
||||||
|
*
|
||||||
|
* @details Least significant bit position for watchdog timer interrupt field
|
||||||
|
* in SEC LIC interrupt status register.
|
||||||
|
* Value: 0
|
||||||
|
*/
|
||||||
#define PVA_REG_SEC_LIC_INTR_WDT_LSB 0
|
#define PVA_REG_SEC_LIC_INTR_WDT_LSB 0
|
||||||
|
|
||||||
/* CCQ status 2 */
|
/**
|
||||||
|
* @brief CCQ status 2 interrupt overflow bit
|
||||||
|
*
|
||||||
|
* @details Bit mask for CCQ interrupt overflow condition in status register 2.
|
||||||
|
* Indicates CCQ overflow condition requiring attention.
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_INTR_OVERFLOW_BIT PVA_BIT(28)
|
#define PVA_REG_CCQ_STATUS2_INTR_OVERFLOW_BIT PVA_BIT(28)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ status 2 interrupt status 8 bit
|
||||||
|
*
|
||||||
|
* @details Bit mask for CCQ interrupt status 8 in status register 2.
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT PVA_BIT(24)
|
#define PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT PVA_BIT(24)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ status 2 interrupt status 7 bit
|
||||||
|
*
|
||||||
|
* @details Bit mask for CCQ interrupt status 7 in status register 2.
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_INTR_STATUS7_BIT PVA_BIT(20)
|
#define PVA_REG_CCQ_STATUS2_INTR_STATUS7_BIT PVA_BIT(20)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ status 2 all interrupt bits combined
|
||||||
|
*
|
||||||
|
* @details Combined bit mask for all CCQ interrupt conditions in status register 2.
|
||||||
|
* Includes overflow, status8, and status7 interrupt bits.
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_INTR_ALL_BITS \
|
#define PVA_REG_CCQ_STATUS2_INTR_ALL_BITS \
|
||||||
(PVA_REG_CCQ_STATUS2_INTR_OVERFLOW_BIT | \
|
(PVA_REG_CCQ_STATUS2_INTR_OVERFLOW_BIT | \
|
||||||
PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT | \
|
PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT | \
|
||||||
PVA_REG_CCQ_STATUS2_INTR_STATUS7_BIT)
|
PVA_REG_CCQ_STATUS2_INTR_STATUS7_BIT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ status 2 number of entries field MSB bit position
|
||||||
|
*
|
||||||
|
* @details Most significant bit position for number of entries field
|
||||||
|
* in CCQ status register 2.
|
||||||
|
* Value: 4
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_NUM_ENTRIES_MSB 4
|
#define PVA_REG_CCQ_STATUS2_NUM_ENTRIES_MSB 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ status 2 number of entries field LSB bit position
|
||||||
|
*
|
||||||
|
* @details Least significant bit position for number of entries field
|
||||||
|
* in CCQ status register 2.
|
||||||
|
* Value: 0
|
||||||
|
*/
|
||||||
#define PVA_REG_CCQ_STATUS2_NUM_ENTRIES_LSB 0
|
#define PVA_REG_CCQ_STATUS2_NUM_ENTRIES_LSB 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ register specification structure
|
||||||
|
*
|
||||||
|
* @details This structure defines the register layout for a single CCQ
|
||||||
|
* (Command and Control Queue) interface including status registers and
|
||||||
|
* the command FIFO register. Each CCQ provides an independent command
|
||||||
|
* submission interface between software and firmware.
|
||||||
|
*/
|
||||||
struct pva_kmd_ccq_regspec {
|
struct pva_kmd_ccq_regspec {
|
||||||
|
/**
|
||||||
|
* @brief Number of status registers for this CCQ
|
||||||
|
* Valid range: [1 .. PVA_CFG_CCQ_STATUS_COUNT]
|
||||||
|
*/
|
||||||
uint32_t status_count;
|
uint32_t status_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of CCQ status register addresses
|
||||||
|
*/
|
||||||
uint32_t status[PVA_CFG_CCQ_STATUS_COUNT];
|
uint32_t status[PVA_CFG_CCQ_STATUS_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CCQ FIFO register address for command submission
|
||||||
|
*/
|
||||||
uint32_t fifo;
|
uint32_t fifo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Complete PVA register specification structure
|
||||||
|
*
|
||||||
|
* @details This structure contains the complete register specification for
|
||||||
|
* a PVA device including all subsystem registers, security configuration,
|
||||||
|
* Stream ID configuration, and CCQ interfaces. It provides a comprehensive
|
||||||
|
* mapping of all hardware registers needed for PVA operation.
|
||||||
|
*/
|
||||||
struct pva_kmd_regspec {
|
struct pva_kmd_regspec {
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC interrupt enable register address
|
||||||
|
*/
|
||||||
uint32_t sec_lic_intr_enable;
|
uint32_t sec_lic_intr_enable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SEC LIC interrupt status register address
|
||||||
|
*/
|
||||||
uint32_t sec_lic_intr_status;
|
uint32_t sec_lic_intr_status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG R5 user lower segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_r5user_lsegreg;
|
uint32_t cfg_r5user_lsegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG R5 user upper segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_r5user_usegreg;
|
uint32_t cfg_r5user_usegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR1 lower segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar1_lsegreg;
|
uint32_t cfg_priv_ar1_lsegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR1 upper segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar1_usegreg;
|
uint32_t cfg_priv_ar1_usegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR2 lower segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar2_lsegreg;
|
uint32_t cfg_priv_ar2_lsegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR2 upper segment register address
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar2_usegreg;
|
uint32_t cfg_priv_ar2_usegreg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR1 start address register
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar1_start;
|
uint32_t cfg_priv_ar1_start;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR1 end address register
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar1_end;
|
uint32_t cfg_priv_ar1_end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR2 start address register
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar2_start;
|
uint32_t cfg_priv_ar2_start;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege AR2 end address register
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_ar2_end;
|
uint32_t cfg_priv_ar2_end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG user Stream ID base register address
|
||||||
|
*/
|
||||||
uint32_t cfg_user_sid_base;
|
uint32_t cfg_user_sid_base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG privilege Stream ID register address
|
||||||
|
*/
|
||||||
uint32_t cfg_priv_sid;
|
uint32_t cfg_priv_sid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG VPS Stream ID register address
|
||||||
|
*/
|
||||||
uint32_t cfg_vps_sid;
|
uint32_t cfg_vps_sid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG performance monitor register address
|
||||||
|
*/
|
||||||
uint32_t cfg_perf_mon;
|
uint32_t cfg_perf_mon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CFG SCR privilege 0 register address
|
||||||
|
*/
|
||||||
uint32_t cfg_scr_priv_0;
|
uint32_t cfg_scr_priv_0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of CCQ interfaces available
|
||||||
|
* Valid range: [1 .. PVA_MAX_NUM_CCQ]
|
||||||
|
*/
|
||||||
uint32_t ccq_count;
|
uint32_t ccq_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of VPU debug instruction register offsets
|
||||||
|
*/
|
||||||
uint32_t vpu_dbg_instr_reg_offset[PVA_NUM_ENGINES];
|
uint32_t vpu_dbg_instr_reg_offset[PVA_NUM_ENGINES];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Array of CCQ register specifications
|
||||||
|
*/
|
||||||
struct pva_kmd_ccq_regspec ccq_regs[PVA_MAX_NUM_CCQ];
|
struct pva_kmd_ccq_regspec ccq_regs[PVA_MAX_NUM_CCQ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enumeration of PVA register apertures
|
||||||
|
*
|
||||||
|
* @details This enumeration defines the different register apertures within
|
||||||
|
* the PVA hardware that can be accessed for device control and monitoring.
|
||||||
|
* Each aperture corresponds to a specific subsystem or functional block
|
||||||
|
* within the PVA cluster.
|
||||||
|
*/
|
||||||
enum pva_kmd_reg_aperture {
|
enum pva_kmd_reg_aperture {
|
||||||
/** Main PVA_CLUSTER aperture */
|
/** @brief Main PVA cluster aperture containing all subsystems */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER = 0,
|
PVA_KMD_APERTURE_PVA_CLUSTER = 0,
|
||||||
/** Sub-clusters within PVA_CLUSTER */
|
/** @brief SEC (Security) subsystem aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_SEC,
|
PVA_KMD_APERTURE_PVA_CLUSTER_SEC,
|
||||||
|
/** @brief PROC (Processor) subsystem aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_PROC,
|
PVA_KMD_APERTURE_PVA_CLUSTER_PROC,
|
||||||
|
/** @brief PM (Power Management) subsystem aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_PM,
|
PVA_KMD_APERTURE_PVA_CLUSTER_PM,
|
||||||
|
/** @brief HSP (Hardware Synchronization Primitives) aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_HSP,
|
PVA_KMD_APERTURE_PVA_CLUSTER_HSP,
|
||||||
|
/** @brief EVP (Exception Vector Processor) aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_EVP,
|
PVA_KMD_APERTURE_PVA_CLUSTER_EVP,
|
||||||
|
/** @brief CFG SID (Stream ID configuration) aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_CFG_SID,
|
PVA_KMD_APERTURE_PVA_CLUSTER_CFG_SID,
|
||||||
|
/** @brief CFG CCQ (Command and Control Queue configuration) aperture */
|
||||||
PVA_KMD_APERTURE_PVA_CLUSTER_CFG_CCQ,
|
PVA_KMD_APERTURE_PVA_CLUSTER_CFG_CCQ,
|
||||||
/** Debug aperture */
|
/** @brief VPU debug aperture for debugging support */
|
||||||
PVA_KMD_APERTURE_VPU_DEBUG,
|
PVA_KMD_APERTURE_VPU_DEBUG,
|
||||||
|
/** @brief Total number of apertures */
|
||||||
PVA_KMD_APERTURE_COUNT,
|
PVA_KMD_APERTURE_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,17 +51,26 @@ pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
|||||||
uint32_t max_dma_config_size = get_max_dma_config_size(pva);
|
uint32_t max_dma_config_size = get_max_dma_config_size(pva);
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
uint32_t size_u32;
|
||||||
|
|
||||||
res_table->pva = pva;
|
res_table->pva = pva;
|
||||||
res_table->n_entries = n_entries;
|
res_table->n_entries = safe_addu32(n_entries, PVA_MAX_PRIV_RES_ID);
|
||||||
res_table->user_smmu_ctx_id = user_smmu_ctx_id;
|
res_table->user_smmu_ctx_id = user_smmu_ctx_id;
|
||||||
pva_kmd_sema_init(&res_table->resource_semaphore, n_entries);
|
pva_kmd_sema_init(&res_table->resource_semaphore, res_table->n_entries);
|
||||||
pva_kmd_mutex_init(&res_table->resource_table_lock);
|
err = pva_kmd_mutex_init(&res_table->resource_table_lock);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_resource_table_init mutex_init failed");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
size = (uint64_t)safe_mulu32(
|
size = (uint64_t)safe_mulu32(
|
||||||
n_entries, (uint32_t)sizeof(struct pva_resource_entry));
|
res_table->n_entries,
|
||||||
size += (uint64_t)safe_mulu32(
|
(uint32_t)sizeof(struct pva_resource_entry));
|
||||||
n_entries, (uint32_t)sizeof(struct pva_resource_aux_info));
|
size = safe_addu64(
|
||||||
|
size, (uint64_t)safe_mulu32(
|
||||||
|
res_table->n_entries,
|
||||||
|
(uint32_t)sizeof(struct pva_resource_aux_info)));
|
||||||
res_table->table_mem = pva_kmd_device_memory_alloc_map(
|
res_table->table_mem = pva_kmd_device_memory_alloc_map(
|
||||||
size, pva, PVA_ACCESS_RW, PVA_R5_SMMU_CONTEXT_ID);
|
size, pva, PVA_ACCESS_RW, PVA_R5_SMMU_CONTEXT_ID);
|
||||||
if (res_table->table_mem == NULL) {
|
if (res_table->table_mem == NULL) {
|
||||||
@@ -69,9 +78,10 @@ pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
|||||||
goto deinit_locks;
|
goto deinit_locks;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = (uint64_t)safe_mulu32(sizeof(struct pva_kmd_resource_record),
|
size_u32 = safe_mulu32((uint32_t)sizeof(struct pva_kmd_resource_record),
|
||||||
n_entries);
|
res_table->n_entries);
|
||||||
res_table->records_mem = pva_kmd_zalloc(size);
|
res_table->records_mem =
|
||||||
|
(struct pva_kmd_resource_record *)pva_kmd_zalloc(size_u32);
|
||||||
|
|
||||||
if (res_table->records_mem == NULL) {
|
if (res_table->records_mem == NULL) {
|
||||||
err = PVA_NOMEM;
|
err = PVA_NOMEM;
|
||||||
@@ -79,13 +89,26 @@ pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = pva_kmd_block_allocator_init(
|
err = pva_kmd_block_allocator_init(
|
||||||
&res_table->resource_record_allocator, res_table->records_mem,
|
&res_table->priv_resource_record_allocator,
|
||||||
PVA_RESOURCE_ID_BASE, sizeof(struct pva_kmd_resource_record),
|
res_table->records_mem, PVA_RESOURCE_ID_BASE,
|
||||||
n_entries);
|
(uint32_t)sizeof(struct pva_kmd_resource_record),
|
||||||
|
PVA_MAX_PRIV_RES_ID);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto free_records_mem;
|
goto free_records_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = pva_kmd_block_allocator_init(
|
||||||
|
&res_table->resource_record_allocator,
|
||||||
|
(uint8_t *)res_table->records_mem +
|
||||||
|
safe_mulu32(PVA_MAX_PRIV_RES_ID,
|
||||||
|
(uint32_t)sizeof(
|
||||||
|
struct pva_kmd_resource_record)),
|
||||||
|
PVA_USER_RESOURCE_ID_BASE,
|
||||||
|
(uint32_t)sizeof(struct pva_kmd_resource_record), n_entries);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto free_priv_resource_record_allocator;
|
||||||
|
}
|
||||||
|
|
||||||
err = pva_kmd_devmem_pool_init(&res_table->dma_config_pool, pva,
|
err = pva_kmd_devmem_pool_init(&res_table->dma_config_pool, pva,
|
||||||
PVA_R5_SMMU_CONTEXT_ID,
|
PVA_R5_SMMU_CONTEXT_ID,
|
||||||
max_dma_config_size,
|
max_dma_config_size,
|
||||||
@@ -98,6 +121,9 @@ pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
|||||||
|
|
||||||
free_resource_record_allocator:
|
free_resource_record_allocator:
|
||||||
pva_kmd_block_allocator_deinit(&res_table->resource_record_allocator);
|
pva_kmd_block_allocator_deinit(&res_table->resource_record_allocator);
|
||||||
|
free_priv_resource_record_allocator:
|
||||||
|
pva_kmd_block_allocator_deinit(
|
||||||
|
&res_table->priv_resource_record_allocator);
|
||||||
free_records_mem:
|
free_records_mem:
|
||||||
pva_kmd_free(res_table->records_mem);
|
pva_kmd_free(res_table->records_mem);
|
||||||
free_table_mem:
|
free_table_mem:
|
||||||
@@ -110,7 +136,7 @@ deinit_locks:
|
|||||||
|
|
||||||
static struct pva_kmd_resource_record *
|
static struct pva_kmd_resource_record *
|
||||||
pva_kmd_alloc_resource_id(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_alloc_resource_id(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t *out_resource_id)
|
uint32_t *out_resource_id, bool priv)
|
||||||
{
|
{
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
struct pva_kmd_resource_record *rec = NULL;
|
struct pva_kmd_resource_record *rec = NULL;
|
||||||
@@ -129,9 +155,21 @@ pva_kmd_alloc_resource_id(struct pva_kmd_resource_table *resource_table,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv) {
|
||||||
rec = (struct pva_kmd_resource_record *)pva_kmd_zalloc_block(
|
rec = (struct pva_kmd_resource_record *)pva_kmd_zalloc_block(
|
||||||
&resource_table->resource_record_allocator, out_resource_id);
|
&resource_table->priv_resource_record_allocator,
|
||||||
ASSERT(rec != NULL);
|
out_resource_id);
|
||||||
|
} else {
|
||||||
|
rec = (struct pva_kmd_resource_record *)pva_kmd_zalloc_block(
|
||||||
|
&resource_table->resource_record_allocator,
|
||||||
|
out_resource_id);
|
||||||
|
}
|
||||||
|
if (rec == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_alloc_resource_id: No available resource slots");
|
||||||
|
pva_kmd_sema_post(&resource_table->resource_semaphore);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return rec;
|
return rec;
|
||||||
@@ -143,8 +181,15 @@ pva_kmd_free_resource_id(struct pva_kmd_resource_table *resource_table,
|
|||||||
{
|
{
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
|
|
||||||
err = pva_kmd_free_block(&resource_table->resource_record_allocator,
|
if (resource_id <= PVA_MAX_PRIV_RES_ID) {
|
||||||
|
err = pva_kmd_free_block(
|
||||||
|
&resource_table->priv_resource_record_allocator,
|
||||||
resource_id);
|
resource_id);
|
||||||
|
} else {
|
||||||
|
err = pva_kmd_free_block(
|
||||||
|
&resource_table->resource_record_allocator,
|
||||||
|
resource_id);
|
||||||
|
}
|
||||||
ASSERT(err == PVA_SUCCESS);
|
ASSERT(err == PVA_SUCCESS);
|
||||||
|
|
||||||
pva_kmd_sema_post(&resource_table->resource_semaphore);
|
pva_kmd_sema_post(&resource_table->resource_semaphore);
|
||||||
@@ -154,9 +199,8 @@ static void
|
|||||||
pva_kmd_release_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_release_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id, bool drop_dma_reference)
|
uint32_t resource_id, bool drop_dma_reference)
|
||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec = pva_kmd_get_block_unsafe(
|
struct pva_kmd_resource_record *rec =
|
||||||
&resource_table->resource_record_allocator, resource_id);
|
pva_kmd_peek_resource(resource_table, resource_id);
|
||||||
|
|
||||||
ASSERT(rec != NULL);
|
ASSERT(rec != NULL);
|
||||||
|
|
||||||
switch (rec->type) {
|
switch (rec->type) {
|
||||||
@@ -180,6 +224,7 @@ pva_kmd_release_resource(struct pva_kmd_resource_table *resource_table,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
FAULT("Unsupported resource type");
|
FAULT("Unsupported resource type");
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
pva_kmd_free_resource_id(resource_table, resource_id);
|
pva_kmd_free_resource_id(resource_table, resource_id);
|
||||||
@@ -188,13 +233,14 @@ pva_kmd_release_resource(struct pva_kmd_resource_table *resource_table,
|
|||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_add_dram_buffer_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_add_dram_buffer_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
struct pva_kmd_device_memory *dev_mem,
|
struct pva_kmd_device_memory *dev_mem,
|
||||||
uint32_t *out_resource_id)
|
uint32_t *out_resource_id, bool priv)
|
||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec =
|
struct pva_kmd_resource_record *rec = pva_kmd_alloc_resource_id(
|
||||||
pva_kmd_alloc_resource_id(resource_table, out_resource_id);
|
resource_table, out_resource_id, priv);
|
||||||
|
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
pva_kmd_log_err("No more resource id");
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_add_dram_buffer_resource No more resource id");
|
||||||
return PVA_NO_RESOURCE_ID;
|
return PVA_NO_RESOURCE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,8 +283,13 @@ void pva_kmd_update_fw_resource_table(struct pva_kmd_resource_table *res_table)
|
|||||||
for (id = PVA_RESOURCE_ID_BASE; id <= max_resource_id; id++) {
|
for (id = PVA_RESOURCE_ID_BASE; id <= max_resource_id; id++) {
|
||||||
struct pva_resource_entry *entry =
|
struct pva_resource_entry *entry =
|
||||||
get_fw_resource(res_table, id);
|
get_fw_resource(res_table, id);
|
||||||
|
if (id <= PVA_MAX_PRIV_RES_ID) {
|
||||||
|
rec = pva_kmd_get_block_unsafe(
|
||||||
|
&res_table->priv_resource_record_allocator, id);
|
||||||
|
} else {
|
||||||
rec = pva_kmd_get_block_unsafe(
|
rec = pva_kmd_get_block_unsafe(
|
||||||
&res_table->resource_record_allocator, id);
|
&res_table->resource_record_allocator, id);
|
||||||
|
}
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -251,13 +302,17 @@ void pva_kmd_update_fw_resource_table(struct pva_kmd_resource_table *res_table)
|
|||||||
entry->size_lo = iova_lo(rec->dram.mem->size);
|
entry->size_lo = iova_lo(rec->dram.mem->size);
|
||||||
entry->size_hi = iova_hi(rec->dram.mem->size);
|
entry->size_hi = iova_hi(rec->dram.mem->size);
|
||||||
entry->smmu_context_id = rec->dram.mem->smmu_ctx_idx;
|
entry->smmu_context_id = rec->dram.mem->smmu_ctx_idx;
|
||||||
entry->access_flags = rec->dram.mem->iova_access_flags;
|
/* CERT INT31-C: iova_access_flags limited to PVA_ACCESS_* values (1,2,3),
|
||||||
|
* always fits in uint8_t, safe to cast */
|
||||||
|
entry->access_flags =
|
||||||
|
(uint8_t)rec->dram.mem->iova_access_flags;
|
||||||
break;
|
break;
|
||||||
case PVA_RESOURCE_TYPE_INVALID:
|
case PVA_RESOURCE_TYPE_INVALID:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pva_kmd_log_err("Unsupported resource type");
|
pva_kmd_log_err("Unsupported resource type");
|
||||||
pva_kmd_fault();
|
pva_kmd_fault();
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,9 +321,8 @@ struct pva_kmd_resource_record *
|
|||||||
pva_kmd_use_resource_unsafe(struct pva_kmd_resource_table *res_table,
|
pva_kmd_use_resource_unsafe(struct pva_kmd_resource_table *res_table,
|
||||||
uint32_t resource_id)
|
uint32_t resource_id)
|
||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec = pva_kmd_get_block_unsafe(
|
struct pva_kmd_resource_record *rec =
|
||||||
&res_table->resource_record_allocator, resource_id);
|
pva_kmd_peek_resource(res_table, resource_id);
|
||||||
|
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -283,9 +337,8 @@ pva_kmd_use_resource(struct pva_kmd_resource_table *res_table,
|
|||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec;
|
struct pva_kmd_resource_record *rec;
|
||||||
pva_kmd_mutex_lock(&res_table->resource_table_lock);
|
pva_kmd_mutex_lock(&res_table->resource_table_lock);
|
||||||
rec = pva_kmd_get_block_unsafe(&res_table->resource_record_allocator,
|
|
||||||
resource_id);
|
|
||||||
|
|
||||||
|
rec = pva_kmd_peek_resource(res_table, resource_id);
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
pva_kmd_mutex_unlock(&res_table->resource_table_lock);
|
pva_kmd_mutex_unlock(&res_table->resource_table_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -301,8 +354,15 @@ struct pva_kmd_resource_record *
|
|||||||
pva_kmd_peek_resource(struct pva_kmd_resource_table *res_table,
|
pva_kmd_peek_resource(struct pva_kmd_resource_table *res_table,
|
||||||
uint32_t resource_id)
|
uint32_t resource_id)
|
||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec = pva_kmd_get_block_unsafe(
|
struct pva_kmd_resource_record *rec;
|
||||||
|
if (resource_id <= PVA_MAX_PRIV_RES_ID) {
|
||||||
|
rec = pva_kmd_get_block_unsafe(
|
||||||
|
&res_table->priv_resource_record_allocator,
|
||||||
|
resource_id);
|
||||||
|
} else {
|
||||||
|
rec = pva_kmd_get_block_unsafe(
|
||||||
&res_table->resource_record_allocator, resource_id);
|
&res_table->resource_record_allocator, resource_id);
|
||||||
|
}
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
@@ -318,10 +378,8 @@ void pva_kmd_drop_resource(struct pva_kmd_resource_table *resource_table,
|
|||||||
void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id)
|
uint32_t resource_id)
|
||||||
{
|
{
|
||||||
struct pva_kmd_resource_record *rec;
|
struct pva_kmd_resource_record *rec =
|
||||||
|
pva_kmd_peek_resource(resource_table, resource_id);
|
||||||
rec = pva_kmd_get_block_unsafe(
|
|
||||||
&resource_table->resource_record_allocator, resource_id);
|
|
||||||
|
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
pva_kmd_log_err_u64("Unexpected resource ID drop", resource_id);
|
pva_kmd_log_err_u64("Unexpected resource ID drop", resource_id);
|
||||||
@@ -329,7 +387,7 @@ void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rec->ref_count = safe_subu32(rec->ref_count, 1U);
|
rec->ref_count = safe_subu32(rec->ref_count, 1U);
|
||||||
if (rec->ref_count == 0) {
|
if (rec->ref_count == 0U) {
|
||||||
pva_kmd_release_resource(resource_table, resource_id, true);
|
pva_kmd_release_resource(resource_table, resource_id, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,15 +395,17 @@ void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
|||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_add_vpu_bin_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_add_vpu_bin_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
const void *executable, uint32_t executable_size,
|
const void *executable, uint32_t executable_size,
|
||||||
uint32_t *out_resource_id)
|
uint32_t *out_resource_id, bool priv)
|
||||||
{
|
{
|
||||||
uint32_t res_id;
|
uint32_t res_id;
|
||||||
struct pva_kmd_resource_record *rec =
|
struct pva_kmd_resource_record *rec =
|
||||||
pva_kmd_alloc_resource_id(resource_table, &res_id);
|
pva_kmd_alloc_resource_id(resource_table, &res_id, priv);
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
struct pva_kmd_vpu_bin_resource *vpu_bin;
|
struct pva_kmd_vpu_bin_resource *vpu_bin;
|
||||||
|
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_add_vpu_bin_resource No more resource id");
|
||||||
err = PVA_NO_RESOURCE_ID;
|
err = PVA_NO_RESOURCE_ID;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@@ -395,7 +455,9 @@ pva_kmd_make_resource_entry(struct pva_kmd_resource_table *resource_table,
|
|||||||
entry->size_lo = iova_lo(rec->dram.mem->size);
|
entry->size_lo = iova_lo(rec->dram.mem->size);
|
||||||
entry->size_hi = iova_hi(rec->dram.mem->size);
|
entry->size_hi = iova_hi(rec->dram.mem->size);
|
||||||
entry->smmu_context_id = rec->dram.mem->smmu_ctx_idx;
|
entry->smmu_context_id = rec->dram.mem->smmu_ctx_idx;
|
||||||
entry->access_flags = rec->dram.mem->iova_access_flags;
|
/* CERT INT31-C: iova_access_flags limited to PVA_ACCESS_* values (1,2,3),
|
||||||
|
* always fits in uint8_t, safe to cast */
|
||||||
|
entry->access_flags = (uint8_t)rec->dram.mem->iova_access_flags;
|
||||||
break;
|
break;
|
||||||
case PVA_RESOURCE_TYPE_EXEC_BIN:
|
case PVA_RESOURCE_TYPE_EXEC_BIN:
|
||||||
entry->type = rec->type;
|
entry->type = rec->type;
|
||||||
@@ -419,6 +481,7 @@ pva_kmd_make_resource_entry(struct pva_kmd_resource_table *resource_table,
|
|||||||
default:
|
default:
|
||||||
pva_kmd_log_err("Unsupported resource type");
|
pva_kmd_log_err("Unsupported resource type");
|
||||||
pva_kmd_fault();
|
pva_kmd_fault();
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
pva_kmd_drop_resource(resource_table, resource_id);
|
pva_kmd_drop_resource(resource_table, resource_id);
|
||||||
@@ -428,7 +491,7 @@ pva_kmd_make_resource_entry(struct pva_kmd_resource_table *resource_table,
|
|||||||
enum pva_error pva_kmd_add_dma_config_resource(
|
enum pva_error pva_kmd_add_dma_config_resource(
|
||||||
struct pva_kmd_resource_table *resource_table,
|
struct pva_kmd_resource_table *resource_table,
|
||||||
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
||||||
uint32_t dma_config_size, uint32_t *out_resource_id)
|
uint32_t dma_config_size, uint32_t *out_resource_id, bool priv)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
uint32_t fw_fetch_size;
|
uint32_t fw_fetch_size;
|
||||||
@@ -437,6 +500,7 @@ enum pva_error pva_kmd_add_dma_config_resource(
|
|||||||
struct pva_kmd_resource_record *rec;
|
struct pva_kmd_resource_record *rec;
|
||||||
uint32_t res_id;
|
uint32_t res_id;
|
||||||
struct pva_kmd_devmem_element dma_cfg_mem = { 0 };
|
struct pva_kmd_devmem_element dma_cfg_mem = { 0 };
|
||||||
|
bool skip_validation = false;
|
||||||
|
|
||||||
err = pva_kmd_devmem_pool_zalloc(&resource_table->dma_config_pool,
|
err = pva_kmd_devmem_pool_zalloc(&resource_table->dma_config_pool,
|
||||||
&dma_cfg_mem);
|
&dma_cfg_mem);
|
||||||
@@ -445,9 +509,7 @@ enum pva_error pva_kmd_add_dma_config_resource(
|
|||||||
}
|
}
|
||||||
fw_dma_cfg = pva_kmd_get_devmem_va(&dma_cfg_mem);
|
fw_dma_cfg = pva_kmd_get_devmem_va(&dma_cfg_mem);
|
||||||
|
|
||||||
// Must satisfy alignment requirement for converting to struct
|
ASSERT(((uintptr_t)(void *)fw_dma_cfg) % sizeof(uint64_t) == 0UL);
|
||||||
// pva_dma_config_resource*
|
|
||||||
ASSERT(((uintptr_t)fw_dma_cfg) % sizeof(uint64_t) == 0);
|
|
||||||
|
|
||||||
dma_aux = pva_kmd_zalloc(sizeof(struct pva_kmd_dma_resource_aux));
|
dma_aux = pva_kmd_zalloc(sizeof(struct pva_kmd_dma_resource_aux));
|
||||||
if (dma_aux == NULL) {
|
if (dma_aux == NULL) {
|
||||||
@@ -456,16 +518,17 @@ enum pva_error pva_kmd_add_dma_config_resource(
|
|||||||
}
|
}
|
||||||
dma_aux->res_table = resource_table;
|
dma_aux->res_table = resource_table;
|
||||||
|
|
||||||
|
skip_validation = (priv || resource_table->pva->test_mode);
|
||||||
pva_kmd_mutex_lock(&resource_table->resource_table_lock);
|
pva_kmd_mutex_lock(&resource_table->resource_table_lock);
|
||||||
err = pva_kmd_load_dma_config(resource_table, dma_cfg_hdr,
|
err = pva_kmd_load_dma_config(resource_table, dma_cfg_hdr,
|
||||||
dma_config_size, dma_aux, fw_dma_cfg,
|
dma_config_size, dma_aux, fw_dma_cfg,
|
||||||
&fw_fetch_size);
|
&fw_fetch_size, skip_validation);
|
||||||
pva_kmd_mutex_unlock(&resource_table->resource_table_lock);
|
pva_kmd_mutex_unlock(&resource_table->resource_table_lock);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto free_dma_aux;
|
goto free_dma_aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = pva_kmd_alloc_resource_id(resource_table, &res_id);
|
rec = pva_kmd_alloc_resource_id(resource_table, &res_id, priv);
|
||||||
if (rec == NULL) {
|
if (rec == NULL) {
|
||||||
err = PVA_NO_RESOURCE_ID;
|
err = PVA_NO_RESOURCE_ID;
|
||||||
goto unload_dma;
|
goto unload_dma;
|
||||||
@@ -521,8 +584,10 @@ pva_kmd_release_all_resources(struct pva_kmd_resource_table *res_table)
|
|||||||
|
|
||||||
void pva_kmd_resource_table_deinit(struct pva_kmd_resource_table *res_table)
|
void pva_kmd_resource_table_deinit(struct pva_kmd_resource_table *res_table)
|
||||||
{
|
{
|
||||||
pva_kmd_release_all_resources(res_table);
|
(void)pva_kmd_release_all_resources(res_table);
|
||||||
pva_kmd_block_allocator_deinit(&res_table->resource_record_allocator);
|
pva_kmd_block_allocator_deinit(&res_table->resource_record_allocator);
|
||||||
|
pva_kmd_block_allocator_deinit(
|
||||||
|
&res_table->priv_resource_record_allocator);
|
||||||
pva_kmd_free(res_table->records_mem);
|
pva_kmd_free(res_table->records_mem);
|
||||||
pva_kmd_devmem_pool_deinit(&res_table->dma_config_pool);
|
pva_kmd_devmem_pool_deinit(&res_table->dma_config_pool);
|
||||||
pva_kmd_mutex_deinit(&res_table->resource_table_lock);
|
pva_kmd_mutex_deinit(&res_table->resource_table_lock);
|
||||||
@@ -535,7 +600,10 @@ void pva_kmd_resource_table_lock(struct pva_kmd_device *pva,
|
|||||||
{
|
{
|
||||||
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, res_table_id);
|
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, res_table_id);
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&ctx->ctx_resource_table.resource_table_lock);
|
if (ctx != NULL) {
|
||||||
|
pva_kmd_mutex_lock(
|
||||||
|
&ctx->ctx_resource_table.resource_table_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_resource_table_unlock(struct pva_kmd_device *pva,
|
void pva_kmd_resource_table_unlock(struct pva_kmd_device *pva,
|
||||||
@@ -543,5 +611,8 @@ void pva_kmd_resource_table_unlock(struct pva_kmd_device *pva,
|
|||||||
{
|
{
|
||||||
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, res_table_id);
|
struct pva_kmd_context *ctx = pva_kmd_get_context(pva, res_table_id);
|
||||||
|
|
||||||
pva_kmd_mutex_unlock(&ctx->ctx_resource_table.resource_table_lock);
|
if (ctx != NULL) {
|
||||||
|
pva_kmd_mutex_unlock(
|
||||||
|
&ctx->ctx_resource_table.resource_table_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,128 +16,575 @@
|
|||||||
#include "pva_kmd_thread_sema.h"
|
#include "pva_kmd_thread_sema.h"
|
||||||
#include "pva_kmd_devmem_pool.h"
|
#include "pva_kmd_devmem_pool.h"
|
||||||
|
|
||||||
|
#define PVA_USER_RESOURCE_ID_BASE (PVA_MAX_PRIV_RES_ID + 1U)
|
||||||
|
|
||||||
struct pva_kmd_device;
|
struct pva_kmd_device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource structure for DRAM memory buffers
|
||||||
|
*
|
||||||
|
* @details This structure contains information about a DRAM memory buffer
|
||||||
|
* resource that has been registered with the resource table. It provides
|
||||||
|
* access to the device memory allocation that backs the DRAM resource.
|
||||||
|
*/
|
||||||
struct pva_kmd_dram_resource {
|
struct pva_kmd_dram_resource {
|
||||||
|
/**
|
||||||
|
* @brief Pointer to device memory allocation for this DRAM resource
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *mem;
|
struct pva_kmd_device_memory *mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource structure for VPU binary executables
|
||||||
|
*
|
||||||
|
* @details This structure contains information about a VPU executable binary
|
||||||
|
* that has been loaded and registered with the resource table. It includes
|
||||||
|
* both metadata and code sections, along with symbol table information for
|
||||||
|
* proper executable management and debugging.
|
||||||
|
*/
|
||||||
struct pva_kmd_vpu_bin_resource {
|
struct pva_kmd_vpu_bin_resource {
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for executable metadata
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *metainfo_mem;
|
struct pva_kmd_device_memory *metainfo_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation for executable code sections
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *sections_mem;
|
struct pva_kmd_device_memory *sections_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Symbol table for debugging and runtime symbol resolution
|
||||||
|
*/
|
||||||
struct pva_kmd_exec_symbol_table symbol_table;
|
struct pva_kmd_exec_symbol_table symbol_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource structure for DMA configuration objects
|
||||||
|
*
|
||||||
|
* @details This structure contains information about a DMA configuration
|
||||||
|
* that has been validated and registered with the resource table. It includes
|
||||||
|
* the device memory element, auxiliary memory, and addressing information
|
||||||
|
* needed for DMA operations.
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_config_resource {
|
struct pva_kmd_dma_config_resource {
|
||||||
|
/**
|
||||||
|
* @brief Device memory element for DMA configuration storage
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_element devmem;
|
struct pva_kmd_devmem_element devmem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Auxiliary memory for additional DMA configuration data
|
||||||
|
*/
|
||||||
struct pva_kmd_dma_resource_aux *aux_mem;
|
struct pva_kmd_dma_resource_aux *aux_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of the DMA configuration in bytes
|
||||||
|
* Valid range: [1 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief IOVA address for hardware access to DMA configuration
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t iova_addr;
|
uint64_t iova_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resource record for tracking registered resources
|
||||||
|
*
|
||||||
|
* @details This structure represents a single entry in the resource table,
|
||||||
|
* containing type information, reference counting, and type-specific data
|
||||||
|
* for the resource. Resources can be DRAM buffers, VPU executables, or
|
||||||
|
* DMA configurations, each with their own specific data requirements.
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_record {
|
struct pva_kmd_resource_record {
|
||||||
/**
|
/**
|
||||||
* Possible types:
|
* @brief Type of resource stored in this record
|
||||||
* PVA_RESOURCE_TYPE_DRAM
|
*
|
||||||
* PVA_RESOURCE_TYPE_EXEC_BIN
|
* @details Possible types:
|
||||||
* PVA_RESOURCE_TYPE_DMA_CONFIG
|
* - PVA_RESOURCE_TYPE_DRAM
|
||||||
|
* - PVA_RESOURCE_TYPE_EXEC_BIN
|
||||||
|
* - PVA_RESOURCE_TYPE_DMA_CONFIG
|
||||||
|
* Valid values: @ref pva_resource_type enumeration values
|
||||||
*/
|
*/
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reference count for tracking resource usage
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t ref_count;
|
uint32_t ref_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Union containing type-specific resource data
|
||||||
|
*/
|
||||||
union {
|
union {
|
||||||
|
/** @brief DRAM resource data */
|
||||||
struct pva_kmd_dram_resource dram;
|
struct pva_kmd_dram_resource dram;
|
||||||
|
/** @brief VPU binary resource data */
|
||||||
struct pva_kmd_vpu_bin_resource vpu_bin;
|
struct pva_kmd_vpu_bin_resource vpu_bin;
|
||||||
|
/** @brief DMA configuration resource data */
|
||||||
struct pva_kmd_dma_config_resource dma_config;
|
struct pva_kmd_dma_config_resource dma_config;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @brief Resource table for managing hardware resources and firmware communication
|
||||||
*
|
*
|
||||||
|
* @details This structure manages the resource table used for communication
|
||||||
|
* between KMD and firmware. It provides secure resource management through
|
||||||
|
* indirection, where user space applications use opaque resource IDs instead
|
||||||
|
* of direct hardware addresses. The table supports different resource types
|
||||||
|
* including DRAM buffers, VPU executables, and DMA configurations.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_resource_table {
|
struct pva_kmd_resource_table {
|
||||||
/** @brief User smmu context ID.
|
/**
|
||||||
|
* @brief User SMMU context ID for memory protection
|
||||||
*
|
*
|
||||||
* - DRAM memory, VPU data/text sections will be mapped to this space.
|
* @details - DRAM memory, VPU data/text sections will be mapped to this space.
|
||||||
* - VPU metadata, DMA configurations will always be mapped to R5 SMMU
|
* - VPU metadata, DMA configurations will always be mapped to R5 SMMU context.
|
||||||
* context. */
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
*/
|
||||||
uint8_t user_smmu_ctx_id;
|
uint8_t user_smmu_ctx_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of allocated entries in the resource table
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t n_entries;
|
uint32_t n_entries;
|
||||||
/** Maximum resource ID we have seen so far */
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum resource ID allocated so far
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t curr_max_resource_id;
|
uint32_t curr_max_resource_id;
|
||||||
|
|
||||||
/** Semaphore to keep track of resources in use*/
|
/**
|
||||||
|
* @brief Semaphore to track resources currently in use
|
||||||
|
*
|
||||||
|
* @details Semaphore to keep track of resources in use
|
||||||
|
*/
|
||||||
pva_kmd_sema_t resource_semaphore;
|
pva_kmd_sema_t resource_semaphore;
|
||||||
|
|
||||||
/** Memory for resource table entries, in R5 segment */
|
/**
|
||||||
|
* @brief Device memory for resource table entries in R5 segment
|
||||||
|
*
|
||||||
|
* @details Memory for resource table entries, in R5 segment
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *table_mem;
|
struct pva_kmd_device_memory *table_mem;
|
||||||
|
|
||||||
/** Pool for FW DMA configurations */
|
/**
|
||||||
|
* @brief Memory pool for firmware DMA configurations
|
||||||
|
*
|
||||||
|
* @details Pool for FW DMA configurations
|
||||||
|
*/
|
||||||
struct pva_kmd_devmem_pool dma_config_pool;
|
struct pva_kmd_devmem_pool dma_config_pool;
|
||||||
|
|
||||||
/** Memory for resource records */
|
/**
|
||||||
|
* @brief Memory allocation for resource record storage
|
||||||
|
*
|
||||||
|
* @details Memory for resource records
|
||||||
|
*/
|
||||||
void *records_mem;
|
void *records_mem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing resource record allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_block_allocator resource_record_allocator;
|
struct pva_kmd_block_allocator resource_record_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Block allocator for managing privileged resource record allocation
|
||||||
|
*/
|
||||||
|
struct pva_kmd_block_allocator priv_resource_record_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to parent PVA device
|
||||||
|
*/
|
||||||
struct pva_kmd_device *pva;
|
struct pva_kmd_device *pva;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mutex protecting resource table operations
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t resource_table_lock;
|
pva_kmd_mutex_t resource_table_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a resource table for KMD-firmware communication
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates device memory for the resource table entries
|
||||||
|
* - Initializes the resource record allocator for managing entries
|
||||||
|
* - Sets up the DMA configuration pool for firmware DMA operations
|
||||||
|
* - Configures SMMU context for user memory protection
|
||||||
|
* - Initializes synchronization primitives for thread-safe access
|
||||||
|
* - Prepares the table for resource registration and management
|
||||||
|
* - Establishes communication interface with firmware
|
||||||
|
*
|
||||||
|
* The initialized resource table provides secure resource management by
|
||||||
|
* using opaque resource IDs instead of direct hardware addresses. After
|
||||||
|
* initialization, resources can be registered using the various add
|
||||||
|
* functions and accessed through resource IDs.
|
||||||
|
*
|
||||||
|
* @param[out] res_table Pointer to @ref pva_kmd_resource_table structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] user_smmu_ctx_id SMMU context ID for user memory protection
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_SMMU_CONTEXTS-1]
|
||||||
|
* @param[in] n_entries Maximum number of resource entries supported
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Resource table initialized successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate table memory
|
||||||
|
* @retval PVA_INTERNAL Failed to initialize DMA configuration pool
|
||||||
|
* @retval PVA_ENOSPC Failed to initialize resource record allocator
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
pva_kmd_resource_table_init(struct pva_kmd_resource_table *res_table,
|
||||||
struct pva_kmd_device *pva,
|
struct pva_kmd_device *pva,
|
||||||
uint8_t user_smmu_ctx_id, uint32_t n_entries);
|
uint8_t user_smmu_ctx_id, uint32_t n_entries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a resource table and free associated resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures all resources are properly released and unreferenced
|
||||||
|
* - Deinitializes the DMA configuration pool
|
||||||
|
* - Cleans up the resource record allocator
|
||||||
|
* - Frees allocated device memory for table entries
|
||||||
|
* - Destroys synchronization primitives
|
||||||
|
* - Invalidates the resource table for future use
|
||||||
|
*
|
||||||
|
* All resources must be properly dropped before calling this function.
|
||||||
|
* After deinitialization, the resource table becomes invalid and cannot
|
||||||
|
* be used for further operations.
|
||||||
|
*
|
||||||
|
* @param[in, out] res_table Pointer to @ref pva_kmd_resource_table structure to deinitialize
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_resource_table_deinit(struct pva_kmd_resource_table *res_table);
|
void pva_kmd_resource_table_deinit(struct pva_kmd_resource_table *res_table);
|
||||||
|
|
||||||
/** KMD only writes to FW resource table during init time. Once the address of
|
/**
|
||||||
|
* @brief Update firmware resource table with current resource information
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Synchronizes the firmware resource table with KMD resource state
|
||||||
|
* - Updates resource entries that firmware needs for operation
|
||||||
|
* - Ensures firmware has current IOVA mappings and resource metadata
|
||||||
|
* - Maintains consistency between KMD and firmware resource views
|
||||||
|
*
|
||||||
|
* KMD only writes to FW resource table during init time. Once the address of
|
||||||
* the resource table is sent to FW, all updates should be done through commands.
|
* the resource table is sent to FW, all updates should be done through commands.
|
||||||
|
* This function is typically called during initialization or after significant
|
||||||
|
* resource table changes that require firmware synchronization.
|
||||||
|
*
|
||||||
|
* @param[in, out] res_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
*/
|
*/
|
||||||
void pva_kmd_update_fw_resource_table(struct pva_kmd_resource_table *res_table);
|
void pva_kmd_update_fw_resource_table(struct pva_kmd_resource_table *res_table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a DRAM buffer resource to the resource table
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided device memory allocation
|
||||||
|
* - Allocates a new resource record for the DRAM buffer
|
||||||
|
* - Maps the memory to the appropriate SMMU context
|
||||||
|
* - Assigns a unique resource ID for the buffer
|
||||||
|
* - Initializes reference counting for the resource
|
||||||
|
* - Updates the resource table with the new entry
|
||||||
|
* - Returns the assigned resource ID to the caller
|
||||||
|
*
|
||||||
|
* The DRAM buffer becomes accessible to firmware through the returned
|
||||||
|
* resource ID. The memory must remain valid for the lifetime of the
|
||||||
|
* resource registration.
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] memory Pointer to device memory allocation
|
||||||
|
* Valid value: non-null, must be allocated
|
||||||
|
* @param[out] out_resource_id Pointer to store the assigned resource ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Resource added successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate resource record
|
||||||
|
* @retval PVA_NO_RESOURCE_ID No available resource IDs
|
||||||
|
* @retval PVA_INVAL Failed to map memory to SMMU context
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_add_dram_buffer_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_add_dram_buffer_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
struct pva_kmd_device_memory *memory,
|
struct pva_kmd_device_memory *memory,
|
||||||
uint32_t *out_resource_id);
|
uint32_t *out_resource_id, bool priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a VPU binary executable resource to the resource table
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates and parses the provided executable binary
|
||||||
|
* - Allocates device memory for executable metadata and code sections
|
||||||
|
* - Loads the executable into appropriate memory segments
|
||||||
|
* - Maps executable sections to SMMU contexts with proper permissions
|
||||||
|
* - Extracts and stores symbol table information for debugging
|
||||||
|
* - Assigns a unique resource ID for the executable
|
||||||
|
* - Updates the resource table with the new executable entry
|
||||||
|
*
|
||||||
|
* The VPU executable becomes available for execution through the returned
|
||||||
|
* resource ID. The executable data must remain valid for the lifetime of
|
||||||
|
* the resource registration.
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] executable Pointer to executable binary data
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] executable_size Size of executable binary in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[out] out_resource_id Pointer to store the assigned resource ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Executable resource added successfully
|
||||||
|
* @retval PVA_INVALID_SYMBOL Executable format is invalid or corrupted
|
||||||
|
* @retval PVA_NOMEM Failed to allocate memory for executable
|
||||||
|
* @retval PVA_NO_RESOURCE_ID No available resource IDs
|
||||||
|
* @retval PVA_INVAL Failed to map executable to SMMU context
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_add_vpu_bin_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_add_vpu_bin_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
const void *executable, uint32_t executable_size,
|
const void *executable, uint32_t executable_size,
|
||||||
uint32_t *out_resource_id);
|
uint32_t *out_resource_id, bool priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a DMA configuration resource to the resource table
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the provided DMA configuration parameters
|
||||||
|
* - Allocates device memory from the DMA configuration pool
|
||||||
|
* - Stores the DMA configuration in firmware-accessible memory
|
||||||
|
* - Maps the configuration to appropriate SMMU contexts
|
||||||
|
* - Validates DMA access patterns and constraints
|
||||||
|
* - Assigns a unique resource ID for the DMA configuration
|
||||||
|
* - Updates the resource table with the new configuration entry
|
||||||
|
*
|
||||||
|
* The DMA configuration becomes available for DMA operations through the
|
||||||
|
* returned resource ID. The configuration includes transfer parameters,
|
||||||
|
* access patterns, and memory slot definitions.
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] dma_cfg_hdr Pointer to DMA configuration header
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] dma_config_size Size of DMA configuration in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[out] out_resource_id Pointer to store the assigned resource ID
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS DMA configuration added successfully
|
||||||
|
* @retval PVA_INVALID_DMA_CONFIG DMA configuration is invalid
|
||||||
|
* @retval PVA_ENOSPC DMA configuration pool is full
|
||||||
|
* @retval PVA_NO_RESOURCE_ID No available resource IDs
|
||||||
|
* @retval PVA_INVAL Failed to map configuration to SMMU context
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_add_dma_config_resource(
|
enum pva_error pva_kmd_add_dma_config_resource(
|
||||||
struct pva_kmd_resource_table *resource_table,
|
struct pva_kmd_resource_table *resource_table,
|
||||||
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
const struct pva_ops_dma_config_register *dma_cfg_hdr,
|
||||||
uint32_t dma_config_size, uint32_t *out_resource_id);
|
uint32_t dma_config_size, uint32_t *out_resource_id, bool priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment reference count of the resources
|
* @brief Increment reference count and get resource record (unsafe version)
|
||||||
*
|
*
|
||||||
* TODO: make use and drop thread safe.
|
* @details This function performs the following operations:
|
||||||
* */
|
* - Validates the resource ID against the resource table bounds
|
||||||
|
* - Retrieves the resource record for the specified ID
|
||||||
|
* - Increments the reference count for usage tracking
|
||||||
|
* - Returns pointer to the resource record for access
|
||||||
|
*
|
||||||
|
* This function is not thread-safe and requires external synchronization.
|
||||||
|
* The caller must ensure proper locking around calls to this function and
|
||||||
|
* the corresponding @ref pva_kmd_drop_resource_unsafe().
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to access
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_kmd_resource_record if resource exists
|
||||||
|
* @retval NULL Invalid resource ID or resource not found
|
||||||
|
*
|
||||||
|
* @note TODO: make use and drop thread safe.
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_record *
|
struct pva_kmd_resource_record *
|
||||||
pva_kmd_use_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_use_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id);
|
uint32_t resource_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increment reference count and get resource record (thread-safe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the resource table lock for thread-safe operation
|
||||||
|
* - Validates the resource ID against the resource table bounds
|
||||||
|
* - Retrieves the resource record for the specified ID
|
||||||
|
* - Increments the reference count for usage tracking
|
||||||
|
* - Releases the resource table lock
|
||||||
|
* - Returns pointer to the resource record for access
|
||||||
|
*
|
||||||
|
* This function is thread-safe and can be called concurrently from multiple
|
||||||
|
* threads. The returned resource record remains valid until the corresponding
|
||||||
|
* @ref pva_kmd_drop_resource() is called.
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to access
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_kmd_resource_record if resource exists
|
||||||
|
* @retval NULL Invalid resource ID or resource not found
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_record *
|
struct pva_kmd_resource_record *
|
||||||
pva_kmd_use_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_use_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id);
|
uint32_t resource_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get resource record without incrementing reference count
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the resource table lock for thread-safe operation
|
||||||
|
* - Validates the resource ID against the resource table bounds
|
||||||
|
* - Retrieves the resource record for the specified ID
|
||||||
|
* - Returns pointer to the resource record without changing reference count
|
||||||
|
* - Releases the resource table lock
|
||||||
|
*
|
||||||
|
* This function allows inspection of resource records without affecting
|
||||||
|
* their reference counting. The returned pointer is only valid while
|
||||||
|
* the caller maintains appropriate synchronization with the resource table.
|
||||||
|
*
|
||||||
|
* @param[in] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to inspect
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to @ref pva_kmd_resource_record if resource exists
|
||||||
|
* @retval NULL Invalid resource ID or resource not found
|
||||||
|
*/
|
||||||
struct pva_kmd_resource_record *
|
struct pva_kmd_resource_record *
|
||||||
pva_kmd_peek_resource(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_peek_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id);
|
uint32_t resource_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decrement reference count for a resource (thread-safe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the resource table lock for thread-safe operation
|
||||||
|
* - Validates the resource ID against the resource table bounds
|
||||||
|
* - Decrements the reference count for the specified resource
|
||||||
|
* - Checks if the reference count reaches zero for cleanup
|
||||||
|
* - Frees the resource record if no longer referenced
|
||||||
|
* - Releases the resource table lock
|
||||||
|
*
|
||||||
|
* This function must be called for every successful @ref pva_kmd_use_resource()
|
||||||
|
* to maintain proper reference counting. When the reference count reaches
|
||||||
|
* zero, the resource is automatically cleaned up and its ID becomes available
|
||||||
|
* for reuse.
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to release
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
*/
|
||||||
void pva_kmd_drop_resource(struct pva_kmd_resource_table *resource_table,
|
void pva_kmd_drop_resource(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id);
|
uint32_t resource_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decrement reference count for a resource (unsafe version)
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Validates the resource ID against the resource table bounds
|
||||||
|
* - Decrements the reference count for the specified resource
|
||||||
|
* - Checks if the reference count reaches zero for cleanup
|
||||||
|
* - Frees the resource record if no longer referenced
|
||||||
|
*
|
||||||
|
* This function is not thread-safe and requires external synchronization.
|
||||||
|
* The caller must ensure proper locking around calls to this function and
|
||||||
|
* the corresponding @ref pva_kmd_use_resource_unsafe().
|
||||||
|
*
|
||||||
|
* @param[in, out] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to release
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
*/
|
||||||
void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
void pva_kmd_drop_resource_unsafe(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id);
|
uint32_t resource_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a firmware-compatible resource entry from a resource record
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Retrieves the resource record for the specified resource ID
|
||||||
|
* - Extracts type-specific information from the resource record
|
||||||
|
* - Converts the resource data to firmware-compatible format
|
||||||
|
* - Populates the provided resource entry structure
|
||||||
|
* - Includes IOVA addresses and metadata needed by firmware
|
||||||
|
* - Validates resource consistency before entry creation
|
||||||
|
*
|
||||||
|
* The created resource entry can be used by firmware to access the
|
||||||
|
* resource through hardware operations. The entry contains all necessary
|
||||||
|
* information for firmware to perform DMA operations or executable loading.
|
||||||
|
*
|
||||||
|
* @param[in] resource_table Pointer to @ref pva_kmd_resource_table structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] resource_id Resource ID to create entry for
|
||||||
|
* Valid range: [0 .. curr_max_resource_id]
|
||||||
|
* @param[out] entry Pointer to @ref pva_resource_entry to populate
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Resource entry created successfully
|
||||||
|
* @retval PVA_INVAL Invalid resource ID or entry pointer
|
||||||
|
* @retval PVA_INVALID_RESOURCE Resource in invalid state for entry creation
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_make_resource_entry(struct pva_kmd_resource_table *resource_table,
|
pva_kmd_make_resource_entry(struct pva_kmd_resource_table *resource_table,
|
||||||
uint32_t resource_id,
|
uint32_t resource_id,
|
||||||
struct pva_resource_entry *entry);
|
struct pva_resource_entry *entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire lock for a specific resource table
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Identifies the resource table associated with the specified ID
|
||||||
|
* - Acquires the mutex lock for thread-safe resource table access
|
||||||
|
* - Provides exclusive access to resource table operations
|
||||||
|
* - Ensures atomic operations on resource table state
|
||||||
|
*
|
||||||
|
* This function should be used when multiple resource table operations
|
||||||
|
* need to be performed atomically. The lock must be released using
|
||||||
|
* @ref pva_kmd_resource_table_unlock() after the operations complete.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] res_table_id Resource table identifier to lock
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_KMD_RESOURCES-1]
|
||||||
|
*/
|
||||||
void pva_kmd_resource_table_lock(struct pva_kmd_device *pva,
|
void pva_kmd_resource_table_lock(struct pva_kmd_device *pva,
|
||||||
uint8_t res_table_id);
|
uint8_t res_table_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release lock for a specific resource table
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Identifies the resource table associated with the specified ID
|
||||||
|
* - Releases the mutex lock to allow other threads access
|
||||||
|
* - Completes the atomic operation sequence started with lock
|
||||||
|
* - Enables other threads to perform resource table operations
|
||||||
|
*
|
||||||
|
* This function must be called after @ref pva_kmd_resource_table_lock()
|
||||||
|
* to release the exclusive access to the resource table. Failure to
|
||||||
|
* unlock will result in deadlock for other threads.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] res_table_id Resource table identifier to unlock
|
||||||
|
* Valid range: [0 .. PVA_KMD_MAX_NUM_KMD_RESOURCES-1]
|
||||||
|
*/
|
||||||
void pva_kmd_resource_table_unlock(struct pva_kmd_device *pva,
|
void pva_kmd_resource_table_unlock(struct pva_kmd_device *pva,
|
||||||
uint8_t res_table_id);
|
uint8_t res_table_id);
|
||||||
#endif // PVA_KMD_RESOURCE_TABLE_H
|
#endif // PVA_KMD_RESOURCE_TABLE_H
|
||||||
|
|||||||
@@ -107,14 +107,14 @@ static void sha256_transform(struct sha256_ctx *ctx, const void *data_in)
|
|||||||
void sha256_init(struct sha256_ctx *ctx)
|
void sha256_init(struct sha256_ctx *ctx)
|
||||||
{
|
{
|
||||||
ctx->bitlen = 0;
|
ctx->bitlen = 0;
|
||||||
ctx->state[0] = U32(0x6a09e667);
|
ctx->state[0] = U32(0x6a09e667U);
|
||||||
ctx->state[1] = U32(0xbb67ae85);
|
ctx->state[1] = U32(0xbb67ae85U);
|
||||||
ctx->state[2] = U32(0x3c6ef372);
|
ctx->state[2] = U32(0x3c6ef372U);
|
||||||
ctx->state[3] = U32(0xa54ff53a);
|
ctx->state[3] = U32(0xa54ff53aU);
|
||||||
ctx->state[4] = U32(0x510e527f);
|
ctx->state[4] = U32(0x510e527fU);
|
||||||
ctx->state[5] = U32(0x9b05688c);
|
ctx->state[5] = U32(0x9b05688cU);
|
||||||
ctx->state[6] = U32(0x1f83d9ab);
|
ctx->state[6] = U32(0x1f83d9abU);
|
||||||
ctx->state[7] = U32(0x5be0cd19);
|
ctx->state[7] = U32(0x5be0cd19U);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256_update(struct sha256_ctx *ctx, const void *data, size_t len)
|
void sha256_update(struct sha256_ctx *ctx, const void *data, size_t len)
|
||||||
@@ -122,7 +122,7 @@ void sha256_update(struct sha256_ctx *ctx, const void *data, size_t len)
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < len; i += U32(64)) {
|
for (i = 0; i < len; i += U32(64)) {
|
||||||
ctx->bitlen &= U32(0xffffffff);
|
ctx->bitlen &= U32(0xffffffffU);
|
||||||
sha256_transform(ctx, ((const uint8_t *)data) + i);
|
sha256_transform(ctx, ((const uint8_t *)data) + i);
|
||||||
ctx->bitlen =
|
ctx->bitlen =
|
||||||
safe_wrap_add_u32((uint32_t)ctx->bitlen, U32(512));
|
safe_wrap_add_u32((uint32_t)ctx->bitlen, U32(512));
|
||||||
@@ -141,8 +141,8 @@ void sha256_finalize(struct sha256_ctx *ctx, const void *input,
|
|||||||
void *p = data;
|
void *p = data;
|
||||||
uint32_t t;
|
uint32_t t;
|
||||||
|
|
||||||
input_size &= U32(0xffffffff);
|
input_size &= U32(0xffffffffU);
|
||||||
ctx->bitlen &= U32(0xffffffff);
|
ctx->bitlen &= U32(0xffffffffU);
|
||||||
|
|
||||||
/* the false of this condition is illegal for this API agreement */
|
/* the false of this condition is illegal for this API agreement */
|
||||||
/* this check is here only for Coverity INT30-C */
|
/* this check is here only for Coverity INT30-C */
|
||||||
|
|||||||
@@ -5,69 +5,138 @@
|
|||||||
#define PVA_KMD_SHA256_H
|
#define PVA_KMD_SHA256_H
|
||||||
|
|
||||||
#include "pva_api_types.h"
|
#include "pva_api_types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility macro to cast value to uint32_t
|
||||||
|
*
|
||||||
|
* @details Convenience macro for casting values to 32-bit unsigned integers.
|
||||||
|
* Used throughout SHA256 implementation for type safety and clarity.
|
||||||
|
*/
|
||||||
#define U32(x) ((uint32_t)(x))
|
#define U32(x) ((uint32_t)(x))
|
||||||
|
|
||||||
struct sha256_ctx {
|
/**
|
||||||
/*
|
* @brief SHA256 hash computation context structure
|
||||||
* On bitlen:
|
|
||||||
*
|
*
|
||||||
* While we don't exceed 2^32 bit (2^29 byte) length for the input buffer,
|
* @details This structure maintains the state for incremental SHA256 hash
|
||||||
* size_t is more efficient at least on RISC-V. This particular
|
* computation. It stores the bit length of processed data and the current
|
||||||
* structure is needed to make Coverity happy.
|
* hash state array. The union for bitlen accommodates both size_t (for
|
||||||
|
* efficiency on RISC-V and other architectures) and uint32_t (for Coverity
|
||||||
|
* analysis) representations of the bit length.
|
||||||
|
*/
|
||||||
|
struct sha256_ctx {
|
||||||
|
/**
|
||||||
|
* @brief Bit length of processed data
|
||||||
|
*
|
||||||
|
* @details Union to handle bit length efficiently while satisfying static analysis.
|
||||||
|
* While we don't exceed 2^32 bit (2^29 byte) length for input buffers,
|
||||||
|
* size_t is more efficient on at least RISC-V. This union structure
|
||||||
|
* is needed to make Coverity static analysis happy.
|
||||||
*/
|
*/
|
||||||
union {
|
union {
|
||||||
|
/** @brief Bit length as size_t for efficiency */
|
||||||
size_t bitlen;
|
size_t bitlen;
|
||||||
|
/** @brief Bit length as uint32_t for static analysis */
|
||||||
uint32_t bitlen_low;
|
uint32_t bitlen_low;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SHA256 hash state array
|
||||||
|
*
|
||||||
|
* @details Array of 8 32-bit words representing the current SHA256 hash state.
|
||||||
|
* These values are updated during hash computation and contain the final
|
||||||
|
* hash result when computation is complete.
|
||||||
|
*/
|
||||||
uint32_t state[8];
|
uint32_t state[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes struct sha256_ctx
|
* @brief Initialize SHA256 context for hash computation
|
||||||
*
|
*
|
||||||
* \param[in] ctx pointer of struct sha256_ctx context
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the SHA256 context structure to known initial state
|
||||||
|
* - Sets the bit length counter to zero
|
||||||
|
* - Loads the SHA256 initial hash values into the state array
|
||||||
|
* - Prepares the context for incremental hash computation
|
||||||
|
* - Ensures context is in valid state for subsequent operations
|
||||||
*
|
*
|
||||||
* \return void
|
* This function must be called before any hash data can be processed
|
||||||
|
* using @ref sha256_update() or @ref sha256_finalize().
|
||||||
|
*
|
||||||
|
* @param[out] ctx Pointer to @ref sha256_ctx context structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
*/
|
*/
|
||||||
void sha256_init(struct sha256_ctx *ctx);
|
void sha256_init(struct sha256_ctx *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief
|
* @brief Process full blocks of data for SHA256 hash computation
|
||||||
* Hash full blocks, in units of 64 bytes
|
|
||||||
* can be called repeatedly with chunks of the message
|
|
||||||
* to be hashed (len bytes at data).
|
|
||||||
*
|
*
|
||||||
* \param[in] ctx pointer of struct sha256_ctx context
|
* @details This function performs the following operations:
|
||||||
* \param[in] data pointer to the data block to be hashed
|
* - Processes complete 64-byte blocks of input data
|
||||||
* \param[in] len length (in units of 64 bytes) of the data to be hashed.
|
* - Updates the SHA256 state with the processed block data
|
||||||
|
* - Maintains bit length counter for the total processed data
|
||||||
|
* - Can be called repeatedly with chunks of the message to be hashed
|
||||||
|
* - Optimized for processing large amounts of data efficiently
|
||||||
|
* - Handles block-aligned data for optimal performance
|
||||||
*
|
*
|
||||||
* \return void
|
* This function processes data in 64-byte chunks and can be called multiple
|
||||||
|
* times to hash large inputs incrementally. The input length should be a
|
||||||
|
* multiple of 64 bytes for optimal operation.
|
||||||
|
*
|
||||||
|
* @param[in, out] ctx Pointer to @ref sha256_ctx context structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] data Pointer to input data block to be hashed
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] len Length of data in bytes (should be multiple of 64)
|
||||||
|
* Valid range: [0 .. SIZE_MAX]
|
||||||
*/
|
*/
|
||||||
void sha256_update(struct sha256_ctx *ctx, const void *data, size_t len);
|
void sha256_update(struct sha256_ctx *ctx, const void *data, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief
|
* @brief Finalize SHA256 hash computation and produce result
|
||||||
* Finalize the hash and keep the calcualted hash in out.
|
|
||||||
* Required: input_size < 64. Call pva_sha256_update() first otherwise.
|
|
||||||
*
|
*
|
||||||
* \param[in] ctx pointer of struct sha256_ctx context
|
* @details This function performs the following operations:
|
||||||
* \param[in] input pointer to the data block
|
* - Processes any remaining input data less than 64 bytes
|
||||||
* (left over from \ref pva_sha256_update) to be hashed
|
* - Applies SHA256 padding according to the algorithm specification
|
||||||
* \param[in] input_size size of the data block to hashed
|
* - Includes the total bit length in the final padding block
|
||||||
* (left over from \ref pva_sha256_update to be hashed)
|
* - Completes the hash computation and produces the final result
|
||||||
* \param[out] out places the calcuated sha256 key in out.
|
* - Stores the 256-bit hash result in the output array
|
||||||
|
* - Handles final block processing with proper padding
|
||||||
*
|
*
|
||||||
* \return void
|
* This function must be called after all data has been processed with
|
||||||
|
* @ref sha256_update() to complete the hash computation. The input_size
|
||||||
|
* parameter must be less than 64 bytes (remaining data after block processing).
|
||||||
|
*
|
||||||
|
* @param[in, out] ctx Pointer to @ref sha256_ctx context structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] input Pointer to remaining data block to be hashed
|
||||||
|
* Valid value: non-null if input_size > 0,
|
||||||
|
* may be null if input_size == 0
|
||||||
|
* @param[in] input_size Size of remaining data block in bytes
|
||||||
|
* Valid range: [0 .. 63]
|
||||||
|
* @param[out] out Array to store the computed SHA256 hash result
|
||||||
|
* Valid value: non-null, must have space for 8 uint32_t values
|
||||||
*/
|
*/
|
||||||
void sha256_finalize(struct sha256_ctx *ctx, const void *input,
|
void sha256_finalize(struct sha256_ctx *ctx, const void *input,
|
||||||
size_t input_size, uint32_t out[8]);
|
size_t input_size, uint32_t out[8]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief
|
* @brief Copy SHA256 context state from one context to another
|
||||||
* copy state information to ctx_out from ctx_in
|
*
|
||||||
* \param[in] ctx_in input struct sha256_ctx
|
* @details This function performs the following operations:
|
||||||
* \param[out] ctx_out output struct sha256_ctx
|
* - Copies the complete state from input context to output context
|
||||||
* \return void
|
* - Transfers bit length counter and hash state array
|
||||||
|
* - Creates an independent copy that can be used separately
|
||||||
|
* - Enables branched hash computation from a common base
|
||||||
|
* - Preserves the state for continued computation on both contexts
|
||||||
|
* - Useful for scenarios requiring multiple hash computations from same base
|
||||||
|
*
|
||||||
|
* This function allows creating checkpoints in hash computation or
|
||||||
|
* branching hash computation to produce multiple related hashes efficiently.
|
||||||
|
*
|
||||||
|
* @param[in] ctx_in Pointer to source @ref sha256_ctx structure to copy from
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] ctx_out Pointer to destination @ref sha256_ctx structure to copy to
|
||||||
|
* Valid value: non-null
|
||||||
*/
|
*/
|
||||||
void sha256_copy(const struct sha256_ctx *ctx_in, struct sha256_ctx *ctx_out);
|
void sha256_copy(const struct sha256_ctx *ctx_in, struct sha256_ctx *ctx_out);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "pva_kmd_context.h"
|
#include "pva_kmd_context.h"
|
||||||
#include "pva_kmd_shim_trace_event.h"
|
#include "pva_kmd_shim_trace_event.h"
|
||||||
#include "pva_kmd_shared_buffer.h"
|
#include "pva_kmd_shared_buffer.h"
|
||||||
|
#include "pva_kmd_fw_tracepoints.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
||||||
uint8_t interface,
|
uint8_t interface,
|
||||||
@@ -21,7 +23,7 @@ enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
|||||||
uint64_t buffer_size;
|
uint64_t buffer_size;
|
||||||
struct pva_cmd_init_shared_dram_buffer init_cmd = { 0 };
|
struct pva_cmd_init_shared_dram_buffer init_cmd = { 0 };
|
||||||
|
|
||||||
ASSERT(interface < PVA_MAX_NUM_CCQ);
|
ASSERT(interface < (uint8_t)PVA_MAX_NUM_CCQ);
|
||||||
buffer = &pva->kmd_fw_buffers[interface];
|
buffer = &pva->kmd_fw_buffers[interface];
|
||||||
|
|
||||||
// If the buffer is already initialized, skip buffer allocation and just notify FW.
|
// If the buffer is already initialized, skip buffer allocation and just notify FW.
|
||||||
@@ -65,11 +67,21 @@ enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
|||||||
device_memory = buffer->resource_memory;
|
device_memory = buffer->resource_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
pva_kmd_set_cmd_init_shared_dram_buffer(
|
/* Validate device memory size and iova fit in uint32_t */
|
||||||
&init_cmd, interface, device_memory->iova, device_memory->size);
|
if ((device_memory->size > U32_MAX) ||
|
||||||
|
(device_memory->iova > U32_MAX)) {
|
||||||
|
pva_kmd_log_err("Device memory size or iova exceeds U32_MAX");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto release_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CERT INT31-C: iova and size validated to fit in uint32_t, safe to cast */
|
||||||
|
pva_kmd_set_cmd_init_shared_dram_buffer(&init_cmd, (uint8_t)interface,
|
||||||
|
device_memory->iova,
|
||||||
|
device_memory->size);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&pva->submitter, &init_cmd,
|
err = pva_kmd_submit_cmd_sync(&pva->submitter, &init_cmd,
|
||||||
sizeof(init_cmd),
|
(uint32_t)sizeof(init_cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -95,13 +107,13 @@ enum pva_error pva_kmd_shared_buffer_deinit(struct pva_kmd_device *pva,
|
|||||||
struct pva_kmd_shared_buffer *buffer;
|
struct pva_kmd_shared_buffer *buffer;
|
||||||
struct pva_cmd_deinit_shared_dram_buffer deinit_cmd = { 0 };
|
struct pva_cmd_deinit_shared_dram_buffer deinit_cmd = { 0 };
|
||||||
|
|
||||||
ASSERT(interface < PVA_MAX_NUM_CCQ);
|
ASSERT(interface < (uint8_t)PVA_MAX_NUM_CCQ);
|
||||||
buffer = &pva->kmd_fw_buffers[interface];
|
buffer = &pva->kmd_fw_buffers[interface];
|
||||||
|
|
||||||
pva_kmd_set_cmd_deinit_shared_dram_buffer(&deinit_cmd, interface);
|
pva_kmd_set_cmd_deinit_shared_dram_buffer(&deinit_cmd, interface);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&pva->submitter, &deinit_cmd,
|
err = pva_kmd_submit_cmd_sync(&pva->submitter, &deinit_cmd,
|
||||||
sizeof(deinit_cmd),
|
(uint32_t)sizeof(deinit_cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -119,58 +131,43 @@ enum pva_error pva_kmd_shared_buffer_deinit(struct pva_kmd_device *pva,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shared_buffer_process_msg(struct pva_kmd_device *pva,
|
static void process_fw_event_msg(struct pva_kmd_device *pva, void *msg_body,
|
||||||
uint8_t interface, void *msg)
|
uint32_t msg_size)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
|
||||||
struct pva_kmd_fw_buffer_msg_header header;
|
|
||||||
struct pva_kmd_fw_msg_cmdbuf_trace cmdbuf_trace;
|
|
||||||
struct pva_kmd_fw_msg_vpu_exec_trace vpu_trace;
|
|
||||||
struct pva_kmd_fw_msg_engine_acquire_trace engine_acquire_trace;
|
|
||||||
struct pva_kmd_fw_msg_fence_trace fence_trace;
|
|
||||||
struct pva_kmd_fw_msg_res_unreg unreg_data;
|
|
||||||
struct pva_kmd_context *ctx = NULL;
|
|
||||||
void *msg_body;
|
|
||||||
uint32_t msg_size;
|
|
||||||
struct pva_fw_tracepoint tracepoint;
|
|
||||||
|
|
||||||
ASSERT(msg != NULL);
|
|
||||||
|
|
||||||
// Copy the header
|
|
||||||
memcpy(&header, msg, sizeof(header));
|
|
||||||
msg_size = safe_subu32(header.size, sizeof(header));
|
|
||||||
msg_body = (uint8_t *)msg + sizeof(header);
|
|
||||||
|
|
||||||
switch (header.type) {
|
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_FW_EVENT: {
|
|
||||||
// TODO: This must be updated once profiler config is exposed through debugfs.
|
// TODO: This must be updated once profiler config is exposed through debugfs.
|
||||||
// KMD must use the same timestamp size as the FW. It is possible that the user
|
// KMD must use the same timestamp size as the FW. It is possible that the user
|
||||||
// changes the timestamp size through debugfs after FW logged the event.
|
// changes the timestamp size through debugfs after FW logged the event.
|
||||||
// FW must log the type of timestamp it used to capture the event.
|
// FW must log the type of timestamp it used to capture the event.
|
||||||
ASSERT(msg_size ==
|
ASSERT(msg_size == sizeof(struct pva_fw_event_message) +
|
||||||
sizeof(struct pva_fw_event_message) +
|
|
||||||
pva->debugfs_context.g_fw_profiling_config
|
pva->debugfs_context.g_fw_profiling_config
|
||||||
.timestamp_size);
|
.timestamp_size);
|
||||||
|
|
||||||
err = pva_kmd_process_fw_event(pva, msg_body, msg_size);
|
pva_kmd_process_fw_event(pva, (uint8_t *)msg_body, msg_size);
|
||||||
if (err != PVA_SUCCESS) {
|
}
|
||||||
pva_kmd_log_err("Failed to process FW event");
|
|
||||||
}
|
static void process_trace_msg(struct pva_kmd_device *pva, uint32_t msg_type,
|
||||||
break;
|
void *msg_body, uint32_t msg_size)
|
||||||
}
|
{
|
||||||
|
switch (msg_type) {
|
||||||
|
#if PVA_ENABLE_FW_TRACEPOINTS == 1
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_FW_TRACEPOINT: {
|
case PVA_KMD_FW_BUF_MSG_TYPE_FW_TRACEPOINT: {
|
||||||
|
struct pva_fw_tracepoint tracepoint;
|
||||||
ASSERT(msg_size == sizeof(struct pva_fw_tracepoint));
|
ASSERT(msg_size == sizeof(struct pva_fw_tracepoint));
|
||||||
memcpy(&tracepoint, msg_body, sizeof(tracepoint));
|
memcpy(&tracepoint, msg_body, sizeof(tracepoint));
|
||||||
pva_kmd_process_fw_tracepoint(pva, &tracepoint);
|
pva_kmd_process_fw_tracepoint(pva, &tracepoint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if PVA_ENABLE_NSYS_PROFILING == 1
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_CMD_BUF_TRACE: {
|
case PVA_KMD_FW_BUF_MSG_TYPE_CMD_BUF_TRACE: {
|
||||||
|
struct pva_kmd_fw_msg_cmdbuf_trace cmdbuf_trace;
|
||||||
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_cmdbuf_trace));
|
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_cmdbuf_trace));
|
||||||
memcpy(&cmdbuf_trace, msg_body, sizeof(cmdbuf_trace));
|
memcpy(&cmdbuf_trace, msg_body, sizeof(cmdbuf_trace));
|
||||||
pva_kmd_nsys_cmdbuf_trace(pva, &cmdbuf_trace);
|
pva_kmd_nsys_cmdbuf_trace(pva, &cmdbuf_trace);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_VPU_TRACE: {
|
case PVA_KMD_FW_BUF_MSG_TYPE_VPU_TRACE: {
|
||||||
|
struct pva_kmd_fw_msg_vpu_exec_trace vpu_trace;
|
||||||
ASSERT(msg_size ==
|
ASSERT(msg_size ==
|
||||||
sizeof(struct pva_kmd_fw_msg_vpu_exec_trace));
|
sizeof(struct pva_kmd_fw_msg_vpu_exec_trace));
|
||||||
memcpy(&vpu_trace, msg_body, sizeof(vpu_trace));
|
memcpy(&vpu_trace, msg_body, sizeof(vpu_trace));
|
||||||
@@ -181,22 +178,43 @@ static void shared_buffer_process_msg(struct pva_kmd_device *pva,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_FENCE_TRACE: {
|
case PVA_KMD_FW_BUF_MSG_TYPE_FENCE_TRACE: {
|
||||||
|
struct pva_kmd_fw_msg_fence_trace fence_trace;
|
||||||
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_fence_trace));
|
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_fence_trace));
|
||||||
memcpy(&fence_trace, msg_body, sizeof(fence_trace));
|
(void)memcpy(&fence_trace, (const uint8_t *)msg_body,
|
||||||
|
sizeof(fence_trace));
|
||||||
pva_kmd_nsys_fence_trace(pva, &fence_trace);
|
pva_kmd_nsys_fence_trace(pva, &fence_trace);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_ENGINE_ACQUIRE_TRACE: {
|
case PVA_KMD_FW_BUF_MSG_TYPE_ENGINE_ACQUIRE_TRACE: {
|
||||||
|
struct pva_kmd_fw_msg_engine_acquire_trace engine_acquire_trace;
|
||||||
ASSERT(msg_size ==
|
ASSERT(msg_size ==
|
||||||
sizeof(struct pva_kmd_fw_msg_engine_acquire_trace));
|
sizeof(struct pva_kmd_fw_msg_engine_acquire_trace));
|
||||||
memcpy(&engine_acquire_trace, msg_body,
|
(void)memcpy(&engine_acquire_trace, (const uint8_t *)msg_body,
|
||||||
sizeof(engine_acquire_trace));
|
sizeof(engine_acquire_trace));
|
||||||
pva_kmd_nsys_engine_acquire_trace(pva, &engine_acquire_trace);
|
pva_kmd_nsys_engine_acquire_trace(pva, &engine_acquire_trace);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PVA_KMD_FW_BUF_MSG_TYPE_RES_UNREG: {
|
#endif
|
||||||
|
default: {
|
||||||
|
// This should not happen as we only call this function for known message types.
|
||||||
|
// Added for fixing the compiler warning.
|
||||||
|
FAULT("Unexpected trace message type in process_trace_msg");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_res_unreg_msg(struct pva_kmd_device *pva, uint8_t interface,
|
||||||
|
void *msg_body, uint32_t msg_size)
|
||||||
|
{
|
||||||
|
struct pva_kmd_fw_msg_res_unreg unreg_data;
|
||||||
|
struct pva_kmd_context *ctx = NULL;
|
||||||
|
|
||||||
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_res_unreg));
|
ASSERT(msg_size == sizeof(struct pva_kmd_fw_msg_res_unreg));
|
||||||
memcpy(&unreg_data, msg_body, sizeof(unreg_data));
|
/* MISRA C-2023 Rule 11.5: msg_body is void*, explicit cast needed for type safety */
|
||||||
|
(void)memcpy(&unreg_data,
|
||||||
|
(const struct pva_kmd_fw_msg_res_unreg *)msg_body,
|
||||||
|
sizeof(unreg_data));
|
||||||
ctx = pva_kmd_get_context(pva, interface);
|
ctx = pva_kmd_get_context(pva, interface);
|
||||||
|
|
||||||
ASSERT(ctx != NULL);
|
ASSERT(ctx != NULL);
|
||||||
@@ -206,8 +224,37 @@ static void shared_buffer_process_msg(struct pva_kmd_device *pva,
|
|||||||
// the required lock.
|
// the required lock.
|
||||||
pva_kmd_drop_resource_unsafe(&ctx->ctx_resource_table,
|
pva_kmd_drop_resource_unsafe(&ctx->ctx_resource_table,
|
||||||
unreg_data.resource_id);
|
unreg_data.resource_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shared_buffer_process_msg(struct pva_kmd_device *pva,
|
||||||
|
uint8_t interface, void *msg)
|
||||||
|
{
|
||||||
|
struct pva_kmd_fw_buffer_msg_header header;
|
||||||
|
void *msg_body;
|
||||||
|
uint32_t msg_size;
|
||||||
|
|
||||||
|
ASSERT(msg != NULL);
|
||||||
|
|
||||||
|
// Copy the header
|
||||||
|
(void)memcpy(&header, (const struct pva_kmd_fw_buffer_msg_header *)msg,
|
||||||
|
sizeof(header));
|
||||||
|
msg_size = safe_subu32(header.size, (uint32_t)sizeof(header));
|
||||||
|
msg_body = (uint8_t *)msg + sizeof(header);
|
||||||
|
|
||||||
|
switch (header.type) {
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_FW_EVENT:
|
||||||
|
process_fw_event_msg(pva, msg_body, msg_size);
|
||||||
|
break;
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_FW_TRACEPOINT:
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_CMD_BUF_TRACE:
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_VPU_TRACE:
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_FENCE_TRACE:
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_ENGINE_ACQUIRE_TRACE:
|
||||||
|
process_trace_msg(pva, header.type, msg_body, msg_size);
|
||||||
|
break;
|
||||||
|
case PVA_KMD_FW_BUF_MSG_TYPE_RES_UNREG:
|
||||||
|
process_res_unreg_msg(pva, interface, msg_body, msg_size);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
FAULT("Unexpected message type while processing shared buffer");
|
FAULT("Unexpected message type while processing shared buffer");
|
||||||
break;
|
break;
|
||||||
@@ -216,32 +263,43 @@ static void shared_buffer_process_msg(struct pva_kmd_device *pva,
|
|||||||
|
|
||||||
void pva_kmd_shared_buffer_process(void *pva_dev, uint8_t interface)
|
void pva_kmd_shared_buffer_process(void *pva_dev, uint8_t interface)
|
||||||
{
|
{
|
||||||
struct pva_kmd_device *pva = (struct pva_kmd_device *)pva_dev;
|
struct pva_kmd_device *pva;
|
||||||
struct pva_kmd_shared_buffer *fw_buffer =
|
struct pva_kmd_shared_buffer *fw_buffer;
|
||||||
&pva->kmd_fw_buffers[interface];
|
|
||||||
uint32_t *buffer_head;
|
uint32_t *buffer_head;
|
||||||
uint32_t buffer_tail;
|
uint32_t buffer_tail;
|
||||||
uint32_t buffer_size;
|
uint32_t buffer_size;
|
||||||
uint8_t *buffer_body;
|
uint8_t *buffer_body;
|
||||||
uint32_t element_size;
|
uint32_t element_size;
|
||||||
uint8_t *current_element = NULL;
|
uint8_t *current_element;
|
||||||
|
uint64_t buffer_size_u64;
|
||||||
|
|
||||||
|
pva = (struct pva_kmd_device *)pva_dev;
|
||||||
|
fw_buffer = &pva->kmd_fw_buffers[interface];
|
||||||
|
current_element = NULL;
|
||||||
|
|
||||||
|
if (fw_buffer->lock_cb != NULL) {
|
||||||
|
fw_buffer->lock_cb(pva, interface);
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(fw_buffer->resource_memory->size > sizeof(*fw_buffer->header));
|
ASSERT(fw_buffer->resource_memory->size > sizeof(*fw_buffer->header));
|
||||||
|
|
||||||
buffer_head = &fw_buffer->header->head;
|
buffer_head = &fw_buffer->header->head;
|
||||||
buffer_tail = fw_buffer->header->tail;
|
buffer_tail = fw_buffer->header->tail;
|
||||||
buffer_size =
|
/* buffer size bounded by resource memory allocation */
|
||||||
|
buffer_size_u64 =
|
||||||
fw_buffer->resource_memory->size - sizeof(*fw_buffer->header);
|
fw_buffer->resource_memory->size - sizeof(*fw_buffer->header);
|
||||||
|
ASSERT(buffer_size_u64 <= U32_MAX);
|
||||||
|
buffer_size = (uint32_t)buffer_size_u64;
|
||||||
buffer_body = fw_buffer->body;
|
buffer_body = fw_buffer->body;
|
||||||
element_size = fw_buffer->header->element_size;
|
element_size = fw_buffer->header->element_size;
|
||||||
|
|
||||||
ASSERT(buffer_body != NULL);
|
ASSERT(buffer_body != NULL);
|
||||||
|
|
||||||
// Ensure element size fits within the buffer
|
// Ensure element size fits within the buffer
|
||||||
ASSERT(buffer_size % element_size == 0);
|
ASSERT(buffer_size % element_size == 0U);
|
||||||
|
|
||||||
// check buffer header to see if there was an overflow
|
// check buffer header to see if there was an overflow
|
||||||
if (fw_buffer->header->flags & PVA_KMD_FW_BUF_FLAG_OVERFLOW) {
|
if ((fw_buffer->header->flags & PVA_KMD_FW_BUF_FLAG_OVERFLOW) != 0U) {
|
||||||
// Clear the overflow flag
|
// Clear the overflow flag
|
||||||
// Note: this might be error prone. We are writing the flag here and at
|
// Note: this might be error prone. We are writing the flag here and at
|
||||||
// the same time, the FW might be updating the flag too. Since the
|
// the same time, the FW might be updating the flag too. Since the
|
||||||
@@ -270,10 +328,6 @@ void pva_kmd_shared_buffer_process(void *pva_dev, uint8_t interface)
|
|||||||
// We will drop the overflowed messages.
|
// We will drop the overflowed messages.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fw_buffer->lock_cb != NULL) {
|
|
||||||
fw_buffer->lock_cb(pva, interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop while `head` has not yet caught up to `tail`
|
// Loop while `head` has not yet caught up to `tail`
|
||||||
while (*buffer_head != buffer_tail) {
|
while (*buffer_head != buffer_tail) {
|
||||||
// Ensure current position is valid
|
// Ensure current position is valid
|
||||||
|
|||||||
@@ -5,31 +5,140 @@
|
|||||||
|
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function pointer type for processing shared buffer elements
|
||||||
|
*
|
||||||
|
* @details This function pointer type defines the signature for callback
|
||||||
|
* functions used to process individual elements from shared buffers. The
|
||||||
|
* callback is invoked for each element that needs to be processed, allowing
|
||||||
|
* different interfaces to handle their specific element types appropriately.
|
||||||
|
*
|
||||||
|
* @param[in] context Pointer to context data for the processing operation
|
||||||
|
* Valid value: can be null if no context needed
|
||||||
|
* @param[in] interface Interface identifier for the shared buffer
|
||||||
|
* Valid range: [0 .. UINT8_MAX]
|
||||||
|
* @param[in] element Pointer to the element data to be processed
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Element processed successfully
|
||||||
|
* @retval error_code Processing failed with specific error
|
||||||
|
*/
|
||||||
typedef enum pva_error (*shared_buffer_process_element_cb)(void *context,
|
typedef enum pva_error (*shared_buffer_process_element_cb)(void *context,
|
||||||
uint8_t interface,
|
uint8_t interface,
|
||||||
uint8_t *element);
|
uint8_t *element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function pointer type for shared buffer locking operations
|
||||||
|
*
|
||||||
|
* @details This function pointer type defines the signature for callback
|
||||||
|
* functions used to lock and unlock shared buffers. These callbacks provide
|
||||||
|
* synchronization mechanisms to ensure thread-safe access to shared buffer
|
||||||
|
* data structures between KMD and firmware operations.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Identifier for the shared buffer interface
|
||||||
|
* Valid range: [0 .. UINT8_MAX]
|
||||||
|
*/
|
||||||
typedef void (*shared_buffer_lock_cb)(struct pva_kmd_device *pva,
|
typedef void (*shared_buffer_lock_cb)(struct pva_kmd_device *pva,
|
||||||
uint8_t interface);
|
uint8_t interface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure for managing shared buffer communication between KMD and firmware
|
||||||
|
*
|
||||||
|
* @details This structure manages a shared buffer used for communication between
|
||||||
|
* the KMD and firmware. The buffer consists of a header located in shared DRAM
|
||||||
|
* memory that both KMD and firmware can access, along with local KMD fields
|
||||||
|
* for bookkeeping and callback management. The structure supports element-based
|
||||||
|
* communication with configurable processing and synchronization callbacks.
|
||||||
|
*/
|
||||||
struct pva_kmd_shared_buffer {
|
struct pva_kmd_shared_buffer {
|
||||||
// Only 'header' is in shared DRAM memory
|
/**
|
||||||
// Other fields are local to KMD and should be used for internal bookkeeping
|
* @brief Pointer to shared buffer header in DRAM memory
|
||||||
|
*
|
||||||
|
* @details Only 'header' is in shared DRAM memory accessible by both KMD and firmware
|
||||||
|
*/
|
||||||
struct pva_fw_shared_buffer_header *header;
|
struct pva_fw_shared_buffer_header *header;
|
||||||
// 'body' tracks the begining of buffer contents in DRAM
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to beginning of buffer contents in DRAM
|
||||||
|
*
|
||||||
|
* @details 'body' tracks the beginning of buffer contents in DRAM
|
||||||
|
*/
|
||||||
uint8_t *body;
|
uint8_t *body;
|
||||||
// 'process_cb' callback is used to process elements in the buffer
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for processing buffer elements
|
||||||
|
*
|
||||||
|
* @details 'process_cb' callback is used to process elements in the buffer
|
||||||
|
*/
|
||||||
shared_buffer_process_element_cb process_cb;
|
shared_buffer_process_element_cb process_cb;
|
||||||
// 'lock_cb' callback is used to lock the buffer
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for acquiring buffer lock
|
||||||
|
*
|
||||||
|
* @details 'lock_cb' callback is used to lock the buffer for thread safety
|
||||||
|
*/
|
||||||
shared_buffer_lock_cb lock_cb;
|
shared_buffer_lock_cb lock_cb;
|
||||||
// 'unlock_cb' callback is used to unlock the buffer
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for releasing buffer lock
|
||||||
|
*
|
||||||
|
* @details 'unlock_cb' callback is used to unlock the buffer
|
||||||
|
*/
|
||||||
shared_buffer_lock_cb unlock_cb;
|
shared_buffer_lock_cb unlock_cb;
|
||||||
// 'resource_memory' is used to track the memory allocated for the buffer
|
|
||||||
|
/**
|
||||||
|
* @brief Device memory allocation tracking for the buffer
|
||||||
|
*
|
||||||
|
* @details 'resource_memory' is used to track the memory allocated for the buffer
|
||||||
|
*/
|
||||||
struct pva_kmd_device_memory *resource_memory;
|
struct pva_kmd_device_memory *resource_memory;
|
||||||
// 'resource_offset' is used to track offset of buffer in 'resource_id'
|
|
||||||
|
/**
|
||||||
|
* @brief Offset of buffer within the allocated resource
|
||||||
|
*
|
||||||
|
* @details 'resource_offset' is used to track offset of buffer in 'resource_id'
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t resource_offset;
|
uint32_t resource_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a shared buffer for KMD-firmware communication
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates device memory for the shared buffer and its header
|
||||||
|
* - Initializes the buffer header with specified element and buffer sizes
|
||||||
|
* - Sets up the buffer structure with provided callback functions
|
||||||
|
* - Configures the buffer for the specified interface identifier
|
||||||
|
* - Registers the buffer memory with the device's resource management system
|
||||||
|
* - Establishes proper synchronization mechanisms for thread-safe access
|
||||||
|
* - Prepares the buffer for element-based communication with firmware
|
||||||
|
*
|
||||||
|
* The initialized buffer can be used for bidirectional communication between
|
||||||
|
* KMD and firmware, with elements processed using the provided callback
|
||||||
|
* functions. The buffer must be deinitialized using @ref pva_kmd_shared_buffer_deinit()
|
||||||
|
* when no longer needed.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Interface identifier for this shared buffer
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
* @param[in] element_size Size of each element in bytes
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] buffer_size Total buffer size in bytes
|
||||||
|
* Valid range: [element_size .. UINT32_MAX]
|
||||||
|
* @param[in] lock_cb Callback function for acquiring buffer lock
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] unlock_cb Callback function for releasing buffer lock
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Buffer initialized successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate buffer memory
|
||||||
|
* @retval PVA_INVAL Invalid parameters or callback pointers
|
||||||
|
* @retval PVA_INTERNAL Failed to register buffer with resource system
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
||||||
uint8_t interface,
|
uint8_t interface,
|
||||||
uint32_t element_size,
|
uint32_t element_size,
|
||||||
@@ -37,14 +146,103 @@ enum pva_error pva_kmd_shared_buffer_init(struct pva_kmd_device *pva,
|
|||||||
shared_buffer_lock_cb lock_cb,
|
shared_buffer_lock_cb lock_cb,
|
||||||
shared_buffer_lock_cb unlock_cb);
|
shared_buffer_lock_cb unlock_cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize a shared buffer and free associated resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Ensures the buffer is properly synchronized and no operations are pending
|
||||||
|
* - Unregisters the buffer memory from the device's resource management system
|
||||||
|
* - Frees the allocated device memory for buffer and header
|
||||||
|
* - Cleans up the buffer structure and callback associations
|
||||||
|
* - Invalidates the buffer for the specified interface identifier
|
||||||
|
* - Ensures proper cleanup of synchronization mechanisms
|
||||||
|
*
|
||||||
|
* After calling this function, the shared buffer becomes invalid and cannot
|
||||||
|
* be used for communication. Any pending operations should be completed
|
||||||
|
* before calling this function to avoid resource leaks or synchronization issues.
|
||||||
|
*
|
||||||
|
* @param[in, out] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Interface identifier for the buffer to deinitialize
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Buffer deinitialized successfully
|
||||||
|
* @retval PVA_INVAL Invalid interface or device pointer
|
||||||
|
* @retval PVA_AGAIN Buffer still has pending operations
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_shared_buffer_deinit(struct pva_kmd_device *pva,
|
enum pva_error pva_kmd_shared_buffer_deinit(struct pva_kmd_device *pva,
|
||||||
uint8_t interface);
|
uint8_t interface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process pending elements in the shared buffer
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the buffer lock using the configured lock callback
|
||||||
|
* - Checks for new elements available in the shared buffer
|
||||||
|
* - Processes each available element using the configured process callback
|
||||||
|
* - Updates buffer pointers to mark elements as consumed
|
||||||
|
* - Handles buffer wraparound and overflow conditions appropriately
|
||||||
|
* - Releases the buffer lock using the configured unlock callback
|
||||||
|
* - Maintains proper synchronization between KMD and firmware
|
||||||
|
*
|
||||||
|
* This function is typically called in response to notifications from
|
||||||
|
* firmware indicating that new data is available in the shared buffer.
|
||||||
|
* The processing continues until all available elements have been handled.
|
||||||
|
*
|
||||||
|
* @param[in] pva_dev Pointer to PVA device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Interface identifier for the buffer to process
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*/
|
||||||
void pva_kmd_shared_buffer_process(void *pva_dev, uint8_t interface);
|
void pva_kmd_shared_buffer_process(void *pva_dev, uint8_t interface);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bind a processing handler to a shared buffer interface
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Associates a processing callback with the specified shared buffer interface
|
||||||
|
* - Stores the provided context data for use during element processing
|
||||||
|
* - Configures the buffer to use the specified handler for incoming elements
|
||||||
|
* - Validates that the interface and handler are properly configured
|
||||||
|
* - Updates internal state to enable processing for this interface
|
||||||
|
*
|
||||||
|
* The bound handler will be called for each element that needs processing
|
||||||
|
* on the specified interface. The context data is passed to the handler
|
||||||
|
* to provide any necessary state or configuration information.
|
||||||
|
*
|
||||||
|
* @param[in] pva_dev Pointer to PVA device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Interface identifier for the buffer
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
* @param[in] data Context data to pass to the processing handler
|
||||||
|
* Valid value: can be null if no context needed
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Handler bound successfully
|
||||||
|
* @retval PVA_INVAL Invalid interface or device pointer
|
||||||
|
* @retval PVA_INTERNAL Buffer not properly initialized
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_bind_shared_buffer_handler(void *pva_dev,
|
enum pva_error pva_kmd_bind_shared_buffer_handler(void *pva_dev,
|
||||||
uint8_t interface,
|
uint8_t interface,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the processing handler from a shared buffer interface
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Removes the processing callback association from the specified interface
|
||||||
|
* - Clears any stored context data for the interface
|
||||||
|
* - Disables element processing for the interface
|
||||||
|
* - Ensures proper cleanup of handler-related resources
|
||||||
|
* - Updates internal state to reflect the handler removal
|
||||||
|
*
|
||||||
|
* After calling this function, the shared buffer will no longer process
|
||||||
|
* elements for the specified interface until a new handler is bound using
|
||||||
|
* @ref pva_kmd_bind_shared_buffer_handler().
|
||||||
|
*
|
||||||
|
* @param[in] pva_dev Pointer to PVA device structure
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] interface Interface identifier for the buffer
|
||||||
|
* Valid range: [0 .. PVA_MAX_NUM_CCQ-1]
|
||||||
|
*/
|
||||||
void pva_kmd_release_shared_buffer_handler(void *pva_dev, uint8_t interface);
|
void pva_kmd_release_shared_buffer_handler(void *pva_dev, uint8_t interface);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "pva_kmd_silicon_boot.h"
|
#include "pva_kmd_silicon_boot.h"
|
||||||
#include "pva_kmd_shim_silicon.h"
|
#include "pva_kmd_shim_silicon.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
static inline void pva_kmd_set_sema(struct pva_kmd_device *pva,
|
static inline void pva_kmd_set_sema(struct pva_kmd_device *pva,
|
||||||
uint32_t sema_idx, uint32_t val)
|
uint32_t sema_idx, uint32_t val)
|
||||||
@@ -20,21 +21,6 @@ static inline void pva_kmd_set_sema(struct pva_kmd_device *pva,
|
|||||||
pva_kmd_write(pva, safe_addu32(PVA_REG_HSP_SS0_SET_ADDR, gap), val);
|
pva_kmd_write(pva, safe_addu32(PVA_REG_HSP_SS0_SET_ADDR, gap), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_fw_print_buffer(struct pva_kmd_fw_print_buffer *print_buffer,
|
|
||||||
void *debug_buffer_va)
|
|
||||||
{
|
|
||||||
print_buffer->buffer_info = pva_offset_pointer(
|
|
||||||
debug_buffer_va,
|
|
||||||
FW_TRACE_BUFFER_SIZE + FW_CODE_COVERAGE_BUFFER_SIZE);
|
|
||||||
print_buffer->buffer_info->size =
|
|
||||||
FW_DEBUG_LOG_BUFFER_SIZE - sizeof(*print_buffer->buffer_info);
|
|
||||||
print_buffer->buffer_info->head = 0;
|
|
||||||
print_buffer->buffer_info->tail = 0;
|
|
||||||
print_buffer->buffer_info->flags = 0;
|
|
||||||
print_buffer->content = pva_offset_pointer(
|
|
||||||
print_buffer->buffer_info, sizeof(*print_buffer->buffer_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disable_sec_mission_error_reporting(struct pva_kmd_device *pva)
|
static void disable_sec_mission_error_reporting(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
pva_kmd_write(pva, PVA_REG_SEC_ERRSLICE0_MISSIONERR_ENABLE_ADDR, 0U);
|
pva_kmd_write(pva, PVA_REG_SEC_ERRSLICE0_MISSIONERR_ENABLE_ADDR, 0U);
|
||||||
@@ -55,16 +41,17 @@ void pva_kmd_config_evp_seg_regs(struct pva_kmd_device *pva)
|
|||||||
{
|
{
|
||||||
uint64_t seg_reg_value;
|
uint64_t seg_reg_value;
|
||||||
/* EVP */
|
/* EVP */
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_RESET_ADDR, EVP_RESET_VECTOR);
|
pva_kmd_write(pva, PVA_REG_EVP_RESET_ADDR, PVA_EVP_RESET_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_UNDEF_ADDR,
|
pva_kmd_write(pva, PVA_REG_EVP_UNDEF_ADDR,
|
||||||
EVP_UNDEFINED_INSTRUCTION_VECTOR);
|
PVA_EVP_UNDEFINED_INSTRUCTION_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_SWI_ADDR, EVP_SVC_VECTOR);
|
pva_kmd_write(pva, PVA_REG_EVP_SWI_ADDR, PVA_EVP_SVC_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_PREFETCH_ABORT_ADDR,
|
pva_kmd_write(pva, PVA_REG_EVP_PREFETCH_ABORT_ADDR,
|
||||||
EVP_PREFETCH_ABORT_VECTOR);
|
PVA_EVP_PREFETCH_ABORT_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_DATA_ABORT_ADDR, EVP_DATA_ABORT_VECTOR);
|
pva_kmd_write(pva, PVA_REG_EVP_DATA_ABORT_ADDR,
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_RSVD_ADDR, EVP_RESERVED_VECTOR);
|
PVA_EVP_DATA_ABORT_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_IRQ_ADDR, EVP_IRQ_VECTOR);
|
pva_kmd_write(pva, PVA_REG_EVP_RSVD_ADDR, PVA_EVP_RESERVED_VECTOR);
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_FIQ_ADDR, EVP_FIQ_VECTOR);
|
pva_kmd_write(pva, PVA_REG_EVP_IRQ_ADDR, PVA_EVP_IRQ_VECTOR);
|
||||||
|
pva_kmd_write(pva, PVA_REG_EVP_FIQ_ADDR, PVA_EVP_FIQ_VECTOR);
|
||||||
/* R5 regions are defined as:
|
/* R5 regions are defined as:
|
||||||
* - PRIV1 region for firmware code and data.
|
* - PRIV1 region for firmware code and data.
|
||||||
* - PRIV2 region for debug printf data.
|
* - PRIV2 region for debug printf data.
|
||||||
@@ -109,7 +96,8 @@ void pva_kmd_config_evp_seg_regs(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
void pva_kmd_config_scr_regs(struct pva_kmd_device *pva)
|
void pva_kmd_config_scr_regs(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
uint32_t scr_lock_mask = pva->is_silicon ? 0xFFFFFFFF : (~PVA_SCR_LOCK);
|
uint32_t scr_lock_mask =
|
||||||
|
pva->is_silicon ? 0xFFFFFFFFU : (~PVA_SCR_LOCK);
|
||||||
|
|
||||||
pva_kmd_write(pva, PVA_REG_EVP_SCR_ADDR,
|
pva_kmd_write(pva, PVA_REG_EVP_SCR_ADDR,
|
||||||
PVA_EVP_SCR_VAL & scr_lock_mask);
|
PVA_EVP_SCR_VAL & scr_lock_mask);
|
||||||
@@ -133,8 +121,11 @@ void pva_kmd_config_sid(struct pva_kmd_device *pva)
|
|||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint8_t priv1_sid;
|
uint8_t priv1_sid;
|
||||||
uint8_t priv_sid;
|
uint8_t priv_sid;
|
||||||
priv_sid = pva->stream_ids[PVA_R5_SMMU_CONTEXT_ID] & 0xFF;
|
priv_sid = (uint8_t)(pva->stream_ids[PVA_R5_SMMU_CONTEXT_ID] &
|
||||||
priv1_sid = pva->stream_ids[pva->r5_image_smmu_context_id] & 0xFF;
|
(uint8_t)U8_MAX);
|
||||||
|
priv1_sid = (uint8_t)(pva->stream_ids[pva->r5_image_smmu_context_id] &
|
||||||
|
(uint8_t)U8_MAX);
|
||||||
|
|
||||||
/* Priv SIDs */
|
/* Priv SIDs */
|
||||||
if (pva->load_from_gsc) {
|
if (pva->load_from_gsc) {
|
||||||
pva_kmd_write(pva, pva->regspec.cfg_priv_sid,
|
pva_kmd_write(pva, pva->regspec.cfg_priv_sid,
|
||||||
@@ -159,7 +150,7 @@ void pva_kmd_config_sid(struct pva_kmd_device *pva)
|
|||||||
}
|
}
|
||||||
/* User SIDs */
|
/* User SIDs */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
for (i = 1; i < pva->hw_consts.n_smmu_contexts - 1; i++) {
|
for (i = 1U; i < (pva->hw_consts.n_smmu_contexts - 1U); i++) {
|
||||||
addr = safe_addu32(pva->regspec.cfg_user_sid_base, offset);
|
addr = safe_addu32(pva->regspec.cfg_user_sid_base, offset);
|
||||||
pva_kmd_write(pva, addr, pva->stream_ids[i]);
|
pva_kmd_write(pva, addr, pva->stream_ids[i]);
|
||||||
offset = safe_addu32(offset, 4U);
|
offset = safe_addu32(offset, 4U);
|
||||||
@@ -173,7 +164,7 @@ static uint32_t get_syncpt_offset(struct pva_kmd_device *pva,
|
|||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
offset = safe_subu64(syncpt_iova, pva_kmd_get_r5_iova_start());
|
offset = safe_subu64(syncpt_iova, pva_kmd_get_r5_iova_start());
|
||||||
|
|
||||||
ASSERT(offset <= UINT32_MAX);
|
ASSERT(offset <= U32_MAX);
|
||||||
return (uint32_t)offset;
|
return (uint32_t)offset;
|
||||||
} else {
|
} else {
|
||||||
// This is only for SIM mode where syncpoints are not supported.
|
// This is only for SIM mode where syncpoints are not supported.
|
||||||
@@ -188,7 +179,8 @@ enum pva_error pva_kmd_load_fw(struct pva_kmd_device *pva)
|
|||||||
uint32_t boot_sema = 0;
|
uint32_t boot_sema = 0;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
uint32_t checkpoint;
|
uint32_t checkpoint;
|
||||||
uint32_t scr_lock_mask = pva->is_silicon ? 0xFFFFFFFF : (~PVA_SCR_LOCK);
|
uint32_t scr_lock_mask =
|
||||||
|
pva->is_silicon ? 0xFFFFFFFFU : (~PVA_SCR_LOCK);
|
||||||
|
|
||||||
/* Load firmware */
|
/* Load firmware */
|
||||||
if (!pva->load_from_gsc) {
|
if (!pva->load_from_gsc) {
|
||||||
@@ -210,7 +202,7 @@ enum pva_error pva_kmd_load_fw(struct pva_kmd_device *pva)
|
|||||||
"pva_kmd_device_memory_alloc_map failed in pva_kmd_load_fw");
|
"pva_kmd_device_memory_alloc_map failed in pva_kmd_load_fw");
|
||||||
goto free_fw_mem;
|
goto free_fw_mem;
|
||||||
}
|
}
|
||||||
init_fw_print_buffer(&pva->fw_print_buffer, pva->fw_debug_mem->va);
|
pva_kmd_init_fw_print_buffer(pva, pva->fw_debug_mem->va);
|
||||||
pva->debugfs_context.r5_ocd_stage_buffer = pva->fw_debug_mem->va;
|
pva->debugfs_context.r5_ocd_stage_buffer = pva->fw_debug_mem->va;
|
||||||
|
|
||||||
/* Program SCRs */
|
/* Program SCRs */
|
||||||
@@ -253,9 +245,11 @@ enum pva_error pva_kmd_load_fw(struct pva_kmd_device *pva)
|
|||||||
if (pva->bl_sector_pack_format == PVA_BL_XBAR_RAW) {
|
if (pva->bl_sector_pack_format == PVA_BL_XBAR_RAW) {
|
||||||
boot_sema = PVA_BOOT_SEMA_USE_XBAR_RAW;
|
boot_sema = PVA_BOOT_SEMA_USE_XBAR_RAW;
|
||||||
}
|
}
|
||||||
|
#if SYSTEM_TESTS_ENABLED == 1
|
||||||
if (pva->test_mode) {
|
if (pva->test_mode) {
|
||||||
boot_sema |= PVA_BOOT_SEMA_TEST_MODE;
|
boot_sema |= PVA_BOOT_SEMA_TEST_MODE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
pva_kmd_set_sema(pva, PVA_BOOT_SEMA, boot_sema);
|
pva_kmd_set_sema(pva, PVA_BOOT_SEMA, boot_sema);
|
||||||
|
|
||||||
pva_kmd_set_sema(pva, PVA_RO_SYNC_BASE_SEMA,
|
pva_kmd_set_sema(pva, PVA_RO_SYNC_BASE_SEMA,
|
||||||
@@ -294,7 +288,7 @@ enum pva_error pva_kmd_load_fw(struct pva_kmd_device *pva)
|
|||||||
pva, pva->regspec.ccq_regs[PVA_PRIV_CCQ_ID]
|
pva, pva->regspec.ccq_regs[PVA_PRIV_CCQ_ID]
|
||||||
.status[PVA_REG_CCQ_STATUS6_IDX]);
|
.status[PVA_REG_CCQ_STATUS6_IDX]);
|
||||||
pva_kmd_log_err_hex32("Checkpoint value:", checkpoint);
|
pva_kmd_log_err_hex32("Checkpoint value:", checkpoint);
|
||||||
pva_kmd_report_error_fsi(pva, err);
|
pva_kmd_report_error_fsi(pva, (uint32_t)err);
|
||||||
goto free_sec_lic;
|
goto free_sec_lic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +297,7 @@ enum pva_error pva_kmd_load_fw(struct pva_kmd_device *pva)
|
|||||||
free_sec_lic:
|
free_sec_lic:
|
||||||
pva_kmd_free_intr(pva, PVA_KMD_INTR_LINE_SEC_LIC);
|
pva_kmd_free_intr(pva, PVA_KMD_INTR_LINE_SEC_LIC);
|
||||||
free_fw_debug_mem:
|
free_fw_debug_mem:
|
||||||
pva_kmd_drain_fw_print(&pva->fw_print_buffer);
|
pva_kmd_drain_fw_print(pva);
|
||||||
pva_kmd_freeze_fw(pva);
|
pva_kmd_freeze_fw(pva);
|
||||||
pva_kmd_device_memory_free(pva->fw_debug_mem);
|
pva_kmd_device_memory_free(pva->fw_debug_mem);
|
||||||
free_fw_mem:
|
free_fw_mem:
|
||||||
@@ -335,7 +329,7 @@ void pva_kmd_freeze_fw(struct pva_kmd_device *pva)
|
|||||||
void pva_kmd_unload_fw(struct pva_kmd_device *pva)
|
void pva_kmd_unload_fw(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
pva_kmd_free_intr(pva, PVA_KMD_INTR_LINE_SEC_LIC);
|
pva_kmd_free_intr(pva, PVA_KMD_INTR_LINE_SEC_LIC);
|
||||||
pva_kmd_drain_fw_print(&pva->fw_print_buffer);
|
pva_kmd_drain_fw_print(pva);
|
||||||
|
|
||||||
// FW so that we can free memory
|
// FW so that we can free memory
|
||||||
pva_kmd_freeze_fw(pva);
|
pva_kmd_freeze_fw(pva);
|
||||||
|
|||||||
@@ -9,27 +9,44 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Configure EVP and Segment config registers
|
* @brief Configure EVP and Segment config registers
|
||||||
*
|
*
|
||||||
* This function configures the EVP and Segment config registers.
|
* @details This function configures the Exception Vector Prefix (EVP) and
|
||||||
|
* Segment configuration registers for the PVA device. The EVP registers
|
||||||
|
* control the location of exception vectors for the embedded processor,
|
||||||
|
* while segment configuration registers define memory mapping and access
|
||||||
|
* permissions. This configuration is essential for proper firmware loading
|
||||||
|
* and execution on the PVA hardware.
|
||||||
*
|
*
|
||||||
* @param pva Pointer to the PVA device.
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
*/
|
*/
|
||||||
void pva_kmd_config_evp_seg_regs(struct pva_kmd_device *pva);
|
void pva_kmd_config_evp_seg_regs(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configure SCR registers.
|
* @brief Configure SCR (System Control Register) registers
|
||||||
*
|
*
|
||||||
* This function configures the SCR registers.
|
* @details This function configures the System Control Registers (SCR) for
|
||||||
|
* the PVA device. SCR registers control various system-level settings including
|
||||||
|
* cache policies, memory protection attributes, and processor modes. Proper
|
||||||
|
* SCR configuration is critical for secure and efficient operation of the
|
||||||
|
* embedded processor within the PVA hardware.
|
||||||
*
|
*
|
||||||
* @param pva Pointer to the PVA device.
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
*/
|
*/
|
||||||
void pva_kmd_config_scr_regs(struct pva_kmd_device *pva);
|
void pva_kmd_config_scr_regs(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configure SID registers.
|
* @brief Configure SID (Stream ID) registers
|
||||||
*
|
*
|
||||||
* This function configures the SID registers.
|
* @details This function configures the Stream ID (SID) registers for the PVA
|
||||||
|
* device. SID registers define the stream identifiers used by the SMMU (System
|
||||||
|
* Memory Management Unit) for memory access control and virtualization. Proper
|
||||||
|
* SID configuration ensures that PVA memory accesses are correctly identified
|
||||||
|
* and routed through the appropriate SMMU translation contexts for security
|
||||||
|
* and isolation.
|
||||||
*
|
*
|
||||||
* @param pva Pointer to the PVA device.
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
*/
|
*/
|
||||||
void pva_kmd_config_sid(struct pva_kmd_device *pva);
|
void pva_kmd_config_sid(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,12 @@
|
|||||||
|
|
||||||
#include "pva_kmd_silicon_elf_parser.h"
|
#include "pva_kmd_silicon_elf_parser.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
#ifndef max
|
#ifndef max
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UINT8_MAX
|
|
||||||
#define UINT8_MAX 0xFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// CERT complains about casts from const uint8_t*, so do intermediate cast to void*
|
// CERT complains about casts from const uint8_t*, so do intermediate cast to void*
|
||||||
static inline const void *uint_8_to_void(const uint8_t *const p)
|
static inline const void *uint_8_to_void(const uint8_t *const p)
|
||||||
{
|
{
|
||||||
@@ -21,8 +18,8 @@ static inline const void *uint_8_to_void(const uint8_t *const p)
|
|||||||
bool elf_header_check(const elf_ct e)
|
bool elf_header_check(const elf_ct e)
|
||||||
{
|
{
|
||||||
const elfFileHeader *efh = (const elfFileHeader *)e;
|
const elfFileHeader *efh = (const elfFileHeader *)e;
|
||||||
if ((ELFCLASS32 == efh->oclass) &&
|
if ((PVA_ELFCLASS32 == efh->oclass) &&
|
||||||
(ELFMAGIC_LSB == *(const elfWord *)e)) {
|
(PVA_ELFMAGIC_LSB == *(const elfWord *)e)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -217,8 +214,8 @@ static const char *elf_string_at_offset(const elf_parser_ctx e,
|
|||||||
const elfSectionHeader *eshstr,
|
const elfSectionHeader *eshstr,
|
||||||
unsigned int offset)
|
unsigned int offset)
|
||||||
{
|
{
|
||||||
const char *strtab;
|
const char *string_table;
|
||||||
elfOff stroffset;
|
elfOff string_offset;
|
||||||
|
|
||||||
if (SHT_STRTAB != eshstr->type) {
|
if (SHT_STRTAB != eshstr->type) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -226,13 +223,14 @@ static const char *elf_string_at_offset(const elf_parser_ctx e,
|
|||||||
if (offset >= eshstr->size) {
|
if (offset >= eshstr->size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strtab = (const char *)e.elf_file;
|
string_table = (const char *)e.elf_file;
|
||||||
stroffset = eshstr->offset + offset;
|
string_offset = eshstr->offset + offset;
|
||||||
if (stroffset < eshstr->offset) { // check that stroffset doesn't wrap
|
if (string_offset <
|
||||||
|
eshstr->offset) { // check that string_offset doesn't wrap
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strtab = &strtab[stroffset];
|
string_table = &string_table[string_offset];
|
||||||
return strtab;
|
return string_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *elf_section_name(const elf_parser_ctx e,
|
const char *elf_section_name(const elf_parser_ctx e,
|
||||||
@@ -345,7 +343,7 @@ const elfSymbol *elf_symbol(const elf_parser_ctx e, unsigned int index)
|
|||||||
if (index >= (esh->size / esh->entsize)) {
|
if (index >= (esh->size / esh->entsize)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (esh->addralign <= (uint8_t)UINT8_MAX) {
|
if (esh->addralign <= (uint8_t)U8_MAX) {
|
||||||
align = (uint8_t)esh->addralign;
|
align = (uint8_t)esh->addralign;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -387,7 +385,7 @@ const char *elf_symbol_name(const elf_parser_ctx e, const elfSectionHeader *esh,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
p = (const char *)e.elf_file;
|
p = (const char *)e.elf_file;
|
||||||
if (esh->addralign <= (uint8_t)UINT8_MAX) {
|
if (esh->addralign <= (uint8_t)U8_MAX) {
|
||||||
align = (uint8_t)esh->addralign;
|
align = (uint8_t)esh->addralign;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -26,16 +26,16 @@ enum pva_elf_seg_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Maximum number of characters in symbol name */
|
/** Maximum number of characters in symbol name */
|
||||||
#define ELF_MAXIMUM_SYMBOL_LENGTH 64U
|
#define PVA_ELF_MAXIMUM_SYMBOL_LENGTH 64U
|
||||||
|
|
||||||
/** Maximum number of characters in section name */
|
/** Maximum number of characters in section name */
|
||||||
#define ELF_MAXIMUM_SECTION_NAME 64
|
#define PVA_ELF_MAXIMUM_SECTION_NAME 64
|
||||||
|
|
||||||
/** Section name of EXPORTS section */
|
/** Section name of EXPORTS section */
|
||||||
#define ELF_EXPORTS_SECTION "EXPORTS"
|
#define PVA_ELF_EXPORTS_SECTION "EXPORTS"
|
||||||
|
|
||||||
/** Section name of EXPORTS section name length */
|
/** Section name of EXPORTS section name length */
|
||||||
#define ELF_EXPORTS_SECTION_NAME_LENGTH 7
|
#define PVA_ELF_EXPORTS_SECTION_NAME_LENGTH 7
|
||||||
|
|
||||||
/** Alignment needed for Data section of ELFs */
|
/** Alignment needed for Data section of ELFs */
|
||||||
#define DATA_SECTION_ALIGNMENT 32U
|
#define DATA_SECTION_ALIGNMENT 32U
|
||||||
@@ -44,7 +44,7 @@ enum pva_elf_seg_type {
|
|||||||
#define TEXT_SECTION_ALIGNMENT 128U
|
#define TEXT_SECTION_ALIGNMENT 128U
|
||||||
|
|
||||||
/** VPU icache size: 16KB */
|
/** VPU icache size: 16KB */
|
||||||
#define VPU_ICACHE_SIZE (16U * 1024U)
|
#define VPU_ICACHE_SIZE (16UL * 1024UL)
|
||||||
|
|
||||||
/** This value indicates the that current symbol can be ignored in the VPU ELF */
|
/** This value indicates the that current symbol can be ignored in the VPU ELF */
|
||||||
#define SYM_IGNORE 1
|
#define SYM_IGNORE 1
|
||||||
@@ -82,14 +82,14 @@ static const struct pack_rule {
|
|||||||
} };
|
} };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Compares the \a section_name with all
|
* \brief Compares the \a section_name with all
|
||||||
* vpu elf section names until it finds a match and
|
* vpu elf section names until it finds a match and
|
||||||
* then return corresponding segment type.
|
* then return corresponding segment type.
|
||||||
* If the segment type is \ref PVA_SEG_VPU_DATA, then it further
|
* If the segment type is \ref PVA_SEG_VPU_DATA, then it further
|
||||||
* checks if its PVA_SEG_VPU_IN_PARAMS.
|
* checks if its PVA_SEG_VPU_IN_PARAMS.
|
||||||
* \param[in] section_name Name of the section to be searched for, in VPU ELF
|
* \param[in] section_name Name of the section to be searched for, in VPU ELF
|
||||||
* \return returns corresponding value from enum pva_elf_seg_type.
|
* \return returns corresponding value from enum pva_elf_seg_type.
|
||||||
*/
|
*/
|
||||||
static int32_t find_pva_ucode_segment_type(const char *section_name)
|
static int32_t find_pva_ucode_segment_type(const char *section_name)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@@ -105,14 +105,14 @@ static int32_t find_pva_ucode_segment_type(const char *section_name)
|
|||||||
}
|
}
|
||||||
if (ret == (int32_t)PVA_SEG_VPU_DATA) {
|
if (ret == (int32_t)PVA_SEG_VPU_DATA) {
|
||||||
uint64_t section_name_len =
|
uint64_t section_name_len =
|
||||||
strnlen(section_name, ELF_MAXIMUM_SECTION_NAME);
|
strnlen(section_name, PVA_ELF_MAXIMUM_SECTION_NAME);
|
||||||
uint64_t exports_section_name_len =
|
uint64_t exports_section_name_len =
|
||||||
ELF_EXPORTS_SECTION_NAME_LENGTH;
|
PVA_ELF_EXPORTS_SECTION_NAME_LENGTH;
|
||||||
// Check Export section present in DATA segment. Only support export sections.
|
// Check Export section present in DATA segment. Only support export sections.
|
||||||
if ((section_name_len >= exports_section_name_len) &&
|
if ((section_name_len >= exports_section_name_len) &&
|
||||||
(strncmp((section_name +
|
(strncmp((section_name +
|
||||||
(section_name_len - exports_section_name_len)),
|
(section_name_len - exports_section_name_len)),
|
||||||
ELF_EXPORTS_SECTION,
|
PVA_ELF_EXPORTS_SECTION,
|
||||||
(size_t)exports_section_name_len)) == 0) {
|
(size_t)exports_section_name_len)) == 0) {
|
||||||
ret = (int32_t)PVA_SEG_VPU_IN_PARAMS;
|
ret = (int32_t)PVA_SEG_VPU_IN_PARAMS;
|
||||||
}
|
}
|
||||||
@@ -149,8 +149,8 @@ static int32_t validate_symbol(elf_parser_ctx elf, uint32_t symbol_entry_id,
|
|||||||
|
|
||||||
*sym = elf_symbol(elf, symbol_entry_id);
|
*sym = elf_symbol(elf, symbol_entry_id);
|
||||||
if ((*sym == NULL) || ((*sym)->size == 0U) ||
|
if ((*sym == NULL) || ((*sym)->size == 0U) ||
|
||||||
(ELF_ST_BIND(*sym) != STB_GLOBAL) ||
|
(PVA_ELF_ST_BIND(*sym) != STB_GLOBAL) ||
|
||||||
(ELF_ST_TYPE(*sym) == STT_FUNC)) {
|
(PVA_ELF_ST_TYPE(*sym) == STT_FUNC)) {
|
||||||
err = SYM_IGNORE;
|
err = SYM_IGNORE;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ done:
|
|||||||
* @param[in] elf pointer to const image of elf file.
|
* @param[in] elf pointer to const image of elf file.
|
||||||
* @param[in] section_header pointer to VPU ELF PVA_SEG_VPU_IN_PARAMS section header
|
* @param[in] section_header pointer to VPU ELF PVA_SEG_VPU_IN_PARAMS section header
|
||||||
* @param[in, out] symbol_info pointer to ELF image symbol which needs to be updated.
|
* @param[in, out] symbol_info pointer to ELF image symbol which needs to be updated.
|
||||||
*/
|
*/
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
update_exports_symbol(elf_parser_ctx elf,
|
update_exports_symbol(elf_parser_ctx elf,
|
||||||
const elfSectionHeader *section_header,
|
const elfSectionHeader *section_header,
|
||||||
@@ -240,12 +240,19 @@ update_exports_symbol(elf_parser_ctx elf,
|
|||||||
uint32_t symOffset = 0U;
|
uint32_t symOffset = 0U;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
pva_math_error math_err = MATH_OP_SUCCESS;
|
pva_math_error math_err = MATH_OP_SUCCESS;
|
||||||
|
uint32_t symbol_end;
|
||||||
|
uint32_t section_end;
|
||||||
|
|
||||||
|
/* Calculate symbol end address */
|
||||||
|
symbol_end = addu32(symbol_info->vmem_addr,
|
||||||
|
(uint32_t)SIZE_EXPORTS_TABLE_ENTRY, &math_err);
|
||||||
|
/* Calculate section end address */
|
||||||
|
section_end =
|
||||||
|
addu32(section_header->addr, section_header->size, &math_err);
|
||||||
|
|
||||||
if ((section_header == NULL) ||
|
if ((section_header == NULL) ||
|
||||||
(symbol_info->vmem_addr < section_header->addr) ||
|
(symbol_info->vmem_addr < section_header->addr) ||
|
||||||
(addu32(symbol_info->vmem_addr, (uint32_t)SIZE_EXPORTS_TABLE_ENTRY,
|
(symbol_end > section_end)) {
|
||||||
&math_err) >
|
|
||||||
addu32(section_header->addr, section_header->size, &math_err))) {
|
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
@@ -258,9 +265,10 @@ update_exports_symbol(elf_parser_ctx elf,
|
|||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
symbol_info->symbol_type = *(uint8_t *)((uintptr_t)&data[symOffset]);
|
symbol_info->symbol_type = (enum pva_symbol_type)(
|
||||||
if ((symbol_info->symbol_type == (uint8_t)PVA_SYM_TYPE_INVALID) ||
|
*(uint8_t *)((uintptr_t)&data[symOffset]));
|
||||||
(symbol_info->symbol_type >= (uint8_t)PVA_SYM_TYPE_MAX)) {
|
if ((symbol_info->symbol_type == PVA_SYM_TYPE_INVALID) ||
|
||||||
|
(symbol_info->symbol_type >= PVA_SYM_TYPE_MAX)) {
|
||||||
pva_kmd_log_err("Invalid symbol type found");
|
pva_kmd_log_err("Invalid symbol type found");
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -424,7 +432,7 @@ static void *pva_realloc(void *ptr, uint32_t old_size, uint32_t new_size)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(new_buffer, ptr, old_size);
|
(void)memcpy(new_buffer, ptr, old_size);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pva_kmd_free(ptr);
|
pva_kmd_free(ptr);
|
||||||
@@ -439,6 +447,7 @@ static void *copy_text_section(const elf_parser_ctx elf,
|
|||||||
uint32_t const *word;
|
uint32_t const *word;
|
||||||
uint32_t *dst_word;
|
uint32_t *dst_word;
|
||||||
uint32_t wi;
|
uint32_t wi;
|
||||||
|
char *base;
|
||||||
/* The load address in section header is in words (uint32_t) */
|
/* The load address in section header is in words (uint32_t) */
|
||||||
uint32_t load_addr_bytes =
|
uint32_t load_addr_bytes =
|
||||||
safe_mulu32(section_header->addr, (uint32_t)sizeof(uint32_t));
|
safe_mulu32(section_header->addr, (uint32_t)sizeof(uint32_t));
|
||||||
@@ -464,9 +473,14 @@ static void *copy_text_section(const elf_parser_ctx elf,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
word = (uint32_t const *)elf_data;
|
word = (uint32_t const *)(void const *)elf_data;
|
||||||
|
|
||||||
dst_word = (uint32_t *)((uintptr_t)out_buffer + load_addr_bytes);
|
ASSERT(((uintptr_t)(void *)out_buffer % sizeof(uint32_t)) == 0U);
|
||||||
|
ASSERT((load_addr_bytes % sizeof(uint32_t)) == 0U);
|
||||||
|
|
||||||
|
/* Use byte pointer arithmetic to avoid INT36-C violation */
|
||||||
|
base = (char *)out_buffer;
|
||||||
|
dst_word = (uint32_t *)(void *)(base + load_addr_bytes);
|
||||||
for (wi = 0; wi < (section_header->size / sizeof(uint32_t)); wi++) {
|
for (wi = 0; wi < (section_header->size / sizeof(uint32_t)); wi++) {
|
||||||
dst_word[wi] = change_byte_order(word[wi]);
|
dst_word[wi] = change_byte_order(word[wi]);
|
||||||
}
|
}
|
||||||
@@ -548,7 +562,7 @@ static void copy_data_section(const elf_parser_ctx elf,
|
|||||||
|
|
||||||
ASSERT(elf_data != NULL);
|
ASSERT(elf_data != NULL);
|
||||||
|
|
||||||
memcpy(dst, elf_data, section_header->size);
|
(void)memcpy(dst, (const void *)elf_data, section_header->size);
|
||||||
|
|
||||||
*buffer_offset = safe_addu32(*buffer_offset, aligned_size);
|
*buffer_offset = safe_addu32(*buffer_offset, aligned_size);
|
||||||
}
|
}
|
||||||
@@ -683,7 +697,7 @@ load_sections(struct pva_kmd_device *pva, uint8_t smmu_id,
|
|||||||
|
|
||||||
ASSERT(TEXT_SECTION_ALIGNMENT >= DATA_SECTION_ALIGNMENT);
|
ASSERT(TEXT_SECTION_ALIGNMENT >= DATA_SECTION_ALIGNMENT);
|
||||||
/* This is guaranteed to be true as TEXT_SECTION_ALIGNMENT is more strict */
|
/* This is guaranteed to be true as TEXT_SECTION_ALIGNMENT is more strict */
|
||||||
ASSERT(data_begin % DATA_SECTION_ALIGNMENT == 0);
|
ASSERT(data_begin % DATA_SECTION_ALIGNMENT == 0U);
|
||||||
|
|
||||||
/* Map it as read-only. TODO: when VPU debugger is supported, we may
|
/* Map it as read-only. TODO: when VPU debugger is supported, we may
|
||||||
* need to map text as READ_WRITE conditionally. */
|
* need to map text as READ_WRITE conditionally. */
|
||||||
@@ -693,9 +707,9 @@ load_sections(struct pva_kmd_device *pva, uint8_t smmu_id,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dev_mem->va, text_section_buf, text_size);
|
(void)memcpy(dev_mem->va, text_section_buf, text_size);
|
||||||
memcpy(pva_offset_pointer(dev_mem->va, data_begin), data_section_buf,
|
(void)memcpy(pva_offset_pointer(dev_mem->va, data_begin),
|
||||||
data_size);
|
data_section_buf, data_size);
|
||||||
|
|
||||||
*out_data_begin_offset = data_begin;
|
*out_data_begin_offset = data_begin;
|
||||||
out:
|
out:
|
||||||
@@ -744,13 +758,16 @@ load_metainfo(struct pva_kmd_device *pva, uint64_t section_iova,
|
|||||||
iova_hi(addu64(section_iova, data_begin_off, &math_err));
|
iova_hi(addu64(section_iova, data_begin_off, &math_err));
|
||||||
metainfo->data_section_addr_lo =
|
metainfo->data_section_addr_lo =
|
||||||
iova_lo(addu64(section_iova, data_begin_off, &math_err));
|
iova_lo(addu64(section_iova, data_begin_off, &math_err));
|
||||||
metainfo->num_data_sections = n_data_sections;
|
/* CERT INT31-C: n_data_sections is constrained by ELF structure,
|
||||||
|
* practically always fits in uint8_t, safe to cast */
|
||||||
|
metainfo->num_data_sections = (uint8_t)n_data_sections;
|
||||||
metainfo->num_vmem_buffers = n_symbols;
|
metainfo->num_vmem_buffers = n_symbols;
|
||||||
|
|
||||||
data_sections_mem = pva_offset_pointer(metainfo, sizeof(*metainfo));
|
data_sections_mem = pva_offset_pointer(metainfo, sizeof(*metainfo));
|
||||||
if (n_data_sections > 0U && section_infos != NULL) {
|
if (n_data_sections > 0U && section_infos != NULL) {
|
||||||
memcpy(data_sections_mem, section_infos,
|
(void)memcpy(data_sections_mem, section_infos,
|
||||||
mulu32(n_data_sections, (uint32_t)sizeof(*section_infos),
|
mulu32(n_data_sections,
|
||||||
|
(uint32_t)sizeof(*section_infos),
|
||||||
&math_err));
|
&math_err));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,6 +793,77 @@ out:
|
|||||||
return dev_mem;
|
return dev_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate ELF, count symbols and allocate symbol table
|
||||||
|
*/
|
||||||
|
static enum pva_error
|
||||||
|
validate_and_prepare_symbols(elf_parser_ctx elf,
|
||||||
|
struct pva_kmd_exec_symbol_table *out_symbol_table)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
pva_math_error math_err = MATH_OP_SUCCESS;
|
||||||
|
uint32_t num_symbols = 0;
|
||||||
|
|
||||||
|
err = validate_elf(elf);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = count_symbols(elf, &num_symbols);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_symbol_table->n_symbols = num_symbols;
|
||||||
|
if (num_symbols > 0U) {
|
||||||
|
out_symbol_table->symbols = pva_kmd_zalloc(
|
||||||
|
mulu32((uint32_t)sizeof(struct pva_symbol_info),
|
||||||
|
num_symbols, &math_err));
|
||||||
|
if (out_symbol_table->symbols == NULL) {
|
||||||
|
err = PVA_NOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (math_err != MATH_OP_SUCCESS) {
|
||||||
|
err = PVA_ERR_MATH_OP;
|
||||||
|
pva_kmd_log_err(
|
||||||
|
"pva_kmd_load_executable: validate_and_prepare_symbols math error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process data sections and prepare data section buffer
|
||||||
|
*/
|
||||||
|
static enum pva_error
|
||||||
|
process_data_sections(elf_parser_ctx elf, uint32_t *n_data_sections,
|
||||||
|
uint32_t *total_data_section_size,
|
||||||
|
void **data_section_buf,
|
||||||
|
struct pva_fw_data_section_info **section_infos)
|
||||||
|
{
|
||||||
|
enum pva_error err = PVA_SUCCESS;
|
||||||
|
|
||||||
|
err = count_data_sections(elf, n_data_sections,
|
||||||
|
total_data_section_size);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's OK to not have data sections */
|
||||||
|
if (*total_data_section_size != 0U) {
|
||||||
|
*data_section_buf =
|
||||||
|
aggregate_data_sections(elf, *n_data_sections,
|
||||||
|
*total_data_section_size,
|
||||||
|
section_infos);
|
||||||
|
ASSERT(*data_section_buf != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
||||||
struct pva_kmd_device *pva, uint8_t dma_smmu_id,
|
struct pva_kmd_device *pva, uint8_t dma_smmu_id,
|
||||||
@@ -784,9 +872,7 @@ pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
|||||||
struct pva_kmd_device_memory **out_sections)
|
struct pva_kmd_device_memory **out_sections)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
pva_math_error math_err = MATH_OP_SUCCESS;
|
|
||||||
elf_parser_ctx elf = { 0 };
|
elf_parser_ctx elf = { 0 };
|
||||||
uint32_t num_symbols = 0;
|
|
||||||
uint32_t n_data_sections;
|
uint32_t n_data_sections;
|
||||||
uint32_t total_data_section_size = 0;
|
uint32_t total_data_section_size = 0;
|
||||||
struct pva_fw_data_section_info *section_infos = NULL;
|
struct pva_fw_data_section_info *section_infos = NULL;
|
||||||
@@ -799,32 +885,12 @@ pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
|||||||
|
|
||||||
elf.elf_file = executable_data;
|
elf.elf_file = executable_data;
|
||||||
elf.size = executable_size;
|
elf.size = executable_size;
|
||||||
err = validate_elf(elf);
|
|
||||||
|
err = validate_and_prepare_symbols(elf, out_symbol_table);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = count_symbols(elf, &num_symbols);
|
|
||||||
if (err != PVA_SUCCESS) {
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_symbol_table->n_symbols = num_symbols;
|
|
||||||
if (num_symbols > 0) {
|
|
||||||
out_symbol_table->symbols = pva_kmd_zalloc(
|
|
||||||
mulu32((uint32_t)sizeof(struct pva_symbol_info),
|
|
||||||
num_symbols, &math_err));
|
|
||||||
if (out_symbol_table->symbols == NULL) {
|
|
||||||
err = PVA_NOMEM;
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
if (math_err != MATH_OP_SUCCESS) {
|
|
||||||
err = PVA_ERR_MATH_OP;
|
|
||||||
pva_kmd_log_err("pva_kmd_load_executable math error");
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fill_symbol_table(elf, out_symbol_table,
|
err = fill_symbol_table(elf, out_symbol_table,
|
||||||
pva->hw_consts.n_vmem_regions,
|
pva->hw_consts.n_vmem_regions,
|
||||||
pva->vmem_regions_tab);
|
pva->vmem_regions_tab);
|
||||||
@@ -837,25 +903,17 @@ pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
|||||||
/* Must have text sections */
|
/* Must have text sections */
|
||||||
if (text_section_buf == NULL) {
|
if (text_section_buf == NULL) {
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
"pva_kmd_load_executable aggregate_text_sections error");
|
"pva_kmd_load_executable: aggregate_text_sections error");
|
||||||
goto free_syms;
|
goto free_syms;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = count_data_sections(elf, &n_data_sections,
|
err = process_data_sections(elf, &n_data_sections,
|
||||||
&total_data_section_size);
|
&total_data_section_size, &data_section_buf,
|
||||||
|
§ion_infos);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto free_text_buf;
|
goto free_text_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It's OK to not have data sections */
|
|
||||||
if (total_data_section_size != 0) {
|
|
||||||
data_section_buf =
|
|
||||||
aggregate_data_sections(elf, n_data_sections,
|
|
||||||
total_data_section_size,
|
|
||||||
§ion_infos);
|
|
||||||
ASSERT(data_section_buf != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
sections_mem = load_sections(pva, dma_smmu_id, text_section_buf,
|
sections_mem = load_sections(pva, dma_smmu_id, text_section_buf,
|
||||||
total_text_section_size, data_section_buf,
|
total_text_section_size, data_section_buf,
|
||||||
total_data_section_size, &data_begin_off);
|
total_data_section_size, &data_begin_off);
|
||||||
@@ -863,29 +921,23 @@ pva_kmd_load_executable(const void *executable_data, uint32_t executable_size,
|
|||||||
goto free_data_buf;
|
goto free_data_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
metainfo_mem =
|
metainfo_mem = load_metainfo(pva, sections_mem->iova,
|
||||||
load_metainfo(pva, sections_mem->iova, total_text_section_size,
|
total_text_section_size, data_begin_off,
|
||||||
data_begin_off, total_data_section_size,
|
total_data_section_size, section_infos,
|
||||||
section_infos, n_data_sections,
|
n_data_sections, out_symbol_table->symbols,
|
||||||
out_symbol_table->symbols, num_symbols);
|
out_symbol_table->n_symbols);
|
||||||
if (metainfo_mem == NULL) {
|
if (metainfo_mem == NULL) {
|
||||||
goto free_sec_mem;
|
goto free_sec_mem;
|
||||||
}
|
}
|
||||||
/* Success. Now clean up temporary allocations */
|
|
||||||
if (data_section_buf != NULL) {
|
|
||||||
pva_kmd_free(data_section_buf);
|
|
||||||
}
|
|
||||||
if (section_infos != NULL) {
|
|
||||||
pva_kmd_free(section_infos);
|
|
||||||
}
|
|
||||||
pva_kmd_free(text_section_buf);
|
|
||||||
|
|
||||||
|
/* Success - set outputs and fall through to cleanup */
|
||||||
*out_metainfo = metainfo_mem;
|
*out_metainfo = metainfo_mem;
|
||||||
*out_sections = sections_mem;
|
*out_sections = sections_mem;
|
||||||
|
goto free_data_buf;
|
||||||
|
|
||||||
return PVA_SUCCESS;
|
|
||||||
free_sec_mem:
|
free_sec_mem:
|
||||||
pva_kmd_device_memory_free(sections_mem);
|
pva_kmd_device_memory_free(sections_mem);
|
||||||
|
|
||||||
free_data_buf:
|
free_data_buf:
|
||||||
if (data_section_buf != NULL) {
|
if (data_section_buf != NULL) {
|
||||||
pva_kmd_free(data_section_buf);
|
pva_kmd_free(data_section_buf);
|
||||||
@@ -896,7 +948,9 @@ free_data_buf:
|
|||||||
free_text_buf:
|
free_text_buf:
|
||||||
pva_kmd_free(text_section_buf);
|
pva_kmd_free(text_section_buf);
|
||||||
free_syms:
|
free_syms:
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_free(out_symbol_table->symbols);
|
pva_kmd_free(out_symbol_table->symbols);
|
||||||
|
}
|
||||||
err_out:
|
err_out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,18 +16,19 @@ int pva_kmd_hwpm_ip_reg_op(void *ip_dev, uint32_t reg_op,
|
|||||||
{
|
{
|
||||||
struct pva_kmd_device *pva = ip_dev;
|
struct pva_kmd_device *pva = ip_dev;
|
||||||
|
|
||||||
if (reg_offset > UINT32_MAX)
|
if (reg_offset > U32_MAX)
|
||||||
return PVA_INVAL;
|
return PVA_INVAL;
|
||||||
|
|
||||||
switch (reg_op) {
|
switch (reg_op) {
|
||||||
case TEGRA_SOC_HWPM_IP_REG_OP_READ:
|
case TEGRA_SOC_HWPM_IP_REG_OP_READ:
|
||||||
*reg_data =
|
*reg_data =
|
||||||
pva_kmd_read(pva, safe_addu32(pva->regspec.cfg_perf_mon,
|
pva_kmd_read(pva, safe_addu32(pva->regspec.cfg_perf_mon,
|
||||||
reg_offset));
|
(uint32_t)reg_offset));
|
||||||
break;
|
break;
|
||||||
case TEGRA_SOC_HWPM_IP_REG_OP_WRITE:
|
case TEGRA_SOC_HWPM_IP_REG_OP_WRITE:
|
||||||
pva_kmd_write(
|
pva_kmd_write(pva,
|
||||||
pva, safe_addu32(pva->regspec.cfg_perf_mon, reg_offset),
|
safe_addu32(pva->regspec.cfg_perf_mon,
|
||||||
|
(uint32_t)reg_offset),
|
||||||
*reg_data);
|
*reg_data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,42 +1,97 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
/* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
#ifndef PVA_KMD_SILICON_HWPM_H
|
#ifndef PVA_KMD_SILICON_HWPM_H
|
||||||
#define PVA_KMD_SILICON_HWPM_H
|
#define PVA_KMD_SILICON_HWPM_H
|
||||||
#include "pva_kmd.h"
|
#include "pva_kmd.h"
|
||||||
#include "pva_kmd_shim_debugfs.h"
|
#include "pva_kmd_shim_debugfs.h"
|
||||||
|
|
||||||
|
#if PVA_ENABLE_HWPM == 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief pva_hwpm_ip_pm
|
* @brief PVA hardware performance monitoring power management control
|
||||||
*
|
*
|
||||||
* This function called from Tegra HWPM driver to
|
* @details This function is called from the Tegra HWPM (Hardware Performance
|
||||||
* poweron/off pva device.
|
* Monitoring) driver to control the power state of the PVA device for
|
||||||
*
|
* performance monitoring operations. It manages the power-on/power-off
|
||||||
* @param ip_dev Pointer to PVA device
|
* sequence of the PVA device to enable or disable hardware performance
|
||||||
* @param disable disable/enable power management. PVA is
|
* monitoring capabilities. When disable is false, the PVA device is powered
|
||||||
* powered on when false.
|
* on to allow HWPM register access and monitoring operations.
|
||||||
* @param reg_offset offset of register relative to PVA HWP base
|
*
|
||||||
* @return 0 on Success or negative error code
|
* @param[in] ip_dev Pointer to PVA device instance
|
||||||
*
|
* Valid value: typically @ref pva_kmd_device pointer
|
||||||
*/
|
* @param[in] disable Power management control flag
|
||||||
|
* Valid values:
|
||||||
|
* - true: Disable power management (power off PVA)
|
||||||
|
* - false: Enable power management (power on PVA)
|
||||||
|
*
|
||||||
|
* @retval 0 Power management operation completed successfully
|
||||||
|
* @retval -EINVAL Invalid device pointer or parameter
|
||||||
|
* @retval -ENODEV Device not available or not initialized
|
||||||
|
* @retval -ETIMEDOUT Timeout during power state transition
|
||||||
|
* @retval -EIO Hardware error during power management operation
|
||||||
|
*/
|
||||||
int pva_kmd_hwpm_ip_pm(void *ip_dev, bool disable);
|
int pva_kmd_hwpm_ip_pm(void *ip_dev, bool disable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief pva_hwpm_ip_reg_op
|
* @brief PVA hardware performance monitoring register access operation
|
||||||
*
|
*
|
||||||
* This function called from Tegra HWPM driver to
|
* @details This function is called from the Tegra HWPM (Hardware Performance
|
||||||
* access PVA HWPM registers.
|
* Monitoring) driver to perform read or write operations on PVA HWPM registers.
|
||||||
*
|
* It provides controlled access to performance monitoring registers within the
|
||||||
* @param ip_dev Pointer to PVA device
|
* PVA device, supporting both read and write operations. The function validates
|
||||||
* @param reg_op access operation and can be one of
|
* the register offset, performs the requested operation, and manages data
|
||||||
* TEGRA_SOC_HWPM_IP_REG_OP_READ
|
* transfer to/from the specified register location.
|
||||||
* TEGRA_SOC_HWPM_IP_REG_OP_WRITE
|
*
|
||||||
* @param inst_element_index element index within PVA instance
|
* @param[in] ip_dev Pointer to PVA device instance
|
||||||
* @param reg_offset offset of register relative to PVA HWP base
|
* Valid value: typically @ref pva_kmd_device pointer
|
||||||
* @param reg_data pointer to where data is to be placed or read.
|
* @param[in] reg_op Register operation type
|
||||||
* @return 0 on Success or negative error code
|
* Valid values:
|
||||||
*
|
* - TEGRA_SOC_HWPM_IP_REG_OP_READ: Read operation
|
||||||
*/
|
* - TEGRA_SOC_HWPM_IP_REG_OP_WRITE: Write operation
|
||||||
|
* @param[in] inst_element_index Element index within PVA instance
|
||||||
|
* Valid range: [0 .. PVA_MAX_ELEMENTS-1]
|
||||||
|
* @param[in] reg_offset Register offset relative to PVA HWPM base address
|
||||||
|
* Valid range: [0 .. PVA_HWPM_REGISTER_SPACE_SIZE-4]
|
||||||
|
* Must be 4-byte aligned
|
||||||
|
* @param[in,out] reg_data Pointer to register data
|
||||||
|
* For read: buffer to store read data (output)
|
||||||
|
* For write: buffer containing data to write (input)
|
||||||
|
* Valid value: non-null, must point to valid 32-bit storage
|
||||||
|
*
|
||||||
|
* @retval 0 Register operation completed successfully
|
||||||
|
* @retval -EINVAL Invalid device pointer, operation type, or register offset
|
||||||
|
* @retval -ENODEV Device not available or not initialized
|
||||||
|
* @retval -EACCES Access denied to specified register
|
||||||
|
* @retval -ETIMEDOUT Timeout during register access
|
||||||
|
* @retval -EIO Hardware error during register operation
|
||||||
|
*/
|
||||||
int pva_kmd_hwpm_ip_reg_op(void *ip_dev, uint32_t reg_op,
|
int pva_kmd_hwpm_ip_reg_op(void *ip_dev, uint32_t reg_op,
|
||||||
uint32_t inst_element_index, uint64_t reg_offset,
|
uint32_t inst_element_index, uint64_t reg_offset,
|
||||||
uint32_t *reg_data);
|
uint32_t *reg_data);
|
||||||
|
|
||||||
|
#else /* PVA_ENABLE_HWPM */
|
||||||
|
|
||||||
|
/* Dummy inline functions when HWPM is disabled */
|
||||||
|
static inline int pva_kmd_hwpm_ip_pm(void *ip_dev, bool disable)
|
||||||
|
{
|
||||||
|
(void)ip_dev;
|
||||||
|
(void)disable;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pva_kmd_hwpm_ip_reg_op(void *ip_dev, uint32_t reg_op,
|
||||||
|
uint32_t inst_element_index,
|
||||||
|
uint64_t reg_offset,
|
||||||
|
uint32_t *reg_data)
|
||||||
|
{
|
||||||
|
(void)ip_dev;
|
||||||
|
(void)reg_op;
|
||||||
|
(void)inst_element_index;
|
||||||
|
(void)reg_offset;
|
||||||
|
(void)reg_data;
|
||||||
|
return -1; /* Return error to indicate HWPM not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PVA_ENABLE_HWPM */
|
||||||
#endif //PVA_KMD_SILICON_HWPM_H
|
#endif //PVA_KMD_SILICON_HWPM_H
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "pva_fw_hyp.h"
|
#include "pva_fw_hyp.h"
|
||||||
#include "pva_kmd_msg.h"
|
#include "pva_kmd_msg.h"
|
||||||
#include "pva_kmd_abort.h"
|
#include "pva_kmd_abort.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
struct pva_fw_msg {
|
struct pva_fw_msg {
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
@@ -20,9 +21,9 @@ static void read_hyp_msg(struct pva_kmd_device *pva, struct pva_fw_msg *msg)
|
|||||||
msg->len = PVA_EXTRACT(msg->data[0], PVA_FW_MSG_LEN_MSB,
|
msg->len = PVA_EXTRACT(msg->data[0], PVA_FW_MSG_LEN_MSB,
|
||||||
PVA_FW_MSG_LEN_LSB, uint8_t);
|
PVA_FW_MSG_LEN_LSB, uint8_t);
|
||||||
ASSERT(msg->len <= PVA_ARRAY_SIZE(msg->data));
|
ASSERT(msg->len <= PVA_ARRAY_SIZE(msg->data));
|
||||||
for (i = 1; i < msg->len; i++) {
|
for (i = 1U; i < msg->len; i++) {
|
||||||
msg->data[i] = pva_kmd_read_mailbox(
|
msg->data[i] = pva_kmd_read_mailbox(
|
||||||
pva, PVA_FW_MBOX_TO_HYP_BASE + i - 1);
|
pva, PVA_FW_MBOX_TO_HYP_BASE + i - 1U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,21 +44,21 @@ void pva_kmd_hyp_isr(void *data, enum pva_kmd_intr_line intr_line)
|
|||||||
h1x_val = PVA_EXTRACT(intr_status, PVA_REG_SEC_LIC_INTR_H1X_MSB,
|
h1x_val = PVA_EXTRACT(intr_status, PVA_REG_SEC_LIC_INTR_H1X_MSB,
|
||||||
PVA_REG_SEC_LIC_INTR_H1X_LSB, uint32_t);
|
PVA_REG_SEC_LIC_INTR_H1X_LSB, uint32_t);
|
||||||
|
|
||||||
if (wdt_val != 0) {
|
if (wdt_val != 0U) {
|
||||||
/* Clear interrupt status */
|
/* Clear interrupt status */
|
||||||
pva_kmd_write(pva, pva->regspec.sec_lic_intr_status, wdt_val);
|
pva_kmd_write(pva, pva->regspec.sec_lic_intr_status, wdt_val);
|
||||||
pva_kmd_log_err("PVA watchdog timeout!");
|
pva_kmd_log_err("PVA watchdog timeout!");
|
||||||
pva_kmd_abort_fw(pva, PVA_ERR_WDT_TIMEOUT);
|
pva_kmd_abort_fw(pva, PVA_ERR_WDT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h1x_val != 0) {
|
if (h1x_val != 0U) {
|
||||||
pva_kmd_log_err_u64("Host1x errors", h1x_val);
|
pva_kmd_log_err_u64("Host1x errors", h1x_val);
|
||||||
/* Clear interrupt status */
|
/* Clear interrupt status */
|
||||||
pva_kmd_write(pva, pva->regspec.sec_lic_intr_status, h1x_val);
|
pva_kmd_write(pva, pva->regspec.sec_lic_intr_status, h1x_val);
|
||||||
pva_kmd_abort_fw(pva, PVA_ERR_HOST1X_ERR);
|
pva_kmd_abort_fw(pva, PVA_ERR_HOST1X_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hsp_val != 0) {
|
if (hsp_val != 0U) {
|
||||||
struct pva_fw_msg msg = { 0 };
|
struct pva_fw_msg msg = { 0 };
|
||||||
|
|
||||||
read_hyp_msg(pva, &msg);
|
read_hyp_msg(pva, &msg);
|
||||||
@@ -90,7 +91,15 @@ void pva_kmd_isr(void *data, enum pva_kmd_intr_line intr_line)
|
|||||||
{
|
{
|
||||||
struct pva_kmd_device *pva = data;
|
struct pva_kmd_device *pva = data;
|
||||||
uint32_t intr_status;
|
uint32_t intr_status;
|
||||||
uint8_t intr_interface = intr_line - PVA_KMD_INTR_LINE_CCQ0;
|
uint8_t intr_interface;
|
||||||
|
|
||||||
|
/* Convert interrupt line to interface index (CCQ0=1 -> interface=0, etc.) */
|
||||||
|
if (intr_line >= PVA_KMD_INTR_LINE_CCQ0) {
|
||||||
|
intr_interface = (uint8_t)((uint8_t)intr_line -
|
||||||
|
(uint8_t)PVA_KMD_INTR_LINE_CCQ0);
|
||||||
|
} else {
|
||||||
|
intr_interface = 0U; /* Fallback for invalid input */
|
||||||
|
}
|
||||||
|
|
||||||
intr_status = read_ccq_status(pva, intr_interface, 2) &
|
intr_status = read_ccq_status(pva, intr_interface, 2) &
|
||||||
PVA_REG_CCQ_STATUS2_INTR_ALL_BITS;
|
PVA_REG_CCQ_STATUS2_INTR_ALL_BITS;
|
||||||
@@ -100,7 +109,7 @@ void pva_kmd_isr(void *data, enum pva_kmd_intr_line intr_line)
|
|||||||
*/
|
*/
|
||||||
write_ccq_status(pva, intr_interface, 2, intr_status);
|
write_ccq_status(pva, intr_interface, 2, intr_status);
|
||||||
|
|
||||||
if (intr_status & PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT) {
|
if ((intr_status & PVA_REG_CCQ_STATUS2_INTR_STATUS8_BIT) != 0U) {
|
||||||
pva_kmd_shared_buffer_process(pva, intr_interface);
|
pva_kmd_shared_buffer_process(pva, intr_interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,12 +118,16 @@ enum pva_error pva_kmd_bind_shared_buffer_handler(void *pva_dev,
|
|||||||
uint8_t interface, void *data)
|
uint8_t interface, void *data)
|
||||||
{
|
{
|
||||||
struct pva_kmd_device *pva = (struct pva_kmd_device *)pva_dev;
|
struct pva_kmd_device *pva = (struct pva_kmd_device *)pva_dev;
|
||||||
|
uint8_t base_line = (uint8_t)PVA_KMD_INTR_LINE_CCQ0;
|
||||||
|
uint8_t target_line = safe_addu8(base_line, interface);
|
||||||
return pva_kmd_bind_intr_handler(
|
return pva_kmd_bind_intr_handler(
|
||||||
pva, PVA_KMD_INTR_LINE_CCQ0 + interface, pva_kmd_isr, data);
|
pva, (enum pva_kmd_intr_line)target_line, pva_kmd_isr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_release_shared_buffer_handler(void *pva_dev, uint8_t interface)
|
void pva_kmd_release_shared_buffer_handler(void *pva_dev, uint8_t interface)
|
||||||
{
|
{
|
||||||
struct pva_kmd_device *pva = (struct pva_kmd_device *)pva_dev;
|
struct pva_kmd_device *pva = (struct pva_kmd_device *)pva_dev;
|
||||||
pva_kmd_free_intr(pva, PVA_KMD_INTR_LINE_CCQ0 + interface);
|
uint8_t base_line = (uint8_t)PVA_KMD_INTR_LINE_CCQ0;
|
||||||
|
uint8_t target_line = safe_addu8(base_line, interface);
|
||||||
|
pva_kmd_free_intr(pva, (enum pva_kmd_intr_line)target_line);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,42 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
/* SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
#ifndef PVA_KMD_SILICON_ISR_H
|
#ifndef PVA_KMD_SILICON_ISR_H
|
||||||
#define PVA_KMD_SILICON_ISR_H
|
#define PVA_KMD_SILICON_ISR_H
|
||||||
#include "pva_kmd_silicon_utils.h"
|
#include "pva_kmd_silicon_utils.h"
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Hypervisor interrupt service routine for PVA device
|
||||||
|
*
|
||||||
|
* @details This function handles hypervisor-level interrupts from the PVA
|
||||||
|
* device. It processes interrupts that require hypervisor privileges and
|
||||||
|
* performs necessary actions such as error handling, security validation,
|
||||||
|
* and inter-VM communication. The function identifies the interrupt source
|
||||||
|
* and dispatches appropriate handling routines based on the interrupt line.
|
||||||
|
*
|
||||||
|
* @param[in] data Pointer to device-specific data context
|
||||||
|
* Valid value: typically @ref pva_kmd_device pointer
|
||||||
|
* @param[in] intr_line Interrupt line that triggered the handler
|
||||||
|
* Valid values: @ref pva_kmd_intr_line enumeration values
|
||||||
|
*/
|
||||||
void pva_kmd_hyp_isr(void *data, enum pva_kmd_intr_line intr_line);
|
void pva_kmd_hyp_isr(void *data, enum pva_kmd_intr_line intr_line);
|
||||||
|
|
||||||
/* CCQ interrupt handler */
|
/**
|
||||||
|
* @brief Main interrupt service routine for PVA device
|
||||||
|
*
|
||||||
|
* @details This function serves as the primary interrupt handler for PVA
|
||||||
|
* device interrupts, particularly handling CCQ (Command and Control Queue)
|
||||||
|
* interrupts and other device-level events. It processes hardware interrupts,
|
||||||
|
* identifies the interrupt source, performs necessary acknowledgment, and
|
||||||
|
* dispatches appropriate handling routines. The function ensures proper
|
||||||
|
* interrupt handling and maintains device state consistency.
|
||||||
|
*
|
||||||
|
* @param[in] data Pointer to device-specific data context
|
||||||
|
* Valid value: typically @ref pva_kmd_device pointer
|
||||||
|
* @param[in] intr_line Interrupt line that triggered the handler
|
||||||
|
* Valid values: @ref pva_kmd_intr_line enumeration values
|
||||||
|
*/
|
||||||
void pva_kmd_isr(void *data, enum pva_kmd_intr_line intr_line);
|
void pva_kmd_isr(void *data, enum pva_kmd_intr_line intr_line);
|
||||||
|
|
||||||
#endif // PVA_KMD_SILICON_ISR_H
|
#endif // PVA_KMD_SILICON_ISR_H
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ uint32_t pva_kmd_get_ccq_space(struct pva_kmd_device *pva, uint8_t ccq_id)
|
|||||||
|
|
||||||
void pva_kmd_disable_all_interrupts_nosync(struct pva_kmd_device *pva)
|
void pva_kmd_disable_all_interrupts_nosync(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < PVA_KMD_INTR_LINE_COUNT; i++) {
|
for (uint8_t i = 0; i < (uint8_t)PVA_KMD_INTR_LINE_COUNT; i++) {
|
||||||
pva_kmd_disable_intr_nosync(pva, (enum pva_kmd_intr_line)i);
|
pva_kmd_disable_intr_nosync(pva, (enum pva_kmd_intr_line)i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,21 @@
|
|||||||
#include "pva_kmd_shim_silicon.h"
|
#include "pva_kmd_shim_silicon.h"
|
||||||
#include "pva_math_utils.h"
|
#include "pva_math_utils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a 32-bit value to PVA device register
|
||||||
|
*
|
||||||
|
* @details This inline function writes a 32-bit value to a register within the
|
||||||
|
* PVA device address space. It uses the PVA cluster aperture for register
|
||||||
|
* access and includes debug logging for register write operations. The function
|
||||||
|
* provides a convenient interface for writing to PVA hardware registers.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] addr Register address offset within PVA address space
|
||||||
|
* Valid range: [0 .. PVA_REGISTER_SPACE_SIZE-1]
|
||||||
|
* @param[in] val 32-bit value to write to the register
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
static inline void pva_kmd_write(struct pva_kmd_device *pva, uint32_t addr,
|
static inline void pva_kmd_write(struct pva_kmd_device *pva, uint32_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
@@ -15,6 +30,23 @@ static inline void pva_kmd_write(struct pva_kmd_device *pva, uint32_t addr,
|
|||||||
pva_kmd_aperture_write(pva, PVA_KMD_APERTURE_PVA_CLUSTER, addr, val);
|
pva_kmd_aperture_write(pva, PVA_KMD_APERTURE_PVA_CLUSTER, addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a 32-bit value from PVA device register
|
||||||
|
*
|
||||||
|
* @details This inline function reads a 32-bit value from a register within
|
||||||
|
* the PVA device address space. It uses the PVA cluster aperture for register
|
||||||
|
* access and returns the value read from the specified register address. The
|
||||||
|
* function provides a convenient interface for reading from PVA hardware
|
||||||
|
* registers.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] addr Register address offset within PVA address space
|
||||||
|
* Valid range: [0 .. PVA_REGISTER_SPACE_SIZE-1]
|
||||||
|
*
|
||||||
|
* @retval uint32_t Value read from the register
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
static inline uint32_t pva_kmd_read(struct pva_kmd_device *pva, uint32_t addr)
|
static inline uint32_t pva_kmd_read(struct pva_kmd_device *pva, uint32_t addr)
|
||||||
{
|
{
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
@@ -23,6 +55,22 @@ static inline uint32_t pva_kmd_read(struct pva_kmd_device *pva, uint32_t addr)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a value to HSP shared mailbox register
|
||||||
|
*
|
||||||
|
* @details This inline function writes a value to a specific HSP (Hardware
|
||||||
|
* Synchronization Primitive) shared mailbox register. It calculates the
|
||||||
|
* appropriate register address based on the mailbox index and writes the
|
||||||
|
* value to the corresponding mailbox register. Mailboxes are used for
|
||||||
|
* communication between different processing units.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] mailbox_idx Index of the mailbox to write to
|
||||||
|
* Valid range: [0 .. MAX_MAILBOX_COUNT-1]
|
||||||
|
* @param[in] val 32-bit value to write to the mailbox
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
static inline void pva_kmd_write_mailbox(struct pva_kmd_device *pva,
|
static inline void pva_kmd_write_mailbox(struct pva_kmd_device *pva,
|
||||||
uint32_t mailbox_idx, uint32_t val)
|
uint32_t mailbox_idx, uint32_t val)
|
||||||
{
|
{
|
||||||
@@ -32,6 +80,23 @@ static inline void pva_kmd_write_mailbox(struct pva_kmd_device *pva,
|
|||||||
pva_kmd_write(pva, addr, val);
|
pva_kmd_write(pva, addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a value from HSP shared mailbox register
|
||||||
|
*
|
||||||
|
* @details This inline function reads a value from a specific HSP (Hardware
|
||||||
|
* Synchronization Primitive) shared mailbox register. It calculates the
|
||||||
|
* appropriate register address based on the mailbox index and reads the
|
||||||
|
* value from the corresponding mailbox register. Mailboxes are used for
|
||||||
|
* communication between different processing units.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] mailbox_idx Index of the mailbox to read from
|
||||||
|
* Valid range: [0 .. MAX_MAILBOX_COUNT-1]
|
||||||
|
*
|
||||||
|
* @retval uint32_t Value read from the mailbox register
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
static inline uint32_t pva_kmd_read_mailbox(struct pva_kmd_device *pva,
|
static inline uint32_t pva_kmd_read_mailbox(struct pva_kmd_device *pva,
|
||||||
uint32_t mailbox_idx)
|
uint32_t mailbox_idx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "pva_api_types.h"
|
#include "pva_api_types.h"
|
||||||
#include "pva_kmd_utils.h"
|
#include "pva_kmd_utils.h"
|
||||||
#include "pva_kmd_abort.h"
|
#include "pva_kmd_abort.h"
|
||||||
|
#include "pva_kmd_limits.h"
|
||||||
|
|
||||||
void pva_kmd_submitter_init(struct pva_kmd_submitter *submitter,
|
void pva_kmd_submitter_init(struct pva_kmd_submitter *submitter,
|
||||||
struct pva_kmd_queue *queue,
|
struct pva_kmd_queue *queue,
|
||||||
@@ -150,7 +151,7 @@ enum pva_error pva_kmd_submitter_wait(struct pva_kmd_submitter *submitter,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
while (*fence_addr < fence_val) {
|
while (*fence_addr < fence_val) {
|
||||||
if (pva->recovery) {
|
if (pva->fw_aborted) {
|
||||||
return PVA_ERR_FW_ABORTED;
|
return PVA_ERR_FW_ABORTED;
|
||||||
}
|
}
|
||||||
pva_kmd_sleep_us(poll_interval_us);
|
pva_kmd_sleep_us(poll_interval_us);
|
||||||
@@ -180,7 +181,13 @@ enum pva_error pva_kmd_submit_cmd_sync(struct pva_kmd_submitter *submitter,
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_dst = pva_kmd_reserve_cmd_space(&builder, size);
|
/* Validate that size fits in uint16_t before casting */
|
||||||
|
if (size > (uint64_t)U16_MAX) {
|
||||||
|
pva_kmd_log_err("Command size exceeds UINT16_MAX");
|
||||||
|
err = PVA_INVAL;
|
||||||
|
goto cancel_builder;
|
||||||
|
}
|
||||||
|
cmd_dst = pva_kmd_reserve_cmd_space(&builder, (uint16_t)size);
|
||||||
if (cmd_dst == NULL) {
|
if (cmd_dst == NULL) {
|
||||||
err = PVA_INVAL;
|
err = PVA_INVAL;
|
||||||
pva_kmd_log_err(
|
pva_kmd_log_err(
|
||||||
@@ -188,7 +195,7 @@ enum pva_error pva_kmd_submit_cmd_sync(struct pva_kmd_submitter *submitter,
|
|||||||
goto cancel_builder;
|
goto cancel_builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(cmd_dst, cmds, size);
|
(void)memcpy(cmd_dst, cmds, size);
|
||||||
err = pva_kmd_submitter_submit(submitter, &builder, &fence_val);
|
err = pva_kmd_submitter_submit(submitter, &builder, &fence_val);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
goto cancel_builder;
|
goto cancel_builder;
|
||||||
|
|||||||
@@ -7,21 +7,88 @@
|
|||||||
#include "pva_kmd_mutex.h"
|
#include "pva_kmd_mutex.h"
|
||||||
#include "pva_kmd_queue.h"
|
#include "pva_kmd_queue.h"
|
||||||
|
|
||||||
/** A thread-safe submitter utility */
|
/**
|
||||||
|
* @brief Thread-safe command buffer submission utility
|
||||||
|
*
|
||||||
|
* @details This structure provides a thread-safe interface for submitting
|
||||||
|
* command buffers to PVA queues. It manages submission synchronization,
|
||||||
|
* fence handling, and command buffer chunk allocation to ensure safe
|
||||||
|
* concurrent access from multiple threads while maintaining proper
|
||||||
|
* ordering and completion tracking.
|
||||||
|
*/
|
||||||
struct pva_kmd_submitter {
|
struct pva_kmd_submitter {
|
||||||
/** The lock protects the submission to the queue, including
|
/**
|
||||||
* incrementing the post fence */
|
* @brief Lock protecting submission operations and post fence increment
|
||||||
|
*
|
||||||
|
* @details The lock protects the submission to the queue, including
|
||||||
|
* incrementing the post fence
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t *submit_lock;
|
pva_kmd_mutex_t *submit_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the target queue for submissions
|
||||||
|
*/
|
||||||
struct pva_kmd_queue *queue;
|
struct pva_kmd_queue *queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Virtual address of post fence value in memory
|
||||||
|
*/
|
||||||
uint32_t *post_fence_va;
|
uint32_t *post_fence_va;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Post fence configuration for submission completion tracking
|
||||||
|
*/
|
||||||
struct pva_fw_postfence post_fence;
|
struct pva_fw_postfence post_fence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Next fence value to be assigned to submissions
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
*/
|
||||||
uint32_t fence_future_value;
|
uint32_t fence_future_value;
|
||||||
|
|
||||||
/** This lock protects the use of the chunk_pool*/
|
/**
|
||||||
|
* @brief Lock protecting chunk pool operations
|
||||||
|
*
|
||||||
|
* @details This lock protects the use of the chunk_pool
|
||||||
|
*/
|
||||||
pva_kmd_mutex_t *chunk_pool_lock;
|
pva_kmd_mutex_t *chunk_pool_lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pointer to command buffer chunk pool for allocation
|
||||||
|
*/
|
||||||
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool;
|
struct pva_kmd_cmdbuf_chunk_pool *chunk_pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a PVA command buffer submitter
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes all fields of the submitter structure with provided parameters
|
||||||
|
* - Associates the submitter with the specified queue and synchronization primitives
|
||||||
|
* - Sets up fence management using the provided post fence configuration
|
||||||
|
* - Configures command buffer chunk allocation through the provided chunk pool
|
||||||
|
* - Prepares the submitter for thread-safe command buffer submissions
|
||||||
|
* - Establishes proper locking mechanisms for concurrent operation
|
||||||
|
*
|
||||||
|
* The submitter structure must be allocated before calling this function.
|
||||||
|
* After initialization, the submitter is ready for command buffer preparation
|
||||||
|
* and submission operations using the other submitter functions.
|
||||||
|
*
|
||||||
|
* @param[out] submitter Pointer to @ref pva_kmd_submitter structure to initialize
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] queue Pointer to target @ref pva_kmd_queue for submissions
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] submit_lock Pointer to mutex for submission synchronization
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_pool Pointer to command buffer chunk pool
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] chunk_pool_lock Pointer to mutex for chunk pool synchronization
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] post_fence_va Virtual address of post fence memory location
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] post_fence Pointer to post fence configuration
|
||||||
|
* Valid value: non-null
|
||||||
|
*/
|
||||||
void pva_kmd_submitter_init(struct pva_kmd_submitter *submitter,
|
void pva_kmd_submitter_init(struct pva_kmd_submitter *submitter,
|
||||||
struct pva_kmd_queue *queue,
|
struct pva_kmd_queue *queue,
|
||||||
pva_kmd_mutex_t *submit_lock,
|
pva_kmd_mutex_t *submit_lock,
|
||||||
@@ -30,35 +97,168 @@ void pva_kmd_submitter_init(struct pva_kmd_submitter *submitter,
|
|||||||
uint32_t *post_fence_va,
|
uint32_t *post_fence_va,
|
||||||
struct pva_fw_postfence const *post_fence);
|
struct pva_fw_postfence const *post_fence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepare a command buffer builder for submission
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the chunk pool lock for thread-safe chunk allocation
|
||||||
|
* - Allocates command buffer chunks from the submitter's chunk pool
|
||||||
|
* - Initializes the command buffer builder with allocated chunks
|
||||||
|
* - Sets up the builder for command construction and submission
|
||||||
|
* - Configures chunk linking and memory management for the builder
|
||||||
|
* - Releases the chunk pool lock after successful preparation
|
||||||
|
*
|
||||||
|
* The prepared builder can be used to construct command sequences using
|
||||||
|
* the command buffer builder API. After command construction is complete,
|
||||||
|
* the builder should be submitted using @ref pva_kmd_submitter_submit().
|
||||||
|
*
|
||||||
|
* @param[in, out] submitter Pointer to @ref pva_kmd_submitter structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[out] builder Pointer to @ref pva_kmd_cmdbuf_builder to prepare
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Builder prepared successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate command buffer chunks
|
||||||
|
* @retval PVA_ENOSPC Chunk pool has no available chunks
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_submitter_prepare(struct pva_kmd_submitter *submitter,
|
pva_kmd_submitter_prepare(struct pva_kmd_submitter *submitter,
|
||||||
struct pva_kmd_cmdbuf_builder *builder);
|
struct pva_kmd_cmdbuf_builder *builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit a prepared command buffer to the queue
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the submission lock for thread-safe queue operations
|
||||||
|
* - Finalizes the command buffer and prepares submission information
|
||||||
|
* - Assigns a unique fence value for completion tracking
|
||||||
|
* - Submits the command buffer to the associated queue using @ref pva_kmd_queue_submit()
|
||||||
|
* - Updates the post fence future value for subsequent submissions
|
||||||
|
* - Returns the assigned fence value to the caller for synchronization
|
||||||
|
* - Releases the submission lock after successful submission
|
||||||
|
*
|
||||||
|
* The command buffer builder must be properly prepared using
|
||||||
|
* @ref pva_kmd_submitter_prepare() and populated with commands before
|
||||||
|
* calling this function. The returned fence value can be used with
|
||||||
|
* @ref pva_kmd_submitter_wait() to synchronize on completion.
|
||||||
|
*
|
||||||
|
* @param[in, out] submitter Pointer to @ref pva_kmd_submitter structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in, out] builder Pointer to prepared @ref pva_kmd_cmdbuf_builder
|
||||||
|
* Valid value: non-null, must be prepared
|
||||||
|
* @param[out] out_fence_val Pointer to store the assigned fence value
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Submission completed successfully
|
||||||
|
* @retval PVA_INVAL Invalid submitter or builder parameters
|
||||||
|
* @retval PVA_QUEUE_FULL Target queue has no space for submission
|
||||||
|
* @retval PVA_TIMEDOUT Failed to notify firmware of submission
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_submitter_submit(struct pva_kmd_submitter *submitter,
|
enum pva_error pva_kmd_submitter_submit(struct pva_kmd_submitter *submitter,
|
||||||
struct pva_kmd_cmdbuf_builder *builder,
|
struct pva_kmd_cmdbuf_builder *builder,
|
||||||
uint32_t *out_fence_val);
|
uint32_t *out_fence_val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wait for a submitted command buffer to complete
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Polls the post fence memory location for the specified fence value
|
||||||
|
* - Uses configurable polling intervals to balance CPU usage and latency
|
||||||
|
* - Implements timeout mechanisms to prevent indefinite blocking
|
||||||
|
* - Checks for fence value completion using memory-mapped reads
|
||||||
|
* - Returns success when the fence value is reached or timeout on failure
|
||||||
|
* - Provides blocking synchronization for submitted command buffers
|
||||||
|
*
|
||||||
|
* The fence value must be obtained from a previous call to
|
||||||
|
* @ref pva_kmd_submitter_submit(). The function will block until the
|
||||||
|
* command buffer associated with the fence value completes execution
|
||||||
|
* or the timeout period expires.
|
||||||
|
*
|
||||||
|
* @param[in] submitter Pointer to @ref pva_kmd_submitter structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] fence_val Fence value to wait for completion
|
||||||
|
* Valid range: [0 .. UINT32_MAX]
|
||||||
|
* @param[in] poll_interval_ms Polling interval in milliseconds
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] timeout_ms Timeout period in milliseconds
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Fence value reached, command buffer completed
|
||||||
|
* @retval PVA_TIMEDOUT Timeout expired before fence value reached
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_submitter_wait(struct pva_kmd_submitter *submitter,
|
enum pva_error pva_kmd_submitter_wait(struct pva_kmd_submitter *submitter,
|
||||||
uint32_t fence_val,
|
uint32_t fence_val,
|
||||||
uint32_t poll_interval_ms,
|
uint32_t poll_interval_ms,
|
||||||
uint32_t timeout_ms);
|
uint32_t timeout_ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit a command buffer with custom fence configuration
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Acquires the submission lock for thread-safe queue operations
|
||||||
|
* - Finalizes the command buffer using the provided custom fence configuration
|
||||||
|
* - Submits the command buffer to the associated queue with custom fence
|
||||||
|
* - Uses the provided fence instead of the submitter's default post fence
|
||||||
|
* - Enables custom synchronization mechanisms for specialized use cases
|
||||||
|
* - Releases the submission lock after successful submission
|
||||||
|
*
|
||||||
|
* This function allows for custom fence configurations that may differ
|
||||||
|
* from the submitter's default post fence. The custom fence can specify
|
||||||
|
* different syncpoint targets, fence values, or synchronization behavior
|
||||||
|
* for specialized submission requirements.
|
||||||
|
*
|
||||||
|
* @param[in, out] submitter Pointer to @ref pva_kmd_submitter structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in, out] builder Pointer to prepared @ref pva_kmd_cmdbuf_builder
|
||||||
|
* Valid value: non-null, must be prepared
|
||||||
|
* @param[in] fence Pointer to custom @ref pva_fw_postfence configuration
|
||||||
|
* Valid value: non-null
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Submission completed successfully
|
||||||
|
* @retval PVA_INVAL Invalid submitter, builder, or fence parameters
|
||||||
|
* @retval PVA_QUEUE_FULL Target queue has no space for submission
|
||||||
|
* @retval PVA_TIMEDOUT Failed to notify firmware of submission
|
||||||
|
*/
|
||||||
enum pva_error
|
enum pva_error
|
||||||
pva_kmd_submitter_submit_with_fence(struct pva_kmd_submitter *submitter,
|
pva_kmd_submitter_submit_with_fence(struct pva_kmd_submitter *submitter,
|
||||||
struct pva_kmd_cmdbuf_builder *builder,
|
struct pva_kmd_cmdbuf_builder *builder,
|
||||||
struct pva_fw_postfence *fence);
|
struct pva_fw_postfence *fence);
|
||||||
|
|
||||||
/* prepare submission */
|
/**
|
||||||
/* add cmd */
|
* @brief Submit commands synchronously and wait for completion
|
||||||
/* add cmd */
|
*
|
||||||
/* do submit -> fence value */
|
* @details This function performs the following operations:
|
||||||
/* wait for fence */
|
* - Prepares a command buffer builder with chunk allocation
|
||||||
|
* - Reserves space in the command buffer for the provided commands
|
||||||
/* prepare submission */
|
* - Copies the command data into the reserved buffer space
|
||||||
/* add cmd */
|
* - Submits the command buffer to the firmware via the queue
|
||||||
/* add cmd */
|
* - Waits for command execution to complete using fence synchronization
|
||||||
/* do submit with fence (provide a fence) */
|
* - Automatically cleans up allocated chunks upon completion or error
|
||||||
|
* - Provides a simplified interface for single-shot command submission
|
||||||
/* Helper function to submit several commands and wait for them to complete.
|
*
|
||||||
Total size must be smaller than a chunk. */
|
* This is a convenience function that combines command buffer preparation,
|
||||||
|
* submission, and synchronous waiting into a single operation. The total
|
||||||
|
* command size must fit within a single chunk. For larger command sequences
|
||||||
|
* or asynchronous operation, use the individual submitter functions.
|
||||||
|
*
|
||||||
|
* @param[in] submitter Pointer to @ref pva_kmd_submitter structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
* @param[in] cmds Pointer to command data to submit
|
||||||
|
* Valid value: non-null
|
||||||
|
* @param[in] size Size of command data in bytes
|
||||||
|
* Valid range: [1 .. chunk_size]
|
||||||
|
* @param[in] poll_interval_us Polling interval for fence checking in microseconds
|
||||||
|
* Valid range: [1 .. UINT32_MAX]
|
||||||
|
* @param[in] timeout_us Maximum timeout for command completion in microseconds
|
||||||
|
* Valid range: [poll_interval_us .. UINT32_MAX]
|
||||||
|
*
|
||||||
|
* @retval PVA_SUCCESS Commands submitted and completed successfully
|
||||||
|
* @retval PVA_NOMEM Failed to allocate command buffer chunk
|
||||||
|
* @retval PVA_INVAL Command size exceeds chunk capacity
|
||||||
|
* @retval PVA_QUEUE_FULL Submission queue has no space available
|
||||||
|
* @retval PVA_TIMEDOUT Command execution or submission timed out
|
||||||
|
* @retval PVA_ERR_FW_ABORTED Firmware operation aborted during wait
|
||||||
|
*/
|
||||||
enum pva_error pva_kmd_submit_cmd_sync(struct pva_kmd_submitter *submitter,
|
enum pva_error pva_kmd_submit_cmd_sync(struct pva_kmd_submitter *submitter,
|
||||||
void *cmds, uint32_t size,
|
void *cmds, uint32_t size,
|
||||||
uint32_t poll_interval_us,
|
uint32_t poll_interval_us,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
#include "pva_kmd_t23x.h"
|
#include "pva_kmd_t23x.h"
|
||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_kmd_pfsd.h"
|
||||||
|
|
||||||
struct vmem_region vmem_regions_tab_t23x[PVA_VMEM_REGION_COUNT_T23X] = {
|
struct vmem_region vmem_regions_tab_t23x[PVA_VMEM_REGION_COUNT_T23X] = {
|
||||||
{ .start = T23x_VMEM0_START, .end = T23x_VMEM0_END },
|
{ .start = T23x_VMEM0_START, .end = T23x_VMEM0_END },
|
||||||
@@ -16,7 +17,7 @@ void pva_kmd_device_init_t23x(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
pva->hw_consts.hw_gen = PVA_HW_GEN2;
|
pva->hw_consts.hw_gen = PVA_HW_GEN2;
|
||||||
pva->hw_consts.n_smmu_contexts = PVA_NUM_SMMU_CONTEXTS_T23X;
|
pva->hw_consts.n_smmu_contexts = PVA_NUM_SMMU_CONTEXTS_T23X;
|
||||||
pva->r5_image_smmu_context_id = PVA_NUM_SMMU_CONTEXTS_T23X - 1;
|
pva->r5_image_smmu_context_id = PVA_NUM_SMMU_CONTEXTS_T23X - 1U;
|
||||||
pva->hw_consts.n_dma_descriptors = PVA_NUM_DMA_DESC_T23X;
|
pva->hw_consts.n_dma_descriptors = PVA_NUM_DMA_DESC_T23X;
|
||||||
pva->hw_consts.n_user_dma_channels = PVA_DMA_NUM_CHANNELS_T23X - 1U;
|
pva->hw_consts.n_user_dma_channels = PVA_DMA_NUM_CHANNELS_T23X - 1U;
|
||||||
pva->hw_consts.n_hwseq_words = PVA_NUM_HWSEQ_WORDS_T23X;
|
pva->hw_consts.n_hwseq_words = PVA_NUM_HWSEQ_WORDS_T23X;
|
||||||
@@ -29,8 +30,10 @@ void pva_kmd_device_init_t23x(struct pva_kmd_device *pva)
|
|||||||
PVA_KMD_PVA0_T23x_REG_BASE;
|
PVA_KMD_PVA0_T23x_REG_BASE;
|
||||||
pva->reg_size[PVA_KMD_APERTURE_PVA_CLUSTER] =
|
pva->reg_size[PVA_KMD_APERTURE_PVA_CLUSTER] =
|
||||||
PVA_KMD_PVA0_T23x_REG_SIZE;
|
PVA_KMD_PVA0_T23x_REG_SIZE;
|
||||||
pva->reg_phy_base[PVA_KMD_APERTURE_VPU_DEBUG] = TEGRA_PVA0_VPU_DBG_BASE;
|
pva->reg_phy_base[PVA_KMD_APERTURE_VPU_DEBUG] =
|
||||||
pva->reg_size[PVA_KMD_APERTURE_VPU_DEBUG] = TEGRA_PVA0_VPU_DBG_SIZE;
|
TEGRA_PVA0_VPU_DBG_BASE_T23X;
|
||||||
|
pva->reg_size[PVA_KMD_APERTURE_VPU_DEBUG] =
|
||||||
|
TEGRA_PVA0_VPU_DBG_SIZE_T23X;
|
||||||
|
|
||||||
pva->regspec.sec_lic_intr_enable = 0x28064;
|
pva->regspec.sec_lic_intr_enable = 0x28064;
|
||||||
pva->regspec.sec_lic_intr_status = 0x2806C;
|
pva->regspec.sec_lic_intr_status = 0x2806C;
|
||||||
@@ -80,4 +83,11 @@ void pva_kmd_device_init_t23x(struct pva_kmd_device *pva)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pva->tsc_to_ns_multiplier = PVA_NS_PER_TSC_TICK_T23X;
|
pva->tsc_to_ns_multiplier = PVA_NS_PER_TSC_TICK_T23X;
|
||||||
|
|
||||||
|
pva->pfsd_info.vpu_elf_data = pva_pfsd_vpu_elf_t23x;
|
||||||
|
pva->pfsd_info.vpu_elf_size = PVA_ALIGN8(PVA_PFSD_VPU_ELF_SIZE_T23X);
|
||||||
|
pva->pfsd_info.ppe_elf_data = NULL;
|
||||||
|
pva->pfsd_info.ppe_elf_size = 0;
|
||||||
|
pva->pfsd_info.pfsd_dma_cfg = pfsd_dma_cfg_t23x;
|
||||||
|
pva->pfsd_info.register_cmd_buffer = &pva_kmd_pfsd_t23x_register_cmdbuf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,27 +5,106 @@
|
|||||||
#define PVA_KMD_T23X_H
|
#define PVA_KMD_T23X_H
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
/** Number of VMEM regions */
|
/**
|
||||||
|
* @brief Number of VMEM regions available in T23X platform
|
||||||
|
*
|
||||||
|
* @details Defines the total number of Vector Memory (VMEM) regions available
|
||||||
|
* in the T23X Tegra platform. VMEM regions are fast on-chip memory banks used
|
||||||
|
* by VPU for data processing operations.
|
||||||
|
*/
|
||||||
#define PVA_VMEM_REGION_COUNT_T23X 3U
|
#define PVA_VMEM_REGION_COUNT_T23X 3U
|
||||||
|
|
||||||
/** Start Address of VMEM0 Bank in T23X */
|
/**
|
||||||
|
* @brief Start address of VMEM0 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the first Vector Memory bank (VMEM0) in T23X Tegra
|
||||||
|
* platform. This region provides fast access memory for VPU operations.
|
||||||
|
* Value: 0x40 (64 bytes offset)
|
||||||
|
*/
|
||||||
#define T23x_VMEM0_START 0x40U
|
#define T23x_VMEM0_START 0x40U
|
||||||
/** End Address of VMEM0 Bank in T23X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM0 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the first Vector Memory bank (VMEM0) in
|
||||||
|
* T23X Tegra platform. The usable range is from T23x_VMEM0_START to
|
||||||
|
* (T23x_VMEM0_END - 1).
|
||||||
|
* Value: 0x20000 (128KB)
|
||||||
|
*/
|
||||||
#define T23x_VMEM0_END 0x20000U
|
#define T23x_VMEM0_END 0x20000U
|
||||||
/** Start Address of VMEM1 Bank in T23X */
|
|
||||||
|
/**
|
||||||
|
* @brief Start address of VMEM1 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the second Vector Memory bank (VMEM1) in T23X Tegra
|
||||||
|
* platform. This region provides additional fast access memory for VPU
|
||||||
|
* operations.
|
||||||
|
* Value: 0x40000 (256KB offset)
|
||||||
|
*/
|
||||||
#define T23x_VMEM1_START 0x40000U
|
#define T23x_VMEM1_START 0x40000U
|
||||||
/** End Address of VMEM1 Bank in T23X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM1 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the second Vector Memory bank (VMEM1) in
|
||||||
|
* T23X Tegra platform. The usable range is from T23x_VMEM1_START to
|
||||||
|
* (T23x_VMEM1_END - 1).
|
||||||
|
* Value: 0x60000 (384KB)
|
||||||
|
*/
|
||||||
#define T23x_VMEM1_END 0x60000U
|
#define T23x_VMEM1_END 0x60000U
|
||||||
/** Start Address of VMEM2 Bank in T23X */
|
|
||||||
|
/**
|
||||||
|
* @brief Start address of VMEM2 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the third Vector Memory bank (VMEM2) in T23X Tegra
|
||||||
|
* platform. This region provides additional fast access memory for VPU
|
||||||
|
* operations.
|
||||||
|
* Value: 0x80000 (512KB offset)
|
||||||
|
*/
|
||||||
#define T23x_VMEM2_START 0x80000U
|
#define T23x_VMEM2_START 0x80000U
|
||||||
/** End Address of VMEM2 Bank in T23X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM2 bank in T23X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the third Vector Memory bank (VMEM2) in
|
||||||
|
* T23X Tegra platform. The usable range is from T23x_VMEM2_START to
|
||||||
|
* (T23x_VMEM2_END - 1).
|
||||||
|
* Value: 0xA0000 (640KB)
|
||||||
|
*/
|
||||||
#define T23x_VMEM2_END 0xA0000U
|
#define T23x_VMEM2_END 0xA0000U
|
||||||
|
|
||||||
/** @brief Base address for PVA0 VPU Debug Register space (CSITE_PVA0VPU) */
|
/**
|
||||||
#define TEGRA_PVA0_VPU_DBG_BASE 0x24740000U
|
* @brief Base address for PVA0 VPU Debug Register space (CSITE_PVA0VPU)
|
||||||
/** @brief Size (in bytes) of the PVA0 VPU Debug Register space (CSITE_PVA0VPU) */
|
*
|
||||||
#define TEGRA_PVA0_VPU_DBG_SIZE 0x40000U
|
* @details Physical base address of the PVA0 VPU debug register space in T23X
|
||||||
|
* platform. This address space provides access to VPU debug and monitoring
|
||||||
|
* registers through the CoreSight interface.
|
||||||
|
* Value: 0x24740000
|
||||||
|
*/
|
||||||
|
#define TEGRA_PVA0_VPU_DBG_BASE_T23X 0x24740000U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size (in bytes) of the PVA0 VPU Debug Register space (CSITE_PVA0VPU)
|
||||||
|
*
|
||||||
|
* @details Size of the PVA0 VPU debug register space in T23X platform. This
|
||||||
|
* defines the extent of the debug register address space accessible through
|
||||||
|
* the CoreSight interface.
|
||||||
|
* Value: 0x40000 (256KB)
|
||||||
|
*/
|
||||||
|
#define TEGRA_PVA0_VPU_DBG_SIZE_T23X 0x40000U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize PVA device for T23X platform
|
||||||
|
*
|
||||||
|
* @details This function performs T23X-specific initialization of the PVA
|
||||||
|
* device. It configures platform-specific parameters, sets up memory regions,
|
||||||
|
* initializes hardware-specific features, and prepares the device for operation
|
||||||
|
* on the T23X Tegra platform. This includes setting up VMEM regions, debug
|
||||||
|
* interfaces, and other platform-specific configurations.
|
||||||
|
*
|
||||||
|
* @param[in,out] pva Pointer to @ref pva_kmd_device structure to initialize
|
||||||
|
* Valid value: non-null, must be pre-allocated
|
||||||
|
*/
|
||||||
void pva_kmd_device_init_t23x(struct pva_kmd_device *pva);
|
void pva_kmd_device_init_t23x(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
#endif // PVA_KMD_T23X_H
|
#endif // PVA_KMD_T23X_H
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
#include "pva_kmd_t26x.h"
|
#include "pva_kmd_t26x.h"
|
||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
|
#include "pva_kmd_pfsd.h"
|
||||||
|
|
||||||
struct vmem_region vmem_regions_tab_t26x[PVA_VMEM_REGION_COUNT_T26X] = {
|
struct vmem_region vmem_regions_tab_t26x[PVA_VMEM_REGION_COUNT_T26X] = {
|
||||||
{ .start = T26x_VMEM0_START, .end = T26x_VMEM0_END },
|
{ .start = T26x_VMEM0_START, .end = T26x_VMEM0_END },
|
||||||
@@ -17,7 +18,7 @@ void pva_kmd_device_init_t26x(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
pva->hw_consts.hw_gen = PVA_HW_GEN3;
|
pva->hw_consts.hw_gen = PVA_HW_GEN3;
|
||||||
pva->hw_consts.n_smmu_contexts = PVA_NUM_SMMU_CONTEXTS_T26X;
|
pva->hw_consts.n_smmu_contexts = PVA_NUM_SMMU_CONTEXTS_T26X;
|
||||||
pva->r5_image_smmu_context_id = PVA_NUM_SMMU_CONTEXTS_T26X - 1;
|
pva->r5_image_smmu_context_id = PVA_NUM_SMMU_CONTEXTS_T26X - 1U;
|
||||||
pva->hw_consts.n_dma_descriptors = PVA_NUM_DMA_DESC_T26X;
|
pva->hw_consts.n_dma_descriptors = PVA_NUM_DMA_DESC_T26X;
|
||||||
pva->hw_consts.n_user_dma_channels = PVA_DMA_NUM_CHANNELS_T26X - 1U;
|
pva->hw_consts.n_user_dma_channels = PVA_DMA_NUM_CHANNELS_T26X - 1U;
|
||||||
pva->hw_consts.n_hwseq_words = PVA_NUM_HWSEQ_WORDS_T26X;
|
pva->hw_consts.n_hwseq_words = PVA_NUM_HWSEQ_WORDS_T26X;
|
||||||
@@ -30,8 +31,10 @@ void pva_kmd_device_init_t26x(struct pva_kmd_device *pva)
|
|||||||
PVA_KMD_PVA0_T26x_REG_BASE;
|
PVA_KMD_PVA0_T26x_REG_BASE;
|
||||||
pva->reg_size[PVA_KMD_APERTURE_PVA_CLUSTER] =
|
pva->reg_size[PVA_KMD_APERTURE_PVA_CLUSTER] =
|
||||||
PVA_KMD_PVA0_T26x_REG_SIZE;
|
PVA_KMD_PVA0_T26x_REG_SIZE;
|
||||||
pva->reg_phy_base[PVA_KMD_APERTURE_VPU_DEBUG] = TEGRA_PVA0_VPU_DBG_BASE;
|
pva->reg_phy_base[PVA_KMD_APERTURE_VPU_DEBUG] =
|
||||||
pva->reg_size[PVA_KMD_APERTURE_VPU_DEBUG] = TEGRA_PVA0_VPU_DBG_SIZE;
|
TEGRA_PVA0_VPU_DBG_BASE_T26X;
|
||||||
|
pva->reg_size[PVA_KMD_APERTURE_VPU_DEBUG] =
|
||||||
|
TEGRA_PVA0_VPU_DBG_SIZE_T26X;
|
||||||
|
|
||||||
pva->regspec.sec_lic_intr_enable = 0x28064;
|
pva->regspec.sec_lic_intr_enable = 0x28064;
|
||||||
pva->regspec.sec_lic_intr_status = 0x2806C;
|
pva->regspec.sec_lic_intr_status = 0x2806C;
|
||||||
@@ -75,4 +78,11 @@ void pva_kmd_device_init_t26x(struct pva_kmd_device *pva)
|
|||||||
}
|
}
|
||||||
pva->bl_sector_pack_format = PVA_BL_TEGRA_RAW;
|
pva->bl_sector_pack_format = PVA_BL_TEGRA_RAW;
|
||||||
pva->tsc_to_ns_multiplier = PVA_NS_PER_TSC_TICK_T26X;
|
pva->tsc_to_ns_multiplier = PVA_NS_PER_TSC_TICK_T26X;
|
||||||
|
|
||||||
|
pva->pfsd_info.vpu_elf_data = pva_pfsd_vpu_elf_t26x;
|
||||||
|
pva->pfsd_info.vpu_elf_size = PVA_ALIGN8(PVA_PFSD_VPU_ELF_SIZE_T26X);
|
||||||
|
pva->pfsd_info.ppe_elf_data = pva_pfsd_ppe_elf_t26x;
|
||||||
|
pva->pfsd_info.ppe_elf_size = PVA_ALIGN8(PVA_PFSD_PPE_ELF_SIZE_T26X);
|
||||||
|
pva->pfsd_info.pfsd_dma_cfg = pfsd_dma_cfg_t26x;
|
||||||
|
pva->pfsd_info.register_cmd_buffer = &pva_kmd_pfsd_t26x_register_cmdbuf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,34 +5,147 @@
|
|||||||
#define PVA_KMD_T26X_H
|
#define PVA_KMD_T26X_H
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PVA0 register base address for T26X platform
|
||||||
|
*
|
||||||
|
* @details Physical base address of the PVA0 register space in T26X Tegra
|
||||||
|
* platform. This address space provides access to all PVA0 control and
|
||||||
|
* status registers for device configuration and operation.
|
||||||
|
* Value: 0x818c000000
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_T26x_REG_BASE 0x818c000000
|
#define PVA_KMD_PVA0_T26x_REG_BASE 0x818c000000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PVA0 register space size for T26X platform
|
||||||
|
*
|
||||||
|
* @details Size of the PVA0 register address space in T26X Tegra platform.
|
||||||
|
* This defines the extent of the register space accessible for PVA0 device
|
||||||
|
* configuration and control operations.
|
||||||
|
* Value: 0x900000 (9MB)
|
||||||
|
*/
|
||||||
#define PVA_KMD_PVA0_T26x_REG_SIZE 0x900000
|
#define PVA_KMD_PVA0_T26x_REG_SIZE 0x900000
|
||||||
|
|
||||||
/** Number of VMEM regions in T26X */
|
/**
|
||||||
|
* @brief Number of VMEM regions available in T26X platform
|
||||||
|
*
|
||||||
|
* @details Defines the total number of Vector Memory (VMEM) regions available
|
||||||
|
* in the T26X Tegra platform. VMEM regions are fast on-chip memory banks used
|
||||||
|
* by VPU for data processing operations. T26X has one additional VMEM region
|
||||||
|
* compared to T23X.
|
||||||
|
*/
|
||||||
#define PVA_VMEM_REGION_COUNT_T26X 4U
|
#define PVA_VMEM_REGION_COUNT_T26X 4U
|
||||||
|
|
||||||
/** Start Address of VMEM0 Bank in T26X */
|
/**
|
||||||
|
* @brief Start address of VMEM0 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the first Vector Memory bank (VMEM0) in T26X Tegra
|
||||||
|
* platform. This region provides fast access memory for VPU operations.
|
||||||
|
* Value: 0x40 (64 bytes offset)
|
||||||
|
*/
|
||||||
#define T26x_VMEM0_START 0x40U
|
#define T26x_VMEM0_START 0x40U
|
||||||
/** End Address of VMEM0 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM0 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the first Vector Memory bank (VMEM0) in
|
||||||
|
* T26X Tegra platform. The usable range is from T26x_VMEM0_START to
|
||||||
|
* (T26x_VMEM0_END - 1).
|
||||||
|
* Value: 0x20000 (128KB)
|
||||||
|
*/
|
||||||
#define T26x_VMEM0_END 0x20000U
|
#define T26x_VMEM0_END 0x20000U
|
||||||
/** Start Address of VMEM1 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief Start address of VMEM1 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the second Vector Memory bank (VMEM1) in T26X Tegra
|
||||||
|
* platform. This region provides additional fast access memory for VPU
|
||||||
|
* operations.
|
||||||
|
* Value: 0x40000 (256KB offset)
|
||||||
|
*/
|
||||||
#define T26x_VMEM1_START 0x40000U
|
#define T26x_VMEM1_START 0x40000U
|
||||||
/** End Address of VMEM1 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM1 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the second Vector Memory bank (VMEM1) in
|
||||||
|
* T26X Tegra platform. The usable range is from T26x_VMEM1_START to
|
||||||
|
* (T26x_VMEM1_END - 1).
|
||||||
|
* Value: 0x60000 (384KB)
|
||||||
|
*/
|
||||||
#define T26x_VMEM1_END 0x60000U
|
#define T26x_VMEM1_END 0x60000U
|
||||||
/** End Address of VMEM2 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief Start address of VMEM2 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the third Vector Memory bank (VMEM2) in T26X Tegra
|
||||||
|
* platform. This region provides additional fast access memory for VPU
|
||||||
|
* operations.
|
||||||
|
* Value: 0x80000 (512KB offset)
|
||||||
|
*/
|
||||||
#define T26x_VMEM2_START 0x80000U
|
#define T26x_VMEM2_START 0x80000U
|
||||||
/** End Address of VMEM2 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM2 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the third Vector Memory bank (VMEM2) in
|
||||||
|
* T26X Tegra platform. The usable range is from T26x_VMEM2_START to
|
||||||
|
* (T26x_VMEM2_END - 1).
|
||||||
|
* Value: 0xA0000 (640KB)
|
||||||
|
*/
|
||||||
#define T26x_VMEM2_END 0xA0000U
|
#define T26x_VMEM2_END 0xA0000U
|
||||||
/** End Address of VMEM3 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief Start address of VMEM3 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details Base address of the fourth Vector Memory bank (VMEM3) in T26X Tegra
|
||||||
|
* platform. This additional VMEM region (not available in T23X) provides
|
||||||
|
* extra fast access memory for VPU operations.
|
||||||
|
* Value: 0xC0000 (768KB offset)
|
||||||
|
*/
|
||||||
#define T26x_VMEM3_START 0xC0000U
|
#define T26x_VMEM3_START 0xC0000U
|
||||||
/** End Address of VMEM3 Bank in T26X */
|
|
||||||
|
/**
|
||||||
|
* @brief End address of VMEM3 bank in T26X platform
|
||||||
|
*
|
||||||
|
* @details End address (exclusive) of the fourth Vector Memory bank (VMEM3) in
|
||||||
|
* T26X Tegra platform. The usable range is from T26x_VMEM3_START to
|
||||||
|
* (T26x_VMEM3_END - 1).
|
||||||
|
* Value: 0xE0000 (896KB)
|
||||||
|
*/
|
||||||
#define T26x_VMEM3_END 0xE0000U
|
#define T26x_VMEM3_END 0xE0000U
|
||||||
|
|
||||||
/** @brief Base address for PVA0 VPU Debug Register space (CSITE_PVA0VPU) */
|
/**
|
||||||
#define TEGRA_PVA0_VPU_DBG_BASE 0x24740000U
|
* @brief Base address for PVA0 VPU Debug Register space (CSITE_PVA0VPU)
|
||||||
/** @brief Size (in bytes) of the PVA0 VPU Debug Register space (CSITE_PVA0VPU) */
|
*
|
||||||
#define TEGRA_PVA0_VPU_DBG_SIZE 0x40000U
|
* @details Physical base address of the PVA0 VPU debug register space in T26X
|
||||||
|
* platform. This address space provides access to VPU debug and monitoring
|
||||||
|
* registers through the CoreSight interface.
|
||||||
|
* Value: 0x10740000
|
||||||
|
*/
|
||||||
|
#define TEGRA_PVA0_VPU_DBG_BASE_T26X 0x10740000U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size (in bytes) of the PVA0 VPU Debug Register space (CSITE_PVA0VPU)
|
||||||
|
*
|
||||||
|
* @details Size of the PVA0 VPU debug register space in T26X platform. This
|
||||||
|
* defines the extent of the debug register address space accessible through
|
||||||
|
* the CoreSight interface.
|
||||||
|
* Value: 0x40000 (256KB)
|
||||||
|
*/
|
||||||
|
#define TEGRA_PVA0_VPU_DBG_SIZE_T26X 0x40000U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize PVA device for T26X platform
|
||||||
|
*
|
||||||
|
* @details This function performs T26X-specific initialization of the PVA
|
||||||
|
* device. It configures platform-specific parameters, sets up memory regions,
|
||||||
|
* initializes hardware-specific features, and prepares the device for operation
|
||||||
|
* on the T26X Tegra platform. This includes setting up all four VMEM regions,
|
||||||
|
* debug interfaces, and other platform-specific configurations unique to T26X.
|
||||||
|
*
|
||||||
|
* @param[in,out] pva Pointer to @ref pva_kmd_device structure to initialize
|
||||||
|
* Valid value: non-null, must be pre-allocated
|
||||||
|
*/
|
||||||
void pva_kmd_device_init_t26x(struct pva_kmd_device *pva);
|
void pva_kmd_device_init_t26x(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
#endif // PVA_KMD_T26X_H
|
#endif // PVA_KMD_T26X_H
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "pva_kmd_constants.h"
|
#include "pva_kmd_constants.h"
|
||||||
#include "pva_utils.h"
|
#include "pva_utils.h"
|
||||||
#include "pva_kmd_tegra_stats.h"
|
#include "pva_kmd_tegra_stats.h"
|
||||||
|
#include "pva_kmd_debugfs.h"
|
||||||
|
|
||||||
void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva)
|
void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva)
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,8 @@ void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva)
|
|||||||
|
|
||||||
err = pva_kmd_add_dram_buffer_resource(&pva->dev_resource_table,
|
err = pva_kmd_add_dram_buffer_resource(&pva->dev_resource_table,
|
||||||
pva->tegra_stats_memory,
|
pva->tegra_stats_memory,
|
||||||
&pva->tegra_stats_resource_id);
|
&pva->tegra_stats_resource_id,
|
||||||
|
false);
|
||||||
ASSERT(err == PVA_SUCCESS);
|
ASSERT(err == PVA_SUCCESS);
|
||||||
pva_kmd_update_fw_resource_table(&pva->dev_resource_table);
|
pva_kmd_update_fw_resource_table(&pva->dev_resource_table);
|
||||||
}
|
}
|
||||||
@@ -55,16 +57,26 @@ static uint64_t calc_vpu_utilization(uint64_t total_utilization,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum pva_error
|
static enum pva_error
|
||||||
pva_kmd_notify_fw_get_tegra_stats(struct pva_kmd_device *pva,
|
notify_fw_get_tegra_stats(struct pva_kmd_device *pva,
|
||||||
struct pva_kmd_tegrastats *kmd_tegra_stats)
|
struct pva_kmd_tegrastats *kmd_tegra_stats)
|
||||||
{
|
{
|
||||||
struct pva_cmd_get_tegra_stats cmd = { 0 };
|
struct pva_cmd_get_tegra_stats cmd = { 0 };
|
||||||
uint64_t buffer_offset = 0U;
|
uint64_t buffer_offset = 0U;
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
struct pva_kmd_fw_tegrastats fw_tegra_stats = { 0 };
|
struct pva_kmd_fw_tegrastats fw_tegra_stats = { 0 };
|
||||||
|
bool stats_enabled = pva->debugfs_context.stats_enable;
|
||||||
uint64_t duration = 0U;
|
uint64_t duration = 0U;
|
||||||
|
|
||||||
|
if (stats_enabled == false) {
|
||||||
|
pva_kmd_log_info("Tegra stats are disabled");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pva_kmd_device_maybe_on(pva)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Power on PVA if not already */
|
/* Power on PVA if not already */
|
||||||
err = pva_kmd_device_busy(pva);
|
err = pva_kmd_device_busy(pva);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -75,9 +87,10 @@ pva_kmd_notify_fw_get_tegra_stats(struct pva_kmd_device *pva,
|
|||||||
|
|
||||||
pva_kmd_set_cmd_get_tegra_stats(&cmd, pva->tegra_stats_resource_id,
|
pva_kmd_set_cmd_get_tegra_stats(&cmd, pva->tegra_stats_resource_id,
|
||||||
pva->tegra_stats_buf_size,
|
pva->tegra_stats_buf_size,
|
||||||
buffer_offset, true);
|
buffer_offset, stats_enabled);
|
||||||
|
|
||||||
err = pva_kmd_submit_cmd_sync(&pva->submitter, &cmd, sizeof(cmd),
|
err = pva_kmd_submit_cmd_sync(&pva->submitter, &cmd,
|
||||||
|
(uint32_t)sizeof(cmd),
|
||||||
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
PVA_KMD_WAIT_FW_POLL_INTERVAL_US,
|
||||||
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
PVA_KMD_WAIT_FW_TIMEOUT_US);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
@@ -90,6 +103,7 @@ pva_kmd_notify_fw_get_tegra_stats(struct pva_kmd_device *pva,
|
|||||||
|
|
||||||
pva_kmd_device_idle(pva);
|
pva_kmd_device_idle(pva);
|
||||||
|
|
||||||
|
out:
|
||||||
duration = sat_sub64(fw_tegra_stats.window_end_time,
|
duration = sat_sub64(fw_tegra_stats.window_end_time,
|
||||||
fw_tegra_stats.window_start_time);
|
fw_tegra_stats.window_start_time);
|
||||||
|
|
||||||
@@ -107,3 +121,78 @@ dev_idle:
|
|||||||
err_out:
|
err_out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t print_vpu_stats(struct pva_kmd_tegrastats *kmd_tegra_stats,
|
||||||
|
uint8_t *out_buffer, uint64_t offset,
|
||||||
|
uint64_t len)
|
||||||
|
{
|
||||||
|
char kernel_buffer[256];
|
||||||
|
int64_t formatted_len;
|
||||||
|
|
||||||
|
formatted_len = snprintf(
|
||||||
|
kernel_buffer, sizeof(kernel_buffer),
|
||||||
|
"%llu\n%llu\n%llu\n%llu\n",
|
||||||
|
(long long unsigned int)(kmd_tegra_stats->window_start_time),
|
||||||
|
(long long unsigned int)(kmd_tegra_stats->window_end_time),
|
||||||
|
(long long unsigned int)
|
||||||
|
kmd_tegra_stats->average_vpu_utilization[0],
|
||||||
|
(long long unsigned int)
|
||||||
|
kmd_tegra_stats->average_vpu_utilization[1]);
|
||||||
|
|
||||||
|
if (formatted_len <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatted_len++; //accounting for null terminating character
|
||||||
|
|
||||||
|
if (len < (uint64_t)formatted_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the formatted string from kernel buffer to user buffer
|
||||||
|
return pva_kmd_read_from_buffer_to_user(out_buffer, len, offset,
|
||||||
|
kernel_buffer,
|
||||||
|
(uint64_t)formatted_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t get_vpu_stats(struct pva_kmd_device *dev, void *file_data,
|
||||||
|
uint8_t *out_buffer, uint64_t offset,
|
||||||
|
uint64_t size)
|
||||||
|
{
|
||||||
|
struct pva_kmd_tegrastats kmd_tegra_stats;
|
||||||
|
|
||||||
|
// We don't support partial reads for vpu stats because we cannot mix two
|
||||||
|
// reads at different times together.
|
||||||
|
if (offset != 0U) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
kmd_tegra_stats.window_start_time = 0;
|
||||||
|
kmd_tegra_stats.window_end_time = 0;
|
||||||
|
kmd_tegra_stats.average_vpu_utilization[0] = 0;
|
||||||
|
kmd_tegra_stats.average_vpu_utilization[1] = 0;
|
||||||
|
|
||||||
|
notify_fw_get_tegra_stats(dev, &kmd_tegra_stats);
|
||||||
|
|
||||||
|
return print_vpu_stats(&kmd_tegra_stats, out_buffer, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pva_error pva_kmd_tegrastats_init_debugfs(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
enum pva_error err;
|
||||||
|
|
||||||
|
pva_kmd_debugfs_create_bool(pva, "stats_enabled",
|
||||||
|
&pva->debugfs_context.stats_enable);
|
||||||
|
|
||||||
|
pva->debugfs_context.vpu_fops.read = &get_vpu_stats;
|
||||||
|
pva->debugfs_context.vpu_fops.write = NULL;
|
||||||
|
pva->debugfs_context.vpu_fops.pdev = pva;
|
||||||
|
err = pva_kmd_debugfs_create_file(pva, "vpu_stats",
|
||||||
|
&pva->debugfs_context.vpu_fops);
|
||||||
|
if (err != PVA_SUCCESS) {
|
||||||
|
pva_kmd_log_err("Failed to create vpu_stats debugfs file");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,26 +1,115 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
/* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
#ifndef PVA_KMD_TEGRA_STATS_H
|
#ifndef PVA_KMD_TEGRA_STATS_H
|
||||||
#define PVA_KMD_TEGRA_STATS_H
|
#define PVA_KMD_TEGRA_STATS_H
|
||||||
#include "pva_kmd_device.h"
|
#include "pva_kmd_device.h"
|
||||||
|
|
||||||
|
#if PVA_ENABLE_TEGRASTATS == 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure which holds vpu stats information
|
* @brief Structure containing VPU utilization statistics for Tegra monitoring
|
||||||
|
*
|
||||||
|
* @details This structure holds performance statistics for VPU engines within
|
||||||
|
* the PVA device, providing utilization metrics and timing information for
|
||||||
|
* system monitoring and performance analysis. The statistics are collected
|
||||||
|
* over defined time windows and provide insights into VPU workload distribution
|
||||||
|
* and efficiency.
|
||||||
*/
|
*/
|
||||||
struct pva_kmd_tegrastats {
|
struct pva_kmd_tegrastats {
|
||||||
/** Holds vpu utilization as a percentage for each VPU in the PVA */
|
/**
|
||||||
|
* @brief Array of average VPU utilization percentages for each VPU engine
|
||||||
|
*
|
||||||
|
* @details Holds VPU utilization as a percentage for each VPU in the PVA cluster.
|
||||||
|
* Each entry represents the average utilization of a specific VPU engine
|
||||||
|
* during the measurement window.
|
||||||
|
* Valid range for each element: [0 .. 100] (percentage)
|
||||||
|
*/
|
||||||
uint64_t average_vpu_utilization[PVA_NUM_PVE];
|
uint64_t average_vpu_utilization[PVA_NUM_PVE];
|
||||||
/** Current state of pva_kmd_tegrastats */
|
|
||||||
|
/**
|
||||||
|
* @brief Start timestamp of the current statistics measurement window
|
||||||
|
*
|
||||||
|
* @details Timestamp marking the beginning of the current measurement window
|
||||||
|
* for statistics collection. Used to calculate measurement duration and
|
||||||
|
* normalize utilization metrics.
|
||||||
|
* Valid range: [0 .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t window_start_time;
|
uint64_t window_start_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief End timestamp of the current statistics measurement window
|
||||||
|
*
|
||||||
|
* @details Timestamp marking the end of the current measurement window
|
||||||
|
* for statistics collection. Used in conjunction with window_start_time
|
||||||
|
* to determine the measurement period.
|
||||||
|
* Valid range: [window_start_time .. UINT64_MAX]
|
||||||
|
*/
|
||||||
uint64_t window_end_time;
|
uint64_t window_end_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize Tegra statistics collection for PVA device
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Initializes the Tegra statistics collection infrastructure
|
||||||
|
* - Sets up performance monitoring counters for VPU engines
|
||||||
|
* - Configures timing mechanisms for utilization measurement
|
||||||
|
* - Prepares data structures for statistics accumulation
|
||||||
|
* - Establishes baseline metrics for utilization calculation
|
||||||
|
* - Enables performance monitoring in firmware if needed
|
||||||
|
*
|
||||||
|
* The statistics collection provides valuable information for system
|
||||||
|
* monitoring tools like tegrastats to display PVA utilization metrics.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must be initialized
|
||||||
|
*/
|
||||||
void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva);
|
void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize Tegra statistics collection and clean up resources
|
||||||
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Stops statistics collection and performance monitoring
|
||||||
|
* - Disables performance monitoring counters
|
||||||
|
* - Cleans up statistics data structures and allocated memory
|
||||||
|
* - Frees resources associated with utilization tracking
|
||||||
|
* - Ensures proper cleanup of monitoring infrastructure
|
||||||
|
* - Resets statistics state for the device
|
||||||
|
*
|
||||||
|
* This function should be called during device shutdown to ensure
|
||||||
|
* proper cleanup of all statistics-related resources.
|
||||||
|
*
|
||||||
|
* @param[in] pva Pointer to @ref pva_kmd_device structure
|
||||||
|
* Valid value: non-null, must have been initialized with stats
|
||||||
|
*/
|
||||||
void pva_kmd_device_deinit_tegra_stats(struct pva_kmd_device *pva);
|
void pva_kmd_device_deinit_tegra_stats(struct pva_kmd_device *pva);
|
||||||
|
|
||||||
enum pva_error
|
/* Initialize Tegrastats debugfs nodes */
|
||||||
pva_kmd_notify_fw_get_tegra_stats(struct pva_kmd_device *pva,
|
enum pva_error pva_kmd_tegrastats_init_debugfs(struct pva_kmd_device *pva);
|
||||||
struct pva_kmd_tegrastats *kmd_tegra_stats);
|
|
||||||
|
#else /* PVA_ENABLE_TEGRASTATS */
|
||||||
|
|
||||||
|
/* Dummy inline functions when Tegrastats is disabled */
|
||||||
|
static inline void pva_kmd_device_init_tegra_stats(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pva_kmd_device_deinit_tegra_stats(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dummy initialization function when Tegrastats is disabled */
|
||||||
|
static inline enum pva_error
|
||||||
|
pva_kmd_tegrastats_init_debugfs(struct pva_kmd_device *pva)
|
||||||
|
{
|
||||||
|
(void)pva;
|
||||||
|
return PVA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PVA_ENABLE_TEGRASTATS */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ void *pva_kmd_zalloc(uint64_t size)
|
|||||||
|
|
||||||
void pva_kmd_free(void *ptr)
|
void pva_kmd_free(void *ptr)
|
||||||
{
|
{
|
||||||
|
if (ptr != NULL) {
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_fault(void)
|
void pva_kmd_fault(void)
|
||||||
@@ -71,8 +73,12 @@ enum pva_error pva_kmd_sema_wait_timeout(pva_kmd_sema_t *sem,
|
|||||||
ASSERT(ret == 0);
|
ASSERT(ret == 0);
|
||||||
|
|
||||||
/* Add timeout (specified in milliseconds) to the current time */
|
/* Add timeout (specified in milliseconds) to the current time */
|
||||||
ts.tv_sec += timeout_ms / 1000;
|
{
|
||||||
ts.tv_nsec += (timeout_ms % 1000) * 1000000;
|
uint32_t sec_part = timeout_ms / 1000U;
|
||||||
|
uint32_t nsec_part = (timeout_ms % 1000U) * 1000000U;
|
||||||
|
ts.tv_sec += (time_t)sec_part;
|
||||||
|
ts.tv_nsec += (long)nsec_part;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle case where nanoseconds exceed 1 second */
|
/* Handle case where nanoseconds exceed 1 second */
|
||||||
if (ts.tv_nsec >= 1000000000) {
|
if (ts.tv_nsec >= 1000000000) {
|
||||||
@@ -82,11 +88,12 @@ enum pva_error pva_kmd_sema_wait_timeout(pva_kmd_sema_t *sem,
|
|||||||
|
|
||||||
wait_again:
|
wait_again:
|
||||||
ret = sem_timedwait(sem, &ts);
|
ret = sem_timedwait(sem, &ts);
|
||||||
if (ret != 0) {
|
if (ret == -1) {
|
||||||
if (errno == ETIMEDOUT) {
|
int saved_errno = errno;
|
||||||
|
if (saved_errno == ETIMEDOUT) {
|
||||||
pva_kmd_log_err("pva_kmd_sema_wait_timeout Timed out");
|
pva_kmd_log_err("pva_kmd_sema_wait_timeout Timed out");
|
||||||
return PVA_TIMEDOUT;
|
return PVA_TIMEDOUT;
|
||||||
} else if (errno == EINTR) {
|
} else if (saved_errno == EINTR) {
|
||||||
goto wait_again;
|
goto wait_again;
|
||||||
} else {
|
} else {
|
||||||
FAULT("Unexpected sem_timedwait error");
|
FAULT("Unexpected sem_timedwait error");
|
||||||
@@ -111,7 +118,7 @@ void pva_kmd_sema_post(pva_kmd_sema_t *sem)
|
|||||||
struct pva_kmd_device_memory *
|
struct pva_kmd_device_memory *
|
||||||
pva_kmd_device_memory_alloc_map(uint64_t size, struct pva_kmd_device *pva,
|
pva_kmd_device_memory_alloc_map(uint64_t size, struct pva_kmd_device *pva,
|
||||||
uint32_t iova_access_flags,
|
uint32_t iova_access_flags,
|
||||||
uint32_t smmu_ctx_idx)
|
uint8_t smmu_ctx_idx)
|
||||||
{
|
{
|
||||||
struct pva_kmd_device_memory *mem;
|
struct pva_kmd_device_memory *mem;
|
||||||
enum pva_error err;
|
enum pva_error err;
|
||||||
@@ -142,24 +149,30 @@ err_out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_atomic_store(pva_kmd_atomic_t *atomic_val, int val)
|
void pva_kmd_atomic_store(pva_kmd_atomic_t *a_var, int val)
|
||||||
{
|
{
|
||||||
atomic_store(atomic_val, val);
|
atomic_store(a_var, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pva_kmd_atomic_fetch_add(pva_kmd_atomic_t *atomic_val, int val)
|
int pva_kmd_atomic_fetch_add(pva_kmd_atomic_t *a_var, int val)
|
||||||
{
|
{
|
||||||
return atomic_fetch_add(atomic_val, val);
|
/* MISRA Deviation: Atomic to non-atomic conversion is required for return value */
|
||||||
|
int result = (int)atomic_fetch_add(a_var, val);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pva_kmd_atomic_fetch_sub(pva_kmd_atomic_t *atomic_val, int val)
|
int pva_kmd_atomic_fetch_sub(pva_kmd_atomic_t *a_var, int val)
|
||||||
{
|
{
|
||||||
return atomic_fetch_sub(atomic_val, val);
|
/* MISRA Deviation: Atomic to non-atomic conversion is required for return value */
|
||||||
|
int result = (int)atomic_fetch_sub(a_var, val);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pva_kmd_atomic_load(pva_kmd_atomic_t *atomic_val)
|
int pva_kmd_atomic_load(pva_kmd_atomic_t *a_var)
|
||||||
{
|
{
|
||||||
return atomic_load(atomic_val);
|
/* MISRA Deviation: Atomic to non-atomic conversion is required for return value */
|
||||||
|
int result = (int)atomic_load(a_var);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pva_kmd_device_maybe_on(struct pva_kmd_device *pva)
|
bool pva_kmd_device_maybe_on(struct pva_kmd_device *pva)
|
||||||
@@ -167,7 +180,7 @@ bool pva_kmd_device_maybe_on(struct pva_kmd_device *pva)
|
|||||||
bool device_on = false;
|
bool device_on = false;
|
||||||
|
|
||||||
pva_kmd_mutex_lock(&pva->powercycle_lock);
|
pva_kmd_mutex_lock(&pva->powercycle_lock);
|
||||||
if (pva->refcount > 0) {
|
if (pva->refcount > 0U) {
|
||||||
device_on = true;
|
device_on = true;
|
||||||
}
|
}
|
||||||
pva_kmd_mutex_unlock(&pva->powercycle_lock);
|
pva_kmd_mutex_unlock(&pva->powercycle_lock);
|
||||||
|
|||||||
@@ -9,18 +9,3 @@ void *pva_kmd_zalloc_nofail(uint64_t size)
|
|||||||
ASSERT(ptr != NULL);
|
ASSERT(ptr != NULL);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pva_kmd_log_err(const char *msg)
|
|
||||||
{
|
|
||||||
pva_kmd_print_str(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pva_kmd_log_err_u64(const char *msg, uint64_t val)
|
|
||||||
{
|
|
||||||
pva_kmd_print_str_u64(msg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pva_kmd_log_err_hex32(const char *msg, uint32_t val)
|
|
||||||
{
|
|
||||||
pva_kmd_print_str_hex32(msg, val);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,11 +11,38 @@
|
|||||||
#include "pva_plat_faults.h"
|
#include "pva_plat_faults.h"
|
||||||
#include "pva_math_utils.h"
|
#include "pva_math_utils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of a 4KB memory page in bytes
|
||||||
|
*
|
||||||
|
* @details This macro defines the standard 4KB page size commonly used in
|
||||||
|
* memory management and allocation operations. It is calculated as 4 * 1024
|
||||||
|
* bytes and is used for memory alignment and size calculations.
|
||||||
|
*/
|
||||||
#define SIZE_4KB (4 * 1024)
|
#define SIZE_4KB (4 * 1024)
|
||||||
|
|
||||||
void pva_kmd_log_err(const char *msg);
|
/**
|
||||||
void pva_kmd_log_err_u64(const char *msg, uint64_t val);
|
* @brief Allocate zero-initialized memory that cannot fail
|
||||||
void pva_kmd_log_err_hex32(const char *msg, uint32_t val);
|
*
|
||||||
|
* @details This function performs the following operations:
|
||||||
|
* - Allocates memory of the specified size for KMD internal use
|
||||||
|
* - Initializes all allocated memory to zero
|
||||||
|
* - Uses platform-appropriate memory allocation mechanisms
|
||||||
|
* - Guarantees that the allocation will not fail - if memory cannot be
|
||||||
|
* allocated, the system will halt or take appropriate recovery action
|
||||||
|
* - Returns a pointer to the allocated and zero-initialized memory region
|
||||||
|
* - Ensures memory is properly aligned for the target platform
|
||||||
|
*
|
||||||
|
* This function is designed for critical memory allocations where failure
|
||||||
|
* is not acceptable. The allocated memory must be freed using the appropriate
|
||||||
|
* platform-specific deallocation function to prevent memory leaks. The
|
||||||
|
* "nofail" designation means the function will either succeed or take
|
||||||
|
* system-level action to handle the out-of-memory condition.
|
||||||
|
*
|
||||||
|
* @param[in] size Size of memory to allocate in bytes
|
||||||
|
* Valid range: [1 .. UINT64_MAX]
|
||||||
|
*
|
||||||
|
* @retval non-null Pointer to allocated and zero-initialized memory
|
||||||
|
*/
|
||||||
void *pva_kmd_zalloc_nofail(uint64_t size);
|
void *pva_kmd_zalloc_nofail(uint64_t size);
|
||||||
|
|
||||||
#endif // PVA_KMD_UTILS_H
|
#endif // PVA_KMD_UTILS_H
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ enum pva_error pva_kmd_init_vpu_app_auth(struct pva_kmd_device *pva, bool ena)
|
|||||||
err = pva_kmd_mutex_init(&pva_auth->allow_list_lock);
|
err = pva_kmd_mutex_init(&pva_auth->allow_list_lock);
|
||||||
if (err != PVA_SUCCESS) {
|
if (err != PVA_SUCCESS) {
|
||||||
pva_kmd_log_err("Failed to initialize allow list lock");
|
pva_kmd_log_err("Failed to initialize allow list lock");
|
||||||
goto free;
|
goto cleanup_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
default_path_len = strnlen(default_path, ALLOWLIST_FILE_LEN);
|
default_path_len = strnlen(default_path, ALLOWLIST_FILE_LEN);
|
||||||
@@ -45,7 +45,7 @@ enum pva_error pva_kmd_init_vpu_app_auth(struct pva_kmd_device *pva, bool ena)
|
|||||||
|
|
||||||
return PVA_SUCCESS;
|
return PVA_SUCCESS;
|
||||||
|
|
||||||
free:
|
cleanup_free:
|
||||||
pva_kmd_free(pva_auth);
|
pva_kmd_free(pva_auth);
|
||||||
error:
|
error:
|
||||||
pva->pva_auth = NULL;
|
pva->pva_auth = NULL;
|
||||||
@@ -62,7 +62,7 @@ error:
|
|||||||
* \ref PVA_SUCCESS Success. Passed in key matched wth calculated key.
|
* \ref PVA_SUCCESS Success. Passed in key matched wth calculated key.
|
||||||
* \ref -EACCES. Passed in Key doesn't match with calcualted key.
|
* \ref -EACCES. Passed in Key doesn't match with calcualted key.
|
||||||
*/
|
*/
|
||||||
static enum pva_error is_key_match(uint8_t *dataptr, size_t size,
|
static enum pva_error is_key_match(const uint8_t *dataptr, size_t size,
|
||||||
struct shakey key)
|
struct shakey key)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
@@ -108,8 +108,8 @@ static enum pva_error is_key_match(uint8_t *dataptr, size_t size,
|
|||||||
* - -EACCES if no match found.
|
* - -EACCES if no match found.
|
||||||
*/
|
*/
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
check_all_keys_for_match(struct shakey *pallkeys, uint8_t *dataptr, size_t size,
|
check_all_keys_for_match(struct shakey *pallkeys, const uint8_t *dataptr,
|
||||||
const struct vpu_hash_vector *match_hash)
|
size_t size, const struct vpu_hash_vector *match_hash)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
@@ -172,7 +172,7 @@ static int32_t compare_hash_value(const struct vpu_hash_vector *pkey,
|
|||||||
* @param[in] len length (in bytes) of data at @ref buf.
|
* @param[in] len length (in bytes) of data at @ref buf.
|
||||||
* @retval value of calculated crc32.
|
* @retval value of calculated crc32.
|
||||||
*/
|
*/
|
||||||
static uint32_t pva_crc32(uint32_t crc, uint8_t *buf, size_t len)
|
static uint32_t pva_crc32(uint32_t crc, const uint8_t *buf, size_t len)
|
||||||
{
|
{
|
||||||
int32_t k;
|
int32_t k;
|
||||||
size_t count;
|
size_t count;
|
||||||
@@ -233,7 +233,7 @@ binary_search(const struct vpu_hash_vector *key,
|
|||||||
|
|
||||||
static enum pva_error
|
static enum pva_error
|
||||||
pva_kmd_vpu_check_sha256_key(struct vpu_hash_key_pair *vpu_hash_keys,
|
pva_kmd_vpu_check_sha256_key(struct vpu_hash_key_pair *vpu_hash_keys,
|
||||||
uint8_t *dataptr, size_t size)
|
const uint8_t *dataptr, size_t size)
|
||||||
{
|
{
|
||||||
enum pva_error err = PVA_SUCCESS;
|
enum pva_error err = PVA_SUCCESS;
|
||||||
struct vpu_hash_vector cal_Hash;
|
struct vpu_hash_vector cal_Hash;
|
||||||
@@ -287,8 +287,7 @@ enum pva_error pva_kmd_verify_exectuable_hash(struct pva_kmd_device *pva,
|
|||||||
|
|
||||||
if (err == PVA_SUCCESS) {
|
if (err == PVA_SUCCESS) {
|
||||||
err = pva_kmd_vpu_check_sha256_key(
|
err = pva_kmd_vpu_check_sha256_key(
|
||||||
pva_auth->vpu_hash_keys, (uint8_t *)dataptr,
|
pva_auth->vpu_hash_keys, dataptr, size);
|
||||||
size);
|
|
||||||
if (err == PVA_SUCCESS) {
|
if (err == PVA_SUCCESS) {
|
||||||
pva_dbg_printf(
|
pva_dbg_printf(
|
||||||
"App authentication successfull\n");
|
"App authentication successfull\n");
|
||||||
@@ -382,12 +381,14 @@ void pva_kmd_deinit_vpu_app_auth(struct pva_kmd_device *pva)
|
|||||||
{
|
{
|
||||||
struct pva_vpu_auth *pva_auth;
|
struct pva_vpu_auth *pva_auth;
|
||||||
|
|
||||||
if (pva == NULL)
|
if (pva == NULL) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pva_auth = pva->pva_auth;
|
pva_auth = pva->pva_auth;
|
||||||
if (pva_auth == NULL)
|
if (pva_auth == NULL) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pva_kmd_allowlist_destroy(pva_auth);
|
pva_kmd_allowlist_destroy(pva_auth);
|
||||||
pva_kmd_mutex_deinit(&pva_auth->allow_list_lock);
|
pva_kmd_mutex_deinit(&pva_auth->allow_list_lock);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user