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