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