aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-12-06 18:20:40 -0500
committerDave Airlie <airlied@redhat.com>2011-01-04 22:45:30 -0500
commit5bcf719b7db0f9366cedaf102b081f99b1c325ae (patch)
tree6929d42e1d61a3b1bd7b130a37a80b99718e14aa
parent8d608aa6295242fe4c4b6105b8c59c6a5b232d89 (diff)
drm/switcheroo: track state of switch in drivers.
We need to track the state of the switch in drivers, so that after s/r we don't resume the card we've explicitly switched off before. Also don't allow a userspace open to occur if we've switched the gpu off. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_fops.c2
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c12
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c4
-rw-r--r--include/drm/drmP.h6
10 files changed, 40 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index a39794bac04b..2ec7d48fc4a8 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -236,6 +236,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
236 return -EBUSY; /* No exclusive opens */ 236 return -EBUSY; /* No exclusive opens */
237 if (!drm_cpu_valid()) 237 if (!drm_cpu_valid())
238 return -EINVAL; 238 return -EINVAL;
239 if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
240 return -EINVAL;
239 241
240 DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); 242 DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
241 243
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ec1f650f6fab..0568dbdc10ef 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1151,12 +1151,16 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
1151 pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 1151 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
1152 if (state == VGA_SWITCHEROO_ON) { 1152 if (state == VGA_SWITCHEROO_ON) {
1153 printk(KERN_INFO "i915: switched on\n"); 1153 printk(KERN_INFO "i915: switched on\n");
1154 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
1154 /* i915 resume handler doesn't set to D0 */ 1155 /* i915 resume handler doesn't set to D0 */
1155 pci_set_power_state(dev->pdev, PCI_D0); 1156 pci_set_power_state(dev->pdev, PCI_D0);
1156 i915_resume(dev); 1157 i915_resume(dev);
1158 dev->switch_power_state = DRM_SWITCH_POWER_ON;
1157 } else { 1159 } else {
1158 printk(KERN_ERR "i915: switched off\n"); 1160 printk(KERN_ERR "i915: switched off\n");
1161 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
1159 i915_suspend(dev, pmm); 1162 i915_suspend(dev, pmm);
1163 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
1160 } 1164 }
1161} 1165}
1162 1166
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 9eee6cf7901e..872493331988 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -271,6 +271,8 @@ static int i915_drm_freeze(struct drm_device *dev)
271{ 271{
272 struct drm_i915_private *dev_priv = dev->dev_private; 272 struct drm_i915_private *dev_priv = dev->dev_private;
273 273
274 drm_kms_helper_poll_disable(dev);
275
274 pci_save_state(dev->pdev); 276 pci_save_state(dev->pdev);
275 277
276 /* If KMS is active, we do the leavevt stuff here */ 278 /* If KMS is active, we do the leavevt stuff here */
@@ -307,7 +309,9 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
307 if (state.event == PM_EVENT_PRETHAW) 309 if (state.event == PM_EVENT_PRETHAW)
308 return 0; 310 return 0;
309 311
310 drm_kms_helper_poll_disable(dev); 312
313 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
314 return 0;
311 315
312 error = i915_drm_freeze(dev); 316 error = i915_drm_freeze(dev);
313 if (error) 317 if (error)
@@ -361,6 +365,9 @@ int i915_resume(struct drm_device *dev)
361{ 365{
362 int ret; 366 int ret;
363 367
368 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
369 return 0;
370
364 if (pci_enable_device(dev->pdev)) 371 if (pci_enable_device(dev->pdev))
365 return -EIO; 372 return -EIO;
366 373
@@ -569,6 +576,9 @@ static int i915_pm_suspend(struct device *dev)
569 return -ENODEV; 576 return -ENODEV;
570 } 577 }
571 578
579 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
580 return 0;
581
572 error = i915_drm_freeze(drm_dev); 582 error = i915_drm_freeze(drm_dev);
573 if (error) 583 if (error)
574 return error; 584 return error;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index bb170570938b..13bb672a16f4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -171,6 +171,9 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
171 if (pm_state.event == PM_EVENT_PRETHAW) 171 if (pm_state.event == PM_EVENT_PRETHAW)
172 return 0; 172 return 0;
173 173
174 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
175 return 0;
176
174 NV_INFO(dev, "Disabling fbcon acceleration...\n"); 177 NV_INFO(dev, "Disabling fbcon acceleration...\n");
175 nouveau_fbcon_save_disable_accel(dev); 178 nouveau_fbcon_save_disable_accel(dev);
176 179
@@ -254,6 +257,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
254 struct drm_crtc *crtc; 257 struct drm_crtc *crtc;
255 int ret, i; 258 int ret, i;
256 259
260 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
261 return 0;
262
257 nouveau_fbcon_save_disable_accel(dev); 263 nouveau_fbcon_save_disable_accel(dev);
258 264
259 NV_INFO(dev, "We're back, enabling device...\n"); 265 NV_INFO(dev, "We're back, enabling device...\n");
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index e81575687354..e59f5bcab1ad 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -753,6 +753,8 @@ struct drm_nouveau_private {
753 753
754 struct nouveau_fbdev *nfbdev; 754 struct nouveau_fbdev *nfbdev;
755 struct apertures_struct *apertures; 755 struct apertures_struct *apertures;
756
757 bool powered_down;
756}; 758};
757 759
758static inline struct drm_nouveau_private * 760static inline struct drm_nouveau_private *
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 1b87eee22fa9..a54fc431fe98 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -596,12 +596,16 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
596 pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 596 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
597 if (state == VGA_SWITCHEROO_ON) { 597 if (state == VGA_SWITCHEROO_ON) {
598 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); 598 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
599 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
599 nouveau_pci_resume(pdev); 600 nouveau_pci_resume(pdev);
600 drm_kms_helper_poll_enable(dev); 601 drm_kms_helper_poll_enable(dev);
602 dev->switch_power_state = DRM_SWITCH_POWER_ON;
601 } else { 603 } else {
602 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); 604 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
605 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
603 drm_kms_helper_poll_disable(dev); 606 drm_kms_helper_poll_disable(dev);
604 nouveau_pci_suspend(pdev, pmm); 607 nouveau_pci_suspend(pdev, pmm);
608 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
605 } 609 }
606} 610}
607 611
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d2697f8f2da8..140eaceab279 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1167,7 +1167,6 @@ struct radeon_device {
1167 uint8_t audio_status_bits; 1167 uint8_t audio_status_bits;
1168 uint8_t audio_category_code; 1168 uint8_t audio_category_code;
1169 1169
1170 bool powered_down;
1171 struct notifier_block acpi_nb; 1170 struct notifier_block acpi_nb;
1172 /* only one userspace can use Hyperz features at a time */ 1171 /* only one userspace can use Hyperz features at a time */
1173 struct drm_file *hyperz_filp; 1172 struct drm_file *hyperz_filp;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 1a1017f0d9db..4ee0c53b28a7 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -642,20 +642,20 @@ void radeon_check_arguments(struct radeon_device *rdev)
642static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) 642static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
643{ 643{
644 struct drm_device *dev = pci_get_drvdata(pdev); 644 struct drm_device *dev = pci_get_drvdata(pdev);
645 struct radeon_device *rdev = dev->dev_private;
646 pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 645 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
647 if (state == VGA_SWITCHEROO_ON) { 646 if (state == VGA_SWITCHEROO_ON) {
648 printk(KERN_INFO "radeon: switched on\n"); 647 printk(KERN_INFO "radeon: switched on\n");
649 /* don't suspend or resume card normally */ 648 /* don't suspend or resume card normally */
650 rdev->powered_down = false; 649 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
651 radeon_resume_kms(dev); 650 radeon_resume_kms(dev);
651 dev->switch_power_state = DRM_SWITCH_POWER_ON;
652 drm_kms_helper_poll_enable(dev); 652 drm_kms_helper_poll_enable(dev);
653 } else { 653 } else {
654 printk(KERN_INFO "radeon: switched off\n"); 654 printk(KERN_INFO "radeon: switched off\n");
655 drm_kms_helper_poll_disable(dev); 655 drm_kms_helper_poll_disable(dev);
656 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
656 radeon_suspend_kms(dev, pmm); 657 radeon_suspend_kms(dev, pmm);
657 /* don't suspend or resume card normally */ 658 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
658 rdev->powered_down = true;
659 } 659 }
660} 660}
661 661
@@ -842,7 +842,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
842 } 842 }
843 rdev = dev->dev_private; 843 rdev = dev->dev_private;
844 844
845 if (rdev->powered_down) 845 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
846 return 0; 846 return 0;
847 847
848 /* turn off display hw */ 848 /* turn off display hw */
@@ -900,7 +900,7 @@ int radeon_resume_kms(struct drm_device *dev)
900 struct drm_connector *connector; 900 struct drm_connector *connector;
901 struct radeon_device *rdev = dev->dev_private; 901 struct radeon_device *rdev = dev->dev_private;
902 902
903 if (rdev->powered_down) 903 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
904 return 0; 904 return 0;
905 905
906 acquire_console_sem(); 906 acquire_console_sem();
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 4bf423ca4c12..b2686334d46b 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -203,10 +203,6 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
203 */ 203 */
204int radeon_driver_firstopen_kms(struct drm_device *dev) 204int radeon_driver_firstopen_kms(struct drm_device *dev)
205{ 205{
206 struct radeon_device *rdev = dev->dev_private;
207
208 if (rdev->powered_down)
209 return -EINVAL;
210 return 0; 206 return 0;
211} 207}
212 208
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0f14f94ed8f4..a4694c610330 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1121,9 +1121,13 @@ struct drm_device {
1121 spinlock_t object_name_lock; 1121 spinlock_t object_name_lock;
1122 struct idr object_name_idr; 1122 struct idr object_name_idr;
1123 /*@} */ 1123 /*@} */
1124 1124 int switch_power_state;
1125}; 1125};
1126 1126
1127#define DRM_SWITCH_POWER_ON 0
1128#define DRM_SWITCH_POWER_OFF 1
1129#define DRM_SWITCH_POWER_CHANGING 2
1130
1127static __inline__ int drm_core_check_feature(struct drm_device *dev, 1131static __inline__ int drm_core_check_feature(struct drm_device *dev,
1128 int feature) 1132 int feature)
1129{ 1133{