ACPI: PCC: replace wait_for_completion()
authorHuisong Li <lihuisong@huawei.com>
Tue, 20 Sep 2022 09:44:59 +0000 (17:44 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 22 Sep 2022 19:08:03 +0000 (21:08 +0200)
Currently, the function waiting for completion of mailbox operation is
'wait_for_completion()'.  The PCC method will be permanently blocked if
this mailbox message fails to execute. So this patch replaces it with
'wait_for_completion_timeout()'. And set the timeout interval to an
arbitrary retries on top of nominal to prevent the remote processor is
slow to respond to PCC commands.

Fixes: 77e2a04745ff ("ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype")
Signed-off-by: Huisong Li <lihuisong@huawei.com>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpi_pcc.c

index 84f1ac416b570d4ffbcfd017d67001fa65751120..16ba875e32931d17baebbd57097a93c5e86f8178 100644 (file)
 
 #include <acpi/pcc.h>
 
+/*
+ * Arbitrary retries in case the remote processor is slow to respond
+ * to PCC commands
+ */
+#define PCC_CMD_WAIT_RETRIES_NUM       500
+
 struct pcc_data {
        struct pcc_mbox_chan *pcc_chan;
        void __iomem *pcc_comm_addr;
@@ -89,6 +95,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
 {
        int ret;
        struct pcc_data *data = region_context;
+       u64 usecs_lat;
 
        reinit_completion(&data->done);
 
@@ -99,8 +106,20 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
        if (ret < 0)
                return AE_ERROR;
 
-       if (data->pcc_chan->mchan->mbox->txdone_irq)
-               wait_for_completion(&data->done);
+       if (data->pcc_chan->mchan->mbox->txdone_irq) {
+               /*
+                * pcc_chan->latency is just a Nominal value. In reality the remote
+                * processor could be much slower to reply. So add an arbitrary
+                * amount of wait on top of Nominal.
+                */
+               usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
+               ret = wait_for_completion_timeout(&data->done,
+                                                 usecs_to_jiffies(usecs_lat));
+               if (ret == 0) {
+                       pr_err("PCC command executed timeout!\n");
+                       return AE_TIME;
+               }
+       }
 
        mbox_client_txdone(data->pcc_chan->mchan, ret);