root/drivers/gpu/drm/nouveau/nouveau_abi16.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nouveau_abi16
  2. nouveau_abi16_get
  3. nouveau_abi16_put
  4. nouveau_abi16_swclass
  5. nouveau_abi16_ntfy_fini
  6. nouveau_abi16_chan_fini
  7. nouveau_abi16_fini
  8. nouveau_abi16_ioctl_getparam
  9. nouveau_abi16_ioctl_channel_alloc
  10. nouveau_abi16_chan
  11. nouveau_abi16_usif
  12. nouveau_abi16_ioctl_channel_free
  13. nouveau_abi16_ioctl_grobj_alloc
  14. nouveau_abi16_ioctl_notifierobj_alloc
  15. nouveau_abi16_ioctl_gpuobj_free

   1 /*
   2  * Copyright 2012 Red Hat Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  */
  23 
  24 #include <nvif/client.h>
  25 #include <nvif/driver.h>
  26 #include <nvif/fifo.h>
  27 #include <nvif/ioctl.h>
  28 #include <nvif/class.h>
  29 #include <nvif/cl0002.h>
  30 #include <nvif/cla06f.h>
  31 #include <nvif/unpack.h>
  32 
  33 #include "nouveau_drv.h"
  34 #include "nouveau_dma.h"
  35 #include "nouveau_gem.h"
  36 #include "nouveau_chan.h"
  37 #include "nouveau_abi16.h"
  38 #include "nouveau_vmm.h"
  39 
  40 static struct nouveau_abi16 *
  41 nouveau_abi16(struct drm_file *file_priv)
  42 {
  43         struct nouveau_cli *cli = nouveau_cli(file_priv);
  44         if (!cli->abi16) {
  45                 struct nouveau_abi16 *abi16;
  46                 cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL);
  47                 if (cli->abi16) {
  48                         struct nv_device_v0 args = {
  49                                 .device = ~0ULL,
  50                         };
  51 
  52                         INIT_LIST_HEAD(&abi16->channels);
  53 
  54                         /* allocate device object targeting client's default
  55                          * device (ie. the one that belongs to the fd it
  56                          * opened)
  57                          */
  58                         if (nvif_device_init(&cli->base.object, 0, NV_DEVICE,
  59                                              &args, sizeof(args),
  60                                              &abi16->device) == 0)
  61                                 return cli->abi16;
  62 
  63                         kfree(cli->abi16);
  64                         cli->abi16 = NULL;
  65                 }
  66         }
  67         return cli->abi16;
  68 }
  69 
  70 struct nouveau_abi16 *
  71 nouveau_abi16_get(struct drm_file *file_priv)
  72 {
  73         struct nouveau_cli *cli = nouveau_cli(file_priv);
  74         mutex_lock(&cli->mutex);
  75         if (nouveau_abi16(file_priv))
  76                 return cli->abi16;
  77         mutex_unlock(&cli->mutex);
  78         return NULL;
  79 }
  80 
  81 int
  82 nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
  83 {
  84         struct nouveau_cli *cli = (void *)abi16->device.object.client;
  85         mutex_unlock(&cli->mutex);
  86         return ret;
  87 }
  88 
  89 s32
  90 nouveau_abi16_swclass(struct nouveau_drm *drm)
  91 {
  92         switch (drm->client.device.info.family) {
  93         case NV_DEVICE_INFO_V0_TNT:
  94                 return NVIF_CLASS_SW_NV04;
  95         case NV_DEVICE_INFO_V0_CELSIUS:
  96         case NV_DEVICE_INFO_V0_KELVIN:
  97         case NV_DEVICE_INFO_V0_RANKINE:
  98         case NV_DEVICE_INFO_V0_CURIE:
  99                 return NVIF_CLASS_SW_NV10;
 100         case NV_DEVICE_INFO_V0_TESLA:
 101                 return NVIF_CLASS_SW_NV50;
 102         case NV_DEVICE_INFO_V0_FERMI:
 103         case NV_DEVICE_INFO_V0_KEPLER:
 104         case NV_DEVICE_INFO_V0_MAXWELL:
 105         case NV_DEVICE_INFO_V0_PASCAL:
 106         case NV_DEVICE_INFO_V0_VOLTA:
 107                 return NVIF_CLASS_SW_GF100;
 108         }
 109 
 110         return 0x0000;
 111 }
 112 
 113 static void
 114 nouveau_abi16_ntfy_fini(struct nouveau_abi16_chan *chan,
 115                         struct nouveau_abi16_ntfy *ntfy)
 116 {
 117         nvif_object_fini(&ntfy->object);
 118         nvkm_mm_free(&chan->heap, &ntfy->node);
 119         list_del(&ntfy->head);
 120         kfree(ntfy);
 121 }
 122 
 123 static void
 124 nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
 125                         struct nouveau_abi16_chan *chan)
 126 {
 127         struct nouveau_abi16_ntfy *ntfy, *temp;
 128 
 129         /* wait for all activity to stop before releasing notify object, which
 130          * may be still in use */
 131         if (chan->chan && chan->ntfy)
 132                 nouveau_channel_idle(chan->chan);
 133 
 134         /* cleanup notifier state */
 135         list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) {
 136                 nouveau_abi16_ntfy_fini(chan, ntfy);
 137         }
 138 
 139         if (chan->ntfy) {
 140                 nouveau_vma_del(&chan->ntfy_vma);
 141                 nouveau_bo_unpin(chan->ntfy);
 142                 drm_gem_object_put_unlocked(&chan->ntfy->bo.base);
 143         }
 144 
 145         if (chan->heap.block_size)
 146                 nvkm_mm_fini(&chan->heap);
 147 
 148         /* destroy channel object, all children will be killed too */
 149         if (chan->chan) {
 150                 nouveau_channel_idle(chan->chan);
 151                 nouveau_channel_del(&chan->chan);
 152         }
 153 
 154         list_del(&chan->head);
 155         kfree(chan);
 156 }
 157 
 158 void
 159 nouveau_abi16_fini(struct nouveau_abi16 *abi16)
 160 {
 161         struct nouveau_cli *cli = (void *)abi16->device.object.client;
 162         struct nouveau_abi16_chan *chan, *temp;
 163 
 164         /* cleanup channels */
 165         list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
 166                 nouveau_abi16_chan_fini(abi16, chan);
 167         }
 168 
 169         /* destroy the device object */
 170         nvif_device_fini(&abi16->device);
 171 
 172         kfree(cli->abi16);
 173         cli->abi16 = NULL;
 174 }
 175 
 176 int
 177 nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
 178 {
 179         struct nouveau_cli *cli = nouveau_cli(file_priv);
 180         struct nouveau_drm *drm = nouveau_drm(dev);
 181         struct nvif_device *device = &drm->client.device;
 182         struct nvkm_gr *gr = nvxx_gr(device);
 183         struct drm_nouveau_getparam *getparam = data;
 184 
 185         switch (getparam->param) {
 186         case NOUVEAU_GETPARAM_CHIPSET_ID:
 187                 getparam->value = device->info.chipset;
 188                 break;
 189         case NOUVEAU_GETPARAM_PCI_VENDOR:
 190                 if (device->info.platform != NV_DEVICE_INFO_V0_SOC)
 191                         getparam->value = dev->pdev->vendor;
 192                 else
 193                         getparam->value = 0;
 194                 break;
 195         case NOUVEAU_GETPARAM_PCI_DEVICE:
 196                 if (device->info.platform != NV_DEVICE_INFO_V0_SOC)
 197                         getparam->value = dev->pdev->device;
 198                 else
 199                         getparam->value = 0;
 200                 break;
 201         case NOUVEAU_GETPARAM_BUS_TYPE:
 202                 switch (device->info.platform) {
 203                 case NV_DEVICE_INFO_V0_AGP : getparam->value = 0; break;
 204                 case NV_DEVICE_INFO_V0_PCI : getparam->value = 1; break;
 205                 case NV_DEVICE_INFO_V0_PCIE: getparam->value = 2; break;
 206                 case NV_DEVICE_INFO_V0_SOC : getparam->value = 3; break;
 207                 case NV_DEVICE_INFO_V0_IGP :
 208                         if (!pci_is_pcie(dev->pdev))
 209                                 getparam->value = 1;
 210                         else
 211                                 getparam->value = 2;
 212                         break;
 213                 default:
 214                         WARN_ON(1);
 215                         break;
 216                 }
 217                 break;
 218         case NOUVEAU_GETPARAM_FB_SIZE:
 219                 getparam->value = drm->gem.vram_available;
 220                 break;
 221         case NOUVEAU_GETPARAM_AGP_SIZE:
 222                 getparam->value = drm->gem.gart_available;
 223                 break;
 224         case NOUVEAU_GETPARAM_VM_VRAM_BASE:
 225                 getparam->value = 0; /* deprecated */
 226                 break;
 227         case NOUVEAU_GETPARAM_PTIMER_TIME:
 228                 getparam->value = nvif_device_time(device);
 229                 break;
 230         case NOUVEAU_GETPARAM_HAS_BO_USAGE:
 231                 getparam->value = 1;
 232                 break;
 233         case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
 234                 getparam->value = 1;
 235                 break;
 236         case NOUVEAU_GETPARAM_GRAPH_UNITS:
 237                 getparam->value = nvkm_gr_units(gr);
 238                 break;
 239         default:
 240                 NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param);
 241                 return -EINVAL;
 242         }
 243 
 244         return 0;
 245 }
 246 
 247 int
 248 nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 249 {
 250         struct drm_nouveau_channel_alloc *init = data;
 251         struct nouveau_cli *cli = nouveau_cli(file_priv);
 252         struct nouveau_drm *drm = nouveau_drm(dev);
 253         struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
 254         struct nouveau_abi16_chan *chan;
 255         struct nvif_device *device;
 256         u64 engine;
 257         int ret;
 258 
 259         if (unlikely(!abi16))
 260                 return -ENOMEM;
 261 
 262         if (!drm->channel)
 263                 return nouveau_abi16_put(abi16, -ENODEV);
 264 
 265         device = &abi16->device;
 266 
 267         /* hack to allow channel engine type specification on kepler */
 268         if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
 269                 if (init->fb_ctxdma_handle == ~0) {
 270                         switch (init->tt_ctxdma_handle) {
 271                         case 0x01: engine = NV_DEVICE_INFO_ENGINE_GR    ; break;
 272                         case 0x02: engine = NV_DEVICE_INFO_ENGINE_MSPDEC; break;
 273                         case 0x04: engine = NV_DEVICE_INFO_ENGINE_MSPPP ; break;
 274                         case 0x08: engine = NV_DEVICE_INFO_ENGINE_MSVLD ; break;
 275                         case 0x30: engine = NV_DEVICE_INFO_ENGINE_CE    ; break;
 276                         default:
 277                                 return nouveau_abi16_put(abi16, -ENOSYS);
 278                         }
 279                 } else {
 280                         engine = NV_DEVICE_INFO_ENGINE_GR;
 281                 }
 282 
 283                 if (engine != NV_DEVICE_INFO_ENGINE_CE)
 284                         engine = nvif_fifo_runlist(device, engine);
 285                 else
 286                         engine = nvif_fifo_runlist_ce(device);
 287                 init->fb_ctxdma_handle = engine;
 288                 init->tt_ctxdma_handle = 0;
 289         }
 290 
 291         if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
 292                 return nouveau_abi16_put(abi16, -EINVAL);
 293 
 294         /* allocate "abi16 channel" data and make up a handle for it */
 295         chan = kzalloc(sizeof(*chan), GFP_KERNEL);
 296         if (!chan)
 297                 return nouveau_abi16_put(abi16, -ENOMEM);
 298 
 299         INIT_LIST_HEAD(&chan->notifiers);
 300         list_add(&chan->head, &abi16->channels);
 301 
 302         /* create channel object and initialise dma and fence management */
 303         ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
 304                                   init->tt_ctxdma_handle, false, &chan->chan);
 305         if (ret)
 306                 goto done;
 307 
 308         init->channel = chan->chan->chid;
 309 
 310         if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
 311                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
 312                                         NOUVEAU_GEM_DOMAIN_GART;
 313         else
 314         if (chan->chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM)
 315                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
 316         else
 317                 init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
 318 
 319         if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 320                 init->subchan[0].handle = 0x00000000;
 321                 init->subchan[0].grclass = 0x0000;
 322                 init->subchan[1].handle = chan->chan->nvsw.handle;
 323                 init->subchan[1].grclass = 0x506e;
 324                 init->nr_subchan = 2;
 325         }
 326 
 327         /* Named memory object area */
 328         ret = nouveau_gem_new(cli, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART,
 329                               0, 0, &chan->ntfy);
 330         if (ret == 0)
 331                 ret = nouveau_bo_pin(chan->ntfy, TTM_PL_FLAG_TT, false);
 332         if (ret)
 333                 goto done;
 334 
 335         if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
 336                 ret = nouveau_vma_new(chan->ntfy, chan->chan->vmm,
 337                                       &chan->ntfy_vma);
 338                 if (ret)
 339                         goto done;
 340         }
 341 
 342         ret = drm_gem_handle_create(file_priv, &chan->ntfy->bo.base,
 343                                     &init->notifier_handle);
 344         if (ret)
 345                 goto done;
 346 
 347         ret = nvkm_mm_init(&chan->heap, 0, 0, PAGE_SIZE, 1);
 348 done:
 349         if (ret)
 350                 nouveau_abi16_chan_fini(abi16, chan);
 351         return nouveau_abi16_put(abi16, ret);
 352 }
 353 
 354 static struct nouveau_abi16_chan *
 355 nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
 356 {
 357         struct nouveau_abi16_chan *chan;
 358 
 359         list_for_each_entry(chan, &abi16->channels, head) {
 360                 if (chan->chan->chid == channel)
 361                         return chan;
 362         }
 363 
 364         return NULL;
 365 }
 366 
 367 int
 368 nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size)
 369 {
 370         union {
 371                 struct nvif_ioctl_v0 v0;
 372         } *args = data;
 373         struct nouveau_abi16_chan *chan;
 374         struct nouveau_abi16 *abi16;
 375         int ret = -ENOSYS;
 376 
 377         if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
 378                 switch (args->v0.type) {
 379                 case NVIF_IOCTL_V0_NEW:
 380                 case NVIF_IOCTL_V0_MTHD:
 381                 case NVIF_IOCTL_V0_SCLASS:
 382                         break;
 383                 default:
 384                         return -EACCES;
 385                 }
 386         } else
 387                 return ret;
 388 
 389         if (!(abi16 = nouveau_abi16(file_priv)))
 390                 return -ENOMEM;
 391 
 392         if (args->v0.token != ~0ULL) {
 393                 if (!(chan = nouveau_abi16_chan(abi16, args->v0.token)))
 394                         return -EINVAL;
 395                 args->v0.object = nvif_handle(&chan->chan->user);
 396                 args->v0.owner  = NVIF_IOCTL_V0_OWNER_ANY;
 397                 return 0;
 398         }
 399 
 400         args->v0.object = nvif_handle(&abi16->device.object);
 401         args->v0.owner  = NVIF_IOCTL_V0_OWNER_ANY;
 402         return 0;
 403 }
 404 
 405 int
 406 nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
 407 {
 408         struct drm_nouveau_channel_free *req = data;
 409         struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
 410         struct nouveau_abi16_chan *chan;
 411 
 412         if (unlikely(!abi16))
 413                 return -ENOMEM;
 414 
 415         chan = nouveau_abi16_chan(abi16, req->channel);
 416         if (!chan)
 417                 return nouveau_abi16_put(abi16, -ENOENT);
 418         nouveau_abi16_chan_fini(abi16, chan);
 419         return nouveau_abi16_put(abi16, 0);
 420 }
 421 
 422 int
 423 nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
 424 {
 425         struct drm_nouveau_grobj_alloc *init = data;
 426         struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
 427         struct nouveau_abi16_chan *chan;
 428         struct nouveau_abi16_ntfy *ntfy;
 429         struct nvif_client *client;
 430         struct nvif_sclass *sclass;
 431         s32 oclass = 0;
 432         int ret, i;
 433 
 434         if (unlikely(!abi16))
 435                 return -ENOMEM;
 436 
 437         if (init->handle == ~0)
 438                 return nouveau_abi16_put(abi16, -EINVAL);
 439         client = abi16->device.object.client;
 440 
 441         chan = nouveau_abi16_chan(abi16, init->channel);
 442         if (!chan)
 443                 return nouveau_abi16_put(abi16, -ENOENT);
 444 
 445         ret = nvif_object_sclass_get(&chan->chan->user, &sclass);
 446         if (ret < 0)
 447                 return nouveau_abi16_put(abi16, ret);
 448 
 449         if ((init->class & 0x00ff) == 0x006e) {
 450                 /* nvsw: compatibility with older 0x*6e class identifier */
 451                 for (i = 0; !oclass && i < ret; i++) {
 452                         switch (sclass[i].oclass) {
 453                         case NVIF_CLASS_SW_NV04:
 454                         case NVIF_CLASS_SW_NV10:
 455                         case NVIF_CLASS_SW_NV50:
 456                         case NVIF_CLASS_SW_GF100:
 457                                 oclass = sclass[i].oclass;
 458                                 break;
 459                         default:
 460                                 break;
 461                         }
 462                 }
 463         } else
 464         if ((init->class & 0x00ff) == 0x00b1) {
 465                 /* msvld: compatibility with incorrect version exposure */
 466                 for (i = 0; i < ret; i++) {
 467                         if ((sclass[i].oclass & 0x00ff) == 0x00b1) {
 468                                 oclass = sclass[i].oclass;
 469                                 break;
 470                         }
 471                 }
 472         } else
 473         if ((init->class & 0x00ff) == 0x00b2) { /* mspdec */
 474                 /* mspdec: compatibility with incorrect version exposure */
 475                 for (i = 0; i < ret; i++) {
 476                         if ((sclass[i].oclass & 0x00ff) == 0x00b2) {
 477                                 oclass = sclass[i].oclass;
 478                                 break;
 479                         }
 480                 }
 481         } else
 482         if ((init->class & 0x00ff) == 0x00b3) { /* msppp */
 483                 /* msppp: compatibility with incorrect version exposure */
 484                 for (i = 0; i < ret; i++) {
 485                         if ((sclass[i].oclass & 0x00ff) == 0x00b3) {
 486                                 oclass = sclass[i].oclass;
 487                                 break;
 488                         }
 489                 }
 490         } else {
 491                 oclass = init->class;
 492         }
 493 
 494         nvif_object_sclass_put(&sclass);
 495         if (!oclass)
 496                 return nouveau_abi16_put(abi16, -EINVAL);
 497 
 498         ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL);
 499         if (!ntfy)
 500                 return nouveau_abi16_put(abi16, -ENOMEM);
 501 
 502         list_add(&ntfy->head, &chan->notifiers);
 503 
 504         client->route = NVDRM_OBJECT_ABI16;
 505         ret = nvif_object_init(&chan->chan->user, init->handle, oclass,
 506                                NULL, 0, &ntfy->object);
 507         client->route = NVDRM_OBJECT_NVIF;
 508 
 509         if (ret)
 510                 nouveau_abi16_ntfy_fini(chan, ntfy);
 511         return nouveau_abi16_put(abi16, ret);
 512 }
 513 
 514 int
 515 nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
 516 {
 517         struct drm_nouveau_notifierobj_alloc *info = data;
 518         struct nouveau_drm *drm = nouveau_drm(dev);
 519         struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
 520         struct nouveau_abi16_chan *chan;
 521         struct nouveau_abi16_ntfy *ntfy;
 522         struct nvif_device *device = &abi16->device;
 523         struct nvif_client *client;
 524         struct nv_dma_v0 args = {};
 525         int ret;
 526 
 527         if (unlikely(!abi16))
 528                 return -ENOMEM;
 529 
 530         /* completely unnecessary for these chipsets... */
 531         if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI))
 532                 return nouveau_abi16_put(abi16, -EINVAL);
 533         client = abi16->device.object.client;
 534 
 535         chan = nouveau_abi16_chan(abi16, info->channel);
 536         if (!chan)
 537                 return nouveau_abi16_put(abi16, -ENOENT);
 538 
 539         ntfy = kzalloc(sizeof(*ntfy), GFP_KERNEL);
 540         if (!ntfy)
 541                 return nouveau_abi16_put(abi16, -ENOMEM);
 542 
 543         list_add(&ntfy->head, &chan->notifiers);
 544 
 545         ret = nvkm_mm_head(&chan->heap, 0, 1, info->size, info->size, 1,
 546                            &ntfy->node);
 547         if (ret)
 548                 goto done;
 549 
 550         args.start = ntfy->node->offset;
 551         args.limit = ntfy->node->offset + ntfy->node->length - 1;
 552         if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
 553                 args.target = NV_DMA_V0_TARGET_VM;
 554                 args.access = NV_DMA_V0_ACCESS_VM;
 555                 args.start += chan->ntfy_vma->addr;
 556                 args.limit += chan->ntfy_vma->addr;
 557         } else
 558         if (drm->agp.bridge) {
 559                 args.target = NV_DMA_V0_TARGET_AGP;
 560                 args.access = NV_DMA_V0_ACCESS_RDWR;
 561                 args.start += drm->agp.base + chan->ntfy->bo.offset;
 562                 args.limit += drm->agp.base + chan->ntfy->bo.offset;
 563         } else {
 564                 args.target = NV_DMA_V0_TARGET_VM;
 565                 args.access = NV_DMA_V0_ACCESS_RDWR;
 566                 args.start += chan->ntfy->bo.offset;
 567                 args.limit += chan->ntfy->bo.offset;
 568         }
 569 
 570         client->route = NVDRM_OBJECT_ABI16;
 571         client->super = true;
 572         ret = nvif_object_init(&chan->chan->user, info->handle,
 573                                NV_DMA_IN_MEMORY, &args, sizeof(args),
 574                                &ntfy->object);
 575         client->super = false;
 576         client->route = NVDRM_OBJECT_NVIF;
 577         if (ret)
 578                 goto done;
 579 
 580         info->offset = ntfy->node->offset;
 581 done:
 582         if (ret)
 583                 nouveau_abi16_ntfy_fini(chan, ntfy);
 584         return nouveau_abi16_put(abi16, ret);
 585 }
 586 
 587 int
 588 nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
 589 {
 590         struct drm_nouveau_gpuobj_free *fini = data;
 591         struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
 592         struct nouveau_abi16_chan *chan;
 593         struct nouveau_abi16_ntfy *ntfy;
 594         int ret = -ENOENT;
 595 
 596         if (unlikely(!abi16))
 597                 return -ENOMEM;
 598 
 599         chan = nouveau_abi16_chan(abi16, fini->channel);
 600         if (!chan)
 601                 return nouveau_abi16_put(abi16, -EINVAL);
 602 
 603         /* synchronize with the user channel and destroy the gpu object */
 604         nouveau_channel_idle(chan->chan);
 605 
 606         list_for_each_entry(ntfy, &chan->notifiers, head) {
 607                 if (ntfy->object.handle == fini->handle) {
 608                         nouveau_abi16_ntfy_fini(chan, ntfy);
 609                         ret = 0;
 610                         break;
 611                 }
 612         }
 613 
 614         return nouveau_abi16_put(abi16, ret);
 615 }

/* [<][>][^][v][top][bottom][index][help] */