[Intel-gfx] [RFC] drm/i915/guc: Enable guc logging on guc log relay write
Daniele Ceraolo Spurio
daniele.ceraolospurio at intel.com
Wed Sep 11 00:48:07 UTC 2019
On 9/10/19 3:46 PM, Robert M. Fosha wrote:
> Creating and opening the GuC log relay file enables and starts
> the relay potentially before the caller is ready to consume logs.
> Change the behavior so that relay starts only on an explicit call
> to the write function (with a value of '1'). Other values flush
> the log relay as before.
>
> Cc: Matthew Brost <matthew.brost at intel.com>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
> Signed-off-by: Robert M. Fosha <robert.m.fosha at intel.com>
> ---
> drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 38 +++++++++++++++++-----
> drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 2 ++
> drivers/gpu/drm/i915/i915_debugfs.c | 27 +++++++++++++--
> 3 files changed, 56 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
> index 36332064de9c..9a98270d05b6 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
> @@ -361,6 +361,7 @@ void intel_guc_log_init_early(struct intel_guc_log *log)
> {
> mutex_init(&log->relay.lock);
> INIT_WORK(&log->relay.flush_work, capture_logs_work);
> + log->relay_started = false;
> }
>
> static int guc_log_relay_create(struct intel_guc_log *log)
> @@ -585,15 +586,6 @@ int intel_guc_log_relay_open(struct intel_guc_log *log)
>
> mutex_unlock(&log->relay.lock);
>
> - guc_log_enable_flush_events(log);
> -
> - /*
> - * When GuC is logging without us relaying to userspace, we're ignoring
> - * the flush notification. This means that we need to unconditionally
> - * flush on relay enabling, since GuC only notifies us once.
> - */
> - queue_work(system_highpri_wq, &log->relay.flush_work);
> -
> return 0;
>
> out_relay:
> @@ -604,12 +596,38 @@ int intel_guc_log_relay_open(struct intel_guc_log *log)
> return ret;
> }
>
> +int intel_guc_log_relay_start(struct intel_guc_log *log)
> +{
> + int ret = 0;
> +
> + if (log->relay_started) {
> + ret = -EEXIST;
> + } else {
style: for this kind of checks, we usually just return early instead of
using an if-else, i.e.:
if (log->relay_started)
return -EEXIST;
[...] /* code */
return 0;
> + guc_log_enable_flush_events(log);
> +
> + /*
> + * When GuC is logging without us relaying to userspace, we're
> + * ignoring the flush notification. This means that we need to
> + * unconditionally * flush on relay enabling, since GuC only
stray "*"
> + * notifies us once.
> + */
> + queue_work(system_highpri_wq, &log->relay.flush_work);
> +
> + log->relay_started = false;
s/false/true/
> + }
> +
> + return ret;
> +}
> +
> void intel_guc_log_relay_flush(struct intel_guc_log *log)
> {
> struct intel_guc *guc = log_to_guc(log);
> struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
> intel_wakeref_t wakeref;
>
> + if (!log->relay_started)
> + return;
> +
> /*
> * Before initiating the forceful flush, wait for any pending/ongoing
> * flush to complete otherwise forceful flush may not actually happen.
> @@ -638,6 +656,8 @@ void intel_guc_log_relay_close(struct intel_guc_log *log)
> guc_log_unmap(log);
> guc_log_relay_destroy(log);
> mutex_unlock(&log->relay.lock);
> +
> + log->relay_started = false;
For symmetry, it might be worth adding a guc_log_relay_stop:
static void guc_log_relay_stop(...)
{
if (!log->relay_started)
return;
guc_log_disable_flush_events(log);
intel_synchronize_irq(i915);
flush_work(&log->relay.flush_work);
log->relay_started = false;
}
and call it from intel_guc_log_relay_close().
Also, it should be impossible to race the start/flush with the stop
because the relay_write can't race the relay_close, but it might be
worth a comment in case we decide to have guc_log_relay_stop() callable
from the debugfs in the future.
> }
>
> void intel_guc_log_handle_flush_event(struct intel_guc_log *log)
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
> index 6f764879acb1..ecf7a49416b4 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h
> @@ -44,6 +44,7 @@ struct intel_guc;
>
> struct intel_guc_log {
> u32 level;
> + bool relay_started;
this should move inside the relay structure below. Just "started" will
be enough as a name at that point because the structure is already
called relay.
> struct i915_vma *vma;
> struct {
> void *buf_addr;
> @@ -67,6 +68,7 @@ void intel_guc_log_destroy(struct intel_guc_log *log);
> int intel_guc_log_set_level(struct intel_guc_log *log, u32 level);
> bool intel_guc_log_relay_enabled(const struct intel_guc_log *log);
intel_guc_log_relay_enabled() implied both created and started before,
but now that you're splitting that in 2 separate states you'll need to
account for that. From a quick look, all the callers seem to just care
about the buffers being allocated, so a rename should be enough.
> int intel_guc_log_relay_open(struct intel_guc_log *log);
> +int intel_guc_log_relay_start(struct intel_guc_log *log);
> void intel_guc_log_relay_flush(struct intel_guc_log *log);
> void intel_guc_log_relay_close(struct intel_guc_log *log);
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 708855e051b5..c3683fdd0deb 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2049,9 +2049,32 @@ i915_guc_log_relay_write(struct file *filp,
> loff_t *ppos)
> {
> struct intel_guc_log *log = filp->private_data;
> + char *input_buffer;
> + int val;
> + int ret;
>
> - intel_guc_log_relay_flush(log);
> - return cnt;
> + input_buffer = memdup_user_nul(ubuf, cnt);
> + if (IS_ERR(input_buffer))
> + return PTR_ERR(input_buffer);
> +
> + ret = kstrtoint(input_buffer, 10, &val);
> + if (ret < 0)
> + goto out;
> +
you can use kstrtoint_from_user to convert user input to int directly,
without having to copy to a temp buf.
> + /*
> + * Enable and start the guc log relay on value of 1.
> + * Flush log relay for any other value.
> + */
> + if (val == 1) {
> + ret = intel_guc_log_relay_start(log);
> + } else {
> + intel_guc_log_relay_flush(log);
> + ret = cnt;
> + }
> +
> +out:
> + kfree(input_buffer);
> + return ret;
Probably better to always return cnt in case of success, i.e:
return ret ?: cnt;
And remove the ret = cnt above.
Daniele
> }
>
> static int i915_guc_log_relay_release(struct inode *inode, struct file *file)
>
More information about the Intel-gfx
mailing list