From daa91dfedfc0c4cfc7a0e1595de02f8f5df1ce85 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 3 Jul 2022 19:05:44 +0200 Subject: [PATCH] nouveau/ws: get rid of libdrm and just completely rework device and context creation Signed-off-by: Karol Herbst Part-of: --- src/nouveau/winsys/nouveau_bo.c | 8 +- src/nouveau/winsys/nouveau_context.c | 104 ++++++++++++---- src/nouveau/winsys/nouveau_context.h | 16 ++- src/nouveau/winsys/nouveau_device.c | 178 +++++++++++++++++++++------ src/nouveau/winsys/nouveau_device.h | 30 ++--- src/nouveau/winsys/nouveau_push.c | 16 +-- src/nouveau/winsys/nouveau_push.h | 1 - 7 files changed, 253 insertions(+), 100 deletions(-) diff --git a/src/nouveau/winsys/nouveau_bo.c b/src/nouveau/winsys/nouveau_bo.c index 6a3c46b98da..00114f2a07d 100644 --- a/src/nouveau/winsys/nouveau_bo.c +++ b/src/nouveau/winsys/nouveau_bo.c @@ -1,6 +1,5 @@ #include "nouveau_bo.h" -#include #include #include @@ -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; diff --git a/src/nouveau/winsys/nouveau_context.c b/src/nouveau/winsys/nouveau_context.c index ce31947e187..cccbb0fa60e 100644 --- a/src/nouveau/winsys/nouveau_context.c +++ b/src/nouveau/winsys/nouveau_context.c @@ -1,7 +1,10 @@ #include "nouveau_context.h" +#include #include -#include +#include +#include +#include #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); } diff --git a/src/nouveau/winsys/nouveau_context.h b/src/nouveau/winsys/nouveau_context.h index e3357724815..3cd277877ea 100644 --- a/src/nouveau/winsys/nouveau_context.h +++ b/src/nouveau/winsys/nouveau_context.h @@ -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); diff --git a/src/nouveau/winsys/nouveau_device.c b/src/nouveau/winsys/nouveau_device.c index 701e84f3195..dadf8447d6b 100644 --- a/src/nouveau/winsys/nouveau_device.c +++ b/src/nouveau/winsys/nouveau_device.c @@ -1,10 +1,11 @@ #include "nouveau_device.h" #include -#include #include +#include #include #include +#include #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); } diff --git a/src/nouveau/winsys/nouveau_device.h b/src/nouveau/winsys/nouveau_device.h index 772fd861610..0764e3e5f05 100644 --- a/src/nouveau/winsys/nouveau_device.h +++ b/src/nouveau/winsys/nouveau_device.h @@ -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 *); diff --git a/src/nouveau/winsys/nouveau_push.c b/src/nouveau/winsys/nouveau_push.c index 779ec3ddf27..85d8be0f97f 100644 --- a/src/nouveau/winsys/nouveau_push.c +++ b/src/nouveau/winsys/nouveau_push.c @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -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); diff --git a/src/nouveau/winsys/nouveau_push.h b/src/nouveau/winsys/nouveau_push.h index 6352b517143..375a5ad4041 100644 --- a/src/nouveau/winsys/nouveau_push.h +++ b/src/nouveau/winsys/nouveau_push.h @@ -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;