linux/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.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 "gf100.h"
  25
  26#include <core/memory.h>
  27#include <core/option.h>
  28#include <subdev/fb.h>
  29#include <subdev/mmu.h>
  30
  31struct nvkm_vmm *
  32gf100_bar_bar1_vmm(struct nvkm_bar *base)
  33{
  34        return gf100_bar(base)->bar[1].vmm;
  35}
  36
  37void
  38gf100_bar_bar1_wait(struct nvkm_bar *base)
  39{
  40        /* NFI why it's twice. */
  41        nvkm_bar_flush(base);
  42        nvkm_bar_flush(base);
  43}
  44
  45void
  46gf100_bar_bar1_fini(struct nvkm_bar *bar)
  47{
  48        nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000);
  49}
  50
  51void
  52gf100_bar_bar1_init(struct nvkm_bar *base)
  53{
  54        struct nvkm_device *device = base->subdev.device;
  55        struct gf100_bar *bar = gf100_bar(base);
  56        const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
  57        nvkm_wr32(device, 0x001704, 0x80000000 | addr);
  58}
  59
  60struct nvkm_vmm *
  61gf100_bar_bar2_vmm(struct nvkm_bar *base)
  62{
  63        return gf100_bar(base)->bar[0].vmm;
  64}
  65
  66void
  67gf100_bar_bar2_fini(struct nvkm_bar *bar)
  68{
  69        nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000);
  70}
  71
  72void
  73gf100_bar_bar2_init(struct nvkm_bar *base)
  74{
  75        struct nvkm_device *device = base->subdev.device;
  76        struct gf100_bar *bar = gf100_bar(base);
  77        u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
  78        if (bar->bar2_halve)
  79                addr |= 0x40000000;
  80        nvkm_wr32(device, 0x001714, 0x80000000 | addr);
  81}
  82
  83static int
  84gf100_bar_oneinit_bar(struct gf100_bar *bar, struct gf100_barN *bar_vm,
  85                      struct lock_class_key *key, int bar_nr)
  86{
  87        struct nvkm_device *device = bar->base.subdev.device;
  88        resource_size_t bar_len;
  89        int ret;
  90
  91        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false,
  92                              &bar_vm->inst);
  93        if (ret)
  94                return ret;
  95
  96        bar_len = device->func->resource_size(device, bar_nr);
  97        if (bar_nr == 3 && bar->bar2_halve)
  98                bar_len >>= 1;
  99
 100        ret = nvkm_vmm_new(device, 0, bar_len, NULL, 0, key,
 101                           (bar_nr == 3) ? "bar2" : "bar1", &bar_vm->vmm);
 102        if (ret)
 103                return ret;
 104
 105        atomic_inc(&bar_vm->vmm->engref[NVKM_SUBDEV_BAR]);
 106        bar_vm->vmm->debug = bar->base.subdev.debug;
 107
 108        /*
 109         * Bootstrap page table lookup.
 110         */
 111        if (bar_nr == 3) {
 112                ret = nvkm_vmm_boot(bar_vm->vmm);
 113                if (ret)
 114                        return ret;
 115        }
 116
 117        return nvkm_vmm_join(bar_vm->vmm, bar_vm->inst);
 118}
 119
 120int
 121gf100_bar_oneinit(struct nvkm_bar *base)
 122{
 123        static struct lock_class_key bar1_lock;
 124        static struct lock_class_key bar2_lock;
 125        struct gf100_bar *bar = gf100_bar(base);
 126        int ret;
 127
 128        /* BAR2 */
 129        if (bar->base.func->bar2.init) {
 130                ret = gf100_bar_oneinit_bar(bar, &bar->bar[0], &bar2_lock, 3);
 131                if (ret)
 132                        return ret;
 133
 134                bar->base.subdev.oneinit = true;
 135                nvkm_bar_bar2_init(bar->base.subdev.device);
 136        }
 137
 138        /* BAR1 */
 139        ret = gf100_bar_oneinit_bar(bar, &bar->bar[1], &bar1_lock, 1);
 140        if (ret)
 141                return ret;
 142
 143        return 0;
 144}
 145
 146void *
 147gf100_bar_dtor(struct nvkm_bar *base)
 148{
 149        struct gf100_bar *bar = gf100_bar(base);
 150
 151        nvkm_vmm_part(bar->bar[1].vmm, bar->bar[1].inst);
 152        nvkm_vmm_unref(&bar->bar[1].vmm);
 153        nvkm_memory_unref(&bar->bar[1].inst);
 154
 155        nvkm_vmm_part(bar->bar[0].vmm, bar->bar[0].inst);
 156        nvkm_vmm_unref(&bar->bar[0].vmm);
 157        nvkm_memory_unref(&bar->bar[0].inst);
 158        return bar;
 159}
 160
 161int
 162gf100_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device,
 163               int index, struct nvkm_bar **pbar)
 164{
 165        struct gf100_bar *bar;
 166        if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL)))
 167                return -ENOMEM;
 168        nvkm_bar_ctor(func, device, index, &bar->base);
 169        bar->bar2_halve = nvkm_boolopt(device->cfgopt, "NvBar2Halve", false);
 170        *pbar = &bar->base;
 171        return 0;
 172}
 173
 174static const struct nvkm_bar_func
 175gf100_bar_func = {
 176        .dtor = gf100_bar_dtor,
 177        .oneinit = gf100_bar_oneinit,
 178        .bar1.init = gf100_bar_bar1_init,
 179        .bar1.fini = gf100_bar_bar1_fini,
 180        .bar1.wait = gf100_bar_bar1_wait,
 181        .bar1.vmm = gf100_bar_bar1_vmm,
 182        .bar2.init = gf100_bar_bar2_init,
 183        .bar2.fini = gf100_bar_bar2_fini,
 184        .bar2.wait = gf100_bar_bar1_wait,
 185        .bar2.vmm = gf100_bar_bar2_vmm,
 186        .flush = g84_bar_flush,
 187};
 188
 189int
 190gf100_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar)
 191{
 192        return gf100_bar_new_(&gf100_bar_func, device, index, pbar);
 193}
 194