From: Ben Skeggs <bske...@redhat.com> Signed-off-by: Ben Skeggs <bske...@redhat.com> --- nouveau/nouveau-symbol-check | 1 + nouveau/nouveau.c | 133 ++++++++++++++++++++++++++++--------------- nouveau/nouveau.h | 2 + 3 files changed, 89 insertions(+), 47 deletions(-)
diff --git a/nouveau/nouveau-symbol-check b/nouveau/nouveau-symbol-check index 275b6e7..b265cea 100755 --- a/nouveau/nouveau-symbol-check +++ b/nouveau/nouveau-symbol-check @@ -27,6 +27,7 @@ nouveau_bufctx_reset nouveau_client_del nouveau_client_new nouveau_device_del +nouveau_device_new nouveau_device_open nouveau_device_open_existing nouveau_device_wrap diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c index 56e00ac..fef338b 100644 --- a/nouveau/nouveau.c +++ b/nouveau/nouveau.c @@ -45,6 +45,10 @@ #include "nouveau.h" #include "private.h" +#include "nvif/class.h" +#include "nvif/cl0080.h" +#include "nvif/unpack.h" + #ifdef DEBUG drm_private uint32_t nouveau_debug = 0; @@ -231,75 +235,107 @@ nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd, } int -nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) +nouveau_device_new(struct nouveau_object *parent, int32_t oclass, + void *data, uint32_t size, struct nouveau_device **pdev) { - struct nouveau_drm *drm; + union { + struct nv_device_v0 v0; + } *args = data; + struct nouveau_drm *drm = nouveau_drm(parent); struct nouveau_device_priv *nvdev; struct nouveau_device *dev; - uint64_t chipset, vram, gart, bousage; - int ret; + uint64_t v; char *tmp; + int ret = -ENOSYS; + + if (oclass != NV_DEVICE || + nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)) + return ret; if (!(nvdev = calloc(1, sizeof(*nvdev)))) return -ENOMEM; - dev = &nvdev->base; + dev = *pdev = &nvdev->base; + dev->fd = -1; - ret = pthread_mutex_init(&nvdev->lock, NULL); - if (ret) { - free(nvdev); - return ret; - } - - ret = nouveau_drm_new(fd, &drm); - if (ret) { - nouveau_device_del(&dev); - return ret; - } - drm->nvif = false; + if (args->v0.device == ~0ULL) { + nvdev->base.object.parent = &drm->client; + nvdev->base.object.handle = ~0ULL; + nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; + nvdev->base.object.length = ~0; - nvdev->base.object.parent = &drm->client; - nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; - nvdev->base.object.length = ~0; - nvdev->base.fd = drm->fd; - nvdev->base.drm_version = drm->drm_version; - nvdev->base.lib_version = drm->lib_version; + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &v); + if (ret) + goto done; + nvdev->base.chipset = v; - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset); - if (ret == 0) - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram); - if (ret == 0) - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart); - if (ret) { - nouveau_device_del(&dev); - return ret; - } + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &v); + if (ret == 0) + nvdev->have_bo_usage = (v != 0); + } else + return -ENOSYS; - ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage); - if (ret == 0) - nvdev->have_bo_usage = (bousage != 0); + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &v); + if (ret) + goto done; + nvdev->base.vram_size = v; - nvdev->close = close; + ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &v); + if (ret) + goto done; + nvdev->base.gart_size = v; tmp = getenv("NOUVEAU_LIBDRM_VRAM_LIMIT_PERCENT"); if (tmp) nvdev->vram_limit_percent = atoi(tmp); else nvdev->vram_limit_percent = 80; + + nvdev->base.vram_limit = + (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100; + tmp = getenv("NOUVEAU_LIBDRM_GART_LIMIT_PERCENT"); if (tmp) nvdev->gart_limit_percent = atoi(tmp); else nvdev->gart_limit_percent = 80; - DRMINITLISTHEAD(&nvdev->bo_list); - nvdev->base.chipset = chipset; - nvdev->base.vram_size = vram; - nvdev->base.gart_size = gart; - nvdev->base.vram_limit = - (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100; + nvdev->base.gart_limit = (nvdev->base.gart_size * nvdev->gart_limit_percent) / 100; - *pdev = &nvdev->base; + ret = pthread_mutex_init(&nvdev->lock, NULL); + DRMINITLISTHEAD(&nvdev->bo_list); +done: + if (ret) + nouveau_device_del(pdev); + return ret; +} + +int +nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) +{ + struct nouveau_drm *drm; + struct nouveau_device_priv *nvdev; + int ret; + + ret = nouveau_drm_new(fd, &drm); + if (ret) + return ret; + drm->nvif = false; + + ret = nouveau_device_new(&drm->client, NV_DEVICE, + &(struct nv_device_v0) { + .device = ~0ULL, + }, sizeof(struct nv_device_v0), pdev); + if (ret) { + nouveau_drm_del(&drm); + return ret; + } + + nvdev = nouveau_device(*pdev); + nvdev->base.fd = drm->fd; + nvdev->base.drm_version = drm->drm_version; + nvdev->base.lib_version = drm->lib_version; + nvdev->close = close; return 0; } @@ -320,12 +356,15 @@ nouveau_device_del(struct nouveau_device **pdev) { struct nouveau_device_priv *nvdev = nouveau_device(*pdev); if (nvdev) { - struct nouveau_drm *drm = nouveau_drm(&nvdev->base.object); free(nvdev->client); - nouveau_drm_del(&drm); pthread_mutex_destroy(&nvdev->lock); - if (nvdev->close) - drmClose(nvdev->base.fd); + if (nvdev->base.fd >= 0) { + struct nouveau_drm *drm = + nouveau_drm(&nvdev->base.object); + nouveau_drm_del(&drm); + if (nvdev->close) + drmClose(nvdev->base.fd); + } free(nvdev); *pdev = NULL; } diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h index a693acf..f3cf8f5 100644 --- a/nouveau/nouveau.h +++ b/nouveau/nouveau.h @@ -122,6 +122,8 @@ struct nouveau_device { uint64_t gart_limit; }; +int nouveau_device_new(struct nouveau_object *parent, int32_t oclass, + void *data, uint32_t size, struct nouveau_device **); int nouveau_device_wrap(int fd, int close, struct nouveau_device **); int nouveau_device_open(const char *busid, struct nouveau_device **); void nouveau_device_del(struct nouveau_device **); -- 2.6.4 _______________________________________________ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau