Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: PCC: Setup PCC Opregion handler only if platform interrupt is available

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>

authored by

Huisong Li and committed by
Rafael J. Wysocki
a10b1c99 8338b74a

+29 -18
+29 -18
drivers/acpi/acpi_pcc.c
··· 53 53 struct pcc_data *data; 54 54 struct acpi_pcc_info *ctx = handler_context; 55 55 struct pcc_mbox_chan *pcc_chan; 56 + static acpi_status ret; 56 57 57 58 data = kzalloc(sizeof(*data), GFP_KERNEL); 58 59 if (!data) ··· 70 69 if (IS_ERR(data->pcc_chan)) { 71 70 pr_err("Failed to find PCC channel for subspace %d\n", 72 71 ctx->subspace_id); 73 - kfree(data); 74 - return AE_NOT_FOUND; 72 + ret = AE_NOT_FOUND; 73 + goto err_free_data; 75 74 } 76 75 77 76 pcc_chan = data->pcc_chan; 77 + if (!pcc_chan->mchan->mbox->txdone_irq) { 78 + pr_err("This channel-%d does not support interrupt.\n", 79 + ctx->subspace_id); 80 + ret = AE_SUPPORT; 81 + goto err_free_channel; 82 + } 78 83 data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr, 79 84 pcc_chan->shmem_size); 80 85 if (!data->pcc_comm_addr) { 81 86 pr_err("Failed to ioremap PCC comm region mem for %d\n", 82 87 ctx->subspace_id); 83 - pcc_mbox_free_channel(data->pcc_chan); 84 - kfree(data); 85 - return AE_NO_MEMORY; 88 + ret = AE_NO_MEMORY; 89 + goto err_free_channel; 86 90 } 87 91 88 92 *region_context = data; 89 93 return AE_OK; 94 + 95 + err_free_channel: 96 + pcc_mbox_free_channel(data->pcc_chan); 97 + err_free_data: 98 + kfree(data); 99 + 100 + return ret; 90 101 } 91 102 92 103 static acpi_status ··· 119 106 if (ret < 0) 120 107 return AE_ERROR; 121 108 122 - if (data->pcc_chan->mchan->mbox->txdone_irq) { 123 - /* 124 - * pcc_chan->latency is just a Nominal value. In reality the remote 125 - * processor could be much slower to reply. So add an arbitrary 126 - * amount of wait on top of Nominal. 127 - */ 128 - usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; 129 - ret = wait_for_completion_timeout(&data->done, 130 - usecs_to_jiffies(usecs_lat)); 131 - if (ret == 0) { 132 - pr_err("PCC command executed timeout!\n"); 133 - return AE_TIME; 134 - } 109 + /* 110 + * pcc_chan->latency is just a Nominal value. In reality the remote 111 + * processor could be much slower to reply. So add an arbitrary 112 + * amount of wait on top of Nominal. 113 + */ 114 + usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; 115 + ret = wait_for_completion_timeout(&data->done, 116 + usecs_to_jiffies(usecs_lat)); 117 + if (ret == 0) { 118 + pr_err("PCC command executed timeout!\n"); 119 + return AE_TIME; 135 120 } 136 121 137 122 mbox_chan_txdone(data->pcc_chan->mchan, ret);