Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs
0023  */
0024 #include "gf100.h"
0025 
0026 #include <core/memory.h>
0027 #include <core/option.h>
0028 #include <subdev/fb.h>
0029 #include <subdev/mmu.h>
0030 
0031 struct nvkm_vmm *
0032 gf100_bar_bar1_vmm(struct nvkm_bar *base)
0033 {
0034     return gf100_bar(base)->bar[1].vmm;
0035 }
0036 
0037 void
0038 gf100_bar_bar1_wait(struct nvkm_bar *base)
0039 {
0040     /* NFI why it's twice. */
0041     nvkm_bar_flush(base);
0042     nvkm_bar_flush(base);
0043 }
0044 
0045 void
0046 gf100_bar_bar1_fini(struct nvkm_bar *bar)
0047 {
0048     nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000);
0049 }
0050 
0051 void
0052 gf100_bar_bar1_init(struct nvkm_bar *base)
0053 {
0054     struct nvkm_device *device = base->subdev.device;
0055     struct gf100_bar *bar = gf100_bar(base);
0056     const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
0057     nvkm_wr32(device, 0x001704, 0x80000000 | addr);
0058 }
0059 
0060 struct nvkm_vmm *
0061 gf100_bar_bar2_vmm(struct nvkm_bar *base)
0062 {
0063     return gf100_bar(base)->bar[0].vmm;
0064 }
0065 
0066 void
0067 gf100_bar_bar2_fini(struct nvkm_bar *bar)
0068 {
0069     nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000);
0070 }
0071 
0072 void
0073 gf100_bar_bar2_init(struct nvkm_bar *base)
0074 {
0075     struct nvkm_device *device = base->subdev.device;
0076     struct gf100_bar *bar = gf100_bar(base);
0077     u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
0078     if (bar->bar2_halve)
0079         addr |= 0x40000000;
0080     nvkm_wr32(device, 0x001714, 0x80000000 | addr);
0081 }
0082 
0083 static int
0084 gf100_bar_oneinit_bar(struct gf100_bar *bar, struct gf100_barN *bar_vm,
0085               struct lock_class_key *key, int bar_nr)
0086 {
0087     struct nvkm_device *device = bar->base.subdev.device;
0088     resource_size_t bar_len;
0089     int ret;
0090 
0091     ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false,
0092                   &bar_vm->inst);
0093     if (ret)
0094         return ret;
0095 
0096     bar_len = device->func->resource_size(device, bar_nr);
0097     if (!bar_len)
0098         return -ENOMEM;
0099     if (bar_nr == 3 && bar->bar2_halve)
0100         bar_len >>= 1;
0101 
0102     ret = nvkm_vmm_new(device, 0, bar_len, NULL, 0, key,
0103                (bar_nr == 3) ? "bar2" : "bar1", &bar_vm->vmm);
0104     if (ret)
0105         return ret;
0106 
0107     atomic_inc(&bar_vm->vmm->engref[NVKM_SUBDEV_BAR]);
0108     bar_vm->vmm->debug = bar->base.subdev.debug;
0109 
0110     /*
0111      * Bootstrap page table lookup.
0112      */
0113     if (bar_nr == 3) {
0114         ret = nvkm_vmm_boot(bar_vm->vmm);
0115         if (ret)
0116             return ret;
0117     }
0118 
0119     return nvkm_vmm_join(bar_vm->vmm, bar_vm->inst);
0120 }
0121 
0122 int
0123 gf100_bar_oneinit(struct nvkm_bar *base)
0124 {
0125     static struct lock_class_key bar1_lock;
0126     static struct lock_class_key bar2_lock;
0127     struct gf100_bar *bar = gf100_bar(base);
0128     int ret;
0129 
0130     /* BAR2 */
0131     if (bar->base.func->bar2.init) {
0132         ret = gf100_bar_oneinit_bar(bar, &bar->bar[0], &bar2_lock, 3);
0133         if (ret)
0134             return ret;
0135 
0136         bar->base.subdev.oneinit = true;
0137         nvkm_bar_bar2_init(bar->base.subdev.device);
0138     }
0139 
0140     /* BAR1 */
0141     ret = gf100_bar_oneinit_bar(bar, &bar->bar[1], &bar1_lock, 1);
0142     if (ret)
0143         return ret;
0144 
0145     return 0;
0146 }
0147 
0148 void *
0149 gf100_bar_dtor(struct nvkm_bar *base)
0150 {
0151     struct gf100_bar *bar = gf100_bar(base);
0152 
0153     nvkm_vmm_part(bar->bar[1].vmm, bar->bar[1].inst);
0154     nvkm_vmm_unref(&bar->bar[1].vmm);
0155     nvkm_memory_unref(&bar->bar[1].inst);
0156 
0157     nvkm_vmm_part(bar->bar[0].vmm, bar->bar[0].inst);
0158     nvkm_vmm_unref(&bar->bar[0].vmm);
0159     nvkm_memory_unref(&bar->bar[0].inst);
0160     return bar;
0161 }
0162 
0163 int
0164 gf100_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device,
0165            enum nvkm_subdev_type type, int inst, struct nvkm_bar **pbar)
0166 {
0167     struct gf100_bar *bar;
0168     if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL)))
0169         return -ENOMEM;
0170     nvkm_bar_ctor(func, device, type, inst, &bar->base);
0171     bar->bar2_halve = nvkm_boolopt(device->cfgopt, "NvBar2Halve", false);
0172     *pbar = &bar->base;
0173     return 0;
0174 }
0175 
0176 static const struct nvkm_bar_func
0177 gf100_bar_func = {
0178     .dtor = gf100_bar_dtor,
0179     .oneinit = gf100_bar_oneinit,
0180     .bar1.init = gf100_bar_bar1_init,
0181     .bar1.fini = gf100_bar_bar1_fini,
0182     .bar1.wait = gf100_bar_bar1_wait,
0183     .bar1.vmm = gf100_bar_bar1_vmm,
0184     .bar2.init = gf100_bar_bar2_init,
0185     .bar2.fini = gf100_bar_bar2_fini,
0186     .bar2.wait = gf100_bar_bar1_wait,
0187     .bar2.vmm = gf100_bar_bar2_vmm,
0188     .flush = g84_bar_flush,
0189 };
0190 
0191 int
0192 gf100_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0193           struct nvkm_bar **pbar)
0194 {
0195     return gf100_bar_new_(&gf100_bar_func, device, type, inst, pbar);
0196 }