diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_object.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_object.c | 105 | 
1 files changed, 31 insertions, 74 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index e7c100ba63a..b6bcb254f4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  		}  	} -	instmem->prepare_access(dev, true);  	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);  	do {  		if (!nouveau_ramht_entry_valid(dev, ramht, co)) { @@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  			nv_wo32(dev, ramht, (co + 4)/4, ctx);  			list_add_tail(&ref->list, &chan->ramht_refs); -			instmem->finish_access(dev); +			instmem->flush(dev);  			return 0;  		}  		NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", @@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  		if (co >= dev_priv->ramht_size)  			co = 0;  	} while (co != ho); -	instmem->finish_access(dev);  	NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);  	return -ENOMEM; @@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  		return;  	} -	instmem->prepare_access(dev, true);  	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);  	do {  		if (nouveau_ramht_entry_valid(dev, ramht, co) && @@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  			nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);  			list_del(&ref->list); -			instmem->finish_access(dev); +			instmem->flush(dev);  			return;  		} @@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)  			co = 0;  	} while (co != ho);  	list_del(&ref->list); -	instmem->finish_access(dev);  	NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",  		 chan->id, ref->handle); @@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nouveau_engine *engine = &dev_priv->engine;  	struct nouveau_gpuobj *gpuobj; -	struct mem_block *pramin = NULL; +	struct drm_mm *pramin = NULL;  	int ret;  	NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", @@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,  	 * available.  	 */  	if (chan) { -		if (chan->ramin_heap) { -			NV_DEBUG(dev, "private heap\n"); -			pramin = chan->ramin_heap; -		} else -		if (dev_priv->card_type < NV_50) { -			NV_DEBUG(dev, "global heap fallback\n"); -			pramin = dev_priv->ramin_heap; -		} +		NV_DEBUG(dev, "channel heap\n"); +		pramin = &chan->ramin_heap;  	} else {  		NV_DEBUG(dev, "global heap\n"); -		pramin = dev_priv->ramin_heap; -	} - -	if (!pramin) { -		NV_ERROR(dev, "No PRAMIN heap!\n"); -		return -EINVAL; -	} +		pramin = &dev_priv->ramin_heap; -	if (!chan) {  		ret = engine->instmem.populate(dev, gpuobj, &size);  		if (ret) {  			nouveau_gpuobj_del(dev, &gpuobj); @@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,  	}  	/* Allocate a chunk of the PRAMIN aperture */ -	gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, -						    drm_order(align), -						    (struct drm_file *)-2, 0); +	gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); +	if (gpuobj->im_pramin) +		gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); +  	if (!gpuobj->im_pramin) {  		nouveau_gpuobj_del(dev, &gpuobj);  		return -ENOMEM; @@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,  	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {  		int i; -		engine->instmem.prepare_access(dev, true);  		for (i = 0; i < gpuobj->im_pramin->size; i += 4)  			nv_wo32(dev, gpuobj, i/4, 0); -		engine->instmem.finish_access(dev); +		engine->instmem.flush(dev);  	}  	*gpuobj_ret = gpuobj; @@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)  	}  	if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { -		engine->instmem.prepare_access(dev, true);  		for (i = 0; i < gpuobj->im_pramin->size; i += 4)  			nv_wo32(dev, gpuobj, i/4, 0); -		engine->instmem.finish_access(dev); +		engine->instmem.flush(dev);  	}  	if (gpuobj->dtor) @@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)  		if (gpuobj->flags & NVOBJ_FLAG_FAKE)  			kfree(gpuobj->im_pramin);  		else -			nouveau_mem_free_block(gpuobj->im_pramin); +			drm_mm_put_block(gpuobj->im_pramin);  	}  	list_del(&gpuobj->list); @@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,  	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);  	if (p_offset != ~0) { -		gpuobj->im_pramin = kzalloc(sizeof(struct mem_block), +		gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node),  					    GFP_KERNEL);  		if (!gpuobj->im_pramin) {  			nouveau_gpuobj_del(dev, &gpuobj); @@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,  	}  	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { -		dev_priv->engine.instmem.prepare_access(dev, true);  		for (i = 0; i < gpuobj->im_pramin->size; i += 4)  			nv_wo32(dev, gpuobj, i/4, 0); -		dev_priv->engine.instmem.finish_access(dev); +		dev_priv->engine.instmem.flush(dev);  	}  	if (pref) { @@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,  		return ret;  	} -	instmem->prepare_access(dev, true); -  	if (dev_priv->card_type < NV_50) {  		uint32_t frame, adjust, pte_flags = 0; @@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,  		nv_wo32(dev, *gpuobj, 5, flags5);  	} -	instmem->finish_access(dev); +	instmem->flush(dev);  	(*gpuobj)->engine = NVOBJ_ENGINE_SW;  	(*gpuobj)->class  = class; @@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,  		return ret;  	} -	dev_priv->engine.instmem.prepare_access(dev, true);  	if (dev_priv->card_type >= NV_50) {  		nv_wo32(dev, *gpuobj, 0, class);  		nv_wo32(dev, *gpuobj, 5, 0x00010000); @@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,  			}  		}  	} -	dev_priv->engine.instmem.finish_access(dev); +	dev_priv->engine.instmem.flush(dev);  	(*gpuobj)->engine = NVOBJ_ENGINE_GR;  	(*gpuobj)->class  = class; @@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)  	base = 0;  	/* PGRAPH context */ +	size += dev_priv->engine.graph.grctx_size;  	if (dev_priv->card_type == NV_50) {  		/* Various fixed table thingos */ @@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)  		size += 0x8000;  		/* RAMFC */  		size += 0x1000; -		/* PGRAPH context */ -		size += 0x70000;  	} -	NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", -		 chan->id, size, base);  	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,  				     &chan->ramin);  	if (ret) { @@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)  	}  	pramin = chan->ramin->gpuobj; -	ret = nouveau_mem_init_heap(&chan->ramin_heap, -				    pramin->im_pramin->start + base, size); +	ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size);  	if (ret) {  		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);  		nouveau_gpuobj_ref_del(dev, &chan->ramin); @@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,  	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); -	/* Reserve a block of PRAMIN for the channel -	 *XXX: maybe on <NV50 too at some point -	 */ -	if (0 || dev_priv->card_type == NV_50) { -		ret = nouveau_gpuobj_channel_init_pramin(chan); -		if (ret) { -			NV_ERROR(dev, "init pramin\n"); -			return ret; -		} +	/* Allocate a chunk of memory for per-channel object storage */ +	ret = nouveau_gpuobj_channel_init_pramin(chan); +	if (ret) { +		NV_ERROR(dev, "init pramin\n"); +		return ret;  	}  	/* NV50 VM @@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,  	if (dev_priv->card_type >= NV_50) {  		uint32_t vm_offset, pde; -		instmem->prepare_access(dev, true); -  		vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;  		vm_offset += chan->ramin->gpuobj->im_pramin->start;  		ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,  							0, &chan->vm_pd, NULL); -		if (ret) { -			instmem->finish_access(dev); +		if (ret)  			return ret; -		}  		for (i = 0; i < 0x4000; i += 8) {  			nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);  			nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); @@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,  		ret = nouveau_gpuobj_ref_add(dev, NULL, 0,  					     dev_priv->gart_info.sg_ctxdma,  					     &chan->vm_gart_pt); -		if (ret) { -			instmem->finish_access(dev); +		if (ret)  			return ret; -		}  		nv_wo32(dev, chan->vm_pd, pde++,  			    chan->vm_gart_pt->instance | 0x03);  		nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); @@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,  			ret = nouveau_gpuobj_ref_add(dev, NULL, 0,  						     dev_priv->vm_vram_pt[i],  						     &chan->vm_vram_pt[i]); -			if (ret) { -				instmem->finish_access(dev); +			if (ret)  				return ret; -			}  			nv_wo32(dev, chan->vm_pd, pde++,  				    chan->vm_vram_pt[i]->instance | 0x61);  			nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);  		} -		instmem->finish_access(dev); +		instmem->flush(dev);  	}  	/* RAMHT */ @@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)  	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)  		nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); -	if (chan->ramin_heap) -		nouveau_mem_takedown(&chan->ramin_heap); +	if (chan->ramin_heap.free_stack.next) +		drm_mm_takedown(&chan->ramin_heap);  	if (chan->ramin)  		nouveau_gpuobj_ref_del(dev, &chan->ramin); @@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev)  			return -ENOMEM;  		} -		dev_priv->engine.instmem.prepare_access(dev, false);  		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)  			gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); -		dev_priv->engine.instmem.finish_access(dev);  	}  	return 0; @@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev)  		if (!gpuobj->im_backing_suspend)  			continue; -		dev_priv->engine.instmem.prepare_access(dev, true);  		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)  			nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); -		dev_priv->engine.instmem.finish_access(dev); +		dev_priv->engine.instmem.flush(dev);  	}  	nouveau_gpuobj_suspend_cleanup(dev); @@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,  	struct nouveau_channel *chan;  	int ret; -	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;  	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);  	if (init->handle == ~0) @@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,  	struct nouveau_channel *chan;  	int ret; -	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;  	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);  	ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);  |