nouveau/ws: get rid of libdrm

and just completely rework device and context creation

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Karol Herbst 2022-07-03 19:05:44 +02:00 committed by Marge Bot
parent cafccc2305
commit daa91dfedf
7 changed files with 253 additions and 100 deletions

View file

@ -1,6 +1,5 @@
#include "nouveau_bo.h"
#include <nouveau/nouveau.h>
#include <nouveau_drm.h>
#include <xf86drm.h>
@ -10,7 +9,6 @@
struct nouveau_ws_bo *
nouveau_ws_bo_new(struct nouveau_ws_device *dev, uint64_t size, uint64_t align, enum nouveau_ws_bo_flags flags)
{
struct nouveau_ws_device_priv *pdev = nouveau_ws_device(dev);
struct nouveau_ws_bo *bo = CALLOC_STRUCT(nouveau_ws_bo);
struct drm_nouveau_gem_new req = {};
@ -22,7 +20,7 @@ nouveau_ws_bo_new(struct nouveau_ws_device *dev, uint64_t size, uint64_t align,
if (flags & NOUVEAU_WS_BO_GART)
req.info.domain |= NOUVEAU_GEM_DOMAIN_GART;
else
req.info.domain |= pdev->local_mem_domain;
req.info.domain |= dev->local_mem_domain;
if (flags & NOUVEAU_WS_BO_MAP)
req.info.domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
@ -30,7 +28,7 @@ nouveau_ws_bo_new(struct nouveau_ws_device *dev, uint64_t size, uint64_t align,
req.info.size = size;
req.align = align;
int ret = drmCommandWriteRead(pdev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req));
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req));
if (ret) {
FREE(bo);
return NULL;
@ -40,7 +38,7 @@ nouveau_ws_bo_new(struct nouveau_ws_device *dev, uint64_t size, uint64_t align,
bo->offset = req.info.offset;
bo->handle = req.info.handle;
bo->map_handle = req.info.map_handle;
bo->fd = pdev->fd;
bo->fd = dev->fd;
bo->flags = flags;
bo->refcnt = 1;

View file

@ -1,7 +1,10 @@
#include "nouveau_context.h"
#include <drm/drm.h>
#include <errno.h>
#include <nouveau/nouveau.h>
#include <nouveau_drm.h>
#include <nouveau/nvif/ioctl.h>
#include <xf86drm.h>
#include "nouveau_device.h"
@ -9,47 +12,100 @@
#include "classes/cl902d.h"
#include "classes/clc5c0.h"
static void
nouveau_ws_subchan_dealloc(int fd, struct nouveau_ws_object *obj)
{
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_del del;
} args = {
.ioctl = {
.object = (uintptr_t)obj,
.owner = NVIF_IOCTL_V0_OWNER_ANY,
.route = 0x00,
.type = NVIF_IOCTL_V0_DEL,
.version = 0,
},
};
/* TODO returns -ENOENT for unknown reasons */
drmCommandWrite(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
}
static int
nouveau_ws_subchan_alloc(int fd, int channel, uint32_t handle, uint16_t oclass, struct nouveau_ws_object *obj)
{
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_new_v0 new;
} args = {
.ioctl = {
.route = 0xff,
.token = channel,
.type = NVIF_IOCTL_V0_NEW,
.version = 0,
},
.new = {
.handle = handle,
.object = (uintptr_t)obj,
.oclass = oclass,
.route = NVIF_IOCTL_V0_ROUTE_NVIF,
.token = (uintptr_t)obj,
.version = 0,
},
};
return drmCommandWrite(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
}
static void
nouveau_ws_channel_dealloc(int fd, int channel)
{
struct drm_nouveau_channel_free req = {
.channel = channel,
};
int ret = drmCommandWrite(fd, DRM_NOUVEAU_CHANNEL_FREE, &req, sizeof(req));
assert(!ret);
}
int
nouveau_ws_context_create(struct nouveau_ws_device *dev, struct nouveau_ws_context **out)
{
struct nouveau_ws_device_priv *pdev = nouveau_ws_device(dev);
struct nvc0_fifo nvc0_data = { };
uint32_t size = sizeof(nvc0_data);
struct drm_nouveau_channel_alloc req = { };
*out = CALLOC_STRUCT(nouveau_ws_context);
if (!*out)
return -ENOMEM;
int ret = nouveau_object_new(&pdev->dev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS,
&nvc0_data, size, &(*out)->channel);
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC, &req, sizeof(req));
if (ret)
goto fail_chan;
ret = nouveau_object_new((*out)->channel, 0xbeef902d, FERMI_TWOD_A, NULL, 0,
&(*out)->eng2d);
ret = nouveau_ws_subchan_alloc(dev->fd, req.channel, 0xbeef902d, FERMI_TWOD_A, &(*out)->eng2d);
if (ret)
goto fail_2d;
uint32_t obj_class = 0xa140;//NVF0_P2MF_CLASS;
ret = nouveau_object_new((*out)->channel, 0xbeef323f, obj_class, NULL, 0,
&(*out)->m2mf);
if (ret) {
FREE(*out);
return ret;
}
ret = nouveau_ws_subchan_alloc(dev->fd, req.channel, 0xbeef323f, obj_class, &(*out)->m2mf);
if (ret)
goto fail_subchan;
obj_class = TURING_COMPUTE_A;
ret = nouveau_object_new((*out)->channel, 0xbeef00c0, obj_class, NULL, 0,
&(*out)->compute);
if (ret) {
FREE(*out);
return ret;
}
ret = nouveau_ws_subchan_alloc(dev->fd, req.channel, 0xbeef00c0, obj_class, &(*out)->compute);
if (ret)
goto fail_subchan;
(*out)->channel = req.channel;
(*out)->dev = dev;
return 0;
fail_subchan:
nouveau_ws_subchan_dealloc(dev->fd, &(*out)->compute);
nouveau_ws_subchan_dealloc(dev->fd, &(*out)->m2mf);
nouveau_ws_subchan_dealloc(dev->fd, &(*out)->eng2d);
fail_2d:
nouveau_object_del(&(*out)->channel);
nouveau_ws_channel_dealloc(dev->fd, req.channel);
fail_chan:
FREE(*out);
return ret;
@ -58,7 +114,9 @@ fail_chan:
void
nouveau_ws_context_destroy(struct nouveau_ws_context *context)
{
nouveau_object_del(&context->eng2d);
nouveau_object_del(&context->channel);
nouveau_ws_subchan_dealloc(context->dev->fd, &context->compute);
nouveau_ws_subchan_dealloc(context->dev->fd, &context->m2mf);
nouveau_ws_subchan_dealloc(context->dev->fd, &context->eng2d);
nouveau_ws_channel_dealloc(context->dev->fd, context->channel);
FREE(context);
}

View file

@ -5,12 +5,18 @@
struct nouveau_ws_device;
struct nouveau_ws_context {
struct nouveau_object *channel;
struct nouveau_ws_object {
uint8_t __pad;
};
struct nouveau_object *eng2d;
struct nouveau_object *m2mf;
struct nouveau_object *compute;
struct nouveau_ws_context {
struct nouveau_ws_device *dev;
int channel;
struct nouveau_ws_object eng2d;
struct nouveau_ws_object m2mf;
struct nouveau_ws_object compute;
};
int nouveau_ws_context_create(struct nouveau_ws_device *, struct nouveau_ws_context **out);

View file

@ -1,10 +1,11 @@
#include "nouveau_device.h"
#include <drm/drm.h>
#include <nouveau/nouveau.h>
#include <nouveau_drm.h>
#include <nouveau/nvif/ioctl.h>
#include <nvif/cl0080.h>
#include <nvif/class.h>
#include <xf86drm.h>
#include "util/u_debug.h"
#include "util/os_file.h"
@ -125,63 +126,161 @@ nouveau_ws_device_set_dbg_flags(struct nouveau_ws_device *dev)
dev->debug_flags = parse_debug_string(getenv("NVK_DEBUG"), flags);
}
static int
nouveau_ws_param(int fd, uint64_t param, uint64_t *value)
{
struct drm_nouveau_getparam data = { .param = param };
int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &data, sizeof(data));
if (ret)
return ret;
*value = data.value;
return 0;
}
static int
nouveau_ws_device_alloc(int fd, struct nouveau_ws_device *dev)
{
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_new_v0 new;
struct nv_device_v0 dev;
} args = {
.ioctl = {
.object = 0,
.owner = NVIF_IOCTL_V0_OWNER_ANY,
.route = 0x00,
.type = NVIF_IOCTL_V0_NEW,
.version = 0,
},
.new = {
.handle = 0,
.object = (uintptr_t)dev,
.oclass = NV_DEVICE,
.route = NVIF_IOCTL_V0_ROUTE_NVIF,
.token = (uintptr_t)dev,
.version = 0,
},
.dev = {
.device = ~0ULL,
},
};
return drmCommandWrite(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
}
static int
nouveau_ws_device_info(int fd, struct nouveau_ws_device *dev)
{
struct {
struct nvif_ioctl_v0 ioctl;
struct nvif_ioctl_mthd_v0 mthd;
struct nv_device_info_v0 info;
} args = {
.ioctl = {
.object = (uintptr_t)dev,
.owner = NVIF_IOCTL_V0_OWNER_ANY,
.route = 0x00,
.type = NVIF_IOCTL_V0_MTHD,
.version = 0,
},
.mthd = {
.method = NV_DEVICE_V0_INFO,
.version = 0,
},
.info = {
.version = 0,
},
};
int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
if (ret)
return ret;
dev->chipset = args.info.chipset;
dev->vram_size = args.info.ram_user;
switch (args.info.platform) {
case NV_DEVICE_INFO_V0_IGP:
dev->device_type = NOUVEAU_WS_DEVICE_TYPE_IGP;
break;
case NV_DEVICE_INFO_V0_SOC:
dev->device_type = NOUVEAU_WS_DEVICE_TYPE_SOC;
break;
case NV_DEVICE_INFO_V0_PCI:
case NV_DEVICE_INFO_V0_AGP:
case NV_DEVICE_INFO_V0_PCIE:
default:
dev->device_type = NOUVEAU_WS_DEVICE_TYPE_DIS;
break;
}
dev->chipset_name = strndup(args.info.chip, sizeof(args.info.chip));
dev->device_name = strndup(args.info.name, sizeof(args.info.name));
return 0;
}
struct nouveau_ws_device *
nouveau_ws_device_new(int fd)
{
struct nouveau_ws_device_priv *device = CALLOC_STRUCT(nouveau_ws_device_priv);
uint64_t device_id = 0;
struct nouveau_drm *drm;
struct nouveau_device *dev;
struct nouveau_ws_device *device = CALLOC_STRUCT(nouveau_ws_device);
uint64_t value = 0;
int dup_fd = os_dupfd_cloexec(fd);
drmVersionPtr ver;
if (nouveau_drm_new(dup_fd, &drm)) {
ver = drmGetVersion(dup_fd);
if (!ver)
return NULL;
}
struct nv_device_v0 v0 = {
.device = ~0ULL,
};
uint32_t version =
ver->version_major << 24 |
ver->version_minor << 8 |
ver->version_patchlevel;
drmFreeVersion(ver);
if (nouveau_device_new(&drm->client, NV_DEVICE, &v0, sizeof(v0), &dev)) {
if (version < 0x01000301)
goto out_drm;
}
if (nouveau_getparam(dev, NOUVEAU_GETPARAM_PCI_DEVICE, &device_id)) {
if (nouveau_ws_device_alloc(dup_fd, device))
goto out_drm;
if (nouveau_ws_device_info(dup_fd, device))
goto out_drm;
if (nouveau_ws_param(dup_fd, NOUVEAU_GETPARAM_PCI_DEVICE, &value))
goto out_dev;
}
device->device_id = value;
if (nouveau_ws_param(dup_fd, NOUVEAU_GETPARAM_AGP_SIZE, &value))
goto out_dev;
os_get_available_system_memory(&device->gart_size);
device->gart_size = MIN2(device->gart_size, value);
device->base.vendor_id = 0x10de;
device->base.device_id = device_id;
device->base.chipset = dev->chipset;
device->base.cls = cls_for_chipset(dev->chipset);
device->base.cm = sm_for_cls(device->base.cls, dev->chipset);
device->base.vram_size = dev->vram_size;
os_get_available_system_memory(&device->base.gart_size);
device->base.gart_size = MIN2(device->base.gart_size, dev->gart_size);
device->base.is_integrated = dev->vram_size == 0;
device->drm = drm;
device->dev = dev;
device->fd = dup_fd;
device->vendor_id = 0x10de;
device->cls = cls_for_chipset(device->chipset);
device->cm = sm_for_cls(device->cls, device->chipset);
device->is_integrated = device->vram_size == 0;
if (dev->vram_size == 0)
if (device->vram_size == 0)
device->local_mem_domain = NOUVEAU_GEM_DOMAIN_GART;
else
device->local_mem_domain = NOUVEAU_GEM_DOMAIN_VRAM;
uint64_t value;
if (nouveau_getparam(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value))
if (nouveau_ws_param(dup_fd, NOUVEAU_GETPARAM_GRAPH_UNITS, &value))
goto out_dev;
device->base.gpc_count = value & 0x000000ff;
device->base.mp_count = value >> 8;
device->gpc_count = value & 0x000000ff;
device->mp_count = value >> 8;
nouveau_ws_device_set_dbg_flags(&device->base);
nouveau_ws_device_set_dbg_flags(device);
return &device->base;
return device;
out_dev:
nouveau_device_del(&dev);
FREE(device);
out_drm:
nouveau_drm_del(&drm);
close(dup_fd);
return NULL;
}
@ -192,11 +291,8 @@ nouveau_ws_device_destroy(struct nouveau_ws_device *device)
if (!device)
return;
struct nouveau_ws_device_priv *priv = nouveau_ws_device(device);
nouveau_device_del(&priv->dev);
nouveau_drm_del(&priv->drm);
close(priv->fd);
FREE(priv);
close(device->fd);
FREE(device->chipset_name);
FREE(device->device_name);
FREE(device);
}

View file

@ -17,17 +17,32 @@ enum nvk_debug {
NVK_DEBUG_PUSH_SYNC = 1ull << 1,
};
enum nouveau_ws_device_type {
NOUVEAU_WS_DEVICE_TYPE_IGP = 0,
NOUVEAU_WS_DEVICE_TYPE_DIS = 1,
NOUVEAU_WS_DEVICE_TYPE_SOC = 2,
};
struct nouveau_ws_device {
int fd;
uint16_t vendor_id;
uint16_t device_id;
enum nouveau_ws_device_type device_type;
uint32_t chipset;
char *chipset_name;
char *device_name;
/* first byte of class id */
uint8_t cls;
/* maps to CUDAs Compute capability version */
uint8_t cm;
uint64_t vram_size;
uint64_t gart_size;
bool is_integrated;
uint32_t local_mem_domain;
uint8_t gpc_count;
uint16_t mp_count;
@ -35,21 +50,6 @@ struct nouveau_ws_device {
enum nvk_debug debug_flags;
};
/* don't use directly, gets removed once the new UAPI is here */
struct nouveau_ws_device_priv {
struct nouveau_ws_device base;
struct nouveau_drm *drm;
struct nouveau_device *dev;
int fd;
uint32_t local_mem_domain;
};
static struct nouveau_ws_device_priv *
nouveau_ws_device(struct nouveau_ws_device *dev)
{
return container_of(dev, struct nouveau_ws_device_priv, base);
}
struct nouveau_ws_device *nouveau_ws_device_new(int fd);
void nouveau_ws_device_destroy(struct nouveau_ws_device *);

View file

@ -2,7 +2,6 @@
#include <errno.h>
#include <nouveau_drm.h>
#include <nouveau/nouveau.h>
#include <sys/mman.h>
#include <xf86drm.h>
@ -216,9 +215,6 @@ nouveau_ws_push_submit(
struct nouveau_ws_device *dev,
struct nouveau_ws_context *ctx
) {
struct nouveau_ws_device_priv *pdev = nouveau_ws_device(dev);
struct nouveau_fifo *fifo = ctx->channel->data;
struct drm_nouveau_gem_pushbuf_bo req_bo[NOUVEAU_GEM_MAX_BUFFERS] = {};
struct drm_nouveau_gem_pushbuf req = {};
struct drm_nouveau_gem_pushbuf_push req_push = {};
@ -241,8 +237,8 @@ nouveau_ws_push_submit(
req_bo[i].valid_domains |= NOUVEAU_GEM_DOMAIN_GART;
req_bo[i].read_domains |= NOUVEAU_GEM_DOMAIN_GART;
} else {
req_bo[i].valid_domains |= pdev->local_mem_domain;
req_bo[i].read_domains |= pdev->local_mem_domain;
req_bo[i].valid_domains |= dev->local_mem_domain;
req_bo[i].read_domains |= dev->local_mem_domain;
}
}
@ -251,8 +247,8 @@ nouveau_ws_push_submit(
req_bo[i].valid_domains |= NOUVEAU_GEM_DOMAIN_GART;
req_bo[i].write_domains |= NOUVEAU_GEM_DOMAIN_GART;
} else {
req_bo[i].valid_domains |= pdev->local_mem_domain;
req_bo[i].write_domains |= pdev->local_mem_domain;
req_bo[i].valid_domains |= dev->local_mem_domain;
req_bo[i].write_domains |= dev->local_mem_domain;
}
}
@ -263,7 +259,7 @@ nouveau_ws_push_submit(
req_push.offset = 0;
req_push.length = (push->map - push->orig_map) * 4;
req.channel = fifo->channel;
req.channel = ctx->channel;
req.nr_buffers = i;
req.buffers = (uintptr_t)&req_bo;
req.nr_push = 1;
@ -272,7 +268,7 @@ nouveau_ws_push_submit(
if (dev->debug_flags & NVK_DEBUG_PUSH_SYNC)
req.vram_available |= NOUVEAU_GEM_PUSHBUF_SYNC;
int ret = drmCommandWriteRead(pdev->fd, DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
if ((ret && (dev->debug_flags & NVK_DEBUG_PUSH_SYNC)) || dev->debug_flags & NVK_DEBUG_PUSH_DUMP) {
printf("DRM_NOUVEAU_GEM_PUSHBUF returned %i, dumping pushbuffer\n", ret);

View file

@ -4,7 +4,6 @@
#include "nouveau_private.h"
#include "nouveau_bo.h"
#include "nouveau_drm.h"
#include "util/u_dynarray.h"
struct nouveau_ws_context;