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