1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2017 Linaro Ltd. 5 */ 6 #include <linux/hash.h> 7 #include <linux/list.h> 8 #include <linux/slab.h> 9 #include <linux/soc/qcom/smem.h> 10 #include <media/videobuf2-v4l2.h> 11 12 #include "core.h" 13 #include "hfi.h" 14 #include "hfi_helper.h" 15 #include "hfi_msgs.h" 16 #include "hfi_parser.h" 17 18 #define SMEM_IMG_VER_TBL 469 19 #define VER_STR_SZ 128 20 #define SMEM_IMG_OFFSET_VENUS (14 * 128) 21 22 static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, 23 struct hfi_msg_event_notify_pkt *pkt) 24 { 25 enum hfi_version ver = core->res->hfi_version; 26 struct hfi_event_data event = {0}; 27 int num_properties_changed; 28 struct hfi_framesize *frame_sz; 29 struct hfi_profile_level *profile_level; 30 struct hfi_bit_depth *pixel_depth; 31 struct hfi_pic_struct *pic_struct; 32 struct hfi_colour_space *colour_info; 33 struct hfi_buffer_requirements *bufreq; 34 struct hfi_extradata_input_crop *crop; 35 struct hfi_dpb_counts *dpb_count; 36 u8 *data_ptr; 37 u32 ptype; 38 39 inst->error = HFI_ERR_NONE; 40 41 switch (pkt->event_data1) { 42 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES: 43 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES: 44 break; 45 default: 46 inst->error = HFI_ERR_SESSION_INVALID_PARAMETER; 47 goto done; 48 } 49 50 event.event_type = pkt->event_data1; 51 52 num_properties_changed = pkt->event_data2; 53 if (!num_properties_changed) { 54 inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 55 goto done; 56 } 57 58 data_ptr = (u8 *)&pkt->ext_event_data[0]; 59 do { 60 ptype = *((u32 *)data_ptr); 61 switch (ptype) { 62 case HFI_PROPERTY_PARAM_FRAME_SIZE: 63 data_ptr += sizeof(u32); 64 frame_sz = (struct hfi_framesize *)data_ptr; 65 event.width = frame_sz->width; 66 event.height = frame_sz->height; 67 data_ptr += sizeof(*frame_sz); 68 break; 69 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 70 data_ptr += sizeof(u32); 71 profile_level = (struct hfi_profile_level *)data_ptr; 72 event.profile = profile_level->profile; 73 event.level = profile_level->level; 74 data_ptr += sizeof(*profile_level); 75 break; 76 case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: 77 data_ptr += sizeof(u32); 78 pixel_depth = (struct hfi_bit_depth *)data_ptr; 79 event.bit_depth = pixel_depth->bit_depth; 80 data_ptr += sizeof(*pixel_depth); 81 break; 82 case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: 83 data_ptr += sizeof(u32); 84 pic_struct = (struct hfi_pic_struct *)data_ptr; 85 event.pic_struct = pic_struct->progressive_only; 86 data_ptr += sizeof(*pic_struct); 87 break; 88 case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: 89 data_ptr += sizeof(u32); 90 colour_info = (struct hfi_colour_space *)data_ptr; 91 event.colour_space = colour_info->colour_space; 92 data_ptr += sizeof(*colour_info); 93 break; 94 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 95 data_ptr += sizeof(u32); 96 event.entropy_mode = *(u32 *)data_ptr; 97 data_ptr += sizeof(u32); 98 break; 99 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 100 data_ptr += sizeof(u32); 101 bufreq = (struct hfi_buffer_requirements *)data_ptr; 102 event.buf_count = hfi_bufreq_get_count_min(bufreq, ver); 103 data_ptr += sizeof(*bufreq); 104 break; 105 case HFI_INDEX_EXTRADATA_INPUT_CROP: 106 data_ptr += sizeof(u32); 107 crop = (struct hfi_extradata_input_crop *)data_ptr; 108 event.input_crop.left = crop->left; 109 event.input_crop.top = crop->top; 110 event.input_crop.width = crop->width; 111 event.input_crop.height = crop->height; 112 data_ptr += sizeof(*crop); 113 break; 114 case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: 115 data_ptr += sizeof(u32); 116 dpb_count = (struct hfi_dpb_counts *)data_ptr; 117 event.buf_count = dpb_count->fw_min_cnt; 118 data_ptr += sizeof(*dpb_count); 119 break; 120 default: 121 break; 122 } 123 num_properties_changed--; 124 } while (num_properties_changed > 0); 125 126 done: 127 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); 128 } 129 130 static void event_release_buffer_ref(struct venus_core *core, 131 struct venus_inst *inst, 132 struct hfi_msg_event_notify_pkt *pkt) 133 { 134 struct hfi_event_data event = {0}; 135 struct hfi_msg_event_release_buffer_ref_pkt *data; 136 137 data = (struct hfi_msg_event_release_buffer_ref_pkt *) 138 pkt->ext_event_data; 139 140 event.event_type = HFI_EVENT_RELEASE_BUFFER_REFERENCE; 141 event.packet_buffer = data->packet_buffer; 142 event.extradata_buffer = data->extradata_buffer; 143 event.tag = data->output_tag; 144 145 inst->error = HFI_ERR_NONE; 146 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); 147 } 148 149 static void event_sys_error(struct venus_core *core, u32 event, 150 struct hfi_msg_event_notify_pkt *pkt) 151 { 152 if (pkt) 153 dev_dbg(core->dev, VDBGH 154 "sys error (session id:%x, data1:%x, data2:%x)\n", 155 pkt->shdr.session_id, pkt->event_data1, 156 pkt->event_data2); 157 158 core->core_ops->event_notify(core, event); 159 } 160 161 static void 162 event_session_error(struct venus_core *core, struct venus_inst *inst, 163 struct hfi_msg_event_notify_pkt *pkt) 164 { 165 struct device *dev = core->dev; 166 167 dev_dbg(dev, VDBGH "session error: event id:%x, session id:%x\n", 168 pkt->event_data1, pkt->shdr.session_id); 169 170 if (!inst) 171 return; 172 173 switch (pkt->event_data1) { 174 /* non fatal session errors */ 175 case HFI_ERR_SESSION_INVALID_SCALE_FACTOR: 176 case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE: 177 case HFI_ERR_SESSION_UNSUPPORTED_SETTING: 178 case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED: 179 inst->error = HFI_ERR_NONE; 180 break; 181 default: 182 dev_err(dev, "session error: event id:%x (%x), session id:%x\n", 183 pkt->event_data1, pkt->event_data2, 184 pkt->shdr.session_id); 185 186 inst->error = pkt->event_data1; 187 inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL); 188 break; 189 } 190 } 191 192 static void hfi_event_notify(struct venus_core *core, struct venus_inst *inst, 193 void *packet) 194 { 195 struct hfi_msg_event_notify_pkt *pkt = packet; 196 197 if (!packet) 198 return; 199 200 switch (pkt->event_id) { 201 case HFI_EVENT_SYS_ERROR: 202 event_sys_error(core, EVT_SYS_ERROR, pkt); 203 break; 204 case HFI_EVENT_SESSION_ERROR: 205 event_session_error(core, inst, pkt); 206 break; 207 case HFI_EVENT_SESSION_SEQUENCE_CHANGED: 208 event_seq_changed(core, inst, pkt); 209 break; 210 case HFI_EVENT_RELEASE_BUFFER_REFERENCE: 211 event_release_buffer_ref(core, inst, pkt); 212 break; 213 case HFI_EVENT_SESSION_PROPERTY_CHANGED: 214 break; 215 default: 216 break; 217 } 218 } 219 220 static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, 221 void *packet) 222 { 223 struct hfi_msg_sys_init_done_pkt *pkt = packet; 224 int rem_bytes; 225 u32 error; 226 227 error = pkt->error_type; 228 if (error != HFI_ERR_NONE) 229 goto done; 230 231 if (!pkt->num_properties) { 232 error = HFI_ERR_SYS_INVALID_PARAMETER; 233 goto done; 234 } 235 236 rem_bytes = pkt->hdr.size - sizeof(*pkt); 237 if (rem_bytes <= 0) { 238 /* missing property data */ 239 error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES; 240 goto done; 241 } 242 243 error = hfi_parser(core, inst, pkt->data, rem_bytes); 244 245 done: 246 core->error = error; 247 complete(&core->done); 248 } 249 250 static void 251 sys_get_prop_image_version(struct venus_core *core, 252 struct hfi_msg_sys_property_info_pkt *pkt) 253 { 254 struct device *dev = core->dev; 255 u8 *smem_tbl_ptr; 256 u8 *img_ver; 257 int req_bytes; 258 size_t smem_blk_sz; 259 int ret; 260 261 req_bytes = pkt->hdr.size - sizeof(*pkt); 262 263 if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1) 264 /* bad packet */ 265 return; 266 267 img_ver = pkt->data; 268 if (!img_ver) 269 return; 270 271 ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u", 272 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); 273 if (ret) 274 goto done; 275 276 ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u", 277 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); 278 if (ret) 279 goto done; 280 281 ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u", 282 &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); 283 if (ret) 284 goto done; 285 286 dev_err(dev, VDBGL "error reading F/W version\n"); 287 return; 288 289 done: 290 dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n", 291 img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev); 292 293 smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, 294 SMEM_IMG_VER_TBL, &smem_blk_sz); 295 if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ) 296 memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS, 297 img_ver, VER_STR_SZ); 298 } 299 300 static void hfi_sys_property_info(struct venus_core *core, 301 struct venus_inst *inst, void *packet) 302 { 303 struct hfi_msg_sys_property_info_pkt *pkt = packet; 304 struct device *dev = core->dev; 305 306 if (!pkt->num_properties) { 307 dev_dbg(dev, VDBGL "no properties\n"); 308 return; 309 } 310 311 switch (pkt->property) { 312 case HFI_PROPERTY_SYS_IMAGE_VERSION: 313 sys_get_prop_image_version(core, pkt); 314 break; 315 default: 316 dev_dbg(dev, VDBGL "unknown property data\n"); 317 break; 318 } 319 } 320 321 static void hfi_sys_rel_resource_done(struct venus_core *core, 322 struct venus_inst *inst, 323 void *packet) 324 { 325 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet; 326 327 core->error = pkt->error_type; 328 complete(&core->done); 329 } 330 331 static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst, 332 void *packet) 333 { 334 struct hfi_msg_sys_ping_ack_pkt *pkt = packet; 335 336 core->error = HFI_ERR_NONE; 337 338 if (pkt->client_data != 0xbeef) 339 core->error = HFI_ERR_SYS_FATAL; 340 341 complete(&core->done); 342 } 343 344 static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst, 345 void *packet) 346 { 347 dev_dbg(core->dev, VDBGL "sys idle\n"); 348 } 349 350 static void hfi_sys_pc_prepare_done(struct venus_core *core, 351 struct venus_inst *inst, void *packet) 352 { 353 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet; 354 355 dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n", 356 pkt->error_type); 357 } 358 359 static unsigned int 360 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt, 361 struct hfi_profile_level *profile_level) 362 { 363 struct hfi_profile_level *hfi; 364 u32 req_bytes; 365 366 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 367 368 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level)) 369 /* bad packet */ 370 return HFI_ERR_SESSION_INVALID_PARAMETER; 371 372 hfi = (struct hfi_profile_level *)&pkt->data[0]; 373 profile_level->profile = hfi->profile; 374 profile_level->level = hfi->level; 375 376 return HFI_ERR_NONE; 377 } 378 379 static unsigned int 380 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, 381 struct hfi_buffer_requirements *bufreq) 382 { 383 struct hfi_buffer_requirements *buf_req; 384 u32 req_bytes; 385 unsigned int idx = 0; 386 387 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 388 389 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0]) 390 /* bad packet */ 391 return HFI_ERR_SESSION_INVALID_PARAMETER; 392 393 buf_req = (struct hfi_buffer_requirements *)&pkt->data[0]; 394 if (!buf_req) 395 return HFI_ERR_SESSION_INVALID_PARAMETER; 396 397 while (req_bytes) { 398 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); 399 idx++; 400 401 if (idx > HFI_BUFFER_TYPE_MAX) 402 return HFI_ERR_SESSION_INVALID_PARAMETER; 403 404 req_bytes -= sizeof(struct hfi_buffer_requirements); 405 buf_req++; 406 } 407 408 return HFI_ERR_NONE; 409 } 410 411 static void hfi_session_prop_info(struct venus_core *core, 412 struct venus_inst *inst, void *packet) 413 { 414 struct hfi_msg_session_property_info_pkt *pkt = packet; 415 struct device *dev = core->dev; 416 union hfi_get_property *hprop = &inst->hprop; 417 unsigned int error = HFI_ERR_NONE; 418 419 if (!pkt->num_properties) { 420 error = HFI_ERR_SESSION_INVALID_PARAMETER; 421 dev_err(dev, "%s: no properties\n", __func__); 422 goto done; 423 } 424 425 switch (pkt->property) { 426 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 427 memset(hprop->bufreq, 0, sizeof(hprop->bufreq)); 428 error = session_get_prop_buf_req(pkt, hprop->bufreq); 429 break; 430 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 431 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level)); 432 error = session_get_prop_profile_level(pkt, 433 &hprop->profile_level); 434 break; 435 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 436 break; 437 default: 438 dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property); 439 return; 440 } 441 442 done: 443 inst->error = error; 444 complete(&inst->done); 445 } 446 447 static void hfi_session_init_done(struct venus_core *core, 448 struct venus_inst *inst, void *packet) 449 { 450 struct hfi_msg_session_init_done_pkt *pkt = packet; 451 int rem_bytes; 452 u32 error; 453 454 error = pkt->error_type; 455 if (error != HFI_ERR_NONE) 456 goto done; 457 458 if (!IS_V1(core)) 459 goto done; 460 461 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 462 if (rem_bytes <= 0) { 463 error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 464 goto done; 465 } 466 467 error = hfi_parser(core, inst, pkt->data, rem_bytes); 468 done: 469 inst->error = error; 470 complete(&inst->done); 471 } 472 473 static void hfi_session_load_res_done(struct venus_core *core, 474 struct venus_inst *inst, void *packet) 475 { 476 struct hfi_msg_session_load_resources_done_pkt *pkt = packet; 477 478 inst->error = pkt->error_type; 479 complete(&inst->done); 480 } 481 482 static void hfi_session_flush_done(struct venus_core *core, 483 struct venus_inst *inst, void *packet) 484 { 485 struct hfi_msg_session_flush_done_pkt *pkt = packet; 486 487 inst->error = pkt->error_type; 488 complete(&inst->done); 489 if (inst->ops->flush_done) 490 inst->ops->flush_done(inst); 491 } 492 493 static void hfi_session_etb_done(struct venus_core *core, 494 struct venus_inst *inst, void *packet) 495 { 496 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet; 497 498 inst->error = pkt->error_type; 499 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag, 500 pkt->filled_len, pkt->offset, 0, 0, 0); 501 } 502 503 static void hfi_session_ftb_done(struct venus_core *core, 504 struct venus_inst *inst, void *packet) 505 { 506 u32 session_type = inst->session_type; 507 u64 timestamp_us = 0; 508 u32 timestamp_hi = 0, timestamp_lo = 0; 509 unsigned int error; 510 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0; 511 u32 pic_type = 0, buffer_type = 0, output_tag = -1; 512 513 if (session_type == VIDC_SESSION_TYPE_ENC) { 514 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet; 515 516 timestamp_hi = pkt->time_stamp_hi; 517 timestamp_lo = pkt->time_stamp_lo; 518 hfi_flags = pkt->flags; 519 offset = pkt->offset; 520 filled_len = pkt->filled_len; 521 pic_type = pkt->picture_type; 522 output_tag = pkt->output_tag; 523 buffer_type = HFI_BUFFER_OUTPUT; 524 525 error = pkt->error_type; 526 } else if (session_type == VIDC_SESSION_TYPE_DEC) { 527 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = 528 packet; 529 530 timestamp_hi = pkt->time_stamp_hi; 531 timestamp_lo = pkt->time_stamp_lo; 532 hfi_flags = pkt->flags; 533 offset = pkt->offset; 534 filled_len = pkt->filled_len; 535 pic_type = pkt->picture_type; 536 output_tag = pkt->output_tag; 537 538 if (pkt->stream_id == 0) 539 buffer_type = HFI_BUFFER_OUTPUT; 540 else if (pkt->stream_id == 1) 541 buffer_type = HFI_BUFFER_OUTPUT2; 542 543 error = pkt->error_type; 544 } else { 545 error = HFI_ERR_SESSION_INVALID_PARAMETER; 546 } 547 548 if (buffer_type != HFI_BUFFER_OUTPUT && 549 buffer_type != HFI_BUFFER_OUTPUT2) 550 goto done; 551 552 if (hfi_flags & HFI_BUFFERFLAG_EOS) 553 flags |= V4L2_BUF_FLAG_LAST; 554 555 switch (pic_type) { 556 case HFI_PICTURE_IDR: 557 case HFI_PICTURE_I: 558 flags |= V4L2_BUF_FLAG_KEYFRAME; 559 break; 560 case HFI_PICTURE_P: 561 flags |= V4L2_BUF_FLAG_PFRAME; 562 break; 563 case HFI_PICTURE_B: 564 flags |= V4L2_BUF_FLAG_BFRAME; 565 break; 566 case HFI_FRAME_NOTCODED: 567 case HFI_UNUSED_PICT: 568 case HFI_FRAME_YUV: 569 default: 570 break; 571 } 572 573 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) { 574 timestamp_us = timestamp_hi; 575 timestamp_us = (timestamp_us << 32) | timestamp_lo; 576 } 577 578 done: 579 inst->error = error; 580 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len, 581 offset, flags, hfi_flags, timestamp_us); 582 } 583 584 static void hfi_session_start_done(struct venus_core *core, 585 struct venus_inst *inst, void *packet) 586 { 587 struct hfi_msg_session_start_done_pkt *pkt = packet; 588 589 inst->error = pkt->error_type; 590 complete(&inst->done); 591 } 592 593 static void hfi_session_stop_done(struct venus_core *core, 594 struct venus_inst *inst, void *packet) 595 { 596 struct hfi_msg_session_stop_done_pkt *pkt = packet; 597 598 inst->error = pkt->error_type; 599 complete(&inst->done); 600 } 601 602 static void hfi_session_rel_res_done(struct venus_core *core, 603 struct venus_inst *inst, void *packet) 604 { 605 struct hfi_msg_session_release_resources_done_pkt *pkt = packet; 606 607 inst->error = pkt->error_type; 608 complete(&inst->done); 609 } 610 611 static void hfi_session_rel_buf_done(struct venus_core *core, 612 struct venus_inst *inst, void *packet) 613 { 614 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet; 615 616 inst->error = pkt->error_type; 617 complete(&inst->done); 618 } 619 620 static void hfi_session_end_done(struct venus_core *core, 621 struct venus_inst *inst, void *packet) 622 { 623 struct hfi_msg_session_end_done_pkt *pkt = packet; 624 625 inst->error = pkt->error_type; 626 complete(&inst->done); 627 } 628 629 static void hfi_session_abort_done(struct venus_core *core, 630 struct venus_inst *inst, void *packet) 631 { 632 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet; 633 634 inst->error = pkt->error_type; 635 complete(&inst->done); 636 } 637 638 static void hfi_session_get_seq_hdr_done(struct venus_core *core, 639 struct venus_inst *inst, void *packet) 640 { 641 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet; 642 643 inst->error = pkt->error_type; 644 complete(&inst->done); 645 } 646 647 struct hfi_done_handler { 648 u32 pkt; 649 u32 pkt_sz; 650 u32 pkt_sz2; 651 void (*done)(struct venus_core *, struct venus_inst *, void *); 652 bool is_sys_pkt; 653 }; 654 655 static const struct hfi_done_handler handlers[] = { 656 {.pkt = HFI_MSG_EVENT_NOTIFY, 657 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), 658 .done = hfi_event_notify, 659 }, 660 {.pkt = HFI_MSG_SYS_INIT, 661 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), 662 .done = hfi_sys_init_done, 663 .is_sys_pkt = true, 664 }, 665 {.pkt = HFI_MSG_SYS_PROPERTY_INFO, 666 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), 667 .done = hfi_sys_property_info, 668 .is_sys_pkt = true, 669 }, 670 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE, 671 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt), 672 .done = hfi_sys_rel_resource_done, 673 .is_sys_pkt = true, 674 }, 675 {.pkt = HFI_MSG_SYS_PING_ACK, 676 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt), 677 .done = hfi_sys_ping_done, 678 .is_sys_pkt = true, 679 }, 680 {.pkt = HFI_MSG_SYS_IDLE, 681 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt), 682 .done = hfi_sys_idle_done, 683 .is_sys_pkt = true, 684 }, 685 {.pkt = HFI_MSG_SYS_PC_PREP, 686 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt), 687 .done = hfi_sys_pc_prepare_done, 688 .is_sys_pkt = true, 689 }, 690 {.pkt = HFI_MSG_SYS_SESSION_INIT, 691 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt), 692 .done = hfi_session_init_done, 693 }, 694 {.pkt = HFI_MSG_SYS_SESSION_END, 695 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt), 696 .done = hfi_session_end_done, 697 }, 698 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES, 699 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt), 700 .done = hfi_session_load_res_done, 701 }, 702 {.pkt = HFI_MSG_SESSION_START, 703 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt), 704 .done = hfi_session_start_done, 705 }, 706 {.pkt = HFI_MSG_SESSION_STOP, 707 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt), 708 .done = hfi_session_stop_done, 709 }, 710 {.pkt = HFI_MSG_SYS_SESSION_ABORT, 711 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt), 712 .done = hfi_session_abort_done, 713 }, 714 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER, 715 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt), 716 .done = hfi_session_etb_done, 717 }, 718 {.pkt = HFI_MSG_SESSION_FILL_BUFFER, 719 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), 720 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt), 721 .done = hfi_session_ftb_done, 722 }, 723 {.pkt = HFI_MSG_SESSION_FLUSH, 724 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), 725 .done = hfi_session_flush_done, 726 }, 727 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO, 728 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), 729 .done = hfi_session_prop_info, 730 }, 731 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, 732 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt), 733 .done = hfi_session_rel_res_done, 734 }, 735 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER, 736 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt), 737 .done = hfi_session_get_seq_hdr_done, 738 }, 739 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, 740 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), 741 .done = hfi_session_rel_buf_done, 742 }, 743 }; 744 745 void hfi_process_watchdog_timeout(struct venus_core *core) 746 { 747 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL); 748 } 749 750 static struct venus_inst *to_instance(struct venus_core *core, u32 session_id) 751 { 752 struct venus_inst *inst; 753 754 mutex_lock(&core->lock); 755 list_for_each_entry(inst, &core->instances, list) 756 if (hash32_ptr(inst) == session_id) { 757 mutex_unlock(&core->lock); 758 return inst; 759 } 760 mutex_unlock(&core->lock); 761 762 return NULL; 763 } 764 765 u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr) 766 { 767 const struct hfi_done_handler *handler; 768 struct device *dev = core->dev; 769 struct venus_inst *inst; 770 bool found = false; 771 unsigned int i; 772 773 for (i = 0; i < ARRAY_SIZE(handlers); i++) { 774 handler = &handlers[i]; 775 if (handler->pkt != hdr->pkt_type) 776 continue; 777 found = true; 778 break; 779 } 780 781 if (!found) 782 return hdr->pkt_type; 783 784 if (hdr->size && hdr->size < handler->pkt_sz && 785 hdr->size < handler->pkt_sz2) { 786 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n", 787 hdr->size, handler->pkt_sz, hdr->pkt_type); 788 789 return hdr->pkt_type; 790 } 791 792 if (handler->is_sys_pkt) { 793 inst = NULL; 794 } else { 795 struct hfi_session_pkt *pkt; 796 797 pkt = (struct hfi_session_pkt *)hdr; 798 inst = to_instance(core, pkt->shdr.session_id); 799 800 if (!inst) 801 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n", 802 pkt->shdr.session_id, 803 handler ? handler->pkt : 0); 804 805 /* 806 * Event of type HFI_EVENT_SYS_ERROR will not have any session 807 * associated with it 808 */ 809 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) { 810 dev_err(dev, "got invalid session id:%x\n", 811 pkt->shdr.session_id); 812 goto invalid_session; 813 } 814 } 815 816 handler->done(core, inst, hdr); 817 818 invalid_session: 819 return hdr->pkt_type; 820 } 821