@@ -952,17 +952,16 @@ static int
nv50_mstc_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx, bool force)
{
+ struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nv50_mstc *mstc = nv50_mstc(connector);
int ret;
if (drm_connector_is_unregistered(connector))
return connector_status_disconnected;
- ret = pm_runtime_get_sync(connector->dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(connector->dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return connector_status_disconnected;
- }
ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr,
mstc->port);
@@ -970,8 +969,7 @@ nv50_mstc_detect(struct drm_connector *connector,
goto out;
out:
- pm_runtime_mark_last_busy(connector->dev->dev);
- pm_runtime_put_autosuspend(connector->dev->dev);
+ nouveau_runpm_put(drm);
return ret;
}
@@ -1950,7 +1948,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
asyh->clr.mask, asyh->set.mask);
if (old_crtc_state->active && !new_crtc_state->active) {
- pm_runtime_put_noidle(dev->dev);
+ nouveau_runpm_put_noidle(drm);
drm_crtc_vblank_off(crtc);
}
@@ -2040,7 +2038,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (new_crtc_state->active) {
if (!old_crtc_state->active) {
drm_crtc_vblank_on(crtc);
- pm_runtime_get_noresume(dev->dev);
+ nouveau_runpm_get_noresume(drm);
}
if (new_crtc_state->event)
drm_crtc_vblank_get(crtc);
@@ -2159,8 +2157,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_state_put(state);
/* Drop the RPM ref we got from nv50_disp_atomic_commit() */
- pm_runtime_mark_last_busy(dev->dev);
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
}
static void
@@ -2175,15 +2172,14 @@ static int
nv50_disp_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool nonblock)
{
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_plane_state *new_plane_state;
struct drm_plane *plane;
int ret, i;
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return ret;
- }
ret = drm_atomic_helper_setup_commit(state, nonblock);
if (ret)
@@ -2219,7 +2215,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
* Grab another RPM ref for the commit tail, which will release the
* ref when it's finished
*/
- pm_runtime_get_noresume(dev->dev);
+ nouveau_runpm_get_noresume(drm);
if (nonblock)
queue_work(system_unbound_wq, &state->commit_work);
@@ -2230,7 +2226,7 @@ nv50_disp_atomic_commit(struct drm_device *dev,
if (ret)
drm_atomic_helper_unprepare_planes(dev, state);
done:
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
return ret;
}
@@ -2439,6 +2435,7 @@ static inline void
nv50_display_read_hw_or_state(struct drm_device *dev, struct nv50_disp *disp,
struct nouveau_encoder *outp)
{
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_crtc *crtc;
struct drm_connector_list_iter conn_iter;
struct drm_connector *conn;
@@ -2501,7 +2498,7 @@ nv50_display_read_hw_or_state(struct drm_device *dev, struct nv50_disp *disp,
armh->state.connector_mask = drm_connector_mask(conn);
armh->state.active = true;
armh->state.enable = true;
- pm_runtime_get_noresume(dev->dev);
+ nouveau_runpm_get_noresume(drm);
outp->crtc = crtc;
outp->ctrl = NVVAL(NV507D, SOR_SET_CONTROL, PROTOCOL, proto) | BIT(crtc->index);
@@ -26,7 +26,6 @@
#include <acpi/button.h>
-#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
#include <drm/drm_atomic_helper.h>
@@ -579,11 +578,11 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
* if possible.
*/
if (drm_kms_helper_is_poll_worker()) {
- pm_runtime_get_noresume(dev->dev);
+ nouveau_runpm_get_noresume(drm);
} else {
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret) {
+ nouveau_runpm_put(drm);
nouveau_connector_set_edid(nv_connector, NULL);
return conn_status;
}
@@ -674,8 +673,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
if (!nv_connector->edid)
drm_dp_cec_unset_edid(&nv_connector->aux);
- pm_runtime_mark_last_busy(dev->dev);
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
return conn_status;
}
@@ -40,6 +40,7 @@
#include "nouveau_crtc.h"
#include "nouveau_encoder.h"
+#include "nouveau_runpm.h"
struct nvkm_i2c_port;
struct dcb_output;
@@ -31,6 +31,7 @@
#include <linux/debugfs.h>
#include "nouveau_debugfs.h"
#include "nouveau_drv.h"
+#include "nouveau_runpm.h"
static int
nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
@@ -51,18 +52,14 @@ nouveau_debugfs_strap_peek(struct seq_file *m, void *data)
struct nouveau_drm *drm = nouveau_drm(node->minor->dev);
int ret;
- ret = pm_runtime_get_sync(drm->dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(drm->dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return ret;
- }
seq_printf(m, "0x%08x\n",
nvif_rd32(&drm->device, 0x101000));
- pm_runtime_mark_last_busy(drm->dev->dev);
- pm_runtime_put_autosuspend(drm->dev->dev);
-
+ nouveau_runpm_put(drm);
return 0;
}
@@ -135,8 +132,9 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
- struct drm_device *drm = m->private;
- struct nouveau_debugfs *debugfs = nouveau_debugfs(drm);
+ struct drm_device *dev = m->private;
+ struct nouveau_debugfs *debugfs = nouveau_debugfs(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct nvif_control_pstate_user args = { .pwrsrc = -EINVAL };
char buf[32] = {}, *tmp, *cur = buf;
long value, ret;
@@ -174,14 +172,12 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
args.ustate = value;
}
- ret = pm_runtime_get_sync(drm->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(drm->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return ret;
- }
ret = debugfs->impl->pstate.user(debugfs->priv, &args);
- pm_runtime_put_autosuspend(drm->dev);
+ nouveau_runpm_put(drm);
if (ret < 0)
return ret;
@@ -466,7 +466,7 @@ nouveau_display_hpd_work(struct work_struct *work)
int changed = 0;
struct drm_connector *first_changed_connector = NULL;
- pm_runtime_get_sync(dev->dev);
+ nouveau_runpm_try_get(drm);
spin_lock_irq(&drm->hpd_lock);
pending = drm->hpd_pending;
@@ -474,8 +474,10 @@ nouveau_display_hpd_work(struct work_struct *work)
spin_unlock_irq(&drm->hpd_lock);
/* Nothing to do, exit early without updating the last busy counter */
- if (!pending)
- goto noop;
+ if (!pending) {
+ nouveau_runpm_put_noop(drm);
+ return;
+ }
mutex_lock(&dev->mode_config.mutex);
drm_connector_list_iter_begin(dev, &conn_iter);
@@ -532,9 +534,7 @@ nouveau_display_hpd_work(struct work_struct *work)
if (first_changed_connector)
drm_connector_put(first_changed_connector);
- pm_runtime_mark_last_busy(drm->dev->dev);
-noop:
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
}
#ifdef CONFIG_ACPI
@@ -545,24 +545,25 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
{
struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
struct acpi_bus_event *info = data;
+ struct device *dev = drm->dev->dev;
int ret;
if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
- ret = pm_runtime_get(drm->dev->dev);
+ ret = pm_runtime_get(dev);
if (ret == 1 || ret == -EACCES) {
/* If the GPU is already awake, or in a state
* where we can't wake it up, it can handle
* it's own hotplug events.
*/
- pm_runtime_put_autosuspend(drm->dev->dev);
+ pm_runtime_put_autosuspend(dev);
} else if (ret == 0 || ret == -EINPROGRESS) {
/* We've started resuming the GPU already, so
* it will handle scheduling a full reprobe
* itself
*/
NV_DEBUG(drm, "ACPI requested connector reprobe\n");
- pm_runtime_put_noidle(drm->dev->dev);
+ pm_runtime_put_noidle(dev);
} else {
NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n",
ret);
@@ -25,7 +25,6 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
#include <linux/mmu_notifier.h>
#include <linux/dynamic_debug.h>
@@ -72,6 +71,7 @@
#include "nouveau_exec.h"
#include "nouveau_uvmm.h"
#include "nouveau_sched.h"
+#include "nouveau_runpm.h"
DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
"DRM_UT_CORE",
@@ -486,10 +486,8 @@ nouveau_drm_device_fini(struct nouveau_drm *drm)
struct drm_device *dev = drm->dev;
struct nouveau_cli *cli, *temp_cli;
- if (nouveau_pmops_runtime(dev->dev)) {
- pm_runtime_get_sync(dev->dev);
- pm_runtime_forbid(dev->dev);
- }
+ if (nouveau_pmops_runtime(dev->dev))
+ nouveau_runpm_disable(drm);
nouveau_led_fini(dev);
nouveau_dmem_fini(drm);
@@ -581,14 +579,8 @@ nouveau_drm_device_init(struct nouveau_drm *drm)
nouveau_dmem_init(drm);
nouveau_led_init(dev);
- if (nouveau_pmops_runtime(dev->dev)) {
- 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(dev->dev);
- }
+ if (nouveau_pmops_runtime(dev->dev))
+ nouveau_runpm_enable(drm);
ret = drm_dev_register(drm->dev, 0);
if (ret) {
@@ -1025,11 +1017,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
int ret;
/* need to bring up power immediately if opening device */
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return ret;
- }
get_task_comm(tmpname, current);
rcu_read_lock();
@@ -1058,8 +1048,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
kfree(cli);
}
- pm_runtime_mark_last_busy(dev->dev);
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
return ret;
}
@@ -1079,7 +1068,7 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
if (!drm_dev_enter(dev, &dev_index))
return;
- pm_runtime_get_sync(dev->dev);
+ nouveau_runpm_try_get(drm);
mutex_lock(&cli->mutex);
if (cli->abi16)
@@ -1092,8 +1081,9 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
nouveau_cli_fini(cli);
kfree(cli);
- pm_runtime_mark_last_busy(dev->dev);
- pm_runtime_put_autosuspend(dev->dev);
+
+ nouveau_runpm_put(drm);
+
drm_dev_exit(dev_index);
}
@@ -1122,14 +1112,12 @@ long
nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct drm_file *filp = file->private_data;
- struct drm_device *dev = filp->minor->dev;
+ struct nouveau_drm *drm = nouveau_drm(filp->minor->dev);
long ret;
- ret = pm_runtime_get_sync(dev->dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(dev->dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
return ret;
- }
switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) {
case DRM_NOUVEAU_NVIF:
@@ -1140,8 +1128,7 @@ nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
- pm_runtime_mark_last_busy(dev->dev);
- pm_runtime_put_autosuspend(dev->dev);
+ nouveau_runpm_put(drm);
return ret;
}
@@ -30,6 +30,7 @@
#include "nouveau_dma.h"
#include "nouveau_fence.h"
#include "nouveau_abi16.h"
+#include "nouveau_runpm.h"
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
@@ -78,22 +79,18 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
{
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
- struct device *dev = drm->dev->dev;
int ret;
- ret = pm_runtime_get_sync(dev);
- if (WARN_ON(ret < 0 && ret != -EACCES)) {
- pm_runtime_put_autosuspend(dev);
+ ret = nouveau_runpm_get(drm);
+ if (WARN_ON(ret))
return;
- }
if (gem->import_attach)
drm_prime_gem_destroy(gem, nvbo->bo.sg);
ttm_bo_put(&nvbo->bo);
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
+ nouveau_runpm_put(drm);
}
int
@@ -102,7 +99,6 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
- struct device *dev = drm->dev->dev;
struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli);
struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
struct nouveau_vma *vma;
@@ -119,19 +115,17 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
if (ret)
return ret;
- ret = pm_runtime_get_sync(dev);
- if (ret < 0 && ret != -EACCES) {
- pm_runtime_put_autosuspend(dev);
+ ret = nouveau_runpm_get(drm);
+ if (ret)
goto out;
- }
/* only create a VMA on binding */
if (!nouveau_cli_uvmm(cli))
ret = nouveau_vma_new(nvbo, vmm, &vma);
else
ret = 0;
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
+
+ nouveau_runpm_put(drm);
out:
ttm_bo_unreserve(&nvbo->bo);
return ret;
@@ -188,7 +182,6 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
- struct device *dev = drm->dev->dev;
struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
struct nouveau_vma *vma;
int ret;
@@ -206,12 +199,11 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
vma = nouveau_vma_find(nvbo, vmm);
if (vma) {
if (--vma->refs == 0) {
- ret = pm_runtime_get_sync(dev);
- if (!WARN_ON(ret < 0 && ret != -EACCES)) {
+ ret = nouveau_runpm_get(drm);
+ if (!WARN_ON(ret)) {
nouveau_gem_object_unmap(nvbo, vma);
- pm_runtime_mark_last_busy(dev);
+ nouveau_runpm_put(drm);
}
- pm_runtime_put_autosuspend(dev);
}
}
ttm_bo_unreserve(&nvbo->bo);
new file mode 100644
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NOUVEAU_RUNPM_H__
+#define __NOUVEAU_RUNPM_H__
+#include <linux/pm_runtime.h>
+
+static inline struct device *
+nouveau_runpm_dev(struct nouveau_drm *drm)
+{
+ return drm->dev->dev;
+}
+
+static inline void
+nouveau_runpm_put_noidle(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_put_noidle(dev);
+}
+
+static inline void
+nouveau_runpm_put_noop(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_put_autosuspend(dev);
+}
+
+static inline void
+nouveau_runpm_put(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+}
+
+static inline int
+nouveau_runpm_try_get(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ return pm_runtime_get_sync(dev);
+}
+
+static inline __must_check int
+nouveau_runpm_get(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+ int ret;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0 && ret != -EACCES) {
+ pm_runtime_put_autosuspend(dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline void
+nouveau_runpm_get_noresume(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_get_noresume(dev);
+}
+
+static inline void
+nouveau_runpm_disable(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_get_sync(dev);
+ pm_runtime_forbid(dev);
+}
+
+static inline void
+nouveau_runpm_enable(struct nouveau_drm *drm)
+{
+ struct device *dev = nouveau_runpm_dev(drm);
+
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 5000);
+ pm_runtime_set_active(dev);
+ pm_runtime_allow(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put(dev);
+}
+#endif
This wraps direct calls to pm_runtime functions to cleanup some common usage patterns, and keep the logic in one place. From the next commit, the pm_runtime calls will need to operate against the DRM driver's auxiliary device instead of directly on the underlying PCI device. This commit will help make that switch cleaner. Signed-off-by: Ben Skeggs <bskeggs@nvidia.com> --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 31 ++++--- drivers/gpu/drm/nouveau/nouveau_connector.c | 12 ++- drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/nouveau/nouveau_debugfs.c | 24 +++--- drivers/gpu/drm/nouveau/nouveau_display.c | 19 ++--- drivers/gpu/drm/nouveau/nouveau_drm.c | 45 ++++------- drivers/gpu/drm/nouveau/nouveau_gem.c | 30 +++---- drivers/gpu/drm/nouveau/nouveau_runpm.h | 89 +++++++++++++++++++++ 8 files changed, 156 insertions(+), 95 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_runpm.h