linux/drivers/staging/media/atomisp/pci/runtime/bufq/src/bufq.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Support for Intel Camera Imaging ISP subsystem.
   4 * Copyright (c) 2015, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 */
  15
  16#include "assert_support.h"             /* assert */
  17#include "ia_css_buffer.h"
  18#include "sp.h"
  19#include "ia_css_bufq.h"                /* Bufq API's */
  20#include "ia_css_queue.h"               /* ia_css_queue_t */
  21#include "sw_event_global.h"            /* Event IDs.*/
  22#include "ia_css_eventq.h"              /* ia_css_eventq_recv()*/
  23#include "ia_css_debug.h"               /* ia_css_debug_dtrace*/
  24#include "sh_css_internal.h"            /* sh_css_queue_type */
  25#include "sp_local.h"                   /* sp_address_of */
  26#include "sh_css_firmware.h"            /* sh_css_sp_fw*/
  27
  28#define BUFQ_DUMP_FILE_NAME_PREFIX_SIZE 256
  29
  30static char prefix[BUFQ_DUMP_FILE_NAME_PREFIX_SIZE] = {0};
  31
  32/*********************************************************/
  33/* Global Queue objects used by CSS                      */
  34/*********************************************************/
  35
  36struct sh_css_queues {
  37        /* Host2SP buffer queue */
  38        ia_css_queue_t host2sp_buffer_queue_handles
  39        [SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
  40        /* SP2Host buffer queue */
  41        ia_css_queue_t sp2host_buffer_queue_handles
  42        [SH_CSS_MAX_NUM_QUEUES];
  43
  44        /* Host2SP event queue */
  45        ia_css_queue_t host2sp_psys_event_queue_handle;
  46
  47        /* SP2Host event queue */
  48        ia_css_queue_t sp2host_psys_event_queue_handle;
  49
  50        /* Host2SP ISYS event queue */
  51        ia_css_queue_t host2sp_isys_event_queue_handle;
  52
  53        /* SP2Host ISYS event queue */
  54        ia_css_queue_t sp2host_isys_event_queue_handle;
  55        /* Tagger command queue */
  56        ia_css_queue_t host2sp_tag_cmd_queue_handle;
  57};
  58
  59/*******************************************************
  60*** Static variables
  61********************************************************/
  62static struct sh_css_queues css_queues;
  63
  64static int
  65buffer_type_to_queue_id_map[SH_CSS_MAX_SP_THREADS][IA_CSS_NUM_DYNAMIC_BUFFER_TYPE];
  66static bool queue_availability[SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
  67
  68/*******************************************************
  69*** Static functions
  70********************************************************/
  71static void map_buffer_type_to_queue_id(
  72    unsigned int thread_id,
  73    enum ia_css_buffer_type buf_type
  74);
  75static void unmap_buffer_type_to_queue_id(
  76    unsigned int thread_id,
  77    enum ia_css_buffer_type buf_type
  78);
  79
  80static ia_css_queue_t *bufq_get_qhandle(
  81    enum sh_css_queue_type type,
  82    enum sh_css_queue_id id,
  83    int thread
  84);
  85
  86/*******************************************************
  87*** Public functions
  88********************************************************/
  89void ia_css_queue_map_init(void)
  90{
  91        unsigned int i, j;
  92
  93        for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
  94                for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++)
  95                        queue_availability[i][j] = true;
  96        }
  97
  98        for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
  99                for (j = 0; j < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE; j++)
 100                        buffer_type_to_queue_id_map[i][j] = SH_CSS_INVALID_QUEUE_ID;
 101        }
 102}
 103
 104void ia_css_queue_map(
 105    unsigned int thread_id,
 106    enum ia_css_buffer_type buf_type,
 107    bool map)
 108{
 109        assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
 110        assert(thread_id < SH_CSS_MAX_SP_THREADS);
 111
 112        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
 113                            "ia_css_queue_map() enter: buf_type=%d, thread_id=%d\n", buf_type, thread_id);
 114
 115        if (map)
 116                map_buffer_type_to_queue_id(thread_id, buf_type);
 117        else
 118                unmap_buffer_type_to_queue_id(thread_id, buf_type);
 119}
 120
 121/*
 122 * @brief Query the internal queue ID.
 123 */
 124bool ia_css_query_internal_queue_id(
 125    enum ia_css_buffer_type buf_type,
 126    unsigned int thread_id,
 127    enum sh_css_queue_id *val)
 128{
 129        IA_CSS_ENTER("buf_type=%d, thread_id=%d, val = %p", buf_type, thread_id, val);
 130
 131        if ((!val) || (thread_id >= SH_CSS_MAX_SP_THREADS) ||
 132            (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)) {
 133                IA_CSS_LEAVE("return_val = false");
 134                return false;
 135        }
 136
 137        *val = buffer_type_to_queue_id_map[thread_id][buf_type];
 138        if ((*val == SH_CSS_INVALID_QUEUE_ID) || (*val >= SH_CSS_MAX_NUM_QUEUES)) {
 139                IA_CSS_LOG("INVALID queue ID MAP = %d\n", *val);
 140                IA_CSS_LEAVE("return_val = false");
 141                return false;
 142        }
 143        IA_CSS_LEAVE("return_val = true");
 144        return true;
 145}
 146
 147/*******************************************************
 148*** Static functions
 149********************************************************/
 150static void map_buffer_type_to_queue_id(
 151    unsigned int thread_id,
 152    enum ia_css_buffer_type buf_type)
 153{
 154        unsigned int i;
 155
 156        assert(thread_id < SH_CSS_MAX_SP_THREADS);
 157        assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
 158        assert(buffer_type_to_queue_id_map[thread_id][buf_type] ==
 159               SH_CSS_INVALID_QUEUE_ID);
 160
 161        /* queue 0 is reserved for parameters because it doesn't depend on events */
 162        if (buf_type == IA_CSS_BUFFER_TYPE_PARAMETER_SET) {
 163                assert(queue_availability[thread_id][IA_CSS_PARAMETER_SET_QUEUE_ID]);
 164                queue_availability[thread_id][IA_CSS_PARAMETER_SET_QUEUE_ID] = false;
 165                buffer_type_to_queue_id_map[thread_id][buf_type] =
 166                    IA_CSS_PARAMETER_SET_QUEUE_ID;
 167                return;
 168        }
 169
 170        /* queue 1 is reserved for per frame parameters because it doesn't depend on events */
 171        if (buf_type == IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET) {
 172                assert(queue_availability[thread_id][IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID]);
 173                queue_availability[thread_id][IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID] = false;
 174                buffer_type_to_queue_id_map[thread_id][buf_type] =
 175                    IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID;
 176                return;
 177        }
 178
 179        for (i = SH_CSS_QUEUE_C_ID; i < SH_CSS_MAX_NUM_QUEUES; i++) {
 180                if (queue_availability[thread_id][i]) {
 181                        queue_availability[thread_id][i] = false;
 182                        buffer_type_to_queue_id_map[thread_id][buf_type] = i;
 183                        break;
 184                }
 185        }
 186
 187        assert(i != SH_CSS_MAX_NUM_QUEUES);
 188        return;
 189}
 190
 191static void unmap_buffer_type_to_queue_id(
 192    unsigned int thread_id,
 193    enum ia_css_buffer_type buf_type)
 194{
 195        int queue_id;
 196
 197        assert(thread_id < SH_CSS_MAX_SP_THREADS);
 198        assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
 199        assert(buffer_type_to_queue_id_map[thread_id][buf_type] !=
 200               SH_CSS_INVALID_QUEUE_ID);
 201
 202        queue_id = buffer_type_to_queue_id_map[thread_id][buf_type];
 203        buffer_type_to_queue_id_map[thread_id][buf_type] = SH_CSS_INVALID_QUEUE_ID;
 204        queue_availability[thread_id][queue_id] = true;
 205}
 206
 207static ia_css_queue_t *bufq_get_qhandle(
 208    enum sh_css_queue_type type,
 209    enum sh_css_queue_id id,
 210    int thread)
 211{
 212        ia_css_queue_t *q = NULL;
 213
 214        switch (type) {
 215        case sh_css_host2sp_buffer_queue:
 216                if ((thread >= SH_CSS_MAX_SP_THREADS) || (thread < 0) ||
 217                    (id == SH_CSS_INVALID_QUEUE_ID))
 218                        break;
 219                q = &css_queues.host2sp_buffer_queue_handles[thread][id];
 220                break;
 221        case sh_css_sp2host_buffer_queue:
 222                if (id == SH_CSS_INVALID_QUEUE_ID)
 223                        break;
 224                q = &css_queues.sp2host_buffer_queue_handles[id];
 225                break;
 226        case sh_css_host2sp_psys_event_queue:
 227                q = &css_queues.host2sp_psys_event_queue_handle;
 228                break;
 229        case sh_css_sp2host_psys_event_queue:
 230                q = &css_queues.sp2host_psys_event_queue_handle;
 231                break;
 232        case sh_css_host2sp_isys_event_queue:
 233                q = &css_queues.host2sp_isys_event_queue_handle;
 234                break;
 235        case sh_css_sp2host_isys_event_queue:
 236                q = &css_queues.sp2host_isys_event_queue_handle;
 237                break;
 238        case sh_css_host2sp_tag_cmd_queue:
 239                q = &css_queues.host2sp_tag_cmd_queue_handle;
 240                break;
 241        default:
 242                break;
 243        }
 244
 245        return q;
 246}
 247
 248/* Local function to initialize a buffer queue. This reduces
 249 * the chances of copy-paste errors or typos.
 250 */
 251static inline void
 252init_bufq(unsigned int desc_offset,
 253          unsigned int elems_offset,
 254          ia_css_queue_t *handle)
 255{
 256        const struct ia_css_fw_info *fw;
 257        unsigned int q_base_addr;
 258        ia_css_queue_remote_t remoteq;
 259
 260        fw = &sh_css_sp_fw;
 261        q_base_addr = fw->info.sp.host_sp_queue;
 262
 263        /* Setup queue location as SP and proc id as SP0_ID */
 264        remoteq.location = IA_CSS_QUEUE_LOC_SP;
 265        remoteq.proc_id = SP0_ID;
 266        remoteq.cb_desc_addr = q_base_addr + desc_offset;
 267        remoteq.cb_elems_addr = q_base_addr + elems_offset;
 268        /* Initialize the queue instance and obtain handle */
 269        ia_css_queue_remote_init(handle, &remoteq);
 270}
 271
 272void ia_css_bufq_init(void)
 273{
 274        int i, j;
 275
 276        IA_CSS_ENTER_PRIVATE("");
 277
 278        /* Setup all the local queue descriptors for Host2SP Buffer Queues */
 279        for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++)
 280                for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++) {
 281                        init_bufq((uint32_t)offsetof(struct host_sp_queues,
 282                                                     host2sp_buffer_queues_desc[i][j]),
 283                                  (uint32_t)offsetof(struct host_sp_queues, host2sp_buffer_queues_elems[i][j]),
 284                                  &css_queues.host2sp_buffer_queue_handles[i][j]);
 285                }
 286
 287        /* Setup all the local queue descriptors for SP2Host Buffer Queues */
 288        for (i = 0; i < SH_CSS_MAX_NUM_QUEUES; i++) {
 289                init_bufq(offsetof(struct host_sp_queues, sp2host_buffer_queues_desc[i]),
 290                          offsetof(struct host_sp_queues, sp2host_buffer_queues_elems[i]),
 291                          &css_queues.sp2host_buffer_queue_handles[i]);
 292        }
 293
 294        /* Host2SP event queue*/
 295        init_bufq((uint32_t)offsetof(struct host_sp_queues,
 296                                     host2sp_psys_event_queue_desc),
 297                  (uint32_t)offsetof(struct host_sp_queues, host2sp_psys_event_queue_elems),
 298                  &css_queues.host2sp_psys_event_queue_handle);
 299
 300        /* SP2Host event queue */
 301        init_bufq((uint32_t)offsetof(struct host_sp_queues,
 302                                     sp2host_psys_event_queue_desc),
 303                  (uint32_t)offsetof(struct host_sp_queues, sp2host_psys_event_queue_elems),
 304                  &css_queues.sp2host_psys_event_queue_handle);
 305
 306        /* Host2SP ISYS event queue */
 307        init_bufq((uint32_t)offsetof(struct host_sp_queues,
 308                                     host2sp_isys_event_queue_desc),
 309                  (uint32_t)offsetof(struct host_sp_queues, host2sp_isys_event_queue_elems),
 310                  &css_queues.host2sp_isys_event_queue_handle);
 311
 312        /* SP2Host ISYS event queue*/
 313        init_bufq((uint32_t)offsetof(struct host_sp_queues,
 314                                     sp2host_isys_event_queue_desc),
 315                  (uint32_t)offsetof(struct host_sp_queues, sp2host_isys_event_queue_elems),
 316                  &css_queues.sp2host_isys_event_queue_handle);
 317
 318        /* Host2SP tagger command queue */
 319        init_bufq((uint32_t)offsetof(struct host_sp_queues, host2sp_tag_cmd_queue_desc),
 320                  (uint32_t)offsetof(struct host_sp_queues, host2sp_tag_cmd_queue_elems),
 321                  &css_queues.host2sp_tag_cmd_queue_handle);
 322
 323        IA_CSS_LEAVE_PRIVATE("");
 324}
 325
 326int ia_css_bufq_enqueue_buffer(
 327    int thread_index,
 328    int queue_id,
 329    uint32_t item)
 330{
 331        ia_css_queue_t *q;
 332        int error;
 333
 334        IA_CSS_ENTER_PRIVATE("queue_id=%d", queue_id);
 335        if ((thread_index >= SH_CSS_MAX_SP_THREADS) || (thread_index < 0) ||
 336            (queue_id == SH_CSS_INVALID_QUEUE_ID))
 337                return -EINVAL;
 338
 339        /* Get the queue for communication */
 340        q = bufq_get_qhandle(sh_css_host2sp_buffer_queue,
 341                             queue_id,
 342                             thread_index);
 343        if (q) {
 344                error = ia_css_queue_enqueue(q, item);
 345        } else {
 346                IA_CSS_ERROR("queue is not initialized");
 347                error = -EBUSY;
 348        }
 349
 350        IA_CSS_LEAVE_ERR_PRIVATE(error);
 351        return error;
 352}
 353
 354int ia_css_bufq_dequeue_buffer(
 355    int queue_id,
 356    uint32_t *item)
 357{
 358        int error;
 359        ia_css_queue_t *q;
 360
 361        IA_CSS_ENTER_PRIVATE("queue_id=%d", queue_id);
 362        if ((!item) ||
 363            (queue_id <= SH_CSS_INVALID_QUEUE_ID) ||
 364            (queue_id >= SH_CSS_MAX_NUM_QUEUES)
 365           )
 366                return -EINVAL;
 367
 368        q = bufq_get_qhandle(sh_css_sp2host_buffer_queue,
 369                             queue_id,
 370                             -1);
 371        if (q) {
 372                error = ia_css_queue_dequeue(q, item);
 373        } else {
 374                IA_CSS_ERROR("queue is not initialized");
 375                error = -EBUSY;
 376        }
 377
 378        IA_CSS_LEAVE_ERR_PRIVATE(error);
 379        return error;
 380}
 381
 382int ia_css_bufq_enqueue_psys_event(
 383    u8 evt_id,
 384    u8 evt_payload_0,
 385    u8 evt_payload_1,
 386    uint8_t evt_payload_2)
 387{
 388        int error = 0;
 389        ia_css_queue_t *q;
 390
 391        IA_CSS_ENTER_PRIVATE("evt_id=%d", evt_id);
 392        q = bufq_get_qhandle(sh_css_host2sp_psys_event_queue, -1, -1);
 393        if (!q) {
 394                IA_CSS_ERROR("queue is not initialized");
 395                return -EBUSY;
 396        }
 397
 398        error = ia_css_eventq_send(q,
 399                                   evt_id, evt_payload_0, evt_payload_1, evt_payload_2);
 400
 401        IA_CSS_LEAVE_ERR_PRIVATE(error);
 402        return error;
 403}
 404
 405int ia_css_bufq_dequeue_psys_event(
 406    u8 item[BUFQ_EVENT_SIZE])
 407{
 408        int error = 0;
 409        ia_css_queue_t *q;
 410
 411        /* No ENTER/LEAVE in this function since this is polled
 412         * by some test apps. Enablign logging here floods the log
 413         * files which may cause timeouts. */
 414        if (!item)
 415                return -EINVAL;
 416
 417        q = bufq_get_qhandle(sh_css_sp2host_psys_event_queue, -1, -1);
 418        if (!q) {
 419                IA_CSS_ERROR("queue is not initialized");
 420                return -EBUSY;
 421        }
 422        error = ia_css_eventq_recv(q, item);
 423
 424        return error;
 425}
 426
 427int ia_css_bufq_dequeue_isys_event(
 428    u8 item[BUFQ_EVENT_SIZE])
 429{
 430        int error = 0;
 431        ia_css_queue_t *q;
 432
 433        /* No ENTER/LEAVE in this function since this is polled
 434         * by some test apps. Enablign logging here floods the log
 435         * files which may cause timeouts. */
 436        if (!item)
 437                return -EINVAL;
 438
 439        q = bufq_get_qhandle(sh_css_sp2host_isys_event_queue, -1, -1);
 440        if (!q) {
 441                IA_CSS_ERROR("queue is not initialized");
 442                return -EBUSY;
 443        }
 444        error = ia_css_eventq_recv(q, item);
 445        return error;
 446}
 447
 448int ia_css_bufq_enqueue_isys_event(uint8_t evt_id)
 449{
 450        int error = 0;
 451        ia_css_queue_t *q;
 452
 453        IA_CSS_ENTER_PRIVATE("event_id=%d", evt_id);
 454        q = bufq_get_qhandle(sh_css_host2sp_isys_event_queue, -1, -1);
 455        if (!q) {
 456                IA_CSS_ERROR("queue is not initialized");
 457                return -EBUSY;
 458        }
 459
 460        error = ia_css_eventq_send(q, evt_id, 0, 0, 0);
 461
 462        IA_CSS_LEAVE_ERR_PRIVATE(error);
 463        return error;
 464}
 465
 466int ia_css_bufq_enqueue_tag_cmd(
 467    uint32_t item)
 468{
 469        int error;
 470        ia_css_queue_t *q;
 471
 472        IA_CSS_ENTER_PRIVATE("item=%d", item);
 473        q = bufq_get_qhandle(sh_css_host2sp_tag_cmd_queue, -1, -1);
 474        if (!q) {
 475                IA_CSS_ERROR("queue is not initialized");
 476                return -EBUSY;
 477        }
 478        error = ia_css_queue_enqueue(q, item);
 479
 480        IA_CSS_LEAVE_ERR_PRIVATE(error);
 481        return error;
 482}
 483
 484int ia_css_bufq_deinit(void)
 485{
 486        return 0;
 487}
 488
 489static void bufq_dump_queue_info(const char *prefix, ia_css_queue_t *qhandle)
 490{
 491        u32 free = 0, used = 0;
 492
 493        assert(prefix && qhandle);
 494        ia_css_queue_get_used_space(qhandle, &used);
 495        ia_css_queue_get_free_space(qhandle, &free);
 496        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s: used=%u free=%u\n",
 497                            prefix, used, free);
 498}
 499
 500void ia_css_bufq_dump_queue_info(void)
 501{
 502        int i, j;
 503
 504        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "Queue Information:\n");
 505
 506        for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
 507                for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++) {
 508                        snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE,
 509                                 "host2sp_buffer_queue[%u][%u]", i, j);
 510                        bufq_dump_queue_info(prefix,
 511                                             &css_queues.host2sp_buffer_queue_handles[i][j]);
 512                }
 513        }
 514
 515        for (i = 0; i < SH_CSS_MAX_NUM_QUEUES; i++) {
 516                snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE,
 517                         "sp2host_buffer_queue[%u]", i);
 518                bufq_dump_queue_info(prefix,
 519                                     &css_queues.sp2host_buffer_queue_handles[i]);
 520        }
 521        bufq_dump_queue_info("host2sp_psys_event",
 522                             &css_queues.host2sp_psys_event_queue_handle);
 523        bufq_dump_queue_info("sp2host_psys_event",
 524                             &css_queues.sp2host_psys_event_queue_handle);
 525
 526        bufq_dump_queue_info("host2sp_isys_event",
 527                             &css_queues.host2sp_isys_event_queue_handle);
 528        bufq_dump_queue_info("sp2host_isys_event",
 529                             &css_queues.sp2host_isys_event_queue_handle);
 530        bufq_dump_queue_info("host2sp_tag_cmd",
 531                             &css_queues.host2sp_tag_cmd_queue_handle);
 532}
 533