linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/g84.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 "nv50.h"
  25
  26#include <subdev/timer.h>
  27
  28#include <nvif/class.h>
  29
  30static const struct nvkm_bitfield nv50_gr_status[] = {
  31        { 0x00000001, "BUSY" }, /* set when any bit is set */
  32        { 0x00000002, "DISPATCH" },
  33        { 0x00000004, "UNK2" },
  34        { 0x00000008, "UNK3" },
  35        { 0x00000010, "UNK4" },
  36        { 0x00000020, "UNK5" },
  37        { 0x00000040, "M2MF" },
  38        { 0x00000080, "UNK7" },
  39        { 0x00000100, "CTXPROG" },
  40        { 0x00000200, "VFETCH" },
  41        { 0x00000400, "CCACHE_PREGEOM" },
  42        { 0x00000800, "STRMOUT_VATTR_POSTGEOM" },
  43        { 0x00001000, "VCLIP" },
  44        { 0x00002000, "RATTR_APLANE" },
  45        { 0x00004000, "TRAST" },
  46        { 0x00008000, "CLIPID" },
  47        { 0x00010000, "ZCULL" },
  48        { 0x00020000, "ENG2D" },
  49        { 0x00040000, "RMASK" },
  50        { 0x00080000, "TPC_RAST" },
  51        { 0x00100000, "TPC_PROP" },
  52        { 0x00200000, "TPC_TEX" },
  53        { 0x00400000, "TPC_GEOM" },
  54        { 0x00800000, "TPC_MP" },
  55        { 0x01000000, "ROP" },
  56        {}
  57};
  58
  59static const struct nvkm_bitfield
  60nv50_gr_vstatus_0[] = {
  61        { 0x01, "VFETCH" },
  62        { 0x02, "CCACHE" },
  63        { 0x04, "PREGEOM" },
  64        { 0x08, "POSTGEOM" },
  65        { 0x10, "VATTR" },
  66        { 0x20, "STRMOUT" },
  67        { 0x40, "VCLIP" },
  68        {}
  69};
  70
  71static const struct nvkm_bitfield
  72nv50_gr_vstatus_1[] = {
  73        { 0x01, "TPC_RAST" },
  74        { 0x02, "TPC_PROP" },
  75        { 0x04, "TPC_TEX" },
  76        { 0x08, "TPC_GEOM" },
  77        { 0x10, "TPC_MP" },
  78        {}
  79};
  80
  81static const struct nvkm_bitfield
  82nv50_gr_vstatus_2[] = {
  83        { 0x01, "RATTR" },
  84        { 0x02, "APLANE" },
  85        { 0x04, "TRAST" },
  86        { 0x08, "CLIPID" },
  87        { 0x10, "ZCULL" },
  88        { 0x20, "ENG2D" },
  89        { 0x40, "RMASK" },
  90        { 0x80, "ROP" },
  91        {}
  92};
  93
  94static void
  95nvkm_gr_vstatus_print(struct nv50_gr *gr, int r,
  96                      const struct nvkm_bitfield *units, u32 status)
  97{
  98        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
  99        u32 stat = status;
 100        u8  mask = 0x00;
 101        char msg[64];
 102        int i;
 103
 104        for (i = 0; units[i].name && status; i++) {
 105                if ((status & 7) == 1)
 106                        mask |= (1 << i);
 107                status >>= 3;
 108        }
 109
 110        nvkm_snprintbf(msg, sizeof(msg), units, mask);
 111        nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n", r, stat, msg);
 112}
 113
 114int
 115g84_gr_tlb_flush(struct nvkm_gr *base)
 116{
 117        struct nv50_gr *gr = nv50_gr(base);
 118        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 119        struct nvkm_device *device = subdev->device;
 120        struct nvkm_timer *tmr = device->timer;
 121        bool idle, timeout = false;
 122        unsigned long flags;
 123        char status[128];
 124        u64 start;
 125        u32 tmp;
 126
 127        spin_lock_irqsave(&gr->lock, flags);
 128        nvkm_mask(device, 0x400500, 0x00000001, 0x00000000);
 129
 130        start = nvkm_timer_read(tmr);
 131        do {
 132                idle = true;
 133
 134                for (tmp = nvkm_rd32(device, 0x400380); tmp && idle; tmp >>= 3) {
 135                        if ((tmp & 7) == 1)
 136                                idle = false;
 137                }
 138
 139                for (tmp = nvkm_rd32(device, 0x400384); tmp && idle; tmp >>= 3) {
 140                        if ((tmp & 7) == 1)
 141                                idle = false;
 142                }
 143
 144                for (tmp = nvkm_rd32(device, 0x400388); tmp && idle; tmp >>= 3) {
 145                        if ((tmp & 7) == 1)
 146                                idle = false;
 147                }
 148        } while (!idle &&
 149                 !(timeout = nvkm_timer_read(tmr) - start > 2000000000));
 150
 151        if (timeout) {
 152                nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n");
 153
 154                tmp = nvkm_rd32(device, 0x400700);
 155                nvkm_snprintbf(status, sizeof(status), nv50_gr_status, tmp);
 156                nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n", tmp, status);
 157
 158                nvkm_gr_vstatus_print(gr, 0, nv50_gr_vstatus_0,
 159                                       nvkm_rd32(device, 0x400380));
 160                nvkm_gr_vstatus_print(gr, 1, nv50_gr_vstatus_1,
 161                                       nvkm_rd32(device, 0x400384));
 162                nvkm_gr_vstatus_print(gr, 2, nv50_gr_vstatus_2,
 163                                       nvkm_rd32(device, 0x400388));
 164        }
 165
 166
 167        nvkm_wr32(device, 0x100c80, 0x00000001);
 168        nvkm_msec(device, 2000,
 169                if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
 170                        break;
 171        );
 172        nvkm_mask(device, 0x400500, 0x00000001, 0x00000001);
 173        spin_unlock_irqrestore(&gr->lock, flags);
 174        return timeout ? -EBUSY : 0;
 175}
 176
 177static const struct nvkm_gr_func
 178g84_gr = {
 179        .init = nv50_gr_init,
 180        .intr = nv50_gr_intr,
 181        .chan_new = nv50_gr_chan_new,
 182        .tlb_flush = g84_gr_tlb_flush,
 183        .units = nv50_gr_units,
 184        .sclass = {
 185                { -1, -1, NV_NULL_CLASS, &nv50_gr_object },
 186                { -1, -1, NV50_TWOD, &nv50_gr_object },
 187                { -1, -1, NV50_MEMORY_TO_MEMORY_FORMAT, &nv50_gr_object },
 188                { -1, -1, NV50_COMPUTE, &nv50_gr_object },
 189                { -1, -1, G82_TESLA, &nv50_gr_object },
 190                {}
 191        }
 192};
 193
 194int
 195g84_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
 196{
 197        return nv50_gr_new_(&g84_gr, device, type, inst, pgr);
 198}
 199