static int PVRSRVDRMUnload(struct drm_device *dev) { struct pvr_drm_dev_priv *psDevPriv = (struct pvr_drm_dev_priv *)dev->dev_private; #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) IMG_HANDLE hSysData = psDevPriv->hSysData; #endif PVR_TRACE(("PVRSRVDRMUnload")); #if defined(SUPPORT_DRM_DC_MODULE) (void)PVRSRVDRMDisplayDeinit(dev); #endif psDevPriv->dev_node = NULL; PVRSRVSystemDeInit(); #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) psDevPriv->hSysData = NULL; SysReleaseSystemData(hSysData); drm_irq_uninstall(dev); #endif return 0; }
/** * amdgpu_irq_fini - tear down driver interrupt info * * @adev: amdgpu device pointer * * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). */ void amdgpu_irq_fini(struct amdgpu_device *adev) { unsigned i; drm_vblank_cleanup(adev->ddev); if (adev->irq.installed) { drm_irq_uninstall(adev->ddev); adev->irq.installed = false; if (adev->irq.msi_enabled) pci_disable_msi(adev->pdev); flush_work(&adev->hotplug_work); } for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) { struct amdgpu_irq_src *src = adev->irq.sources[i]; if (!src) continue; kfree(src->enabled_types); src->enabled_types = NULL; if (src->data) { kfree(src->data); kfree(src); adev->irq.sources[i] = NULL; } } }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; intel_runtime_pm_get(dev_priv); /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); /* We do a lot of poking in a lot of registers, make sure they work * properly. */ hsw_disable_package_c8(dev_priv); intel_display_set_init_power(dev, true); drm_kms_helper_poll_disable(dev); pci_save_state(dev->pdev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error; error = i915_gem_suspend(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); return error; } cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); drm_irq_uninstall(dev); dev_priv->enable_hotplug_processing = false; /* * Disable CRTCs directly since we want to preserve sw state * for _thaw. */ mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) dev_priv->display.crtc_disable(crtc); mutex_unlock(&dev->mode_config.mutex); intel_modeset_suspend_hw(dev); } i915_gem_suspend_gtt_mappings(dev); i915_save_state(dev); intel_opregion_fini(dev); console_lock(); intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED); console_unlock(); return 0; }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv; int error; dev_priv = dev->dev_private; drm_kms_helper_poll_disable(dev); #if 0 pci_save_state(dev->pdev); #endif DRM_LOCK(dev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { error = -i915_gem_idle(dev); if (error) { DRM_UNLOCK(dev); device_printf(dev->device, "GEM idle failed, resume might fail\n"); return (error); } drm_irq_uninstall(dev); } i915_save_state(dev); intel_opregion_fini(dev); /* Modeset on resume, not lid events */ dev_priv->modeset_on_lid = 0; DRM_UNLOCK(dev); return 0; }
/** * IRQ control ioctl. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_control structure. * \return zero on success or a negative number on failure. * * Calls irq_install() or irq_uninstall() according to \p arg. */ int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_control *ctl = data; /* Handle drivers who used to require IRQ setup no longer does. */ if (!(dev->driver->flags & DRIVER_IRQ)) return (0); switch (ctl->func) { case DRM_INST_HANDLER: if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != dev->irq) return (EINVAL); return (drm_irq_install(dev)); case DRM_UNINST_HANDLER: if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; return (drm_irq_uninstall(dev)); default: return (EINVAL); } }
PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState) { PVRSRV_ERROR eError= PVRSRV_OK; PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)(gsSysSpecificData.hSGXPCI); if (eNewPowerState != gpsSysData->eCurrentPowerState) { if ((eNewPowerState == PVRSRV_SYS_POWER_STATE_D3) && (gpsSysData->eCurrentPowerState < PVRSRV_SYS_POWER_STATE_D3)) { #if !defined(SUPPORT_DRI_DRM_EXT) drm_irq_uninstall(gpDrmDevice); #endif SysUnmapRegisters(); //Save some pci state that won't get saved properly by pci_save_state() pci_read_config_dword(psPVRPCI->psPCIDev, 0x5C, &gsSysSpecificData.saveBSM); pci_read_config_dword(psPVRPCI->psPCIDev, 0xFC, &gsSysSpecificData.saveVBT); pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_ADDR_LOC, &gsSysSpecificData.msi_addr); pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_DATA_LOC, &gsSysSpecificData.msi_data); #if !defined(SUPPORT_DRI_DRM_EXT) eError = OSPCISuspendDev(gsSysSpecificData.hSGXPCI); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSPCISuspendDev failed (%d)", eError)); } #endif } } return eError; }
static void nouveau_card_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; DRM_DEBUG("prev state = %d\n", dev_priv->init_state); if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { nouveau_backlight_exit(dev); nouveau_dma_channel_takedown(dev); engine->fifo.takedown(dev); engine->graph.takedown(dev); engine->fb.takedown(dev); engine->timer.takedown(dev); engine->mc.takedown(dev); nouveau_sgdma_nottm_hack_takedown(dev); nouveau_sgdma_takedown(dev); nouveau_gpuobj_takedown(dev); nouveau_gpuobj_del(dev, &dev_priv->vm_vram_pt); nouveau_mem_close(dev); engine->instmem.takedown(dev); drm_irq_uninstall(dev); nouveau_gpuobj_late_takedown(dev); dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } }
/** * amdgpu_irq_fini - tear down driver interrupt info * * @adev: amdgpu device pointer * * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). */ void amdgpu_irq_fini(struct amdgpu_device *adev) { unsigned i, j; if (adev->irq.installed) { drm_irq_uninstall(adev->ddev); adev->irq.installed = false; if (adev->irq.msi_enabled) pci_disable_msi(adev->pdev); flush_work(&adev->hotplug_work); cancel_work_sync(&adev->reset_work); } for (i = 0; i < AMDGPU_IH_CLIENTID_MAX; ++i) { if (!adev->irq.client[i].sources) continue; for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) { struct amdgpu_irq_src *src = adev->irq.client[i].sources[j]; if (!src) continue; kfree(src->enabled_types); src->enabled_types = NULL; if (src->data) { kfree(src->data); kfree(src); adev->irq.client[i].sources[j] = NULL; } } kfree(adev->irq.client[i].sources); } }
void radeon_irq_kms_fini(struct radeon_device *rdev) { if (rdev->irq.installed) { rdev->irq.installed = false; drm_irq_uninstall(rdev->ddev); } }
static int i915_suspend(struct drm_device *dev, pm_message_t state) { struct drm_i915_private *dev_priv = dev->dev_private; if (!dev || !dev_priv) { DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv); DRM_ERROR("DRM not initialized, aborting suspend.\n"); return -ENODEV; } if (state.event == PM_EVENT_PRETHAW) return 0; pci_save_state(dev->pdev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (i915_gem_idle(dev)) dev_err(&dev->pdev->dev, "GEM idle failed, resume may fail\n"); drm_irq_uninstall(dev); } i915_save_state(dev); intel_opregion_free(dev, 1); if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ pci_disable_device(dev->pdev); pci_set_power_state(dev->pdev, PCI_D3hot); } return 0; }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; drm_kms_helper_poll_disable(dev); pci_save_state(dev->pdev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error = i915_gem_idle(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); return error; } drm_irq_uninstall(dev); } i915_save_state(dev); intel_opregion_fini(dev); /* Modeset on resume, not lid events */ dev_priv->modeset_on_lid = 0; console_lock(); intel_fbdev_set_suspend(dev, 1); console_unlock(); return 0; }
void radeon_irq_kms_fini(struct radeon_device *rdev) { if (rdev->irq.installed) { rdev->irq.installed = false; drm_irq_uninstall(rdev->ddev); if (rdev->msi_enabled) pci_disable_msi(rdev->pdev); } }
/** * radeon_irq_kms_fini - tear down driver interrrupt info * * @rdev: radeon device pointer * * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). */ void radeon_irq_kms_fini(struct radeon_device *rdev) { drm_vblank_cleanup(rdev->ddev); if (rdev->irq.installed) { drm_irq_uninstall(rdev->ddev); rdev->irq.installed = false; } taskqueue_drain(rdev->tq, &rdev->hotplug_work); }
void nouveau_irq_fini(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; drm_irq_uninstall(dev); if (dev_priv->msi_enabled) pci_disable_msi(dev->pdev); }
int via_final_context(struct drm_device *dev, int context) { int i; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; for (i = 0; i < MAX_CONTEXT; i++) if (global_ppriv[i].used && (global_ppriv[i].context == context)) break; if (i < MAX_CONTEXT) { set_t *set; ITEM_TYPE item; int retval; DRM_DEBUG("find socket %d, context = %d\n", i, context); /* Video Memory */ set = global_ppriv[i].sets[0]; retval = via_setFirst(set, &item); while (retval) { DRM_DEBUG("free video memory 0x%lx\n", item); via_mmFreeMem((PMemBlock) item); retval = via_setNext(set, &item); } via_setDestroy(set); /* AGP Memory */ set = global_ppriv[i].sets[1]; retval = via_setFirst(set, &item); while (retval) { DRM_DEBUG("free agp memory 0x%lx\n", item); via_mmFreeMem((PMemBlock) item); retval = via_setNext(set, &item); } via_setDestroy(set); global_ppriv[i].used = 0; } via_release_futex(dev_priv, context); #if defined(__linux__) /* Linux specific until context tracking code gets ported to BSD */ /* Last context, perform cleanup */ if (dev->ctx_count == 1 && dev->dev_private) { DRM_DEBUG("Last Context\n"); if (dev->irq) drm_irq_uninstall(dev); via_cleanup_futex(dev_priv); via_do_cleanup_map(dev); } #endif return 1; }
static int fsl_dcu_unload(struct drm_device *dev) { drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); drm_irq_uninstall(dev); dev->dev_private = NULL; return 0; }
/** * radeon_irq_kms_fini - tear down driver interrupt info * * @rdev: radeon device pointer * * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). */ void radeon_irq_kms_fini(struct radeon_device *rdev) { drm_vblank_cleanup(rdev->ddev); if (rdev->irq.installed) { drm_irq_uninstall(rdev->ddev); rdev->irq.installed = false; if (rdev->msi_enabled) pci_disable_msi(rdev->pdev); flush_work(&rdev->hotplug_work); } }
static int shmob_drm_unload(struct drm_device *dev) { drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); drm_irq_uninstall(dev); dev->dev_private = NULL; return 0; }
static int vmw_driver_unload(struct drm_device *dev) { struct vmw_private *dev_priv = vmw_priv(dev); enum vmw_res_type i; unregister_pm_notifier(&dev_priv->pm_nb); if (dev_priv->ctx.res_ht_initialized) drm_ht_remove(&dev_priv->ctx.res_ht); vfree(dev_priv->ctx.cmd_bounce); if (dev_priv->enable_fb) { vmw_fb_off(dev_priv); vmw_fb_close(dev_priv); vmw_fifo_resource_dec(dev_priv); vmw_svga_disable(dev_priv); } vmw_kms_close(dev_priv); vmw_overlay_close(dev_priv); if (dev_priv->has_gmr) (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); vmw_release_device_early(dev_priv); if (dev_priv->has_mob) (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); (void) ttm_bo_device_release(&dev_priv->bdev); vmw_release_device_late(dev_priv); vmw_fence_manager_takedown(dev_priv->fman); if (dev_priv->capabilities & SVGA_CAP_IRQMASK) drm_irq_uninstall(dev_priv->dev); if (dev_priv->stealth) pci_release_region(dev->pdev, 2); else pci_release_regions(dev->pdev); ttm_object_device_release(&dev_priv->tdev); iounmap(dev_priv->mmio_virt); arch_phys_wc_del(dev_priv->mmio_mtrr); if (dev_priv->ctx.staged_bindings) vmw_binding_state_free(dev_priv->ctx.staged_bindings); vmw_ttm_global_release(dev_priv); for (i = vmw_res_context; i < vmw_res_max; ++i) idr_destroy(&dev_priv->res_idr[i]); kfree(dev_priv); return 0; }
static int armada_drm_unload(struct drm_device *dev) { struct armada_private *priv = dev->dev_private; drm_kms_helper_poll_fini(dev); armada_fbdev_fini(dev); drm_irq_uninstall(dev); drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); flush_work(&priv->fb_unref_work); dev->dev_private = NULL; return 0; }
static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) { struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; int ret; ret = fsl_dcu_drm_modeset_init(fsl_dev); if (ret < 0) { dev_err(dev->dev, "failed to initialize mode setting\n"); return ret; } ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret < 0) { dev_err(dev->dev, "failed to initialize vblank\n"); goto done; } ret = fsl_dcu_drm_irq_init(dev); if (ret < 0) goto done; dev->irq_enabled = true; if (legacyfb_depth != 16 && legacyfb_depth != 24 && legacyfb_depth != 32) { dev_warn(dev->dev, "Invalid legacyfb_depth. Defaulting to 24bpp\n"); legacyfb_depth = 24; } fsl_dev->fbdev = drm_fbdev_cma_init(dev, legacyfb_depth, 1); if (IS_ERR(fsl_dev->fbdev)) { ret = PTR_ERR(fsl_dev->fbdev); fsl_dev->fbdev = NULL; goto done; } return 0; done: drm_kms_helper_poll_fini(dev); if (fsl_dev->fbdev) drm_fbdev_cma_fini(fsl_dev->fbdev); drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); drm_irq_uninstall(dev); dev->dev_private = NULL; return ret; }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; intel_runtime_pm_get(dev_priv); /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); /* We do a lot of poking in a lot of registers, make sure they work * properly. */ intel_display_set_init_power(dev_priv, true); drm_kms_helper_poll_disable(dev); pci_save_state(dev->pdev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error; error = i915_gem_suspend(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); return error; } intel_disable_gt_powersave(dev); /* * Disable CRTCs directly since we want to preserve sw state * for _thaw. */ drm_modeset_lock_all(dev); for_each_crtc(dev, crtc) { dev_priv->display.crtc_disable(crtc); } drm_modeset_unlock_all(dev); intel_dp_mst_suspend(dev); drm_irq_uninstall(dev); intel_modeset_suspend_hw(dev); }
int via_final_context(struct drm_device *dev, int context) { drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; via_release_futex(dev_priv, context); if (dev->ctx_count == 1 && dev->dev_private) { DRM_DEBUG("Last Context\n"); drm_irq_uninstall(dev); via_cleanup_futex(dev_priv); via_do_cleanup_map(dev); } return 1; }
static void fsl_dcu_unload(struct drm_device *dev) { struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; drm_crtc_force_disable_all(dev); drm_kms_helper_poll_fini(dev); if (fsl_dev->fbdev) drm_fbdev_cma_fini(fsl_dev->fbdev); drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); drm_irq_uninstall(dev); dev->dev_private = NULL; }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; drm_kms_helper_poll_disable(dev); #ifndef __NetBSD__ /* pmf handles this for us. */ pci_save_state(dev->pdev); #endif /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error = i915_gem_idle(dev); if (error) { #ifdef __NetBSD__ dev_err(pci_dev_dev(dev->pdev), "GEM idle failed, resume might fail\n"); #else dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); #endif return error; } cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); intel_modeset_disable(dev); drm_irq_uninstall(dev); } i915_save_state(dev); intel_opregion_fini(dev); /* Modeset on resume, not lid events */ dev_priv->modeset_on_lid = 0; #ifndef __NetBSD__ /* XXX fb */ console_lock(); intel_fbdev_set_suspend(dev, 1); console_unlock(); #endif return 0; }
int via_final_context(struct drm_device *dev, int context) { drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; via_release_futex(dev_priv, context); /* Linux specific until context tracking code gets ported to BSD */ /* Last context, perform cleanup */ if (dev->ctx_count == 1 && dev->dev_private) { DRM_DEBUG("Last Context\n"); if (dev->irq) drm_irq_uninstall(dev); via_cleanup_futex(dev_priv); via_do_cleanup_map(dev); } return 1; }
static int fsl_dcu_unload(struct drm_device *dev) { struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; drm_kms_helper_poll_fini(dev); if (fsl_dev->fbdev) drm_fbdev_cma_fini(fsl_dev->fbdev); drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); drm_irq_uninstall(dev); dev->dev_private = NULL; return 0; }
static void nouveau_card_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { nouveau_backlight_exit(dev); if (dev_priv->channel) { nouveau_channel_free(dev_priv->channel); dev_priv->channel = NULL; } if (!nouveau_noaccel) { engine->fifo.takedown(dev); engine->graph.takedown(dev); } engine->fb.takedown(dev); engine->timer.takedown(dev); engine->mc.takedown(dev); mutex_lock(&dev->struct_mutex); ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); mutex_unlock(&dev->struct_mutex); nouveau_sgdma_takedown(dev); nouveau_gpuobj_takedown(dev); nouveau_mem_close(dev); engine->instmem.takedown(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_irq_uninstall(dev); nouveau_gpuobj_late_takedown(dev); nouveau_bios_takedown(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } }
static int msm_unload(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; struct msm_gpu *gpu = priv->gpu; drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); drm_vblank_cleanup(dev); pm_runtime_get_sync(dev->dev); drm_irq_uninstall(dev); pm_runtime_put_sync(dev->dev); flush_workqueue(priv->wq); destroy_workqueue(priv->wq); if (kms) { pm_runtime_disable(dev->dev); kms->funcs->destroy(kms); } if (gpu) { mutex_lock(&dev->struct_mutex); gpu->funcs->pm_suspend(gpu); gpu->funcs->destroy(gpu); mutex_unlock(&dev->struct_mutex); } if (priv->vram.paddr) { DEFINE_DMA_ATTRS(attrs); dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); drm_mm_takedown(&priv->vram.mm); dma_free_attrs(dev->dev, priv->vram.size, NULL, priv->vram.paddr, &attrs); } component_unbind_all(dev->dev, dev); dev->dev_private = NULL; kfree(priv); return 0; }
static void mxsfb_unload(struct drm_device *drm) { struct mxsfb_drm_private *mxsfb = drm->dev_private; if (mxsfb->fbdev) drm_fbdev_cma_fini(mxsfb->fbdev); drm_kms_helper_poll_fini(drm); drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); pm_runtime_get_sync(drm->dev); drm_irq_uninstall(drm); pm_runtime_put_sync(drm->dev); drm->dev_private = NULL; pm_runtime_disable(drm->dev); }