drivers/acpi/acpi_pcc.c

Source file repositories/reference/linux-study-clean/drivers/acpi/acpi_pcc.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/acpi_pcc.c
Extension
.c
Size
3886 bytes
Lines
145
Domain
Driver Families
Bucket
drivers/acpi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pcc_data {
	struct pcc_mbox_chan *pcc_chan;
	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;
	acpi_status ret;

	data = kzalloc_obj(*data);
	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;
	}

	*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_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) {

Annotation

Implementation Notes