Hi Is there an easy way to check this is on?
I have radeon.dynpm=1 in grub but usually when I use switcheroo I see messages saying the card if now off at the moment I can old see messages saying when the card gets powered up Is it possible to have the on and off messages appearing? Cheers Mike On 20 September 2013 18:18, Alex Deucher <alexdeucher at gmail.com> wrote: > From: Dave Airlie <airlied at redhat.com> > > This hooks radeon up to the runtime PM system to enable > dynamic power management for secondary GPUs in switchable > and powerxpress laptops. > > v2: agd5f: clean up, add module parameter > > Signed-off-by: Dave Airlie <airlied at redhat.com> > Signed-off-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/radeon/radeon.h | 8 +- > drivers/gpu/drm/radeon/radeon_atpx_handler.c | 4 + > drivers/gpu/drm/radeon/radeon_connectors.c | 63 ++++++++++++-- > drivers/gpu/drm/radeon/radeon_device.c | 52 +++++++++--- > drivers/gpu/drm/radeon/radeon_display.c | 47 ++++++++++- > drivers/gpu/drm/radeon/radeon_drv.c | 122 > +++++++++++++++++++++++++-- > drivers/gpu/drm/radeon/radeon_drv.h | 3 + > drivers/gpu/drm/radeon/radeon_ioc32.c | 2 +- > drivers/gpu/drm/radeon/radeon_irq_kms.c | 8 +- > drivers/gpu/drm/radeon/radeon_kms.c | 26 +++++- > 10 files changed, 299 insertions(+), 36 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon.h > b/drivers/gpu/drm/radeon/radeon.h > index 986100a..ad54525 100644 > --- a/drivers/gpu/drm/radeon/radeon.h > +++ b/drivers/gpu/drm/radeon/radeon.h > @@ -98,6 +98,7 @@ extern int radeon_lockup_timeout; > extern int radeon_fastfb; > extern int radeon_dpm; > extern int radeon_aspm; > +extern int radeon_runtime_pm; > > /* > * Copy from radeon_drv.h so we don't have to include both and have > conflicting > @@ -2212,6 +2213,9 @@ struct radeon_device { > /* clock, powergating flags */ > u32 cg_flags; > u32 pg_flags; > + > + struct dev_pm_domain vga_pm_domain; > + bool have_disp_power_ref; > }; > > int radeon_device_init(struct radeon_device *rdev, > @@ -2673,8 +2677,8 @@ extern void radeon_ttm_placement_from_domain(struct > radeon_bo *rbo, u32 domain); > extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); > extern void radeon_vram_location(struct radeon_device *rdev, struct > radeon_mc *mc, u64 base); > extern void radeon_gtt_location(struct radeon_device *rdev, struct > radeon_mc *mc); > -extern int radeon_resume_kms(struct drm_device *dev, bool resume); > -extern int radeon_suspend_kms(struct drm_device *dev, bool suspend); > +extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool > fbcon); > +extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool > fbcon); > extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, > u64 size); > extern void radeon_program_register_sequence(struct radeon_device *rdev, > const u32 *registers, > diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c > b/drivers/gpu/drm/radeon/radeon_atpx_handler.c > index d96070b..6153ec1 100644 > --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c > +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c > @@ -59,6 +59,10 @@ struct atpx_mux { > u16 mux; > } __packed; > > +bool radeon_is_px(void) { > + return radeon_atpx_priv.atpx_detected; > +} > + > /** > * radeon_atpx_call - call an ATPX method > * > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c > b/drivers/gpu/drm/radeon/radeon_connectors.c > index 79159b5..5855b5b 100644 > --- a/drivers/gpu/drm/radeon/radeon_connectors.c > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c > @@ -31,6 +31,8 @@ > #include "radeon.h" > #include "atom.h" > > +#include <linux/pm_runtime.h> > + > extern void > radeon_combios_connected_scratch_regs(struct drm_connector *connector, > struct drm_encoder *encoder, > @@ -626,6 +628,11 @@ radeon_lvds_detect(struct drm_connector *connector, > bool force) > struct radeon_connector *radeon_connector = > to_radeon_connector(connector); > struct drm_encoder *encoder = > radeon_best_single_encoder(connector); > enum drm_connector_status ret = connector_status_disconnected; > + int r; > + > + r = pm_runtime_get_sync(connector->dev->dev); > + if (r < 0) > + return connector_status_disconnected; > > if (encoder) { > struct radeon_encoder *radeon_encoder = > to_radeon_encoder(encoder); > @@ -651,6 +658,8 @@ radeon_lvds_detect(struct drm_connector *connector, > bool force) > /* check acpi lid status ??? */ > > radeon_connector_update_scratch_regs(connector, ret); > + pm_runtime_mark_last_busy(connector->dev->dev); > + pm_runtime_put_autosuspend(connector->dev->dev); > return ret; > } > > @@ -750,6 +759,11 @@ radeon_vga_detect(struct drm_connector *connector, > bool force) > struct drm_encoder_helper_funcs *encoder_funcs; > bool dret = false; > enum drm_connector_status ret = connector_status_disconnected; > + int r; > + > + r = pm_runtime_get_sync(connector->dev->dev); > + if (r < 0) > + return connector_status_disconnected; > > encoder = radeon_best_single_encoder(connector); > if (!encoder) > @@ -790,9 +804,8 @@ radeon_vga_detect(struct drm_connector *connector, > bool force) > * detected a monitor via load. > */ > if (radeon_connector->detected_by_load) > - return connector->status; > - else > - return ret; > + ret = connector->status; > + goto out; > } > > if (radeon_connector->dac_load_detect && encoder) { > @@ -817,6 +830,11 @@ radeon_vga_detect(struct drm_connector *connector, > bool force) > } > > radeon_connector_update_scratch_regs(connector, ret); > + > +out: > + pm_runtime_mark_last_busy(connector->dev->dev); > + pm_runtime_put_autosuspend(connector->dev->dev); > + > return ret; > } > > @@ -873,10 +891,15 @@ radeon_tv_detect(struct drm_connector *connector, > bool force) > struct drm_encoder_helper_funcs *encoder_funcs; > struct radeon_connector *radeon_connector = > to_radeon_connector(connector); > enum drm_connector_status ret = connector_status_disconnected; > + int r; > > if (!radeon_connector->dac_load_detect) > return ret; > > + r = pm_runtime_get_sync(connector->dev->dev); > + if (r < 0) > + return connector_status_disconnected; > + > encoder = radeon_best_single_encoder(connector); > if (!encoder) > ret = connector_status_disconnected; > @@ -887,6 +910,8 @@ radeon_tv_detect(struct drm_connector *connector, bool > force) > if (ret == connector_status_connected) > ret = > radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, > false); > radeon_connector_update_scratch_regs(connector, ret); > + pm_runtime_mark_last_busy(connector->dev->dev); > + pm_runtime_put_autosuspend(connector->dev->dev); > return ret; > } > > @@ -954,12 +979,18 @@ radeon_dvi_detect(struct drm_connector *connector, > bool force) > struct drm_encoder *encoder = NULL; > struct drm_encoder_helper_funcs *encoder_funcs; > struct drm_mode_object *obj; > - int i; > + int i, r; > enum drm_connector_status ret = connector_status_disconnected; > bool dret = false, broken_edid = false; > > - if (!force && radeon_check_hpd_status_unchanged(connector)) > - return connector->status; > + r = pm_runtime_get_sync(connector->dev->dev); > + if (r < 0) > + return connector_status_disconnected; > + > + if (!force && radeon_check_hpd_status_unchanged(connector)) { > + ret = connector->status; > + goto exit; > + } > > if (radeon_connector->ddc_bus) > dret = radeon_ddc_probe(radeon_connector, false); > @@ -1110,6 +1141,11 @@ out: > > /* updated in get modes as well since we need to know if it's > analog or digital */ > radeon_connector_update_scratch_regs(connector, ret); > + > +exit: > + pm_runtime_mark_last_busy(connector->dev->dev); > + pm_runtime_put_autosuspend(connector->dev->dev); > + > return ret; > } > > @@ -1377,9 +1413,16 @@ radeon_dp_detect(struct drm_connector *connector, > bool force) > enum drm_connector_status ret = connector_status_disconnected; > struct radeon_connector_atom_dig *radeon_dig_connector = > radeon_connector->con_priv; > struct drm_encoder *encoder = > radeon_best_single_encoder(connector); > + int r; > > - if (!force && radeon_check_hpd_status_unchanged(connector)) > - return connector->status; > + r = pm_runtime_get_sync(connector->dev->dev); > + if (r < 0) > + return connector_status_disconnected; > + > + if (!force && radeon_check_hpd_status_unchanged(connector)) { > + ret = connector->status; > + goto out; > + } > > if (radeon_connector->edid) { > kfree(radeon_connector->edid); > @@ -1443,6 +1486,10 @@ radeon_dp_detect(struct drm_connector *connector, > bool force) > } > > radeon_connector_update_scratch_regs(connector, ret); > +out: > + pm_runtime_mark_last_busy(connector->dev->dev); > + pm_runtime_put_autosuspend(connector->dev->dev); > + > return ret; > } > > diff --git a/drivers/gpu/drm/radeon/radeon_device.c > b/drivers/gpu/drm/radeon/radeon_device.c > index 37cfcee..b9b9dfd 100644 > --- a/drivers/gpu/drm/radeon/radeon_device.c > +++ b/drivers/gpu/drm/radeon/radeon_device.c > @@ -101,6 +101,12 @@ static const char radeon_family_name[][16] = { > "LAST", > }; > > +#if defined(CONFIG_VGA_SWITCHEROO) > +bool radeon_is_px(void); > +#else > +static inline bool radeon_is_px(void) { return false; } > +#endif > + > /** > * radeon_program_register_sequence - program an array of registers. > * > @@ -1076,6 +1082,10 @@ static bool > radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) > static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum > vga_switcheroo_state state) > { > struct drm_device *dev = pci_get_drvdata(pdev); > + > + if (radeon_is_px() && state == VGA_SWITCHEROO_OFF) > + return; > + > if (state == VGA_SWITCHEROO_ON) { > unsigned d3_delay = dev->pdev->d3_delay; > > @@ -1086,7 +1096,7 @@ static void radeon_switcheroo_set_state(struct > pci_dev *pdev, enum vga_switchero > if (d3_delay < 20 && > radeon_switcheroo_quirk_long_wakeup(pdev)) > dev->pdev->d3_delay = 20; > > - radeon_resume_kms(dev, 1); > + radeon_resume_kms(dev, true, true); > > dev->pdev->d3_delay = d3_delay; > > @@ -1096,7 +1106,7 @@ static void radeon_switcheroo_set_state(struct > pci_dev *pdev, enum vga_switchero > printk(KERN_INFO "radeon: switched off\n"); > drm_kms_helper_poll_disable(dev); > dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > - radeon_suspend_kms(dev, 1); > + radeon_suspend_kms(dev, true, true); > dev->switch_power_state = DRM_SWITCH_POWER_OFF; > } > } > @@ -1146,6 +1156,7 @@ int radeon_device_init(struct radeon_device *rdev, > { > int r, i; > int dma_bits; > + bool runtime = false; > > rdev->shutdown = false; > rdev->dev = &pdev->dev; > @@ -1292,7 +1303,14 @@ int radeon_device_init(struct radeon_device *rdev, > /* this will fail for cards that aren't VGA class devices, just > * ignore it */ > vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); > - vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, > false); > + > + if (radeon_runtime_pm == 1) > + runtime = true; > + if ((radeon_runtime_pm == -1) && radeon_is_px()) > + runtime = true; > + vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, > runtime); > + if (runtime) > + vga_switcheroo_init_domain_pm_ops(rdev->dev, > &rdev->vga_pm_domain); > > r = radeon_init(rdev); > if (r) > @@ -1373,7 +1391,7 @@ void radeon_device_fini(struct radeon_device *rdev) > * Returns 0 for success or an error on failure. > * Called at driver suspend. > */ > -int radeon_suspend_kms(struct drm_device *dev, bool suspend) > +int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) > { > struct radeon_device *rdev; > struct drm_crtc *crtc; > @@ -1448,9 +1466,12 @@ int radeon_suspend_kms(struct drm_device *dev, bool > suspend) > pci_disable_device(dev->pdev); > pci_set_power_state(dev->pdev, PCI_D3hot); > } > - console_lock(); > - radeon_fbdev_set_suspend(rdev, 1); > - console_unlock(); > + > + if (fbcon) { > + console_lock(); > + radeon_fbdev_set_suspend(rdev, 1); > + console_unlock(); > + } > return 0; > } > > @@ -1463,7 +1484,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool > suspend) > * Returns 0 for success or an error on failure. > * Called at driver resume. > */ > -int radeon_resume_kms(struct drm_device *dev, bool resume) > +int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) > { > struct drm_connector *connector; > struct radeon_device *rdev = dev->dev_private; > @@ -1472,12 +1493,15 @@ int radeon_resume_kms(struct drm_device *dev, bool > resume) > if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) > return 0; > > - console_lock(); > + if (fbcon) { > + console_lock(); > + } > if (resume) { > pci_set_power_state(dev->pdev, PCI_D0); > pci_restore_state(dev->pdev); > if (pci_enable_device(dev->pdev)) { > - console_unlock(); > + if (fbcon) > + console_unlock(); > return -1; > } > } > @@ -1492,9 +1516,11 @@ int radeon_resume_kms(struct drm_device *dev, bool > resume) > radeon_pm_resume(rdev); > radeon_restore_bios_scratch_regs(rdev); > > - radeon_fbdev_set_suspend(rdev, 0); > - console_unlock(); > - > + if (fbcon) { > + radeon_fbdev_set_suspend(rdev, 0); > + console_unlock(); > + } > + > /* init dig PHYs, disp eng pll */ > if (rdev->is_atom_bios) { > radeon_atom_encoder_init(rdev); > diff --git a/drivers/gpu/drm/radeon/radeon_display.c > b/drivers/gpu/drm/radeon/radeon_display.c > index 0d1aa05..bc37e33 100644 > --- a/drivers/gpu/drm/radeon/radeon_display.c > +++ b/drivers/gpu/drm/radeon/radeon_display.c > @@ -30,6 +30,7 @@ > #include "atom.h" > #include <asm/div64.h> > > +#include <linux/pm_runtime.h> > #include <drm/drm_crtc_helper.h> > #include <drm/drm_edid.h> > > @@ -494,11 +495,55 @@ unlock_free: > return r; > } > > +static int > +radeon_crtc_set_config(struct drm_mode_set *set) > +{ > + struct drm_device *dev; > + struct radeon_device *rdev; > + struct drm_crtc *crtc; > + bool active = false; > + int ret; > + > + if (!set || !set->crtc) > + return -EINVAL; > + > + dev = set->crtc->dev; > + > + ret = pm_runtime_get_sync(dev->dev); > + if (ret < 0) > + return ret; > + > + ret = drm_crtc_helper_set_config(set); > + > + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) > + if (crtc->enabled) > + active = true; > + > + pm_runtime_mark_last_busy(dev->dev); > + > + rdev = dev->dev_private; > + /* if we have active crtcs and we don't have a power ref, > + take the current one */ > + if (active && !rdev->have_disp_power_ref) { > + rdev->have_disp_power_ref = true; > + return ret; > + } > + /* if we have no active crtcs, then drop the power ref > + we got before */ > + if (!active && rdev->have_disp_power_ref) { > + pm_runtime_put_autosuspend(dev->dev); > + rdev->have_disp_power_ref = false; > + } > + > + /* drop the power reference we got coming in here */ > + pm_runtime_put_autosuspend(dev->dev); > + return ret; > +} > static const struct drm_crtc_funcs radeon_crtc_funcs = { > .cursor_set = radeon_crtc_cursor_set, > .cursor_move = radeon_crtc_cursor_move, > .gamma_set = radeon_crtc_gamma_set, > - .set_config = drm_crtc_helper_set_config, > + .set_config = radeon_crtc_set_config, > .destroy = radeon_crtc_destroy, > .page_flip = radeon_crtc_page_flip, > }; > diff --git a/drivers/gpu/drm/radeon/radeon_drv.c > b/drivers/gpu/drm/radeon/radeon_drv.c > index 788bfb0..427c64f 100644 > --- a/drivers/gpu/drm/radeon/radeon_drv.c > +++ b/drivers/gpu/drm/radeon/radeon_drv.c > @@ -36,8 +36,9 @@ > #include <drm/drm_pciids.h> > #include <linux/console.h> > #include <linux/module.h> > - > - > +#include <linux/pm_runtime.h> > +#include <linux/vga_switcheroo.h> > +#include "drm_crtc_helper.h" > /* > * KMS wrapper. > * - 2.0.0 - initial interface > @@ -87,8 +88,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev, > struct drm_file *file_priv); > void radeon_driver_preclose_kms(struct drm_device *dev, > struct drm_file *file_priv); > -int radeon_suspend_kms(struct drm_device *dev, bool suspend); > -int radeon_resume_kms(struct drm_device *dev, bool resume); > +int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon); > +int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); > u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); > int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); > void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); > @@ -137,9 +138,11 @@ void radeon_debugfs_cleanup(struct drm_minor *minor); > #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; > @@ -162,6 +165,7 @@ int radeon_lockup_timeout = 10000; > int radeon_fastfb = 0; > int radeon_dpm = -1; > int radeon_aspm = -1; > +int radeon_runtime_pm = -1; > > MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); > module_param_named(no_wb, radeon_no_wb, int, 0444); > @@ -223,6 +227,9 @@ module_param_named(dpm, radeon_dpm, int, 0444); > MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = > auto)"); > module_param_named(aspm, radeon_aspm, int, 0444); > > +MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 > = PX only default)"); > +module_param_named(runpm, radeon_runtime_pm, int, 0444); > + > static struct pci_device_id pciidlist[] = { > radeon_PCI_IDS > }; > @@ -259,6 +266,7 @@ static int radeon_resume(struct drm_device *dev) > return 0; > } > > + > static const struct file_operations radeon_driver_old_fops = { > .owner = THIS_MODULE, > .open = drm_open, > @@ -357,28 +365,121 @@ static int radeon_pmops_suspend(struct device *dev) > { > struct pci_dev *pdev = to_pci_dev(dev); > struct drm_device *drm_dev = pci_get_drvdata(pdev); > - return radeon_suspend_kms(drm_dev, 1); > + return radeon_suspend_kms(drm_dev, true, true); > } > > static int radeon_pmops_resume(struct device *dev) > { > struct pci_dev *pdev = to_pci_dev(dev); > struct drm_device *drm_dev = pci_get_drvdata(pdev); > - return radeon_resume_kms(drm_dev, 1); > + return radeon_resume_kms(drm_dev, true, true); > } > > static int radeon_pmops_freeze(struct device *dev) > { > struct pci_dev *pdev = to_pci_dev(dev); > struct drm_device *drm_dev = pci_get_drvdata(pdev); > - return radeon_suspend_kms(drm_dev, 0); > + return radeon_suspend_kms(drm_dev, false, true); > } > > static int radeon_pmops_thaw(struct device *dev) > { > struct pci_dev *pdev = to_pci_dev(dev); > struct drm_device *drm_dev = pci_get_drvdata(pdev); > - return radeon_resume_kms(drm_dev, 0); > + return radeon_resume_kms(drm_dev, false, true); > +} > + > +static int radeon_pmops_runtime_suspend(struct device *dev) > +{ > + struct pci_dev *pdev = to_pci_dev(dev); > + struct drm_device *drm_dev = pci_get_drvdata(pdev); > + int ret; > + > + if (radeon_runtime_pm == 0) > + return -EINVAL; > + > + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > + drm_kms_helper_poll_disable(drm_dev); > + vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); > + > + ret = radeon_suspend_kms(drm_dev, false, false); > + pci_save_state(pdev); > + pci_disable_device(pdev); > + pci_set_power_state(pdev, PCI_D3cold); > + drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; > + > + return 0; > +} > + > +static int radeon_pmops_runtime_resume(struct device *dev) > +{ > + struct pci_dev *pdev = to_pci_dev(dev); > + struct drm_device *drm_dev = pci_get_drvdata(pdev); > + int ret; > + > + if (radeon_runtime_pm == 0) > + return -EINVAL; > + > + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > + > + pci_set_power_state(pdev, PCI_D0); > + pci_restore_state(pdev); > + ret = pci_enable_device(pdev); > + if (ret) > + return ret; > + pci_set_master(pdev); > + > + ret = radeon_resume_kms(drm_dev, false, false); > + drm_kms_helper_poll_enable(drm_dev); > + vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); > + drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; > + return 0; > +} > + > +static int radeon_pmops_runtime_idle(struct device *dev) > +{ > + struct pci_dev *pdev = to_pci_dev(dev); > + struct drm_device *drm_dev = pci_get_drvdata(pdev); > + struct drm_crtc *crtc; > + > + if (radeon_runtime_pm == 0) > + return -EBUSY; > + > + /* are we PX enabled? */ > + if (radeon_runtime_pm == -1 && !radeon_is_px()) { > + DRM_DEBUG_DRIVER("failing to power off - not px\n"); > + return -EBUSY; > + } > + > + list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { > + if (crtc->enabled) { > + DRM_DEBUG_DRIVER("failing to power off - crtc > active\n"); > + return -EBUSY; > + } > + } > + > + pm_runtime_mark_last_busy(dev); > + pm_runtime_autosuspend(dev); > + /* we don't want the main rpm_idle to call suspend - we want to > autosuspend */ > + return 1; > +} > + > +long radeon_drm_ioctl(struct file *filp, > + unsigned int cmd, unsigned long arg) > +{ > + struct drm_file *file_priv = filp->private_data; > + struct drm_device *dev; > + long ret; > + dev = file_priv->minor->dev; > + ret = pm_runtime_get_sync(dev->dev); > + if (ret < 0) > + return ret; > + > + ret = drm_ioctl(filp, cmd, arg); > + > + pm_runtime_mark_last_busy(dev->dev); > + pm_runtime_put_autosuspend(dev->dev); > + return ret; > } > > static const struct dev_pm_ops radeon_pm_ops = { > @@ -388,13 +489,16 @@ static const struct dev_pm_ops radeon_pm_ops = { > .thaw = radeon_pmops_thaw, > .poweroff = radeon_pmops_freeze, > .restore = radeon_pmops_resume, > + .runtime_suspend = radeon_pmops_runtime_suspend, > + .runtime_resume = radeon_pmops_runtime_resume, > + .runtime_idle = radeon_pmops_runtime_idle, > }; > > static const struct file_operations radeon_driver_kms_fops = { > .owner = THIS_MODULE, > .open = drm_open, > .release = drm_release, > - .unlocked_ioctl = drm_ioctl, > + .unlocked_ioctl = radeon_drm_ioctl, > .mmap = radeon_mmap, > .poll = drm_poll, > .read = drm_read, > diff --git a/drivers/gpu/drm/radeon/radeon_drv.h > b/drivers/gpu/drm/radeon/radeon_drv.h > index b369d42..543dcfa 100644 > --- a/drivers/gpu/drm/radeon/radeon_drv.h > +++ b/drivers/gpu/drm/radeon/radeon_drv.h > @@ -113,6 +113,9 @@ > #define DRIVER_MINOR 33 > #define DRIVER_PATCHLEVEL 0 > > +long radeon_drm_ioctl(struct file *filp, > + unsigned int cmd, unsigned long arg); > + > /* The rest of the file is DEPRECATED! */ > #ifdef CONFIG_DRM_RADEON_UMS > > diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c > b/drivers/gpu/drm/radeon/radeon_ioc32.c > index c180df8..bdb0f93 100644 > --- a/drivers/gpu/drm/radeon/radeon_ioc32.c > +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c > @@ -418,7 +418,7 @@ long radeon_kms_compat_ioctl(struct file *filp, > unsigned int cmd, unsigned long > if (nr < DRM_COMMAND_BASE) > return drm_compat_ioctl(filp, cmd, arg); > > - ret = drm_ioctl(filp, cmd, arg); > + ret = radeon_drm_ioctl(filp, cmd, arg); > > return ret; > } > diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c > b/drivers/gpu/drm/radeon/radeon_irq_kms.c > index cc9e848..ec6240b 100644 > --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c > +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c > @@ -32,6 +32,8 @@ > #include "radeon.h" > #include "atom.h" > > +#include <linux/pm_runtime.h> > + > #define RADEON_WAIT_IDLE_TIMEOUT 200 > > /** > @@ -47,8 +49,12 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) > { > struct drm_device *dev = (struct drm_device *) arg; > struct radeon_device *rdev = dev->dev_private; > + irqreturn_t ret; > > - return radeon_irq_process(rdev); > + ret = radeon_irq_process(rdev); > + if (ret == IRQ_HANDLED) > + pm_runtime_mark_last_busy(dev->dev); > + return ret; > } > > /* > diff --git a/drivers/gpu/drm/radeon/radeon_kms.c > b/drivers/gpu/drm/radeon/radeon_kms.c > index 61580dd..bffff51 100644 > --- a/drivers/gpu/drm/radeon/radeon_kms.c > +++ b/drivers/gpu/drm/radeon/radeon_kms.c > @@ -32,7 +32,7 @@ > > #include <linux/vga_switcheroo.h> > #include <linux/slab.h> > - > +#include <linux/pm_runtime.h> > /** > * radeon_driver_unload_kms - Main unload function for KMS. > * > @@ -50,9 +50,14 @@ int radeon_driver_unload_kms(struct drm_device *dev) > > if (rdev == NULL) > return 0; > + > if (rdev->rmmio == NULL) > goto done_free; > + > + pm_runtime_get_sync(dev->dev); > + > radeon_acpi_fini(rdev); > + > radeon_modeset_fini(rdev); > radeon_device_fini(rdev); > > @@ -125,9 +130,20 @@ int radeon_driver_load_kms(struct drm_device *dev, > unsigned long flags) > "Error during ACPI methods call\n"); > } > > + if (radeon_runtime_pm != 0) { > + pm_runtime_use_autosuspend(dev->dev); > + pm_runtime_set_autosuspend_delay(dev->dev, 5000); > + pm_runtime_set_active(dev->dev); > + pm_runtime_allow(dev->dev); > + pm_runtime_mark_last_busy(dev->dev); > + pm_runtime_put_autosuspend(dev->dev); > + } > + > out: > if (r) > radeon_driver_unload_kms(dev); > + > + > return r; > } > > @@ -475,9 +491,14 @@ void radeon_driver_lastclose_kms(struct drm_device > *dev) > int radeon_driver_open_kms(struct drm_device *dev, struct drm_file > *file_priv) > { > struct radeon_device *rdev = dev->dev_private; > + int r; > > file_priv->driver_priv = NULL; > > + r = pm_runtime_get_sync(dev->dev); > + if (r < 0) > + return r; > + > /* new gpu have virtual address space support */ > if (rdev->family >= CHIP_CAYMAN) { > struct radeon_fpriv *fpriv; > @@ -506,6 +527,9 @@ int radeon_driver_open_kms(struct drm_device *dev, > struct drm_file *file_priv) > > file_priv->driver_priv = fpriv; > } > + > + pm_runtime_mark_last_busy(dev->dev); > + pm_runtime_put_autosuspend(dev->dev); > return 0; > } > > -- > 1.8.3.1 > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20130920/cb790232/attachment-0001.html>