nouveau: Use a sw method instead of notify interrupt to signal fence completion.

main
Ben Skeggs 2007-11-05 05:42:08 +11:00
parent 9096d50df7
commit 5092865601
2 changed files with 67 additions and 46 deletions

View File

@ -67,9 +67,7 @@ nouveau_fence_emit(struct drm_device *dev, uint32_t class, uint32_t flags,
DRM_DEBUG("emit 0x%08x\n", *breadcrumb);
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1);
OUT_RING (*breadcrumb);
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
OUT_RING (NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN);
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
BEGIN_RING(NvSubM2MF, 0x0150, 1);
OUT_RING (0);
FIRE_RING ();

View File

@ -244,39 +244,53 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
return 0;
}
struct nouveau_pgraph_trap {
int channel;
int class;
int subc, mthd, size;
uint32_t data, data2;
};
static void
nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id)
nouveau_graph_trap_info(struct drm_device *dev,
struct nouveau_pgraph_trap *trap)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t address;
uint32_t channel, class;
uint32_t method, subc, data, data2;
if (nouveau_graph_trapped_channel(dev, &trap->channel))
trap->channel = -1;
address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
trap->mthd = address & 0x1FFC;
trap->data = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
if (dev_priv->card_type < NV_10) {
trap->subc = (address >> 13) & 0x7;
} else {
trap->subc = (address >> 16) & 0x7;
trap->data2 = NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
}
if (dev_priv->card_type < NV_10) {
trap->class = NV_READ(0x400180 + trap->subc*4) & 0xFF;
} else if (dev_priv->card_type < NV_40) {
trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFF;
} else if (dev_priv->card_type < NV_50) {
trap->class = NV_READ(0x400160 + trap->subc*4) & 0xFFFF;
} else {
trap->class = NV_READ(0x400814);
}
}
static void
nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
struct nouveau_pgraph_trap *trap)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t nsource, nstatus;
if (nouveau_graph_trapped_channel(dev, &channel))
channel = -1;
data = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
method = address & 0x1FFC;
if (dev_priv->card_type < NV_10) {
subc = (address >> 13) & 0x7;
data2= 0;
} else {
subc = (address >> 16) & 0x7;
data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
}
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
if (dev_priv->card_type < NV_10) {
class = NV_READ(0x400180 + subc*4) & 0xFF;
} else if (dev_priv->card_type < NV_40) {
class = NV_READ(0x400160 + subc*4) & 0xFFF;
} else if (dev_priv->card_type < NV_50) {
class = NV_READ(0x400160 + subc*4) & 0xFFFF;
} else {
class = NV_READ(0x400814);
}
DRM_INFO("%s - nSource:", id);
nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
@ -291,37 +305,29 @@ nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id)
printk("\n");
DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n",
id, channel, subc, class, method, data2, data);
id, trap->channel, trap->subc, trap->class, trap->mthd,
trap->data2, trap->data);
}
static inline void
nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_trap trap;
int unhandled = 0;
if (nsource & NV03_PGRAPH_NSOURCE_NOTIFICATION && dev_priv->ttm) {
int channel;
if (!nouveau_graph_trapped_channel(dev, &channel)) {
nouveau_fence_handler(dev, channel);
}
} else
if (dev_priv->card_type == NV_04 &&
(nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
uint32_t class, mthd;
nouveau_graph_trap_info(dev, &trap);
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
/* NV4 (nvidia TNT 1) reports software methods with
* PGRAPH NOTIFY ILLEGAL_MTHD
*/
mthd = NV_READ(NV04_PGRAPH_TRAPPED_ADDR) & 0x1FFC;
class = NV_READ(NV04_PGRAPH_CTX_SWITCH1) & 0xFFF;
DRM_DEBUG("Got NV04 software method method %x for class %#x\n",
mthd, class);
trap.mthd, trap.class);
if (nouveau_sw_method_execute(dev, class, mthd)) {
if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
DRM_ERROR("Unable to execute NV04 software method %x "
"for object class %x. Please report.\n",
mthd, class);
trap.mthd, trap.class);
unhandled = 1;
}
} else {
@ -329,13 +335,30 @@ nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
}
if (unhandled)
nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY");
nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
}
static inline void
nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
{
nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR");
struct nouveau_pgraph_trap trap;
int unhandled = 0;
nouveau_graph_trap_info(dev, &trap);
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
if (trap.channel >= 0 && trap.mthd == 0x0150) {
nouveau_fence_handler(dev, trap.channel);
} else
if (nouveau_sw_method_execute(dev, trap.class, trap.mthd)) {
unhandled = 1;
}
} else {
unhandled = 1;
}
if (unhandled)
nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
}
static inline void