drm/amdgpu: add helper function to do common ras_late_init/fini (v3)
authorHawking Zhang <Hawking.Zhang@amd.com>
Fri, 30 Aug 2019 05:29:18 +0000 (13:29 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 13 Sep 2019 22:11:04 +0000 (17:11 -0500)
In late_init for ras, the helper function will be used to
1). disable ras feature if the IP block is masked as disabled
2). send enable feature command if the ip block was masked as enabled
3). create debugfs/sysfs node per IP block
4). register interrupt handler

v2: check ih_info.cb to decide add interrupt handler or not

v3: add ras_late_fini for cleanup all the ras fs node and remove
interrupt handler

Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h

index f7180109bef405a7249280c6f38a8dc95338fc48..0b466d101f53db733c250f20c1574c0d7ade7e1a 100644 (file)
@@ -1566,6 +1566,78 @@ recovery_out:
        return -EINVAL;
 }
 
+/* helper function to handle common stuff in ip late init phase */
+int amdgpu_ras_late_init(struct amdgpu_device *adev,
+                        struct ras_common_if *ras_block,
+                        struct ras_fs_if *fs_info,
+                        struct ras_ih_if *ih_info)
+{
+       int r;
+
+       /* disable RAS feature per IP block if it is not supported */
+       if (!amdgpu_ras_is_supported(adev, ras_block->block)) {
+               amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0);
+               return 0;
+       }
+
+       r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
+       if (r) {
+               if (r == -EAGAIN) {
+                       /* request gpu reset. will run again */
+                       amdgpu_ras_request_reset_on_boot(adev,
+                                       ras_block->block);
+                       return 0;
+               } else if (adev->in_suspend || adev->in_gpu_reset) {
+                       /* in resume phase, if fail to enable ras,
+                        * clean up all ras fs nodes, and disable ras */
+                       goto cleanup;
+               } else
+                       return r;
+       }
+
+       /* in resume phase, no need to create ras fs node */
+       if (adev->in_suspend || adev->in_gpu_reset)
+               return 0;
+
+       if (ih_info->cb) {
+               r = amdgpu_ras_interrupt_add_handler(adev, ih_info);
+               if (r)
+                       goto interrupt;
+       }
+
+       amdgpu_ras_debugfs_create(adev, fs_info);
+
+       r = amdgpu_ras_sysfs_create(adev, fs_info);
+       if (r)
+               goto sysfs;
+
+       return 0;
+cleanup:
+       amdgpu_ras_sysfs_remove(adev, ras_block);
+sysfs:
+       amdgpu_ras_debugfs_remove(adev, ras_block);
+       if (ih_info->cb)
+               amdgpu_ras_interrupt_remove_handler(adev, ih_info);
+interrupt:
+       amdgpu_ras_feature_enable(adev, ras_block, 0);
+       return r;
+}
+
+/* helper function to remove ras fs node and interrupt handler */
+void amdgpu_ras_late_fini(struct amdgpu_device *adev,
+                         struct ras_common_if *ras_block,
+                         struct ras_ih_if *ih_info)
+{
+       if (!ras_block || !ih_info)
+               return;
+
+       amdgpu_ras_sysfs_remove(adev, ras_block);
+       amdgpu_ras_debugfs_remove(adev, ras_block);
+       if (ih_info->cb)
+                amdgpu_ras_interrupt_remove_handler(adev, ih_info);
+       amdgpu_ras_feature_enable(adev, ras_block, 0);
+}
+
 /* do some init work after IP late init as dependence.
  * and it runs in resume/gpu reset/booting up cases.
  */
index 6c76bb2a684325925ca7952d0d0a41c3372096e4..66b71525446e22f675984b27f6df7acde5570c4a 100644 (file)
@@ -566,6 +566,13 @@ amdgpu_ras_error_to_ta(enum amdgpu_ras_error_type error) {
 int amdgpu_ras_init(struct amdgpu_device *adev);
 int amdgpu_ras_fini(struct amdgpu_device *adev);
 int amdgpu_ras_pre_fini(struct amdgpu_device *adev);
+int amdgpu_ras_late_init(struct amdgpu_device *adev,
+                        struct ras_common_if *ras_block,
+                        struct ras_fs_if *fs_info,
+                        struct ras_ih_if *ih_info);
+void amdgpu_ras_late_fini(struct amdgpu_device *adev,
+                         struct ras_common_if *ras_block,
+                         struct ras_ih_if *ih_info);
 
 int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
                struct ras_common_if *head, bool enable);