mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 17:23:55 +08:00
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>
This commit is contained in:
parent
8d608aa629
commit
5bcf719b7d
@ -236,6 +236,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
|||||||
return -EBUSY; /* No exclusive opens */
|
return -EBUSY; /* No exclusive opens */
|
||||||
if (!drm_cpu_valid())
|
if (!drm_cpu_valid())
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
|
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
|
||||||
|
|
||||||
|
@ -1151,12 +1151,16 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
|
|||||||
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
||||||
if (state == VGA_SWITCHEROO_ON) {
|
if (state == VGA_SWITCHEROO_ON) {
|
||||||
printk(KERN_INFO "i915: switched on\n");
|
printk(KERN_INFO "i915: switched on\n");
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
/* i915 resume handler doesn't set to D0 */
|
/* i915 resume handler doesn't set to D0 */
|
||||||
pci_set_power_state(dev->pdev, PCI_D0);
|
pci_set_power_state(dev->pdev, PCI_D0);
|
||||||
i915_resume(dev);
|
i915_resume(dev);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "i915: switched off\n");
|
printk(KERN_ERR "i915: switched off\n");
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
i915_suspend(dev, pmm);
|
i915_suspend(dev, pmm);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +271,8 @@ static int i915_drm_freeze(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
|
||||||
|
drm_kms_helper_poll_disable(dev);
|
||||||
|
|
||||||
pci_save_state(dev->pdev);
|
pci_save_state(dev->pdev);
|
||||||
|
|
||||||
/* If KMS is active, we do the leavevt stuff here */
|
/* 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)
|
|||||||
if (state.event == PM_EVENT_PRETHAW)
|
if (state.event == PM_EVENT_PRETHAW)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
drm_kms_helper_poll_disable(dev);
|
|
||||||
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
error = i915_drm_freeze(dev);
|
error = i915_drm_freeze(dev);
|
||||||
if (error)
|
if (error)
|
||||||
@ -361,6 +365,9 @@ int i915_resume(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (pci_enable_device(dev->pdev))
|
if (pci_enable_device(dev->pdev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@ -569,6 +576,9 @@ static int i915_pm_suspend(struct device *dev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
error = i915_drm_freeze(drm_dev);
|
error = i915_drm_freeze(drm_dev);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
@ -171,6 +171,9 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
|
|||||||
if (pm_state.event == PM_EVENT_PRETHAW)
|
if (pm_state.event == PM_EVENT_PRETHAW)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
NV_INFO(dev, "Disabling fbcon acceleration...\n");
|
NV_INFO(dev, "Disabling fbcon acceleration...\n");
|
||||||
nouveau_fbcon_save_disable_accel(dev);
|
nouveau_fbcon_save_disable_accel(dev);
|
||||||
|
|
||||||
@ -254,6 +257,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
|||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
nouveau_fbcon_save_disable_accel(dev);
|
nouveau_fbcon_save_disable_accel(dev);
|
||||||
|
|
||||||
NV_INFO(dev, "We're back, enabling device...\n");
|
NV_INFO(dev, "We're back, enabling device...\n");
|
||||||
|
@ -753,6 +753,8 @@ struct drm_nouveau_private {
|
|||||||
|
|
||||||
struct nouveau_fbdev *nfbdev;
|
struct nouveau_fbdev *nfbdev;
|
||||||
struct apertures_struct *apertures;
|
struct apertures_struct *apertures;
|
||||||
|
|
||||||
|
bool powered_down;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct drm_nouveau_private *
|
static inline struct drm_nouveau_private *
|
||||||
|
@ -596,12 +596,16 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
|
|||||||
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
||||||
if (state == VGA_SWITCHEROO_ON) {
|
if (state == VGA_SWITCHEROO_ON) {
|
||||||
printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
|
printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
nouveau_pci_resume(pdev);
|
nouveau_pci_resume(pdev);
|
||||||
drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable(dev);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
|
printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
drm_kms_helper_poll_disable(dev);
|
drm_kms_helper_poll_disable(dev);
|
||||||
nouveau_pci_suspend(pdev, pmm);
|
nouveau_pci_suspend(pdev, pmm);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1167,7 +1167,6 @@ struct radeon_device {
|
|||||||
uint8_t audio_status_bits;
|
uint8_t audio_status_bits;
|
||||||
uint8_t audio_category_code;
|
uint8_t audio_category_code;
|
||||||
|
|
||||||
bool powered_down;
|
|
||||||
struct notifier_block acpi_nb;
|
struct notifier_block acpi_nb;
|
||||||
/* only one userspace can use Hyperz features at a time */
|
/* only one userspace can use Hyperz features at a time */
|
||||||
struct drm_file *hyperz_filp;
|
struct drm_file *hyperz_filp;
|
||||||
|
@ -642,20 +642,20 @@ void radeon_check_arguments(struct radeon_device *rdev)
|
|||||||
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
|
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
|
||||||
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
|
||||||
if (state == VGA_SWITCHEROO_ON) {
|
if (state == VGA_SWITCHEROO_ON) {
|
||||||
printk(KERN_INFO "radeon: switched on\n");
|
printk(KERN_INFO "radeon: switched on\n");
|
||||||
/* don't suspend or resume card normally */
|
/* don't suspend or resume card normally */
|
||||||
rdev->powered_down = false;
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
radeon_resume_kms(dev);
|
radeon_resume_kms(dev);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||||
drm_kms_helper_poll_enable(dev);
|
drm_kms_helper_poll_enable(dev);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_INFO "radeon: switched off\n");
|
printk(KERN_INFO "radeon: switched off\n");
|
||||||
drm_kms_helper_poll_disable(dev);
|
drm_kms_helper_poll_disable(dev);
|
||||||
|
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||||
radeon_suspend_kms(dev, pmm);
|
radeon_suspend_kms(dev, pmm);
|
||||||
/* don't suspend or resume card normally */
|
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||||
rdev->powered_down = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,7 +842,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
|
|||||||
}
|
}
|
||||||
rdev = dev->dev_private;
|
rdev = dev->dev_private;
|
||||||
|
|
||||||
if (rdev->powered_down)
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* turn off display hw */
|
/* turn off display hw */
|
||||||
@ -900,7 +900,7 @@ int radeon_resume_kms(struct drm_device *dev)
|
|||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
struct radeon_device *rdev = dev->dev_private;
|
||||||
|
|
||||||
if (rdev->powered_down)
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
acquire_console_sem();
|
acquire_console_sem();
|
||||||
|
@ -203,10 +203,6 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||||||
*/
|
*/
|
||||||
int radeon_driver_firstopen_kms(struct drm_device *dev)
|
int radeon_driver_firstopen_kms(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
|
||||||
|
|
||||||
if (rdev->powered_down)
|
|
||||||
return -EINVAL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,9 +1121,13 @@ struct drm_device {
|
|||||||
spinlock_t object_name_lock;
|
spinlock_t object_name_lock;
|
||||||
struct idr object_name_idr;
|
struct idr object_name_idr;
|
||||||
/*@} */
|
/*@} */
|
||||||
|
int switch_power_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DRM_SWITCH_POWER_ON 0
|
||||||
|
#define DRM_SWITCH_POWER_OFF 1
|
||||||
|
#define DRM_SWITCH_POWER_CHANGING 2
|
||||||
|
|
||||||
static __inline__ int drm_core_check_feature(struct drm_device *dev,
|
static __inline__ int drm_core_check_feature(struct drm_device *dev,
|
||||||
int feature)
|
int feature)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user