Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Oct 2014 16:24:42 +0100
From:      Tijl Coosemans <tijl@FreeBSD.org>
To:        x11@FreeBSD.org, kib@FreeBSD.org, dumbbell@FreeBSD.org
Subject:   [rfc] Radeon AGP support patches
Message-ID:  <20141026162442.1330d4c3@kalimero.tijl.coosemans.org>

next in thread | raw e-mail | index | archive | help
--MP_/g.m.arrYGIU2b4/NXP_KxQo
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi,

I worked on AGP support for Radeon cards this week.  Please take a look
at the attached patches.

Patch 1:
Adds support for AGP_USER_TYPES to sys/dev/agp.  For normal memory types
a vm_object is allocated, for user types only a vm_page array.  It is
then up to the caller (e.g. TTM code) to manage this array.  Arbitrary
pages can be mapped into the GTT this way.

Patch 2:
This isn't needed for AGP support but it's something I ran into when
chasing a bug.  The handle field in our drm_local_map_t is different
than in Linux.  On Linux this field contains a unique ID for user space
maps and a virtual address for kernel space maps.  On FreeBSD this
field always contains a unique ID and the virtual address of kernel
space maps is stored in another field named virtual.  See the old DRM
code in sys/dev/drm.  I think most of the changes in the patch are in
dead code (unless the driver still supports running old DRMv1 X servers).

Patch 3:
Enable AGP support in sys/dev/drm2.  In PCI mode the GTT exists on the
graphics card so when accessing system memory it already does its own
virtual address translation and only physical addresses appear on the
system bus.  The CPU can access the same addresses with its own VM
system like it always does.  In AGP mode, translation is done by the
AGP chipset so fictitious addresses appear on the system bus.  For the
CPU cache management to work correctly it needs to use these same
fictitious addresses instead of using the real physical addresses
directly.  The patch marks the AGP aperture range fictitious in
radeon_device.c where the VRAM aperture is also marked fictitious such
that PHYS_TO_VM_PAGE in ttm_bo_vm_fault works for addresses in this
range.

The rest of the patch is mostly porting to our agp_* API.  It also
fixes two memory leaks in ttm_agp_backend.c.  One is a missing free in
ttm_agp_tt_create.  The other is because ttm_agp_bind allocates an
agp_memory struct but ttm_agp_unbind does not free it.  So when calling
ttm_agp_bind a second time the reference to the struct is lost.  The
patch changes ttm_agp_bind so the allocation only happens in the first
call.  The struct is released in ttm_agp_destroy.

The changes to ttm_page_alloc.c reduce the diff with Linux.

Patch 4:
Something else I ran into.  In function ttm_bo_kmap_ttm when mapping a
TTM buffer object in kernel space that may be cached (TTM_PL_FLAG_CACHED)
use normal WB caching like Linux does instead of WC.  I think this may be
a copy-paste error from similar looking code in ttm_bo_ioremap that is
defined right above this function.
--MP_/g.m.arrYGIU2b4/NXP_KxQo
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=radeon-agp-1.patch

Index: sys/dev/agp/agp.c
===================================================================
--- sys/dev/agp/agp.c	(revision 273255)
+++ sys/dev/agp/agp.c	(working copy)
@@ -483,29 +483,36 @@ agp_generic_alloc_memory(device_t dev, i
 	struct agp_memory *mem;
 
 	if ((size & (AGP_PAGE_SIZE - 1)) != 0)
-		return 0;
+		return (NULL);
 
-	if (sc->as_allocated + size > sc->as_maxmem)
-		return 0;
+	if (size > sc->as_maxmem - sc->as_allocated)
+		return (NULL);
 
-	if (type != 0) {
+	if (type >= AGP_USER_TYPES) {
+		mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
+		mem->am_pages = malloc(atop(round_page(size)) *
+				       sizeof(*mem->am_pages), M_AGP,
+				       M_WAITOK | M_ZERO);
+	} else if (type == AGP_NORMAL_MEMORY) {
+		mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
+		mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
+						 atop(round_page(size)));
+	} else {
 		printf("agp_generic_alloc_memory: unsupported type %d\n",
 		       type);
-		return 0;
+		return (NULL);
 	}
 
-	mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
 	mem->am_id = sc->as_nextid++;
 	mem->am_size = size;
-	mem->am_type = 0;
-	mem->am_obj = vm_object_allocate(OBJT_DEFAULT, atop(round_page(size)));
+	mem->am_type = type;
 	mem->am_physical = 0;
 	mem->am_offset = 0;
 	mem->am_is_bound = 0;
 	TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link);
 	sc->as_allocated += size;
 
-	return mem;
+	return (mem);
 }
 
 int
@@ -518,7 +525,10 @@ agp_generic_free_memory(device_t dev, st
 
 	sc->as_allocated -= mem->am_size;
 	TAILQ_REMOVE(&sc->as_memory, mem, am_link);
-	vm_object_deallocate(mem->am_obj);
+	if (mem->am_type >= AGP_USER_TYPES)
+		free(mem->am_pages, M_AGP);
+	else
+		vm_object_deallocate(mem->am_obj);
 	free(mem, M_AGP);
 	return 0;
 }
@@ -537,7 +547,46 @@ agp_generic_bind_memory(device_t dev, st
 	    offset + mem->am_size > AGP_GET_APERTURE(dev)) {
 		device_printf(dev, "binding memory at bad offset %#x\n",
 		    (int)offset);
-		return EINVAL;
+		return (EINVAL);
+	}
+
+	if (mem->am_type >= AGP_USER_TYPES) {
+		mtx_lock(&sc->as_lock);
+		if (mem->am_is_bound) {
+			device_printf(dev, "memory already bound\n");
+			mtx_unlock(&sc->as_lock);
+			return (EINVAL);
+		}
+		for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
+			m = mem->am_pages[i >> PAGE_SHIFT];
+
+			/*
+			 * Install entries in the GATT, making sure that if
+			 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
+			 * aligned to PAGE_SIZE, we don't modify too many GATT 
+			 * entries.
+			 */
+			for (j = 0; j < PAGE_SIZE && i + j < mem->am_size;
+			     j += AGP_PAGE_SIZE) {
+				vm_offset_t pa = VM_PAGE_TO_PHYS(m) + j;
+				AGP_DPF("binding offset %#jx to pa %#jx\n",
+					(uintmax_t)offset + i + j,
+					(uintmax_t)pa);
+				error = AGP_BIND_PAGE(dev, offset + i + j, pa);
+				if (error) {
+					/*
+					 * Bail out. Reverse all the mappings.
+					 */
+					for (k = 0; k < i + j;
+					     k += AGP_PAGE_SIZE)
+						AGP_UNBIND_PAGE(dev,
+								offset + k);
+					mtx_unlock(&sc->as_lock);
+					return (error);
+				}
+			}
+		}
+		goto done;
 	}
 
 	/*
@@ -604,6 +653,7 @@ agp_generic_bind_memory(device_t dev, st
 	}
 	VM_OBJECT_WUNLOCK(mem->am_obj);
 
+done:
 	/*
 	 * Flush the cpu cache since we are providing a new mapping
 	 * for these pages.
@@ -620,7 +670,7 @@ agp_generic_bind_memory(device_t dev, st
 
 	mtx_unlock(&sc->as_lock);
 
-	return 0;
+	return (0);
 bad:
 	mtx_unlock(&sc->as_lock);
 	VM_OBJECT_ASSERT_WLOCKED(mem->am_obj);
@@ -634,7 +684,7 @@ bad:
 	}
 	VM_OBJECT_WUNLOCK(mem->am_obj);
 
-	return error;
+	return (error);
 }
 
 int
@@ -659,15 +709,16 @@ agp_generic_unbind_memory(device_t dev, 
 	 */
 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
 		AGP_UNBIND_PAGE(dev, mem->am_offset + i);
-	VM_OBJECT_WLOCK(mem->am_obj);
-	for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
-		m = vm_page_lookup(mem->am_obj, atop(i));
-		vm_page_lock(m);
-		vm_page_unwire(m, PQ_INACTIVE);
-		vm_page_unlock(m);
+	if (mem->am_type < AGP_USER_TYPES) {
+		VM_OBJECT_WLOCK(mem->am_obj);
+		for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
+			m = vm_page_lookup(mem->am_obj, atop(i));
+			vm_page_lock(m);
+			vm_page_unwire(m, PQ_INACTIVE);
+			vm_page_unlock(m);
+		}
+		VM_OBJECT_WUNLOCK(mem->am_obj);
 	}
-	VM_OBJECT_WUNLOCK(mem->am_obj);
-		
 	agp_flush_cache();
 	AGP_FLUSH_TLB(dev);
 
@@ -756,6 +807,9 @@ agp_allocate_user(device_t dev, agp_allo
 {
 	struct agp_memory *mem;
 
+	if (alloc->type >= AGP_USER_TYPES)
+		return EINVAL;
+
 	mem = AGP_ALLOC_MEMORY(dev,
 			       alloc->type,
 			       alloc->pg_count << AGP_PAGE_SHIFT);
Index: sys/dev/agp/agppriv.h
===================================================================
--- sys/dev/agp/agppriv.h	(revision 273255)
+++ sys/dev/agp/agppriv.h	(working copy)
@@ -55,7 +55,10 @@ struct agp_memory {
 	int		am_id;			/* unique id for block */
 	vm_size_t	am_size;		/* number of bytes allocated */
 	int		am_type;		/* chipset specific type */
-	struct vm_object *am_obj;		/* VM object owning pages */
+	union {
+		struct vm_object *am_obj;	/* VM object owning pages */
+		struct vm_page **am_pages;	/* user types pages */
+	};
 	vm_offset_t	am_physical;		/* bogus hack for i810 */
 	vm_offset_t	am_offset;		/* page offset if bound */
 	int		am_is_bound;		/* non-zero if bound */

--MP_/g.m.arrYGIU2b4/NXP_KxQo
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=radeon-agp-2.patch

Index: sys/dev/drm2/ati_pcigart.c
===================================================================
--- sys/dev/drm2/ati_pcigart.c	(revision 273255)
+++ sys/dev/drm2/ati_pcigart.c	(working copy)
@@ -152,7 +152,7 @@ int drm_ati_pcigart_init(struct drm_devi
 	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
 		memset(pci_gart, 0, max_ati_pages * sizeof(u32));
 	} else {
-		memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32));
+		memset_io((void __iomem *)map->virtual, 0, max_ati_pages * sizeof(u32));
 	}
 
 	gart_idx = 0;
Index: sys/dev/drm2/radeon/r600_blit.c
===================================================================
--- sys/dev/drm2/radeon/r600_blit.c	(revision 273255)
+++ sys/dev/drm2/radeon/r600_blit.c	(working copy)
@@ -136,8 +136,8 @@ set_shaders(struct drm_device *dev)
 	DRM_DEBUG("\n");
 
 	/* load shaders */
-	vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset);
-	ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256);
+	vs = (u32 *) ((char *)dev->agp_buffer_map->virtual + dev_priv->blit_vb->offset);
+	ps = (u32 *) ((char *)dev->agp_buffer_map->virtual + dev_priv->blit_vb->offset + 256);
 
 	for (i = 0; i < r6xx_vs_size; i++)
 		vs[i] = cpu_to_le32(r6xx_vs[i]);
@@ -545,7 +545,7 @@ static void r600_nomm_put_vb(struct drm_
 static void *r600_nomm_get_vb_ptr(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	return (((char *)dev->agp_buffer_map->handle +
+	return (((char *)dev->agp_buffer_map->virtual +
 		 dev_priv->blit_vb->offset + dev_priv->blit_vb->used));
 }
 
Index: sys/dev/drm2/radeon/r600_cp.c
===================================================================
--- sys/dev/drm2/radeon/r600_cp.c	(revision 273255)
+++ sys/dev/drm2/radeon/r600_cp.c	(working copy)
@@ -176,7 +176,7 @@ int r600_page_table_init(struct drm_devi
 	pages = (entry->pages <= max_real_pages) ?
 		entry->pages : max_real_pages;
 
-	memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u64));
+	memset_io((void __iomem *)map->virtual, 0, max_ati_pages * sizeof(u64));
 
 	gart_idx = 0;
 	for (i = 0; i < pages; i++) {
@@ -2074,14 +2074,13 @@ int r600_do_init_cp(struct drm_device *d
 	}
 
 #if __OS_HAS_AGP
-	/* XXX */
 	if (dev_priv->flags & RADEON_IS_AGP) {
 		drm_core_ioremap_wc(dev_priv->cp_ring, dev);
 		drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
 		drm_core_ioremap_wc(dev->agp_buffer_map, dev);
-		if (!dev_priv->cp_ring->handle ||
-		    !dev_priv->ring_rptr->handle ||
-		    !dev->agp_buffer_map->handle) {
+		if (!dev_priv->cp_ring->virtual ||
+		    !dev_priv->ring_rptr->virtual ||
+		    !dev->agp_buffer_map->virtual) {
 			DRM_ERROR("could not find ioremap agp regions!\n");
 			r600_do_cleanup_cp(dev);
 			return -EINVAL;
@@ -2089,18 +2088,18 @@ int r600_do_init_cp(struct drm_device *d
 	} else
 #endif
 	{
-		dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset;
-		dev_priv->ring_rptr->handle =
+		dev_priv->cp_ring->virtual = (void *)(unsigned long)dev_priv->cp_ring->offset;
+		dev_priv->ring_rptr->virtual =
 			(void *)(unsigned long)dev_priv->ring_rptr->offset;
-		dev->agp_buffer_map->handle =
+		dev->agp_buffer_map->virtual =
 			(void *)(unsigned long)dev->agp_buffer_map->offset;
 
-		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
-			  dev_priv->cp_ring->handle);
-		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
-			  dev_priv->ring_rptr->handle);
-		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
-			  dev->agp_buffer_map->handle);
+		DRM_DEBUG("dev_priv->cp_ring->virtual %p\n",
+			  dev_priv->cp_ring->virtual);
+		DRM_DEBUG("dev_priv->ring_rptr->virtual %p\n",
+			  dev_priv->ring_rptr->virtual);
+		DRM_DEBUG("dev->agp_buffer_map->virtual %p\n",
+			  dev->agp_buffer_map->virtual);
 	}
 
 	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24;
@@ -2180,8 +2179,8 @@ int r600_do_init_cp(struct drm_device *d
 	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n",
 		  dev_priv->gart_buffers_offset);
 
-	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
-	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->virtual;
+	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->virtual
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
 	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
@@ -2220,14 +2219,14 @@ int r600_do_init_cp(struct drm_device *d
 			dev_priv->gart_info.table_size;
 
 		drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
-		if (!dev_priv->gart_info.mapping.handle) {
+		if (!dev_priv->gart_info.mapping.virtual) {
 			DRM_ERROR("ioremap failed.\n");
 			r600_do_cleanup_cp(dev);
 			return -EINVAL;
 		}
 
 		dev_priv->gart_info.addr =
-			dev_priv->gart_info.mapping.handle;
+			dev_priv->gart_info.mapping.virtual;
 
 		DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
 			  dev_priv->gart_info.addr,
@@ -2381,7 +2380,7 @@ int r600_cp_dispatch_indirect(struct drm
 		 */
 		while (dwords & 0xf) {
 			u32 *data = (u32 *)
-			    ((char *)dev->agp_buffer_map->handle
+			    ((char *)dev->agp_buffer_map->virtual
 			     + buf->offset + start);
 			data[dwords++] = RADEON_CP_PACKET2;
 		}
@@ -2510,7 +2509,7 @@ int r600_cp_dispatch_texture(struct drm_
 		/* Dispatch the indirect buffer.
 		 */
 		buffer =
-		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+		    (u32 *) ((char *)dev->agp_buffer_map->virtual + buf->offset);
 
 		if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
 			DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
@@ -2619,7 +2618,7 @@ int r600_cs_legacy_ioctl(struct drm_devi
 		DRM_ERROR("ib_get failed\n");
 		goto out;
 	}
-	ib = (u32 *)((uintptr_t)dev->agp_buffer_map->handle + buf->offset);
+	ib = (u32 *)((uintptr_t)dev->agp_buffer_map->virtual + buf->offset);
 	/* now parse command stream */
 	r = r600_cs_legacy(dev, data,  fpriv, family, ib, &l);
 	if (r) {
Index: sys/dev/drm2/radeon/radeon_cp.c
===================================================================
--- sys/dev/drm2/radeon/radeon_cp.c	(revision 273255)
+++ sys/dev/drm2/radeon/radeon_cp.c	(working copy)
@@ -64,7 +64,7 @@ u32 radeon_read_ring_rptr(drm_radeon_pri
 		val = DRM_READ32(dev_priv->ring_rptr, off);
 	} else {
 		val = *(((volatile u32 *)
-			 dev_priv->ring_rptr->handle) +
+			 dev_priv->ring_rptr->virtual) +
 			(off / sizeof(u32)));
 		val = le32_to_cpu(val);
 	}
@@ -88,7 +88,7 @@ void radeon_write_ring_rptr(drm_radeon_p
 	if (dev_priv->flags & RADEON_IS_AGP)
 		DRM_WRITE32(dev_priv->ring_rptr, off, val);
 	else
-		*(((volatile u32 *) dev_priv->ring_rptr->handle) +
+		*(((volatile u32 *) dev_priv->ring_rptr->virtual) +
 		  (off / sizeof(u32))) = cpu_to_le32(val);
 }
 
@@ -1330,9 +1330,9 @@ static int radeon_do_init_cp(struct drm_
 		drm_core_ioremap_wc(dev_priv->cp_ring, dev);
 		drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
 		drm_core_ioremap_wc(dev->agp_buffer_map, dev);
-		if (!dev_priv->cp_ring->handle ||
-		    !dev_priv->ring_rptr->handle ||
-		    !dev->agp_buffer_map->handle) {
+		if (!dev_priv->cp_ring->virtual ||
+		    !dev_priv->ring_rptr->virtual ||
+		    !dev->agp_buffer_map->virtual) {
 			DRM_ERROR("could not find ioremap agp regions!\n");
 			radeon_do_cleanup_cp(dev);
 			return -EINVAL;
@@ -1340,19 +1340,19 @@ static int radeon_do_init_cp(struct drm_
 	} else
 #endif
 	{
-		dev_priv->cp_ring->handle =
+		dev_priv->cp_ring->virtual =
 			(void *)(unsigned long)dev_priv->cp_ring->offset;
-		dev_priv->ring_rptr->handle =
+		dev_priv->ring_rptr->virtual =
 			(void *)(unsigned long)dev_priv->ring_rptr->offset;
-		dev->agp_buffer_map->handle =
+		dev->agp_buffer_map->virtual =
 			(void *)(unsigned long)dev->agp_buffer_map->offset;
 
-		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
-			  dev_priv->cp_ring->handle);
-		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
-			  dev_priv->ring_rptr->handle);
-		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
-			  dev->agp_buffer_map->handle);
+		DRM_DEBUG("dev_priv->cp_ring->virtual %p\n",
+			  dev_priv->cp_ring->virtual);
+		DRM_DEBUG("dev_priv->ring_rptr->virtual %p\n",
+			  dev_priv->ring_rptr->virtual);
+		DRM_DEBUG("dev->agp_buffer_map->virtual %p\n",
+			  dev->agp_buffer_map->virtual);
 	}
 
 	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
@@ -1430,8 +1430,8 @@ static int radeon_do_init_cp(struct drm_
 	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
 		  dev_priv->gart_buffers_offset);
 
-	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
-	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->virtual;
+	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->virtual
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
 	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
@@ -1467,7 +1467,7 @@ static int radeon_do_init_cp(struct drm_
 
 			drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
 			dev_priv->gart_info.addr =
-			    dev_priv->gart_info.mapping.handle;
+			    dev_priv->gart_info.mapping.virtual;
 
 			if (dev_priv->flags & RADEON_IS_PCIE)
 				dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
@@ -2139,7 +2139,7 @@ int radeon_master_create(struct drm_devi
 		free(master_priv, DRM_MEM_DRIVER);
 		return ret;
 	}
-	master_priv->sarea_priv = (drm_radeon_sarea_t *)((char *)master_priv->sarea->handle) +
+	master_priv->sarea_priv = (drm_radeon_sarea_t *)((char *)master_priv->sarea->virtual) +
 	    sizeof(struct drm_sarea);
 	master_priv->sarea_priv->pfCurrentPage = 0;
 
Index: sys/dev/drm2/radeon/radeon_state.c
===================================================================
--- sys/dev/drm2/radeon/radeon_state.c	(revision 273255)
+++ sys/dev/drm2/radeon/radeon_state.c	(working copy)
@@ -1453,7 +1453,7 @@ void radeon_cp_dispatch_flip(struct drm_
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	struct drm_radeon_master_private *master_priv = master->driver_priv;
-	struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle;
+	struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->virtual;
 	int offset = (master_priv->sarea_priv->pfCurrentPage == 1)
 	    ? dev_priv->front_offset : dev_priv->back_offset;
 	RING_LOCALS;
@@ -1618,7 +1618,7 @@ static void radeon_cp_dispatch_indirect(
 		 */
 		if (dwords & 1) {
 			u32 *data = (u32 *)
-			    ((char *)dev->agp_buffer_map->handle
+			    ((char *)dev->agp_buffer_map->virtual
 			     + buf->offset + start);
 			data[dwords++] = RADEON_CP_PACKET2;
 		}
@@ -1667,7 +1667,7 @@ static void radeon_cp_dispatch_indices(s
 
 	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
 
-	data = (u32 *) ((char *)dev->agp_buffer_map->handle +
+	data = (u32 *) ((char *)dev->agp_buffer_map->virtual +
 			elt_buf->offset + prim->start);
 
 	data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
@@ -1819,7 +1819,7 @@ static int radeon_cp_dispatch_texture(st
 		/* Dispatch the indirect buffer.
 		 */
 		buffer =
-		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+		    (u32 *) ((char *)dev->agp_buffer_map->virtual + buf->offset);
 		dwords = size / 4;
 
 #define RADEON_COPY_MT(_buf, _data, _width) \

--MP_/g.m.arrYGIU2b4/NXP_KxQo
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=radeon-agp-3.patch

Index: sys/dev/drm2/drm_agpsupport.c
===================================================================
--- sys/dev/drm2/drm_agpsupport.c	(revision 273255)
+++ sys/dev/drm2/drm_agpsupport.c	(working copy)
@@ -396,7 +396,7 @@ void *drm_agp_allocate_memory(size_t pag
 	if (!agpdev)
 		return NULL;
 
-	return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
+	return agp_alloc_memory(agpdev, type, pages << PAGE_SHIFT);
 }
 
 int drm_agp_free_memory(void *handle)
Index: sys/dev/drm2/radeon/radeon.h
===================================================================
--- sys/dev/drm2/radeon/radeon.h	(revision 273255)
+++ sys/dev/drm2/radeon/radeon.h	(working copy)
@@ -1618,6 +1618,7 @@ struct radeon_device {
 	bool				need_dma32;
 	bool				accel_working;
 	bool				fictitious_range_registered;
+	bool				fictitious_agp_range_registered;
 	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
 	const struct firmware *me_fw;	/* all family ME firmware */
 	const struct firmware *pfp_fw;	/* r6/700 PFP firmware */
Index: sys/dev/drm2/radeon/radeon_device.c
===================================================================
--- sys/dev/drm2/radeon/radeon_device.c	(revision 273255)
+++ sys/dev/drm2/radeon/radeon_device.c	(working copy)
@@ -1014,6 +1014,7 @@ int radeon_device_init(struct radeon_dev
 	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 	rdev->accel_working = false;
 	rdev->fictitious_range_registered = false;
+	rdev->fictitious_agp_range_registered = false;
 	/* set up ring ids */
 	for (i = 0; i < RADEON_NUM_RINGS; i++) {
 		rdev->ring[i].idx = i;
@@ -1168,6 +1169,24 @@ int radeon_device_init(struct radeon_dev
 		return (-r);
 	}
 	rdev->fictitious_range_registered = true;
+#if __OS_HAS_AGP
+	if (rdev->flags & RADEON_IS_AGP) {
+		DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n",
+		    __func__, (uintmax_t)rdev->mc.agp_base,
+		    (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size);
+		r = vm_phys_fictitious_reg_range(
+		    rdev->mc.agp_base,
+		    rdev->mc.agp_base + rdev->mc.gtt_size,
+		    VM_MEMATTR_WRITE_COMBINING);
+		if (r != 0) {
+			DRM_ERROR("Failed to register fictitious range "
+			    "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.agp_base,
+			    (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size, r);
+			return (-r);
+		}
+		rdev->fictitious_agp_range_registered = true;
+	}
+#endif
 
 	if ((radeon_testing & 1)) {
 		radeon_test_moves(rdev);
@@ -1205,6 +1224,13 @@ void radeon_device_fini(struct radeon_de
 		    rdev->mc.aper_base,
 		    rdev->mc.aper_base + rdev->mc.visible_vram_size);
 	}
+#if __OS_HAS_AGP
+	if (rdev->fictitious_agp_range_registered) {
+		vm_phys_fictitious_unreg_range(
+		    rdev->mc.agp_base,
+		    rdev->mc.agp_base + rdev->mc.gtt_size);
+	}
+#endif
 
 	radeon_fini(rdev);
 #ifdef DUMBBELL_WIP
Index: sys/dev/drm2/radeon/radeon_ttm.c
===================================================================
--- sys/dev/drm2/radeon/radeon_ttm.c	(revision 273255)
+++ sys/dev/drm2/radeon/radeon_ttm.c	(working copy)
@@ -560,12 +560,10 @@ static struct ttm_tt *radeon_ttm_tt_crea
 
 	rdev = radeon_get_rdev(bdev);
 #if __OS_HAS_AGP
-#ifdef DUMBBELL_WIP
 	if (rdev->flags & RADEON_IS_AGP) {
 		return ttm_agp_tt_create(bdev, rdev->ddev->agp->agpdev,
 					 size, page_flags, dummy_read_page);
 	}
-#endif /* DUMBBELL_WIP */
 #endif
 
 	gtt = malloc(sizeof(struct radeon_ttm_tt),
@@ -610,11 +608,9 @@ static int radeon_ttm_tt_populate(struct
 
 	rdev = radeon_get_rdev(ttm->bdev);
 #if __OS_HAS_AGP
-#ifdef DUMBBELL_WIP
 	if (rdev->flags & RADEON_IS_AGP) {
 		return ttm_agp_tt_populate(ttm);
 	}
-#endif /* DUMBBELL_WIP */
 #endif
 
 #ifdef CONFIG_SWIOTLB
@@ -660,12 +656,10 @@ static void radeon_ttm_tt_unpopulate(str
 
 	rdev = radeon_get_rdev(ttm->bdev);
 #if __OS_HAS_AGP
-#ifdef DUMBBELL_WIP
 	if (rdev->flags & RADEON_IS_AGP) {
 		ttm_agp_tt_unpopulate(ttm);
 		return;
 	}
-#endif /* DUMBBELL_WIP */
 #endif
 
 #ifdef CONFIG_SWIOTLB
Index: sys/dev/drm2/ttm/ttm_agp_backend.c
===================================================================
--- sys/dev/drm2/ttm/ttm_agp_backend.c	(revision 273255)
+++ sys/dev/drm2/ttm/ttm_agp_backend.c	(working copy)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/drm2/ttm/ttm_page_alloc.h>
 #ifdef TTM_HAS_AGP
 #include <dev/drm2/ttm/ttm_placement.h>
+#include <dev/agp/agppriv.h>
 
 struct ttm_agp_backend {
 	struct ttm_tt ttm;
@@ -55,27 +56,31 @@ static int ttm_agp_bind(struct ttm_tt *t
 	int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED);
 	unsigned i;
 
-	mem = agp_alloc_memory(agp_be->bridge, AGP_USER_MEMORY, ttm->num_pages);
-	if (unlikely(mem == NULL))
-		return -ENOMEM;
+	mem = agp_be->mem;
+	if (mem == NULL) {
+		mem = agp_alloc_memory(agp_be->bridge,
+			(cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY,
+			ttm->num_pages * PAGE_SIZE);
+		if (unlikely(mem == NULL))
+			return -ENOMEM;
+	} else if (mem->am_size != ttm->num_pages * PAGE_SIZE) {
+		printf("[TTM] size changed on AGP rebind\n");
+		return -EINVAL;
+	}
 
-	mem->page_count = 0;
 	for (i = 0; i < ttm->num_pages; i++) {
 		vm_page_t page = ttm->pages[i];
 
 		if (!page)
 			page = ttm->dummy_read_page;
 
-		mem->pages[mem->page_count++] = page;
+		mem->am_pages[i] = page;
 	}
 	agp_be->mem = mem;
 
-	mem->is_flushed = 1;
-	mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY;
-
-	ret = agp_bind_memory(mem, node->start);
+	ret = -agp_bind_memory(agp_be->bridge, mem, node->start * PAGE_SIZE);
 	if (ret)
-		pr_err("AGP Bind memory failed\n");
+		printf("[TTM] AGP Bind memory failed\n");
 
 	return ret;
 }
@@ -85,9 +90,9 @@ static int ttm_agp_unbind(struct ttm_tt 
 	struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
 
 	if (agp_be->mem) {
-		if (agp_be->mem->is_bound)
-			return agp_unbind_memory(agp_be->mem);
-		agp_free_memory(agp_be->mem);
+		if (agp_be->mem->am_is_bound)
+			return -agp_unbind_memory(agp_be->bridge, agp_be->mem);
+		agp_free_memory(agp_be->bridge, agp_be->mem);
 		agp_be->mem = NULL;
 	}
 	return 0;
@@ -123,6 +128,7 @@ struct ttm_tt *ttm_agp_tt_create(struct 
 	agp_be->ttm.func = &ttm_agp_func;
 
 	if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) {
+		free(agp_be, M_TTM_AGP);
 		return NULL;
 	}
 
Index: sys/dev/drm2/ttm/ttm_bo_driver.h
===================================================================
--- sys/dev/drm2/ttm/ttm_bo_driver.h	(revision 273255)
+++ sys/dev/drm2/ttm/ttm_bo_driver.h	(working copy)
@@ -990,9 +990,8 @@ extern vm_memattr_t ttm_io_prot(uint32_t
 
 extern const struct ttm_mem_type_manager_func ttm_bo_manager_func;
 
-#if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
+#if __OS_HAS_AGP
 #define TTM_HAS_AGP
-#include <linux/agp_backend.h>
 
 /**
  * ttm_agp_tt_create
@@ -1009,7 +1008,7 @@ extern const struct ttm_mem_type_manager
  * bind and unbind memory backing a ttm_tt.
  */
 extern struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
-					struct agp_bridge_data *bridge,
+					device_t bridge,
 					unsigned long size, uint32_t page_flags,
 					struct vm_page *dummy_read_page);
 int ttm_agp_tt_populate(struct ttm_tt *ttm);
Index: sys/dev/drm2/ttm/ttm_page_alloc.c
===================================================================
--- sys/dev/drm2/ttm/ttm_page_alloc.c	(revision 273255)
+++ sys/dev/drm2/ttm/ttm_page_alloc.c	(working copy)
@@ -45,10 +45,6 @@ __FBSDID("$FreeBSD$");
 #include <dev/drm2/ttm/ttm_bo_driver.h>
 #include <dev/drm2/ttm/ttm_page_alloc.h>
 
-#ifdef TTM_HAS_AGP
-#include <asm/agp.h>
-#endif
-
 #define NUM_PAGES_TO_ALLOC		(PAGE_SIZE/sizeof(vm_page_t))
 #define SMALL_ALLOCATION		16
 #define FREE_ALL_PAGES			(~0U)
@@ -220,46 +216,34 @@ static struct ttm_pool_manager *_manager
 
 static int set_pages_array_wb(vm_page_t *pages, int addrinarray)
 {
-	vm_page_t m;
+#ifdef TTM_HAS_AGP
 	int i;
 
-	for (i = 0; i < addrinarray; i++) {
-		m = pages[i];
-#ifdef TTM_HAS_AGP
-		unmap_page_from_agp(m);
+	for (i = 0; i < addrinarray; i++)
+		pmap_page_set_memattr(pages[i], VM_MEMATTR_WRITE_BACK);
 #endif
-		pmap_page_set_memattr(m, VM_MEMATTR_WRITE_BACK);
-	}
 	return 0;
 }
 
 static int set_pages_array_wc(vm_page_t *pages, int addrinarray)
 {
-	vm_page_t m;
+#ifdef TTM_HAS_AGP
 	int i;
 
-	for (i = 0; i < addrinarray; i++) {
-		m = pages[i];
-#ifdef TTM_HAS_AGP
-		map_page_into_agp(pages[i]);
+	for (i = 0; i < addrinarray; i++)
+		pmap_page_set_memattr(pages[i], VM_MEMATTR_WRITE_COMBINING);
 #endif
-		pmap_page_set_memattr(m, VM_MEMATTR_WRITE_COMBINING);
-	}
 	return 0;
 }
 
 static int set_pages_array_uc(vm_page_t *pages, int addrinarray)
 {
-	vm_page_t m;
+#ifdef TTM_HAS_AGP
 	int i;
 
-	for (i = 0; i < addrinarray; i++) {
-		m = pages[i];
-#ifdef TTM_HAS_AGP
-		map_page_into_agp(pages[i]);
+	for (i = 0; i < addrinarray; i++)
+		pmap_page_set_memattr(pages[i], VM_MEMATTR_UNCACHEABLE);
 #endif
-		pmap_page_set_memattr(m, VM_MEMATTR_UNCACHEABLE);
-	}
 	return 0;
 }
 

--MP_/g.m.arrYGIU2b4/NXP_KxQo
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=radeon-agp-4.patch

Index: sys/dev/drm2/ttm/ttm_bo_util.c
===================================================================
--- sys/dev/drm2/ttm/ttm_bo_util.c	(revision 273255)
+++ sys/dev/drm2/ttm/ttm_bo_util.c	(working copy)
@@ -508,7 +508,7 @@ static int ttm_bo_kmap_ttm(struct ttm_bu
 		 * or to make the buffer object look contiguous.
 		 */
 		prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
-			VM_MEMATTR_WRITE_COMBINING :
+			VM_MEMATTR_WRITE_BACK :
 			ttm_io_prot(mem->placement);
 		map->bo_kmap_type = ttm_bo_map_vmap;
 		map->num_pages = num_pages;

--MP_/g.m.arrYGIU2b4/NXP_KxQo--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20141026162442.1330d4c3>