diff options
| -rw-r--r-- | linux-core/Makefile.kernel | 2 | ||||
| l--------- | linux-core/radeon_cs.c | 1 | ||||
| -rw-r--r-- | linux-core/radeon_gem.c | 211 | ||||
| -rw-r--r-- | linux-core/radeon_reg.h | 4 | ||||
| -rw-r--r-- | shared-core/radeon_cp.c | 30 | ||||
| -rw-r--r-- | shared-core/radeon_cs.c | 181 | ||||
| -rw-r--r-- | shared-core/radeon_drm.h | 15 | ||||
| -rw-r--r-- | shared-core/radeon_drv.h | 56 | ||||
| -rw-r--r-- | shared-core/radeon_state.c | 1 | 
9 files changed, 450 insertions, 51 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index d3668dfb..404944bf 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -41,7 +41,7 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \  		nv50_kms_wrapper.o \  		nv50_fbcon.o  radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_gem.o \ -	 radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o \ +	 radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o radeon_cs.o \  	atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o  sis-objs    := sis_drv.o sis_mm.o  ffb-objs    := ffb_drv.o ffb_context.o diff --git a/linux-core/radeon_cs.c b/linux-core/radeon_cs.c new file mode 120000 index 00000000..0e3fa8ee --- /dev/null +++ b/linux-core/radeon_cs.c @@ -0,0 +1 @@ +../shared-core/radeon_cs.c
\ No newline at end of file diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index d536aed2..021bb9f9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -27,6 +27,9 @@  #include "radeon_drm.h"  #include "radeon_drv.h" +static int radeon_gem_ib_init(struct drm_device *dev); +static int radeon_gem_ib_destroy(struct drm_device *dev); +  int radeon_gem_init_object(struct drm_gem_object *obj)  {  	struct drm_radeon_gem_object *obj_priv; @@ -513,19 +516,19 @@ static int radeon_gart_init(struct drm_device *dev)  		ret = drm_buffer_object_create(dev, RADEON_PCIGART_TABLE_SIZE,  					       drm_bo_type_kernel,  					       DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, -					       0, 1, 0, &dev_priv->mm.pcie_table); +					       0, 1, 0, &dev_priv->mm.pcie_table.bo);  		if (ret)  			return -EINVAL; -		DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table, dev_priv->mm.pcie_table->offset); -		ret = drm_bo_kmap(dev_priv->mm.pcie_table, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, -				  &dev_priv->mm.pcie_table_map); +		DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); +		ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, +				  &dev_priv->mm.pcie_table.kmap);  		if (ret)  			return -EINVAL;  		dev_priv->pcigart_offset_set = 2; -		dev_priv->gart_info.bus_addr =  dev_priv->fb_location + dev_priv->mm.pcie_table->offset; -		dev_priv->gart_info.addr = dev_priv->mm.pcie_table_map.virtual; +		dev_priv->gart_info.bus_addr =  dev_priv->fb_location + dev_priv->mm.pcie_table.bo->offset; +		dev_priv->gart_info.addr = dev_priv->mm.pcie_table.kmap.virtual;  		dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;  		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB;  		memset(dev_priv->gart_info.addr, 0, RADEON_PCIGART_TABLE_SIZE); @@ -566,14 +569,14 @@ int radeon_alloc_gart_objects(struct drm_device *dev)  				       drm_bo_type_kernel,  				       DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT |  				       DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, -				       0, 1, 0, &dev_priv->mm.ring); +				       0, 1, 0, &dev_priv->mm.ring.bo);  	if (ret) {  		DRM_ERROR("failed to allocate ring\n");  		return -EINVAL;  	} -	ret = drm_bo_kmap(dev_priv->mm.ring, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, -			  &dev_priv->mm.ring_map); +	ret = drm_bo_kmap(dev_priv->mm.ring.bo, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, +			  &dev_priv->mm.ring.kmap);  	if (ret) {  		DRM_ERROR("failed to map ring\n");  		return -EINVAL; @@ -583,24 +586,26 @@ int radeon_alloc_gart_objects(struct drm_device *dev)  				       drm_bo_type_kernel,  				       DRM_BO_FLAG_WRITE |DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT |  				       DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, -				       0, 1, 0, &dev_priv->mm.ring_read_ptr); +				       0, 1, 0, &dev_priv->mm.ring_read.bo);  	if (ret) {  		DRM_ERROR("failed to allocate ring read\n");  		return -EINVAL;  	} -	ret = drm_bo_kmap(dev_priv->mm.ring_read_ptr, 0, +	ret = drm_bo_kmap(dev_priv->mm.ring_read.bo, 0,  			  PAGE_SIZE >> PAGE_SHIFT, -			  &dev_priv->mm.ring_read_ptr_map); +			  &dev_priv->mm.ring_read.kmap);  	if (ret) {  		DRM_ERROR("failed to map ring read\n");  		return -EINVAL;  	}  	DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", -		  dev_priv->mm.ring, dev_priv->mm.ring->offset, dev_priv->mm.ring_map.virtual, -		  dev_priv->mm.ring_read_ptr, dev_priv->mm.ring_read_ptr->offset, dev_priv->mm.ring_read_ptr_map.virtual); +		  dev_priv->mm.ring.bo, dev_priv->mm.ring.bo->offset, dev_priv->mm.ring.kmap.virtual, +		  dev_priv->mm.ring_read.bo, dev_priv->mm.ring_read.bo->offset, dev_priv->mm.ring_read.kmap.virtual); +	/* init the indirect buffers */ +	radeon_gem_ib_init(dev);  	return 0;			    } @@ -634,6 +639,8 @@ int radeon_gem_mm_init(struct drm_device *dev)  	ret = radeon_alloc_gart_objects(dev);  	if (ret)  		return -EINVAL; + +	  	return 0;  } @@ -641,16 +648,19 @@ void radeon_gem_mm_fini(struct drm_device *dev)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	radeon_gem_ib_destroy(dev); +  	mutex_lock(&dev->struct_mutex); -	if (dev_priv->mm.ring_read_ptr) { -		drm_bo_kunmap(&dev_priv->mm.ring_read_ptr_map); -		drm_bo_usage_deref_locked(&dev_priv->mm.ring_read_ptr); +	 +	if (dev_priv->mm.ring_read.bo) { +		drm_bo_kunmap(&dev_priv->mm.ring_read.kmap); +		drm_bo_usage_deref_locked(&dev_priv->mm.ring_read.bo);  	} -	if (dev_priv->mm.ring) { -		drm_bo_kunmap(&dev_priv->mm.ring_map); -		drm_bo_usage_deref_locked(&dev_priv->mm.ring); +	if (dev_priv->mm.ring.bo) { +		drm_bo_kunmap(&dev_priv->mm.ring.kmap); +		drm_bo_usage_deref_locked(&dev_priv->mm.ring.bo);  	}  	if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { @@ -658,9 +668,9 @@ void radeon_gem_mm_fini(struct drm_device *dev)  	}  	if (dev_priv->flags & RADEON_IS_PCIE) { -		if (dev_priv->mm.pcie_table) { -			drm_bo_kunmap(&dev_priv->mm.pcie_table_map); -			drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table); +		if (dev_priv->mm.pcie_table.bo) { +			drm_bo_kunmap(&dev_priv->mm.pcie_table.kmap); +			drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table.bo);  		}  	} @@ -685,3 +695,158 @@ int radeon_gem_object_pin(struct drm_gem_object *obj,  	return ret;  } +#define RADEON_IB_MEMORY (1*1024*1024) +#define RADEON_IB_SIZE (65536) + +#define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) + +int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) +{ +	int i, index = -1; +	int ret; +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	for (i = 0; i < RADEON_NUM_IB; i++) { +		if (!(dev_priv->ib_alloc_bitmap & (1 << i))){ +			index = i; +			break; +		} +	} + +	/* if all in use we need to wait */ +	if (index == -1) { +		for (i = 0; i < RADEON_NUM_IB; i++) { +			if (dev_priv->ib_alloc_bitmap & (1 << i)) { +				mutex_lock(&dev_priv->ib_objs[i]->bo->mutex); +				ret = drm_bo_wait(dev_priv->ib_objs[i]->bo, 0, 1, 0, 0); +				mutex_unlock(&dev_priv->ib_objs[i]->bo->mutex); +				if (ret) +					continue; +				dev_priv->ib_alloc_bitmap &= ~(1 << i); +				index = i; +				break; +			} +		} +	} + +	if (index == -1) { +		DRM_ERROR("Major case fail to allocate IB from freelist %x\n", dev_priv->ib_alloc_bitmap); +		return -EINVAL; +	} +		 + +	if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) +		return -EINVAL; + +	*ib = dev_priv->ib_objs[index]->kmap.virtual; +	dev_priv->ib_alloc_bitmap |= (1 << i); +	return 0; +} + +static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_fence_object *fence; +	int ret; +	int i; +	RING_LOCALS; + +	for (i = 0; i < RADEON_NUM_IB; i++) { + +		if (dev_priv->ib_objs[i]->kmap.virtual == ib) { +			ret = drm_bo_do_validate(dev_priv->ib_objs[i]->bo, 0, +				 DRM_BO_FLAG_NO_EVICT, +				 0, 0, NULL); +			if (ret) +				DRM_ERROR("FAiled to validate\n"); + +			DRM_DEBUG("validated IB %x, %d\n", dev_priv->ib_objs[i]->bo->offset, dwords); +			BEGIN_RING(4); +			 +			OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); +			OUT_RING(dev_priv->gart_vm_start + dev_priv->ib_objs[i]->bo->offset); +			OUT_RING(dwords); +			OUT_RING(CP_PACKET2()); + +			ADVANCE_RING(); + +			COMMIT_RING(); + +			/* emit a fence object */ +			ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); +			if (ret) { +				 +				drm_putback_buffer_objects(dev); +			} +			/* dereference the fence object */ +			if (fence) +				drm_fence_usage_deref_unlocked(&fence); +		} +	} + +} + +static int radeon_gem_ib_destroy(struct drm_device *dev) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; +	int i; + +	if (dev_priv->ib_objs) { +		for (i = 0; i < RADEON_NUM_IB; i++) { +			if (dev_priv->ib_objs[i]) { +				drm_bo_kunmap(&dev_priv->ib_objs[i]->kmap); +				drm_bo_usage_deref_unlocked(&dev_priv->ib_objs[i]->bo); +			} +			drm_free(dev_priv->ib_objs[i], sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); +		} +		drm_free(dev_priv->ib_objs, RADEON_NUM_IB*sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); +	} +	dev_priv->ib_objs = NULL; +	return 0; +} + +/* allocate 1MB of 64k IBs the the kernel can keep mapped */ +static int radeon_gem_ib_init(struct drm_device *dev) +{ + +	drm_radeon_private_t *dev_priv = dev->dev_private; +	int i; +	int ret; + +	dev_priv->ib_objs = drm_calloc(RADEON_NUM_IB, sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); +	if (!dev_priv->ib_objs) +		goto free_all; + +	for (i = 0; i  < RADEON_NUM_IB; i++) { +		dev_priv->ib_objs[i] = drm_calloc(1, sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); +		if (!dev_priv->ib_objs[i]) +			goto free_all; + +		ret = drm_buffer_object_create(dev, RADEON_IB_SIZE, +					       drm_bo_type_kernel, +					       DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | +					       DRM_BO_FLAG_MAPPABLE, 0, +					       0, 0, &dev_priv->ib_objs[i]->bo); +		if (ret) +			goto free_all; + +		ret = drm_bo_kmap(dev_priv->ib_objs[i]->bo, 0, RADEON_IB_SIZE >> PAGE_SHIFT, +				  &dev_priv->ib_objs[i]->kmap); + +		if (ret) +			goto free_all; +	} + +	dev_priv->ib_alloc_bitmap = 0; + +	dev_priv->cs.ib_get = radeon_gem_ib_get; +	dev_priv->cs.ib_free = radeon_gem_ib_free; + +	radeon_cs_init(dev); +	return 0; + +free_all: +	radeon_gem_ib_destroy(dev); +	return -ENOMEM; +} + diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index 9b6bf1ec..a5be6a63 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -3086,6 +3086,10 @@  #       define RADEON_CSQ_PRIPIO_INDBM         (3    << 28)  #       define RADEON_CSQ_PRIBM_INDBM          (4    << 28)  #       define RADEON_CSQ_PRIPIO_INDPIO        (15   << 28) + +#define R300_CP_RESYNC_ADDR                 0x778 +#define R300_CP_RESYNC_DATA                 0x77c +  #define RADEON_CP_CSQ_STAT                  0x07f8  #       define RADEON_CSQ_RPTR_PRIMARY_MASK    (0xff <<  0)  #       define RADEON_CSQ_WPTR_PRIMARY_MASK    (0xff <<  8) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 80951e91..46f4290a 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -658,8 +658,8 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,  					 ((dev_priv->gart_vm_start - 1) & 0xffff0000)  					 | (dev_priv->fb_location >> 16)); -	if (dev_priv->mm.ring) { -		ring_start = dev_priv->mm.ring->offset + +	if (dev_priv->mm.ring.bo) { +		ring_start = dev_priv->mm.ring.bo->offset +  			dev_priv->gart_vm_start;  	} else  #if __OS_HAS_AGP @@ -692,9 +692,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,  	dev_priv->ring.tail = cur_read_ptr; -	if (dev_priv->mm.ring_read_ptr) { +	if (dev_priv->mm.ring_read.bo) {  		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, -			     dev_priv->mm.ring_read_ptr->offset + +			     dev_priv->mm.ring_read.bo->offset +  			     dev_priv->gart_vm_start);  	} else  #if __OS_HAS_AGP @@ -745,9 +745,9 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,  	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)  		     + RADEON_SCRATCH_REG_OFFSET); -	if (dev_priv->mm.ring_read_ptr) +	if (dev_priv->mm.ring_read.bo)  		dev_priv->scratch = ((__volatile__ u32 *) -				     dev_priv->mm.ring_read_ptr_map.virtual + +				     dev_priv->mm.ring_read.kmap.virtual +  				     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));  	else  		dev_priv->scratch = ((__volatile__ u32 *) @@ -772,12 +772,18 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,  	radeon_do_wait_for_idle(dev_priv);  	/* Sync everything up */ +	if (dev_priv->chip_family > CHIP_RV280) {  	RADEON_WRITE(RADEON_ISYNC_CNTL,  		     (RADEON_ISYNC_ANY2D_IDLE3D |  		      RADEON_ISYNC_ANY3D_IDLE2D |  		      RADEON_ISYNC_WAIT_IDLEGUI |  		      RADEON_ISYNC_CPSCRATCH_IDLEGUI)); - +	} else { +	RADEON_WRITE(RADEON_ISYNC_CNTL, +		     (RADEON_ISYNC_ANY2D_IDLE3D | +		      RADEON_ISYNC_ANY3D_IDLE2D | +		      RADEON_ISYNC_WAIT_IDLEGUI)); +	}  }  static void radeon_test_writeback(drm_radeon_private_t * dev_priv) @@ -785,8 +791,8 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)  	u32 tmp;  	void *ring_read_ptr; -	if (dev_priv->mm.ring_read_ptr) -		ring_read_ptr = dev_priv->mm.ring_read_ptr_map.virtual; +	if (dev_priv->mm.ring_read.bo) +		ring_read_ptr = dev_priv->mm.ring_read.kmap.virtual;  	else  		ring_read_ptr = dev_priv->ring_rptr->handle; @@ -2282,8 +2288,8 @@ int radeon_modeset_cp_init(struct drm_device *dev)  	dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE;  	dev_priv->cp_mode = RADEON_CSQ_PRIBM_INDBM; -	dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual; -	dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.virtual + +	dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual; +	dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual +  		dev_priv->ring.size / sizeof(u32);  	dev_priv->ring.size_l2qw = drm_order(dev_priv->ring.size / 8);  	dev_priv->ring.rptr_update = 4096; @@ -2297,7 +2303,7 @@ int radeon_modeset_cp_init(struct drm_device *dev)  	radeon_cp_load_microcode(dev_priv); -	DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring->offset, dev_priv->mm.ring_read_ptr->offset); +	DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset);  	radeon_cp_init_ring_buffer(dev, dev_priv); diff --git a/shared-core/radeon_cs.c b/shared-core/radeon_cs.c new file mode 100644 index 00000000..61fef79d --- /dev/null +++ b/shared-core/radeon_cs.c @@ -0,0 +1,181 @@ +/* + * Copyright 2008 Jerome Glisse. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + *    Jerome Glisse <glisse@freedesktop.org> + */ +#include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" +#include "r300_reg.h" + +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) +{ +	struct drm_radeon_private *radeon = dev->dev_private; +	struct drm_radeon_cs *cs = data; +	uint32_t *packets = NULL; +	uint32_t cs_id; +	void *ib = NULL; +	long size; +	int r; + +	/* set command stream id to 0 which is fake id */ +	cs_id = 0; +	DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); + +	if (radeon == NULL) { +		DRM_ERROR("called with no initialization\n"); +		return -EINVAL; +	} +	if (!cs->dwords) { +		return 0; +	} +	/* limit cs to 64K ib */ +	if (cs->dwords > (16 * 1024)) { +		return -EINVAL; +	} +	/* copy cs from userspace maybe we should copy into ib to save +	 * one copy but ib will be mapped wc so not good for cmd checking +	 * somethings worth testing i guess (Jerome) +	 */ +	size = cs->dwords * sizeof(uint32_t); +	packets = drm_alloc(size, DRM_MEM_DRIVER); +	if (packets == NULL) { +		return -ENOMEM; +	} +	if (DRM_COPY_FROM_USER(packets, (void __user *)(unsigned long)cs->packets, size)) { +		r = -EFAULT; +		goto out; +	} +	/* get ib */ +	r = radeon->cs.ib_get(dev, &ib, cs->dwords); +	if (r) { +		goto out; +	} + +	/* now parse command stream */ +	r = radeon->cs.parse(dev, ib, packets, cs->dwords); +	if (r) { +		goto out; +	} + +	/* emit cs id sequence */ +	radeon->cs.id_emit(dev, &cs_id); +	DRM_COPY_TO_USER(&cs->cs_id, &cs_id, sizeof(uint32_t)); +out: +	radeon->cs.ib_free(dev, ib, cs->dwords); +	drm_free(packets, size, DRM_MEM_DRIVER); +	return r; +} + +int radeon_cs_parse(struct drm_device *dev, void *ib, +		    uint32_t *packets, uint32_t dwords) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; +	volatile int rb; + +	/* copy the packet into the IB */ +	memcpy(ib, packets, dwords * sizeof(uint32_t)); + +	/* read back last byte to flush WC buffers */ +	rb = readl((ib + (dwords-1) * sizeof(uint32_t))); + +	return 0; +} + +uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon) +{ +	/* FIXME: protect with a spinlock */ +	/* FIXME: check if wrap affect last reported wrap & sequence */ +	radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF; +	if (!radeon->cs.id_scnt) { +		/* increment wrap counter */ +		radeon->cs.id_wcnt += 0x01000000; +		/* valid sequence counter start at 1 */ +		radeon->cs.id_scnt = 1; +	} +	return (radeon->cs.id_scnt | radeon->cs.id_wcnt); +} + +void r100_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; +	RING_LOCALS; + +	/* ISYNC_CNTL should have CPSCRACTH bit set */ +	*id = radeon_cs_id_get(dev_priv); +	/* emit id in SCRATCH4 (not used yet in old drm) */ +	BEGIN_RING(2); +	OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG4, 0)); +	OUT_RING(*id); +	ADVANCE_RING();	 +} + +void r300_cs_id_emit(struct drm_device *dev, uint32_t *id) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; +	RING_LOCALS; + +	/* ISYNC_CNTL should not have CPSCRACTH bit set */ +	*id = radeon_cs_id_get(dev_priv); +	/* emit id in SCRATCH6 */ +	BEGIN_RING(6); +	OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 0)); +	OUT_RING(6); +	OUT_RING(CP_PACKET0(R300_CP_RESYNC_DATA, 0)); +	OUT_RING(*id); +	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); +	OUT_RING(R300_RB3D_DC_FINISH); +	ADVANCE_RING();	 +} + +uint32_t r100_cs_id_last_get(struct drm_device *dev) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	return RADEON_READ(RADEON_SCRATCH_REG4); +} + +uint32_t r300_cs_id_last_get(struct drm_device *dev) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	return RADEON_READ(RADEON_SCRATCH_REG6); +} + +int radeon_cs_init(struct drm_device *dev) +{ +	drm_radeon_private_t *dev_priv = dev->dev_private; + +	if (dev_priv->chip_family < CHIP_RV280) { +		dev_priv->cs.id_emit = r100_cs_id_emit; +		dev_priv->cs.id_last_get = r100_cs_id_last_get; +	} else if (dev_priv->chip_family < CHIP_R600) { +		dev_priv->cs.id_emit = r300_cs_id_emit; +		dev_priv->cs.id_last_get = r300_cs_id_last_get; +	} + +	dev_priv->cs.parse = radeon_cs_parse; +	/* ib get depends on memory manager or not so memory manager */ +	return 0; +} diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 7fcf9305..c20de561 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -506,6 +506,7 @@ typedef struct {  #define DRM_RADEON_GEM_SET_DOMAIN 0x23  #define DRM_RADEON_GEM_INDIRECT 0x24 // temporary for X server +#define DRM_RADEON_CS           0x25  #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)  #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START) @@ -545,6 +546,7 @@ typedef struct {  #define DRM_IOCTL_RADEON_GEM_SET_DOMAIN  DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)  #define DRM_IOCTL_RADEON_GEM_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INDIRECT, struct drm_radeon_gem_indirect) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)  typedef struct drm_radeon_init { @@ -861,4 +863,17 @@ struct drm_radeon_gem_indirect {  	uint32_t used;  }; +/* New interface which obsolete all previous interface. + */ + + +struct drm_radeon_cs { +//	uint32_t __user     *packets; +	uint32_t            dwords; +	uint32_t            cs_id; +	uint64_t            packets; + +}; + +  #endif diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index b8f49404..c431fe4a 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -195,11 +195,11 @@ enum radeon_mac_model {  #define GET_RING_HEAD(dev_priv)	(dev_priv->writeback_works ? \ -				 (dev_priv->mm.ring_read_ptr ? readl(dev_priv->mm.ring_read_ptr_map.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \ +				 (dev_priv->mm.ring_read.bo ? readl(dev_priv->mm.ring_read.kmap.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \  				 RADEON_READ(RADEON_CP_RB_RPTR)) -#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read_ptr ? \ -				     writel((val), dev_priv->mm.ring_read_ptr_map.virtual) : \ +#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read.bo ? \ +				     writel((val), dev_priv->mm.ring_read.kmap.virtual) : \  				     DRM_WRITE32((dev_priv)->ring_rptr, 0, (val)))  typedef struct drm_radeon_freelist { @@ -261,6 +261,11 @@ struct radeon_virt_surface {  	struct drm_file *file_priv;  }; +struct radeon_mm_obj { +	struct drm_buffer_object *bo; +	struct drm_bo_kmap_obj kmap; +}; +  struct radeon_mm_info {  	uint64_t vram_offset; // Offset into GPU space  	uint64_t vram_size; @@ -268,15 +273,10 @@ struct radeon_mm_info {  	uint64_t gart_start;  	uint64_t gart_size; - -	struct drm_buffer_object *pcie_table; -	struct drm_bo_kmap_obj pcie_table_map; - -	struct drm_buffer_object *ring; -	struct drm_bo_kmap_obj ring_map; - -	struct drm_buffer_object *ring_read_ptr; -	struct drm_bo_kmap_obj ring_read_ptr_map; +	 +	struct radeon_mm_obj pcie_table; +	struct radeon_mm_obj ring; +	struct radeon_mm_obj ring_read;  };  #include "radeon_mode.h" @@ -286,6 +286,25 @@ struct drm_radeon_master_private {  	drm_radeon_sarea_t *sarea_priv;  }; +/* command submission struct */ +struct drm_radeon_cs_priv { +	uint32_t id_wcnt; +	uint32_t id_scnt; +	uint32_t id_last_wcnt; +	uint32_t id_last_scnt; + +	int (*parse)(struct drm_device *dev, void *ib, +			uint32_t *packets, uint32_t dwords); +	void (*id_emit)(struct drm_device *dev, uint32_t *id); +	uint32_t (*id_last_get)(struct drm_device *dev); +	/* this ib handling callback are for hidding memory manager drm +	 * from memory manager less drm, free have to emit ib discard +	 * sequence into the ring */ +	int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords); +	uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib); +	void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords); +}; +  typedef struct drm_radeon_private {  	drm_radeon_ring_buffer_t ring; @@ -392,7 +411,11 @@ typedef struct drm_radeon_private {  	u32 ram_width;  	enum radeon_pll_errata pll_errata; -	 + +	struct radeon_mm_obj **ib_objs; +	/* ib bitmap */ +	uint64_t ib_alloc_bitmap; // TO DO replace with a real bitmap +	struct drm_radeon_cs_priv cs;  } drm_radeon_private_t;  typedef struct drm_radeon_buf_priv { @@ -669,14 +692,15 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,  #define RADEON_SCRATCH_REG3		0x15ec  #define RADEON_SCRATCH_REG4		0x15f0  #define RADEON_SCRATCH_REG5		0x15f4 +#define RADEON_SCRATCH_REG6		0x15f8  #define RADEON_SCRATCH_UMSK		0x0770  #define RADEON_SCRATCH_ADDR		0x0774  #define RADEON_SCRATCHOFF( x )		(RADEON_SCRATCH_REG_OFFSET + 4*(x))  #define GET_SCRATCH( x )	(dev_priv->writeback_works ?			\ -				 (dev_priv->mm.ring_read_ptr ? \ -				  readl(dev_priv->mm.ring_read_ptr_map.virtual + RADEON_SCRATCHOFF(0)) : \ +				 (dev_priv->mm.ring_read.bo ? \ +				  readl(dev_priv->mm.ring_read.kmap.virtual + RADEON_SCRATCHOFF(0)) : \  				  DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \  				 RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x))) @@ -1593,4 +1617,6 @@ extern void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on);  extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);  extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);  extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master); +extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); +extern int radeon_cs_init(struct drm_device *dev);  #endif				/* __RADEON_DRV_H__ */ diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 6de4b135..d56dac19 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3279,6 +3279,7 @@ struct drm_ioctl_desc radeon_ioctls[] = {  	DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),  	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),  	DRM_IOCTL_DEF(DRM_RADEON_GEM_INDIRECT, radeon_gem_indirect_ioctl, DRM_AUTH), +	DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),  };  int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); | 
