mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-28 15:13:55 +08:00
Merge branch 'linux-4.12' of git://github.com/skeggsb/linux into drm-fixes
4 nouveau regression fixes. * 'linux-4.12' of git://github.com/skeggsb/linux: drm/nouveau/tmr: fully separate alarm execution/pending lists drm/nouveau: enable autosuspend only when it'll actually be used drm/nouveau: replace multiple open-coded runpm support checks with function drm/nouveau/kms/nv50: add null check before pointer dereference
This commit is contained in:
commit
1f779cd745
@ -4,6 +4,7 @@
|
||||
|
||||
struct nvkm_alarm {
|
||||
struct list_head head;
|
||||
struct list_head exec;
|
||||
u64 timestamp;
|
||||
void (*func)(struct nvkm_alarm *);
|
||||
};
|
||||
|
@ -80,7 +80,7 @@ int nouveau_modeset = -1;
|
||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
|
||||
int nouveau_runtime_pm = -1;
|
||||
static int nouveau_runtime_pm = -1;
|
||||
module_param_named(runpm, nouveau_runtime_pm, int, 0400);
|
||||
|
||||
static struct drm_driver driver_stub;
|
||||
@ -495,7 +495,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
nouveau_fbcon_init(dev);
|
||||
nouveau_led_init(dev);
|
||||
|
||||
if (nouveau_runtime_pm != 0) {
|
||||
if (nouveau_pmops_runtime()) {
|
||||
pm_runtime_use_autosuspend(dev->dev);
|
||||
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
|
||||
pm_runtime_set_active(dev->dev);
|
||||
@ -527,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
|
||||
if (nouveau_runtime_pm != 0) {
|
||||
if (nouveau_pmops_runtime()) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
}
|
||||
@ -726,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev)
|
||||
return nouveau_do_resume(drm_dev, false);
|
||||
}
|
||||
|
||||
bool
|
||||
nouveau_pmops_runtime()
|
||||
{
|
||||
if (nouveau_runtime_pm == -1)
|
||||
return nouveau_is_optimus() || nouveau_is_v1_dsm();
|
||||
return nouveau_runtime_pm == 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_pmops_runtime_suspend(struct device *dev)
|
||||
{
|
||||
@ -733,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (nouveau_runtime_pm == 0) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* are we optimus enabled? */
|
||||
if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
|
||||
DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -765,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
||||
struct nvif_device *device = &nouveau_drm(drm_dev)->client.device;
|
||||
int ret;
|
||||
|
||||
if (nouveau_runtime_pm == 0)
|
||||
return -EINVAL;
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev)
|
||||
struct nouveau_drm *drm = nouveau_drm(drm_dev);
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (nouveau_runtime_pm == 0) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* are we optimus enabled? */
|
||||
if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
|
||||
DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
|
||||
if (!nouveau_pmops_runtime()) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv)
|
||||
#include <nvif/object.h>
|
||||
#include <nvif/device.h>
|
||||
|
||||
extern int nouveau_runtime_pm;
|
||||
|
||||
struct nouveau_drm {
|
||||
struct nouveau_cli client;
|
||||
struct drm_device *dev;
|
||||
@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev)
|
||||
|
||||
int nouveau_pmops_suspend(struct device *);
|
||||
int nouveau_pmops_resume(struct device *);
|
||||
bool nouveau_pmops_runtime(void);
|
||||
|
||||
#include <nvkm/core/tegra.h>
|
||||
|
||||
|
@ -87,7 +87,7 @@ void
|
||||
nouveau_vga_init(struct nouveau_drm *drm)
|
||||
{
|
||||
struct drm_device *dev = drm->dev;
|
||||
bool runtime = false;
|
||||
bool runtime = nouveau_pmops_runtime();
|
||||
|
||||
/* only relevant for PCI devices */
|
||||
if (!dev->pdev)
|
||||
@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm)
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);
|
||||
|
||||
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
|
||||
@ -113,18 +109,13 @@ void
|
||||
nouveau_vga_fini(struct nouveau_drm *drm)
|
||||
{
|
||||
struct drm_device *dev = drm->dev;
|
||||
bool runtime = false;
|
||||
bool runtime = nouveau_pmops_runtime();
|
||||
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
runtime = true;
|
||||
|
||||
vga_switcheroo_unregister_client(dev->pdev);
|
||||
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
|
||||
vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
|
||||
|
@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
|
||||
asyc->set.dither = true;
|
||||
}
|
||||
} else {
|
||||
asyc->set.mask = ~0;
|
||||
if (asyc)
|
||||
asyc->set.mask = ~0;
|
||||
asyh->set.mask = ~0;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
/* Move to completed list. We'll drop the lock before
|
||||
* executing the callback so it can reschedule itself.
|
||||
*/
|
||||
list_move_tail(&alarm->head, &exec);
|
||||
list_del_init(&alarm->head);
|
||||
list_add(&alarm->exec, &exec);
|
||||
}
|
||||
|
||||
/* Shut down interrupt if no more pending alarms. */
|
||||
@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
|
||||
/* Execute completed callbacks. */
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, head) {
|
||||
list_del_init(&alarm->head);
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, exec) {
|
||||
list_del(&alarm->exec);
|
||||
alarm->func(alarm);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user