nouveau: Use a sw method instead of notify interrupt to signal fence completion.
parent
9096d50df7
commit
5092865601
|
@ -67,9 +67,7 @@ nouveau_fence_emit(struct drm_device *dev, uint32_t class, uint32_t flags,
|
||||||
DRM_DEBUG("emit 0x%08x\n", *breadcrumb);
|
DRM_DEBUG("emit 0x%08x\n", *breadcrumb);
|
||||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1);
|
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_REF, 1);
|
||||||
OUT_RING (*breadcrumb);
|
OUT_RING (*breadcrumb);
|
||||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
|
BEGIN_RING(NvSubM2MF, 0x0150, 1);
|
||||||
OUT_RING (NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN);
|
|
||||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
|
|
||||||
OUT_RING (0);
|
OUT_RING (0);
|
||||||
FIRE_RING ();
|
FIRE_RING ();
|
||||||
|
|
||||||
|
|
|
@ -244,39 +244,53 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct nouveau_pgraph_trap {
|
||||||
|
int channel;
|
||||||
|
int class;
|
||||||
|
int subc, mthd, size;
|
||||||
|
uint32_t data, data2;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
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;
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
uint32_t address;
|
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;
|
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);
|
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
|
||||||
nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
|
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);
|
DRM_INFO("%s - nSource:", id);
|
||||||
nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
|
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");
|
printk("\n");
|
||||||
|
|
||||||
DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\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
|
static inline void
|
||||||
nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
|
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;
|
int unhandled = 0;
|
||||||
|
|
||||||
if (nsource & NV03_PGRAPH_NSOURCE_NOTIFICATION && dev_priv->ttm) {
|
nouveau_graph_trap_info(dev, &trap);
|
||||||
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;
|
|
||||||
|
|
||||||
|
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
|
||||||
/* NV4 (nvidia TNT 1) reports software methods with
|
/* NV4 (nvidia TNT 1) reports software methods with
|
||||||
* PGRAPH NOTIFY ILLEGAL_MTHD
|
* 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",
|
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 "
|
DRM_ERROR("Unable to execute NV04 software method %x "
|
||||||
"for object class %x. Please report.\n",
|
"for object class %x. Please report.\n",
|
||||||
mthd, class);
|
trap.mthd, trap.class);
|
||||||
unhandled = 1;
|
unhandled = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -329,13 +335,30 @@ nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unhandled)
|
if (unhandled)
|
||||||
nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY");
|
nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
|
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
|
static inline void
|
||||||
|
|
Loading…
Reference in New Issue