return 0;
}
+static int smu_init_fb_allocations(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ struct smu_table *driver_table = &(smu_table->driver_table);
+ uint32_t max_table_size = 0;
+ int ret, i;
+
+ /* VRAM allocation for tool table */
+ if (tables[SMU_TABLE_PMSTATUSLOG].size) {
+ ret = amdgpu_bo_create_kernel(adev,
+ tables[SMU_TABLE_PMSTATUSLOG].size,
+ tables[SMU_TABLE_PMSTATUSLOG].align,
+ tables[SMU_TABLE_PMSTATUSLOG].domain,
+ &tables[SMU_TABLE_PMSTATUSLOG].bo,
+ &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
+ &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
+ if (ret) {
+ pr_err("VRAM allocation for tool table failed!\n");
+ return ret;
+ }
+ }
+
+ /* VRAM allocation for driver table */
+ for (i = 0; i < SMU_TABLE_COUNT; i++) {
+ if (tables[i].size == 0)
+ continue;
+
+ if (i == SMU_TABLE_PMSTATUSLOG)
+ continue;
+
+ if (max_table_size < tables[i].size)
+ max_table_size = tables[i].size;
+ }
+
+ driver_table->size = max_table_size;
+ driver_table->align = PAGE_SIZE;
+ driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM;
+
+ ret = amdgpu_bo_create_kernel(adev,
+ driver_table->size,
+ driver_table->align,
+ driver_table->domain,
+ &driver_table->bo,
+ &driver_table->mc_address,
+ &driver_table->cpu_addr);
+ if (ret) {
+ pr_err("VRAM allocation for driver table failed!\n");
+ if (tables[SMU_TABLE_PMSTATUSLOG].mc_address)
+ amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo,
+ &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
+ &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
+ }
+
+ return ret;
+}
+
+static int smu_fini_fb_allocations(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ struct smu_table *driver_table = &(smu_table->driver_table);
+
+ if (!tables)
+ return 0;
+
+ if (tables[SMU_TABLE_PMSTATUSLOG].mc_address)
+ amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo,
+ &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
+ &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
+
+ amdgpu_bo_free_kernel(&driver_table->bo,
+ &driver_table->mc_address,
+ &driver_table->cpu_addr);
+
+ return 0;
+}
+
+/**
+ * smu_alloc_memory_pool - allocate memory pool in the system memory
+ *
+ * @smu: amdgpu_device pointer
+ *
+ * This memory pool will be used for SMC use and msg SetSystemVirtualDramAddr
+ * and DramLogSetDramAddr can notify it changed.
+ *
+ * Returns 0 on success, error on failure.
+ */
+static int smu_alloc_memory_pool(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *memory_pool = &smu_table->memory_pool;
+ uint64_t pool_size = smu->pool_size;
+ int ret = 0;
+
+ if (pool_size == SMU_MEMORY_POOL_SIZE_ZERO)
+ return ret;
+
+ memory_pool->size = pool_size;
+ memory_pool->align = PAGE_SIZE;
+ memory_pool->domain = AMDGPU_GEM_DOMAIN_GTT;
+
+ switch (pool_size) {
+ case SMU_MEMORY_POOL_SIZE_256_MB:
+ case SMU_MEMORY_POOL_SIZE_512_MB:
+ case SMU_MEMORY_POOL_SIZE_1_GB:
+ case SMU_MEMORY_POOL_SIZE_2_GB:
+ ret = amdgpu_bo_create_kernel(adev,
+ memory_pool->size,
+ memory_pool->align,
+ memory_pool->domain,
+ &memory_pool->bo,
+ &memory_pool->mc_address,
+ &memory_pool->cpu_addr);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_free_memory_pool(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *memory_pool = &smu_table->memory_pool;
+
+ if (memory_pool->size == SMU_MEMORY_POOL_SIZE_ZERO)
+ return 0;
+
+ amdgpu_bo_free_kernel(&memory_pool->bo,
+ &memory_pool->mc_address,
+ &memory_pool->cpu_addr);
+
+ memset(memory_pool, 0, sizeof(struct smu_table));
+
+ return 0;
+}
+
static int smu_smc_table_sw_init(struct smu_context *smu)
{
int ret;
return ret;
}
+ /*
+ * allocate vram bos to store smc table contents.
+ */
+ ret = smu_init_fb_allocations(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_alloc_memory_pool(smu);
+ if (ret)
+ return ret;
+
return 0;
}
{
int ret;
+ ret = smu_free_memory_pool(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_fini_fb_allocations(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_fini_power(smu);
+ if (ret) {
+ pr_err("Failed to init smu_fini_power!\n");
+ return ret;
+ }
+
ret = smu_fini_smc_tables(smu);
if (ret) {
pr_err("Failed to smu_fini_smc_tables!\n");
return ret;
}
- ret = smu_fini_power(smu);
- if (ret) {
- pr_err("Failed to init smu_fini_power!\n");
- return ret;
- }
-
- return 0;
-}
-
-static int smu_init_fb_allocations(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- struct smu_table_context *smu_table = &smu->smu_table;
- struct smu_table *tables = smu_table->tables;
- struct smu_table *driver_table = &(smu_table->driver_table);
- uint32_t max_table_size = 0;
- int ret, i;
-
- /* VRAM allocation for tool table */
- if (tables[SMU_TABLE_PMSTATUSLOG].size) {
- ret = amdgpu_bo_create_kernel(adev,
- tables[SMU_TABLE_PMSTATUSLOG].size,
- tables[SMU_TABLE_PMSTATUSLOG].align,
- tables[SMU_TABLE_PMSTATUSLOG].domain,
- &tables[SMU_TABLE_PMSTATUSLOG].bo,
- &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
- &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
- if (ret) {
- pr_err("VRAM allocation for tool table failed!\n");
- return ret;
- }
- }
-
- /* VRAM allocation for driver table */
- for (i = 0; i < SMU_TABLE_COUNT; i++) {
- if (tables[i].size == 0)
- continue;
-
- if (i == SMU_TABLE_PMSTATUSLOG)
- continue;
-
- if (max_table_size < tables[i].size)
- max_table_size = tables[i].size;
- }
-
- driver_table->size = max_table_size;
- driver_table->align = PAGE_SIZE;
- driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM;
-
- ret = amdgpu_bo_create_kernel(adev,
- driver_table->size,
- driver_table->align,
- driver_table->domain,
- &driver_table->bo,
- &driver_table->mc_address,
- &driver_table->cpu_addr);
- if (ret) {
- pr_err("VRAM allocation for driver table failed!\n");
- if (tables[SMU_TABLE_PMSTATUSLOG].mc_address)
- amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo,
- &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
- &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
- }
-
- return ret;
-}
-
-static int smu_fini_fb_allocations(struct smu_context *smu)
-{
- struct smu_table_context *smu_table = &smu->smu_table;
- struct smu_table *tables = smu_table->tables;
- struct smu_table *driver_table = &(smu_table->driver_table);
-
- if (!tables)
- return 0;
-
- if (tables[SMU_TABLE_PMSTATUSLOG].mc_address)
- amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo,
- &tables[SMU_TABLE_PMSTATUSLOG].mc_address,
- &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr);
-
- amdgpu_bo_free_kernel(&driver_table->bo,
- &driver_table->mc_address,
- &driver_table->cpu_addr);
-
return 0;
}
return ret;
/*
- * allocate vram bos to store smc table contents.
- */
- ret = smu_init_fb_allocations(smu);
- if (ret)
- return ret;
-
- /*
* Parse pptable format and fill PPTable_t smc_pptable to
* smu_table_context structure. And read the smc_dpm_table from vbios,
* then fill it into smc_pptable.
return ret;
}
-/**
- * smu_alloc_memory_pool - allocate memory pool in the system memory
- *
- * @smu: amdgpu_device pointer
- *
- * This memory pool will be used for SMC use and msg SetSystemVirtualDramAddr
- * and DramLogSetDramAddr can notify it changed.
- *
- * Returns 0 on success, error on failure.
- */
-static int smu_alloc_memory_pool(struct smu_context *smu)
-{
- struct amdgpu_device *adev = smu->adev;
- struct smu_table_context *smu_table = &smu->smu_table;
- struct smu_table *memory_pool = &smu_table->memory_pool;
- uint64_t pool_size = smu->pool_size;
- int ret = 0;
-
- if (pool_size == SMU_MEMORY_POOL_SIZE_ZERO)
- return ret;
-
- memory_pool->size = pool_size;
- memory_pool->align = PAGE_SIZE;
- memory_pool->domain = AMDGPU_GEM_DOMAIN_GTT;
-
- switch (pool_size) {
- case SMU_MEMORY_POOL_SIZE_256_MB:
- case SMU_MEMORY_POOL_SIZE_512_MB:
- case SMU_MEMORY_POOL_SIZE_1_GB:
- case SMU_MEMORY_POOL_SIZE_2_GB:
- ret = amdgpu_bo_create_kernel(adev,
- memory_pool->size,
- memory_pool->align,
- memory_pool->domain,
- &memory_pool->bo,
- &memory_pool->mc_address,
- &memory_pool->cpu_addr);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static int smu_free_memory_pool(struct smu_context *smu)
-{
- struct smu_table_context *smu_table = &smu->smu_table;
- struct smu_table *memory_pool = &smu_table->memory_pool;
-
- if (memory_pool->size == SMU_MEMORY_POOL_SIZE_ZERO)
- return 0;
-
- amdgpu_bo_free_kernel(&memory_pool->bo,
- &memory_pool->mc_address,
- &memory_pool->cpu_addr);
-
- memset(memory_pool, 0, sizeof(struct smu_table));
-
- return 0;
-}
-
static int smu_start_smc_engine(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
if (ret)
goto failed;
- ret = smu_alloc_memory_pool(smu);
- if (ret)
- goto failed;
-
/*
* Use msg SetSystemVirtualDramAddr and DramLogSetDramAddr can notify
* pool location.
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct smu_context *smu = &adev->smu;
- struct smu_table_context *table_context = &smu->smu_table;
int ret = 0;
if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev))
return ret;
}
- kfree(table_context->driver_pptable);
- table_context->driver_pptable = NULL;
-
- kfree(table_context->max_sustainable_clocks);
- table_context->max_sustainable_clocks = NULL;
-
- kfree(table_context->overdrive_table);
- table_context->overdrive_table = NULL;
-
- ret = smu_fini_fb_allocations(smu);
- if (ret)
- return ret;
-
- ret = smu_free_memory_pool(smu);
- if (ret)
- return ret;
-
return 0;
}
struct smu_table *tables = NULL;
int ret = 0;
- if (smu_table->tables)
- return -EINVAL;
-
tables = kcalloc(SMU_TABLE_COUNT, sizeof(struct smu_table),
GFP_KERNEL);
- if (!tables)
- return -ENOMEM;
-
+ if (!tables) {
+ ret = -ENOMEM;
+ goto err0_out;
+ }
smu_table->tables = tables;
ret = smu_tables_init(smu, tables);
if (ret)
- return ret;
+ goto err1_out;
ret = smu_v11_0_init_dpm_context(smu);
if (ret)
- return ret;
+ goto err1_out;
+
+ smu_table->driver_pptable =
+ kzalloc(tables[SMU_TABLE_PPTABLE].size, GFP_KERNEL);
+ if (!smu_table->driver_pptable) {
+ ret = -ENOMEM;
+ goto err2_out;
+ }
+
+ smu_table->max_sustainable_clocks =
+ kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), GFP_KERNEL);
+ if (!smu_table->max_sustainable_clocks) {
+ ret = -ENOMEM;
+ goto err3_out;
+ }
+
+ /* Arcturus does not support OVERDRIVE */
+ if (tables[SMU_TABLE_OVERDRIVE].size) {
+ smu_table->overdrive_table =
+ kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
+ if (!smu_table->overdrive_table) {
+ ret = -ENOMEM;
+ goto err4_out;
+ }
+
+ smu_table->boot_overdrive_table =
+ kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
+ if (!smu_table->boot_overdrive_table) {
+ ret = -ENOMEM;
+ goto err5_out;
+ }
+ }
return 0;
+
+err5_out:
+ kfree(smu_table->overdrive_table);
+err4_out:
+ kfree(smu_table->max_sustainable_clocks);
+err3_out:
+ kfree(smu_table->driver_pptable);
+err2_out:
+ smu_v11_0_fini_dpm_context(smu);
+err1_out:
+ kfree(tables);
+err0_out:
+ return ret;
}
int smu_v11_0_fini_smc_tables(struct smu_context *smu)
if (!smu_table->tables)
return -EINVAL;
+ kfree(smu_table->boot_overdrive_table);
+ kfree(smu_table->overdrive_table);
+ kfree(smu_table->max_sustainable_clocks);
+ kfree(smu_table->driver_pptable);
+ smu_table->boot_overdrive_table = NULL;
+ smu_table->overdrive_table = NULL;
+ smu_table->max_sustainable_clocks = NULL;
+ smu_table->driver_pptable = NULL;
+ kfree(smu_table->hardcode_pptable);
+ smu_table->hardcode_pptable = NULL;
+
kfree(smu_table->tables);
kfree(smu_table->metrics_table);
kfree(smu_table->watermarks_table);
{
int ret;
- struct smu_table_context *table_context = &smu->smu_table;
- struct smu_table *table = &table_context->tables[SMU_TABLE_PPTABLE];
-
- /* during TDR we need to free and alloc the pptable */
- if (table_context->driver_pptable)
- kfree(table_context->driver_pptable);
-
- table_context->driver_pptable = kzalloc(table->size, GFP_KERNEL);
-
- if (!table_context->driver_pptable)
- return -ENOMEM;
-
ret = smu_store_powerplay_table(smu);
if (ret)
return -EINVAL;
int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
{
- struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
+ struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
+ smu->smu_table.max_sustainable_clocks;
int ret = 0;
- if (!smu->smu_table.max_sustainable_clocks)
- max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
- GFP_KERNEL);
- else
- max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
-
- smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
-
max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100;
max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100;
int ret = 0;
if (initialize) {
- if (table_context->overdrive_table) {
- return -EINVAL;
- }
- table_context->overdrive_table = kzalloc(overdrive_table_size, GFP_KERNEL);
- if (!table_context->overdrive_table) {
- return -ENOMEM;
- }
ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, false);
if (ret) {
pr_err("Failed to export overdrive table!\n");
return ret;
}
- if (!table_context->boot_overdrive_table) {
- table_context->boot_overdrive_table = kmemdup(table_context->overdrive_table, overdrive_table_size, GFP_KERNEL);
- if (!table_context->boot_overdrive_table) {
- return -ENOMEM;
- }
- }
}
ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
if (ret) {