Quoting Tvrtko Ursulin (2019-02-01 17:29:45)
>
> On 01/02/2019 10:52, Chris Wilson wrote:
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c
> > b/drivers/gpu/drm/i915/i915_gem.c
> > index 4067eeaee78a..e47d53e9b634 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -4499,13 +4499,17 @@ int i915_gem_suspend(struct drm_i915_private *i915)
> > mutex_unlock(&i915->drm.struct_mutex);
> > i915_reset_flush(i915);
> >
> > - drain_delayed_work(&i915->gt.retire_work);
> > -
> > /*
> > * As the idle_work is rearming if it detects a race, play safe and
> > * repeat the flush until it is definitely idle.
> > */
> > - drain_delayed_work(&i915->gt.idle_work);
> > + if (drain_delayed_work_state(&i915->gt.retire_work,
> > + TASK_INTERRUPTIBLE) ||
> > + drain_delayed_work_state(&i915->gt.idle_work,
> > + TASK_INTERRUPTIBLE)) {
> > + ret = -EINTR;
> > + goto err_unlock;
> > + }
>
> I'm no suspend expert but it sounds unexpected there would be signals
> involved in the process. Does it have an userspace component? We don't
> bother with interruptible mutex on this path either.
You wouldn't believe what users get up to! And they then file a bug
report that they interrupted suspend and it said EINTR...
> > diff --git a/drivers/gpu/drm/i915/i915_utils.h
> > b/drivers/gpu/drm/i915/i915_utils.h
> > index fcc751aa1ea8..6866b85e4239 100644
> > --- a/drivers/gpu/drm/i915/i915_utils.h
> > +++ b/drivers/gpu/drm/i915/i915_utils.h
> > @@ -25,6 +25,8 @@
> > #ifndef __I915_UTILS_H
> > #define __I915_UTILS_H
> >
> > +#include <linux/sched/signal.h>
> > +
> > #undef WARN_ON
> > /* Many gcc seem to no see through this and fall over :( */
> > #if 0
> > @@ -148,12 +150,22 @@ static inline void __list_del_many(struct list_head
> > *head,
> > * by requeueing itself. Note, that if the worker never cancels itself,
> > * we will spin forever.
> > */
> > -static inline void drain_delayed_work(struct delayed_work *dw)
> > +
> > +static inline int drain_delayed_work_state(struct delayed_work *dw, int
> > state)
> > {
> > do {
> > - while (flush_delayed_work(dw))
> > - ;
> > + do {
> > + if (signal_pending_state(state, current))
> > + return -EINTR;
> > + } while (flush_delayed_work(dw));
> > } while (delayed_work_pending(dw));
> > +
> > + return 0;
> > +}
> > +
> > +static inline void drain_delayed_work(struct delayed_work *dw)
> > +{
> > + drain_delayed_work_state(dw, 0);
>
> 0 would be TASK_RUNNING. signal_pending_state bails out in this case so
> that's good.
The same trick is used in mutex_lock_(interruptible|killable) to map
onto a common handler for mutex_lock, so I don't think its unintentional
;)
-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx