drm/amdgpu: Add reg_state sysfs attribute
authorLijo Lazar <lijo.lazar@amd.com>
Fri, 6 Oct 2023 08:19:03 +0000 (13:49 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 29 Nov 2023 21:49:35 +0000 (16:49 -0500)
Add reg_state attribute to fetch the register snapshot of different
IPs like XGMI, WAFL,PCIE and USR. To get a snapshot for a particular IP
1) Open the sysfs file
2) Seek to the offset as defined in amdgpu_sysfs_reg_offset
3) Read

Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/include/amdgpu_reg_state.h

index 5d3a831..f29d0fa 100644 (file)
@@ -162,6 +162,65 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
 static DEVICE_ATTR(pcie_replay_count, 0444,
                amdgpu_device_get_pcie_replay_count, NULL);
 
+static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj,
+                                         struct bin_attribute *attr, char *buf,
+                                         loff_t ppos, 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);
+       ssize_t bytes_read;
+
+       switch (ppos) {
+       case AMDGPU_SYS_REG_STATE_XGMI:
+               bytes_read = amdgpu_asic_get_reg_state(
+                       adev, AMDGPU_REG_STATE_TYPE_XGMI, buf, count);
+               break;
+       case AMDGPU_SYS_REG_STATE_WAFL:
+               bytes_read = amdgpu_asic_get_reg_state(
+                       adev, AMDGPU_REG_STATE_TYPE_WAFL, buf, count);
+               break;
+       case AMDGPU_SYS_REG_STATE_PCIE:
+               bytes_read = amdgpu_asic_get_reg_state(
+                       adev, AMDGPU_REG_STATE_TYPE_PCIE, buf, count);
+               break;
+       case AMDGPU_SYS_REG_STATE_USR:
+               bytes_read = amdgpu_asic_get_reg_state(
+                       adev, AMDGPU_REG_STATE_TYPE_USR, buf, count);
+               break;
+       case AMDGPU_SYS_REG_STATE_USR_1:
+               bytes_read = amdgpu_asic_get_reg_state(
+                       adev, AMDGPU_REG_STATE_TYPE_USR_1, buf, count);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return bytes_read;
+}
+
+BIN_ATTR(reg_state, 0444, amdgpu_sysfs_reg_state_get, NULL,
+        AMDGPU_SYS_REG_STATE_END);
+
+int amdgpu_reg_state_sysfs_init(struct amdgpu_device *adev)
+{
+       int ret;
+
+       if (!amdgpu_asic_get_reg_state_supported(adev))
+               return 0;
+
+       ret = sysfs_create_bin_file(&adev->dev->kobj, &bin_attr_reg_state);
+
+       return ret;
+}
+
+void amdgpu_reg_state_sysfs_fini(struct amdgpu_device *adev)
+{
+       if (!amdgpu_asic_get_reg_state_supported(adev))
+               return;
+       sysfs_remove_bin_file(&adev->dev->kobj, &bin_attr_reg_state);
+}
+
 /**
  * DOC: board_info
  *
@@ -4233,6 +4292,7 @@ fence_driver_init:
                        "Could not create amdgpu board attributes\n");
 
        amdgpu_fru_sysfs_init(adev);
+       amdgpu_reg_state_sysfs_init(adev);
 
        if (IS_ENABLED(CONFIG_PERF_EVENTS))
                r = amdgpu_pmu_init(adev);
@@ -4355,6 +4415,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
        sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes);
        amdgpu_fru_sysfs_fini(adev);
 
+       amdgpu_reg_state_sysfs_fini(adev);
+
        /* disable ras feature must before hw fini */
        amdgpu_ras_pre_fini(adev);
 
index 3dbdb11..be519c8 100644 (file)
@@ -34,6 +34,15 @@ enum amdgpu_reg_state {
        AMDGPU_REG_STATE_TYPE_USR_1     = 5
 };
 
+enum amdgpu_sysfs_reg_offset {
+       AMDGPU_SYS_REG_STATE_XGMI       = 0x0000,
+       AMDGPU_SYS_REG_STATE_WAFL       = 0x1000,
+       AMDGPU_SYS_REG_STATE_PCIE       = 0x2000,
+       AMDGPU_SYS_REG_STATE_USR        = 0x3000,
+       AMDGPU_SYS_REG_STATE_USR_1      = 0x4000,
+       AMDGPU_SYS_REG_STATE_END        = 0x5000,
+};
+
 struct amdgpu_reg_state_header {
        uint16_t                structure_size;
        uint8_t                 format_revision;
@@ -137,4 +146,8 @@ static inline size_t amdgpu_reginst_size(uint16_t num_inst, size_t inst_size,
                                                   (size)) :               \
                 0)
 
+
+int amdgpu_reg_state_sysfs_init(struct amdgpu_device *adev);
+void amdgpu_reg_state_sysfs_fini(struct amdgpu_device *adev);
+
 #endif