diff options
author | Ben Skeggs | 2015-11-23 17:17:52 -0600 |
---|---|---|
committer | Ben Skeggs | 2015-12-21 21:21:56 -0600 |
commit | 4a3cbf5c0a38adf41d637c5d7273480336df39d0 (patch) | |
tree | bb07ba39db1d77bf2c86c1d9d76dbe0474f575d6 | |
parent | d1ec093e4c5b08c3825fe07e287aa3d023e9c9ae (diff) | |
download | external-libgbm-4a3cbf5c0a38adf41d637c5d7273480336df39d0.tar.gz external-libgbm-4a3cbf5c0a38adf41d637c5d7273480336df39d0.tar.xz external-libgbm-4a3cbf5c0a38adf41d637c5d7273480336df39d0.zip |
nouveau: move more abi16-specific logic into abi16.c
v2.
- add a comment about the (ab)use of nouveau_object::length
- add a comment about abi16_object() return values
v3.
- handle new client + old kernel for sw classes
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>
-rw-r--r-- | nouveau/abi16.c | 88 | ||||
-rw-r--r-- | nouveau/nouveau.c | 56 | ||||
-rw-r--r-- | nouveau/private.h | 7 |
3 files changed, 93 insertions, 58 deletions
diff --git a/nouveau/abi16.c b/nouveau/abi16.c index 59bc4360..44fda645 100644 --- a/nouveau/abi16.c +++ b/nouveau/abi16.c | |||
@@ -32,8 +32,10 @@ | |||
32 | 32 | ||
33 | #include "private.h" | 33 | #include "private.h" |
34 | 34 | ||
35 | #include "nvif/class.h" | ||
35 | 36 | ||
36 | drm_private int | 37 | |
38 | static int | ||
37 | abi16_chan_nv04(struct nouveau_object *obj) | 39 | abi16_chan_nv04(struct nouveau_object *obj) |
38 | { | 40 | { |
39 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; | 41 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; |
@@ -57,7 +59,7 @@ abi16_chan_nv04(struct nouveau_object *obj) | |||
57 | return 0; | 59 | return 0; |
58 | } | 60 | } |
59 | 61 | ||
60 | drm_private int | 62 | static int |
61 | abi16_chan_nvc0(struct nouveau_object *obj) | 63 | abi16_chan_nvc0(struct nouveau_object *obj) |
62 | { | 64 | { |
63 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; | 65 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; |
@@ -78,7 +80,7 @@ abi16_chan_nvc0(struct nouveau_object *obj) | |||
78 | return 0; | 80 | return 0; |
79 | } | 81 | } |
80 | 82 | ||
81 | drm_private int | 83 | static int |
82 | abi16_chan_nve0(struct nouveau_object *obj) | 84 | abi16_chan_nve0(struct nouveau_object *obj) |
83 | { | 85 | { |
84 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; | 86 | struct nouveau_device *dev = (struct nouveau_device *)obj->parent; |
@@ -104,7 +106,7 @@ abi16_chan_nve0(struct nouveau_object *obj) | |||
104 | return 0; | 106 | return 0; |
105 | } | 107 | } |
106 | 108 | ||
107 | drm_private int | 109 | static int |
108 | abi16_engobj(struct nouveau_object *obj) | 110 | abi16_engobj(struct nouveau_object *obj) |
109 | { | 111 | { |
110 | struct drm_nouveau_grobj_alloc req = { | 112 | struct drm_nouveau_grobj_alloc req = { |
@@ -115,6 +117,27 @@ abi16_engobj(struct nouveau_object *obj) | |||
115 | struct nouveau_device *dev; | 117 | struct nouveau_device *dev; |
116 | int ret; | 118 | int ret; |
117 | 119 | ||
120 | /* Older kernel versions did not have the concept of nouveau- | ||
121 | * specific classes and abused some NVIDIA-assigned ones for | ||
122 | * a SW class. The ABI16 layer has compatibility in place to | ||
123 | * translate these older identifiers to the newer ones. | ||
124 | * | ||
125 | * Clients that have been updated to use NVIF are required to | ||
126 | * use the newer class identifiers, which means that they'll | ||
127 | * break if running on an older kernel. | ||
128 | * | ||
129 | * To handle this case, when using ABI16, we translate to the | ||
130 | * older values which work on any kernel. | ||
131 | */ | ||
132 | switch (req.class) { | ||
133 | case NVIF_CLASS_SW_NV04 : req.class = 0x006e; break; | ||
134 | case NVIF_CLASS_SW_NV10 : req.class = 0x016e; break; | ||
135 | case NVIF_CLASS_SW_NV50 : req.class = 0x506e; break; | ||
136 | case NVIF_CLASS_SW_GF100: req.class = 0x906e; break; | ||
137 | default: | ||
138 | break; | ||
139 | } | ||
140 | |||
118 | dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); | 141 | dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); |
119 | ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC, | 142 | ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC, |
120 | &req, sizeof(req)); | 143 | &req, sizeof(req)); |
@@ -125,7 +148,7 @@ abi16_engobj(struct nouveau_object *obj) | |||
125 | return 0; | 148 | return 0; |
126 | } | 149 | } |
127 | 150 | ||
128 | drm_private int | 151 | static int |
129 | abi16_ntfy(struct nouveau_object *obj) | 152 | abi16_ntfy(struct nouveau_object *obj) |
130 | { | 153 | { |
131 | struct nv04_notify *ntfy = obj->data; | 154 | struct nv04_notify *ntfy = obj->data; |
@@ -149,6 +172,61 @@ abi16_ntfy(struct nouveau_object *obj) | |||
149 | } | 172 | } |
150 | 173 | ||
151 | drm_private void | 174 | drm_private void |
175 | abi16_delete(struct nouveau_object *obj) | ||
176 | { | ||
177 | struct nouveau_device *dev = | ||
178 | nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); | ||
179 | if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { | ||
180 | struct drm_nouveau_channel_free req; | ||
181 | req.channel = obj->handle; | ||
182 | drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE, | ||
183 | &req, sizeof(req)); | ||
184 | } else { | ||
185 | struct drm_nouveau_gpuobj_free req; | ||
186 | req.channel = obj->parent->handle; | ||
187 | req.handle = obj->handle; | ||
188 | drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE, | ||
189 | &req, sizeof(req)); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | drm_private bool | ||
194 | abi16_object(struct nouveau_object *obj, int (**func)(struct nouveau_object *)) | ||
195 | { | ||
196 | struct nouveau_object *parent = obj->parent; | ||
197 | |||
198 | /* nouveau_object::length is (ab)used to determine whether the | ||
199 | * object is a legacy object (!=0), or a real NVIF object. | ||
200 | */ | ||
201 | if ((parent->length != 0 && parent->oclass == NOUVEAU_DEVICE_CLASS)) { | ||
202 | if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { | ||
203 | struct nouveau_device *dev = (void *)parent; | ||
204 | if (dev->chipset < 0xc0) | ||
205 | *func = abi16_chan_nv04; | ||
206 | else | ||
207 | if (dev->chipset < 0xe0) | ||
208 | *func = abi16_chan_nvc0; | ||
209 | else | ||
210 | *func = abi16_chan_nve0; | ||
211 | return true; | ||
212 | } | ||
213 | } else | ||
214 | if ((parent->length != 0 && | ||
215 | parent->oclass == NOUVEAU_FIFO_CHANNEL_CLASS)) { | ||
216 | if (obj->oclass == NOUVEAU_NOTIFIER_CLASS) { | ||
217 | *func = abi16_ntfy; | ||
218 | return true; | ||
219 | } | ||
220 | |||
221 | *func = abi16_engobj; | ||
222 | return false; /* try NVIF, if supported, before calling func */ | ||
223 | } | ||
224 | |||
225 | *func = NULL; | ||
226 | return false; | ||
227 | } | ||
228 | |||
229 | drm_private void | ||
152 | abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info) | 230 | abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info) |
153 | { | 231 | { |
154 | struct nouveau_bo_priv *nvbo = nouveau_bo(bo); | 232 | struct nouveau_bo_priv *nvbo = nouveau_bo(bo); |
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index 97fd77b9..8a0be2fa 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c | |||
@@ -135,6 +135,7 @@ nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) | |||
135 | nvdev->gart_limit_percent = 80; | 135 | nvdev->gart_limit_percent = 80; |
136 | DRMINITLISTHEAD(&nvdev->bo_list); | 136 | DRMINITLISTHEAD(&nvdev->bo_list); |
137 | nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; | 137 | nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; |
138 | nvdev->base.object.length = ~0; | ||
138 | nvdev->base.lib_version = 0x01000000; | 139 | nvdev->base.lib_version = 0x01000000; |
139 | nvdev->base.chipset = chipset; | 140 | nvdev->base.chipset = chipset; |
140 | nvdev->base.vram_size = vram; | 141 | nvdev->base.vram_size = vram; |
@@ -251,8 +252,8 @@ nouveau_object_new(struct nouveau_object *parent, uint64_t handle, | |||
251 | uint32_t oclass, void *data, uint32_t length, | 252 | uint32_t oclass, void *data, uint32_t length, |
252 | struct nouveau_object **pobj) | 253 | struct nouveau_object **pobj) |
253 | { | 254 | { |
254 | struct nouveau_device *dev; | ||
255 | struct nouveau_object *obj; | 255 | struct nouveau_object *obj; |
256 | int (*func)(struct nouveau_object *); | ||
256 | int ret = -EINVAL; | 257 | int ret = -EINVAL; |
257 | 258 | ||
258 | if (length == 0) | 259 | if (length == 0) |
@@ -267,37 +268,9 @@ nouveau_object_new(struct nouveau_object *parent, uint64_t handle, | |||
267 | memcpy(obj->data, data, length); | 268 | memcpy(obj->data, data, length); |
268 | *(struct nouveau_object **)obj->data = obj; | 269 | *(struct nouveau_object **)obj->data = obj; |
269 | 270 | ||
270 | dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); | 271 | abi16_object(obj, &func); |
271 | switch (parent->oclass) { | 272 | if (func) |
272 | case NOUVEAU_DEVICE_CLASS: | 273 | ret = func(obj); |
273 | switch (obj->oclass) { | ||
274 | case NOUVEAU_FIFO_CHANNEL_CLASS: | ||
275 | { | ||
276 | if (dev->chipset < 0xc0) | ||
277 | ret = abi16_chan_nv04(obj); | ||
278 | else | ||
279 | if (dev->chipset < 0xe0) | ||
280 | ret = abi16_chan_nvc0(obj); | ||
281 | else | ||
282 | ret = abi16_chan_nve0(obj); | ||
283 | } | ||
284 | break; | ||
285 | default: | ||
286 | break; | ||
287 | } | ||
288 | break; | ||
289 | case NOUVEAU_FIFO_CHANNEL_CLASS: | ||
290 | switch (obj->oclass) { | ||
291 | case NOUVEAU_NOTIFIER_CLASS: | ||
292 | ret = abi16_ntfy(obj); | ||
293 | break; | ||
294 | default: | ||
295 | ret = abi16_engobj(obj); | ||
296 | break; | ||
297 | } | ||
298 | default: | ||
299 | break; | ||
300 | } | ||
301 | 274 | ||
302 | if (ret) { | 275 | if (ret) { |
303 | free(obj); | 276 | free(obj); |
@@ -312,24 +285,11 @@ void | |||
312 | nouveau_object_del(struct nouveau_object **pobj) | 285 | nouveau_object_del(struct nouveau_object **pobj) |
313 | { | 286 | { |
314 | struct nouveau_object *obj = *pobj; | 287 | struct nouveau_object *obj = *pobj; |
315 | struct nouveau_device *dev; | ||
316 | if (obj) { | 288 | if (obj) { |
317 | dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS); | 289 | abi16_delete(obj); |
318 | if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) { | 290 | free(obj); |
319 | struct drm_nouveau_channel_free req; | 291 | *pobj = NULL; |
320 | req.channel = obj->handle; | ||
321 | drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE, | ||
322 | &req, sizeof(req)); | ||
323 | } else { | ||
324 | struct drm_nouveau_gpuobj_free req; | ||
325 | req.channel = obj->parent->handle; | ||
326 | req.handle = obj->handle; | ||
327 | drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE, | ||
328 | &req, sizeof(req)); | ||
329 | } | ||
330 | } | 292 | } |
331 | free(obj); | ||
332 | *pobj = NULL; | ||
333 | } | 293 | } |
334 | 294 | ||
335 | void * | 295 | void * |
diff --git a/nouveau/private.h b/nouveau/private.h index e9439f30..5f352a49 100644 --- a/nouveau/private.h +++ b/nouveau/private.h | |||
@@ -114,11 +114,8 @@ int | |||
114 | nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t); | 114 | nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t); |
115 | 115 | ||
116 | /* abi16.c */ | 116 | /* abi16.c */ |
117 | drm_private int abi16_chan_nv04(struct nouveau_object *); | 117 | drm_private bool abi16_object(struct nouveau_object *, int (**)(struct nouveau_object *)); |
118 | drm_private int abi16_chan_nvc0(struct nouveau_object *); | 118 | drm_private void abi16_delete(struct nouveau_object *); |
119 | drm_private int abi16_chan_nve0(struct nouveau_object *); | ||
120 | drm_private int abi16_engobj(struct nouveau_object *); | ||
121 | drm_private int abi16_ntfy(struct nouveau_object *); | ||
122 | drm_private void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *); | 119 | drm_private void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *); |
123 | drm_private int abi16_bo_init(struct nouveau_bo *, uint32_t alignment, | 120 | drm_private int abi16_bo_init(struct nouveau_bo *, uint32_t alignment, |
124 | union nouveau_bo_config *); | 121 | union nouveau_bo_config *); |