[kernel/f15/master] nouveau: minor updates

Ben Skeggs bskeggs at fedoraproject.org
Wed Mar 9 06:36:23 UTC 2011


commit 496d23d3939a822ff8293d45ef4a7dc6f24461a1
Author: Ben Skeggs <bskeggs at redhat.com>
Date:   Wed Mar 9 16:34:54 2011 +1000

    nouveau: minor updates

 drm-nouveau-updates.patch |  586 +++++++++++++++++++++++++++++++++++++++++++--
 kernel.spec               |    5 +-
 2 files changed, 568 insertions(+), 23 deletions(-)
---
diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch
index d012a1c..3bd652f 100644
--- a/drm-nouveau-updates.patch
+++ b/drm-nouveau-updates.patch
@@ -1,24 +1,30 @@
  drivers/gpu/drm/nouveau/nouveau_bios.c    |   25 +--
  drivers/gpu/drm/nouveau/nouveau_bo.c      |    6 +-
  drivers/gpu/drm/nouveau/nouveau_channel.c |    2 +-
+ drivers/gpu/drm/nouveau/nouveau_display.c |    2 +-
  drivers/gpu/drm/nouveau/nouveau_dp.c      |    2 -
- drivers/gpu/drm/nouveau/nouveau_drv.h     |   13 +-
+ drivers/gpu/drm/nouveau/nouveau_drv.h     |   15 +-
  drivers/gpu/drm/nouveau/nouveau_fence.c   |  190 ++++++++++------
- drivers/gpu/drm/nouveau/nouveau_mem.c     |   16 +-
+ drivers/gpu/drm/nouveau/nouveau_mem.c     |   50 +++-
  drivers/gpu/drm/nouveau/nouveau_object.c  |   22 ++-
- drivers/gpu/drm/nouveau/nouveau_sgdma.c   |  342 +++++++++++++++++++++++++----
+ drivers/gpu/drm/nouveau/nouveau_sgdma.c   |  341 +++++++++++++++++++++++++----
  drivers/gpu/drm/nouveau/nouveau_state.c   |   10 +-
  drivers/gpu/drm/nouveau/nouveau_temp.c    |    4 +-
- drivers/gpu/drm/nouveau/nv04_fifo.c       |   17 ++-
+ drivers/gpu/drm/nouveau/nouveau_util.c    |   23 ++-
+ drivers/gpu/drm/nouveau/nouveau_util.h    |    4 +
+ drivers/gpu/drm/nouveau/nouveau_vm.c      |   13 +-
+ drivers/gpu/drm/nouveau/nv04_fifo.c       |   19 ++-
  drivers/gpu/drm/nouveau/nv40_fb.c         |   59 +++++-
  drivers/gpu/drm/nouveau/nv50_display.c    |    7 +-
+ drivers/gpu/drm/nouveau/nv50_fb.c         |  150 ++++++++++++-
  drivers/gpu/drm/nouveau/nv50_fifo.c       |    3 +-
  drivers/gpu/drm/nouveau/nv50_gpio.c       |   13 +-
- drivers/gpu/drm/nouveau/nv50_graph.c      |    8 +-
+ drivers/gpu/drm/nouveau/nv50_graph.c      |  142 +++++++-----
  drivers/gpu/drm/nouveau/nv50_vm.c         |    1 -
+ drivers/gpu/drm/nouveau/nv84_crypt.c      |    2 +-
  drivers/gpu/drm/nouveau/nvc0_fifo.c       |   15 +-
  drivers/gpu/drm/nouveau/nvc0_graph.c      |    2 -
- 20 files changed, 567 insertions(+), 190 deletions(-)
+ 26 files changed, 841 insertions(+), 281 deletions(-)
 
 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
 index 6bdab89..b8ff1e7 100644
@@ -64,10 +70,10 @@ index 6bdab89..b8ff1e7 100644
  		if (cte->type == 0xff)
  			continue;
 diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
-index d38a4d9..bf260af 100644
+index a521840..53a8000 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
-@@ -382,7 +382,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
+@@ -385,7 +385,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
  	case NOUVEAU_GART_AGP:
  		return ttm_agp_backend_init(bdev, dev->agp->bridge);
  #endif
@@ -77,7 +83,7 @@ index d38a4d9..bf260af 100644
  		return nouveau_sgdma_init_ttm(dev);
  	default:
  		NV_ERROR(dev, "Unknown GART type %d\n",
-@@ -436,7 +437,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+@@ -439,7 +440,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
  				TTM_PL_FLAG_WC;
  			man->default_caching = TTM_PL_FLAG_WC;
  			break;
@@ -100,6 +106,19 @@ index 3960d66..3d7b316 100644
  
  	if (dev_priv->card_type >= NV_50) {
  		if (dev_priv->card_type < NV_C0) {
+diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
+index 505c6bf..566466b 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_display.c
++++ b/drivers/gpu/drm/nouveau/nouveau_display.c
+@@ -244,7 +244,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ 
+ 	/* Initialize a page flip struct */
+ 	*s = (struct nouveau_page_flip_state)
+-		{ { }, s->event, nouveau_crtc(crtc)->index,
++		{ { }, event, nouveau_crtc(crtc)->index,
+ 		  fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
+ 		  new_bo->bo.offset };
+ 
 diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
 index 38d5995..7beb82a 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -121,7 +140,7 @@ index 38d5995..7beb82a 100644
  	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
  	if (ret)
 diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
-index 9821fca..2e3d7fb 100644
+index 982d70b..2cae8e7 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
 +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
 @@ -652,7 +652,6 @@ struct drm_nouveau_private {
@@ -156,6 +175,15 @@ index 9821fca..2e3d7fb 100644
  		struct nouveau_gpuobj *sg_ctxdma;
  		struct nouveau_vma vma;
  	} gart_info;
+@@ -1076,7 +1083,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
+ /* nv50_fb.c */
+ extern int  nv50_fb_init(struct drm_device *);
+ extern void nv50_fb_takedown(struct drm_device *);
+-extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *);
++extern void nv50_fb_vm_trap(struct drm_device *, int display);
+ 
+ /* nvc0_fb.c */
+ extern int  nvc0_fb_init(struct drm_device *);
 diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
 index 221b846..8b46392 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -476,7 +504,7 @@ index 221b846..8b46392 100644
  		if (ret)
  			return ret;
 diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
-index 26347b7..30bd230 100644
+index b0fb9bd..5b769eb 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
 @@ -393,11 +393,17 @@ nouveau_mem_vram_init(struct drm_device *dev)
@@ -502,6 +530,47 @@ index 26347b7..30bd230 100644
  
  	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits));
  	if (ret)
+@@ -419,14 +425,32 @@ nouveau_mem_vram_init(struct drm_device *dev)
+ 	}
+ 
+ 	/* reserve space at end of VRAM for PRAMIN */
+-	if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
+-	    dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
+-		dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024);
+-	else
+-	if (dev_priv->card_type >= NV_40)
+-		dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024);
+-	else
+-		dev_priv->ramin_rsvd_vram = (512 * 1024);
++	if (dev_priv->card_type >= NV_50) {
++		dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
++	} else
++	if (dev_priv->card_type >= NV_40) {
++		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
++		u32 rsvd;
++
++		/* estimate grctx size, the magics come from nv40_grctx.c */
++		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
++		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
++		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
++		else				    rsvd = 0x4a40 * vs;
++		rsvd += 16 * 1024;
++		rsvd *= dev_priv->engine.fifo.channels;
++
++		/* pciegart table */
++		if (drm_device_is_pcie(dev))
++			rsvd += 512 * 1024;
++
++		/* object storage */
++		rsvd += 512 * 1024;
++
++		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
++	} else {
++		dev_priv->ramin_rsvd_vram = 512 * 1024;
++	}
+ 
+ 	ret = dev_priv->engine.vram.init(dev);
+ 	if (ret)
 diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
 index 30b6544..3c12461 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -538,7 +607,7 @@ index 30b6544..3c12461 100644
  	}
  
 diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
-index 9a250eb..bdbaa54 100644
+index 9a250eb..a26383b 100644
 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
 +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
 @@ -74,8 +74,24 @@ nouveau_sgdma_clear(struct ttm_backend *be)
@@ -833,7 +902,7 @@ index 9a250eb..bdbaa54 100644
  	return &nvbe->backend;
  }
  
-@@ -210,21 +414,71 @@ nouveau_sgdma_init(struct drm_device *dev)
+@@ -210,21 +414,70 @@ nouveau_sgdma_init(struct drm_device *dev)
  {
  	struct drm_nouveau_private *dev_priv = dev->dev_private;
  	struct nouveau_gpuobj *gpuobj = NULL;
@@ -842,8 +911,7 @@ index 9a250eb..bdbaa54 100644
 +	u32 aper_size, align;
 +	int ret;
 +
-+	if (dev_priv->card_type >= NV_50 ||
-+	    dev_priv->ramin_rsvd_vram >= 2 * 1024 * 1024)
++	if (dev_priv->card_type >= NV_50 || drm_device_is_pcie(dev))
 +		aper_size = 512 * 1024 * 1024;
 +	else
 +		aper_size = 64 * 1024 * 1024;
@@ -883,7 +951,7 @@ index 9a250eb..bdbaa54 100644
 +		dev_priv->gart_info.type = NOUVEAU_GART_HW;
 +		dev_priv->gart_info.func = &nv50_sgdma_backend;
 +	} else
-+	if (drm_device_is_pcie(dev) &&
++	if (0 && drm_device_is_pcie(dev) &&
 +	    dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
 +		if (nv44_graph_class(dev)) {
 +			dev_priv->gart_info.func = &nv44_sgdma_backend;
@@ -917,7 +985,7 @@ index 9a250eb..bdbaa54 100644
  		if (ret) {
  			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
  			return ret;
-@@ -236,25 +490,14 @@ nouveau_sgdma_init(struct drm_device *dev)
+@@ -236,25 +489,14 @@ nouveau_sgdma_init(struct drm_device *dev)
  				   (0 << 14) /* RW */ |
  				   (2 << 16) /* PCI */);
  		nv_wo32(gpuobj, 4, aper_size - 1);
@@ -945,7 +1013,7 @@ index 9a250eb..bdbaa54 100644
  	return 0;
  }
  
-@@ -265,6 +508,13 @@ nouveau_sgdma_takedown(struct drm_device *dev)
+@@ -265,6 +507,13 @@ nouveau_sgdma_takedown(struct drm_device *dev)
  
  	nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma);
  	nouveau_vm_put(&dev_priv->gart_info.vma);
@@ -1011,8 +1079,90 @@ index 8d9968e..649b041 100644
  
  	client = i2c_new_device(&i2c->adapter, info);
  	if (!client)
+diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c
+index fbe0fb1..e51b515 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_util.c
++++ b/drivers/gpu/drm/nouveau/nouveau_util.c
+@@ -47,18 +47,27 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
+ 		printk(" (unknown bits 0x%08x)", value);
+ }
+ 
+-void
+-nouveau_enum_print(const struct nouveau_enum *en, u32 value)
++const struct nouveau_enum *
++nouveau_enum_find(const struct nouveau_enum *en, u32 value)
+ {
+ 	while (en->name) {
+-		if (value == en->value) {
+-			printk("%s", en->name);
+-			return;
+-		}
+-
++		if (en->value == value)
++			return en;
+ 		en++;
+ 	}
+ 
++	return NULL;
++}
++
++void
++nouveau_enum_print(const struct nouveau_enum *en, u32 value)
++{
++	en = nouveau_enum_find(en, value);
++	if (en) {
++		printk("%s", en->name);
++		return;
++	}
++
+ 	printk("(unknown enum 0x%08x)", value);
+ }
+ 
+diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h
+index d9ceaea..b97719f 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_util.h
++++ b/drivers/gpu/drm/nouveau/nouveau_util.h
+@@ -36,10 +36,14 @@ struct nouveau_bitfield {
+ struct nouveau_enum {
+ 	u32 value;
+ 	const char *name;
++	void *data;
+ };
+ 
+ void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
+ void nouveau_enum_print(const struct nouveau_enum *, u32 value);
++const struct nouveau_enum *
++nouveau_enum_find(const struct nouveau_enum *, u32 value);
++
+ int nouveau_ratelimit(void);
+ 
+ #endif
+diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
+index 97d82ae..b4658f7 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
+@@ -311,18 +311,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
+ 		vm->spg_shift = 12;
+ 		vm->lpg_shift = 17;
+ 		pgt_bits = 27;
+-
+-		/* Should be 4096 everywhere, this is a hack that's
+-		 * currently necessary to avoid an elusive bug that
+-		 * causes corruption when mixing small/large pages
+-		 */
+-		if (length < (1ULL << 40))
+-			block = 4096;
+-		else {
+-			block = (1 << pgt_bits);
+-			if (length < block)
+-				block = length;
+-		}
++		block = 4096;
+ 	} else {
+ 		kfree(vm);
+ 		return -ENOSYS;
 diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
-index f89d104..dfa600c 100644
+index f89d104..db465a3 100644
 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c
 +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
 @@ -379,6 +379,15 @@ out:
@@ -1055,6 +1205,15 @@ index f89d104..dfa600c 100644
  
  				if (dma_get != dma_put)
  					nv_wr32(dev, 0x003244, dma_put);
+@@ -505,7 +516,7 @@ nv04_fifo_isr(struct drm_device *dev)
+ 
+ 		if (dev_priv->card_type == NV_50) {
+ 			if (status & 0x00000010) {
+-				nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
++				nv50_fb_vm_trap(dev, nouveau_ratelimit());
+ 				status &= ~0x00000010;
+ 				nv_wr32(dev, 0x002100, 0x00000010);
+ 			}
 diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c
 index f3d9c05..f0ac2a7 100644
 --- a/drivers/gpu/drm/nouveau/nv40_fb.c
@@ -1170,6 +1329,185 @@ index 7cc94ed..a804a35 100644
  			delayed |= clock;
  			intr1 &= ~clock;
  		}
+diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
+index 50290de..efc8cd4 100644
+--- a/drivers/gpu/drm/nouveau/nv50_fb.c
++++ b/drivers/gpu/drm/nouveau/nv50_fb.c
+@@ -95,12 +95,109 @@ nv50_fb_takedown(struct drm_device *dev)
+ 	kfree(priv);
+ }
+ 
++static struct nouveau_enum vm_dispatch_subclients[] = {
++	{ 0x00000000, "GRCTX", NULL },
++	{ 0x00000001, "NOTIFY", NULL },
++	{ 0x00000002, "QUERY", NULL },
++	{ 0x00000003, "COND", NULL },
++	{ 0x00000004, "M2M_IN", NULL },
++	{ 0x00000005, "M2M_OUT", NULL },
++	{ 0x00000006, "M2M_NOTIFY", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_ccache_subclients[] = {
++	{ 0x00000000, "CB", NULL },
++	{ 0x00000001, "TIC", NULL },
++	{ 0x00000002, "TSC", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_prop_subclients[] = {
++	{ 0x00000000, "RT0", NULL },
++	{ 0x00000001, "RT1", NULL },
++	{ 0x00000002, "RT2", NULL },
++	{ 0x00000003, "RT3", NULL },
++	{ 0x00000004, "RT4", NULL },
++	{ 0x00000005, "RT5", NULL },
++	{ 0x00000006, "RT6", NULL },
++	{ 0x00000007, "RT7", NULL },
++	{ 0x00000008, "ZETA", NULL },
++	{ 0x00000009, "LOCAL", NULL },
++	{ 0x0000000a, "GLOBAL", NULL },
++	{ 0x0000000b, "STACK", NULL },
++	{ 0x0000000c, "DST2D", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_pfifo_subclients[] = {
++	{ 0x00000000, "PUSHBUF", NULL },
++	{ 0x00000001, "SEMAPHORE", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_bar_subclients[] = {
++	{ 0x00000000, "FB", NULL },
++	{ 0x00000001, "IN", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_client[] = {
++	{ 0x00000000, "STRMOUT", NULL },
++	{ 0x00000003, "DISPATCH", vm_dispatch_subclients },
++	{ 0x00000004, "PFIFO_WRITE", NULL },
++	{ 0x00000005, "CCACHE", vm_ccache_subclients },
++	{ 0x00000006, "PPPP", NULL },
++	{ 0x00000007, "CLIPID", NULL },
++	{ 0x00000008, "PFIFO_READ", NULL },
++	{ 0x00000009, "VFETCH", NULL },
++	{ 0x0000000a, "TEXTURE", NULL },
++	{ 0x0000000b, "PROP", vm_prop_subclients },
++	{ 0x0000000c, "PVP", NULL },
++	{ 0x0000000d, "PBSP", NULL },
++	{ 0x0000000e, "PCRYPT", NULL },
++	{ 0x0000000f, "PCOUNTER", NULL },
++	{ 0x00000011, "PDAEMON", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_engine[] = {
++	{ 0x00000000, "PGRAPH", NULL },
++	{ 0x00000001, "PVP", NULL },
++	{ 0x00000004, "PEEPHOLE", NULL },
++	{ 0x00000005, "PFIFO", vm_pfifo_subclients },
++	{ 0x00000006, "BAR", vm_bar_subclients },
++	{ 0x00000008, "PPPP", NULL },
++	{ 0x00000009, "PBSP", NULL },
++	{ 0x0000000a, "PCRYPT", NULL },
++	{ 0x0000000b, "PCOUNTER", NULL },
++	{ 0x0000000c, "SEMAPHORE_BG", NULL },
++	{ 0x0000000d, "PCOPY", NULL },
++	{ 0x0000000e, "PDAEMON", NULL },
++	{}
++};
++
++static struct nouveau_enum vm_fault[] = {
++	{ 0x00000000, "PT_NOT_PRESENT", NULL },
++	{ 0x00000001, "PT_TOO_SHORT", NULL },
++	{ 0x00000002, "PAGE_NOT_PRESENT", NULL },
++	{ 0x00000003, "PAGE_SYSTEM_ONLY", NULL },
++	{ 0x00000004, "PAGE_READ_ONLY", NULL },
++	{ 0x00000006, "NULL_DMAOBJ", NULL },
++	{ 0x00000007, "WRONG_MEMTYPE", NULL },
++	{ 0x0000000b, "VRAM_LIMIT", NULL },
++	{ 0x0000000f, "DMAOBJ_LIMIT", NULL },
++	{}
++};
++
+ void
+-nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
++nv50_fb_vm_trap(struct drm_device *dev, int display)
+ {
+ 	struct drm_nouveau_private *dev_priv = dev->dev_private;
++	const struct nouveau_enum *en, *cl;
+ 	unsigned long flags;
+ 	u32 trap[6], idx, chinst;
++	u8 st0, st1, st2, st3;
+ 	int i, ch;
+ 
+ 	idx = nv_rd32(dev, 0x100c90);
+@@ -117,8 +214,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
+ 	if (!display)
+ 		return;
+ 
++	/* lookup channel id */
+ 	chinst = (trap[2] << 16) | trap[1];
+-
+ 	spin_lock_irqsave(&dev_priv->channels.lock, flags);
+ 	for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
+ 		struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
+@@ -131,9 +228,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
+ 	}
+ 	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+ 
+-	NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x "
+-		     "channel %d (0x%08x)\n",
+-		name, (trap[5] & 0x100 ? "read" : "write"),
+-		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
+-		trap[0], ch, chinst);
++	/* decode status bits into something more useful */
++	if (dev_priv->chipset  < 0xa3 ||
++	    dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
++		st0 = (trap[0] & 0x0000000f) >> 0;
++		st1 = (trap[0] & 0x000000f0) >> 4;
++		st2 = (trap[0] & 0x00000f00) >> 8;
++		st3 = (trap[0] & 0x0000f000) >> 12;
++	} else {
++		st0 = (trap[0] & 0x000000ff) >> 0;
++		st1 = (trap[0] & 0x0000ff00) >> 8;
++		st2 = (trap[0] & 0x00ff0000) >> 16;
++		st3 = (trap[0] & 0xff000000) >> 24;
++	}
++
++	NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
++		(trap[5] & 0x00000100) ? "read" : "write",
++		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst);
++
++	en = nouveau_enum_find(vm_engine, st0);
++	if (en)
++		printk("%s/", en->name);
++	else
++		printk("%02x/", st0);
++
++	cl = nouveau_enum_find(vm_client, st2);
++	if (cl)
++		printk("%s/", cl->name);
++	else
++		printk("%02x/", st2);
++
++	if      (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
++	else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
++	else                     cl = NULL;
++	if (cl)
++		printk("%s", cl->name);
++	else
++		printk("%02x", st3);
++
++	printk(" reason: ");
++	en = nouveau_enum_find(vm_fault, st1);
++	if (en)
++		printk("%s\n", en->name);
++	else
++		printk("0x%08x\n", st1);
+ }
 diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
 index 8dd04c5..c34a074 100644
 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -1246,10 +1584,195 @@ index 6b149c0..d4f4206 100644
  	spin_unlock(&priv->lock);
  }
 diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
-index 37e21d2..c75cff1 100644
+index 37e21d2..a32b301 100644
 --- a/drivers/gpu/drm/nouveau/nv50_graph.c
 +++ b/drivers/gpu/drm/nouveau/nv50_graph.c
-@@ -912,10 +912,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid
+@@ -95,13 +95,41 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
+ }
+ 
+ static void
+-nv50_graph_init_regs(struct drm_device *dev)
++nv50_graph_init_zcull(struct drm_device *dev)
+ {
++	struct drm_nouveau_private *dev_priv = dev->dev_private;
++	int i;
++
+ 	NV_DEBUG(dev, "\n");
+ 
+-	nv_wr32(dev, NV04_PGRAPH_DEBUG_3,
+-				(1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
+-	nv_wr32(dev, 0x402ca8, 0x800);
++	switch (dev_priv->chipset & 0xf0) {
++	case 0x50:
++	case 0x80:
++	case 0x90:
++		nv_wr32(dev, 0x402ca8, 0x00000800);
++		break;
++	case 0xa0:
++	default:
++		nv_wr32(dev, 0x402cc0, 0x00000000);
++		if (dev_priv->chipset == 0xa0 ||
++		    dev_priv->chipset == 0xaa ||
++		    dev_priv->chipset == 0xac) {
++			nv_wr32(dev, 0x402ca8, 0x00000802);
++		} else {
++			nv_wr32(dev, 0x402cc0, 0x00000000);
++			nv_wr32(dev, 0x402ca8, 0x00000002);
++		}
++
++		break;
++	}
++
++	/* zero out zcull regions */
++	for (i = 0; i < 8; i++) {
++		nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000);
++		nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000);
++		nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
++		nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
++	}
+ }
+ 
+ static int
+@@ -136,6 +164,7 @@ nv50_graph_init_ctxctl(struct drm_device *dev)
+ 	}
+ 	kfree(cp);
+ 
++	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
+ 	nv_wr32(dev, 0x400320, 4);
+ 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
+ 	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
+@@ -151,7 +180,7 @@ nv50_graph_init(struct drm_device *dev)
+ 
+ 	nv50_graph_init_reset(dev);
+ 	nv50_graph_init_regs__nv(dev);
+-	nv50_graph_init_regs(dev);
++	nv50_graph_init_zcull(dev);
+ 
+ 	ret = nv50_graph_init_ctxctl(dev);
+ 	if (ret)
+@@ -526,11 +555,11 @@ nv86_graph_tlb_flush(struct drm_device *dev)
+ 
+ static struct nouveau_enum nv50_mp_exec_error_names[] =
+ {
+-	{ 3, "STACK_UNDERFLOW" },
+-	{ 4, "QUADON_ACTIVE" },
+-	{ 8, "TIMEOUT" },
+-	{ 0x10, "INVALID_OPCODE" },
+-	{ 0x40, "BREAKPOINT" },
++	{ 3, "STACK_UNDERFLOW", NULL },
++	{ 4, "QUADON_ACTIVE", NULL },
++	{ 8, "TIMEOUT", NULL },
++	{ 0x10, "INVALID_OPCODE", NULL },
++	{ 0x40, "BREAKPOINT", NULL },
+ 	{}
+ };
+ 
+@@ -558,47 +587,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = {
+ 
+ /* There must be a *lot* of these. Will take some time to gather them up. */
+ struct nouveau_enum nv50_data_error_names[] = {
+-	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE" },
+-	{ 0x00000004, "INVALID_VALUE" },
+-	{ 0x00000005, "INVALID_ENUM" },
+-	{ 0x00000008, "INVALID_OBJECT" },
+-	{ 0x00000009, "READ_ONLY_OBJECT" },
+-	{ 0x0000000a, "SUPERVISOR_OBJECT" },
+-	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" },
+-	{ 0x0000000c, "INVALID_BITFIELD" },
+-	{ 0x0000000d, "BEGIN_END_ACTIVE" },
+-	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" },
+-	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP" },
+-	{ 0x00000010, "RT_DOUBLE_BIND" },
+-	{ 0x00000011, "RT_TYPES_MISMATCH" },
+-	{ 0x00000012, "RT_LINEAR_WITH_ZETA" },
+-	{ 0x00000015, "FP_TOO_FEW_REGS" },
+-	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" },
+-	{ 0x00000017, "RT_LINEAR_WITH_MSAA" },
+-	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" },
+-	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" },
+-	{ 0x0000001a, "RT_INVALID_ALIGNMENT" },
+-	{ 0x0000001b, "SAMPLER_OVER_LIMIT" },
+-	{ 0x0000001c, "TEXTURE_OVER_LIMIT" },
+-	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS" },
+-	{ 0x0000001f, "RT_BPP128_WITH_MS8" },
+-	{ 0x00000021, "Z_OUT_OF_BOUNDS" },
+-	{ 0x00000023, "XY_OUT_OF_BOUNDS" },
+-	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" },
+-	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED" },
+-	{ 0x00000029, "CP_NO_REG_SPACE_PACKED" },
+-	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS" },
+-	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" },
+-	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" },
+-	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" },
+-	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH" },
+-	{ 0x00000031, "ENG2D_FORMAT_MISMATCH" },
+-	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" },
+-	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" },
+-	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" },
+-	{ 0x00000046, "LAYER_ID_NEEDS_GP" },
+-	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" },
+-	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" },
++	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL },
++	{ 0x00000004, "INVALID_VALUE", NULL },
++	{ 0x00000005, "INVALID_ENUM", NULL },
++	{ 0x00000008, "INVALID_OBJECT", NULL },
++	{ 0x00000009, "READ_ONLY_OBJECT", NULL },
++	{ 0x0000000a, "SUPERVISOR_OBJECT", NULL },
++	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
++	{ 0x0000000c, "INVALID_BITFIELD", NULL },
++	{ 0x0000000d, "BEGIN_END_ACTIVE", NULL },
++	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
++	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
++	{ 0x00000010, "RT_DOUBLE_BIND", NULL },
++	{ 0x00000011, "RT_TYPES_MISMATCH", NULL },
++	{ 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
++	{ 0x00000015, "FP_TOO_FEW_REGS", NULL },
++	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
++	{ 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
++	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
++	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
++	{ 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
++	{ 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
++	{ 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
++	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
++	{ 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
++	{ 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
++	{ 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
++	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
++	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
++	{ 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
++	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
++	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
++	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
++	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
++	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
++	{ 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
++	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
++	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
++	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
++	{ 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
++	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
++	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
+ 	{}
+ };
+ 
+@@ -678,7 +707,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
+ 		tps++;
+ 		switch (type) {
+ 		case 6: /* texture error... unknown for now */
+-			nv50_fb_vm_trap(dev, display, name);
+ 			if (display) {
+ 				NV_ERROR(dev, "magic set %d:\n", i);
+ 				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
+@@ -701,7 +729,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
+ 			uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
+ 			uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
+ 			uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
+-			nv50_fb_vm_trap(dev, display, name);
+ 			/* 2d engine destination */
+ 			if (ustatus & 0x00000010) {
+ 				if (display) {
+@@ -912,10 +939,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid
  			printk("\n");
  			NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x"
  				     " %08x %08x %08x\n",
@@ -1264,8 +1787,16 @@ index 37e21d2..c75cff1 100644
  
  		}
  
+@@ -1044,6 +1071,7 @@ nv50_graph_isr(struct drm_device *dev)
+ 			NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d "
+ 				     "class 0x%04x mthd 0x%04x data 0x%08x\n",
+ 				chid, inst, subc, class, mthd, data);
++			nv50_fb_vm_trap(dev, 1);
+ 		}
+ 	}
+ 
 diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
-index 459ff08..03c1a63 100644
+index 6144156..1f47c75 100644
 --- a/drivers/gpu/drm/nouveau/nv50_vm.c
 +++ b/drivers/gpu/drm/nouveau/nv50_vm.c
 @@ -31,7 +31,6 @@ void
@@ -1276,6 +1807,17 @@ index 459ff08..03c1a63 100644
  	u64 phys = 0xdeadcafe00000000ULL;
  	u32 coverage = 0;
  
+diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
+index ec18ae1..fabc7fd 100644
+--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
++++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
+@@ -136,5 +136,5 @@ nv84_crypt_isr(struct drm_device *dev)
+ 	nv_wr32(dev, 0x102130, stat);
+ 	nv_wr32(dev, 0x10200c, 0x10);
+ 
+-	nv50_fb_vm_trap(dev, show, "PCRYPT");
++	nv50_fb_vm_trap(dev, show);
+ }
 diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
 index e6f92c5..e9f8643 100644
 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
diff --git a/kernel.spec b/kernel.spec
index ed0621f..2a5c22c 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -51,7 +51,7 @@ Summary: The Linux kernel
 # For non-released -rc kernels, this will be prepended with "0.", so
 # for example a 3 here will become 0.3
 #
-%global baserelease 1
+%global baserelease 2
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -1970,6 +1970,9 @@ fi
 # and build.
 
 %changelog
+* Wed Mar 09 2011 Ben Skeggs <bskeggs at redhat.com> 2.6.38-0.rc8.git0.2
+- nouveau: allow max clients on nv4x (679629), better error reporting
+
 * Tue Mar 08 2011 Chuck Ebbert <cebbert at redhat.com> 2.6.38-0.rc8.git0.1
 - Linux 2.6.38-rc8
 


More information about the scm-commits mailing list