Skip to content

Commit 7ed51e3

Browse files
Pratap Nirujogialexdeucher
authored andcommitted
drm/amd/amdgpu: Fix SMU warning during isp suspend-resume
ISP mfd child devices are using genpd and the system suspend-resume operations between genpd and amdgpu parent device which uses only runtime suspend-resume are not in sync. Linux power manager during suspend-resume resuming the genpd devices earlier than the amdgpu parent device. This is resulting in the below warning as SMU is in suspended state when genpd attempts to resume ISP. WARNING: CPU: 13 PID: 5435 at drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c:398 smu_dpm_set_power_gate+0x36f/0x380 [amdgpu] To fix this warning isp suspend-resume is handled as part of amdgpu parent device suspend-resume instead of genpd sequence. Each ISP MFD child device is marked as dev_pm_syscore_device to skip genpd suspend-resume and use pm_runtime_force api's to suspend-resume the devices when callbacks from amdgpu are received. Co-developed-by: Gjorgji Rosikopulos <grosikop@amd.com> Signed-off-by: Gjorgji Rosikopulos <grosikop@amd.com> Signed-off-by: Bin Du <bin.du@amd.com> Signed-off-by: Pratap Nirujogi <pratap.nirujogi@amd.com> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 0288a34)
1 parent 531b432 commit 7ed51e3

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_isp.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,36 @@ void isp_kernel_buffer_free(void **buf_obj, u64 *gpu_addr, void **cpu_addr)
318318
}
319319
EXPORT_SYMBOL(isp_kernel_buffer_free);
320320

321+
static int isp_resume(struct amdgpu_ip_block *ip_block)
322+
{
323+
struct amdgpu_device *adev = ip_block->adev;
324+
struct amdgpu_isp *isp = &adev->isp;
325+
326+
if (isp->funcs->hw_resume)
327+
return isp->funcs->hw_resume(isp);
328+
329+
return -ENODEV;
330+
}
331+
332+
static int isp_suspend(struct amdgpu_ip_block *ip_block)
333+
{
334+
struct amdgpu_device *adev = ip_block->adev;
335+
struct amdgpu_isp *isp = &adev->isp;
336+
337+
if (isp->funcs->hw_suspend)
338+
return isp->funcs->hw_suspend(isp);
339+
340+
return -ENODEV;
341+
}
342+
321343
static const struct amd_ip_funcs isp_ip_funcs = {
322344
.name = "isp_ip",
323345
.early_init = isp_early_init,
324346
.hw_init = isp_hw_init,
325347
.hw_fini = isp_hw_fini,
326348
.is_idle = isp_is_idle,
349+
.suspend = isp_suspend,
350+
.resume = isp_resume,
327351
.set_clockgating_state = isp_set_clockgating_state,
328352
.set_powergating_state = isp_set_powergating_state,
329353
};

drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ struct amdgpu_isp;
3838
struct isp_funcs {
3939
int (*hw_init)(struct amdgpu_isp *isp);
4040
int (*hw_fini)(struct amdgpu_isp *isp);
41+
int (*hw_suspend)(struct amdgpu_isp *isp);
42+
int (*hw_resume)(struct amdgpu_isp *isp);
4143
};
4244

4345
struct amdgpu_isp {

drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727

2828
#include <linux/gpio/machine.h>
29+
#include <linux/pm_runtime.h>
2930
#include "amdgpu.h"
3031
#include "isp_v4_1_1.h"
3132

@@ -145,6 +146,9 @@ static int isp_genpd_add_device(struct device *dev, void *data)
145146
return -ENODEV;
146147
}
147148

149+
/* The devices will be managed by the pm ops from the parent */
150+
dev_pm_syscore_device(dev, true);
151+
148152
exit:
149153
/* Continue to add */
150154
return 0;
@@ -177,12 +181,47 @@ static int isp_genpd_remove_device(struct device *dev, void *data)
177181
drm_err(&adev->ddev, "Failed to remove dev from genpd %d\n", ret);
178182
return -ENODEV;
179183
}
184+
dev_pm_syscore_device(dev, false);
180185

181186
exit:
182187
/* Continue to remove */
183188
return 0;
184189
}
185190

191+
static int isp_suspend_device(struct device *dev, void *data)
192+
{
193+
return pm_runtime_force_suspend(dev);
194+
}
195+
196+
static int isp_resume_device(struct device *dev, void *data)
197+
{
198+
return pm_runtime_force_resume(dev);
199+
}
200+
201+
static int isp_v4_1_1_hw_suspend(struct amdgpu_isp *isp)
202+
{
203+
int r;
204+
205+
r = device_for_each_child(isp->parent, NULL,
206+
isp_suspend_device);
207+
if (r)
208+
dev_err(isp->parent, "failed to suspend hw devices (%d)\n", r);
209+
210+
return r;
211+
}
212+
213+
static int isp_v4_1_1_hw_resume(struct amdgpu_isp *isp)
214+
{
215+
int r;
216+
217+
r = device_for_each_child(isp->parent, NULL,
218+
isp_resume_device);
219+
if (r)
220+
dev_err(isp->parent, "failed to resume hw device (%d)\n", r);
221+
222+
return r;
223+
}
224+
186225
static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
187226
{
188227
const struct software_node *amd_camera_node, *isp4_node;
@@ -369,6 +408,8 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
369408
static const struct isp_funcs isp_v4_1_1_funcs = {
370409
.hw_init = isp_v4_1_1_hw_init,
371410
.hw_fini = isp_v4_1_1_hw_fini,
411+
.hw_suspend = isp_v4_1_1_hw_suspend,
412+
.hw_resume = isp_v4_1_1_hw_resume,
372413
};
373414

374415
void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp)

0 commit comments

Comments
 (0)