drivers/acpi/acpi_pcc.c | 78 ++++++++++++++++++++++++++++------------- drivers/mailbox/pcc.c | 12 ++++++- 2 files changed, 64 insertions(+), 26 deletions(-)
The goal is to allow clients to submit a message in both irq and polling
mode of the pcc mailbox. The ACPI specification does not require a
platform irq for pcc channels. Let's implement the case where it is not
available.
peek_data is mapped to pcc_mbox_error_check_and_clear, so that it
returns true if no error occurred while the platform processed last
message, and therefore clients can fetch response data provided by the
platform.
Tested-by: Thibault Cantori <thibault.cantori@sipearl.com>
Co-developed-by: Olivier Dautricourt <olivier.dautricourt@sipearl.com>
Signed-off-by: Olivier Dautricourt <olivier.dautricourt@sipearl.com>
Signed-off-by: Andrea Tomassetti <andrea.tomassetti@sipearl.com>
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202511120243.soxAFpqQ-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202511120558.Cln7LF6M-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202511120729.R3XQNSnx-lkp@intel.com/
---
v2: Fix issues reported by the kernel test robot
- sparse: incorrect type in argument 2 (different address spaces)
- acpi_pcc.c:(.text+0x69): undefined reference to `__udivdi3'
drivers/acpi/acpi_pcc.c | 78 ++++++++++++++++++++++++++++-------------
drivers/mailbox/pcc.c | 12 ++++++-
2 files changed, 64 insertions(+), 26 deletions(-)
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c
index 97064e943768..37f94fa4c424 100644
--- a/drivers/acpi/acpi_pcc.c
+++ b/drivers/acpi/acpi_pcc.c
@@ -51,7 +51,6 @@ 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);
@@ -59,7 +58,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
return AE_NO_MEMORY;
data->cl.rx_callback = pcc_rx_callback;
- data->cl.knows_txdone = true;
+ data->cl.knows_txdone = false;
data->ctx.length = ctx->length;
data->ctx.subspace_id = ctx->subspace_id;
data->ctx.internal_buffer = ctx->internal_buffer;
@@ -73,61 +72,90 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
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;
- }
-
*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
+acpi_pcc_send_msg_polling(struct pcc_data *data)
+{
+ int ret;
+
+ ret = mbox_send_message(data->pcc_chan->mchan,
+ (__force void *)data->pcc_chan->shmem);
+ if (ret == -ETIME) {
+ pr_err("PCC command executed timeout!\n");
+ return AE_TIME;
+ }
+
+ if (ret < 0)
+ return AE_ERROR;
+
+ if (!mbox_client_peek_data(data->pcc_chan->mchan))
+ return AE_ERROR;
+
+ return AE_OK;
+}
+
+static acpi_status
+acpi_pcc_send_msg_irq(struct pcc_data *data)
+{
+ int ret;
+
+ ret = mbox_send_message(data->pcc_chan->mchan, NULL);
+ if (ret < 0)
+ return AE_ERROR;
+
+ ret = wait_for_completion_timeout(&data->done,
+ usecs_to_jiffies(data->cl.tx_tout * USEC_PER_MSEC));
+ if (ret == 0) {
+ pr_err("PCC command executed timeout!\n");
+ return AE_TIME;
+ }
+
+ mbox_chan_txdone(data->pcc_chan->mchan, ret);
+
+ 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;
+ acpi_status ret;
struct pcc_data *data = region_context;
u64 usecs_lat;
+ bool use_polling = data->pcc_chan->mchan->mbox->txdone_poll;
reinit_completion(&data->done);
/* Write to Shared Memory */
memcpy_toio(data->pcc_chan->shmem, (void *)value, data->ctx.length);
- ret = mbox_send_message(data->pcc_chan->mchan, NULL);
- if (ret < 0)
- return AE_ERROR;
-
/*
* 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);
+ data->cl.tx_block = use_polling;
+ data->cl.tx_tout = div_u64(usecs_lat, USEC_PER_MSEC);
+
+ if (use_polling)
+ ret = acpi_pcc_send_msg_polling(data);
+ else
+ ret = acpi_pcc_send_msg_irq(data);
memcpy_fromio(value, data->pcc_chan->shmem, data->ctx.length);
- return AE_OK;
+ return ret;
}
void __init acpi_init_pcc(void)
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 0a00719b2482..e4e744669f81 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -579,11 +579,17 @@ static void pcc_shutdown(struct mbox_chan *chan)
devm_free_irq(chan->mbox->dev, pchan->plat_irq, chan);
}
+static bool pcc_peek_data(struct mbox_chan *chan)
+{
+ return pcc_mbox_error_check_and_clear(chan->con_priv) == 0;
+}
+
static const struct mbox_chan_ops pcc_chan_ops = {
.send_data = pcc_send_data,
.startup = pcc_startup,
.shutdown = pcc_shutdown,
.last_tx_done = pcc_last_tx_done,
+ .peek_data = pcc_peek_data,
};
/**
@@ -877,8 +883,12 @@ static int pcc_mbox_probe(struct platform_device *pdev)
(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
acpi_pcct_tbl = (struct acpi_table_pcct *) pcct_tbl;
- if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
+ if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL) {
pcc_mbox_ctrl->txdone_irq = true;
+ } else {
+ pcc_mbox_ctrl->txdone_poll = true;
+ pcc_mbox_ctrl->txpoll_period = 1;
+ }
for (i = 0; i < count; i++) {
struct pcc_chan_info *pchan = chan_info + i;
base-commit: 8b690556d8fe074b4f9835075050fba3fb180e93
--
2.51.2
On Wed, Nov 19, 2025 at 10:01:18AM +0100, Andrea Tomassetti wrote: > The goal is to allow clients to submit a message in both irq and polling > mode of the pcc mailbox. The ACPI specification does not require a > platform irq for pcc channels. Let's implement the case where it is not > available. > > peek_data is mapped to pcc_mbox_error_check_and_clear, so that it > returns true if no error occurred while the platform processed last > message, and therefore clients can fetch response data provided by the > platform. > > Tested-by: Thibault Cantori <thibault.cantori@sipearl.com> > Co-developed-by: Olivier Dautricourt <olivier.dautricourt@sipearl.com> > Signed-off-by: Olivier Dautricourt <olivier.dautricourt@sipearl.com> > Signed-off-by: Andrea Tomassetti <andrea.tomassetti@sipearl.com> > Reported-by: kernel test robot <lkp@intel.com> > Closes: https://lore.kernel.org/oe-kbuild-all/202511120243.soxAFpqQ-lkp@intel.com/ > Closes: https://lore.kernel.org/oe-kbuild-all/202511120558.Cln7LF6M-lkp@intel.com/ > Closes: https://lore.kernel.org/oe-kbuild-all/202511120729.R3XQNSnx-lkp@intel.com/ > --- > v2: Fix issues reported by the kernel test robot > - sparse: incorrect type in argument 2 (different address spaces) > - acpi_pcc.c:(.text+0x69): undefined reference to `__udivdi3' > > drivers/acpi/acpi_pcc.c | 78 ++++++++++++++++++++++++++++------------- > drivers/mailbox/pcc.c | 12 ++++++- Please separate the changes to the PCC OpRegion handler and the PCC mailbox driver into individual patches. I’ve also done some cleanup work [1], which has been tested and resolves part of the polling vs. IRQ flag initialization issue. I’d appreciate it if you could rebase your changes on top of those updates to make the review process smoother and help us move forward more quickly. -- Regards, Sudeep [1] https://lore.kernel.org/all/20251016-pcc_mb_updates-v1-0-0fba69616f69@arm.com/
© 2016 - 2025 Red Hat, Inc.