Unverified Commit 43c34ad0 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!8808 v2 Add support for PCC Operation Region

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhang Zekun <zhangzekun11@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/FA255IRWPFWVYR5CDWBXIUN2NVGBSW6K/ 
Add support for PCC Operation Region

v2:
- Fix check format error
- Add configs in x86, because it will be enabled by default

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


-- 
2.17.1
 
https://gitee.com/openeuler/kernel/issues/I9VPZ8 
 
Link:https://gitee.com/openeuler/kernel/pulls/8808

 

Reviewed-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents afef0523 5d2678d6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ CONFIG_ACPI_WATCHDOG=y
CONFIG_ACPI_EXTLOG=m
CONFIG_ACPI_ADXL=y
# CONFIG_ACPI_CONFIGFS is not set
CONFIG_ACPI_PCC=y
CONFIG_PMIC_OPREGION=y
CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_PRMT=y
+17 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+153 −0
Original line number Diff line number Diff line
// 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>

/*
 * Arbitrary retries in case the remote processor is slow to respond
 * to PCC commands
 */
#define PCC_CMD_WAIT_RETRIES_NUM	500ULL

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;
};

static 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;
	static acpi_status ret;

	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);
		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);
		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
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;
	u64 usecs_lat;

	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;

	/*
	 * 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);

	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");
}
Loading