Back to index

libdrm  2.4.37
Functions
nouveau.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86atomic.h>
#include "libdrm_lists.h"
#include "nouveau_drm.h"
#include "nouveau.h"
#include "private.h"

Go to the source code of this file.

Functions

int nouveau_device_open_existing (struct nouveau_device **pdev, int close, int fd, drm_context_t ctx)
int nouveau_device_wrap (int fd, int close, struct nouveau_device **pdev)
int nouveau_device_open (const char *busid, struct nouveau_device **pdev)
void nouveau_device_del (struct nouveau_device **pdev)
int nouveau_getparam (struct nouveau_device *dev, uint64_t param, uint64_t *value)
int nouveau_setparam (struct nouveau_device *dev, uint64_t param, uint64_t value)
int nouveau_client_new (struct nouveau_device *dev, struct nouveau_client **pclient)
void nouveau_client_del (struct nouveau_client **pclient)
int nouveau_object_new (struct nouveau_object *parent, uint64_t handle, uint32_t oclass, void *data, uint32_t length, struct nouveau_object **pobj)
void nouveau_object_del (struct nouveau_object **pobj)
void * nouveau_object_find (struct nouveau_object *obj, uint32_t pclass)
static void nouveau_bo_del (struct nouveau_bo *bo)
int nouveau_bo_new (struct nouveau_device *dev, uint32_t flags, uint32_t align, uint64_t size, union nouveau_bo_config *config, struct nouveau_bo **pbo)
int nouveau_bo_wrap (struct nouveau_device *dev, uint32_t handle, struct nouveau_bo **pbo)
int nouveau_bo_name_ref (struct nouveau_device *dev, uint32_t name, struct nouveau_bo **pbo)
int nouveau_bo_name_get (struct nouveau_bo *bo, uint32_t *name)
void nouveau_bo_ref (struct nouveau_bo *bo, struct nouveau_bo **pref)
int nouveau_bo_wait (struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client)
int nouveau_bo_map (struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client)

Function Documentation

static void nouveau_bo_del ( struct nouveau_bo bo) [static]

Definition at line 314 of file nouveau.c.

{
       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
       struct drm_gem_close req = { bo->handle };
       DRMLISTDEL(&nvbo->head);
       if (bo->map)
              munmap(bo->map, bo->size);
       drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
       free(nvbo);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nouveau_bo_map ( struct nouveau_bo bo,
uint32_t  access,
struct nouveau_client client 
)

Definition at line 479 of file nouveau.c.

{
       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
       if (bo->map == NULL) {
              bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
                            MAP_SHARED, bo->device->fd, nvbo->map_handle);
              if (bo->map == MAP_FAILED) {
                     bo->map = NULL;
                     return -errno;
              }
       }
       return nouveau_bo_wait(bo, access, client);
}

Here is the call graph for this function:

int nouveau_bo_name_get ( struct nouveau_bo bo,
uint32_t *  name 
)

Definition at line 416 of file nouveau.c.

{
       struct drm_gem_flink req = { .handle = bo->handle };
       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
       if (!nvbo->name) {
              int ret = drmIoctl(bo->device->fd, DRM_IOCTL_GEM_FLINK, &req);
              if (ret)
                     return ret;
              nvbo->name = req.name;
       }
       *name = nvbo->name;
       return 0;
}

Here is the call graph for this function:

int nouveau_bo_name_ref ( struct nouveau_device dev,
uint32_t  name,
struct nouveau_bo **  pbo 
)

Definition at line 390 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = nouveau_device(dev);
       struct nouveau_bo_priv *nvbo;
       struct drm_gem_open req = { .name = name };
       int ret;

       DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
              if (nvbo->name == name) {
                     *pbo = NULL;
                     nouveau_bo_ref(&nvbo->base, pbo);
                     return 0;
              }
       }

       ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
       if (ret == 0) {
              ret = nouveau_bo_wrap(dev, req.handle, pbo);
              nouveau_bo((*pbo))->name = name;
       }

       return ret;
}

Here is the call graph for this function:

int nouveau_bo_new ( struct nouveau_device dev,
uint32_t  flags,
uint32_t  align,
uint64_t  size,
union nouveau_bo_config config,
struct nouveau_bo **  pbo 
)

Definition at line 326 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = nouveau_device(dev);
       struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
       struct nouveau_bo *bo = &nvbo->base;
       int ret;

       if (!nvbo)
              return -ENOMEM;
       atomic_set(&nvbo->refcnt, 1);
       bo->device = dev;
       bo->flags = flags;
       bo->size = size;

       ret = abi16_bo_init(bo, align, config);
       if (ret) {
              free(nvbo);
              return ret;
       }

       DRMLISTADD(&nvbo->head, &nvdev->bo_list);

       *pbo = bo;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nouveau_bo_ref ( struct nouveau_bo bo,
struct nouveau_bo **  pref 
)

Definition at line 431 of file nouveau.c.

{
       struct nouveau_bo *ref = *pref;
       if (bo) {
              atomic_inc(&nouveau_bo(bo)->refcnt);
       }
       if (ref) {
              if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt))
                     nouveau_bo_del(ref);
       }
       *pref = bo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nouveau_bo_wait ( struct nouveau_bo bo,
uint32_t  access,
struct nouveau_client client 
)

Definition at line 445 of file nouveau.c.

{
       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
       struct drm_nouveau_gem_cpu_prep req;
       struct nouveau_pushbuf *push;
       int ret = 0;

       if (!(access & NOUVEAU_BO_RDWR))
              return 0;

       push = cli_push_get(client, bo);
       if (push && push->channel)
              nouveau_pushbuf_kick(push, push->channel);

       if (!nvbo->name && !(nvbo->access & NOUVEAU_BO_WR) &&
                        !(      access & NOUVEAU_BO_WR))
              return 0;

       req.handle = bo->handle;
       req.flags = 0;
       if (access & NOUVEAU_BO_WR)
              req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
       if (access & NOUVEAU_BO_NOBLOCK)
              req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;

       ret = drmCommandWrite(bo->device->fd, DRM_NOUVEAU_GEM_CPU_PREP,
                           &req, sizeof(req));
       if (ret == 0)
              nvbo->access = 0;
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nouveau_bo_wrap ( struct nouveau_device dev,
uint32_t  handle,
struct nouveau_bo **  pbo 
)

Definition at line 355 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = nouveau_device(dev);
       struct drm_nouveau_gem_info req = { .handle = handle };
       struct nouveau_bo_priv *nvbo;
       int ret;

       DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
              if (nvbo->base.handle == handle) {
                     *pbo = NULL;
                     nouveau_bo_ref(&nvbo->base, pbo);
                     return 0;
              }
       }

       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO,
                              &req, sizeof(req));
       if (ret)
              return ret;

       nvbo = calloc(1, sizeof(*nvbo));
       if (nvbo) {
              atomic_set(&nvbo->refcnt, 1);
              nvbo->base.device = dev;
              abi16_bo_info(&nvbo->base, &req);
              DRMLISTADD(&nvbo->head, &nvdev->bo_list);
              *pbo = &nvbo->base;
              return 0;
       }

       return -ENOMEM;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nouveau_client_del ( struct nouveau_client **  pclient)

Definition at line 206 of file nouveau.c.

{
       struct nouveau_client_priv *pcli = nouveau_client(*pclient);
       struct nouveau_device_priv *nvdev;
       if (pcli) {
              int id = pcli->base.id;
              nvdev = nouveau_device(pcli->base.device);
              nvdev->client[id / 32] &= ~(1 << (id % 32));
              free(pcli->kref);
              free(pcli);
       }
}

Here is the call graph for this function:

int nouveau_client_new ( struct nouveau_device dev,
struct nouveau_client **  pclient 
)

Definition at line 172 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = nouveau_device(dev);
       struct nouveau_client_priv *pcli;
       int id = 0, i, ret = -ENOMEM;
       uint32_t *clients;

       for (i = 0; i < nvdev->nr_client; i++) {
              id = ffs(nvdev->client[i]) - 1;
              if (id >= 0)
                     goto out;
       }

       clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
       if (!clients)
              return ret;
       nvdev->client = clients;
       nvdev->client[i] = 0;
       nvdev->nr_client++;

out:
       pcli = calloc(1, sizeof(*pcli));
       if (pcli) {
              nvdev->client[i] |= (1 << id);
              pcli->base.device = dev;
              pcli->base.id = (i * 32) + id;
              ret = 0;
       }

       *pclient = &pcli->base;
       return ret;
}

Here is the call graph for this function:

void nouveau_device_del ( struct nouveau_device **  pdev)

Definition at line 142 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
       if (nvdev) {
              if (nvdev->close)
                     drmClose(nvdev->base.fd);
              free(nvdev->client);
              free(nvdev);
              *pdev = NULL;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nouveau_device_open ( const char *  busid,
struct nouveau_device **  pdev 
)

Definition at line 130 of file nouveau.c.

{
       int ret = -ENODEV, fd = drmOpen("nouveau", busid);
       if (fd >= 0) {
              ret = nouveau_device_wrap(fd, 1, pdev);
              if (ret)
                     drmClose(fd);
       }
       return ret;
}

Here is the call graph for this function:

int nouveau_device_open_existing ( struct nouveau_device **  pdev,
int  close,
int  fd,
drm_context_t  ctx 
)

Definition at line 65 of file nouveau.c.

{
       return -EACCES;
}
int nouveau_device_wrap ( int  fd,
int  close,
struct nouveau_device **  pdev 
)

Definition at line 72 of file nouveau.c.

{
       struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev));
       struct nouveau_device *dev = &nvdev->base;
       uint64_t chipset, vram, gart, bousage;
       drmVersionPtr ver;
       int ret;

#ifdef DEBUG
       debug_init(getenv("NOUVEAU_LIBDRM_DEBUG"));
#endif

       if (!nvdev)
              return -ENOMEM;
       nvdev->base.fd = fd;

       ver = drmGetVersion(fd);
       if (ver) dev->drm_version = (ver->version_major << 24) |
                                (ver->version_minor << 8) |
                                 ver->version_patchlevel;
       drmFreeVersion(ver);

       if ( dev->drm_version != 0x00000010 &&
           (dev->drm_version <  0x01000000 ||
            dev->drm_version >= 0x02000000)) {
              nouveau_device_del(&dev);
              return -EINVAL;
       }

       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, &bousage);
       if (ret == 0)
              nvdev->have_bo_usage = (bousage != 0);

       nvdev->close = close;
       DRMINITLISTHEAD(&nvdev->bo_list);
       nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
       nvdev->base.lib_version = 0x01000000;
       nvdev->base.chipset = chipset;
       nvdev->base.vram_size = vram;
       nvdev->base.gart_size = gart;
       nvdev->base.vram_limit = (nvdev->base.vram_size * 80) / 100;
       nvdev->base.gart_limit = (nvdev->base.gart_size * 80) / 100;

       *pdev = &nvdev->base;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nouveau_getparam ( struct nouveau_device dev,
uint64_t  param,
uint64_t *  value 
)

Definition at line 155 of file nouveau.c.

{
       struct drm_nouveau_getparam r = { param, 0 };
       int fd = dev->fd, ret =
              drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r));
       *value = r.value;
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nouveau_object_del ( struct nouveau_object **  pobj)

Definition at line 279 of file nouveau.c.

{
       struct nouveau_object *obj = *pobj;
       struct nouveau_device *dev;
       if (obj) {
              dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
              if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
                     struct drm_nouveau_channel_free req;
                     req.channel = obj->handle;
                     drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE,
                                   &req, sizeof(req));
              } else {
                     struct drm_nouveau_gpuobj_free req;
                     req.channel = obj->parent->handle;
                     req.handle  = obj->handle;
                     drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
                                   &req, sizeof(req));
              }
       }
       free(obj);
       *pobj = NULL;
}

Here is the call graph for this function:

void* nouveau_object_find ( struct nouveau_object obj,
uint32_t  pclass 
)

Definition at line 303 of file nouveau.c.

{
       while (obj && obj->oclass != pclass) {
              obj = obj->parent;
              if (pclass == NOUVEAU_PARENT_CLASS)
                     break;
       }
       return obj;
}

Here is the caller graph for this function:

int nouveau_object_new ( struct nouveau_object parent,
uint64_t  handle,
uint32_t  oclass,
void *  data,
uint32_t  length,
struct nouveau_object **  pobj 
)

Definition at line 220 of file nouveau.c.

{
       struct nouveau_device *dev;
       struct nouveau_object *obj;
       int ret = -EINVAL;

       if (length == 0)
              length = sizeof(struct nouveau_object *);
       obj = malloc(sizeof(*obj) + length);
       obj->parent = parent;
       obj->handle = handle;
       obj->oclass = oclass;
       obj->length = length;
       obj->data = obj + 1;
       if (data)
              memcpy(obj->data, data, length);
       *(struct nouveau_object **)obj->data = obj;

       dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
       switch (parent->oclass) {
       case NOUVEAU_DEVICE_CLASS:
              switch (obj->oclass) {
              case NOUVEAU_FIFO_CHANNEL_CLASS:
              {
                     if (dev->chipset < 0xc0)
                            ret = abi16_chan_nv04(obj);
                     else
                            ret = abi16_chan_nvc0(obj);
              }
                     break;
              default:
                     break;
              }
              break;
       case NOUVEAU_FIFO_CHANNEL_CLASS:
              switch (obj->oclass) {
              case NOUVEAU_NOTIFIER_CLASS:
                     ret = abi16_ntfy(obj);
                     break;
              default:
                     ret = abi16_engobj(obj);
                     break;
              }
       default:
              break;
       }

       if (ret) {
              free(obj);
              return ret;
       }

       *pobj = obj;
       return 0;
}

Here is the call graph for this function:

int nouveau_setparam ( struct nouveau_device dev,
uint64_t  param,
uint64_t  value 
)

Definition at line 165 of file nouveau.c.

{
       struct drm_nouveau_setparam r = { param, value };
       return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r));
}

Here is the call graph for this function: