1*926deccbSFrançois Tigeot /* 2*926deccbSFrançois Tigeot * Copyright 2008 Advanced Micro Devices, Inc. 3*926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc. 4*926deccbSFrançois Tigeot * Copyright 2009 Jerome Glisse. 5*926deccbSFrançois Tigeot * 6*926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 7*926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 8*926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation 9*926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10*926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 11*926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 12*926deccbSFrançois Tigeot * 13*926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in 14*926deccbSFrançois Tigeot * all copies or substantial portions of the Software. 15*926deccbSFrançois Tigeot * 16*926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20*926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21*926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22*926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE. 23*926deccbSFrançois Tigeot * 24*926deccbSFrançois Tigeot * Authors: Dave Airlie 25*926deccbSFrançois Tigeot * Alex Deucher 26*926deccbSFrançois Tigeot * Jerome Glisse 27*926deccbSFrançois Tigeot * 28*926deccbSFrançois Tigeot * $FreeBSD: head/sys/dev/drm2/radeon/radeon_gem.c 254885 2013-08-25 19:37:15Z dumbbell $ 29*926deccbSFrançois Tigeot */ 30*926deccbSFrançois Tigeot 31*926deccbSFrançois Tigeot #include <drm/drmP.h> 32*926deccbSFrançois Tigeot #include <uapi_drm/radeon_drm.h> 33*926deccbSFrançois Tigeot #include "radeon.h" 34*926deccbSFrançois Tigeot #include "radeon_gem.h" 35*926deccbSFrançois Tigeot 36*926deccbSFrançois Tigeot int radeon_gem_object_init(struct drm_gem_object *obj) 37*926deccbSFrançois Tigeot { 38*926deccbSFrançois Tigeot panic("radeon_gem_object_init() must not be called"); 39*926deccbSFrançois Tigeot 40*926deccbSFrançois Tigeot return 0; 41*926deccbSFrançois Tigeot } 42*926deccbSFrançois Tigeot 43*926deccbSFrançois Tigeot void radeon_gem_object_free(struct drm_gem_object *gobj) 44*926deccbSFrançois Tigeot { 45*926deccbSFrançois Tigeot struct radeon_bo *robj = gem_to_radeon_bo(gobj); 46*926deccbSFrançois Tigeot 47*926deccbSFrançois Tigeot if (robj) { 48*926deccbSFrançois Tigeot #ifdef DUMBBELL_WIP 49*926deccbSFrançois Tigeot if (robj->gem_base.import_attach) 50*926deccbSFrançois Tigeot drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); 51*926deccbSFrançois Tigeot #endif /* DUMBBELL_WIP */ 52*926deccbSFrançois Tigeot radeon_bo_unref(&robj); 53*926deccbSFrançois Tigeot } 54*926deccbSFrançois Tigeot } 55*926deccbSFrançois Tigeot 56*926deccbSFrançois Tigeot int radeon_gem_object_create(struct radeon_device *rdev, int size, 57*926deccbSFrançois Tigeot int alignment, int initial_domain, 58*926deccbSFrançois Tigeot bool discardable, bool kernel, 59*926deccbSFrançois Tigeot struct drm_gem_object **obj) 60*926deccbSFrançois Tigeot { 61*926deccbSFrançois Tigeot struct radeon_bo *robj; 62*926deccbSFrançois Tigeot unsigned long max_size; 63*926deccbSFrançois Tigeot int r; 64*926deccbSFrançois Tigeot 65*926deccbSFrançois Tigeot *obj = NULL; 66*926deccbSFrançois Tigeot /* At least align on page size */ 67*926deccbSFrançois Tigeot if (alignment < PAGE_SIZE) { 68*926deccbSFrançois Tigeot alignment = PAGE_SIZE; 69*926deccbSFrançois Tigeot } 70*926deccbSFrançois Tigeot 71*926deccbSFrançois Tigeot /* maximun bo size is the minimun btw visible vram and gtt size */ 72*926deccbSFrançois Tigeot max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); 73*926deccbSFrançois Tigeot if (size > max_size) { 74*926deccbSFrançois Tigeot DRM_ERROR("%s:%d alloc size %dMb bigger than %ldMb limit\n", 75*926deccbSFrançois Tigeot __func__, __LINE__, size >> 20, max_size >> 20); 76*926deccbSFrançois Tigeot return -ENOMEM; 77*926deccbSFrançois Tigeot } 78*926deccbSFrançois Tigeot 79*926deccbSFrançois Tigeot retry: 80*926deccbSFrançois Tigeot r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); 81*926deccbSFrançois Tigeot if (r) { 82*926deccbSFrançois Tigeot if (r != -ERESTART) { 83*926deccbSFrançois Tigeot if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { 84*926deccbSFrançois Tigeot initial_domain |= RADEON_GEM_DOMAIN_GTT; 85*926deccbSFrançois Tigeot goto retry; 86*926deccbSFrançois Tigeot } 87*926deccbSFrançois Tigeot DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", 88*926deccbSFrançois Tigeot size, initial_domain, alignment, r); 89*926deccbSFrançois Tigeot } 90*926deccbSFrançois Tigeot return r; 91*926deccbSFrançois Tigeot } 92*926deccbSFrançois Tigeot *obj = &robj->gem_base; 93*926deccbSFrançois Tigeot 94*926deccbSFrançois Tigeot spin_lock(&rdev->gem.mutex); 95*926deccbSFrançois Tigeot list_add_tail(&robj->list, &rdev->gem.objects); 96*926deccbSFrançois Tigeot spin_unlock(&rdev->gem.mutex); 97*926deccbSFrançois Tigeot 98*926deccbSFrançois Tigeot return 0; 99*926deccbSFrançois Tigeot } 100*926deccbSFrançois Tigeot 101*926deccbSFrançois Tigeot static int radeon_gem_set_domain(struct drm_gem_object *gobj, 102*926deccbSFrançois Tigeot uint32_t rdomain, uint32_t wdomain) 103*926deccbSFrançois Tigeot { 104*926deccbSFrançois Tigeot struct radeon_bo *robj; 105*926deccbSFrançois Tigeot uint32_t domain; 106*926deccbSFrançois Tigeot int r; 107*926deccbSFrançois Tigeot 108*926deccbSFrançois Tigeot /* FIXME: reeimplement */ 109*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 110*926deccbSFrançois Tigeot /* work out where to validate the buffer to */ 111*926deccbSFrançois Tigeot domain = wdomain; 112*926deccbSFrançois Tigeot if (!domain) { 113*926deccbSFrançois Tigeot domain = rdomain; 114*926deccbSFrançois Tigeot } 115*926deccbSFrançois Tigeot if (!domain) { 116*926deccbSFrançois Tigeot /* Do nothings */ 117*926deccbSFrançois Tigeot DRM_ERROR("Set domain without domain !\n"); 118*926deccbSFrançois Tigeot return 0; 119*926deccbSFrançois Tigeot } 120*926deccbSFrançois Tigeot if (domain == RADEON_GEM_DOMAIN_CPU) { 121*926deccbSFrançois Tigeot /* Asking for cpu access wait for object idle */ 122*926deccbSFrançois Tigeot r = radeon_bo_wait(robj, NULL, false); 123*926deccbSFrançois Tigeot if (r) { 124*926deccbSFrançois Tigeot DRM_ERROR("Failed to wait for object !\n"); 125*926deccbSFrançois Tigeot return r; 126*926deccbSFrançois Tigeot } 127*926deccbSFrançois Tigeot } 128*926deccbSFrançois Tigeot return 0; 129*926deccbSFrançois Tigeot } 130*926deccbSFrançois Tigeot 131*926deccbSFrançois Tigeot int radeon_gem_init(struct radeon_device *rdev) 132*926deccbSFrançois Tigeot { 133*926deccbSFrançois Tigeot INIT_LIST_HEAD(&rdev->gem.objects); 134*926deccbSFrançois Tigeot return 0; 135*926deccbSFrançois Tigeot } 136*926deccbSFrançois Tigeot 137*926deccbSFrançois Tigeot void radeon_gem_fini(struct radeon_device *rdev) 138*926deccbSFrançois Tigeot { 139*926deccbSFrançois Tigeot radeon_bo_force_delete(rdev); 140*926deccbSFrançois Tigeot } 141*926deccbSFrançois Tigeot 142*926deccbSFrançois Tigeot /* 143*926deccbSFrançois Tigeot * Call from drm_gem_handle_create which appear in both new and open ioctl 144*926deccbSFrançois Tigeot * case. 145*926deccbSFrançois Tigeot */ 146*926deccbSFrançois Tigeot int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) 147*926deccbSFrançois Tigeot { 148*926deccbSFrançois Tigeot struct radeon_bo *rbo = gem_to_radeon_bo(obj); 149*926deccbSFrançois Tigeot struct radeon_device *rdev = rbo->rdev; 150*926deccbSFrançois Tigeot struct radeon_fpriv *fpriv = file_priv->driver_priv; 151*926deccbSFrançois Tigeot struct radeon_vm *vm = &fpriv->vm; 152*926deccbSFrançois Tigeot struct radeon_bo_va *bo_va; 153*926deccbSFrançois Tigeot int r; 154*926deccbSFrançois Tigeot 155*926deccbSFrançois Tigeot if (rdev->family < CHIP_CAYMAN) { 156*926deccbSFrançois Tigeot return 0; 157*926deccbSFrançois Tigeot } 158*926deccbSFrançois Tigeot 159*926deccbSFrançois Tigeot r = radeon_bo_reserve(rbo, false); 160*926deccbSFrançois Tigeot if (r) { 161*926deccbSFrançois Tigeot return r; 162*926deccbSFrançois Tigeot } 163*926deccbSFrançois Tigeot 164*926deccbSFrançois Tigeot bo_va = radeon_vm_bo_find(vm, rbo); 165*926deccbSFrançois Tigeot if (!bo_va) { 166*926deccbSFrançois Tigeot bo_va = radeon_vm_bo_add(rdev, vm, rbo); 167*926deccbSFrançois Tigeot } else { 168*926deccbSFrançois Tigeot ++bo_va->ref_count; 169*926deccbSFrançois Tigeot } 170*926deccbSFrançois Tigeot radeon_bo_unreserve(rbo); 171*926deccbSFrançois Tigeot 172*926deccbSFrançois Tigeot return 0; 173*926deccbSFrançois Tigeot } 174*926deccbSFrançois Tigeot 175*926deccbSFrançois Tigeot void radeon_gem_object_close(struct drm_gem_object *obj, 176*926deccbSFrançois Tigeot struct drm_file *file_priv) 177*926deccbSFrançois Tigeot { 178*926deccbSFrançois Tigeot struct radeon_bo *rbo = gem_to_radeon_bo(obj); 179*926deccbSFrançois Tigeot struct radeon_device *rdev = rbo->rdev; 180*926deccbSFrançois Tigeot struct radeon_fpriv *fpriv = file_priv->driver_priv; 181*926deccbSFrançois Tigeot struct radeon_vm *vm = &fpriv->vm; 182*926deccbSFrançois Tigeot struct radeon_bo_va *bo_va; 183*926deccbSFrançois Tigeot int r; 184*926deccbSFrançois Tigeot 185*926deccbSFrançois Tigeot if (rdev->family < CHIP_CAYMAN) { 186*926deccbSFrançois Tigeot return; 187*926deccbSFrançois Tigeot } 188*926deccbSFrançois Tigeot 189*926deccbSFrançois Tigeot r = radeon_bo_reserve(rbo, true); 190*926deccbSFrançois Tigeot if (r) { 191*926deccbSFrançois Tigeot dev_err(rdev->dev, "leaking bo va because " 192*926deccbSFrançois Tigeot "we fail to reserve bo (%d)\n", r); 193*926deccbSFrançois Tigeot return; 194*926deccbSFrançois Tigeot } 195*926deccbSFrançois Tigeot bo_va = radeon_vm_bo_find(vm, rbo); 196*926deccbSFrançois Tigeot if (bo_va) { 197*926deccbSFrançois Tigeot if (--bo_va->ref_count == 0) { 198*926deccbSFrançois Tigeot radeon_vm_bo_rmv(rdev, bo_va); 199*926deccbSFrançois Tigeot } 200*926deccbSFrançois Tigeot } 201*926deccbSFrançois Tigeot radeon_bo_unreserve(rbo); 202*926deccbSFrançois Tigeot } 203*926deccbSFrançois Tigeot 204*926deccbSFrançois Tigeot static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) 205*926deccbSFrançois Tigeot { 206*926deccbSFrançois Tigeot if (r == -EDEADLK) { 207*926deccbSFrançois Tigeot r = radeon_gpu_reset(rdev); 208*926deccbSFrançois Tigeot if (!r) 209*926deccbSFrançois Tigeot r = -EAGAIN; 210*926deccbSFrançois Tigeot } 211*926deccbSFrançois Tigeot return r; 212*926deccbSFrançois Tigeot } 213*926deccbSFrançois Tigeot 214*926deccbSFrançois Tigeot /* 215*926deccbSFrançois Tigeot * GEM ioctls. 216*926deccbSFrançois Tigeot */ 217*926deccbSFrançois Tigeot int radeon_gem_info_ioctl(struct drm_device *dev, void *data, 218*926deccbSFrançois Tigeot struct drm_file *filp) 219*926deccbSFrançois Tigeot { 220*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 221*926deccbSFrançois Tigeot struct drm_radeon_gem_info *args = data; 222*926deccbSFrançois Tigeot struct ttm_mem_type_manager *man; 223*926deccbSFrançois Tigeot unsigned i; 224*926deccbSFrançois Tigeot 225*926deccbSFrançois Tigeot man = &rdev->mman.bdev.man[TTM_PL_VRAM]; 226*926deccbSFrançois Tigeot 227*926deccbSFrançois Tigeot args->vram_size = rdev->mc.real_vram_size; 228*926deccbSFrançois Tigeot args->vram_visible = (u64)man->size << PAGE_SHIFT; 229*926deccbSFrançois Tigeot if (rdev->stollen_vga_memory) 230*926deccbSFrançois Tigeot args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); 231*926deccbSFrançois Tigeot args->vram_visible -= radeon_fbdev_total_size(rdev); 232*926deccbSFrançois Tigeot args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024; 233*926deccbSFrançois Tigeot for(i = 0; i < RADEON_NUM_RINGS; ++i) 234*926deccbSFrançois Tigeot args->gart_size -= rdev->ring[i].ring_size; 235*926deccbSFrançois Tigeot return 0; 236*926deccbSFrançois Tigeot } 237*926deccbSFrançois Tigeot 238*926deccbSFrançois Tigeot int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, 239*926deccbSFrançois Tigeot struct drm_file *filp) 240*926deccbSFrançois Tigeot { 241*926deccbSFrançois Tigeot /* TODO: implement */ 242*926deccbSFrançois Tigeot DRM_ERROR("unimplemented %s\n", __func__); 243*926deccbSFrançois Tigeot return -ENOSYS; 244*926deccbSFrançois Tigeot } 245*926deccbSFrançois Tigeot 246*926deccbSFrançois Tigeot int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, 247*926deccbSFrançois Tigeot struct drm_file *filp) 248*926deccbSFrançois Tigeot { 249*926deccbSFrançois Tigeot /* TODO: implement */ 250*926deccbSFrançois Tigeot DRM_ERROR("unimplemented %s\n", __func__); 251*926deccbSFrançois Tigeot return -ENOSYS; 252*926deccbSFrançois Tigeot } 253*926deccbSFrançois Tigeot 254*926deccbSFrançois Tigeot int radeon_gem_create_ioctl(struct drm_device *dev, void *data, 255*926deccbSFrançois Tigeot struct drm_file *filp) 256*926deccbSFrançois Tigeot { 257*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 258*926deccbSFrançois Tigeot struct drm_radeon_gem_create *args = data; 259*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 260*926deccbSFrançois Tigeot uint32_t handle; 261*926deccbSFrançois Tigeot int r; 262*926deccbSFrançois Tigeot 263*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_SHARED); 264*926deccbSFrançois Tigeot /* create a gem object to contain this object in */ 265*926deccbSFrançois Tigeot args->size = roundup(args->size, PAGE_SIZE); 266*926deccbSFrançois Tigeot r = radeon_gem_object_create(rdev, args->size, args->alignment, 267*926deccbSFrançois Tigeot args->initial_domain, false, 268*926deccbSFrançois Tigeot false, &gobj); 269*926deccbSFrançois Tigeot if (r) { 270*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_RELEASE); 271*926deccbSFrançois Tigeot r = radeon_gem_handle_lockup(rdev, r); 272*926deccbSFrançois Tigeot return r; 273*926deccbSFrançois Tigeot } 274*926deccbSFrançois Tigeot handle = 0; 275*926deccbSFrançois Tigeot r = drm_gem_handle_create(filp, gobj, &handle); 276*926deccbSFrançois Tigeot /* drop reference from allocate - handle holds it now */ 277*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 278*926deccbSFrançois Tigeot if (r) { 279*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_RELEASE); 280*926deccbSFrançois Tigeot r = radeon_gem_handle_lockup(rdev, r); 281*926deccbSFrançois Tigeot return r; 282*926deccbSFrançois Tigeot } 283*926deccbSFrançois Tigeot args->handle = handle; 284*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_RELEASE); 285*926deccbSFrançois Tigeot return 0; 286*926deccbSFrançois Tigeot } 287*926deccbSFrançois Tigeot 288*926deccbSFrançois Tigeot int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, 289*926deccbSFrançois Tigeot struct drm_file *filp) 290*926deccbSFrançois Tigeot { 291*926deccbSFrançois Tigeot /* transition the BO to a domain - 292*926deccbSFrançois Tigeot * just validate the BO into a certain domain */ 293*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 294*926deccbSFrançois Tigeot struct drm_radeon_gem_set_domain *args = data; 295*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 296*926deccbSFrançois Tigeot struct radeon_bo *robj; 297*926deccbSFrançois Tigeot int r; 298*926deccbSFrançois Tigeot 299*926deccbSFrançois Tigeot /* for now if someone requests domain CPU - 300*926deccbSFrançois Tigeot * just make sure the buffer is finished with */ 301*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_SHARED); 302*926deccbSFrançois Tigeot 303*926deccbSFrançois Tigeot /* just do a BO wait for now */ 304*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 305*926deccbSFrançois Tigeot if (gobj == NULL) { 306*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_RELEASE); 307*926deccbSFrançois Tigeot return -ENOENT; 308*926deccbSFrançois Tigeot } 309*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 310*926deccbSFrançois Tigeot 311*926deccbSFrançois Tigeot r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); 312*926deccbSFrançois Tigeot 313*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 314*926deccbSFrançois Tigeot lockmgr(&rdev->exclusive_lock, LK_RELEASE); 315*926deccbSFrançois Tigeot r = radeon_gem_handle_lockup(robj->rdev, r); 316*926deccbSFrançois Tigeot return r; 317*926deccbSFrançois Tigeot } 318*926deccbSFrançois Tigeot 319*926deccbSFrançois Tigeot int radeon_mode_dumb_mmap(struct drm_file *filp, 320*926deccbSFrançois Tigeot struct drm_device *dev, 321*926deccbSFrançois Tigeot uint32_t handle, uint64_t *offset_p) 322*926deccbSFrançois Tigeot { 323*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 324*926deccbSFrançois Tigeot struct radeon_bo *robj; 325*926deccbSFrançois Tigeot 326*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, handle); 327*926deccbSFrançois Tigeot if (gobj == NULL) { 328*926deccbSFrançois Tigeot return -ENOENT; 329*926deccbSFrançois Tigeot } 330*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 331*926deccbSFrançois Tigeot *offset_p = radeon_bo_mmap_offset(robj); 332*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 333*926deccbSFrançois Tigeot return 0; 334*926deccbSFrançois Tigeot } 335*926deccbSFrançois Tigeot 336*926deccbSFrançois Tigeot int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, 337*926deccbSFrançois Tigeot struct drm_file *filp) 338*926deccbSFrançois Tigeot { 339*926deccbSFrançois Tigeot struct drm_radeon_gem_mmap *args = data; 340*926deccbSFrançois Tigeot 341*926deccbSFrançois Tigeot return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); 342*926deccbSFrançois Tigeot } 343*926deccbSFrançois Tigeot 344*926deccbSFrançois Tigeot int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, 345*926deccbSFrançois Tigeot struct drm_file *filp) 346*926deccbSFrançois Tigeot { 347*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 348*926deccbSFrançois Tigeot struct drm_radeon_gem_busy *args = data; 349*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 350*926deccbSFrançois Tigeot struct radeon_bo *robj; 351*926deccbSFrançois Tigeot int r; 352*926deccbSFrançois Tigeot uint32_t cur_placement = 0; 353*926deccbSFrançois Tigeot 354*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 355*926deccbSFrançois Tigeot if (gobj == NULL) { 356*926deccbSFrançois Tigeot return -ENOENT; 357*926deccbSFrançois Tigeot } 358*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 359*926deccbSFrançois Tigeot r = radeon_bo_wait(robj, &cur_placement, true); 360*926deccbSFrançois Tigeot switch (cur_placement) { 361*926deccbSFrançois Tigeot case TTM_PL_VRAM: 362*926deccbSFrançois Tigeot args->domain = RADEON_GEM_DOMAIN_VRAM; 363*926deccbSFrançois Tigeot break; 364*926deccbSFrançois Tigeot case TTM_PL_TT: 365*926deccbSFrançois Tigeot args->domain = RADEON_GEM_DOMAIN_GTT; 366*926deccbSFrançois Tigeot break; 367*926deccbSFrançois Tigeot case TTM_PL_SYSTEM: 368*926deccbSFrançois Tigeot args->domain = RADEON_GEM_DOMAIN_CPU; 369*926deccbSFrançois Tigeot default: 370*926deccbSFrançois Tigeot break; 371*926deccbSFrançois Tigeot } 372*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 373*926deccbSFrançois Tigeot r = radeon_gem_handle_lockup(rdev, r); 374*926deccbSFrançois Tigeot return r; 375*926deccbSFrançois Tigeot } 376*926deccbSFrançois Tigeot 377*926deccbSFrançois Tigeot int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, 378*926deccbSFrançois Tigeot struct drm_file *filp) 379*926deccbSFrançois Tigeot { 380*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 381*926deccbSFrançois Tigeot struct drm_radeon_gem_wait_idle *args = data; 382*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 383*926deccbSFrançois Tigeot struct radeon_bo *robj; 384*926deccbSFrançois Tigeot int r; 385*926deccbSFrançois Tigeot 386*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 387*926deccbSFrançois Tigeot if (gobj == NULL) { 388*926deccbSFrançois Tigeot return -ENOENT; 389*926deccbSFrançois Tigeot } 390*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 391*926deccbSFrançois Tigeot r = radeon_bo_wait(robj, NULL, false); 392*926deccbSFrançois Tigeot /* callback hw specific functions if any */ 393*926deccbSFrançois Tigeot if (rdev->asic->ioctl_wait_idle) 394*926deccbSFrançois Tigeot robj->rdev->asic->ioctl_wait_idle(rdev, robj); 395*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 396*926deccbSFrançois Tigeot r = radeon_gem_handle_lockup(rdev, r); 397*926deccbSFrançois Tigeot return r; 398*926deccbSFrançois Tigeot } 399*926deccbSFrançois Tigeot 400*926deccbSFrançois Tigeot int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, 401*926deccbSFrançois Tigeot struct drm_file *filp) 402*926deccbSFrançois Tigeot { 403*926deccbSFrançois Tigeot struct drm_radeon_gem_set_tiling *args = data; 404*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 405*926deccbSFrançois Tigeot struct radeon_bo *robj; 406*926deccbSFrançois Tigeot int r = 0; 407*926deccbSFrançois Tigeot 408*926deccbSFrançois Tigeot DRM_DEBUG("%d \n", args->handle); 409*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 410*926deccbSFrançois Tigeot if (gobj == NULL) 411*926deccbSFrançois Tigeot return -ENOENT; 412*926deccbSFrançois Tigeot robj = gem_to_radeon_bo(gobj); 413*926deccbSFrançois Tigeot r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); 414*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 415*926deccbSFrançois Tigeot return r; 416*926deccbSFrançois Tigeot } 417*926deccbSFrançois Tigeot 418*926deccbSFrançois Tigeot int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, 419*926deccbSFrançois Tigeot struct drm_file *filp) 420*926deccbSFrançois Tigeot { 421*926deccbSFrançois Tigeot struct drm_radeon_gem_get_tiling *args = data; 422*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 423*926deccbSFrançois Tigeot struct radeon_bo *rbo; 424*926deccbSFrançois Tigeot int r = 0; 425*926deccbSFrançois Tigeot 426*926deccbSFrançois Tigeot DRM_DEBUG("\n"); 427*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 428*926deccbSFrançois Tigeot if (gobj == NULL) 429*926deccbSFrançois Tigeot return -ENOENT; 430*926deccbSFrançois Tigeot rbo = gem_to_radeon_bo(gobj); 431*926deccbSFrançois Tigeot r = radeon_bo_reserve(rbo, false); 432*926deccbSFrançois Tigeot if (unlikely(r != 0)) 433*926deccbSFrançois Tigeot goto out; 434*926deccbSFrançois Tigeot radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch); 435*926deccbSFrançois Tigeot radeon_bo_unreserve(rbo); 436*926deccbSFrançois Tigeot out: 437*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 438*926deccbSFrançois Tigeot return r; 439*926deccbSFrançois Tigeot } 440*926deccbSFrançois Tigeot 441*926deccbSFrançois Tigeot int radeon_gem_va_ioctl(struct drm_device *dev, void *data, 442*926deccbSFrançois Tigeot struct drm_file *filp) 443*926deccbSFrançois Tigeot { 444*926deccbSFrançois Tigeot struct drm_radeon_gem_va *args = data; 445*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 446*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 447*926deccbSFrançois Tigeot struct radeon_fpriv *fpriv = filp->driver_priv; 448*926deccbSFrançois Tigeot struct radeon_bo *rbo; 449*926deccbSFrançois Tigeot struct radeon_bo_va *bo_va; 450*926deccbSFrançois Tigeot u32 invalid_flags; 451*926deccbSFrançois Tigeot int r = 0; 452*926deccbSFrançois Tigeot 453*926deccbSFrançois Tigeot if (!rdev->vm_manager.enabled) { 454*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 455*926deccbSFrançois Tigeot return -ENOTTY; 456*926deccbSFrançois Tigeot } 457*926deccbSFrançois Tigeot 458*926deccbSFrançois Tigeot /* !! DONT REMOVE !! 459*926deccbSFrançois Tigeot * We don't support vm_id yet, to be sure we don't have have broken 460*926deccbSFrançois Tigeot * userspace, reject anyone trying to use non 0 value thus moving 461*926deccbSFrançois Tigeot * forward we can use those fields without breaking existant userspace 462*926deccbSFrançois Tigeot */ 463*926deccbSFrançois Tigeot if (args->vm_id) { 464*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 465*926deccbSFrançois Tigeot return -EINVAL; 466*926deccbSFrançois Tigeot } 467*926deccbSFrançois Tigeot 468*926deccbSFrançois Tigeot if (args->offset < RADEON_VA_RESERVED_SIZE) { 469*926deccbSFrançois Tigeot dev_err(dev->device, 470*926deccbSFrançois Tigeot "offset 0x%lX is in reserved area 0x%X\n", 471*926deccbSFrançois Tigeot (unsigned long)args->offset, 472*926deccbSFrançois Tigeot RADEON_VA_RESERVED_SIZE); 473*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 474*926deccbSFrançois Tigeot return -EINVAL; 475*926deccbSFrançois Tigeot } 476*926deccbSFrançois Tigeot 477*926deccbSFrançois Tigeot /* don't remove, we need to enforce userspace to set the snooped flag 478*926deccbSFrançois Tigeot * otherwise we will endup with broken userspace and we won't be able 479*926deccbSFrançois Tigeot * to enable this feature without adding new interface 480*926deccbSFrançois Tigeot */ 481*926deccbSFrançois Tigeot invalid_flags = RADEON_VM_PAGE_VALID | RADEON_VM_PAGE_SYSTEM; 482*926deccbSFrançois Tigeot if ((args->flags & invalid_flags)) { 483*926deccbSFrançois Tigeot dev_err(dev->device, "invalid flags 0x%08X vs 0x%08X\n", 484*926deccbSFrançois Tigeot args->flags, invalid_flags); 485*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 486*926deccbSFrançois Tigeot return -EINVAL; 487*926deccbSFrançois Tigeot } 488*926deccbSFrançois Tigeot if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) { 489*926deccbSFrançois Tigeot dev_err(dev->device, "only supported snooped mapping for now\n"); 490*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 491*926deccbSFrançois Tigeot return -EINVAL; 492*926deccbSFrançois Tigeot } 493*926deccbSFrançois Tigeot 494*926deccbSFrançois Tigeot switch (args->operation) { 495*926deccbSFrançois Tigeot case RADEON_VA_MAP: 496*926deccbSFrançois Tigeot case RADEON_VA_UNMAP: 497*926deccbSFrançois Tigeot break; 498*926deccbSFrançois Tigeot default: 499*926deccbSFrançois Tigeot dev_err(dev->device, "unsupported operation %d\n", 500*926deccbSFrançois Tigeot args->operation); 501*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 502*926deccbSFrançois Tigeot return -EINVAL; 503*926deccbSFrançois Tigeot } 504*926deccbSFrançois Tigeot 505*926deccbSFrançois Tigeot gobj = drm_gem_object_lookup(dev, filp, args->handle); 506*926deccbSFrançois Tigeot if (gobj == NULL) { 507*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 508*926deccbSFrançois Tigeot return -ENOENT; 509*926deccbSFrançois Tigeot } 510*926deccbSFrançois Tigeot rbo = gem_to_radeon_bo(gobj); 511*926deccbSFrançois Tigeot r = radeon_bo_reserve(rbo, false); 512*926deccbSFrançois Tigeot if (r) { 513*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 514*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 515*926deccbSFrançois Tigeot return r; 516*926deccbSFrançois Tigeot } 517*926deccbSFrançois Tigeot bo_va = radeon_vm_bo_find(&fpriv->vm, rbo); 518*926deccbSFrançois Tigeot if (!bo_va) { 519*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 520*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 521*926deccbSFrançois Tigeot return -ENOENT; 522*926deccbSFrançois Tigeot } 523*926deccbSFrançois Tigeot 524*926deccbSFrançois Tigeot switch (args->operation) { 525*926deccbSFrançois Tigeot case RADEON_VA_MAP: 526*926deccbSFrançois Tigeot if (bo_va->soffset) { 527*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_VA_EXIST; 528*926deccbSFrançois Tigeot args->offset = bo_va->soffset; 529*926deccbSFrançois Tigeot goto out; 530*926deccbSFrançois Tigeot } 531*926deccbSFrançois Tigeot r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, args->flags); 532*926deccbSFrançois Tigeot break; 533*926deccbSFrançois Tigeot case RADEON_VA_UNMAP: 534*926deccbSFrançois Tigeot r = radeon_vm_bo_set_addr(rdev, bo_va, 0, 0); 535*926deccbSFrançois Tigeot break; 536*926deccbSFrançois Tigeot default: 537*926deccbSFrançois Tigeot break; 538*926deccbSFrançois Tigeot } 539*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_OK; 540*926deccbSFrançois Tigeot if (r) { 541*926deccbSFrançois Tigeot args->operation = RADEON_VA_RESULT_ERROR; 542*926deccbSFrançois Tigeot } 543*926deccbSFrançois Tigeot out: 544*926deccbSFrançois Tigeot radeon_bo_unreserve(rbo); 545*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 546*926deccbSFrançois Tigeot return r; 547*926deccbSFrançois Tigeot } 548*926deccbSFrançois Tigeot 549*926deccbSFrançois Tigeot int radeon_mode_dumb_create(struct drm_file *file_priv, 550*926deccbSFrançois Tigeot struct drm_device *dev, 551*926deccbSFrançois Tigeot struct drm_mode_create_dumb *args) 552*926deccbSFrançois Tigeot { 553*926deccbSFrançois Tigeot struct radeon_device *rdev = dev->dev_private; 554*926deccbSFrançois Tigeot struct drm_gem_object *gobj; 555*926deccbSFrançois Tigeot uint32_t handle; 556*926deccbSFrançois Tigeot int r; 557*926deccbSFrançois Tigeot 558*926deccbSFrançois Tigeot args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); 559*926deccbSFrançois Tigeot args->size = args->pitch * args->height; 560*926deccbSFrançois Tigeot args->size = roundup2(args->size, PAGE_SIZE); 561*926deccbSFrançois Tigeot 562*926deccbSFrançois Tigeot r = radeon_gem_object_create(rdev, args->size, 0, 563*926deccbSFrançois Tigeot RADEON_GEM_DOMAIN_VRAM, 564*926deccbSFrançois Tigeot false, ttm_bo_type_device, 565*926deccbSFrançois Tigeot &gobj); 566*926deccbSFrançois Tigeot if (r) 567*926deccbSFrançois Tigeot return -ENOMEM; 568*926deccbSFrançois Tigeot 569*926deccbSFrançois Tigeot r = drm_gem_handle_create(file_priv, gobj, &handle); 570*926deccbSFrançois Tigeot /* drop reference from allocate - handle holds it now */ 571*926deccbSFrançois Tigeot drm_gem_object_unreference_unlocked(gobj); 572*926deccbSFrançois Tigeot if (r) { 573*926deccbSFrançois Tigeot return r; 574*926deccbSFrançois Tigeot } 575*926deccbSFrançois Tigeot args->handle = handle; 576*926deccbSFrançois Tigeot return 0; 577*926deccbSFrançois Tigeot } 578*926deccbSFrançois Tigeot 579*926deccbSFrançois Tigeot int radeon_mode_dumb_destroy(struct drm_file *file_priv, 580*926deccbSFrançois Tigeot struct drm_device *dev, 581*926deccbSFrançois Tigeot uint32_t handle) 582*926deccbSFrançois Tigeot { 583*926deccbSFrançois Tigeot return drm_gem_handle_delete(file_priv, handle); 584*926deccbSFrançois Tigeot } 585