drm/nouveau/disp: audit and version SCANOUTPOS method
authorBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 18:10:27 +0000 (04:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 19:28:10 +0000 (05:28 +1000)
The full object interfaces are about to be exposed to userspace, so we
need to check for any security-related issues and version the structs
to make it easier to handle any changes we may need in the future.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
15 files changed:
drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/include/core/class.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nvif/class.h
drivers/gpu/drm/nouveau/nvif/object.h

index f93d76e..6a25f38 100644 (file)
@@ -45,7 +45,7 @@ gm107_disp_sclass[] = {
 
 static struct nouveau_oclass
 gm107_disp_base_oclass[] = {
-       { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+       { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs },
        {}
 };
 
@@ -99,4 +99,5 @@ gm107_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nvd0_disp_sync_mthd_chan,
        .mthd.ovly = &nve0_disp_ovly_mthd_chan,
        .mthd.prev = -0x020000,
+       .head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
index f1f3bd1..6dba53d 100644 (file)
 
 #include "priv.h"
 
+#include <core/client.h>
 #include <core/event.h>
 #include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 struct nv04_disp_priv {
        struct nouveau_disp base;
 };
 
 static int
-nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
-                    void *data, u32 size)
+nv04_disp_scanoutpos(struct nouveau_object *object, struct nv04_disp_priv *priv,
+                    void *data, u32 size, int head)
 {
-       struct nv04_disp_priv *priv = (void *)object->engine;
-       struct nv04_display_scanoutpos *args = data;
-       const int head = (mthd & NV04_DISP_MTHD_HEAD);
+       const u32 hoff = head * 0x2000;
+       union {
+               struct nv04_disp_scanoutpos_v0 v0;
+       } *args = data;
        u32 line;
+       int ret;
+
+       nv_ioctl(object, "disp scanoutpos size %d\n", size);
+       if (nvif_unpack(args->v0, 0, 0, false)) {
+               nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+               args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff;
+               args->v0.vtotal  = nv_rd32(priv, 0x680804 + hoff) & 0xffff;
+               args->v0.vblanke = args->v0.vtotal - 1;
+
+               args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff;
+               args->v0.htotal  = nv_rd32(priv, 0x680824 + hoff) & 0xffff;
+               args->v0.hblanke = args->v0.htotal - 1;
+
+               /*
+                * If output is vga instead of digital then vtotal/htotal is
+                * invalid so we have to give up and trigger the timestamping
+                * fallback in the drm core.
+                */
+               if (!args->v0.vtotal || !args->v0.htotal)
+                       return -ENOTSUPP;
+
+               args->v0.time[0] = ktime_to_ns(ktime_get());
+               line = nv_rd32(priv, 0x600868 + hoff);
+               args->v0.time[1] = ktime_to_ns(ktime_get());
+               args->v0.hline = (line & 0xffff0000) >> 16;
+               args->v0.vline = (line & 0x0000ffff);
+       } else
+               return ret;
 
-       if (size < sizeof(*args))
-               return -EINVAL;
-
-       args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
-       args->vtotal  = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
-       args->vblanke = args->vtotal - 1;
-
-       args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
-       args->htotal  = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
-       args->hblanke = args->htotal - 1;
-
-       /*
-        * If output is vga instead of digital then vtotal/htotal is invalid
-        * so we have to give up and trigger the timestamping fallback in the
-        * drm core.
-        */
-       if (!args->vtotal || !args->htotal)
-               return -ENOTSUPP;
-
-       args->time[0] = ktime_to_ns(ktime_get());
-       line = nv_rd32(priv, 0x600868 + (head * 0x2000));
-       args->time[1] = ktime_to_ns(ktime_get());
-       args->hline = (line & 0xffff0000) >> 16;
-       args->vline = (line & 0x0000ffff);
        return 0;
 }
 
-#define HEAD_MTHD(n) (n), (n) + 0x01
+static int
+nv04_disp_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+       union {
+               struct nv04_disp_mthd_v0 v0;
+       } *args = data;
+       struct nv04_disp_priv *priv = (void *)object->engine;
+       int head, ret;
+
+       nv_ioctl(object, "disp mthd size %d\n", size);
+       if (nvif_unpack(args->v0, 0, 0, true)) {
+               nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+                        args->v0.version, args->v0.method, args->v0.head);
+               mthd = args->v0.method;
+               head = args->v0.head;
+       } else
+               return ret;
+
+       if (head < 0 || head >= 2)
+               return -ENXIO;
+
+       switch (mthd) {
+       case NV04_DISP_SCANOUTPOS:
+               return nv04_disp_scanoutpos(object, priv, data, size, head);
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
 
-static struct nouveau_omthds
-nv04_disp_omthds[] = {
-       { HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
-       {}
+static struct nouveau_ofuncs
+nv04_disp_ofuncs = {
+       .ctor = _nouveau_object_ctor,
+       .dtor = nouveau_object_destroy,
+       .init = nouveau_object_init,
+       .fini = nouveau_object_fini,
+       .mthd = nv04_disp_mthd,
 };
 
 static struct nouveau_oclass
 nv04_disp_sclass[] = {
-       { NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
+       { NV04_DISP_CLASS, &nv04_disp_ofuncs },
        {},
 };
 
index d83d3ef..7e60c11 100644 (file)
@@ -814,31 +814,34 @@ nv50_disp_curs_ofuncs = {
  ******************************************************************************/
 
 int
-nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
-                         void *data, u32 size)
+nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
 {
-       struct nv50_disp_priv *priv = (void *)object->engine;
-       struct nv04_display_scanoutpos *args = data;
-       const int head = (mthd & NV50_DISP_MTHD_HEAD);
-       u32 blanke, blanks, total;
+       const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+       const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+       const u32 total  = nv_rd32(priv, 0x610afc + (head * 0x540));
+       union {
+               struct nv04_disp_scanoutpos_v0 v0;
+       } *args = data;
+       int ret;
+
+       nv_ioctl(object, "disp scanoutpos size %d\n", size);
+       if (nvif_unpack(args->v0, 0, 0, false)) {
+               nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+               args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+               args->v0.hblanke = (blanke & 0x0000ffff);
+               args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+               args->v0.hblanks = (blanks & 0x0000ffff);
+               args->v0.vtotal  = ( total & 0xffff0000) >> 16;
+               args->v0.htotal  = ( total & 0x0000ffff);
+               args->v0.time[0] = ktime_to_ns(ktime_get());
+               args->v0.vline = /* vline read locks hline */
+                       nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+               args->v0.time[1] = ktime_to_ns(ktime_get());
+               args->v0.hline =
+                       nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+       } else
+               return ret;
 
-       if (size < sizeof(*args) || head >= priv->head.nr)
-               return -EINVAL;
-       blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
-       blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
-       total  = nv_rd32(priv, 0x610afc + (head * 0x540));
-
-       args->vblanke = (blanke & 0xffff0000) >> 16;
-       args->hblanke = (blanke & 0x0000ffff);
-       args->vblanks = (blanks & 0xffff0000) >> 16;
-       args->hblanks = (blanks & 0x0000ffff);
-       args->vtotal  = ( total & 0xffff0000) >> 16;
-       args->htotal  = ( total & 0x0000ffff);
-
-       args->time[0] = ktime_to_ns(ktime_get());
-       args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
-       args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
-       args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
        return 0;
 }
 
@@ -846,6 +849,7 @@ int
 nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
                    void *data, u32 size)
 {
+       const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
        union {
                struct nv50_disp_mthd_v0 v0;
                struct nv50_disp_mthd_v1 v1;
@@ -894,6 +898,8 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
        }
 
        switch (mthd) {
+       case NV50_DISP_SCANOUTPOS:
+               return impl->head.scanoutpos(object, priv, data, size, head);
        default:
                break;
        }
@@ -1081,15 +1087,9 @@ nv50_disp_base_ofuncs = {
        .mthd = nv50_disp_base_mthd,
 };
 
-static struct nouveau_omthds
-nv50_disp_base_omthds[] = {
-       { HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-       {},
-};
-
 static struct nouveau_oclass
 nv50_disp_base_oclass[] = {
-       { NV50_DISP_CLASS, &nv50_disp_base_ofuncs, nv50_disp_base_omthds },
+       { NV50_DISP_CLASS, &nv50_disp_base_ofuncs },
        {}
 };
 
@@ -1859,4 +1859,5 @@ nv50_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nv50_disp_sync_mthd_chan,
        .mthd.ovly = &nv50_disp_ovly_mthd_chan,
        .mthd.prev = 0x000004,
+       .head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
index 62a38b5..81bf80f 100644 (file)
 #include "outp.h"
 #include "outpdp.h"
 
-struct nv50_disp_impl {
-       struct nouveau_disp_impl base;
-       struct {
-               const struct nv50_disp_mthd_chan *core;
-               const struct nv50_disp_mthd_chan *base;
-               const struct nv50_disp_mthd_chan *ovly;
-               int prev;
-       } mthd;
-};
-
 #define NV50_DISP_MTHD_ struct nouveau_object *object,                         \
        struct nv50_disp_priv *priv, void *data, u32 size
 #define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
@@ -58,18 +48,27 @@ struct nv50_disp_priv {
        } pior;
 };
 
-#define HEAD_MTHD(n) (n), (n) + 0x03
+struct nv50_disp_impl {
+       struct nouveau_disp_impl base;
+       struct {
+               const struct nv50_disp_mthd_chan *core;
+               const struct nv50_disp_mthd_chan *base;
+               const struct nv50_disp_mthd_chan *ovly;
+               int prev;
+       } mthd;
+       struct {
+               int (*scanoutpos)(NV50_DISP_MTHD_V0);
+       } head;
+};
 
-int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+int nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
 int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
 
-#define DAC_MTHD(n) (n), (n) + 0x03
+int nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
 
 int nv50_dac_power(NV50_DISP_MTHD_V1);
 int nv50_dac_sense(NV50_DISP_MTHD_V1);
 
-#define SOR_MTHD(n) (n), (n) + 0x3f
-
 int nva3_hda_eld(NV50_DISP_MTHD_V1);
 int nvd0_hda_eld(NV50_DISP_MTHD_V1);
 
@@ -97,8 +96,6 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
 int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
                       struct dcb_output *);
 
-#define PIOR_MTHD(n) (n), (n) + 0x03
-
 int nv50_pior_power(NV50_DISP_MTHD_V1);
 
 struct nv50_disp_base {
@@ -203,7 +200,6 @@ extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
 extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
 extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
 extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
-extern struct nouveau_omthds nv84_disp_base_omthds[];
 
 extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
 
@@ -217,7 +213,6 @@ extern struct nv50_disp_chan_impl nvd0_disp_ovly_ofuncs;
 extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
 extern struct nv50_disp_chan_impl nvd0_disp_oimm_ofuncs;
 extern struct nv50_disp_chan_impl nvd0_disp_curs_ofuncs;
-extern struct nouveau_omthds nvd0_disp_base_omthds[];
 extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
 extern struct nouveau_oclass nvd0_disp_cclass;
 void nvd0_disp_intr_supervisor(struct work_struct *);
index c0012d8..8746644 100644 (file)
@@ -212,15 +212,9 @@ nv84_disp_sclass[] = {
        {}
 };
 
-struct nouveau_omthds
-nv84_disp_base_omthds[] = {
-       { HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-       {},
-};
-
 static struct nouveau_oclass
 nv84_disp_base_oclass[] = {
-       { NV84_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+       { NV84_DISP_CLASS, &nv50_disp_base_ofuncs },
        {}
 };
 
@@ -274,4 +268,5 @@ nv84_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nv84_disp_sync_mthd_chan,
        .mthd.ovly = &nv84_disp_ovly_mthd_chan,
        .mthd.prev = 0x000004,
+       .head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
index 192c808..11cd16a 100644 (file)
@@ -71,15 +71,9 @@ nv94_disp_sclass[] = {
        {}
 };
 
-static struct nouveau_omthds
-nv94_disp_base_omthds[] = {
-       { HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-       {},
-};
-
 static struct nouveau_oclass
 nv94_disp_base_oclass[] = {
-       { NV94_DISP_CLASS, &nv50_disp_base_ofuncs, nv94_disp_base_omthds },
+       { NV94_DISP_CLASS, &nv50_disp_base_ofuncs },
        {}
 };
 
@@ -140,4 +134,5 @@ nv94_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nv84_disp_sync_mthd_chan,
        .mthd.ovly = &nv84_disp_ovly_mthd_chan,
        .mthd.prev = 0x000004,
+       .head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
index bfd5cf1..3819575 100644 (file)
@@ -90,7 +90,7 @@ nva0_disp_sclass[] = {
 
 static struct nouveau_oclass
 nva0_disp_base_oclass[] = {
-       { NVA0_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+       { NVA0_DISP_CLASS, &nv50_disp_base_ofuncs },
        {}
 };
 
@@ -144,4 +144,5 @@ nva0_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nv84_disp_sync_mthd_chan,
        .mthd.ovly = &nva0_disp_ovly_mthd_chan,
        .mthd.prev = 0x000004,
+       .head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
index 38a79a0..25df6b9 100644 (file)
@@ -43,15 +43,9 @@ nva3_disp_sclass[] = {
        {}
 };
 
-static struct nouveau_omthds
-nva3_disp_base_omthds[] = {
-       { HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
-       {},
-};
-
 static struct nouveau_oclass
 nva3_disp_base_oclass[] = {
-       { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs, nva3_disp_base_omthds },
+       { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs },
        {}
 };
 
@@ -106,4 +100,5 @@ nva3_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nv84_disp_sync_mthd_chan,
        .mthd.ovly = &nv84_disp_ovly_mthd_chan,
        .mthd.prev = 0x000004,
+       .head.scanoutpos = nv50_disp_base_scanoutpos,
 }.base.base;
index 5aa44ec..deddd05 100644 (file)
  */
 
 #include <core/object.h>
+#include <core/client.h>
 #include <core/parent.h>
 #include <core/handle.h>
 #include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
 
 #include <engine/disp.h>
 
@@ -589,33 +592,35 @@ nvd0_disp_curs_ofuncs = {
  * Base display object
  ******************************************************************************/
 
-static int
-nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
-                         void *data, u32 size)
+int
+nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
 {
-       struct nv50_disp_priv *priv = (void *)object->engine;
-       struct nv04_display_scanoutpos *args = data;
-       const int head = (mthd & NV50_DISP_MTHD_HEAD);
-       u32 blanke, blanks, total;
-
-       if (size < sizeof(*args) || head >= priv->head.nr)
-               return -EINVAL;
-
-       total  = nv_rd32(priv, 0x640414 + (head * 0x300));
-       blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
-       blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
-
-       args->vblanke = (blanke & 0xffff0000) >> 16;
-       args->hblanke = (blanke & 0x0000ffff);
-       args->vblanks = (blanks & 0xffff0000) >> 16;
-       args->hblanks = (blanks & 0x0000ffff);
-       args->vtotal  = ( total & 0xffff0000) >> 16;
-       args->htotal  = ( total & 0x0000ffff);
-
-       args->time[0] = ktime_to_ns(ktime_get());
-       args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
-       args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
-       args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+       const u32 total  = nv_rd32(priv, 0x640414 + (head * 0x300));
+       const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+       const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+       union {
+               struct nv04_disp_scanoutpos_v0 v0;
+       } *args = data;
+       int ret;
+
+       nv_ioctl(object, "disp scanoutpos size %d\n", size);
+       if (nvif_unpack(args->v0, 0, 0, false)) {
+               nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+               args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+               args->v0.hblanke = (blanke & 0x0000ffff);
+               args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+               args->v0.hblanks = (blanks & 0x0000ffff);
+               args->v0.vtotal  = ( total & 0xffff0000) >> 16;
+               args->v0.htotal  = ( total & 0x0000ffff);
+               args->v0.time[0] = ktime_to_ns(ktime_get());
+               args->v0.vline = /* vline read locks hline */
+                       nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+               args->v0.time[1] = ktime_to_ns(ktime_get());
+               args->v0.hline =
+                       nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+       } else
+               return ret;
+
        return 0;
 }
 
@@ -709,15 +714,9 @@ nvd0_disp_base_ofuncs = {
        .mthd = nv50_disp_base_mthd,
 };
 
-struct nouveau_omthds
-nvd0_disp_base_omthds[] = {
-       { HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nvd0_disp_base_scanoutpos },
-       {},
-};
-
 static struct nouveau_oclass
 nvd0_disp_base_oclass[] = {
-       { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+       { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs },
        {}
 };
 
@@ -1242,4 +1241,5 @@ nvd0_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nvd0_disp_sync_mthd_chan,
        .mthd.ovly = &nvd0_disp_ovly_mthd_chan,
        .mthd.prev = -0x020000,
+       .head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
index 49ab742..58b0ac1 100644 (file)
@@ -210,7 +210,7 @@ nve0_disp_sclass[] = {
 
 static struct nouveau_oclass
 nve0_disp_base_oclass[] = {
-       { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+       { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs },
        {}
 };
 
@@ -264,4 +264,5 @@ nve0_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nvd0_disp_sync_mthd_chan,
        .mthd.ovly = &nve0_disp_ovly_mthd_chan,
        .mthd.prev = -0x020000,
+       .head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
index 448dc91..b6b0146 100644 (file)
@@ -45,7 +45,7 @@ nvf0_disp_sclass[] = {
 
 static struct nouveau_oclass
 nvf0_disp_base_oclass[] = {
-       { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+       { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs },
        {}
 };
 
@@ -99,4 +99,5 @@ nvf0_disp_oclass = &(struct nv50_disp_impl) {
        .mthd.base = &nvd0_disp_sync_mthd_chan,
        .mthd.ovly = &nve0_disp_ovly_mthd_chan,
        .mthd.prev = -0x020000,
+       .head.scanoutpos = nvd0_disp_base_scanoutpos,
 }.base.base;
index 9f8066d..24b85a9 100644 (file)
@@ -8,26 +8,9 @@
 
 #define NV04_DISP_CLASS                                              0x00000046
 
-#define NV04_DISP_MTHD                                               0x00000000
-#define NV04_DISP_MTHD_HEAD                                          0x00000001
-
-#define NV04_DISP_SCANOUTPOS                                         0x00000000
-
 struct nv04_display_class {
 };
 
-struct nv04_display_scanoutpos {
-       s64 time[2];
-       u32 vblanks;
-       u32 vblanke;
-       u32 vtotal;
-       u32 vline;
-       u32 hblanks;
-       u32 hblanke;
-       u32 htotal;
-       u32 hline;
-};
-
 /* 5070: NV50_DISP
  * 8270: NV84_DISP
  * 8370: NVA0_DISP
@@ -49,10 +32,6 @@ struct nv04_display_scanoutpos {
 #define NVF0_DISP_CLASS                                              0x00009270
 #define GM107_DISP_CLASS                                             0x00009470
 
-#define NV50_DISP_MTHD_HEAD                                          0x00000003
-
-#define NV50_DISP_SCANOUTPOS                                         0x00000000
-
 struct nv50_display_class {
 };
 
index ffea6c4..f00e56c 100644 (file)
@@ -95,17 +95,22 @@ int
 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                                ktime_t *stime, ktime_t *etime)
 {
-       const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
+       struct {
+               struct nv04_disp_mthd_v0 base;
+               struct nv04_disp_scanoutpos_v0 scan;
+       } args = {
+               .base.method = NV04_DISP_SCANOUTPOS,
+               .base.head = nouveau_crtc(crtc)->index,
+       };
        struct nouveau_display *disp = nouveau_display(crtc->dev);
-       struct nv04_display_scanoutpos args;
        int ret, retry = 1;
 
        do {
-               ret = nvif_exec(&disp->disp, mthd, &args, sizeof(args));
+               ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
                if (ret != 0)
                        return 0;
 
-               if (args.vline) {
+               if (args.scan.vline) {
                        ret |= DRM_SCANOUTPOS_ACCURATE;
                        ret |= DRM_SCANOUTPOS_VALID;
                        break;
@@ -114,10 +119,11 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                if (retry) ndelay(crtc->linedur_ns);
        } while (retry--);
 
-       *hpos = args.hline;
-       *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
-       if (stime) *stime = ns_to_ktime(args.time[0]);
-       if (etime) *etime = ns_to_ktime(args.time[1]);
+       *hpos = args.scan.hline;
+       *vpos = calc(args.scan.vblanks, args.scan.vblanke,
+                    args.scan.vtotal, args.scan.vline);
+       if (stime) *stime = ns_to_ktime(args.scan.time[0]);
+       if (etime) *etime = ns_to_ktime(args.scan.time[1]);
 
        if (*vpos < 0)
                ret |= DRM_SCANOUTPOS_INVBL;
index f869f94..b0998e7 100644 (file)
@@ -294,6 +294,28 @@ struct kepler_channel_gpfifo_a_v0 {
  * legacy display
  ******************************************************************************/
 
+struct nv04_disp_mthd_v0 {
+       __u8  version;
+#define NV04_DISP_SCANOUTPOS                                               0x00
+       __u8  method;
+       __u8  head;
+       __u8  pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+       __u8  version;
+       __u8  pad01[7];
+       __s64 time[2];
+       __u16 vblanks;
+       __u16 vblanke;
+       __u16 vtotal;
+       __u16 vline;
+       __u16 hblanks;
+       __u16 hblanke;
+       __u16 htotal;
+       __u16 hline;
+};
+
 
 /*******************************************************************************
  * display
@@ -303,6 +325,7 @@ struct kepler_channel_gpfifo_a_v0 {
 
 struct nv50_disp_mthd_v0 {
        __u8  version;
+#define NV50_DISP_SCANOUTPOS                                               0x00
        __u8  method;
        __u8  head;
        __u8  pad03[5];
index a5d8281..fac3a3b 100644 (file)
@@ -71,6 +71,5 @@ void nvif_object_unmap(struct nvif_object *);
 /*XXX*/
 #include <core/object.h>
 #define nvkm_object(a) ((struct nouveau_object *)nvif_object(a)->priv)
-#define nvif_exec(a,b,c,d) nv_exec(nvkm_object(a), (b), (c), (d))
 
 #endif