aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs2015-11-23 18:10:04 -0600
committerBen Skeggs2015-12-21 21:22:14 -0600
commitf6b1b5b7c9cf6667d169bad3b33a73e4fe2bc14c (patch)
treecb501fa1f27a6881053abe68baac1dcdf45b46f0 /nouveau
parentc00e1a92a24cb84008d90ce67218bb593396fde5 (diff)
downloadexternal-libgbm-f6b1b5b7c9cf6667d169bad3b33a73e4fe2bc14c.tar.gz
external-libgbm-f6b1b5b7c9cf6667d169bad3b33a73e4fe2bc14c.tar.xz
external-libgbm-f6b1b5b7c9cf6667d169bad3b33a73e4fe2bc14c.zip
nouveau: add interfaces to query information about supported classes
This will expose functionality supported by newer kernel interfaces. Current userspace uses the chipset to determine which classes are likely exposed, which generally works pretty well, but isn't as flexible as it could be. Unfortunately, the G98:GF100 video code in Mesa is still relying on the kernel exposing incorrect vdec classes on some chipsets. The ABI16 kernel interfaces have a workaround for this in place, but that will no longer be available once libdrm supports NVIF. To prevent a regression when NVIF support is added, if there's no kernel support for NVIF, libdrm will magic up a class list containing correct vdec classes anyway instead of failing with -ENODEV. v2. - add description of abi16/vdec workaround - add description of sclass/mclass - leave client-provided pointer unmodified on abi16_sclass() failure Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Diffstat (limited to 'nouveau')
-rw-r--r--nouveau/abi16.c51
-rwxr-xr-xnouveau/nouveau-symbol-check3
-rw-r--r--nouveau/nouveau.c41
-rw-r--r--nouveau/nouveau.h22
-rw-r--r--nouveau/private.h1
5 files changed, 117 insertions, 1 deletions
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
index 44fda645..f260bf95 100644
--- a/nouveau/abi16.c
+++ b/nouveau/abi16.c
@@ -29,12 +29,12 @@
29#include <stdlib.h> 29#include <stdlib.h>
30#include <stdint.h> 30#include <stdint.h>
31#include <stddef.h> 31#include <stddef.h>
32#include <errno.h>
32 33
33#include "private.h" 34#include "private.h"
34 35
35#include "nvif/class.h" 36#include "nvif/class.h"
36 37
37
38static int 38static int
39abi16_chan_nv04(struct nouveau_object *obj) 39abi16_chan_nv04(struct nouveau_object *obj)
40{ 40{
@@ -171,6 +171,55 @@ abi16_ntfy(struct nouveau_object *obj)
171 return 0; 171 return 0;
172} 172}
173 173
174drm_private int
175abi16_sclass(struct nouveau_object *obj, struct nouveau_sclass **psclass)
176{
177 struct nouveau_sclass *sclass;
178 struct nouveau_device *dev;
179
180 if (!(sclass = calloc(8, sizeof(*sclass))))
181 return -ENOMEM;
182 *psclass = sclass;
183
184 switch (obj->oclass) {
185 case NOUVEAU_FIFO_CHANNEL_CLASS:
186 /* Older kernel versions were exposing the wrong video engine
187 * classes on certain G98:GF100 boards. This has since been
188 * corrected, but ABI16 has compatibility in place to avoid
189 * breaking older userspace.
190 *
191 * Clients that have been updated to use NVIF are required to
192 * use the correct classes, which means that they'll break if
193 * running on an older kernel.
194 *
195 * To handle this issue, if using the older kernel interfaces,
196 * we'll magic up a list containing the vdec classes that the
197 * kernel will accept for these boards. Clients should make
198 * use of this information instead of hardcoding classes for
199 * specific chipsets.
200 */
201 dev = (struct nouveau_device *)obj->parent;
202 if (dev->chipset >= 0x98 &&
203 dev->chipset != 0xa0 &&
204 dev->chipset < 0xc0) {
205 *sclass++ = (struct nouveau_sclass){
206 GT212_MSVLD, -1, -1
207 };
208 *sclass++ = (struct nouveau_sclass){
209 GT212_MSPDEC, -1, -1
210 };
211 *sclass++ = (struct nouveau_sclass){
212 GT212_MSPPP, -1, -1
213 };
214 }
215 break;
216 default:
217 break;
218 }
219
220 return sclass - *psclass;
221}
222
174drm_private void 223drm_private void
175abi16_delete(struct nouveau_object *obj) 224abi16_delete(struct nouveau_object *obj)
176{ 225{
diff --git a/nouveau/nouveau-symbol-check b/nouveau/nouveau-symbol-check
index 73301702..38b6ec52 100755
--- a/nouveau/nouveau-symbol-check
+++ b/nouveau/nouveau-symbol-check
@@ -33,8 +33,11 @@ nouveau_device_wrap
33nouveau_getparam 33nouveau_getparam
34nouveau_object_del 34nouveau_object_del
35nouveau_object_find 35nouveau_object_find
36nouveau_object_mclass
36nouveau_object_mthd 37nouveau_object_mthd
37nouveau_object_new 38nouveau_object_new
39nouveau_object_sclass_get
40nouveau_object_sclass_put
38nouveau_pushbuf_bufctx 41nouveau_pushbuf_bufctx
39nouveau_pushbuf_data 42nouveau_pushbuf_data
40nouveau_pushbuf_del 43nouveau_pushbuf_del
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
index 1871e8cd..00173034 100644
--- a/nouveau/nouveau.c
+++ b/nouveau/nouveau.c
@@ -66,6 +66,47 @@ nouveau_object_mthd(struct nouveau_object *obj,
66 return -ENODEV; 66 return -ENODEV;
67} 67}
68 68
69void
70nouveau_object_sclass_put(struct nouveau_sclass **psclass)
71{
72 free(*psclass);
73 *psclass = NULL;
74}
75
76int
77nouveau_object_sclass_get(struct nouveau_object *obj,
78 struct nouveau_sclass **psclass)
79{
80 return abi16_sclass(obj, psclass);
81}
82
83int
84nouveau_object_mclass(struct nouveau_object *obj,
85 const struct nouveau_mclass *mclass)
86{
87 struct nouveau_sclass *sclass;
88 int ret = -ENODEV;
89 int cnt, i, j;
90
91 cnt = nouveau_object_sclass_get(obj, &sclass);
92 if (cnt < 0)
93 return cnt;
94
95 for (i = 0; ret < 0 && mclass[i].oclass; i++) {
96 for (j = 0; j < cnt; j++) {
97 if (mclass[i].oclass == sclass[j].oclass &&
98 mclass[i].version >= sclass[j].minver &&
99 mclass[i].version <= sclass[j].maxver) {
100 ret = i;
101 break;
102 }
103 }
104 }
105
106 nouveau_object_sclass_put(&sclass);
107 return ret;
108}
109
69static void 110static void
70nouveau_object_fini(struct nouveau_object *obj) 111nouveau_object_fini(struct nouveau_object *obj)
71{ 112{
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
index 4c95409e..24cda6f1 100644
--- a/nouveau/nouveau.h
+++ b/nouveau/nouveau.h
@@ -63,12 +63,34 @@ struct nv04_notify {
63 uint32_t length; 63 uint32_t length;
64}; 64};
65 65
66/* Supported class information, provided by the kernel */
67struct nouveau_sclass {
68 int32_t oclass;
69 int minver;
70 int maxver;
71};
72
73/* Client-provided array describing class versions that are desired.
74 *
75 * These are used to match against the kernel's list of supported classes.
76 */
77struct nouveau_mclass {
78 int32_t oclass; /* 0 == EOL */
79 int version;
80 void *data;
81};
82
66int nouveau_object_new(struct nouveau_object *parent, uint64_t handle, 83int nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
67 uint32_t oclass, void *data, uint32_t length, 84 uint32_t oclass, void *data, uint32_t length,
68 struct nouveau_object **); 85 struct nouveau_object **);
69void nouveau_object_del(struct nouveau_object **); 86void nouveau_object_del(struct nouveau_object **);
70int nouveau_object_mthd(struct nouveau_object *, uint32_t mthd, 87int nouveau_object_mthd(struct nouveau_object *, uint32_t mthd,
71 void *data, uint32_t size); 88 void *data, uint32_t size);
89int nouveau_object_sclass_get(struct nouveau_object *,
90 struct nouveau_sclass **);
91void nouveau_object_sclass_put(struct nouveau_sclass **);
92int nouveau_object_mclass(struct nouveau_object *,
93 const struct nouveau_mclass *);
72void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class); 94void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class);
73 95
74struct nouveau_device { 96struct nouveau_device {
diff --git a/nouveau/private.h b/nouveau/private.h
index 5f352a49..83060f96 100644
--- a/nouveau/private.h
+++ b/nouveau/private.h
@@ -116,6 +116,7 @@ nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t);
116/* abi16.c */ 116/* abi16.c */
117drm_private bool abi16_object(struct nouveau_object *, int (**)(struct nouveau_object *)); 117drm_private bool abi16_object(struct nouveau_object *, int (**)(struct nouveau_object *));
118drm_private void abi16_delete(struct nouveau_object *); 118drm_private void abi16_delete(struct nouveau_object *);
119drm_private int abi16_sclass(struct nouveau_object *, struct nouveau_sclass **);
119drm_private void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *); 120drm_private void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *);
120drm_private int abi16_bo_init(struct nouveau_bo *, uint32_t alignment, 121drm_private int abi16_bo_init(struct nouveau_bo *, uint32_t alignment,
121 union nouveau_bo_config *); 122 union nouveau_bo_config *);