[Nouveau] [libdrm v2 11/14] nouveau: add new interface to create a nouveau_device

Ben Skeggs skeggsb at gmail.com
Thu Nov 26 17:02:50 PST 2015


From: Ben Skeggs <bskeggs at redhat.com>

Signed-off-by: Ben Skeggs <bskeggs at 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.3



More information about the Nouveau mailing list