diff mbox

drm/i915: Do not lie about atomic wait granularity

Message ID 1454332655-30400-1-git-send-email-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tvrtko Ursulin Feb. 1, 2016, 1:17 p.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Currently the wait_for_atomic_us only allows for a millisecond
granularity which is not nice towards callers requesting small
micro-second waits.

Re-implement it so micro-second granularity is really supported
and not just in the name of the macro.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
Danger - this might break things which currently work by accident!
---
 drivers/gpu/drm/i915/intel_drv.h | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Comments

Chris Wilson Feb. 1, 2016, 1:30 p.m. UTC | #1
On Mon, Feb 01, 2016 at 01:17:35PM +0000, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> Currently the wait_for_atomic_us only allows for a millisecond
> granularity which is not nice towards callers requesting small
> micro-second waits.
> 
> Re-implement it so micro-second granularity is really supported
> and not just in the name of the macro.
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
> Danger - this might break things which currently work by accident!
> ---
>  drivers/gpu/drm/i915/intel_drv.h | 21 ++++++++++++++++++---
>  1 file changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f620023ed134..9e8a1202194c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -63,10 +63,25 @@
>  	ret__;								\
>  })
>  
> +#define _wait_for_atomic(COND, US) ({ \
> +	unsigned long end__; \
> +	int ret__ = 0; \
> +	get_cpu(); \

Hmm, by virtue of its name (and original intent), we are expected to be
in an atomic context and could just do a BUG_ON(!in_atomic()) to catch
misuse. Since the removal of the panic modeset, all callers outside of
intel_uncore.c are definitely abusing this and we would be better to use
a usleep[_range]() variant instead.
-Chris
Tvrtko Ursulin Feb. 1, 2016, 2:15 p.m. UTC | #2
On 01/02/16 13:30, Chris Wilson wrote:
> On Mon, Feb 01, 2016 at 01:17:35PM +0000, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>
>> Currently the wait_for_atomic_us only allows for a millisecond
>> granularity which is not nice towards callers requesting small
>> micro-second waits.
>>
>> Re-implement it so micro-second granularity is really supported
>> and not just in the name of the macro.
>>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> ---
>> Danger - this might break things which currently work by accident!
>> ---
>>   drivers/gpu/drm/i915/intel_drv.h | 21 ++++++++++++++++++---
>>   1 file changed, 18 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index f620023ed134..9e8a1202194c 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -63,10 +63,25 @@
>>   	ret__;								\
>>   })
>>
>> +#define _wait_for_atomic(COND, US) ({ \
>> +	unsigned long end__; \
>> +	int ret__ = 0; \
>> +	get_cpu(); \
>
> Hmm, by virtue of its name (and original intent), we are expected to be
> in an atomic context and could just do a BUG_ON(!in_atomic()) to catch
> misuse. Since the removal of the panic modeset, all callers outside of
> intel_uncore.c are definitely abusing this and we would be better to use
> a usleep[_range]() variant instead.

I considered a WARN_ON_ONCE and a BUILD_BUG_ON for very long waits but 
chickened out on both.

I'll respin with a WARN_ON_ONCE(!in_atomic)) to start with.

Regards,

Tvrtko
Tvrtko Ursulin Feb. 1, 2016, 2:28 p.m. UTC | #3
On 01/02/16 14:15, Tvrtko Ursulin wrote:
>
> On 01/02/16 13:30, Chris Wilson wrote:
>> On Mon, Feb 01, 2016 at 01:17:35PM +0000, Tvrtko Ursulin wrote:
>>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>
>>> Currently the wait_for_atomic_us only allows for a millisecond
>>> granularity which is not nice towards callers requesting small
>>> micro-second waits.
>>>
>>> Re-implement it so micro-second granularity is really supported
>>> and not just in the name of the macro.
>>>
>>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>> ---
>>> Danger - this might break things which currently work by accident!
>>> ---
>>>   drivers/gpu/drm/i915/intel_drv.h | 21 ++++++++++++++++++---
>>>   1 file changed, 18 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h
>>> b/drivers/gpu/drm/i915/intel_drv.h
>>> index f620023ed134..9e8a1202194c 100644
>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>> @@ -63,10 +63,25 @@
>>>       ret__;                                \
>>>   })
>>>
>>> +#define _wait_for_atomic(COND, US) ({ \
>>> +    unsigned long end__; \
>>> +    int ret__ = 0; \
>>> +    get_cpu(); \
>>
>> Hmm, by virtue of its name (and original intent), we are expected to be
>> in an atomic context and could just do a BUG_ON(!in_atomic()) to catch
>> misuse. Since the removal of the panic modeset, all callers outside of
>> intel_uncore.c are definitely abusing this and we would be better to use
>> a usleep[_range]() variant instead.
>
> I considered a WARN_ON_ONCE and a BUILD_BUG_ON for very long waits but
> chickened out on both.
>
> I'll respin with a WARN_ON_ONCE(!in_atomic)) to start with.

Can't really do that it seems since in_atomic() will be always false on 
non-fully-preemptible kernels.

Could do the current cpu comparison trick to catch false timeouts due 
callers from non-atomic sections but not sure if it is worth it. So it 
looks like manual audit of call sites to me.

Or find a time source with micro-second resolution which does not go 
backwards on CPU migrations?

Regards,

Tvrtko
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f620023ed134..9e8a1202194c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -63,10 +63,25 @@ 
 	ret__;								\
 })
 
+#define _wait_for_atomic(COND, US) ({ \
+	unsigned long end__; \
+	int ret__ = 0; \
+	get_cpu(); \
+	end__ = (local_clock() >> 10) + (US) + 1; \
+	while (!(COND)) { \
+		if (time_after((unsigned long)(local_clock() >> 10), end__)) { \
+			ret__ = -ETIMEDOUT; \
+			break; \
+		} \
+		cpu_relax(); \
+	} \
+	put_cpu(); \
+	ret__; \
+})
+
 #define wait_for(COND, MS) _wait_for(COND, MS, 1)
-#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
-#define wait_for_atomic_us(COND, US) _wait_for((COND), \
-					       DIV_ROUND_UP((US), 1000), 0)
+#define wait_for_atomic(COND, MS) _wait_for_atomic(COND, (MS * 1000))
+#define wait_for_atomic_us(COND, US) _wait_for_atomic((COND), (US))
 
 #define KHz(x) (1000 * (x))
 #define MHz(x) KHz(1000 * (x))