linux/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2014-2019 Intel Corporation
   4 */
   5
   6#include <linux/debugfs.h>
   7
   8#include "gt/intel_gt.h"
   9#include "i915_drv.h"
  10#include "i915_memcpy.h"
  11#include "intel_guc_log.h"
  12
  13static void guc_log_capture_logs(struct intel_guc_log *log);
  14
  15/**
  16 * DOC: GuC firmware log
  17 *
  18 * Firmware log is enabled by setting i915.guc_log_level to the positive level.
  19 * Log data is printed out via reading debugfs i915_guc_log_dump. Reading from
  20 * i915_guc_load_status will print out firmware loading status and scratch
  21 * registers value.
  22 */
  23
  24static int guc_action_flush_log_complete(struct intel_guc *guc)
  25{
  26        u32 action[] = {
  27                INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE
  28        };
  29
  30        return intel_guc_send(guc, action, ARRAY_SIZE(action));
  31}
  32
  33static int guc_action_flush_log(struct intel_guc *guc)
  34{
  35        u32 action[] = {
  36                INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH,
  37                0
  38        };
  39
  40        return intel_guc_send(guc, action, ARRAY_SIZE(action));
  41}
  42
  43static int guc_action_control_log(struct intel_guc *guc, bool enable,
  44                                  bool default_logging, u32 verbosity)
  45{
  46        u32 action[] = {
  47                INTEL_GUC_ACTION_UK_LOG_ENABLE_LOGGING,
  48                (enable ? GUC_LOG_CONTROL_LOGGING_ENABLED : 0) |
  49                (verbosity << GUC_LOG_CONTROL_VERBOSITY_SHIFT) |
  50                (default_logging ? GUC_LOG_CONTROL_DEFAULT_LOGGING : 0)
  51        };
  52
  53        GEM_BUG_ON(verbosity > GUC_LOG_VERBOSITY_MAX);
  54
  55        return intel_guc_send(guc, action, ARRAY_SIZE(action));
  56}
  57
  58static void guc_log_enable_flush_events(struct intel_guc_log *log)
  59{
  60        intel_guc_enable_msg(log_to_guc(log),
  61                             INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
  62                             INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
  63}
  64
  65static void guc_log_disable_flush_events(struct intel_guc_log *log)
  66{
  67        intel_guc_disable_msg(log_to_guc(log),
  68                              INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
  69                              INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
  70}
  71
  72/*
  73 * Sub buffer switch callback. Called whenever relay has to switch to a new
  74 * sub buffer, relay stays on the same sub buffer if 0 is returned.
  75 */
  76static int subbuf_start_callback(struct rchan_buf *buf,
  77                                 void *subbuf,
  78                                 void *prev_subbuf,
  79                                 size_t prev_padding)
  80{
  81        /*
  82         * Use no-overwrite mode by default, where relay will stop accepting
  83         * new data if there are no empty sub buffers left.
  84         * There is no strict synchronization enforced by relay between Consumer
  85         * and Producer. In overwrite mode, there is a possibility of getting
  86         * inconsistent/garbled data, the producer could be writing on to the
  87         * same sub buffer from which Consumer is reading. This can't be avoided
  88         * unless Consumer is fast enough and can always run in tandem with
  89         * Producer.
  90         */
  91        if (relay_buf_full(buf))
  92                return 0;
  93
  94        return 1;
  95}
  96
  97/*
  98 * file_create() callback. Creates relay file in debugfs.
  99 */
 100static struct dentry *create_buf_file_callback(const char *filename,
 101                                               struct dentry *parent,
 102                                               umode_t mode,
 103                                               struct rchan_buf *buf,
 104                                               int *is_global)
 105{
 106        struct dentry *buf_file;
 107
 108        /*
 109         * This to enable the use of a single buffer for the relay channel and
 110         * correspondingly have a single file exposed to User, through which
 111         * it can collect the logs in order without any post-processing.
 112         * Need to set 'is_global' even if parent is NULL for early logging.
 113         */
 114        *is_global = 1;
 115
 116        if (!parent)
 117                return NULL;
 118
 119        buf_file = debugfs_create_file(filename, mode,
 120                                       parent, buf, &relay_file_operations);
 121        if (IS_ERR(buf_file))
 122                return NULL;
 123
 124        return buf_file;
 125}
 126
 127/*
 128 * file_remove() default callback. Removes relay file in debugfs.
 129 */
 130static int remove_buf_file_callback(struct dentry *dentry)
 131{
 132        debugfs_remove(dentry);
 133        return 0;
 134}
 135
 136/* relay channel callbacks */
 137static const struct rchan_callbacks relay_callbacks = {
 138        .subbuf_start = subbuf_start_callback,
 139        .create_buf_file = create_buf_file_callback,
 140        .remove_buf_file = remove_buf_file_callback,
 141};
 142
 143static void guc_move_to_next_buf(struct intel_guc_log *log)
 144{
 145        /*
 146         * Make sure the updates made in the sub buffer are visible when
 147         * Consumer sees the following update to offset inside the sub buffer.
 148         */
 149        smp_wmb();
 150
 151        /* All data has been written, so now move the offset of sub buffer. */
 152        relay_reserve(log->relay.channel, log->vma->obj->base.size);
 153
 154        /* Switch to the next sub buffer */
 155        relay_flush(log->relay.channel);
 156}
 157
 158static void *guc_get_write_buffer(struct intel_guc_log *log)
 159{
 160        /*
 161         * Just get the base address of a new sub buffer and copy data into it
 162         * ourselves. NULL will be returned in no-overwrite mode, if all sub
 163         * buffers are full. Could have used the relay_write() to indirectly
 164         * copy the data, but that would have been bit convoluted, as we need to
 165         * write to only certain locations inside a sub buffer which cannot be
 166         * done without using relay_reserve() along with relay_write(). So its
 167         * better to use relay_reserve() alone.
 168         */
 169        return relay_reserve(log->relay.channel, 0);
 170}
 171
 172static bool guc_check_log_buf_overflow(struct intel_guc_log *log,
 173                                       enum guc_log_buffer_type type,
 174                                       unsigned int full_cnt)
 175{
 176        unsigned int prev_full_cnt = log->stats[type].sampled_overflow;
 177        bool overflow = false;
 178
 179        if (full_cnt != prev_full_cnt) {
 180                overflow = true;
 181
 182                log->stats[type].overflow = full_cnt;
 183                log->stats[type].sampled_overflow += full_cnt - prev_full_cnt;
 184
 185                if (full_cnt < prev_full_cnt) {
 186                        /* buffer_full_cnt is a 4 bit counter */
 187                        log->stats[type].sampled_overflow += 16;
 188                }
 189
 190                dev_notice_ratelimited(guc_to_gt(log_to_guc(log))->i915->drm.dev,
 191                                       "GuC log buffer overflow\n");
 192        }
 193
 194        return overflow;
 195}
 196
 197static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type)
 198{
 199        switch (type) {
 200        case GUC_ISR_LOG_BUFFER:
 201                return ISR_BUFFER_SIZE;
 202        case GUC_DPC_LOG_BUFFER:
 203                return DPC_BUFFER_SIZE;
 204        case GUC_CRASH_DUMP_LOG_BUFFER:
 205                return CRASH_BUFFER_SIZE;
 206        default:
 207                MISSING_CASE(type);
 208        }
 209
 210        return 0;
 211}
 212
 213static void guc_read_update_log_buffer(struct intel_guc_log *log)
 214{
 215        unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt;
 216        struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state;
 217        struct guc_log_buffer_state log_buf_state_local;
 218        enum guc_log_buffer_type type;
 219        void *src_data, *dst_data;
 220        bool new_overflow;
 221
 222        mutex_lock(&log->relay.lock);
 223
 224        if (WARN_ON(!intel_guc_log_relay_created(log)))
 225                goto out_unlock;
 226
 227        /* Get the pointer to shared GuC log buffer */
 228        log_buf_state = src_data = log->relay.buf_addr;
 229
 230        /* Get the pointer to local buffer to store the logs */
 231        log_buf_snapshot_state = dst_data = guc_get_write_buffer(log);
 232
 233        if (unlikely(!log_buf_snapshot_state)) {
 234                /*
 235                 * Used rate limited to avoid deluge of messages, logs might be
 236                 * getting consumed by User at a slow rate.
 237                 */
 238                DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n");
 239                log->relay.full_count++;
 240
 241                goto out_unlock;
 242        }
 243
 244        /* Actual logs are present from the 2nd page */
 245        src_data += PAGE_SIZE;
 246        dst_data += PAGE_SIZE;
 247
 248        for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
 249                /*
 250                 * Make a copy of the state structure, inside GuC log buffer
 251                 * (which is uncached mapped), on the stack to avoid reading
 252                 * from it multiple times.
 253                 */
 254                memcpy(&log_buf_state_local, log_buf_state,
 255                       sizeof(struct guc_log_buffer_state));
 256                buffer_size = guc_get_log_buffer_size(type);
 257                read_offset = log_buf_state_local.read_ptr;
 258                write_offset = log_buf_state_local.sampled_write_ptr;
 259                full_cnt = log_buf_state_local.buffer_full_cnt;
 260
 261                /* Bookkeeping stuff */
 262                log->stats[type].flush += log_buf_state_local.flush_to_file;
 263                new_overflow = guc_check_log_buf_overflow(log, type, full_cnt);
 264
 265                /* Update the state of shared log buffer */
 266                log_buf_state->read_ptr = write_offset;
 267                log_buf_state->flush_to_file = 0;
 268                log_buf_state++;
 269
 270                /* First copy the state structure in snapshot buffer */
 271                memcpy(log_buf_snapshot_state, &log_buf_state_local,
 272                       sizeof(struct guc_log_buffer_state));
 273
 274                /*
 275                 * The write pointer could have been updated by GuC firmware,
 276                 * after sending the flush interrupt to Host, for consistency
 277                 * set write pointer value to same value of sampled_write_ptr
 278                 * in the snapshot buffer.
 279                 */
 280                log_buf_snapshot_state->write_ptr = write_offset;
 281                log_buf_snapshot_state++;
 282
 283                /* Now copy the actual logs. */
 284                if (unlikely(new_overflow)) {
 285                        /* copy the whole buffer in case of overflow */
 286                        read_offset = 0;
 287                        write_offset = buffer_size;
 288                } else if (unlikely((read_offset > buffer_size) ||
 289                                    (write_offset > buffer_size))) {
 290                        DRM_ERROR("invalid log buffer state\n");
 291                        /* copy whole buffer as offsets are unreliable */
 292                        read_offset = 0;
 293                        write_offset = buffer_size;
 294                }
 295
 296                /* Just copy the newly written data */
 297                if (read_offset > write_offset) {
 298                        i915_memcpy_from_wc(dst_data, src_data, write_offset);
 299                        bytes_to_copy = buffer_size - read_offset;
 300                } else {
 301                        bytes_to_copy = write_offset - read_offset;
 302                }
 303                i915_memcpy_from_wc(dst_data + read_offset,
 304                                    src_data + read_offset, bytes_to_copy);
 305
 306                src_data += buffer_size;
 307                dst_data += buffer_size;
 308        }
 309
 310        guc_move_to_next_buf(log);
 311
 312out_unlock:
 313        mutex_unlock(&log->relay.lock);
 314}
 315
 316static void capture_logs_work(struct work_struct *work)
 317{
 318        struct intel_guc_log *log =
 319                container_of(work, struct intel_guc_log, relay.flush_work);
 320
 321        guc_log_capture_logs(log);
 322}
 323
 324static int guc_log_map(struct intel_guc_log *log)
 325{
 326        void *vaddr;
 327
 328        lockdep_assert_held(&log->relay.lock);
 329
 330        if (!log->vma)
 331                return -ENODEV;
 332
 333        /*
 334         * Create a WC (Uncached for read) vmalloc mapping of log
 335         * buffer pages, so that we can directly get the data
 336         * (up-to-date) from memory.
 337         */
 338        vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC);
 339        if (IS_ERR(vaddr))
 340                return PTR_ERR(vaddr);
 341
 342        log->relay.buf_addr = vaddr;
 343
 344        return 0;
 345}
 346
 347static void guc_log_unmap(struct intel_guc_log *log)
 348{
 349        lockdep_assert_held(&log->relay.lock);
 350
 351        i915_gem_object_unpin_map(log->vma->obj);
 352        log->relay.buf_addr = NULL;
 353}
 354
 355void intel_guc_log_init_early(struct intel_guc_log *log)
 356{
 357        mutex_init(&log->relay.lock);
 358        INIT_WORK(&log->relay.flush_work, capture_logs_work);
 359        log->relay.started = false;
 360}
 361
 362static int guc_log_relay_create(struct intel_guc_log *log)
 363{
 364        struct intel_guc *guc = log_to_guc(log);
 365        struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
 366        struct rchan *guc_log_relay_chan;
 367        size_t n_subbufs, subbuf_size;
 368        int ret;
 369
 370        lockdep_assert_held(&log->relay.lock);
 371        GEM_BUG_ON(!log->vma);
 372
 373         /* Keep the size of sub buffers same as shared log buffer */
 374        subbuf_size = log->vma->size;
 375
 376        /*
 377         * Store up to 8 snapshots, which is large enough to buffer sufficient
 378         * boot time logs and provides enough leeway to User, in terms of
 379         * latency, for consuming the logs from relay. Also doesn't take
 380         * up too much memory.
 381         */
 382        n_subbufs = 8;
 383
 384        guc_log_relay_chan = relay_open("guc_log",
 385                                        dev_priv->drm.primary->debugfs_root,
 386                                        subbuf_size, n_subbufs,
 387                                        &relay_callbacks, dev_priv);
 388        if (!guc_log_relay_chan) {
 389                DRM_ERROR("Couldn't create relay chan for GuC logging\n");
 390
 391                ret = -ENOMEM;
 392                return ret;
 393        }
 394
 395        GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size);
 396        log->relay.channel = guc_log_relay_chan;
 397
 398        return 0;
 399}
 400
 401static void guc_log_relay_destroy(struct intel_guc_log *log)
 402{
 403        lockdep_assert_held(&log->relay.lock);
 404
 405        relay_close(log->relay.channel);
 406        log->relay.channel = NULL;
 407}
 408
 409static void guc_log_capture_logs(struct intel_guc_log *log)
 410{
 411        struct intel_guc *guc = log_to_guc(log);
 412        struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
 413        intel_wakeref_t wakeref;
 414
 415        guc_read_update_log_buffer(log);
 416
 417        /*
 418         * Generally device is expected to be active only at this
 419         * time, so get/put should be really quick.
 420         */
 421        with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
 422                guc_action_flush_log_complete(guc);
 423}
 424
 425static u32 __get_default_log_level(struct intel_guc_log *log)
 426{
 427        struct intel_guc *guc = log_to_guc(log);
 428        struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
 429
 430        /* A negative value means "use platform/config default" */
 431        if (i915->params.guc_log_level < 0) {
 432                return (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
 433                        IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) ?
 434                        GUC_LOG_LEVEL_MAX : GUC_LOG_LEVEL_NON_VERBOSE;
 435        }
 436
 437        if (i915->params.guc_log_level > GUC_LOG_LEVEL_MAX) {
 438                DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
 439                         "guc_log_level", i915->params.guc_log_level,
 440                         "verbosity too high");
 441                return (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
 442                        IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) ?
 443                        GUC_LOG_LEVEL_MAX : GUC_LOG_LEVEL_DISABLED;
 444        }
 445
 446        GEM_BUG_ON(i915->params.guc_log_level < GUC_LOG_LEVEL_DISABLED);
 447        GEM_BUG_ON(i915->params.guc_log_level > GUC_LOG_LEVEL_MAX);
 448        return i915->params.guc_log_level;
 449}
 450
 451int intel_guc_log_create(struct intel_guc_log *log)
 452{
 453        struct intel_guc *guc = log_to_guc(log);
 454        struct i915_vma *vma;
 455        u32 guc_log_size;
 456        int ret;
 457
 458        GEM_BUG_ON(log->vma);
 459
 460        /*
 461         *  GuC Log buffer Layout
 462         *
 463         *  +===============================+ 00B
 464         *  |    Crash dump state header    |
 465         *  +-------------------------------+ 32B
 466         *  |       DPC state header        |
 467         *  +-------------------------------+ 64B
 468         *  |       ISR state header        |
 469         *  +-------------------------------+ 96B
 470         *  |                               |
 471         *  +===============================+ PAGE_SIZE (4KB)
 472         *  |        Crash Dump logs        |
 473         *  +===============================+ + CRASH_SIZE
 474         *  |           DPC logs            |
 475         *  +===============================+ + DPC_SIZE
 476         *  |           ISR logs            |
 477         *  +===============================+ + ISR_SIZE
 478         */
 479        guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DPC_BUFFER_SIZE +
 480                        ISR_BUFFER_SIZE;
 481
 482        vma = intel_guc_allocate_vma(guc, guc_log_size);
 483        if (IS_ERR(vma)) {
 484                ret = PTR_ERR(vma);
 485                goto err;
 486        }
 487
 488        log->vma = vma;
 489
 490        log->level = __get_default_log_level(log);
 491        DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n",
 492                         log->level, enableddisabled(log->level),
 493                         yesno(GUC_LOG_LEVEL_IS_VERBOSE(log->level)),
 494                         GUC_LOG_LEVEL_TO_VERBOSITY(log->level));
 495
 496        return 0;
 497
 498err:
 499        DRM_ERROR("Failed to allocate GuC log buffer. %d\n", ret);
 500        return ret;
 501}
 502
 503void intel_guc_log_destroy(struct intel_guc_log *log)
 504{
 505        i915_vma_unpin_and_release(&log->vma, 0);
 506}
 507
 508int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 509{
 510        struct intel_guc *guc = log_to_guc(log);
 511        struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
 512        intel_wakeref_t wakeref;
 513        int ret = 0;
 514
 515        BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0);
 516        GEM_BUG_ON(!log->vma);
 517
 518        /*
 519         * GuC is recognizing log levels starting from 0 to max, we're using 0
 520         * as indication that logging should be disabled.
 521         */
 522        if (level < GUC_LOG_LEVEL_DISABLED || level > GUC_LOG_LEVEL_MAX)
 523                return -EINVAL;
 524
 525        mutex_lock(&dev_priv->drm.struct_mutex);
 526
 527        if (log->level == level)
 528                goto out_unlock;
 529
 530        with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
 531                ret = guc_action_control_log(guc,
 532                                             GUC_LOG_LEVEL_IS_VERBOSE(level),
 533                                             GUC_LOG_LEVEL_IS_ENABLED(level),
 534                                             GUC_LOG_LEVEL_TO_VERBOSITY(level));
 535        if (ret) {
 536                DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
 537                goto out_unlock;
 538        }
 539
 540        log->level = level;
 541
 542out_unlock:
 543        mutex_unlock(&dev_priv->drm.struct_mutex);
 544
 545        return ret;
 546}
 547
 548bool intel_guc_log_relay_created(const struct intel_guc_log *log)
 549{
 550        return log->relay.buf_addr;
 551}
 552
 553int intel_guc_log_relay_open(struct intel_guc_log *log)
 554{
 555        int ret;
 556
 557        if (!log->vma)
 558                return -ENODEV;
 559
 560        mutex_lock(&log->relay.lock);
 561
 562        if (intel_guc_log_relay_created(log)) {
 563                ret = -EEXIST;
 564                goto out_unlock;
 565        }
 566
 567        /*
 568         * We require SSE 4.1 for fast reads from the GuC log buffer and
 569         * it should be present on the chipsets supporting GuC based
 570         * submisssions.
 571         */
 572        if (!i915_has_memcpy_from_wc()) {
 573                ret = -ENXIO;
 574                goto out_unlock;
 575        }
 576
 577        ret = guc_log_relay_create(log);
 578        if (ret)
 579                goto out_unlock;
 580
 581        ret = guc_log_map(log);
 582        if (ret)
 583                goto out_relay;
 584
 585        mutex_unlock(&log->relay.lock);
 586
 587        return 0;
 588
 589out_relay:
 590        guc_log_relay_destroy(log);
 591out_unlock:
 592        mutex_unlock(&log->relay.lock);
 593
 594        return ret;
 595}
 596
 597int intel_guc_log_relay_start(struct intel_guc_log *log)
 598{
 599        if (log->relay.started)
 600                return -EEXIST;
 601
 602        guc_log_enable_flush_events(log);
 603
 604        /*
 605         * When GuC is logging without us relaying to userspace, we're ignoring
 606         * the flush notification. This means that we need to unconditionally
 607         * flush on relay enabling, since GuC only notifies us once.
 608         */
 609        queue_work(system_highpri_wq, &log->relay.flush_work);
 610
 611        log->relay.started = true;
 612
 613        return 0;
 614}
 615
 616void intel_guc_log_relay_flush(struct intel_guc_log *log)
 617{
 618        struct intel_guc *guc = log_to_guc(log);
 619        intel_wakeref_t wakeref;
 620
 621        if (!log->relay.started)
 622                return;
 623
 624        /*
 625         * Before initiating the forceful flush, wait for any pending/ongoing
 626         * flush to complete otherwise forceful flush may not actually happen.
 627         */
 628        flush_work(&log->relay.flush_work);
 629
 630        with_intel_runtime_pm(guc_to_gt(guc)->uncore->rpm, wakeref)
 631                guc_action_flush_log(guc);
 632
 633        /* GuC would have updated log buffer by now, so capture it */
 634        guc_log_capture_logs(log);
 635}
 636
 637/*
 638 * Stops the relay log. Called from intel_guc_log_relay_close(), so no
 639 * possibility of race with start/flush since relay_write cannot race
 640 * relay_close.
 641 */
 642static void guc_log_relay_stop(struct intel_guc_log *log)
 643{
 644        struct intel_guc *guc = log_to_guc(log);
 645        struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
 646
 647        if (!log->relay.started)
 648                return;
 649
 650        guc_log_disable_flush_events(log);
 651        intel_synchronize_irq(i915);
 652
 653        flush_work(&log->relay.flush_work);
 654
 655        log->relay.started = false;
 656}
 657
 658void intel_guc_log_relay_close(struct intel_guc_log *log)
 659{
 660        guc_log_relay_stop(log);
 661
 662        mutex_lock(&log->relay.lock);
 663        GEM_BUG_ON(!intel_guc_log_relay_created(log));
 664        guc_log_unmap(log);
 665        guc_log_relay_destroy(log);
 666        mutex_unlock(&log->relay.lock);
 667}
 668
 669void intel_guc_log_handle_flush_event(struct intel_guc_log *log)
 670{
 671        queue_work(system_highpri_wq, &log->relay.flush_work);
 672}
 673
 674static const char *
 675stringify_guc_log_type(enum guc_log_buffer_type type)
 676{
 677        switch (type) {
 678        case GUC_ISR_LOG_BUFFER:
 679                return "ISR";
 680        case GUC_DPC_LOG_BUFFER:
 681                return "DPC";
 682        case GUC_CRASH_DUMP_LOG_BUFFER:
 683                return "CRASH";
 684        default:
 685                MISSING_CASE(type);
 686        }
 687
 688        return "";
 689}
 690
 691/**
 692 * intel_guc_log_info - dump information about GuC log relay
 693 * @log: the GuC log
 694 * @p: the &drm_printer
 695 *
 696 * Pretty printer for GuC log info
 697 */
 698void intel_guc_log_info(struct intel_guc_log *log, struct drm_printer *p)
 699{
 700        enum guc_log_buffer_type type;
 701
 702        if (!intel_guc_log_relay_created(log)) {
 703                drm_puts(p, "GuC log relay not created\n");
 704                return;
 705        }
 706
 707        drm_puts(p, "GuC logging stats:\n");
 708
 709        drm_printf(p, "\tRelay full count: %u\n", log->relay.full_count);
 710
 711        for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
 712                drm_printf(p, "\t%s:\tflush count %10u, overflow count %10u\n",
 713                           stringify_guc_log_type(type),
 714                           log->stats[type].flush,
 715                           log->stats[type].sampled_overflow);
 716        }
 717}
 718
 719/**
 720 * intel_guc_log_dump - dump the contents of the GuC log
 721 * @log: the GuC log
 722 * @p: the &drm_printer
 723 * @dump_load_err: dump the log saved on GuC load error
 724 *
 725 * Pretty printer for the GuC log
 726 */
 727int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p,
 728                       bool dump_load_err)
 729{
 730        struct intel_guc *guc = log_to_guc(log);
 731        struct intel_uc *uc = container_of(guc, struct intel_uc, guc);
 732        struct drm_i915_gem_object *obj = NULL;
 733        u32 *map;
 734        int i = 0;
 735
 736        if (!intel_guc_is_supported(guc))
 737                return -ENODEV;
 738
 739        if (dump_load_err)
 740                obj = uc->load_err_log;
 741        else if (guc->log.vma)
 742                obj = guc->log.vma->obj;
 743
 744        if (!obj)
 745                return 0;
 746
 747        map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC);
 748        if (IS_ERR(map)) {
 749                DRM_DEBUG("Failed to pin object\n");
 750                drm_puts(p, "(log data unaccessible)\n");
 751                return PTR_ERR(map);
 752        }
 753
 754        for (i = 0; i < obj->base.size / sizeof(u32); i += 4)
 755                drm_printf(p, "0x%08x 0x%08x 0x%08x 0x%08x\n",
 756                           *(map + i), *(map + i + 1),
 757                           *(map + i + 2), *(map + i + 3));
 758
 759        drm_puts(p, "\n");
 760
 761        i915_gem_object_unpin_map(obj);
 762
 763        return 0;
 764}
 765