linux/drivers/media/platform/qcom/venus/hfi_msgs.c
<<
>>
Prefs
   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        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
 119done:
 120        inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event);
 121}
 122
 123static 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
 142static 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
 154static void
 155event_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
 185static 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
 213static 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
 238done:
 239        core->error = error;
 240        complete(&core->done);
 241}
 242
 243static void
 244sys_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[0] || pkt->num_properties > 1)
 255                /* bad packet */
 256                return;
 257
 258        img_ver = pkt->data;
 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
 269static 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->property) {
 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
 290static 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
 300static 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
 313static 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
 319static 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
 328static unsigned int
 329session_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[0];
 342        profile_level->profile = hfi->profile;
 343        profile_level->level = hfi->level;
 344
 345        return HFI_ERR_NONE;
 346}
 347
 348static unsigned int
 349session_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[0])
 359                /* bad packet */
 360                return HFI_ERR_SESSION_INVALID_PARAMETER;
 361
 362        buf_req = (struct hfi_buffer_requirements *)&pkt->data[0];
 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
 380static 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->property) {
 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->property);
 408                return;
 409        }
 410
 411done:
 412        inst->error = error;
 413        complete(&inst->done);
 414}
 415
 416static 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);
 437done:
 438        inst->error = error;
 439        complete(&inst->done);
 440}
 441
 442static 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
 451static 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
 462static 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
 472static 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
 547done:
 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
 553static 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
 562static 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
 571static 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
 580static 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
 589static 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
 598static 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
 607static 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
 616struct 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
 624static 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
 714void hfi_process_watchdog_timeout(struct venus_core *core)
 715{
 716        event_sys_error(core, EVT_SYS_WATCHDOG_TIMEOUT, NULL);
 717}
 718
 719static 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
 734u32 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
 787invalid_session:
 788        return hdr->pkt_type;
 789}
 790
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.