Commit 97e2000f authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nv50: improve evo error handler when more than just channel 0 active



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 43ce028f
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -715,20 +715,21 @@
#define NV50_PDISPLAY_INTR_1_CLK_UNK10                               0x00000010
#define NV50_PDISPLAY_INTR_1_CLK_UNK20                               0x00000020
#define NV50_PDISPLAY_INTR_1_CLK_UNK40                               0x00000040
#define NV50_PDISPLAY_INTR_EN                                        0x0061002c
#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC                            0x0000000c
#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n)                   (1 << ((n) + 2))
#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0                          0x00000004
#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1                          0x00000008
#define NV50_PDISPLAY_INTR_EN_CLK_UNK10                              0x00000010
#define NV50_PDISPLAY_INTR_EN_CLK_UNK20                              0x00000020
#define NV50_PDISPLAY_INTR_EN_CLK_UNK40                              0x00000040
#define NV50_PDISPLAY_INTR_EN_0                                      0x00610028
#define NV50_PDISPLAY_INTR_EN_1                                      0x0061002c
#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC                          0x0000000c
#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n)                 (1 << ((n) + 2))
#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0                        0x00000004
#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1                        0x00000008
#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10                            0x00000010
#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20                            0x00000020
#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40                            0x00000040
#define NV50_PDISPLAY_UNK30_CTRL                                     0x00610030
#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0                        0x00000200
#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1                        0x00000400
#define NV50_PDISPLAY_UNK30_CTRL_PENDING                             0x80000000
#define NV50_PDISPLAY_TRAPPED_ADDR                                   0x00610080
#define NV50_PDISPLAY_TRAPPED_DATA                                   0x00610084
#define NV50_PDISPLAY_TRAPPED_ADDR(i)                  ((i) * 0x08 + 0x00610080)
#define NV50_PDISPLAY_TRAPPED_DATA(i)                  ((i) * 0x08 + 0x00610084)
#define NV50_PDISPLAY_EVO_CTRL(i)                      ((i) * 0x10 + 0x00610200)
#define NV50_PDISPLAY_EVO_CTRL_DMA                                   0x00000010
#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED                          0x00000000
+23 −17
Original line number Diff line number Diff line
@@ -149,13 +149,13 @@ nv50_display_init(struct drm_device *dev)
	}

	nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000);
	nv_wr32(dev, 0x610028, 0x00000000);
	nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000);
	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000);
	nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000);
	nv_wr32(dev, NV50_PDISPLAY_INTR_EN,
		     NV50_PDISPLAY_INTR_EN_CLK_UNK10 |
		     NV50_PDISPLAY_INTR_EN_CLK_UNK20 |
		     NV50_PDISPLAY_INTR_EN_CLK_UNK40);
	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1,
		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 |
		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 |
		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK40);

	/* enable hotplug interrupts */
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -248,7 +248,7 @@ static int nv50_display_disable(struct drm_device *dev)
	}

	/* disable interrupts. */
	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000);
	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000);

	/* disable hotplug interrupts */
	nv_wr32(dev, 0xe054, 0xffffffff);
@@ -451,8 +451,7 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
	if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1)
		nv50_display_vblank_crtc_handler(dev, 1);

	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
		     NV50_PDISPLAY_INTR_EN) & ~intr);
	nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, intr, 0x00000000);
	nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr);
}

@@ -779,16 +778,23 @@ nv50_display_irq_handler_bh(struct work_struct *work)
static void
nv50_display_error_handler(struct drm_device *dev)
{
	uint32_t addr, data;
	u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16;
	u32 addr, data;
	int chid;

	nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000);
	addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR);
	data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA);
	for (chid = 0; chid < 5; chid++) {
		if (!(channels & (1 << chid)))
			continue;

	NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n",
		 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
		nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid);
		addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid));
		data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid));
		NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x "
			      "(0x%04x 0x%02x)\n", chid,
			 addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);

	nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
		nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000);
	}
}

void
@@ -891,9 +897,9 @@ nv50_display_irq_handler(struct drm_device *dev)
		if (!intr0 && !(intr1 & ~delayed))
			break;

		if (intr0 & 0x00010000) {
		if (intr0 & 0x001f0000) {
			nv50_display_error_handler(dev);
			intr0 &= ~0x00010000;
			intr0 &= ~0x001f0000;
		}

		if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) {
+5 −6
Original line number Diff line number Diff line
@@ -384,13 +384,12 @@ nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
	if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1)
		return -EINVAL;

	if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) &
		      NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) {
	if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN_1) &
			   NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(data))) {
		nv_wr32(dev, NV50_PDISPLAY_INTR_1,
			     NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data));
		nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
			NV50_PDISPLAY_INTR_EN) |
			NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data));
		nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
			     NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(data));
	}

	list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);