hfi_msgs.c (21055B)
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 22static 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_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 126done: 127 inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); 128} 129 130static 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 149static 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 161static void 162event_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 192static 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 220static 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) + sizeof(u32); 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 245done: 246 core->error = error; 247 complete(&core->done); 248} 249 250static void 251sys_get_prop_image_version(struct device *dev, 252 struct hfi_msg_sys_property_info_pkt *pkt) 253{ 254 u8 *smem_tbl_ptr; 255 u8 *img_ver; 256 int req_bytes; 257 size_t smem_blk_sz; 258 259 req_bytes = pkt->hdr.size - sizeof(*pkt); 260 261 if (req_bytes < VER_STR_SZ || !pkt->data[0] || pkt->num_properties > 1) 262 /* bad packet */ 263 return; 264 265 img_ver = pkt->data; 266 267 dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver); 268 269 smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, 270 SMEM_IMG_VER_TBL, &smem_blk_sz); 271 if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ) 272 memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS, 273 img_ver, VER_STR_SZ); 274} 275 276static void hfi_sys_property_info(struct venus_core *core, 277 struct venus_inst *inst, void *packet) 278{ 279 struct hfi_msg_sys_property_info_pkt *pkt = packet; 280 struct device *dev = core->dev; 281 282 if (!pkt->num_properties) { 283 dev_dbg(dev, VDBGL "no properties\n"); 284 return; 285 } 286 287 switch (pkt->property) { 288 case HFI_PROPERTY_SYS_IMAGE_VERSION: 289 sys_get_prop_image_version(dev, pkt); 290 break; 291 default: 292 dev_dbg(dev, VDBGL "unknown property data\n"); 293 break; 294 } 295} 296 297static void hfi_sys_rel_resource_done(struct venus_core *core, 298 struct venus_inst *inst, 299 void *packet) 300{ 301 struct hfi_msg_sys_release_resource_done_pkt *pkt = packet; 302 303 core->error = pkt->error_type; 304 complete(&core->done); 305} 306 307static void hfi_sys_ping_done(struct venus_core *core, struct venus_inst *inst, 308 void *packet) 309{ 310 struct hfi_msg_sys_ping_ack_pkt *pkt = packet; 311 312 core->error = HFI_ERR_NONE; 313 314 if (pkt->client_data != 0xbeef) 315 core->error = HFI_ERR_SYS_FATAL; 316 317 complete(&core->done); 318} 319 320static void hfi_sys_idle_done(struct venus_core *core, struct venus_inst *inst, 321 void *packet) 322{ 323 dev_dbg(core->dev, VDBGL "sys idle\n"); 324} 325 326static void hfi_sys_pc_prepare_done(struct venus_core *core, 327 struct venus_inst *inst, void *packet) 328{ 329 struct hfi_msg_sys_pc_prep_done_pkt *pkt = packet; 330 331 dev_dbg(core->dev, VDBGL "pc prepare done (error %x)\n", 332 pkt->error_type); 333} 334 335static unsigned int 336session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt *pkt, 337 struct hfi_profile_level *profile_level) 338{ 339 struct hfi_profile_level *hfi; 340 u32 req_bytes; 341 342 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 343 344 if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level)) 345 /* bad packet */ 346 return HFI_ERR_SESSION_INVALID_PARAMETER; 347 348 hfi = (struct hfi_profile_level *)&pkt->data[0]; 349 profile_level->profile = hfi->profile; 350 profile_level->level = hfi->level; 351 352 return HFI_ERR_NONE; 353} 354 355static unsigned int 356session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, 357 struct hfi_buffer_requirements *bufreq) 358{ 359 struct hfi_buffer_requirements *buf_req; 360 u32 req_bytes; 361 unsigned int idx = 0; 362 363 req_bytes = pkt->shdr.hdr.size - sizeof(*pkt); 364 365 if (!req_bytes || req_bytes % sizeof(*buf_req) || !pkt->data[0]) 366 /* bad packet */ 367 return HFI_ERR_SESSION_INVALID_PARAMETER; 368 369 buf_req = (struct hfi_buffer_requirements *)&pkt->data[0]; 370 if (!buf_req) 371 return HFI_ERR_SESSION_INVALID_PARAMETER; 372 373 while (req_bytes) { 374 memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); 375 idx++; 376 377 if (idx > HFI_BUFFER_TYPE_MAX) 378 return HFI_ERR_SESSION_INVALID_PARAMETER; 379 380 req_bytes -= sizeof(struct hfi_buffer_requirements); 381 buf_req++; 382 } 383 384 return HFI_ERR_NONE; 385} 386 387static void hfi_session_prop_info(struct venus_core *core, 388 struct venus_inst *inst, void *packet) 389{ 390 struct hfi_msg_session_property_info_pkt *pkt = packet; 391 struct device *dev = core->dev; 392 union hfi_get_property *hprop = &inst->hprop; 393 unsigned int error = HFI_ERR_NONE; 394 395 if (!pkt->num_properties) { 396 error = HFI_ERR_SESSION_INVALID_PARAMETER; 397 dev_err(dev, "%s: no properties\n", __func__); 398 goto done; 399 } 400 401 switch (pkt->property) { 402 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: 403 memset(hprop->bufreq, 0, sizeof(hprop->bufreq)); 404 error = session_get_prop_buf_req(pkt, hprop->bufreq); 405 break; 406 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: 407 memset(&hprop->profile_level, 0, sizeof(hprop->profile_level)); 408 error = session_get_prop_profile_level(pkt, 409 &hprop->profile_level); 410 break; 411 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: 412 break; 413 default: 414 dev_dbg(dev, VDBGM "unknown property id:%x\n", pkt->property); 415 return; 416 } 417 418done: 419 inst->error = error; 420 complete(&inst->done); 421} 422 423static void hfi_session_init_done(struct venus_core *core, 424 struct venus_inst *inst, void *packet) 425{ 426 struct hfi_msg_session_init_done_pkt *pkt = packet; 427 int rem_bytes; 428 u32 error; 429 430 error = pkt->error_type; 431 if (error != HFI_ERR_NONE) 432 goto done; 433 434 if (!IS_V1(core)) 435 goto done; 436 437 rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32); 438 if (rem_bytes <= 0) { 439 error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; 440 goto done; 441 } 442 443 error = hfi_parser(core, inst, pkt->data, rem_bytes); 444done: 445 inst->error = error; 446 complete(&inst->done); 447} 448 449static void hfi_session_load_res_done(struct venus_core *core, 450 struct venus_inst *inst, void *packet) 451{ 452 struct hfi_msg_session_load_resources_done_pkt *pkt = packet; 453 454 inst->error = pkt->error_type; 455 complete(&inst->done); 456} 457 458static void hfi_session_flush_done(struct venus_core *core, 459 struct venus_inst *inst, void *packet) 460{ 461 struct hfi_msg_session_flush_done_pkt *pkt = packet; 462 463 inst->error = pkt->error_type; 464 complete(&inst->done); 465 if (inst->ops->flush_done) 466 inst->ops->flush_done(inst); 467} 468 469static void hfi_session_etb_done(struct venus_core *core, 470 struct venus_inst *inst, void *packet) 471{ 472 struct hfi_msg_session_empty_buffer_done_pkt *pkt = packet; 473 474 inst->error = pkt->error_type; 475 inst->ops->buf_done(inst, HFI_BUFFER_INPUT, pkt->input_tag, 476 pkt->filled_len, pkt->offset, 0, 0, 0); 477} 478 479static void hfi_session_ftb_done(struct venus_core *core, 480 struct venus_inst *inst, void *packet) 481{ 482 u32 session_type = inst->session_type; 483 u64 timestamp_us = 0; 484 u32 timestamp_hi = 0, timestamp_lo = 0; 485 unsigned int error; 486 u32 flags = 0, hfi_flags = 0, offset = 0, filled_len = 0; 487 u32 pic_type = 0, buffer_type = 0, output_tag = -1; 488 489 if (session_type == VIDC_SESSION_TYPE_ENC) { 490 struct hfi_msg_session_fbd_compressed_pkt *pkt = packet; 491 492 timestamp_hi = pkt->time_stamp_hi; 493 timestamp_lo = pkt->time_stamp_lo; 494 hfi_flags = pkt->flags; 495 offset = pkt->offset; 496 filled_len = pkt->filled_len; 497 pic_type = pkt->picture_type; 498 output_tag = pkt->output_tag; 499 buffer_type = HFI_BUFFER_OUTPUT; 500 501 error = pkt->error_type; 502 } else if (session_type == VIDC_SESSION_TYPE_DEC) { 503 struct hfi_msg_session_fbd_uncompressed_plane0_pkt *pkt = 504 packet; 505 506 timestamp_hi = pkt->time_stamp_hi; 507 timestamp_lo = pkt->time_stamp_lo; 508 hfi_flags = pkt->flags; 509 offset = pkt->offset; 510 filled_len = pkt->filled_len; 511 pic_type = pkt->picture_type; 512 output_tag = pkt->output_tag; 513 514 if (pkt->stream_id == 0) 515 buffer_type = HFI_BUFFER_OUTPUT; 516 else if (pkt->stream_id == 1) 517 buffer_type = HFI_BUFFER_OUTPUT2; 518 519 error = pkt->error_type; 520 } else { 521 error = HFI_ERR_SESSION_INVALID_PARAMETER; 522 } 523 524 if (buffer_type != HFI_BUFFER_OUTPUT && 525 buffer_type != HFI_BUFFER_OUTPUT2) 526 goto done; 527 528 if (hfi_flags & HFI_BUFFERFLAG_EOS) 529 flags |= V4L2_BUF_FLAG_LAST; 530 531 switch (pic_type) { 532 case HFI_PICTURE_IDR: 533 case HFI_PICTURE_I: 534 flags |= V4L2_BUF_FLAG_KEYFRAME; 535 break; 536 case HFI_PICTURE_P: 537 flags |= V4L2_BUF_FLAG_PFRAME; 538 break; 539 case HFI_PICTURE_B: 540 flags |= V4L2_BUF_FLAG_BFRAME; 541 break; 542 case HFI_FRAME_NOTCODED: 543 case HFI_UNUSED_PICT: 544 case HFI_FRAME_YUV: 545 default: 546 break; 547 } 548 549 if (!(hfi_flags & HFI_BUFFERFLAG_TIMESTAMPINVALID) && filled_len) { 550 timestamp_us = timestamp_hi; 551 timestamp_us = (timestamp_us << 32) | timestamp_lo; 552 } 553 554done: 555 inst->error = error; 556 inst->ops->buf_done(inst, buffer_type, output_tag, filled_len, 557 offset, flags, hfi_flags, timestamp_us); 558} 559 560static void hfi_session_start_done(struct venus_core *core, 561 struct venus_inst *inst, void *packet) 562{ 563 struct hfi_msg_session_start_done_pkt *pkt = packet; 564 565 inst->error = pkt->error_type; 566 complete(&inst->done); 567} 568 569static void hfi_session_stop_done(struct venus_core *core, 570 struct venus_inst *inst, void *packet) 571{ 572 struct hfi_msg_session_stop_done_pkt *pkt = packet; 573 574 inst->error = pkt->error_type; 575 complete(&inst->done); 576} 577 578static void hfi_session_rel_res_done(struct venus_core *core, 579 struct venus_inst *inst, void *packet) 580{ 581 struct hfi_msg_session_release_resources_done_pkt *pkt = packet; 582 583 inst->error = pkt->error_type; 584 complete(&inst->done); 585} 586 587static void hfi_session_rel_buf_done(struct venus_core *core, 588 struct venus_inst *inst, void *packet) 589{ 590 struct hfi_msg_session_release_buffers_done_pkt *pkt = packet; 591 592 inst->error = pkt->error_type; 593 complete(&inst->done); 594} 595 596static void hfi_session_end_done(struct venus_core *core, 597 struct venus_inst *inst, void *packet) 598{ 599 struct hfi_msg_session_end_done_pkt *pkt = packet; 600 601 inst->error = pkt->error_type; 602 complete(&inst->done); 603} 604 605static void hfi_session_abort_done(struct venus_core *core, 606 struct venus_inst *inst, void *packet) 607{ 608 struct hfi_msg_sys_session_abort_done_pkt *pkt = packet; 609 610 inst->error = pkt->error_type; 611 complete(&inst->done); 612} 613 614static void hfi_session_get_seq_hdr_done(struct venus_core *core, 615 struct venus_inst *inst, void *packet) 616{ 617 struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet; 618 619 inst->error = pkt->error_type; 620 complete(&inst->done); 621} 622 623struct hfi_done_handler { 624 u32 pkt; 625 u32 pkt_sz; 626 u32 pkt_sz2; 627 void (*done)(struct venus_core *, struct venus_inst *, void *); 628 bool is_sys_pkt; 629}; 630 631static const struct hfi_done_handler handlers[] = { 632 {.pkt = HFI_MSG_EVENT_NOTIFY, 633 .pkt_sz = sizeof(struct hfi_msg_event_notify_pkt), 634 .done = hfi_event_notify, 635 }, 636 {.pkt = HFI_MSG_SYS_INIT, 637 .pkt_sz = sizeof(struct hfi_msg_sys_init_done_pkt), 638 .done = hfi_sys_init_done, 639 .is_sys_pkt = true, 640 }, 641 {.pkt = HFI_MSG_SYS_PROPERTY_INFO, 642 .pkt_sz = sizeof(struct hfi_msg_sys_property_info_pkt), 643 .done = hfi_sys_property_info, 644 .is_sys_pkt = true, 645 }, 646 {.pkt = HFI_MSG_SYS_RELEASE_RESOURCE, 647 .pkt_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt), 648 .done = hfi_sys_rel_resource_done, 649 .is_sys_pkt = true, 650 }, 651 {.pkt = HFI_MSG_SYS_PING_ACK, 652 .pkt_sz = sizeof(struct hfi_msg_sys_ping_ack_pkt), 653 .done = hfi_sys_ping_done, 654 .is_sys_pkt = true, 655 }, 656 {.pkt = HFI_MSG_SYS_IDLE, 657 .pkt_sz = sizeof(struct hfi_msg_sys_idle_pkt), 658 .done = hfi_sys_idle_done, 659 .is_sys_pkt = true, 660 }, 661 {.pkt = HFI_MSG_SYS_PC_PREP, 662 .pkt_sz = sizeof(struct hfi_msg_sys_pc_prep_done_pkt), 663 .done = hfi_sys_pc_prepare_done, 664 .is_sys_pkt = true, 665 }, 666 {.pkt = HFI_MSG_SYS_SESSION_INIT, 667 .pkt_sz = sizeof(struct hfi_msg_session_init_done_pkt), 668 .done = hfi_session_init_done, 669 }, 670 {.pkt = HFI_MSG_SYS_SESSION_END, 671 .pkt_sz = sizeof(struct hfi_msg_session_end_done_pkt), 672 .done = hfi_session_end_done, 673 }, 674 {.pkt = HFI_MSG_SESSION_LOAD_RESOURCES, 675 .pkt_sz = sizeof(struct hfi_msg_session_load_resources_done_pkt), 676 .done = hfi_session_load_res_done, 677 }, 678 {.pkt = HFI_MSG_SESSION_START, 679 .pkt_sz = sizeof(struct hfi_msg_session_start_done_pkt), 680 .done = hfi_session_start_done, 681 }, 682 {.pkt = HFI_MSG_SESSION_STOP, 683 .pkt_sz = sizeof(struct hfi_msg_session_stop_done_pkt), 684 .done = hfi_session_stop_done, 685 }, 686 {.pkt = HFI_MSG_SYS_SESSION_ABORT, 687 .pkt_sz = sizeof(struct hfi_msg_sys_session_abort_done_pkt), 688 .done = hfi_session_abort_done, 689 }, 690 {.pkt = HFI_MSG_SESSION_EMPTY_BUFFER, 691 .pkt_sz = sizeof(struct hfi_msg_session_empty_buffer_done_pkt), 692 .done = hfi_session_etb_done, 693 }, 694 {.pkt = HFI_MSG_SESSION_FILL_BUFFER, 695 .pkt_sz = sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt), 696 .pkt_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_pkt), 697 .done = hfi_session_ftb_done, 698 }, 699 {.pkt = HFI_MSG_SESSION_FLUSH, 700 .pkt_sz = sizeof(struct hfi_msg_session_flush_done_pkt), 701 .done = hfi_session_flush_done, 702 }, 703 {.pkt = HFI_MSG_SESSION_PROPERTY_INFO, 704 .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt), 705 .done = hfi_session_prop_info, 706 }, 707 {.pkt = HFI_MSG_SESSION_RELEASE_RESOURCES, 708 .pkt_sz = sizeof(struct hfi_msg_session_release_resources_done_pkt), 709 .done = hfi_session_rel_res_done, 710 }, 711 {.pkt = HFI_MSG_SESSION_GET_SEQUENCE_HEADER, 712 .pkt_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt), 713 .done = hfi_session_get_seq_hdr_done, 714 }, 715 {.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS, 716 .pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt), 717 .done = hfi_session_rel_buf_done, 718 }, 719}; 720 721void hfi_process_watchdog_timeout(struct venus_core *core) 722{ 723 event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL); 724} 725 726static struct venus_inst *to_instance(struct venus_core *core, u32 session_id) 727{ 728 struct venus_inst *inst; 729 730 mutex_lock(&core->lock); 731 list_for_each_entry(inst, &core->instances, list) 732 if (hash32_ptr(inst) == session_id) { 733 mutex_unlock(&core->lock); 734 return inst; 735 } 736 mutex_unlock(&core->lock); 737 738 return NULL; 739} 740 741u32 hfi_process_msg_packet(struct venus_core *core, struct hfi_pkt_hdr *hdr) 742{ 743 const struct hfi_done_handler *handler; 744 struct device *dev = core->dev; 745 struct venus_inst *inst; 746 bool found = false; 747 unsigned int i; 748 749 for (i = 0; i < ARRAY_SIZE(handlers); i++) { 750 handler = &handlers[i]; 751 if (handler->pkt != hdr->pkt_type) 752 continue; 753 found = true; 754 break; 755 } 756 757 if (!found) 758 return hdr->pkt_type; 759 760 if (hdr->size && hdr->size < handler->pkt_sz && 761 hdr->size < handler->pkt_sz2) { 762 dev_err(dev, "bad packet size (%d should be %d, pkt type:%x)\n", 763 hdr->size, handler->pkt_sz, hdr->pkt_type); 764 765 return hdr->pkt_type; 766 } 767 768 if (handler->is_sys_pkt) { 769 inst = NULL; 770 } else { 771 struct hfi_session_pkt *pkt; 772 773 pkt = (struct hfi_session_pkt *)hdr; 774 inst = to_instance(core, pkt->shdr.session_id); 775 776 if (!inst) 777 dev_warn(dev, "no valid instance(pkt session_id:%x, pkt:%x)\n", 778 pkt->shdr.session_id, 779 handler ? handler->pkt : 0); 780 781 /* 782 * Event of type HFI_EVENT_SYS_ERROR will not have any session 783 * associated with it 784 */ 785 if (!inst && hdr->pkt_type != HFI_MSG_EVENT_NOTIFY) { 786 dev_err(dev, "got invalid session id:%x\n", 787 pkt->shdr.session_id); 788 goto invalid_session; 789 } 790 } 791 792 handler->done(core, inst, hdr); 793 794invalid_session: 795 return hdr->pkt_type; 796}