Add support for PCC Operation Region
Huisong Li (3): ACPI: PCC: replace wait_for_completion() ACPI: PCC: Fix Tx acknowledge in the PCC address space handler ACPI: PCC: Setup PCC Opregion handler only if platform interrupt is available
Manank Patel (1): ACPI: PCC: Fix unintentional integer overflow
Rafael Mendonca (1): ACPI: PCC: Release resources on address space setup failure path
Sudeep Holla (2): ACPICA: Add support for PCC Opregion special context data ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype
Zhang Zekun (1): arm64: config: Enable ACPI_PCC
kernel test robot (1): ACPI: PCC: pcc_ctx can be static
arch/arm64/configs/openeuler_defconfig | 1 + drivers/acpi/Kconfig | 17 +++ drivers/acpi/Makefile | 1 + drivers/acpi/acpi_pcc.c | 153 +++++++++++++++++++++++++ drivers/acpi/acpica/evregion.c | 10 ++ drivers/acpi/bus.c | 1 + include/acpi/actypes.h | 8 ++ include/linux/acpi.h | 6 + 8 files changed, 197 insertions(+) create mode 100644 drivers/acpi/acpi_pcc.c
From: Sudeep Holla sudeep.holla@arm.com
mainline inclusion from mainlien-v5.17-rc1 commit 0acf24ad7e10f547809faefb8069f8f5482eb4d9 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h...
-------------------------------------
ACPICA commit 55526e8a6133cbf5a9cc0fb75a95dbbac6eb98e6
PCC Opregion added in ACPIC 6.3 requires special context data similar to GPIO and Generic Serial Bus as it needs to know the internal PCC buffer and its length as well as the PCC channel index when the opregion handler is being executed by the OSPM.
Lets add support for the special context data needed by PCC Opregion.
Link: https://github.com/acpica/acpica/commit/55526e8a Signed-off-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Bob Moore robert.moore@intel.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpica/evregion.c | 10 ++++++++++ include/acpi/actypes.h | 8 ++++++++ 2 files changed, 18 insertions(+)
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 980efc9bd5ee..4577ee533303 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -161,6 +161,16 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, return_ACPI_STATUS(AE_NOT_EXIST); }
+ if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + struct acpi_pcc_info *ctx = + handler_desc->address_space.context; + + ctx->internal_buffer = + field_obj->field.internal_pcc_buffer; + ctx->length = region_obj->region.length; + ctx->subspace_id = region_obj->region.address; + } + /* * We must exit the interpreter because the region setup will * potentially execute control methods (for example, the _REG method diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 3fb9aee1f716..ac42f3a45a84 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1105,6 +1105,14 @@ struct acpi_connection_info { u8 access_length; };
+/* Special Context data for PCC Opregion (ACPI 6.3) */ + +struct acpi_pcc_info { + u8 subspace_id; + u16 length; + u8 *internal_buffer; +}; + typedef acpi_status (*acpi_adr_space_setup) (acpi_handle region_handle, u32 function,
From: Sudeep Holla sudeep.holla@arm.com
mainline inclusion from mainline-v5.17-rc1 commit 77e2a04745ff8e391ad402e2d2d1157a5d3a7ebc category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------
PCC OpRegion provides a mechanism to communicate with the platform directly from the AML. PCCT provides the list of PCC channel available in the platform, a subset or all of them can be used in PCC Opregion.
This patch registers the PCC OpRegion handler before ACPI tables are loaded. This relies on the special context data passed to identify and set up the PCC channel before the OpRegion handler is executed for the first time.
Typical PCC Opregion declaration looks like this:
OperationRegion (PFRM, PCC, 2, 0x74) Field (PFRM, ByteAcc, NoLock, Preserve) { SIGN, 32, FLGS, 32, LEN, 32, CMD, 32, DATA, 800 }
It contains four named double words followed by 100 bytes of buffer names DATA.
ASL can fill out the buffer something like:
/* Create global or local buffer */ Name (BUFF, Buffer (0x0C){}) /* Create double word fields over the buffer */ CreateDWordField (BUFF, 0x0, WD0) CreateDWordField (BUFF, 0x04, WD1) CreateDWordField (BUFF, 0x08, WD2)
/* Fill the named fields */ WD0 = 0x50434300 SIGN = BUFF WD0 = 1 FLGS = BUFF WD0 = 0x10 LEN = BUFF
/* Fill the payload in the DATA buffer */ WD0 = 0 WD1 = 0x08 WD2 = 0 DATA = BUFF
/* Write to CMD field to trigger handler */ WD0 = 0x4404 CMD = BUFF
This buffer is received by acpi_pcc_opregion_space_handler. This handler will fetch the complete buffer via internal_pcc_buffer.
The setup handler will receive the special PCC context data which will contain the PCC channel index which used to set up the channel. The buffer pointer and length is saved in region context which is then used in the handler.
(kernel test robot: Build failure with CONFIG_ACPI_DEBUGGER) Link: https://lore.kernel.org/r/202201041539.feAV0l27-lkp@intel.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/Kconfig | 17 ++++++ drivers/acpi/Makefile | 1 + drivers/acpi/acpi_pcc.c | 120 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/bus.c | 1 + include/linux/acpi.h | 6 ++ 5 files changed, 145 insertions(+) create mode 100644 drivers/acpi/acpi_pcc.c
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 435525c7acb3..2f8dfe21e7ce 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -519,6 +519,23 @@ config ACPI_PPTT bool endif
+config ACPI_PCC + bool "ACPI PCC Address Space" + depends on PCC + default y + help + The PCC Address Space also referred as PCC Operation Region pertains + to the region of PCC subspace that succeeds the PCC signature. + + The PCC Operation Region works in conjunction with the PCC Table + (Platform Communications Channel Table). PCC subspaces that are + marked for use as PCC Operation Regions must not be used as PCC + subspaces for the standard ACPI features such as CPPC, RASF, PDTT and + MPST. These standard features must always use the PCC Table instead. + + Enable this feature if you want to set up and install the PCC Address + Space handler to handle PCC OpRegion in the firmware. + source "drivers/acpi/pmic/Kconfig"
endif # ACPI diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 6a1383e87b72..065089733db7 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -65,6 +65,7 @@ acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o acpi-$(CONFIG_ACPI_PRMT) += prmt.o +acpi-$(CONFIG_ACPI_PCC) += acpi_pcc.o
# Address translation acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c new file mode 100644 index 000000000000..41e3ebd204ff --- /dev/null +++ b/drivers/acpi/acpi_pcc.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Sudeep Holla sudeep.holla@arm.com + * Copyright 2021 Arm Limited + * + * The PCC Address Space also referred as PCC Operation Region pertains to the + * region of PCC subspace that succeeds the PCC signature. The PCC Operation + * Region works in conjunction with the PCC Table(Platform Communications + * Channel Table). PCC subspaces that are marked for use as PCC Operation + * Regions must not be used as PCC subspaces for the standard ACPI features + * such as CPPC, RASF, PDTT and MPST. These standard features must always use + * the PCC Table instead. + * + * This driver sets up the PCC Address Space and installs an handler to enable + * handling of PCC OpRegion in the firmware. + * + */ +#include <linux/kernel.h> +#include <linux/acpi.h> +#include <linux/completion.h> +#include <linux/idr.h> +#include <linux/io.h> + +#include <acpi/pcc.h> + +struct pcc_data { + struct pcc_mbox_chan *pcc_chan; + void __iomem *pcc_comm_addr; + struct completion done; + struct mbox_client cl; + struct acpi_pcc_info ctx; +}; + +struct acpi_pcc_info pcc_ctx; + +static void pcc_rx_callback(struct mbox_client *cl, void *m) +{ + struct pcc_data *data = container_of(cl, struct pcc_data, cl); + + complete(&data->done); +} + +static acpi_status +acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, + void *handler_context, void **region_context) +{ + struct pcc_data *data; + struct acpi_pcc_info *ctx = handler_context; + struct pcc_mbox_chan *pcc_chan; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return AE_NO_MEMORY; + + data->cl.rx_callback = pcc_rx_callback; + data->cl.knows_txdone = true; + data->ctx.length = ctx->length; + data->ctx.subspace_id = ctx->subspace_id; + data->ctx.internal_buffer = ctx->internal_buffer; + + init_completion(&data->done); + data->pcc_chan = pcc_mbox_request_channel(&data->cl, ctx->subspace_id); + if (IS_ERR(data->pcc_chan)) { + pr_err("Failed to find PCC channel for subspace %d\n", + ctx->subspace_id); + return AE_NOT_FOUND; + } + + pcc_chan = data->pcc_chan; + data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr, + pcc_chan->shmem_size); + if (!data->pcc_comm_addr) { + pr_err("Failed to ioremap PCC comm region mem for %d\n", + ctx->subspace_id); + return AE_NO_MEMORY; + } + + *region_context = data; + return AE_OK; +} + +static acpi_status +acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, + u32 bits, acpi_integer *value, + void *handler_context, void *region_context) +{ + int ret; + struct pcc_data *data = region_context; + + reinit_completion(&data->done); + + /* Write to Shared Memory */ + memcpy_toio(data->pcc_comm_addr, (void *)value, data->ctx.length); + + ret = mbox_send_message(data->pcc_chan->mchan, NULL); + if (ret < 0) + return AE_ERROR; + + if (data->pcc_chan->mchan->mbox->txdone_irq) + wait_for_completion(&data->done); + + mbox_client_txdone(data->pcc_chan->mchan, ret); + + memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length); + + return AE_OK; +} + +void __init acpi_init_pcc(void) +{ + acpi_status status; + + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_PLATFORM_COMM, + &acpi_pcc_address_space_handler, + &acpi_pcc_address_space_setup, + &pcc_ctx); + if (ACPI_FAILURE(status)) + pr_alert("OperationRegion handler could not be installed\n"); +} diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d8086d49ce6b..ee33119ad203 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1277,6 +1277,7 @@ static int __init acpi_init(void) }
init_prmt(); + acpi_init_pcc(); result = acpi_bus_init(); if (result) { kobject_put(acpi_kobj); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 23272fa4ca95..f21d13657d7d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1404,6 +1404,12 @@ static inline struct acpi_pptt_processor *find_acpi_processor_node_from_cache_id } #endif
+#ifdef CONFIG_ACPI_PCC +void acpi_init_pcc(void); +#else +static inline void acpi_init_pcc(void) { } +#endif + #ifdef CONFIG_ACPI extern int acpi_platform_notify(struct device *dev, enum kobject_action action); #else
From: kernel test robot lkp@intel.com
mainline inclusion from mainline-v5.17-rc1 commit 415b4b6c447ae03cb1d9cfc91df39616c92f15e2 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-------------------------------
drivers/acpi/acpi_pcc.c:34:22: warning: symbol 'pcc_ctx' was not declared. Should it be static?
Reported-by: kernel test robot lkp@intel.com Signed-off-by: kernel test robot lkp@intel.com Reviewed-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index 41e3ebd204ff..a12b55d81209 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -31,7 +31,7 @@ struct pcc_data { struct acpi_pcc_info ctx; };
-struct acpi_pcc_info pcc_ctx; +static struct acpi_pcc_info pcc_ctx;
static void pcc_rx_callback(struct mbox_client *cl, void *m) {
From: Rafael Mendonca rafaelmendsr@gmail.com
mainline inclusion from mainline-v6.1-rc1 commit f890157e61b85ce8ae01a41ffa375e3b99853698 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------------------------
The allocated memory for the pcc_data struct doesn't get freed under an error path in pcc_mbox_request_channel() or acpi_os_ioremap(). Also, the PCC mailbox channel doesn't get freed under an error path in acpi_os_ioremap().
Fixes: 77e2a04745ff8 ("ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype") Signed-off-by: Rafael Mendonca rafaelmendsr@gmail.com Reviewed-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index a12b55d81209..84f1ac416b57 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -63,6 +63,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, if (IS_ERR(data->pcc_chan)) { pr_err("Failed to find PCC channel for subspace %d\n", ctx->subspace_id); + kfree(data); return AE_NOT_FOUND; }
@@ -72,6 +73,8 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, if (!data->pcc_comm_addr) { pr_err("Failed to ioremap PCC comm region mem for %d\n", ctx->subspace_id); + pcc_mbox_free_channel(data->pcc_chan); + kfree(data); return AE_NO_MEMORY; }
From: Huisong Li lihuisong@huawei.com
mainline inclusion from mainline-v6.1-rc1 commit 91cefefb699120efd0a5ba345d12626b688f86ce category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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 Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index 84f1ac416b57..16ba875e3293 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -23,6 +23,12 @@
#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);
From: Huisong Li lihuisong@huawei.com
mainline inclusion from mainline-v6.1-rc1 commit 18729106c26fb97d4c9ae63ba7aba9889a058dc4 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
-----------------------------------
Currently, mbox_client_txdone() is called from the PCC address space handler and that expects the user the Tx state machine to be controlled by the client which is not the case and the below warning is thrown:
| PCCT: Client can't run the TX ticker
Let the controller run the state machine and the end of Tx can be acknowledge by calling mbox_chan_txdone() instead.
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 Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index 16ba875e3293..ee4ce5ba1fb2 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -121,7 +121,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, } }
- mbox_client_txdone(data->pcc_chan->mchan, ret); + mbox_chan_txdone(data->pcc_chan->mchan, ret);
memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
From: Manank Patel pmanank200502@gmail.com
mainline inclusion from mainline-v6.1-rc3 commit: 8338b74a750c534c223e8943cc0ed0e198ece261 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------------------------
Fix an unintentional u32 overflow by changing PCC_CMD_WAIT_RETRIES_NUM to 500ULL.
Fixes: 91cefefb6991 ("ACPI: PCC: replace wait_for_completion()") Signed-off-by: Manank Patel pmanank200502@gmail.com Acked-by: Sudeep Holla sudeep.holla@arm.com Acked-by: Huisong Li lihuisong@huawei.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index ee4ce5ba1fb2..3e252be047b8 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -27,7 +27,7 @@ * Arbitrary retries in case the remote processor is slow to respond * to PCC commands */ -#define PCC_CMD_WAIT_RETRIES_NUM 500 +#define PCC_CMD_WAIT_RETRIES_NUM 500ULL
struct pcc_data { struct pcc_mbox_chan *pcc_chan;
From: Huisong Li lihuisong@huawei.com
mainline inclusion from mainline-v6.2-rc1 commit a10b1c99e2dccee69838b512419843c21b2b87f8 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
------------------------------------------
Currently, PCC OpRegion handler depends on the availability of platform interrupt to be functional currently. If it is not available, the OpRegion can't be executed successfully or the desired outcome won't be possible. So let's reject setting up the PCC OpRegion handler on the platform if it doesn't support or have platform interrupt available.
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 Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- drivers/acpi/acpi_pcc.c | 47 +++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 18 deletions(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c index 3e252be047b8..07a034a53aca 100644 --- a/drivers/acpi/acpi_pcc.c +++ b/drivers/acpi/acpi_pcc.c @@ -53,6 +53,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, struct pcc_data *data; struct acpi_pcc_info *ctx = handler_context; struct pcc_mbox_chan *pcc_chan; + static acpi_status ret;
data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -69,23 +70,35 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, if (IS_ERR(data->pcc_chan)) { pr_err("Failed to find PCC channel for subspace %d\n", ctx->subspace_id); - kfree(data); - return AE_NOT_FOUND; + ret = AE_NOT_FOUND; + goto err_free_data; }
pcc_chan = data->pcc_chan; + if (!pcc_chan->mchan->mbox->txdone_irq) { + pr_err("This channel-%d does not support interrupt.\n", + ctx->subspace_id); + ret = AE_SUPPORT; + goto err_free_channel; + } data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr, pcc_chan->shmem_size); if (!data->pcc_comm_addr) { pr_err("Failed to ioremap PCC comm region mem for %d\n", ctx->subspace_id); - pcc_mbox_free_channel(data->pcc_chan); - kfree(data); - return AE_NO_MEMORY; + ret = AE_NO_MEMORY; + goto err_free_channel; }
*region_context = data; return AE_OK; + +err_free_channel: + pcc_mbox_free_channel(data->pcc_chan); +err_free_data: + kfree(data); + + return ret; }
static acpi_status @@ -106,19 +119,17 @@ 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) { - /* - * 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; - } + /* + * 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_chan_txdone(data->pcc_chan->mchan, ret);
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VPZ8
--------------------------------
ACPI_PCC is enabled default by Kconfig, enable ACPI_PCC by default in Kconfig.
Signed-off-by: Zhang Zekun zhangzekun11@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 9b0bc98d975f..d2aa35d4d3cd 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -769,6 +769,7 @@ CONFIG_ACPI_IORT=y CONFIG_ACPI_GTDT=y CONFIG_ACPI_MPAM=y CONFIG_ACPI_PPTT=y +CONFIG_ACPI_PCC=y # CONFIG_PMIC_OPREGION is not set CONFIG_IRQ_BYPASS_MANAGER=y CONFIG_VIRTUALIZATION=y
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8791 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/N...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/8791 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/N...