/* * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. *
*/
int
nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
{ struct nouveau_cli *cli = abi16->cli;
mutex_unlock(&cli->mutex); return ret;
}
/* Tracks objects created via the DRM_NOUVEAU_NVIF ioctl. * * The only two types of object that userspace ever allocated via this * interface are 'device', in order to retrieve basic device info, and * 'engine objects', which instantiate HW classes on a channel. * * The remainder of what used to be available via DRM_NOUVEAU_NVIF has * been removed, but these object types need to be tracked to maintain * compatibility with userspace.
*/ struct nouveau_abi16_obj { enum nouveau_abi16_obj_type {
DEVICE,
ENGOBJ,
} type;
u64 object;
struct nvif_object engobj;
struct list_head head; /* protected by nouveau_abi16.cli.mutex */
};
s32
nouveau_abi16_swclass(struct nouveau_drm *drm)
{ switch (drm->client.device.info.family) { case NV_DEVICE_INFO_V0_TNT: return NVIF_CLASS_SW_NV04; case NV_DEVICE_INFO_V0_CELSIUS: case NV_DEVICE_INFO_V0_KELVIN: case NV_DEVICE_INFO_V0_RANKINE: case NV_DEVICE_INFO_V0_CURIE: return NVIF_CLASS_SW_NV10; case NV_DEVICE_INFO_V0_TESLA: return NVIF_CLASS_SW_NV50; case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: case NV_DEVICE_INFO_V0_MAXWELL: case NV_DEVICE_INFO_V0_PASCAL: case NV_DEVICE_INFO_V0_VOLTA: return NVIF_CLASS_SW_GF100;
}
if (!drm->channel) return nouveau_abi16_put(abi16, -ENODEV);
/* If uvmm wasn't initialized until now disable it completely to prevent * userspace from mixing up UAPIs. * * The client lock is already acquired by nouveau_abi16_get().
*/
__nouveau_cli_disable_uvmm_noinit(cli);
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR;
/* hack to allow channel engine type specification on kepler */ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (init->fb_ctxdma_handle == ~0) { switch (init->tt_ctxdma_handle) { case NOUVEAU_FIFO_ENGINE_GR:
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; break; case NOUVEAU_FIFO_ENGINE_VP:
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPDEC; break; case NOUVEAU_FIFO_ENGINE_PPP:
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPPP; break; case NOUVEAU_FIFO_ENGINE_BSP:
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSVLD; break; case NOUVEAU_FIFO_ENGINE_CE:
engine = NV_DEVICE_HOST_RUNLIST_ENGINES_CE; break; default: return nouveau_abi16_put(abi16, -ENOSYS);
}
/* allocate "abi16 channel" data and make up a handle for it */
chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) return nouveau_abi16_put(abi16, -ENOMEM);
/* create channel object and initialise dma and fence management */
ret = nouveau_channel_new(cli, false, runm, init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan); if (ret) goto done;
/* If we're not using the VM_BIND uAPI, we don't need a scheduler. * * The client lock is already acquired by nouveau_abi16_get().
*/ if (nouveau_cli_uvmm(cli)) {
ret = nouveau_sched_create(&chan->sched, drm, drm->sched_wq,
chan->chan->chan.gpfifo.max); if (ret) goto done;
}
/* Workaround "nvc0" gallium driver using classes it doesn't allocate on * Kepler and above. NVKM no longer always sets CE_CTX_VALID as part of * channel init, now we know what that stuff actually is. * * Doesn't matter for Kepler/Pascal, CE context stored in NV_RAMIN. * * Userspace was fixed prior to adding Ampere support.
*/ switch (device->info.family) { case NV_DEVICE_INFO_V0_VOLTA:
ret = nvif_object_ctor(&chan->chan->user, "abi16CeWar", 0, VOLTA_DMA_COPY_A,
NULL, 0, &chan->ce); if (ret) goto done; break; case NV_DEVICE_INFO_V0_TURING:
ret = nvif_object_ctor(&chan->chan->user, "abi16CeWar", 0, TURING_DMA_COPY_A,
NULL, 0, &chan->ce); if (ret) goto done; break; default: break;
}
/* Named memory object area */
ret = nouveau_gem_new(cli, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART,
0, 0, &chan->ntfy); if (ret == 0)
ret = nouveau_bo_pin(chan->ntfy, NOUVEAU_GEM_DOMAIN_GART, false); if (ret) goto done;
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
ret = nouveau_vma_new(chan->ntfy, chan->chan->vmm,
&chan->ntfy_vma); if (ret) goto done;
}
ret = drm_gem_handle_create(file_priv, &chan->ntfy->bo.base,
&init->notifier_handle); if (ret) goto done;
ret = nvkm_mm_init(&chan->heap, 0, 0, PAGE_SIZE, 1);
done: if (ret)
nouveau_abi16_chan_fini(abi16, chan); return nouveau_abi16_put(abi16, ret);
}
if (unlikely(!abi16)) return -ENOMEM;
device = &abi16->cli->device;
/* completely unnecessary for these chipsets... */ if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI)) return nouveau_abi16_put(abi16, -EINVAL);
chan = nouveau_abi16_chan(abi16, info->channel); if (!chan) return nouveau_abi16_put(abi16, -ENOENT);
ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL); if (!ntfy) return nouveau_abi16_put(abi16, -ENOMEM);
list_add(&ntfy->head, &chan->notifiers);
ret = nvkm_mm_head(&chan->heap, 0, 1, info->size, info->size, 1,
&ntfy->node); if (ret) goto done;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.