diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 8cdcc459884f8..ac8fe8bd97aae 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -915,15 +915,16 @@ static struct dentry *create_buf_file_callback(const char *filename, { struct dentry *buf_file; - if (!parent) - return NULL; - /* This to enable the use of a single buffer for the relay channel and * correspondingly have a single file exposed to User, through which * it can collect the logs in order without any post-processing. + * Need to set 'is_global' even if parent is NULL for early logging. */ *is_global = 1; + if (!parent) + return NULL; + /* Not using the channel filename passed as an argument, since for each * channel relay appends the corresponding CPU number to the filename * passed in relay_open(). This should be fine as relay just needs a @@ -956,13 +957,40 @@ static void guc_log_remove_relay_file(struct intel_guc *guc) relay_close(guc->log.relay_chan); } -static int guc_log_create_relay_file(struct intel_guc *guc) +static int guc_log_create_relay_channel(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); struct rchan *guc_log_relay_chan; - struct dentry *log_dir; size_t n_subbufs, subbuf_size; + /* Keep the size of sub buffers same as shared log buffer */ + subbuf_size = guc->log.vma->obj->base.size; + + /* Store up to 8 snapshots, which is large enough to buffer sufficient + * boot time logs and provides enough leeway to User, in terms of + * latency, for consuming the logs from relay. Also doesn't take + * up too much memory. + */ + n_subbufs = 8; + + guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size, + n_subbufs, &relay_callbacks, dev_priv); + if (!guc_log_relay_chan) { + DRM_ERROR("Couldn't create relay chan for GuC logging\n"); + return -ENOMEM; + } + + GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); + guc->log.relay_chan = guc_log_relay_chan; + return 0; +} + +static int guc_log_create_relay_file(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct dentry *log_dir; + int ret; + /* For now create the log file in /sys/kernel/debug/dri/0 dir */ log_dir = dev_priv->drm.primary->debugfs_root; @@ -982,26 +1010,12 @@ static int guc_log_create_relay_file(struct intel_guc *guc) return -ENODEV; } - /* Keep the size of sub buffers same as shared log buffer */ - subbuf_size = guc->log.vma->obj->base.size; - - /* Store up to 8 snapshots, which is large enough to buffer sufficient - * boot time logs and provides enough leeway to User, in terms of - * latency, for consuming the logs from relay. Also doesn't take - * up too much memory. - */ - n_subbufs = 8; - - guc_log_relay_chan = relay_open("guc_log", log_dir, subbuf_size, - n_subbufs, &relay_callbacks, dev_priv); - if (!guc_log_relay_chan) { - DRM_ERROR("Couldn't create relay chan for GuC logging\n"); - return -ENOMEM; + ret = relay_late_setup_files(guc->log.relay_chan, "guc_log", log_dir); + if (ret) { + DRM_ERROR("Couldn't associate relay chan with file %d\n", ret); + return ret; } - GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size); - /* FIXME: Cover the update under a lock ? */ - guc->log.relay_chan = guc_log_relay_chan; return 0; } @@ -1021,7 +1035,6 @@ static void guc_move_to_next_buf(struct intel_guc *guc) static void *guc_get_write_buffer(struct intel_guc *guc) { - /* FIXME: Cover the check under a lock ? */ if (!guc->log.relay_chan) return NULL; @@ -1231,6 +1244,16 @@ static int guc_log_create_extras(struct intel_guc *guc) guc->log.buf_addr = vaddr; } + if (!guc->log.relay_chan) { + /* Create a relay channel, so that we have buffers for storing + * the GuC firmware logs, the channel will be linked with a file + * later on when debugfs is registered. + */ + ret = guc_log_create_relay_channel(guc); + if (ret) + return ret; + } + if (!guc->log.flush_wq) { INIT_WORK(&guc->log.flush_work, guc_capture_logs_work);