<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<p style="font-family:Arial;font-size:10pt;color:#0000FF;margin:15pt;" align="Left">
[AMD Official Use Only]<br>
</p>
<br>
<div>
<div style="color: rgb(33, 33, 33); background-color: rgb(255, 255, 255);" dir="auto">
<div dir="auto" style="background-color: rgb(255, 255, 255)">Hi Luben,</div>
<div dir="auto" style="background-color: rgb(255, 255, 255)"><br>
</div>
<div dir="auto" style="background-color: rgb(255, 255, 255)">What I meant by event based is a thread waiting on wait queue for events, not a periodic polling as you had in the original patch. It still fetches the cached data on IOCTL but also triggers an event
 to poll for new errors. Similarly, a<span style="font-size: 12pt;"> periodic error handler running to handle threshold errors also could trigger event. Basically, error data fetch is centralized to the thread.</span></div>
<div dir="auto" style="background-color: rgb(255, 255, 255)"><span style="font-size: 12pt;"><br>
</span></div>
<div dir="auto" style="background-color: rgb(255, 255, 255)"><span style="font-size: 12pt;">It's just a different approach, don't know if that will make things more complex.</span></div>
</div>
<div id="ms-outlook-mobile-signature">
<div><br>
</div>
Thanks,<br>
Lijo</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Tuikov, Luben <Luben.Tuikov@amd.com><br>
<b>Sent:</b> Wednesday, May 26, 2021 8:42:29 PM<br>
<b>To:</b> Lazar, Lijo <Lijo.Lazar@amd.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org><br>
<b>Cc:</b> Deucher, Alexander <Alexander.Deucher@amd.com>; Clements, John <John.Clements@amd.com>; Koenig, Christian <Christian.Koenig@amd.com>; Zhang, Hawking <Hawking.Zhang@amd.com><br>
<b>Subject:</b> Re: [PATCH 3/3] drm/amdgpu: Use delayed work to collect RAS error counters</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">On 2021-05-26 7:00 a.m., Lazar, Lijo wrote:<br>
> [AMD Official Use Only]<br>
><br>
> Scheduling an error status query just based on IOCTL doesn't sound like a sound approach. What if driver needs to handle errors based on that - for ex: if the number of correctable errors exceed a certain threshold?<br>
That's exactly the trigger which evokes the error count procedure. The difference is that on that IOCTL,<br>
we return in O(1), the cached values and then trigger the counting procedure in a delayed work item,<br>
since it takes  O(n^3) and we cannot do it when the IOCTL is being processed as that negatively<br>
affects the user experience, and the overall agility of the system.<br>
<br>
This is the closest implementation to what was had before when the count was trigger at the IOCTL time,<br>
and the IOCTL blocked until the count was completed.<br>
<br>
Acting on exceeding a certain threshold is fine, since we're not competing against the delta<br>
of the excessive amount of errors, just so long as it does exceed. That is, so long as it exceeds,<br>
do something, we don't really care if it exceeds by delta or 10*delta.<br>
<br>
But what is important, is the _time_ frequency of the delayed work, AMDGPU_RAS_COUNTE_DELAY_MS,<br>
in my v2 of this patch. When set to 0, i.e. count as soon as possible, we get about 22% duty cycle of<br>
the CPU just doing that, all the time, as it seems this IOCTL is being called constantly, and thus<br>
the counting takes place all the time, continuously. And this isn't good for the system's performance<br>
and power management.<br>
<br>
When set to 3 seconds, we get a normal (expected) system behaviour in Vega20 sever boards.<br>
<br>
> IMO, I'm more aligned to Luben's original approach of having something waiting in the background - instead of a periodic timer based trigger, it could be an event based trigger.  Event may be an ioctl, error handler timer ticks or something else.<br>
<br>
Well, my original idea broke power management (PM), since it ran continuously<br>
regardless of PM and whether we indeed need the count.<br>
<br>
Now, when you say "Event may be an ioctl"--this is exactly what,<br>
<br>
1) was had before, interlocked, and it made the system unusable to a GUI user, and<br>
2) is what we have in this patch, but we process the count asynchronously, while<br>
    we return the O(1) count instantly.<br>
<br>
The advantage of 2) over my original approach, is that the count is triggered only<br>
on IOCTL call, albeit delayed so that we can return in O(1) the cached value. Thus,<br>
if no QUERY2 IOCTL is received, then we don't count the errors, as we don't schedule<br>
the delayed work.<br>
<br>
Regards,<br>
Luben<br>
<br>
> Thanks,<br>
> Lijo<br>
><br>
> -----Original Message-----<br>
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Luben Tuikov<br>
> Sent: Saturday, May 22, 2021 2:49 AM<br>
> To: amd-gfx@lists.freedesktop.org<br>
> Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; Tuikov, Luben <Luben.Tuikov@amd.com>; Clements, John <John.Clements@amd.com>; Koenig, Christian <Christian.Koenig@amd.com>; Zhang, Hawking <Hawking.Zhang@amd.com><br>
> Subject: [PATCH 3/3] drm/amdgpu: Use delayed work to collect RAS error counters<br>
><br>
> On Context Query2 IOCTL return the correctable and uncorrectable errors in O(1) fashion, from cached values, and schedule a delayed work function to calculate and cache them for the next such IOCTL.<br>
><br>
> Cc: Alexander Deucher <Alexander.Deucher@amd.com><br>
> Cc: Christian König <christian.koenig@amd.com><br>
> Cc: John Clements <john.clements@amd.com><br>
> Cc: Hawking Zhang <Hawking.Zhang@amd.com><br>
> Signed-off-by: Luben Tuikov <luben.tuikov@amd.com><br>
> ---<br>
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 32 +++++++++++++++++++--  drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 38 +++++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h |  5 ++++<br>
>  3 files changed, 73 insertions(+), 2 deletions(-)<br>
><br>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c<br>
> index bb0cfe871aba..4e95d255960b 100644<br>
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c<br>
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c<br>
> @@ -331,10 +331,13 @@ static int amdgpu_ctx_query(struct amdgpu_device *adev,<br>
>        return 0;<br>
>  }<br>
>  <br>
> +#define AMDGPU_RAS_COUNTE_DELAY_MS 3000<br>
> +<br>
>  static int amdgpu_ctx_query2(struct amdgpu_device *adev,<br>
> -     struct amdgpu_fpriv *fpriv, uint32_t id,<br>
> -     union drm_amdgpu_ctx_out *out)<br>
> +                          struct amdgpu_fpriv *fpriv, uint32_t id,<br>
> +                          union drm_amdgpu_ctx_out *out)<br>
>  {<br>
> +     struct amdgpu_ras *con = amdgpu_ras_get_context(adev);<br>
>        struct amdgpu_ctx *ctx;<br>
>        struct amdgpu_ctx_mgr *mgr;<br>
>  <br>
> @@ -361,6 +364,31 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,<br>
>        if (atomic_read(&ctx->guilty))<br>
>                out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;<br>
>  <br>
> +     if (adev->ras_enabled && con) {<br>
> +             /* Return the cached values in O(1),<br>
> +              * and schedule delayed work to cache<br>
> +              * new vaues.<br>
> +              */<br>
> +             int ce_count, ue_count;<br>
> +<br>
> +             ce_count = atomic_read(&con->ras_ce_count);<br>
> +             ue_count = atomic_read(&con->ras_ue_count);<br>
> +<br>
> +             if (ce_count != ctx->ras_counter_ce) {<br>
> +                     ctx->ras_counter_ce = ce_count;<br>
> +                     out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;<br>
> +             }<br>
> +<br>
> +             if (ue_count != ctx->ras_counter_ue) {<br>
> +                     ctx->ras_counter_ue = ue_count;<br>
> +                     out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;<br>
> +             }<br>
> +<br>
> +             if (!delayed_work_pending(&con->ras_counte_delay_work))<br>
> +                     schedule_delayed_work(&con->ras_counte_delay_work,<br>
> +                               msecs_to_jiffies(AMDGPU_RAS_COUNTE_DELAY_MS));<br>
> +     }<br>
> +<br>
>        mutex_unlock(&mgr->lock);<br>
>        return 0;<br>
>  }<br>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c<br>
> index ed3c43e8b0b5..80f576098318 100644<br>
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c<br>
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c<br>
> @@ -27,6 +27,7 @@<br>
>  #include <linux/uaccess.h><br>
>  #include <linux/reboot.h><br>
>  #include <linux/syscalls.h><br>
> +#include <linux/pm_runtime.h><br>
>  <br>
>  #include "amdgpu.h"<br>
>  #include "amdgpu_ras.h"<br>
> @@ -2116,6 +2117,30 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)<br>
>                adev->ras_hw_enabled & amdgpu_ras_mask;  }<br>
>  <br>
> +static void amdgpu_ras_counte_dw(struct work_struct *work) {<br>
> +     struct amdgpu_ras *con = container_of(work, struct amdgpu_ras,<br>
> +                                           ras_counte_delay_work.work);<br>
> +     struct amdgpu_device *adev = con->adev;<br>
> +     struct drm_device *dev = &adev->ddev;<br>
> +     unsigned long ce_count, ue_count;<br>
> +     int res;<br>
> +<br>
> +     res = pm_runtime_get_sync(dev->dev);<br>
> +     if (res < 0)<br>
> +             goto Out;<br>
> +<br>
> +     /* Cache new values.<br>
> +      */<br>
> +     amdgpu_ras_query_error_count(adev, &ce_count, &ue_count);<br>
> +     atomic_set(&con->ras_ce_count, ce_count);<br>
> +     atomic_set(&con->ras_ue_count, ue_count);<br>
> +<br>
> +     pm_runtime_mark_last_busy(dev->dev);<br>
> +Out:<br>
> +     pm_runtime_put_autosuspend(dev->dev);<br>
> +}<br>
> +<br>
>  int amdgpu_ras_init(struct amdgpu_device *adev)  {<br>
>        struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -2130,6 +2155,11 @@ int amdgpu_ras_init(struct amdgpu_device *adev)<br>
>        if (!con)<br>
>                return -ENOMEM;<br>
>  <br>
> +     con->adev = adev;<br>
> +     INIT_DELAYED_WORK(&con->ras_counte_delay_work, amdgpu_ras_counte_dw);<br>
> +     atomic_set(&con->ras_ce_count, 0);<br>
> +     atomic_set(&con->ras_ue_count, 0);<br>
> +<br>
>        con->objs = (struct ras_manager *)(con + 1);<br>
>  <br>
>        amdgpu_ras_set_context(adev, con);<br>
> @@ -2233,6 +2263,8 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,<br>
>                         struct ras_fs_if *fs_info,<br>
>                         struct ras_ih_if *ih_info)<br>
>  {<br>
> +     struct amdgpu_ras *con = amdgpu_ras_get_context(adev);<br>
> +     unsigned long ue_count, ce_count;<br>
>        int r;<br>
>  <br>
>        /* disable RAS feature per IP block if it is not supported */ @@ -2273,6 +2305,12 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,<br>
>        if (r)<br>
>                goto sysfs;<br>
>  <br>
> +     /* Those are the cached values at init.<br>
> +      */<br>
> +     amdgpu_ras_query_error_count(adev, &ce_count, &ue_count);<br>
> +     atomic_set(&con->ras_ce_count, ce_count);<br>
> +     atomic_set(&con->ras_ue_count, ue_count);<br>
> +<br>
>        return 0;<br>
>  cleanup:<br>
>        amdgpu_ras_sysfs_remove(adev, ras_block); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h<br>
> index 10fca0393106..256cea5d34f2 100644<br>
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h<br>
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h<br>
> @@ -340,6 +340,11 @@ struct amdgpu_ras {<br>
>  <br>
>        /* disable ras error count harvest in recovery */<br>
>        bool disable_ras_err_cnt_harvest;<br>
> +<br>
> +     /* RAS count errors delayed work */<br>
> +     struct delayed_work ras_counte_delay_work;<br>
> +     atomic_t ras_ue_count;<br>
> +     atomic_t ras_ce_count;<br>
>  };<br>
>  <br>
>  struct ras_fs_data {<br>
> --<br>
> 2.31.1.527.g2d677e5b15<br>
><br>
> _______________________________________________<br>
> amd-gfx mailing list<br>
> amd-gfx@lists.freedesktop.org<br>
> <a href="https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Clijo.lazar%40amd.com%7C3686015f68f84c9088ab08d91c9e0fcf%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637572287465788021%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=HbdtryTNLwzF862vg6E%2BwKBHmrw8NFz3gKQsU9ggdOk%3D&amp;reserved=0">
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Clijo.lazar%40amd.com%7C3686015f68f84c9088ab08d91c9e0fcf%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637572287465788021%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=HbdtryTNLwzF862vg6E%2BwKBHmrw8NFz3gKQsU9ggdOk%3D&amp;reserved=0</a><br>
<br>
</div>
</span></font></div>
</div>
</body>
</html>