drm/amdgpu/psp: Add vbflash sysfs interface support
Add sysfs interface to copy VBIOS. v2: squash in fix for proper vmalloc API (Alex) Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
09fffcd969
commit
8424f2ccb3
@ -1008,6 +1008,7 @@ struct amdgpu_device {
|
|||||||
|
|
||||||
bool pm_sysfs_en;
|
bool pm_sysfs_en;
|
||||||
bool ucode_sysfs_en;
|
bool ucode_sysfs_en;
|
||||||
|
bool psp_sysfs_en;
|
||||||
|
|
||||||
/* Chip product information */
|
/* Chip product information */
|
||||||
char product_number[16];
|
char product_number[16];
|
||||||
|
@ -3869,6 +3869,14 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||||||
} else
|
} else
|
||||||
adev->ucode_sysfs_en = true;
|
adev->ucode_sysfs_en = true;
|
||||||
|
|
||||||
|
r = amdgpu_psp_sysfs_init(adev);
|
||||||
|
if (r) {
|
||||||
|
adev->psp_sysfs_en = false;
|
||||||
|
if (!amdgpu_sriov_vf(adev))
|
||||||
|
DRM_ERROR("Creating psp sysfs failed\n");
|
||||||
|
} else
|
||||||
|
adev->psp_sysfs_en = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
|
* Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
|
||||||
* Otherwise the mgpu fan boost feature will be skipped due to the
|
* Otherwise the mgpu fan boost feature will be skipped due to the
|
||||||
@ -4001,6 +4009,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
|||||||
amdgpu_pm_sysfs_fini(adev);
|
amdgpu_pm_sysfs_fini(adev);
|
||||||
if (adev->ucode_sysfs_en)
|
if (adev->ucode_sysfs_en)
|
||||||
amdgpu_ucode_sysfs_fini(adev);
|
amdgpu_ucode_sysfs_fini(adev);
|
||||||
|
if (adev->psp_sysfs_en)
|
||||||
|
amdgpu_psp_sysfs_fini(adev);
|
||||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||||
|
|
||||||
/* disable ras feature must before hw fini */
|
/* disable ras feature must before hw fini */
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include "amdgpu_securedisplay.h"
|
#include "amdgpu_securedisplay.h"
|
||||||
#include "amdgpu_atomfirmware.h"
|
#include "amdgpu_atomfirmware.h"
|
||||||
|
|
||||||
|
#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*3)
|
||||||
|
|
||||||
static int psp_sysfs_init(struct amdgpu_device *adev);
|
static int psp_sysfs_init(struct amdgpu_device *adev);
|
||||||
static void psp_sysfs_fini(struct amdgpu_device *adev);
|
static void psp_sysfs_fini(struct amdgpu_device *adev);
|
||||||
|
|
||||||
@ -3443,6 +3445,116 @@ int is_psp_fw_valid(struct psp_bin_desc bin)
|
|||||||
return bin.size_bytes;
|
return bin.size_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t amdgpu_psp_vbflash_write(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *bin_attr,
|
||||||
|
char *buffer, loff_t pos, size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = kobj_to_dev(kobj);
|
||||||
|
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||||
|
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||||
|
|
||||||
|
/* Safeguard against memory drain */
|
||||||
|
if (adev->psp.vbflash_image_size > AMD_VBIOS_FILE_MAX_SIZE_B) {
|
||||||
|
dev_err(adev->dev, "File size cannot exceed %u", AMD_VBIOS_FILE_MAX_SIZE_B);
|
||||||
|
kvfree(adev->psp.vbflash_tmp_buf);
|
||||||
|
adev->psp.vbflash_tmp_buf = NULL;
|
||||||
|
adev->psp.vbflash_image_size = 0;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Just allocate max for now and optimize to realloc later if needed */
|
||||||
|
if (!adev->psp.vbflash_tmp_buf) {
|
||||||
|
adev->psp.vbflash_tmp_buf = kvmalloc(AMD_VBIOS_FILE_MAX_SIZE_B, GFP_KERNEL);
|
||||||
|
if (!adev->psp.vbflash_tmp_buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&adev->psp.mutex);
|
||||||
|
memcpy(adev->psp.vbflash_tmp_buf + pos, buffer, count);
|
||||||
|
adev->psp.vbflash_image_size += count;
|
||||||
|
mutex_unlock(&adev->psp.mutex);
|
||||||
|
|
||||||
|
dev_info(adev->dev, "VBIOS flash write PSP done");
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t amdgpu_psp_vbflash_read(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *bin_attr, char *buffer,
|
||||||
|
loff_t pos, size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = kobj_to_dev(kobj);
|
||||||
|
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||||
|
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||||
|
struct amdgpu_bo *fw_buf_bo = NULL;
|
||||||
|
uint64_t fw_pri_mc_addr;
|
||||||
|
void *fw_pri_cpu_addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_info(adev->dev, "VBIOS flash to PSP started");
|
||||||
|
|
||||||
|
ret = amdgpu_bo_create_kernel(adev, adev->psp.vbflash_image_size,
|
||||||
|
AMDGPU_GPU_PAGE_SIZE,
|
||||||
|
AMDGPU_GEM_DOMAIN_VRAM,
|
||||||
|
&fw_buf_bo,
|
||||||
|
&fw_pri_mc_addr,
|
||||||
|
&fw_pri_cpu_addr);
|
||||||
|
if (ret)
|
||||||
|
goto rel_buf;
|
||||||
|
|
||||||
|
memcpy_toio(fw_pri_cpu_addr, adev->psp.vbflash_tmp_buf, adev->psp.vbflash_image_size);
|
||||||
|
|
||||||
|
mutex_lock(&adev->psp.mutex);
|
||||||
|
ret = psp_update_spirom(&adev->psp, fw_pri_mc_addr);
|
||||||
|
mutex_unlock(&adev->psp.mutex);
|
||||||
|
|
||||||
|
amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
|
||||||
|
|
||||||
|
rel_buf:
|
||||||
|
kvfree(adev->psp.vbflash_tmp_buf);
|
||||||
|
adev->psp.vbflash_tmp_buf = NULL;
|
||||||
|
adev->psp.vbflash_image_size = 0;
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
dev_err(adev->dev, "Failed to load VBIOS FW, err = %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(adev->dev, "VBIOS flash to PSP done");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct bin_attribute psp_vbflash_bin_attr = {
|
||||||
|
.attr = {.name = "psp_vbflash", .mode = 0664},
|
||||||
|
.size = 0,
|
||||||
|
.write = amdgpu_psp_vbflash_write,
|
||||||
|
.read = amdgpu_psp_vbflash_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
int amdgpu_psp_sysfs_init(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct psp_context *psp = &adev->psp;
|
||||||
|
|
||||||
|
if (amdgpu_sriov_vf(adev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||||
|
case IP_VERSION(13, 0, 0):
|
||||||
|
case IP_VERSION(13, 0, 7):
|
||||||
|
if (!psp->adev) {
|
||||||
|
psp->adev = adev;
|
||||||
|
psp_v13_0_set_psp_funcs(psp);
|
||||||
|
}
|
||||||
|
ret = sysfs_create_bin_file(&adev->dev->kobj, &psp_vbflash_bin_attr);
|
||||||
|
if (ret)
|
||||||
|
dev_err(adev->dev, "Failed to create device file psp_vbflash");
|
||||||
|
return ret;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const struct amd_ip_funcs psp_ip_funcs = {
|
const struct amd_ip_funcs psp_ip_funcs = {
|
||||||
.name = "psp",
|
.name = "psp",
|
||||||
.early_init = psp_early_init,
|
.early_init = psp_early_init,
|
||||||
@ -3471,6 +3583,11 @@ static int psp_sysfs_init(struct amdgpu_device *adev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void amdgpu_psp_sysfs_fini(struct amdgpu_device *adev)
|
||||||
|
{
|
||||||
|
sysfs_remove_bin_file(&adev->dev->kobj, &psp_vbflash_bin_attr);
|
||||||
|
}
|
||||||
|
|
||||||
static void psp_sysfs_fini(struct amdgpu_device *adev)
|
static void psp_sysfs_fini(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
device_remove_file(adev->dev, &dev_attr_usbc_pd_fw);
|
device_remove_file(adev->dev, &dev_attr_usbc_pd_fw);
|
||||||
|
@ -372,6 +372,9 @@ struct psp_context
|
|||||||
struct psp_memory_training_context mem_train_ctx;
|
struct psp_memory_training_context mem_train_ctx;
|
||||||
|
|
||||||
uint32_t boot_cfg_bitmask;
|
uint32_t boot_cfg_bitmask;
|
||||||
|
|
||||||
|
char *vbflash_tmp_buf;
|
||||||
|
size_t vbflash_image_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amdgpu_psp_funcs {
|
struct amdgpu_psp_funcs {
|
||||||
@ -501,4 +504,7 @@ int psp_load_fw_list(struct psp_context *psp,
|
|||||||
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
|
void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size);
|
||||||
|
|
||||||
int is_psp_fw_valid(struct psp_bin_desc bin);
|
int is_psp_fw_valid(struct psp_bin_desc bin);
|
||||||
|
|
||||||
|
int amdgpu_psp_sysfs_init(struct amdgpu_device *adev);
|
||||||
|
void amdgpu_psp_sysfs_fini(struct amdgpu_device *adev);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user