root/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c

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

DEFINITIONS

This source file includes following definitions.
  1. nv50_fb_ram_new
  2. nv50_fb_intr
  3. nv50_fb_oneinit
  4. nv50_fb_init
  5. nv50_fb_tags
  6. nv50_fb_dtor
  7. nv50_fb_new_
  8. nv50_fb_new

   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 "nv50.h"
  25 #include "ram.h"
  26 
  27 #include <core/client.h>
  28 #include <core/enum.h>
  29 #include <engine/fifo.h>
  30 
  31 static int
  32 nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram)
  33 {
  34         struct nv50_fb *fb = nv50_fb(base);
  35         return fb->func->ram_new(&fb->base, pram);
  36 }
  37 
  38 static const struct nvkm_enum vm_dispatch_subclients[] = {
  39         { 0x00000000, "GRCTX" },
  40         { 0x00000001, "NOTIFY" },
  41         { 0x00000002, "QUERY" },
  42         { 0x00000003, "COND" },
  43         { 0x00000004, "M2M_IN" },
  44         { 0x00000005, "M2M_OUT" },
  45         { 0x00000006, "M2M_NOTIFY" },
  46         {}
  47 };
  48 
  49 static const struct nvkm_enum vm_ccache_subclients[] = {
  50         { 0x00000000, "CB" },
  51         { 0x00000001, "TIC" },
  52         { 0x00000002, "TSC" },
  53         {}
  54 };
  55 
  56 static const struct nvkm_enum vm_prop_subclients[] = {
  57         { 0x00000000, "RT0" },
  58         { 0x00000001, "RT1" },
  59         { 0x00000002, "RT2" },
  60         { 0x00000003, "RT3" },
  61         { 0x00000004, "RT4" },
  62         { 0x00000005, "RT5" },
  63         { 0x00000006, "RT6" },
  64         { 0x00000007, "RT7" },
  65         { 0x00000008, "ZETA" },
  66         { 0x00000009, "LOCAL" },
  67         { 0x0000000a, "GLOBAL" },
  68         { 0x0000000b, "STACK" },
  69         { 0x0000000c, "DST2D" },
  70         {}
  71 };
  72 
  73 static const struct nvkm_enum vm_pfifo_subclients[] = {
  74         { 0x00000000, "PUSHBUF" },
  75         { 0x00000001, "SEMAPHORE" },
  76         {}
  77 };
  78 
  79 static const struct nvkm_enum vm_bar_subclients[] = {
  80         { 0x00000000, "FB" },
  81         { 0x00000001, "IN" },
  82         {}
  83 };
  84 
  85 static const struct nvkm_enum vm_client[] = {
  86         { 0x00000000, "STRMOUT" },
  87         { 0x00000003, "DISPATCH", vm_dispatch_subclients },
  88         { 0x00000004, "PFIFO_WRITE" },
  89         { 0x00000005, "CCACHE", vm_ccache_subclients },
  90         { 0x00000006, "PMSPPP" },
  91         { 0x00000007, "CLIPID" },
  92         { 0x00000008, "PFIFO_READ" },
  93         { 0x00000009, "VFETCH" },
  94         { 0x0000000a, "TEXTURE" },
  95         { 0x0000000b, "PROP", vm_prop_subclients },
  96         { 0x0000000c, "PVP" },
  97         { 0x0000000d, "PBSP" },
  98         { 0x0000000e, "PCRYPT" },
  99         { 0x0000000f, "PCOUNTER" },
 100         { 0x00000011, "PDAEMON" },
 101         {}
 102 };
 103 
 104 static const struct nvkm_enum vm_engine[] = {
 105         { 0x00000000, "PGRAPH" },
 106         { 0x00000001, "PVP" },
 107         { 0x00000004, "PEEPHOLE" },
 108         { 0x00000005, "PFIFO", vm_pfifo_subclients },
 109         { 0x00000006, "BAR", vm_bar_subclients },
 110         { 0x00000008, "PMSPPP" },
 111         { 0x00000008, "PMPEG" },
 112         { 0x00000009, "PBSP" },
 113         { 0x0000000a, "PCRYPT" },
 114         { 0x0000000b, "PCOUNTER" },
 115         { 0x0000000c, "SEMAPHORE_BG" },
 116         { 0x0000000d, "PCE0" },
 117         { 0x0000000e, "PMU" },
 118         {}
 119 };
 120 
 121 static const struct nvkm_enum vm_fault[] = {
 122         { 0x00000000, "PT_NOT_PRESENT" },
 123         { 0x00000001, "PT_TOO_SHORT" },
 124         { 0x00000002, "PAGE_NOT_PRESENT" },
 125         { 0x00000003, "PAGE_SYSTEM_ONLY" },
 126         { 0x00000004, "PAGE_READ_ONLY" },
 127         { 0x00000006, "NULL_DMAOBJ" },
 128         { 0x00000007, "WRONG_MEMTYPE" },
 129         { 0x0000000b, "VRAM_LIMIT" },
 130         { 0x0000000f, "DMAOBJ_LIMIT" },
 131         {}
 132 };
 133 
 134 static void
 135 nv50_fb_intr(struct nvkm_fb *base)
 136 {
 137         struct nv50_fb *fb = nv50_fb(base);
 138         struct nvkm_subdev *subdev = &fb->base.subdev;
 139         struct nvkm_device *device = subdev->device;
 140         struct nvkm_fifo *fifo = device->fifo;
 141         struct nvkm_fifo_chan *chan;
 142         const struct nvkm_enum *en, *re, *cl, *sc;
 143         u32 trap[6], idx, inst;
 144         u8 st0, st1, st2, st3;
 145         unsigned long flags;
 146         int i;
 147 
 148         idx = nvkm_rd32(device, 0x100c90);
 149         if (!(idx & 0x80000000))
 150                 return;
 151         idx &= 0x00ffffff;
 152 
 153         for (i = 0; i < 6; i++) {
 154                 nvkm_wr32(device, 0x100c90, idx | i << 24);
 155                 trap[i] = nvkm_rd32(device, 0x100c94);
 156         }
 157         nvkm_wr32(device, 0x100c90, idx | 0x80000000);
 158 
 159         /* decode status bits into something more useful */
 160         if (device->chipset  < 0xa3 ||
 161             device->chipset == 0xaa || device->chipset == 0xac) {
 162                 st0 = (trap[0] & 0x0000000f) >> 0;
 163                 st1 = (trap[0] & 0x000000f0) >> 4;
 164                 st2 = (trap[0] & 0x00000f00) >> 8;
 165                 st3 = (trap[0] & 0x0000f000) >> 12;
 166         } else {
 167                 st0 = (trap[0] & 0x000000ff) >> 0;
 168                 st1 = (trap[0] & 0x0000ff00) >> 8;
 169                 st2 = (trap[0] & 0x00ff0000) >> 16;
 170                 st3 = (trap[0] & 0xff000000) >> 24;
 171         }
 172         inst = ((trap[2] << 16) | trap[1]) << 12;
 173 
 174         en = nvkm_enum_find(vm_engine, st0);
 175         re = nvkm_enum_find(vm_fault , st1);
 176         cl = nvkm_enum_find(vm_client, st2);
 177         if      (cl && cl->data) sc = nvkm_enum_find(cl->data, st3);
 178         else if (en && en->data) sc = nvkm_enum_find(en->data, st3);
 179         else                     sc = NULL;
 180 
 181         chan = nvkm_fifo_chan_inst(fifo, inst, &flags);
 182         nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] "
 183                            "engine %02x [%s] client %02x [%s] "
 184                            "subclient %02x [%s] reason %08x [%s]\n",
 185                    (trap[5] & 0x00000100) ? "read" : "write",
 186                    trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
 187                    chan ? chan->chid : -1, inst,
 188                    chan ? chan->object.client->name : "unknown",
 189                    st0, en ? en->name : "",
 190                    st2, cl ? cl->name : "", st3, sc ? sc->name : "",
 191                    st1, re ? re->name : "");
 192         nvkm_fifo_chan_put(fifo, flags, &chan);
 193 }
 194 
 195 static int
 196 nv50_fb_oneinit(struct nvkm_fb *base)
 197 {
 198         struct nv50_fb *fb = nv50_fb(base);
 199         struct nvkm_device *device = fb->base.subdev.device;
 200 
 201         fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
 202         if (fb->r100c08_page) {
 203                 fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
 204                                            PAGE_SIZE, DMA_BIDIRECTIONAL);
 205                 if (dma_mapping_error(device->dev, fb->r100c08))
 206                         return -EFAULT;
 207         }
 208 
 209         return 0;
 210 }
 211 
 212 static void
 213 nv50_fb_init(struct nvkm_fb *base)
 214 {
 215         struct nv50_fb *fb = nv50_fb(base);
 216         struct nvkm_device *device = fb->base.subdev.device;
 217 
 218         /* Not a clue what this is exactly.  Without pointing it at a
 219          * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
 220          * cause IOMMU "read from address 0" errors (rh#561267)
 221          */
 222         nvkm_wr32(device, 0x100c08, fb->r100c08 >> 8);
 223 
 224         /* This is needed to get meaningful information from 100c90
 225          * on traps. No idea what these values mean exactly. */
 226         nvkm_wr32(device, 0x100c90, fb->func->trap);
 227 }
 228 
 229 static u32
 230 nv50_fb_tags(struct nvkm_fb *base)
 231 {
 232         struct nv50_fb *fb = nv50_fb(base);
 233         if (fb->func->tags)
 234                 return fb->func->tags(&fb->base);
 235         return 0;
 236 }
 237 
 238 static void *
 239 nv50_fb_dtor(struct nvkm_fb *base)
 240 {
 241         struct nv50_fb *fb = nv50_fb(base);
 242         struct nvkm_device *device = fb->base.subdev.device;
 243 
 244         if (fb->r100c08_page) {
 245                 dma_unmap_page(device->dev, fb->r100c08, PAGE_SIZE,
 246                                DMA_BIDIRECTIONAL);
 247                 __free_page(fb->r100c08_page);
 248         }
 249 
 250         return fb;
 251 }
 252 
 253 static const struct nvkm_fb_func
 254 nv50_fb_ = {
 255         .dtor = nv50_fb_dtor,
 256         .tags = nv50_fb_tags,
 257         .oneinit = nv50_fb_oneinit,
 258         .init = nv50_fb_init,
 259         .intr = nv50_fb_intr,
 260         .ram_new = nv50_fb_ram_new,
 261 };
 262 
 263 int
 264 nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device,
 265              int index, struct nvkm_fb **pfb)
 266 {
 267         struct nv50_fb *fb;
 268 
 269         if (!(fb = kzalloc(sizeof(*fb), GFP_KERNEL)))
 270                 return -ENOMEM;
 271         nvkm_fb_ctor(&nv50_fb_, device, index, &fb->base);
 272         fb->func = func;
 273         *pfb = &fb->base;
 274 
 275         return 0;
 276 }
 277 
 278 static const struct nv50_fb_func
 279 nv50_fb = {
 280         .ram_new = nv50_ram_new,
 281         .tags = nv20_fb_tags,
 282         .trap = 0x000707ff,
 283 };
 284 
 285 int
 286 nv50_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
 287 {
 288         return nv50_fb_new_(&nv50_fb, device, index, pfb);
 289 }

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