Commit 47606002 authored by Lijo Lazar's avatar Lijo Lazar Committed by Alex Deucher
Browse files

drm/amd/pm: Add cache logic for temperature metric



Add caching logic for baseboard and gpuboard temperature metrics tables.

Signed-off-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Reviewed-by: default avatarAsad Kamal <asad.kamal@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 615471b8
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -3835,6 +3835,9 @@ int smu_set_pm_policy(struct smu_context *smu, enum pp_pm_policy p_type,
static ssize_t smu_sys_get_temp_metrics(void *handle, enum smu_temp_metric_type type, void *table)
{
	struct smu_context *smu = handle;
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *tables = smu_table->tables;
	enum smu_table_id table_id;

	if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
		return -EOPNOTSUPP;
@@ -3842,6 +3845,21 @@ static ssize_t smu_sys_get_temp_metrics(void *handle, enum smu_temp_metric_type
	if (!smu->smu_temp.temp_funcs || !smu->smu_temp.temp_funcs->get_temp_metrics)
		return -EOPNOTSUPP;

	table_id = smu_metrics_get_temp_table_id(type);

	if (table_id == SMU_TABLE_COUNT)
		return -EINVAL;

	/* If the request is to get size alone, return the cached table size */
	if (!table && tables[table_id].cache.size)
		return tables[table_id].cache.size;

	if (smu_table_cache_is_valid(&tables[table_id])) {
		memcpy(table, tables[table_id].cache.buffer,
		       tables[table_id].cache.size);
		return tables[table_id].cache.size;
	}

	return smu->smu_temp.temp_funcs->get_temp_metrics(smu, type, table);
}

+76 −2
Original line number Diff line number Diff line
@@ -249,6 +249,14 @@ struct smu_user_dpm_profile {
		tables[table_id].domain = d;		\
	} while (0)

struct smu_table_cache {
	void *buffer;
	size_t size;
	/* interval in ms*/
	uint32_t interval;
	unsigned long last_cache_time;
};

struct smu_table {
	uint64_t size;
	uint32_t align;
@@ -257,7 +265,7 @@ struct smu_table {
	void *cpu_addr;
	struct amdgpu_bo *bo;
	uint32_t version;
	unsigned long  metrics_time;
	struct smu_table_cache cache;
};

enum smu_perf_level_designation {
@@ -323,7 +331,8 @@ enum smu_table_id {
	SMU_TABLE_ECCINFO,
	SMU_TABLE_COMBO_PPTABLE,
	SMU_TABLE_WIFIBAND,
	SMU_TABLE_TEMP_METRICS,
	SMU_TABLE_GPUBOARD_TEMP_METRICS,
	SMU_TABLE_BASEBOARD_TEMP_METRICS,
	SMU_TABLE_COUNT,
};

@@ -1651,6 +1660,71 @@ typedef struct {
struct smu_dpm_policy *smu_get_pm_policy(struct smu_context *smu,
					 enum pp_pm_policy p_type);

static inline enum smu_table_id
smu_metrics_get_temp_table_id(enum smu_temp_metric_type type)
{
	switch (type) {
	case SMU_TEMP_METRIC_BASEBOARD:
		return SMU_TABLE_BASEBOARD_TEMP_METRICS;
	case SMU_TEMP_METRIC_GPUBOARD:
		return SMU_TABLE_GPUBOARD_TEMP_METRICS;
	default:
		return SMU_TABLE_COUNT;
	}

	return SMU_TABLE_COUNT;
}

static inline void smu_table_cache_update_time(struct smu_table *table,
					       unsigned long time)
{
	table->cache.last_cache_time = time;
}

static inline bool smu_table_cache_is_valid(struct smu_table *table)
{
	if (!table->cache.buffer || !table->cache.last_cache_time ||
	    !table->cache.interval || !table->cache.size ||
	    time_after(jiffies,
		       table->cache.last_cache_time +
			       msecs_to_jiffies(table->cache.interval)))
		return false;

	return true;
}

static inline int smu_table_cache_init(struct smu_context *smu,
				       enum smu_table_id table_id, size_t size,
				       uint32_t cache_interval)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *tables = smu_table->tables;

	tables[table_id].cache.buffer = kzalloc(size, GFP_KERNEL);
	if (!tables[table_id].cache.buffer)
		return -ENOMEM;

	tables[table_id].cache.last_cache_time = 0;
	tables[table_id].cache.interval = cache_interval;
	tables[table_id].cache.size = size;

	return 0;
}

static inline void smu_table_cache_fini(struct smu_context *smu,
					enum smu_table_id table_id)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *tables = smu_table->tables;

	if (tables[table_id].cache.buffer) {
		kfree(tables[table_id].cache.buffer);
		tables[table_id].cache.buffer = NULL;
		tables[table_id].cache.last_cache_time = 0;
		tables[table_id].cache.interval = 0;
	}
}

#if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4)
int smu_get_power_limit(void *handle,
			uint32_t *limit,