Skip to content

Commit

Permalink
drm/vc4: Enable runtime PM.
Browse files Browse the repository at this point in the history
This may actually get us a feature that the closed driver didn't have:
turning off the GPU in between rendering jobs, while the V3D device is
still opened by the client.

There may be some tuning to be applied here to use autosuspend so that
we don't bounce the device's power so much, but in steady-state
GPU-bound rendering we keep the power on (since we keep multiple jobs
outstanding) and even if we power cycle on every job we can still
manage at least 680 fps.

More importantly, though, runtime PM will allow us to power off the
device to do a GPU reset.

v2: Switch #ifdef to CONFIG_PM not CONFIG_PM_SLEEP (caught by kbuild
    test robot)

Signed-off-by: Eric Anholt <[email protected]>
  • Loading branch information
anholt committed Feb 16, 2016
1 parent c4ce60d commit 001bdb5
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/vc4/vc4_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ struct vc4_seqno_cb {
};

struct vc4_v3d {
struct vc4_dev *vc4;
struct platform_device *pdev;
void __iomem *regs;
};
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/vc4/vc4_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/device.h>
#include <linux/io.h>

Expand Down Expand Up @@ -621,6 +622,7 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
static void
vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
{
struct vc4_dev *vc4 = to_vc4_dev(dev);
unsigned i;

/* Need the struct lock for drm_gem_object_unreference(). */
Expand All @@ -639,6 +641,8 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
}
mutex_unlock(&dev->struct_mutex);

pm_runtime_put(&vc4->v3d->pdev->dev);

kfree(exec);
}

Expand Down Expand Up @@ -792,6 +796,12 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
return -ENOMEM;
}

ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
if (ret < 0) {
kfree(exec);
return ret;
}

exec->args = args;
INIT_LIST_HEAD(&exec->unref_list);

Expand Down
36 changes: 36 additions & 0 deletions drivers/gpu/drm/vc4/vc4_v3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#include "linux/component.h"
#include "linux/pm_runtime.h"
#include "vc4_drv.h"
#include "vc4_regs.h"

Expand Down Expand Up @@ -167,6 +168,29 @@ static void vc4_v3d_init_hw(struct drm_device *dev)
V3D_WRITE(V3D_VPMBASE, 0);
}

#ifdef CONFIG_PM
static int vc4_v3d_runtime_suspend(struct device *dev)
{
struct vc4_v3d *v3d = dev_get_drvdata(dev);
struct vc4_dev *vc4 = v3d->vc4;

vc4_irq_uninstall(vc4->dev);

return 0;
}

static int vc4_v3d_runtime_resume(struct device *dev)
{
struct vc4_v3d *v3d = dev_get_drvdata(dev);
struct vc4_dev *vc4 = v3d->vc4;

vc4_v3d_init_hw(vc4->dev);
vc4_irq_postinstall(vc4->dev);

return 0;
}
#endif

static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
Expand All @@ -179,13 +203,16 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
if (!v3d)
return -ENOMEM;

dev_set_drvdata(dev, v3d);

v3d->pdev = pdev;

v3d->regs = vc4_ioremap_regs(pdev, 0);
if (IS_ERR(v3d->regs))
return PTR_ERR(v3d->regs);

vc4->v3d = v3d;
v3d->vc4 = vc4;

if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
Expand All @@ -207,6 +234,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
return ret;
}

pm_runtime_enable(dev);

return 0;
}

Expand All @@ -216,6 +245,8 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
struct drm_device *drm = dev_get_drvdata(master);
struct vc4_dev *vc4 = to_vc4_dev(drm);

pm_runtime_disable(dev);

drm_irq_uninstall(drm);

/* Disable the binner's overflow memory address, so the next
Expand All @@ -228,6 +259,10 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
vc4->v3d = NULL;
}

static const struct dev_pm_ops vc4_v3d_pm_ops = {
SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL)
};

static const struct component_ops vc4_v3d_ops = {
.bind = vc4_v3d_bind,
.unbind = vc4_v3d_unbind,
Expand Down Expand Up @@ -255,5 +290,6 @@ struct platform_driver vc4_v3d_driver = {
.driver = {
.name = "vc4_v3d",
.of_match_table = vc4_v3d_dt_match,
.pm = &vc4_v3d_pm_ops,
},
};

0 comments on commit 001bdb5

Please sign in to comment.