drivers/platform/x86/amd/pmf/spc.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/amd/pmf/spc.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/amd/pmf/spc.c
Extension
.c
Size
10185 bytes
Lines
349
Domain
Driver Families
Bucket
drivers/platform
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

void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {}
#endif

/*
 * This helper function sets the appropriate BIOS input value in the TA enact
 * table based on the provided index. We need this approach because the custom
 * BIOS input array is not continuous, due to the existing TA structure layout.
 */
static void amd_pmf_set_ta_custom_bios_input(struct ta_pmf_enact_table *in, int index, u32 value)
{
	switch (index) {
	case 0 ... 1:
		in->ev_info.bios_input_1[index] = value;
		break;
	case 2 ... 9:
		in->ev_info.bios_input_2[index - 2] = value;
		break;
	default:
		return;
	}
}

static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, struct pmf_bios_input_entry *data,
				       const struct amd_pmf_pb_bitmap *inputs,
				       struct ta_pmf_enact_table *in)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) {
		if (!(data->preq & inputs[i].bit_mask))
			continue;
		amd_pmf_set_ta_custom_bios_input(in, i, data->val[i]);
		pdev->cb_prev.custom_bios_inputs[i] = data->val[i];
		dev_dbg(pdev->dev, "Custom BIOS Input[%d]: %u\n", i, data->val[i]);
	}
}

static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev,
					   struct ta_pmf_enact_table *in)
{
	struct pmf_cbi_ring_buffer *rb = &pdev->cbi_buf;
	unsigned int i;

	guard(mutex)(&pdev->cbi_mutex);

	for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
		amd_pmf_set_ta_custom_bios_input(in, i, pdev->cb_prev.custom_bios_inputs[i]);

	if (CIRC_CNT(rb->head, rb->tail, CUSTOM_BIOS_INPUT_RING_ENTRIES) == 0)
		return;

	/* If no active custom BIOS input pending request, do not consume further work */
	if (!rb->data[rb->tail].preq)
		goto out_rbadvance;

	if (!pdev->smart_pc_enabled)
		return;

	switch (pdev->pmf_if_version) {
	case PMF_IF_V1:
		if (!is_apmf_bios_input_notifications_supported(pdev))
			return;
		amd_pmf_update_bios_inputs(pdev, &rb->data[rb->tail], custom_bios_inputs_v1, in);
		break;
	case PMF_IF_V2:
		amd_pmf_update_bios_inputs(pdev, &rb->data[rb->tail], custom_bios_inputs, in);
		break;
	default:
		break;
	}

out_rbadvance:
	rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1);
}

static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in)
{
	u16 max, avg = 0;
	int i;

	/* Get the avg and max C0 residency of all the cores */
	max = *core_res;
	for (i = 0; i < size; i++) {
		avg += core_res[i];
		if (core_res[i] > max)
			max = core_res[i];
	}
	avg = DIV_ROUND_CLOSEST(avg, size);
	in->ev_info.avg_c0residency = avg;
	in->ev_info.max_c0residency = max;

Annotation

Implementation Notes