diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index df5d5dbd7f0f..e6f0b035e20b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -2214,7 +2214,8 @@ static int psp_securedisplay_initialize(struct psp_context *psp) if (!psp->securedisplay_context.context.bin_desc.size_bytes || !psp->securedisplay_context.context.bin_desc.start_addr) { - dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); + dev_info(psp->adev->dev, + "SECUREDISPLAY: optional securedisplay ta ucode is not available\n"); return 0; } @@ -4185,6 +4186,110 @@ const struct attribute_group amdgpu_flash_attr_group = { .is_visible = amdgpu_flash_attr_is_visible, }; +#if defined(CONFIG_DEBUG_FS) +static int psp_read_spirom_debugfs_open(struct inode *inode, struct file *filp) +{ + struct amdgpu_device *adev = filp->f_inode->i_private; + struct spirom_bo *bo_triplet; + int ret; + + /* serialize the open() file calling */ + if (!mutex_trylock(&adev->psp.mutex)) + return -EBUSY; + + /* + * make sure only one userpace process is alive for dumping so that + * only one memory buffer of AMD_VBIOS_FILE_MAX_SIZE * 2 is consumed. + * let's say the case where one process try opening the file while + * another one has proceeded to read or release. In this way, eliminate + * the use of mutex for read() or release() callback as well. + */ + if (adev->psp.spirom_dump_trip) { + mutex_unlock(&adev->psp.mutex); + return -EBUSY; + } + + bo_triplet = kzalloc(sizeof(struct spirom_bo), GFP_KERNEL); + if (!bo_triplet) { + mutex_unlock(&adev->psp.mutex); + return -ENOMEM; + } + + ret = amdgpu_bo_create_kernel(adev, AMD_VBIOS_FILE_MAX_SIZE_B * 2, + AMDGPU_GPU_PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT, + &bo_triplet->bo, + &bo_triplet->mc_addr, + &bo_triplet->cpu_addr); + if (ret) + goto rel_trip; + + ret = psp_dump_spirom(&adev->psp, bo_triplet->mc_addr); + if (ret) + goto rel_bo; + + adev->psp.spirom_dump_trip = bo_triplet; + mutex_unlock(&adev->psp.mutex); + return 0; +rel_bo: + amdgpu_bo_free_kernel(&bo_triplet->bo, &bo_triplet->mc_addr, + &bo_triplet->cpu_addr); +rel_trip: + kfree(bo_triplet); + mutex_unlock(&adev->psp.mutex); + dev_err(adev->dev, "Trying IFWI dump fails, err = %d\n", ret); + return ret; +} + +static ssize_t psp_read_spirom_debugfs_read(struct file *filp, char __user *buf, size_t size, + loff_t *pos) +{ + struct amdgpu_device *adev = filp->f_inode->i_private; + struct spirom_bo *bo_triplet = adev->psp.spirom_dump_trip; + + if (!bo_triplet) + return -EINVAL; + + return simple_read_from_buffer(buf, + size, + pos, bo_triplet->cpu_addr, + AMD_VBIOS_FILE_MAX_SIZE_B * 2); +} + +static int psp_read_spirom_debugfs_release(struct inode *inode, struct file *filp) +{ + struct amdgpu_device *adev = filp->f_inode->i_private; + struct spirom_bo *bo_triplet = adev->psp.spirom_dump_trip; + + if (bo_triplet) { + amdgpu_bo_free_kernel(&bo_triplet->bo, &bo_triplet->mc_addr, + &bo_triplet->cpu_addr); + kfree(bo_triplet); + } + + adev->psp.spirom_dump_trip = NULL; + return 0; +} + +static const struct file_operations psp_dump_spirom_debugfs_ops = { + .owner = THIS_MODULE, + .open = psp_read_spirom_debugfs_open, + .read = psp_read_spirom_debugfs_read, + .release = psp_read_spirom_debugfs_release, + .llseek = default_llseek, +}; +#endif + +void amdgpu_psp_debugfs_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + struct drm_minor *minor = adev_to_drm(adev)->primary; + + debugfs_create_file_size("psp_spirom_dump", 0444, minor->debugfs_root, + adev, &psp_dump_spirom_debugfs_ops, AMD_VBIOS_FILE_MAX_SIZE_B * 2); +#endif +} + const struct amd_ip_funcs psp_ip_funcs = { .name = "psp", .early_init = psp_early_init, |