linux/drivers/gpu/drm/nouveau/nouveau_chan.c
<<
>>
Prefs
   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 * Authors: Ben Skeggs
  23 */
  24#include <nvif/push006c.h>
  25
  26#include <nvif/class.h>
  27#include <nvif/cl0002.h>
  28#include <nvif/cl006b.h>
  29#include <nvif/cl506f.h>
  30#include <nvif/cl906f.h>
  31#include <nvif/cla06f.h>
  32#include <nvif/clc36f.h>
  33#include <nvif/ioctl.h>
  34
  35#include "nouveau_drv.h"
  36#include "nouveau_dma.h"
  37#include "nouveau_bo.h"
  38#include "nouveau_chan.h"
  39#include "nouveau_fence.h"
  40#include "nouveau_abi16.h"
  41#include "nouveau_vmm.h"
  42#include "nouveau_svm.h"
  43
  44MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM");
  45int nouveau_vram_pushbuf;
  46module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
  47
  48static int
  49nouveau_channel_killed(struct nvif_notify *ntfy)
  50{
  51        struct nouveau_channel *chan = container_of(ntfy, typeof(*chan), kill);
  52        struct nouveau_cli *cli = (void *)chan->user.client;
  53        NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid);
  54        atomic_set(&chan->killed, 1);
  55        if (chan->fence)
  56                nouveau_fence_context_kill(chan->fence, -ENODEV);
  57        return NVIF_NOTIFY_DROP;
  58}
  59
  60int
  61nouveau_channel_idle(struct nouveau_channel *chan)
  62{
  63        if (likely(chan && chan->fence && !atomic_read(&chan->killed))) {
  64                struct nouveau_cli *cli = (void *)chan->user.client;
  65                struct nouveau_fence *fence = NULL;
  66                int ret;
  67
  68                ret = nouveau_fence_new(chan, false, &fence);
  69                if (!ret) {
  70                        ret = nouveau_fence_wait(fence, false, false);
  71                        nouveau_fence_unref(&fence);
  72                }
  73
  74                if (ret) {
  75                        NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n",
  76                                  chan->chid, nvxx_client(&cli->base)->name);
  77                        return ret;
  78                }
  79        }
  80        return 0;
  81}
  82
  83void
  84nouveau_channel_del(struct nouveau_channel **pchan)
  85{
  86        struct nouveau_channel *chan = *pchan;
  87        if (chan) {
  88                struct nouveau_cli *cli = (void *)chan->user.client;
  89                bool super;
  90
  91                if (cli) {
  92                        super = cli->base.super;
  93                        cli->base.super = true;
  94                }
  95
  96                if (chan->fence)
  97                        nouveau_fence(chan->drm)->context_del(chan);
  98
  99                if (cli)
 100                        nouveau_svmm_part(chan->vmm->svmm, chan->inst);
 101
 102                nvif_object_dtor(&chan->nvsw);
 103                nvif_object_dtor(&chan->gart);
 104                nvif_object_dtor(&chan->vram);
 105                nvif_notify_dtor(&chan->kill);
 106                nvif_object_dtor(&chan->user);
 107                nvif_object_dtor(&chan->push.ctxdma);
 108                nouveau_vma_del(&chan->push.vma);
 109                nouveau_bo_unmap(chan->push.buffer);
 110                if (chan->push.buffer && chan->push.buffer->pin_refcnt)
 111                        nouveau_bo_unpin(chan->push.buffer);
 112                nouveau_bo_ref(NULL, &chan->push.buffer);
 113                kfree(chan);
 114
 115                if (cli)
 116                        cli->base.super = super;
 117        }
 118        *pchan = NULL;
 119}
 120
 121static void
 122nouveau_channel_kick(struct nvif_push *push)
 123{
 124        struct nouveau_channel *chan = container_of(push, typeof(*chan), chan._push);
 125        chan->dma.cur = chan->dma.cur + (chan->chan._push.cur - chan->chan._push.bgn);
 126        FIRE_RING(chan);
 127        chan->chan._push.bgn = chan->chan._push.cur;
 128}
 129
 130static int
 131nouveau_channel_wait(struct nvif_push *push, u32 size)
 132{
 133        struct nouveau_channel *chan = container_of(push, typeof(*chan), chan._push);
 134        int ret;
 135        chan->dma.cur = chan->dma.cur + (chan->chan._push.cur - chan->chan._push.bgn);
 136        ret = RING_SPACE(chan, size);
 137        if (ret == 0) {
 138                chan->chan._push.bgn = chan->chan._push.mem.object.map.ptr;
 139                chan->chan._push.bgn = chan->chan._push.bgn + chan->dma.cur;
 140                chan->chan._push.cur = chan->chan._push.bgn;
 141                chan->chan._push.end = chan->chan._push.bgn + size;
 142        }
 143        return ret;
 144}
 145
 146static int
 147nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
 148                     u32 size, struct nouveau_channel **pchan)
 149{
 150        struct nouveau_cli *cli = (void *)device->object.client;
 151        struct nv_dma_v0 args = {};
 152        struct nouveau_channel *chan;
 153        u32 target;
 154        int ret;
 155
 156        chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL);
 157        if (!chan)
 158                return -ENOMEM;
 159
 160        chan->device = device;
 161        chan->drm = drm;
 162        chan->vmm = cli->svm.cli ? &cli->svm : &cli->vmm;
 163        atomic_set(&chan->killed, 0);
 164
 165        /* allocate memory for dma push buffer */
 166        target = TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED;
 167        if (nouveau_vram_pushbuf)
 168                target = TTM_PL_FLAG_VRAM;
 169
 170        ret = nouveau_bo_new(cli, size, 0, target, 0, 0, NULL, NULL,
 171                            &chan->push.buffer);
 172        if (ret == 0) {
 173                ret = nouveau_bo_pin(chan->push.buffer, target, false);
 174                if (ret == 0)
 175                        ret = nouveau_bo_map(chan->push.buffer);
 176        }
 177
 178        if (ret) {
 179                nouveau_channel_del(pchan);
 180                return ret;
 181        }
 182
 183        chan->chan._push.mem.object.parent = cli->base.object.parent;
 184        chan->chan._push.mem.object.client = &cli->base;
 185        chan->chan._push.mem.object.name = "chanPush";
 186        chan->chan._push.mem.object.map.ptr = chan->push.buffer->kmap.virtual;
 187        chan->chan._push.wait = nouveau_channel_wait;
 188        chan->chan._push.kick = nouveau_channel_kick;
 189        chan->chan.push = &chan->chan._push;
 190
 191        /* create dma object covering the *entire* memory space that the
 192         * pushbuf lives in, this is because the GEM code requires that
 193         * we be able to call out to other (indirect) push buffers
 194         */
 195        chan->push.addr = chan->push.buffer->offset;
 196
 197        if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
 198                ret = nouveau_vma_new(chan->push.buffer, chan->vmm,
 199                                      &chan->push.vma);
 200                if (ret) {
 201                        nouveau_channel_del(pchan);
 202                        return ret;
 203                }
 204
 205                chan->push.addr = chan->push.vma->addr;
 206
 207                if (device->info.family >= NV_DEVICE_INFO_V0_FERMI)
 208                        return 0;
 209
 210                args.target = NV_DMA_V0_TARGET_VM;
 211                args.access = NV_DMA_V0_ACCESS_VM;
 212                args.start = 0;
 213                args.limit = chan->vmm->vmm.limit - 1;
 214        } else
 215        if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
 216                if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
 217                        /* nv04 vram pushbuf hack, retarget to its location in
 218                         * the framebuffer bar rather than direct vram access..
 219                         * nfi why this exists, it came from the -nv ddx.
 220                         */
 221                        args.target = NV_DMA_V0_TARGET_PCI;
 222                        args.access = NV_DMA_V0_ACCESS_RDWR;
 223                        args.start = nvxx_device(device)->func->
 224                                resource_addr(nvxx_device(device), 1);
 225                        args.limit = args.start + device->info.ram_user - 1;
 226                } else {
 227                        args.target = NV_DMA_V0_TARGET_VRAM;
 228                        args.access = NV_DMA_V0_ACCESS_RDWR;
 229                        args.start = 0;
 230                        args.limit = device->info.ram_user - 1;
 231                }
 232        } else {
 233                if (chan->drm->agp.bridge) {
 234                        args.target = NV_DMA_V0_TARGET_AGP;
 235                        args.access = NV_DMA_V0_ACCESS_RDWR;
 236                        args.start = chan->drm->agp.base;
 237                        args.limit = chan->drm->agp.base +
 238                                     chan->drm->agp.size - 1;
 239                } else {
 240                        args.target = NV_DMA_V0_TARGET_VM;
 241                        args.access = NV_DMA_V0_ACCESS_RDWR;
 242                        args.start = 0;
 243                        args.limit = chan->vmm->vmm.limit - 1;
 244                }
 245        }
 246
 247        ret = nvif_object_ctor(&device->object, "abi16PushCtxDma", 0,
 248                               NV_DMA_FROM_MEMORY, &args, sizeof(args),
 249                               &chan->push.ctxdma);
 250        if (ret) {
 251                nouveau_channel_del(pchan);
 252                return ret;
 253        }
 254
 255        return 0;
 256}
 257
 258static int
 259nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
 260                    u64 runlist, bool priv, struct nouveau_channel **pchan)
 261{
 262        static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A,
 263                                        VOLTA_CHANNEL_GPFIFO_A,
 264                                        PASCAL_CHANNEL_GPFIFO_A,
 265                                        MAXWELL_CHANNEL_GPFIFO_A,
 266                                        KEPLER_CHANNEL_GPFIFO_B,
 267                                        KEPLER_CHANNEL_GPFIFO_A,
 268                                        FERMI_CHANNEL_GPFIFO,
 269                                        G82_CHANNEL_GPFIFO,
 270                                        NV50_CHANNEL_GPFIFO,
 271                                        0 };
 272        const u16 *oclass = oclasses;
 273        union {
 274                struct nv50_channel_gpfifo_v0 nv50;
 275                struct fermi_channel_gpfifo_v0 fermi;
 276                struct kepler_channel_gpfifo_a_v0 kepler;
 277                struct volta_channel_gpfifo_a_v0 volta;
 278        } args;
 279        struct nouveau_channel *chan;
 280        u32 size;
 281        int ret;
 282
 283        /* allocate dma push buffer */
 284        ret = nouveau_channel_prep(drm, device, 0x12000, &chan);
 285        *pchan = chan;
 286        if (ret)
 287                return ret;
 288
 289        /* create channel object */
 290        do {
 291                if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) {
 292                        args.volta.version = 0;
 293                        args.volta.ilength = 0x02000;
 294                        args.volta.ioffset = 0x10000 + chan->push.addr;
 295                        args.volta.runlist = runlist;
 296                        args.volta.vmm = nvif_handle(&chan->vmm->vmm.object);
 297                        args.volta.priv = priv;
 298                        size = sizeof(args.volta);
 299                } else
 300                if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
 301                        args.kepler.version = 0;
 302                        args.kepler.ilength = 0x02000;
 303                        args.kepler.ioffset = 0x10000 + chan->push.addr;
 304                        args.kepler.runlist = runlist;
 305                        args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object);
 306                        args.kepler.priv = priv;
 307                        size = sizeof(args.kepler);
 308                } else
 309                if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
 310                        args.fermi.version = 0;
 311                        args.fermi.ilength = 0x02000;
 312                        args.fermi.ioffset = 0x10000 + chan->push.addr;
 313                        args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object);
 314                        size = sizeof(args.fermi);
 315                } else {
 316                        args.nv50.version = 0;
 317                        args.nv50.ilength = 0x02000;
 318                        args.nv50.ioffset = 0x10000 + chan->push.addr;
 319                        args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
 320                        args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object);
 321                        size = sizeof(args.nv50);
 322                }
 323
 324                ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
 325                                       *oclass++, &args, size, &chan->user);
 326                if (ret == 0) {
 327                        if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) {
 328                                chan->chid = args.volta.chid;
 329                                chan->inst = args.volta.inst;
 330                                chan->token = args.volta.token;
 331                        } else
 332                        if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) {
 333                                chan->chid = args.kepler.chid;
 334                                chan->inst = args.kepler.inst;
 335                        } else
 336                        if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
 337                                chan->chid = args.fermi.chid;
 338                        } else {
 339                                chan->chid = args.nv50.chid;
 340                        }
 341                        return ret;
 342                }
 343        } while (*oclass);
 344
 345        nouveau_channel_del(pchan);
 346        return ret;
 347}
 348
 349static int
 350nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
 351                    struct nouveau_channel **pchan)
 352{
 353        static const u16 oclasses[] = { NV40_CHANNEL_DMA,
 354                                        NV17_CHANNEL_DMA,
 355                                        NV10_CHANNEL_DMA,
 356                                        NV03_CHANNEL_DMA,
 357                                        0 };
 358        const u16 *oclass = oclasses;
 359        struct nv03_channel_dma_v0 args;
 360        struct nouveau_channel *chan;
 361        int ret;
 362
 363        /* allocate dma push buffer */
 364        ret = nouveau_channel_prep(drm, device, 0x10000, &chan);
 365        *pchan = chan;
 366        if (ret)
 367                return ret;
 368
 369        /* create channel object */
 370        args.version = 0;
 371        args.pushbuf = nvif_handle(&chan->push.ctxdma);
 372        args.offset = chan->push.addr;
 373
 374        do {
 375                ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
 376                                       *oclass++, &args, sizeof(args),
 377                                       &chan->user);
 378                if (ret == 0) {
 379                        chan->chid = args.chid;
 380                        return ret;
 381                }
 382        } while (ret && *oclass);
 383
 384        nouveau_channel_del(pchan);
 385        return ret;
 386}
 387
 388static int
 389nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
 390{
 391        struct nvif_device *device = chan->device;
 392        struct nouveau_drm *drm = chan->drm;
 393        struct nv_dma_v0 args = {};
 394        int ret, i;
 395
 396        nvif_object_map(&chan->user, NULL, 0);
 397
 398        if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
 399                ret = nvif_notify_ctor(&chan->user, "abi16ChanKilled",
 400                                       nouveau_channel_killed,
 401                                       true, NV906F_V0_NTFY_KILLED,
 402                                       NULL, 0, 0, &chan->kill);
 403                if (ret == 0)
 404                        ret = nvif_notify_get(&chan->kill);
 405                if (ret) {
 406                        NV_ERROR(drm, "Failed to request channel kill "
 407                                      "notification: %d\n", ret);
 408                        return ret;
 409                }
 410        }
 411
 412        /* allocate dma objects to cover all allowed vram, and gart */
 413        if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
 414                if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
 415                        args.target = NV_DMA_V0_TARGET_VM;
 416                        args.access = NV_DMA_V0_ACCESS_VM;
 417                        args.start = 0;
 418                        args.limit = chan->vmm->vmm.limit - 1;
 419                } else {
 420                        args.target = NV_DMA_V0_TARGET_VRAM;
 421                        args.access = NV_DMA_V0_ACCESS_RDWR;
 422                        args.start = 0;
 423                        args.limit = device->info.ram_user - 1;
 424                }
 425
 426                ret = nvif_object_ctor(&chan->user, "abi16ChanVramCtxDma", vram,
 427                                       NV_DMA_IN_MEMORY, &args, sizeof(args),
 428                                       &chan->vram);
 429                if (ret)
 430                        return ret;
 431
 432                if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
 433                        args.target = NV_DMA_V0_TARGET_VM;
 434                        args.access = NV_DMA_V0_ACCESS_VM;
 435                        args.start = 0;
 436                        args.limit = chan->vmm->vmm.limit - 1;
 437                } else
 438                if (chan->drm->agp.bridge) {
 439                        args.target = NV_DMA_V0_TARGET_AGP;
 440                        args.access = NV_DMA_V0_ACCESS_RDWR;
 441                        args.start = chan->drm->agp.base;
 442                        args.limit = chan->drm->agp.base +
 443                                     chan->drm->agp.size - 1;
 444                } else {
 445                        args.target = NV_DMA_V0_TARGET_VM;
 446                        args.access = NV_DMA_V0_ACCESS_RDWR;
 447                        args.start = 0;
 448                        args.limit = chan->vmm->vmm.limit - 1;
 449                }
 450
 451                ret = nvif_object_ctor(&chan->user, "abi16ChanGartCtxDma", gart,
 452                                       NV_DMA_IN_MEMORY, &args, sizeof(args),
 453                                       &chan->gart);
 454                if (ret)
 455                        return ret;
 456        }
 457
 458        /* initialise dma tracking parameters */
 459        switch (chan->user.oclass & 0x00ff) {
 460        case 0x006b:
 461        case 0x006e:
 462                chan->user_put = 0x40;
 463                chan->user_get = 0x44;
 464                chan->dma.max = (0x10000 / 4) - 2;
 465                break;
 466        default:
 467                chan->user_put = 0x40;
 468                chan->user_get = 0x44;
 469                chan->user_get_hi = 0x60;
 470                chan->dma.ib_base =  0x10000 / 4;
 471                chan->dma.ib_max  = (0x02000 / 8) - 1;
 472                chan->dma.ib_put  = 0;
 473                chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put;
 474                chan->dma.max = chan->dma.ib_base;
 475                break;
 476        }
 477
 478        chan->dma.put = 0;
 479        chan->dma.cur = chan->dma.put;
 480        chan->dma.free = chan->dma.max - chan->dma.cur;
 481
 482        ret = PUSH_WAIT(chan->chan.push, NOUVEAU_DMA_SKIPS);
 483        if (ret)
 484                return ret;
 485
 486        for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
 487                PUSH_DATA(chan->chan.push, 0x00000000);
 488
 489        /* allocate software object class (used for fences on <= nv05) */
 490        if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
 491                ret = nvif_object_ctor(&chan->user, "abi16NvswFence", 0x006e,
 492                                       NVIF_CLASS_SW_NV04,
 493                                       NULL, 0, &chan->nvsw);
 494                if (ret)
 495                        return ret;
 496
 497                ret = PUSH_WAIT(chan->chan.push, 2);
 498                if (ret)
 499                        return ret;
 500
 501                PUSH_NVSQ(chan->chan.push, NV_SW, 0x0000, chan->nvsw.handle);
 502                PUSH_KICK(chan->chan.push);
 503        }
 504
 505        /* initialise synchronisation */
 506        return nouveau_fence(chan->drm)->context_new(chan);
 507}
 508
 509int
 510nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
 511                    u32 arg0, u32 arg1, bool priv,
 512                    struct nouveau_channel **pchan)
 513{
 514        struct nouveau_cli *cli = (void *)device->object.client;
 515        bool super;
 516        int ret;
 517
 518        /* hack until fencenv50 is fixed, and agp access relaxed */
 519        super = cli->base.super;
 520        cli->base.super = true;
 521
 522        ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
 523        if (ret) {
 524                NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
 525                ret = nouveau_channel_dma(drm, device, pchan);
 526                if (ret) {
 527                        NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
 528                        goto done;
 529                }
 530        }
 531
 532        ret = nouveau_channel_init(*pchan, arg0, arg1);
 533        if (ret) {
 534                NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
 535                nouveau_channel_del(pchan);
 536        }
 537
 538        ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
 539        if (ret)
 540                nouveau_channel_del(pchan);
 541
 542done:
 543        cli->base.super = super;
 544        return ret;
 545}
 546
 547int
 548nouveau_channels_init(struct nouveau_drm *drm)
 549{
 550        struct {
 551                struct nv_device_info_v1 m;
 552                struct {
 553                        struct nv_device_info_v1_data channels;
 554                } v;
 555        } args = {
 556                .m.version = 1,
 557                .m.count = sizeof(args.v) / sizeof(args.v.channels),
 558                .v.channels.mthd = NV_DEVICE_FIFO_CHANNELS,
 559        };
 560        struct nvif_object *device = &drm->client.device.object;
 561        int ret;
 562
 563        ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args));
 564        if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
 565                return -ENODEV;
 566
 567        drm->chan.nr = args.v.channels.data;
 568        drm->chan.context_base = dma_fence_context_alloc(drm->chan.nr);
 569        return 0;
 570}
 571