3232
3333#define ADDR_TO_L2_CACHE_CFG (addr ) ((addr) >> 31)
3434
35- #define IVPU_FW_CHECK_API (vdev , fw_hdr , name ) ivpu_fw_check_api(vdev, fw_hdr, #name, \
36- VPU_##name##_API_VER_INDEX, \
37- VPU_##name##_API_VER_MAJOR, \
38- VPU_##name##_API_VER_MINOR)
35+ #define IVPU_FW_CHECK_API (vdev , fw_hdr , name , min_major ) \
36+ ivpu_fw_check_api(vdev, fw_hdr, #name, \
37+ VPU_##name##_API_VER_INDEX, \
38+ VPU_##name##_API_VER_MAJOR, \
39+ VPU_##name##_API_VER_MINOR, min_major)
3940
4041static char * ivpu_firmware ;
4142module_param_named_unsafe (firmware , ivpu_firmware , charp , 0644 );
@@ -63,19 +64,27 @@ static int ivpu_fw_request(struct ivpu_device *vdev)
6364 return ret ;
6465}
6566
66- static void
67+ static int
6768ivpu_fw_check_api (struct ivpu_device * vdev , const struct vpu_firmware_header * fw_hdr ,
68- const char * str , int index , u16 expected_major , u16 expected_minor )
69+ const char * str , int index , u16 expected_major , u16 expected_minor ,
70+ u16 min_major )
6971{
7072 u16 major = (u16 )(fw_hdr -> api_version [index ] >> 16 );
7173 u16 minor = (u16 )(fw_hdr -> api_version [index ]);
7274
75+ if (major < min_major ) {
76+ ivpu_err (vdev , "Incompatible FW %s API version: %d.%d, required %d.0 or later\n" ,
77+ str , major , minor , min_major );
78+ return - EINVAL ;
79+ }
7380 if (major != expected_major ) {
74- ivpu_warn (vdev , "Incompatible FW %s API version: %d.%d (expected %d.%d)\n" ,
81+ ivpu_warn (vdev , "Major FW %s API version different : %d.%d (expected %d.%d)\n" ,
7582 str , major , minor , expected_major , expected_minor );
7683 }
7784 ivpu_dbg (vdev , FW_BOOT , "FW %s API version: %d.%d (expected %d.%d)\n" ,
7885 str , major , minor , expected_major , expected_minor );
86+
87+ return 0 ;
7988}
8089
8190static int ivpu_fw_parse (struct ivpu_device * vdev )
@@ -131,6 +140,14 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
131140 ivpu_err (vdev , "Invalid entry point: 0x%llx\n" , fw_hdr -> entry_point );
132141 return - EINVAL ;
133142 }
143+ ivpu_dbg (vdev , FW_BOOT , "Header version: 0x%x, format 0x%x\n" ,
144+ fw_hdr -> header_version , fw_hdr -> image_format );
145+ ivpu_dbg (vdev , FW_BOOT , "FW version: %s\n" , (char * )fw_hdr + VPU_FW_HEADER_SIZE );
146+
147+ if (IVPU_FW_CHECK_API (vdev , fw_hdr , BOOT , 3 ))
148+ return - EINVAL ;
149+ if (IVPU_FW_CHECK_API (vdev , fw_hdr , JSM , 3 ))
150+ return - EINVAL ;
134151
135152 fw -> runtime_addr = runtime_addr ;
136153 fw -> runtime_size = runtime_size ;
@@ -141,16 +158,10 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
141158 fw -> cold_boot_entry_point = fw_hdr -> entry_point ;
142159 fw -> entry_point = fw -> cold_boot_entry_point ;
143160
144- ivpu_dbg (vdev , FW_BOOT , "Header version: 0x%x, format 0x%x\n" ,
145- fw_hdr -> header_version , fw_hdr -> image_format );
146161 ivpu_dbg (vdev , FW_BOOT , "Size: file %lu image %u runtime %u shavenn %u\n" ,
147162 fw -> file -> size , fw -> image_size , fw -> runtime_size , fw -> shave_nn_size );
148163 ivpu_dbg (vdev , FW_BOOT , "Address: runtime 0x%llx, load 0x%llx, entry point 0x%llx\n" ,
149164 fw -> runtime_addr , image_load_addr , fw -> entry_point );
150- ivpu_dbg (vdev , FW_BOOT , "FW version: %s\n" , (char * )fw_hdr + VPU_FW_HEADER_SIZE );
151-
152- IVPU_FW_CHECK_API (vdev , fw_hdr , BOOT );
153- IVPU_FW_CHECK_API (vdev , fw_hdr , JSM );
154165
155166 return 0 ;
156167}
0 commit comments