drivers/platform/x86/amd/pmf/auto-mode.c
Source file repositories/reference/linux-study-clean/drivers/platform/x86/amd/pmf/auto-mode.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/platform/x86/amd/pmf/auto-mode.c- Extension
.c- Size
- 17558 bytes
- Lines
- 442
- 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.
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/acpi.hlinux/workqueue.hpmf.h
Detected Declarations
function amd_pmf_dump_auto_mode_defaultsfunction amd_pmf_dump_auto_mode_defaultsfunction amd_pmf_get_moving_avgfunction amd_pmf_trans_automodefunction amd_pmf_update_2_cqlfunction amd_pmf_get_power_thresholdfunction amd_pmf_load_defaults_auto_modefunction amd_pmf_reset_amtfunction amd_pmf_handle_amtfunction amd_pmf_deinit_auto_modefunction amd_pmf_init_auto_mode
Annotated Snippet
static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}
#endif
static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
struct auto_mode_mode_config *table)
{
struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
amd_pmf_send_cmd(dev, SET_SPL, SET_CMD, pwr_ctrl->spl, NULL);
amd_pmf_send_cmd(dev, SET_FPPT, SET_CMD, pwr_ctrl->fppt, NULL);
amd_pmf_send_cmd(dev, SET_SPPT, SET_CMD, pwr_ctrl->sppt, NULL);
amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, SET_CMD, pwr_ctrl->sppt_apu_only, NULL);
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, SET_CMD, pwr_ctrl->stt_min, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, SET_CMD,
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_APU]), NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, SET_CMD,
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_HS2]), NULL);
if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,
config_store.mode_set[idx].fan_control.fan_id);
}
static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
{
int i, total = 0;
if (pdev->socket_power_history_idx == -1) {
for (i = 0; i < AVG_SAMPLE_SIZE; i++)
pdev->socket_power_history[i] = socket_power;
}
pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;
pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;
for (i = 0; i < AVG_SAMPLE_SIZE; i++)
total += pdev->socket_power_history[i];
return total / AVG_SAMPLE_SIZE;
}
void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
{
int avg_power = 0;
bool update = false;
int i, j;
/* Get the average moving average computed by auto mode algorithm */
avg_power = amd_pmf_get_moving_avg(dev, socket_power);
for (i = 0; i < AUTO_TRANSITION_MAX; i++) {
if ((config_store.transition[i].shifting_up && avg_power >=
config_store.transition[i].power_threshold) ||
(!config_store.transition[i].shifting_up && avg_power <=
config_store.transition[i].power_threshold)) {
if (config_store.transition[i].timer <
config_store.transition[i].time_constant)
config_store.transition[i].timer += time_elapsed_ms;
} else {
config_store.transition[i].timer = 0;
}
if (config_store.transition[i].timer >=
config_store.transition[i].time_constant &&
!config_store.transition[i].applied) {
config_store.transition[i].applied = true;
update = true;
} else if (config_store.transition[i].timer <=
config_store.transition[i].time_constant &&
config_store.transition[i].applied) {
config_store.transition[i].applied = false;
update = true;
}
#ifdef CONFIG_AMD_PMF_DEBUG
dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power,
state_as_str(config_store.current_mode));
dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n",
time_elapsed_ms, config_store.transition[i].timer,
config_store.transition[i].time_constant);
dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n",
config_store.transition[i].shifting_up,
config_store.transition[i].power_threshold,
config_store.mode_set[i].power_floor,
config_store.transition[i].power_delta);
#endif
}
Annotation
- Immediate include surface: `linux/acpi.h`, `linux/workqueue.h`, `pmf.h`.
- Detected declarations: `function amd_pmf_dump_auto_mode_defaults`, `function amd_pmf_dump_auto_mode_defaults`, `function amd_pmf_get_moving_avg`, `function amd_pmf_trans_automode`, `function amd_pmf_update_2_cql`, `function amd_pmf_get_power_threshold`, `function amd_pmf_load_defaults_auto_mode`, `function amd_pmf_reset_amt`, `function amd_pmf_handle_amt`, `function amd_pmf_deinit_auto_mode`.
- Atlas domain: Driver Families / drivers/platform.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.