]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/platform/amd: move final timeout check to after final sleep
authorJake Hillion <jake@hillion.co.uk>
Thu, 5 Jun 2025 18:09:26 +0000 (19:09 +0100)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 9 Jun 2025 07:50:40 +0000 (10:50 +0300)
__hsmp_send_message sleeps between result read attempts and has a
timeout of 100ms. Under extreme load it's possible for these sleeps to
take a long time, exceeding the 100ms. In this case the current code
does not check the register and fails with ETIMEDOUT.

Refactor the loop to ensure there is at least one read of the register
after a sleep of any duration. This removes instances of ETIMEDOUT with
a single caller, even with a misbehaving scheduler. Tested on AMD
Bergamo machines.

Suggested-by: Blaise Sanouillet <linux@blaise.sanouillet.com>
Reviewed-by: Suma Hegde <suma.hegde@amd.com>
Tested-by: Suma Hegde <suma.hegde@amd.com>
Signed-off-by: Jake Hillion <jake@hillion.co.uk>
Link: https://lore.kernel.org/r/20250605-amd-hsmp-v2-1-a811bc3dd74a@hillion.co.uk
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/amd/hsmp/hsmp.c

index 538b36b97095eac2a4930d7817efe5e6a3c3ad57..fa8bd5839dd289488bbd8ede4708c95d1ccc8e55 100644 (file)
@@ -97,7 +97,7 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
        short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP);
        timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);
 
-       while (time_before(jiffies, timeout)) {
+       while (true) {
                ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD);
                if (ret) {
                        dev_err(sock->dev, "Error %d reading mailbox status\n", ret);
@@ -106,6 +106,10 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
 
                if (mbox_status != HSMP_STATUS_NOT_READY)
                        break;
+
+               if (!time_before(jiffies, timeout))
+                       break;
+
                if (time_before(jiffies, short_sleep))
                        usleep_range(50, 100);
                else