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 ucode_sysfs_en;
|
||||
bool psp_sysfs_en;
|
||||
|
||||
/* Chip product information */
|
||||
char product_number[16];
|
||||
|
|
|
@ -3869,6 +3869,14 @@ fence_driver_init:
|
|||
} else
|
||||
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.
|
||||
* 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);
|
||||
if (adev->ucode_sysfs_en)
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
if (adev->psp_sysfs_en)
|
||||
amdgpu_psp_sysfs_fini(adev);
|
||||
sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
|
||||
|
||||
/* disable ras feature must before hw fini */
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "amdgpu_securedisplay.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 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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.name = "psp",
|
||||
.early_init = psp_early_init,
|
||||
|
@ -3471,6 +3583,11 @@ static int psp_sysfs_init(struct amdgpu_device *adev)
|
|||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
uint32_t boot_cfg_bitmask;
|
||||
|
||||
char *vbflash_tmp_buf;
|
||||
size_t vbflash_image_size;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue