All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dixit, Ashutosh" <ashutosh.dixit@intel.com>
To: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH] drm/i915/perf: Do not clear pollin for small user read buffers
Date: Thu, 26 Mar 2020 20:39:15 -0700	[thread overview]
Message-ID: <87zhc2sbz0.wl-ashutosh.dixit@intel.com> (raw)
In-Reply-To: <60dd3f4f-7728-89eb-d582-19232967a8bb@intel.com>

On Thu, 26 Mar 2020 02:09:34 -0700, Lionel Landwerlin wrote:
>
> On 26/03/2020 06:43, Ashutosh Dixit wrote:
> > It is wrong to block the user thread in the next poll when OA data is
> > already available which could not fit in the user buffer provided in
> > the previous read. In several cases the exact user buffer size is not
> > known. Blocking user space in poll can lead to data loss when the
> > buffer size used is smaller than the available data.
> >
> > This change fixes this issue and allows user space to read all OA data
> > even when using a buffer size smaller than the available data using
> > multiple non-blocking reads rather than staying blocked in poll till
> > the next timer interrupt.
> >
> > v2: Fix ret value for blocking reads (Umesh)
> >
> > Cc: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
> > Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> > Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_perf.c | 63 ++++++--------------------------
> >   1 file changed, 12 insertions(+), 51 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
> > index 3222f6cd8255..e2d083efba6d 100644
> > --- a/drivers/gpu/drm/i915/i915_perf.c
> > +++ b/drivers/gpu/drm/i915/i915_perf.c
> > @@ -2957,49 +2957,6 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
> >		gen8_update_reg_state_unlocked(ce, stream);
> >   }
> >   -/**
> > - * i915_perf_read_locked - &i915_perf_stream_ops->read with error normalisation
> > - * @stream: An i915 perf stream
> > - * @file: An i915 perf stream file
> > - * @buf: destination buffer given by userspace
> > - * @count: the number of bytes userspace wants to read
> > - * @ppos: (inout) file seek position (unused)
> > - *
> > - * Besides wrapping &i915_perf_stream_ops->read this provides a common place to
> > - * ensure that if we've successfully copied any data then reporting that takes
> > - * precedence over any internal error status, so the data isn't lost.
> > - *
> > - * For example ret will be -ENOSPC whenever there is more buffered data than
> > - * can be copied to userspace, but that's only interesting if we weren't able
> > - * to copy some data because it implies the userspace buffer is too small to
> > - * receive a single record (and we never split records).
> > - *
> > - * Another case with ret == -EFAULT is more of a grey area since it would seem
> > - * like bad form for userspace to ask us to overrun its buffer, but the user
> > - * knows best:
> > - *
> > - *   http://yarchive.net/comp/linux/partial_reads_writes.html
> > - *
> > - * Returns: The number of bytes copied or a negative error code on failure.
> > - */
> > -static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream,
> > -				     struct file *file,
> > -				     char __user *buf,
> > -				     size_t count,
> > -				     loff_t *ppos)
> > -{
> > -	/* Note we keep the offset (aka bytes read) separate from any
> > -	 * error status so that the final check for whether we return
> > -	 * the bytes read with a higher precedence than any error (see
> > -	 * comment below) doesn't need to be handled/duplicated in
> > -	 * stream->ops->read() implementations.
> > -	 */
> > -	size_t offset = 0;
> > -	int ret = stream->ops->read(stream, buf, count, &offset);
> > -
> > -	return offset ?: (ret ?: -EAGAIN);
> > -}
> > -
> >   /**
> >    * i915_perf_read - handles read() FOP for i915 perf stream FDs
> >    * @file: An i915 perf stream file
> > @@ -3025,6 +2982,8 @@ static ssize_t i915_perf_read(struct file *file,
> >   {
> >	struct i915_perf_stream *stream = file->private_data;
> >	struct i915_perf *perf = stream->perf;
> > +	size_t offset = 0;
> > +	int __ret;
> >	ssize_t ret;
> >		/* To ensure it's handled consistently we simply treat all reads of
> > a
> > @@ -3048,16 +3007,19 @@ static ssize_t i915_perf_read(struct file *file,
> >				return ret;
> >				mutex_lock(&perf->lock);
> > -			ret = i915_perf_read_locked(stream, file,
> > -						    buf, count, ppos);
> > +			__ret = stream->ops->read(stream, buf, count, &offset);
> > +			ret = offset ?: (__ret ?: -EAGAIN);
> >			mutex_unlock(&perf->lock);
> >		} while (ret == -EAGAIN);
> >	} else {
> >		mutex_lock(&perf->lock);
> > -		ret = i915_perf_read_locked(stream, file, buf, count, ppos);
> > +		__ret = stream->ops->read(stream, buf, count, &offset);
> > +		ret = offset ?: (__ret ?: -EAGAIN);
> >		mutex_unlock(&perf->lock);
> >	}
> >   +	/* Possible values for __ret are 0, -EFAULT, -ENOSPC, -EAGAIN,
> > ... */
> > +
> >	/* We allow the poll checking to sometimes report false positive EPOLLIN
> >	 * events where we might actually report EAGAIN on read() if there's
> >	 * not really any data available. In this situation though we don't
> > @@ -3065,13 +3027,12 @@ static ssize_t i915_perf_read(struct file *file,
> >	 * and read() returning -EAGAIN. Clearing the oa.pollin state here
> >	 * effectively ensures we back off until the next hrtimer callback
> >	 * before reporting another EPOLLIN event.
> > +	 * The exception to this is if ops->read() returned -ENOSPC which means
> > +	 * that more OA data is available than could fit in the user provided
> > +	 * buffer. In this case we want the next poll() call to not block.
> >	 */
> > -	if (ret >= 0 || ret == -EAGAIN) {
> > -		/* Maybe make ->pollin per-stream state if we support multiple
> > -		 * concurrent streams in the future.
> > -		 */
> > +	if ((ret > 0 || ret == -EAGAIN) && __ret != -ENOSPC)
> >		stream->pollin = false;
> > -	}
> >		return ret;
> >   }
>
> I think this reset of the pollin field is in the wrong place in the driver.
>
> The decision of whether pollin is true/false should be based off the
> difference between head/tail pointers.
>
> In my opinion the best place to do this in at the end of
> gen7/8_append_oa_reports functions, under the stream->oa_buffer.ptr_lock.
>
> If everything has been read up to the tail pointer, then there is nothing
> to wake up userspace for, otherwise leave pollin untouched.

Hi Lionel,

Are you seeing any problems of correctness in the code? My intention was to
use previously existing mechanisms (viz. -ENOSPC). Afais when
stream->ops->read() returns -ENOSPC it has already looked at head/tail
pointers and determined that there is data to be returned which it is
unable to because the provided buffer was too small.

Also, -ENOSPC can also be returned from append_oa_status(), though that can
probably be ignored.

Following your reasoning we should probably also say that pollin should be
set in oa_buffer_check_unlocked()?

About, stream->oa_buffer.ptr_lock, as I said previously, imo it is a lock
between a ring buffer producer (oa_buffer_check_unlocked()) and consumer
(i915_perf_read) which should not be needed, that ring buffer operation
should be lockless. Though we will need to check before removing it, maybe
I am wrong.

So unless you say there are real correctness problems in the patch or
previously existing code I am leaning towards leaving as it as is.

Thanks!
--
Ashutosh
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2020-03-27  3:39 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-26  4:43 [Intel-gfx] [PATCH] drm/i915/perf: Do not clear pollin for small user read buffers Ashutosh Dixit
2020-03-26  5:29 ` [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915/perf: Do not clear pollin for small user read buffers (rev2) Patchwork
2020-03-26  6:47 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
2020-03-26  9:09 ` [Intel-gfx] [PATCH] drm/i915/perf: Do not clear pollin for small user read buffers Lionel Landwerlin
2020-03-27  3:39   ` Dixit, Ashutosh [this message]
  -- strict thread matches above, loose matches on Subject: below --
2020-04-08 23:42 Ashutosh Dixit
2020-04-13 22:05 ` Rodrigo Vivi
2020-04-03  1:01 Ashutosh Dixit
2020-04-03 16:17 ` Chris Wilson
2020-04-03 17:45   ` Dixit, Ashutosh
2020-04-03 17:59     ` Chris Wilson
2020-03-31 23:14 Ashutosh Dixit
2020-04-01  6:57 ` Lionel Landwerlin
2020-04-01  7:43   ` Dixit, Ashutosh
2020-04-01  7:51     ` Lionel Landwerlin
2020-03-31  5:22 Ashutosh Dixit
2020-03-31  7:34 ` Lionel Landwerlin
2020-03-31 23:29   ` Dixit, Ashutosh
2020-03-27 23:16 Ashutosh Dixit
2020-03-30  8:23 ` Lionel Landwerlin
2020-03-31  5:47   ` Dixit, Ashutosh
2020-03-27 23:11 Ashutosh Dixit
2020-03-25 18:20 Ashutosh Dixit
2020-03-25 19:25 ` Lionel Landwerlin
2020-03-25 20:44   ` Dixit, Ashutosh
2020-03-26  0:32 ` Umesh Nerlige Ramappa
2020-03-26  1:52   ` Dixit, Ashutosh
2020-03-26 18:02     ` Umesh Nerlige Ramappa
2020-03-27  1:28       ` Dixit, Ashutosh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zhc2sbz0.wl-ashutosh.dixit@intel.com \
    --to=ashutosh.dixit@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=lionel.g.landwerlin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.