static int nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; if (nvbo->bo.mem.mem_type == TTM_PL_TT) rep->domain = NOUVEAU_GEM_DOMAIN_GART; else rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; rep->offset = nvbo->bo.offset; if (cli->base.vm) { vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (!vma) return -EINVAL; rep->offset = vma->offset; } rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; rep->map_handle = nvbo->bo.addr_space_offset; rep->tile_mode = nvbo->tile_mode; rep->tile_flags = nvbo->tile_flags; return 0; }
void nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; struct nvkm_vma *vma; int ret; if (!cli->vm) return; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL); if (ret) return; vma = nouveau_bo_vma_find(nvbo, cli->vm); if (vma) { if (--vma->refcount == 0) { ret = pm_runtime_get_sync(dev); if (!WARN_ON(ret < 0 && ret != -EACCES)) { nouveau_gem_object_unmap(nvbo, vma); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } } } ttm_bo_unreserve(&nvbo->bo); }
int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_fb *pfb = nouveau_fb(drm->device); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } ret = nouveau_gem_new(dev, req->info.size, req->align, req->info.domain, req->info.tile_mode, req->info.tile_flags, &nvbo); if (ret) return ret; ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle); if (ret == 0) { ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info); if (ret) drm_gem_handle_delete(file_priv, req->info.handle); } /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(&nvbo->gem); return ret; }
int nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; struct nouveau_vma *vma; int ret; if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50) return 0; ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); if (ret) return ret; ret = pm_runtime_get_sync(dev); if (ret < 0 && ret != -EACCES) goto out; ret = nouveau_vma_new(nvbo, &cli->vmm, &vma); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); out: ttm_bo_unreserve(&nvbo->bo); return ret; }
int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; ret = nouveau_gem_new(cli, req->info.size, req->align, req->info.domain, req->info.tile_mode, req->info.tile_flags, &nvbo); if (ret) return ret; ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle); if (ret == 0) { ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info); if (ret) drm_gem_handle_delete(file_priv, req->info.handle); } /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(&nvbo->gem); return ret; }
int nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct nvkm_vma *vma; struct device *dev = drm->dev->dev; int ret; if (!cli->vm) return 0; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL); if (ret) return ret; vma = nouveau_bo_vma_find(nvbo, cli->vm); if (!vma) { vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) { ret = -ENOMEM; goto out; } ret = pm_runtime_get_sync(dev); if (ret < 0 && ret != -EACCES) goto out; ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); if (ret) kfree(vma); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } else { vma->refcount++; } out: ttm_bo_unreserve(&nvbo->bo); return ret; }
void nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; int ret; if (!cli->base.vm) return; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); if (ret) return; vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (vma) { if (--vma->refcount == 0) nouveau_gem_object_unmap(nvbo, vma); } ttm_bo_unreserve(&nvbo->bo); }
int nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; int ret; if (!cli->base.vm) return 0; ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); if (ret) return ret; vma = nouveau_bo_vma_find(nvbo, cli->base.vm); if (!vma) { vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (!vma) { ret = -ENOMEM; goto out; } ret = nouveau_bo_vma_add(nvbo, cli->base.vm, vma); if (ret) { kfree(vma); goto out; } } else { vma->refcount++; } out: ttm_bo_unreserve(&nvbo->bo); return ret; }
static int nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_vma *vma; if (is_power_of_2(nvbo->valid_domains)) rep->domain = nvbo->valid_domains; else if (nvbo->bo.mem.mem_type == TTM_PL_TT) rep->domain = NOUVEAU_GEM_DOMAIN_GART; else rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; rep->offset = nvbo->bo.offset; if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { vma = nouveau_vma_find(nvbo, &cli->vmm); if (!vma) return -EINVAL; rep->offset = vma->addr; } rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node); rep->tile_mode = nvbo->mode; rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG; if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) rep->tile_flags |= nvbo->kind << 8; else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) rep->tile_flags |= nvbo->kind << 8 | nvbo->comp << 16; else rep->tile_flags |= nvbo->zeta; return 0; }