/*
* Copyright 2012 Red Hat Inc .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*
* Authors : Ben Skeggs
*/
#include "nv50.h"
#include <subdev/timer.h>
#include <nvif/class .h>
static const struct nvkm_bitfield nv50_gr_status[] = {
{ 0 x00000001, "BUSY" }, /* set when any bit is set */
{ 0 x00000002, "DISPATCH" },
{ 0 x00000004, "UNK2" },
{ 0 x00000008, "UNK3" },
{ 0 x00000010, "UNK4" },
{ 0 x00000020, "UNK5" },
{ 0 x00000040, "M2MF" },
{ 0 x00000080, "UNK7" },
{ 0 x00000100, "CTXPROG" },
{ 0 x00000200, "VFETCH" },
{ 0 x00000400, "CCACHE_PREGEOM" },
{ 0 x00000800, "STRMOUT_VATTR_POSTGEOM" },
{ 0 x00001000, "VCLIP" },
{ 0 x00002000, "RATTR_APLANE" },
{ 0 x00004000, "TRAST" },
{ 0 x00008000, "CLIPID" },
{ 0 x00010000, "ZCULL" },
{ 0 x00020000, "ENG2D" },
{ 0 x00040000, "RMASK" },
{ 0 x00080000, "TPC_RAST" },
{ 0 x00100000, "TPC_PROP" },
{ 0 x00200000, "TPC_TEX" },
{ 0 x00400000, "TPC_GEOM" },
{ 0 x00800000, "TPC_MP" },
{ 0 x01000000, "ROP" },
{}
};
static const struct nvkm_bitfield
nv50_gr_vstatus_0[] = {
{ 0 x01, "VFETCH" },
{ 0 x02, "CCACHE" },
{ 0 x04, "PREGEOM" },
{ 0 x08, "POSTGEOM" },
{ 0 x10, "VATTR" },
{ 0 x20, "STRMOUT" },
{ 0 x40, "VCLIP" },
{}
};
static const struct nvkm_bitfield
nv50_gr_vstatus_1[] = {
{ 0 x01, "TPC_RAST" },
{ 0 x02, "TPC_PROP" },
{ 0 x04, "TPC_TEX" },
{ 0 x08, "TPC_GEOM" },
{ 0 x10, "TPC_MP" },
{}
};
static const struct nvkm_bitfield
nv50_gr_vstatus_2[] = {
{ 0 x01, "RATTR" },
{ 0 x02, "APLANE" },
{ 0 x04, "TRAST" },
{ 0 x08, "CLIPID" },
{ 0 x10, "ZCULL" },
{ 0 x20, "ENG2D" },
{ 0 x40, "RMASK" },
{ 0 x80, "ROP" },
{}
};
static void
nvkm_gr_vstatus_print(struct nv50_gr *gr, int r,
const struct nvkm_bitfield *units, u32 status)
{
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
u32 stat = status;
u8 mask = 0 x00;
char msg[64 ];
int i;
for (i = 0 ; units[i].name && status; i++) {
if ((status & 7 ) == 1 )
mask |= (1 << i);
status >>= 3 ;
}
nvkm_snprintbf(msg, sizeof (msg), units, mask);
nvkm_error(subdev, "PGRAPH_VSTATUS%d: %08x [%s]\n" , r, stat, msg);
}
int
g84_gr_tlb_flush(struct nvkm_gr *base)
{
struct nv50_gr *gr = nv50_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_timer *tmr = device->timer;
bool idle, timeout = false ;
unsigned long flags;
char status[128 ];
u64 start;
u32 tmp;
spin_lock_irqsave(&gr->lock, flags);
nvkm_mask(device, 0 x400500, 0 x00000001, 0 x00000000);
start = nvkm_timer_read(tmr);
do {
idle = true ;
for (tmp = nvkm_rd32(device, 0 x400380); tmp && idle; tmp >>= 3 ) {
if ((tmp & 7 ) == 1 )
idle = false ;
}
for (tmp = nvkm_rd32(device, 0 x400384); tmp && idle; tmp >>= 3 ) {
if ((tmp & 7 ) == 1 )
idle = false ;
}
for (tmp = nvkm_rd32(device, 0 x400388); tmp && idle; tmp >>= 3 ) {
if ((tmp & 7 ) == 1 )
idle = false ;
}
} while (!idle &&
!(timeout = nvkm_timer_read(tmr) - start > 2000000000 ));
if (timeout) {
nvkm_error(subdev, "PGRAPH TLB flush idle timeout fail\n" );
tmp = nvkm_rd32(device, 0 x400700);
nvkm_snprintbf(status, sizeof (status), nv50_gr_status, tmp);
nvkm_error(subdev, "PGRAPH_STATUS %08x [%s]\n" , tmp, status);
nvkm_gr_vstatus_print(gr, 0 , nv50_gr_vstatus_0,
nvkm_rd32(device, 0 x400380));
nvkm_gr_vstatus_print(gr, 1 , nv50_gr_vstatus_1,
nvkm_rd32(device, 0 x400384));
nvkm_gr_vstatus_print(gr, 2 , nv50_gr_vstatus_2,
nvkm_rd32(device, 0 x400388));
}
nvkm_wr32(device, 0 x100c80, 0 x00000001);
nvkm_msec(device, 2000 ,
if (!(nvkm_rd32(device, 0 x100c80) & 0 x00000001))
break ;
);
nvkm_mask(device, 0 x400500, 0 x00000001, 0 x00000001);
spin_unlock_irqrestore(&gr->lock, flags);
return timeout ? -EBUSY : 0 ;
}
static const struct nvkm_gr_func
g84_gr = {
.init = nv50_gr_init,
.intr = nv50_gr_intr,
.chan_new = nv50_gr_chan_new,
.tlb_flush = g84_gr_tlb_flush,
.units = nv50_gr_units,
.sclass = {
{ -1 , -1 , NV_NULL_CLASS, &nv50_gr_object },
{ -1 , -1 , NV50_TWOD, &nv50_gr_object },
{ -1 , -1 , NV50_MEMORY_TO_MEMORY_FORMAT, &nv50_gr_object },
{ -1 , -1 , NV50_COMPUTE, &nv50_gr_object },
{ -1 , -1 , G82_TESLA, &nv50_gr_object },
{}
}
};
int
g84_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
{
return nv50_gr_new_(&g84_gr, device, type, inst, pgr);
}
Messung V0.5 in Prozent C=99 H=81 G=90
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-10-06)
¤
*© Formatika GbR, Deutschland