aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/drm2
diff options
context:
space:
mode:
authorTijl Coosemans <tijl@FreeBSD.org>2014-10-30 14:26:36 +0000
committerTijl Coosemans <tijl@FreeBSD.org>2014-10-30 14:26:36 +0000
commit1f733a56465201ce5be94cfdcb8e269b24b7b191 (patch)
tree163b17808d43a7389d8787a0d982bdea40d80ca9 /sys/dev/drm2
parentb5019d3a0ce2fcb86cf7b637a86e1cc167728fae (diff)
downloadsrc-1f733a56465201ce5be94cfdcb8e269b24b7b191.tar.gz
src-1f733a56465201ce5be94cfdcb8e269b24b7b191.zip
Port the TTM AGP backend to the FreeBSD agp driver and enable AGP support
in the radeonkms driver. Note: In PCI mode virtual addresses on the graphics card that map to system RAM are translated to physical addresses by the graphics card itself. In AGP mode address translation is done by the AGP chipset so fictitious addresses appear on the system bus. For the CPU cache management to work correctly when the CPU accesses this memory it needs to use the same fictitious addresses (and let the chipset translate them) instead of using the physical addresses directly. Reviewed by: kib MFC after: 1 month
Notes
Notes: svn path=/head/; revision=273862
Diffstat (limited to 'sys/dev/drm2')
-rw-r--r--sys/dev/drm2/drm_agpsupport.c2
-rw-r--r--sys/dev/drm2/radeon/radeon.h1
-rw-r--r--sys/dev/drm2/radeon/radeon_device.c26
-rw-r--r--sys/dev/drm2/radeon/radeon_ttm.c6
-rw-r--r--sys/dev/drm2/ttm/ttm_agp_backend.c41
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_driver.h5
-rw-r--r--sys/dev/drm2/ttm/ttm_page_alloc.c34
7 files changed, 55 insertions, 60 deletions
diff --git a/sys/dev/drm2/drm_agpsupport.c b/sys/dev/drm2/drm_agpsupport.c
index eafe11759df4..1f487e36d965 100644
--- a/sys/dev/drm2/drm_agpsupport.c
+++ b/sys/dev/drm2/drm_agpsupport.c
@@ -396,7 +396,7 @@ void *drm_agp_allocate_memory(size_t pages, u32 type)
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)
diff --git a/sys/dev/drm2/radeon/radeon.h b/sys/dev/drm2/radeon/radeon.h
index aabe9aa4f413..8d932d9528ab 100644
--- a/sys/dev/drm2/radeon/radeon.h
+++ b/sys/dev/drm2/radeon/radeon.h
@@ -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 */
diff --git a/sys/dev/drm2/radeon/radeon_device.c b/sys/dev/drm2/radeon/radeon_device.c
index a20b7ec4901d..370e54185b17 100644
--- a/sys/dev/drm2/radeon/radeon_device.c
+++ b/sys/dev/drm2/radeon/radeon_device.c
@@ -1014,6 +1014,7 @@ int radeon_device_init(struct radeon_device *rdev,
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_device *rdev,
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_device *rdev)
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
diff --git a/sys/dev/drm2/radeon/radeon_ttm.c b/sys/dev/drm2/radeon/radeon_ttm.c
index 22c0935b84c5..f4ac1787bf5a 100644
--- a/sys/dev/drm2/radeon/radeon_ttm.c
+++ b/sys/dev/drm2/radeon/radeon_ttm.c
@@ -560,12 +560,10 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev,
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 ttm_tt *ttm)
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(struct ttm_tt *ttm)
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
diff --git a/sys/dev/drm2/ttm/ttm_agp_backend.c b/sys/dev/drm2/ttm/ttm_agp_backend.c
index 48f2193f8330..004243d4003f 100644
--- a/sys/dev/drm2/ttm/ttm_agp_backend.c
+++ b/sys/dev/drm2/ttm/ttm_agp_backend.c
@@ -41,7 +41,8 @@ __FBSDID("$FreeBSD$");
struct ttm_agp_backend {
struct ttm_tt ttm;
- struct agp_memory *mem;
+ vm_offset_t offset;
+ vm_page_t *pages;
device_t bridge;
};
@@ -51,31 +52,23 @@ static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
{
struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
struct drm_mm_node *node = bo_mem->mm_node;
- struct agp_memory *mem;
- int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED);
+ int ret;
unsigned i;
- mem = agp_alloc_memory(agp_be->bridge, AGP_USER_MEMORY, ttm->num_pages);
- if (unlikely(mem == NULL))
- return -ENOMEM;
-
- 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;
+ agp_be->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);
+ agp_be->offset = node->start * PAGE_SIZE;
+ ret = -agp_bind_pages(agp_be->bridge, agp_be->pages,
+ ttm->num_pages << PAGE_SHIFT, agp_be->offset);
if (ret)
- pr_err("AGP Bind memory failed\n");
+ printf("[TTM] AGP Bind memory failed\n");
return ret;
}
@@ -84,22 +77,16 @@ static int ttm_agp_unbind(struct ttm_tt *ttm)
{
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);
- agp_be->mem = NULL;
- }
- return 0;
+ return -agp_unbind_pages(agp_be->bridge, ttm->num_pages << PAGE_SHIFT,
+ agp_be->offset);
}
static void ttm_agp_destroy(struct ttm_tt *ttm)
{
struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm);
- if (agp_be->mem)
- ttm_agp_unbind(ttm);
ttm_tt_fini(ttm);
+ free(agp_be->pages, M_TTM_AGP);
free(agp_be, M_TTM_AGP);
}
@@ -118,14 +105,18 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
agp_be = malloc(sizeof(*agp_be), M_TTM_AGP, M_WAITOK | M_ZERO);
- agp_be->mem = NULL;
agp_be->bridge = bridge;
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;
}
+ agp_be->offset = 0;
+ agp_be->pages = malloc(agp_be->ttm.num_pages * sizeof(*agp_be->pages),
+ M_TTM_AGP, M_WAITOK);
+
return &agp_be->ttm;
}
diff --git a/sys/dev/drm2/ttm/ttm_bo_driver.h b/sys/dev/drm2/ttm/ttm_bo_driver.h
index 68c5c0ea001f..c4aefab92fe2 100644
--- a/sys/dev/drm2/ttm/ttm_bo_driver.h
+++ b/sys/dev/drm2/ttm/ttm_bo_driver.h
@@ -990,9 +990,8 @@ extern vm_memattr_t ttm_io_prot(uint32_t caching_flags);
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_func ttm_bo_manager_func;
* 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);
diff --git a/sys/dev/drm2/ttm/ttm_page_alloc.c b/sys/dev/drm2/ttm/ttm_page_alloc.c
index 8f513d0ddeaa..2dcecd139a8f 100644
--- a/sys/dev/drm2/ttm/ttm_page_alloc.c
+++ b/sys/dev/drm2/ttm/ttm_page_alloc.c
@@ -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;
}