On 2020-03-02 2:24 p.m., Andrey Grodzovsky wrote: > Starts USBC PD FW download and reads back the latest FW version. > > Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 94 +++++++++++++++++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > index d33f741..76630b9 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > @@ -24,6 +24,7 @@ > */ > > #include <linux/firmware.h> > +#include <linux/dma-mapping.h> > > #include "amdgpu.h" > #include "amdgpu_psp.h" > @@ -38,6 +39,9 @@ > > static void psp_set_funcs(struct amdgpu_device *adev); > > +static int psp_sysfs_init(struct amdgpu_device *adev); > +static void psp_sysfs_fini(struct amdgpu_device *adev); > + > /* > * Due to DF Cstate management centralized to PMFW, the firmware > * loading sequence will be updated as below: > @@ -94,6 +98,7 @@ static int psp_early_init(void *handle) > psp->autoload_supported = false; > break; > case CHIP_NAVI10: > + psp_sysfs_init(adev); > case CHIP_NAVI14: > case CHIP_NAVI12: > psp_v11_0_set_psp_funcs(psp); > @@ -152,6 +157,10 @@ static int psp_sw_fini(void *handle) > release_firmware(adev->psp.ta_fw); > adev->psp.ta_fw = NULL; > } > + > + if (adev->asic_type == CHIP_NAVI10) > + psp_sysfs_fini(adev); > + > return 0; > } > > @@ -1816,6 +1825,76 @@ static int psp_set_powergating_state(void *handle, > return 0; > } > > +static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, > + struct device_attribute *attr, > + char *buf) Alignment of the parameters is off here. After applying your patch, the alignment looks like the above. > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + uint32_t fw_ver; > + int ret; > + > + ret = psp_read_usbc_pd_fw(&adev->psp, &fw_ver); > + if (ret) { > + DRM_ERROR("Failed to read USBC PD FW, err = %d", ret); > + return ret; > + } > + > + return snprintf(buf, PAGE_SIZE, "%x\n", fw_ver); I'd rather print the firmware version in some fixed format, like say "%08X" (in upper hex digits), since it is not an integer, but a fixed string (8) of hexadecimal numbers. It'll make it easy to copy-and-paste and the visual cue is there when displayed to a screen. Even more so when visually compared, say in a report of what was being tested and so on. > +} > + > +static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, > + struct device_attribute *attr, > + const char *buf, > + size_t count) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + void *cpu_addr; > + dma_addr_t dma_addr; > + int ret = 0; No need to set "ret" to anything here. After all, you cannot predict that "all will be well". Let the compiler prove that it is never being used without being set. > + char fw_name[100]; > + const struct firmware *usbc_pd_fw; > + > + > + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf); > + ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev); > + if (ret) > + goto fail; > + > + /* We need contiguous physical mem to place the FW for psp to access */ > + cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL); > + > + ret = dma_mapping_error(adev->dev, dma_addr); > + if (ret) > + goto rel_buf; "rel_buf" could also be the identifier of a string or a buffer. But if you named it "Out_release_buf", then no one would ever confuse it for a name of a variable (all lower case) or a macro (all upper-case). Not a blocker, just style. > + > + memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); > + > + /*TODO Remove once PSP starts snooping CPU cache */ > + clflush_cache_range(cpu_addr, (usbc_pd_fw->size & ~(L1_CACHE_BYTES - 1))); Not a blocker, but it is easier to read a commment like this: /* TODO: Remove once PSP starts snooping the cache. */ cflush_cache_range(cpu_addr, ...); > + > + ret = psp_load_usbc_pd_fw(&adev->psp, dma_addr); > + > +rel_buf: > + dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr); > + release_firmware(usbc_pd_fw); > + > +fail: > + if (ret) { > + DRM_ERROR("Failed to load USBC PD FW, err = %d", ret); > + return ret; > + } > + > + return count; > +} > + > +static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR, > + psp_usbc_pd_fw_sysfs_read, > + psp_usbc_pd_fw_sysfs_write); > + > + > + > const struct amd_ip_funcs psp_ip_funcs = { > .name = "psp", > .early_init = psp_early_init, > @@ -1834,6 +1913,21 @@ const struct amd_ip_funcs psp_ip_funcs = { > .set_powergating_state = psp_set_powergating_state, > }; > > +static int psp_sysfs_init(struct amdgpu_device *adev) > +{ > + int ret = device_create_file(adev->dev, &dev_attr_usbc_pd_fw); > + > + if (ret) > + DRM_ERROR("Failed to create USBC PD FW control file!"); There's an extra space after the tab char in the above two lines--perhaps from a cut-and-paste. Regards, Luben > + > + return ret; > +} > + > +static void psp_sysfs_fini(struct amdgpu_device *adev) > +{ > + device_remove_file(adev->dev, &dev_attr_usbc_pd_fw); > +} > + > static const struct amdgpu_psp_funcs psp_funcs = { > .check_fw_loading_status = psp_check_fw_loading_status, > }; > _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx