[PATCH 3.14 067/228] drm/radeon: fix runpm handling on APUs (v4)

Greg Kroah-Hartman
2014-06-05T00:34:18Z

From: Alex Deucher <alexdeucher@gmail.com>

commit 90c4cde9d5a2bb6239cb3e253bb3832ed89dc75c upstream.

Don't try and runtime suspend the APU in PX systems. We
only want to power down the dGPU.

v2: fix harder
v3: fix stupid typo
v4: consolidate runpm enablement to a single flag

bugs:
https://bugs.freedesktop.org/show_bug.cgi?id=75127
https://bugzilla.kernel.org/show_bug.cgi?id=72701

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
drivers/gpu/drm/radeon/radeon.h | 1 +
drivers/gpu/drm/radeon/radeon_atpx_handler.c | 2 +-
drivers/gpu/drm/radeon/radeon_device.c | 19 ++++++++++---------
drivers/gpu/drm/radeon/radeon_drv.c | 24 ++++--------------------
drivers/gpu/drm/radeon/radeon_family.h | 1 +
drivers/gpu/drm/radeon/radeon_kms.c | 14 ++++++++++----
6 files changed, 27 insertions(+), 34 deletions(-)

--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -2242,6 +2242,7 @@ struct radeon_device {
bool have_disp_power_ref;
};

+bool radeon_is_px(struct drm_device *dev);
int radeon_device_init(struct radeon_device *rdev,
struct drm_device *ddev,
struct pci_dev *pdev,
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -59,7 +59,7 @@ struct atpx_mux {
u16 mux;
} __packed;

-bool radeon_is_px(void) {
+bool radeon_has_atpx(void) {
return radeon_atpx_priv.atpx_detected;
}

--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -102,11 +102,14 @@ static const char radeon_family_name[][1
"LAST",
};

-#if defined(CONFIG_VGA_SWITCHEROO)
-bool radeon_is_px(void);
-#else
-static inline bool radeon_is_px(void) { return false; }
-#endif
+bool radeon_is_px(struct drm_device *dev)
+{
+ struct radeon_device *rdev = dev->dev_private;
+
+ if (rdev->flags & RADEON_IS_PX)
+ return true;
+ return false;
+}

/**
* radeon_program_register_sequence - program an array of registers.
@@ -1082,7 +1085,7 @@ static void radeon_switcheroo_set_state(
{
struct drm_device *dev = pci_get_drvdata(pdev);

- if (radeon_is_px() && state == VGA_SWITCHEROO_OFF)
+ if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return;

if (state == VGA_SWITCHEROO_ON) {
@@ -1303,9 +1306,7 @@ int radeon_device_init(struct radeon_dev
* ignore it */
vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);

- if (radeon_runtime_pm == 1)
- runtime = true;
- if ((radeon_runtime_pm == -1) && radeon_is_px())
+ if (rdev->flags & RADEON_IS_PX)
runtime = true;
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
if (runtime)
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -113,6 +113,7 @@ extern int radeon_get_crtc_scanoutpos(st
unsigned int flags,
int *vpos, int *hpos, ktime_t *stime,
ktime_t *etime);
+extern bool radeon_is_px(struct drm_device *dev);
extern const struct drm_ioctl_desc radeon_ioctls_kms[];
extern int radeon_max_kms_ioctl;
int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -142,11 +143,9 @@ void radeon_debugfs_cleanup(struct drm_m
#if defined(CONFIG_VGA_SWITCHEROO)
void radeon_register_atpx_handler(void);
void radeon_unregister_atpx_handler(void);
-bool radeon_is_px(void);
#else
static inline void radeon_register_atpx_handler(void) {}
static inline void radeon_unregister_atpx_handler(void) {}
-static inline bool radeon_is_px(void) { return false; }
#endif

int radeon_no_wb;
@@ -403,12 +402,7 @@ static int radeon_pmops_runtime_suspend(
struct drm_device *drm_dev = pci_get_drvdata(pdev);
int ret;

- if (radeon_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- if (radeon_runtime_pm == -1 && !radeon_is_px()) {
+ if (!radeon_is_px(drm_dev)) {
pm_runtime_forbid(dev);
return -EBUSY;
}
@@ -432,10 +426,7 @@ static int radeon_pmops_runtime_resume(s
struct drm_device *drm_dev = pci_get_drvdata(pdev);
int ret;

- if (radeon_runtime_pm == 0)
- return -EINVAL;
-
- if (radeon_runtime_pm == -1 && !radeon_is_px())
+ if (!radeon_is_px(drm_dev))
return -EINVAL;

drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -460,14 +451,7 @@ static int radeon_pmops_runtime_idle(str
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct drm_crtc *crtc;

- if (radeon_runtime_pm == 0) {
- pm_runtime_forbid(dev);
- return -EBUSY;
- }
-
- /* are we PX enabled? */
- if (radeon_runtime_pm == -1 && !radeon_is_px()) {
- DRM_DEBUG_DRIVER("failing to power off - not px\n");
+ if (!radeon_is_px(drm_dev)) {
pm_runtime_forbid(dev);
return -EBUSY;
}
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -115,6 +115,7 @@ enum radeon_chip_flags {
RADEON_NEW_MEMMAP = 0x00400000UL,
RADEON_IS_PCI = 0x00800000UL,
RADEON_IS_IGPGART = 0x01000000UL,
+ RADEON_IS_PX = 0x02000000UL,
};

#endif
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -35,9 +35,9 @@
#include <linux/pm_runtime.h>

#if defined(CONFIG_VGA_SWITCHEROO)
-bool radeon_is_px(void);
+bool radeon_has_atpx(void);
#else
-static inline bool radeon_is_px(void) { return false; }
+static inline bool radeon_has_atpx(void) { return false; }
#endif

/**
@@ -107,6 +107,13 @@ int radeon_driver_load_kms(struct drm_de
flags |= RADEON_IS_PCI;
}

+ if (radeon_runtime_pm == 1)
+ flags |= RADEON_IS_PX;
+ else if ((radeon_runtime_pm == -1) &&
+ radeon_has_atpx() &&
+ ((flags & RADEON_IS_IGP) == 0))
+ flags |= RADEON_IS_PX;
+
/* radeon_device_init should report only fatal error
* like memory allocation failure or iomapping failure,
* or memory manager initialization failure, it must
@@ -137,8 +144,7 @@ int radeon_driver_load_kms(struct drm_de
"Error during ACPI methods call\n");
}

- if ((radeon_runtime_pm == 1) ||
- ((radeon_runtime_pm == -1) && radeon_is_px())) {
+ if (radeon_is_px(dev)) {
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
pm_runtime_set_active(dev->dev);