<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Am 21.08.24 um 10:57 schrieb Thomas Hellström:<br>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <pre class="moz-quote-pre" wrap="">On Wed, 2024-08-21 at 10:14 +0200, Christian König wrote:
</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">Am 20.08.24 um 18:00 schrieb Thomas Hellström:
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre class="moz-quote-pre" wrap="">Or why exactly should shrinking fail?
</pre>
          </blockquote>
          <pre class="moz-quote-pre" wrap="">A common example would be not having runtime pm and the particular
bo
needs it to unbind, we want to try the next bo. Example: i915 GGTT
bound bos and Lunar Lake PL_TT bos.
</pre>
        </blockquote>
        <pre class="moz-quote-pre" wrap="">
WHAT? So you basically block shrinking BOs because you can't unbind
them 
because the device is powered down?

I would say that this is a serious NO-GO. It basically means that 
powered down devices can lock down system memory for undefined amount
of 
time.

In other words an application can allocate memory, map it into GGTT
and 
then suspend or even get killed and we are not able to recover the 
memory because there is no activity on the GPU any more?

That really sounds like a bug in the driver design to me.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
It's bad but it's not as bad as it sounds.

Problem is we can't wake up during direct reclaim IIRC due to runtime
pm lockdep violations, but we can and do fire up a thread to wake the
device and after the wakeup delay have subsequent shrink calls succeed,
or punt to kswapd or the oom handler.</pre>
    </blockquote>
    <br>
    Yeah that is obvious. The runtime PM is an interface designed to be
    used from a very high level IOCTL/system call.<br>
    <br>
    And delegating that from a shrinker to a worker is not valid as far
    as I can see, instead of reducing the memory pressure the shrinker
    would then increase it.<br>
    <br>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <pre class="moz-quote-pre" wrap="">I think that's an orthogonal discussion, though. There are other
reasons shrinking might fail, like the bo being busy in direct reclaim
(shouldn't wait for idle there but ok in kswapd), Other points of
failure is ofc shmem radix tree allocations (not seen one yet, though)
which might succeed with a smaller bo.
(Not saying, though, that there isn't more to be done with the xe
runtime pm implementation).</pre>
    </blockquote>
    <br>
    I don't think that argumentation is valid.<br>
    <br>
    When a BO is locked then that it is ok to not shrink it, but TTM
    should be able to determine all those prerequisites.<br>
    <br>
    In other words the idea of a function returning a BO to the driver
    is that the driver is obligated to shrink that one.<br>
    <br>
    That other necessary allocation can fail like shmen for example is
    obvious as well, but that's why we discussed to allow shrinking BOs
    partially as well.<br>
    <br>
    And I really don't think this discussion is orthogonal. We are
    basically discussing what drivers should do and not should do. And
    as far as I can see the requirement to expose the LRUs to drivers
    comes up only because the driver wants to do something it shouldn't.<br>
    <br>
    <span style="white-space: pre-wrap">
</span><span style="white-space: pre-wrap">
</span>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <blockquote type="cite">
        <blockquote type="cite">
          <pre class="moz-quote-pre" wrap="">And again, all other drm bo shrinkers do this. We just want to do
the
same.
</pre>
        </blockquote>
        <pre class="moz-quote-pre" wrap="">
Do you have pointers?
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
As Sima said, this is complicated but not beyond comprehension: i915
<a class="moz-txt-link-freetext" href="https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c#L317">https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c#L317</a></pre>
    </blockquote>
    <br>
    As far as I can tell what i915 does here is extremely questionable.<br>
    <br>
        if (sc->nr_scanned < sc->nr_to_scan &&
    current_is_kswapd()) {<br>
    ....<br>
            with_intel_runtime_pm(&i915->runtime_pm, wakeref) {<br>
    <br>
    with_intel_runtime_pm() then calls pm_runtime_get_sync().<br>
    <br>
    So basically the i915 shrinker assumes that when called from
    kswapd() that it can synchronously wait for runtime PM to power up
    the device again.<br>
    <br>
    As far as I can tell that means that a device driver makes strong
    and completely undocumented assumptions how kswapd works internally.<br>
    <br>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <pre class="moz-quote-pre" wrap="">msm:
<a class="moz-txt-link-freetext" href="https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c#L317">https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c#L317</a>
which uses
<a class="moz-txt-link-freetext" href="https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/drm_gem.c#L1426">https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/drm_gem.c#L1426</a>
that is very similar in structure to what I implemented for TTM.

Panfrost: (although only purgeable objects AFAICT).
<a class="moz-txt-link-freetext" href="https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/drm_gem.c#L1426">https://elixir.bootlin.com/linux/v6.11-rc4/source/drivers/gpu/drm/drm_gem.c#L1426</a></pre>
    </blockquote>
    <br>
    From skimming over the source only MSM actually seems to use this
    and the criteria for rejecting shrinking is everything TTM should
    know, e.g. if a BO is pinned, idle etc...<br>
    <br>
    <span style="white-space: pre-wrap">
</span><span style="white-space: pre-wrap">
</span>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre class="moz-quote-pre" wrap="">If we bump LRU we could end up with infinite loops.
So IMO we need to be able to loop. I don't really care wether
we do
this as an explicit loop or whether we use the LRU walker, but
I
think
from a maintainability point-of-view it is better to keep LRU
walking
in a single place.

If we return an unlocked object, we'd need to refcount and drop
the
lru
lock, but maybe that's not a bad thing.

But what's the main drawback of exporting the existing helper.
</pre>
            </blockquote>
            <pre class="moz-quote-pre" wrap="">Well that we re-creates exactly the mid-layer mess I worked so
hard
to
remove from TTM.
</pre>
          </blockquote>
          <pre class="moz-quote-pre" wrap="">It doesn't IMO. I agree the first attempt did. This affects only
the
LRU iteration itself and I'm even fine to get rid of the callback
using
a for_ macro.
</pre>
        </blockquote>
        <pre class="moz-quote-pre" wrap="">
Well, I mean using a for_each approach is objectively better than
having 
a callback and a state bag.

But the fundamental question is if drivers are allowed to reject 
shrinking. And I think the answer is no, they need to be designed in

way where shrinking is always possible.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Rejects can be out of our control, due to anticipated deadlocks, oom
and deferring to kswapd.

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
What can be that we can't get the necessary locks to evict and object
(because it's about to be used etc...), but that are the per-
requisites 
TTM should be checking.

</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre class="moz-quote-pre" wrap="">In any case, I don't think TTM should enforce a different way
of
shrinking by the means of a severely restricted helper?
</pre>
            </blockquote>
            <pre class="moz-quote-pre" wrap="">Well, as far as I can see that is exactly what TTM should do.

I mean the main advantage to make a common component is to
enforce
correct behavior.
</pre>
          </blockquote>
          <pre class="moz-quote-pre" wrap="">But if all other drivers don't agree this as correct behavior and
instead want to keep behavior that is proven to work, that's a dead
end.
</pre>
        </blockquote>
        <pre class="moz-quote-pre" wrap="">
Well no, even if all drivers agree to (for example) drop security 
precautions it's still not something acceptable.

And same thing here, if we block shrinking because drivers think they
want their runtime PM implemented in a certain way then upstream
needs 
to block this and push back.

As far as I can see it's mandatory to have shrinkers not depend on 
runtime PM, cause otherwise you run into resources handling which 
depends on the well behavior of userspace and that in turn in
something 
we can't allow.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Please see the above explanation for runtime pm, and for the record I
agree that enforcing disallowed or security violations is a completely
valid thing.</pre>
    </blockquote>
    <br>
    Putting the TTM issue aside as far as I can tell what i915 is
    extremely questionable and doing the same thing in XE is most likely
    not something we should allow.<br>
    <br>
    Regards,<br>
    Christian.<br>
    <br>
    <blockquote type="cite" cite="mid:13a47d22fb6753e20046a983126c6fea675beed2.camel@linux.intel.com">
      <pre class="moz-quote-pre" wrap="">

/Thomas

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
Regards,
Christian.

</pre>
        <blockquote type="cite">
          <pre class="moz-quote-pre" wrap="">
/Thomas


</pre>
          <blockquote type="cite">
            <pre class="moz-quote-pre" wrap="">Regards,
Christian.

</pre>
            <blockquote type="cite">
              <pre class="moz-quote-pre" wrap="">/Thomas

</pre>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
</pre>
    </blockquote>
    <br>
  </body>
</html>