From b81ca5e031b2fbd9c5c401057c72f5857f7f5a3a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Aug 2006 10:09:57 +0200 Subject: AGP backends for TTM. --- linux-core/drm_agpsupport.c | 165 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index dce27cdf..92868005 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -552,4 +552,169 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle) return agp_unbind_memory(handle); } +/* + * AGP ttm backend interface. + */ + +static int drm_agp_needs_cache_adjust_true(drm_ttm_backend_t *backend) { + return TRUE; +} + +static int drm_agp_needs_cache_adjust_false(drm_ttm_backend_t *backend) { + return FALSE; +} + +#define AGP_MEM_USER (1 << 16) +#define AGP_MEM_UCACHED (2 << 16) + +static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, + struct page **pages) { + + drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private; + struct page **cur_page, **last_page = pages + num_pages; + DRM_AGP_MEM *mem; + + DRM_DEBUG("drm_agp_populate_ttm\n"); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11) + mem = drm_agp_allocate_memory(num_pages, agp_priv->mem_type); +#else + mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->mem_type); +#endif + if (!mem) + return -1; + + DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count); + mem->page_count = 0; + for (cur_page = pages; cur_page < last_page; ++cur_page) { + mem->memory[mem->page_count++] = page_to_phys(*cur_page); + } + agp_priv->mem = mem; + return 0; +} + +static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, unsigned long offset) { + + drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private; + DRM_AGP_MEM *mem = agp_priv->mem; + int ret; + + DRM_DEBUG("drm_agp_bind_ttm\n"); + mem->is_flushed = FALSE; + ret = drm_agp_bind_memory(mem, offset); + if (ret) { + DRM_ERROR("AGP Bind memory failed\n"); + } + return ret; +} + +static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) { + + drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private; + + DRM_DEBUG("drm_agp_unbind_ttm\n"); + if (agp_priv->mem->is_bound) + return drm_agp_unbind_memory(agp_priv->mem); + else + return 0; +} + +static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) { + + drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private; + DRM_AGP_MEM *mem = agp_priv->mem; + + DRM_DEBUG("drm_agp_clear_ttm\n"); + if (mem) { + if (mem->is_bound) { + drm_agp_unbind_memory(mem); + } + agp_free_memory(mem); + } + agp_priv->mem = NULL; +} + +static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) { + + drm_agp_ttm_priv *agp_priv; + + if (backend) { + DRM_DEBUG("drm_agp_destroy_ttm\n"); + agp_priv = (drm_agp_ttm_priv *) backend->private; + if (agp_priv) { + if (agp_priv->mem) { + drm_agp_clear_ttm(backend); + } + drm_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS); + } + drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); + } +} + + +drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev) { + + drm_ttm_backend_t *agp_be; + drm_agp_ttm_priv *agp_priv; + + agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); + + if (!agp_be) + return NULL; + + agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS); + + if (!agp_priv) { + drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS); + return NULL; + } + + agp_priv->mem = NULL; + agp_priv->mem_type = AGP_MEM_USER; + agp_priv->bridge = dev->agp->bridge; + agp_priv->populated = FALSE; + agp_be->aperture_base = dev->agp->agp_info.aper_base; + agp_be->private = (void *) agp_priv; + agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_true; + agp_be->populate = drm_agp_populate; + agp_be->clear = drm_agp_clear_ttm; + agp_be->bind = drm_agp_bind_ttm; + agp_be->unbind = drm_agp_unbind_ttm; + agp_be->destroy = drm_agp_destroy_ttm; + return agp_be; +} + + +drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) { + + drm_ttm_backend_t *agp_be; + drm_agp_ttm_priv *agp_priv; + + agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); + + if (!agp_be) + return NULL; + + agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS); + + if (!agp_priv) { + drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS); + return NULL; + } + + agp_priv->mem = NULL; + agp_priv->mem_type = AGP_MEM_UCACHED; + agp_priv->bridge = dev->agp->bridge; + agp_priv->populated = FALSE; + agp_be->aperture_base = dev->agp->agp_info.aper_base; + agp_be->private = (void *) agp_priv; + agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_false; + agp_be->populate = drm_agp_populate; + agp_be->clear = drm_agp_clear_ttm; + agp_be->bind = drm_agp_bind_ttm; + agp_be->unbind = drm_agp_unbind_ttm; + agp_be->destroy = drm_agp_destroy_ttm; + return agp_be; +} + + #endif /* __OS_HAS_AGP */ -- cgit v1.2.3 From 7058d06317e17253d874bf4df7b09d0d52a5fd74 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Aug 2006 10:24:48 +0200 Subject: Initial i915 buffer object driver --- linux-core/drm_agpsupport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 92868005..e7226f1f 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -682,7 +682,7 @@ drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev) { agp_be->destroy = drm_agp_destroy_ttm; return agp_be; } - +EXPORT_SYMBOL(drm_agp_init_ttm_uncached); drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) { @@ -715,6 +715,6 @@ drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) { agp_be->destroy = drm_agp_destroy_ttm; return agp_be; } - +EXPORT_SYMBOL(drm_agp_init_ttm_cached); #endif /* __OS_HAS_AGP */ -- cgit v1.2.3 From 99acb7936660843090ea8a9f22d2d50d9433e0de Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 8 Sep 2006 17:24:38 +0200 Subject: Various bugfixes. --- linux-core/drm_agpsupport.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index e7226f1f..60ebc567 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -630,6 +630,7 @@ static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) { } agp_free_memory(mem); } + agp_priv->mem = NULL; } -- cgit v1.2.3 From 711f077b7423c1a436d703885c6d18a2ad2940aa Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 26 Sep 2006 14:36:53 +0200 Subject: Allow for a driver to overload the ttm backend object methods. --- linux-core/drm_agpsupport.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 60ebc567..22987b07 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -625,9 +625,7 @@ static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) { DRM_DEBUG("drm_agp_clear_ttm\n"); if (mem) { - if (mem->is_bound) { - drm_agp_unbind_memory(mem); - } + backend->unbind(backend); agp_free_memory(mem); } @@ -639,25 +637,28 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) { drm_agp_ttm_priv *agp_priv; if (backend) { - DRM_DEBUG("drm_agp_destroy_ttm\n"); - agp_priv = (drm_agp_ttm_priv *) backend->private; + DRM_DEBUG("drm_agp_destroy_ttm\n"); + agp_priv = (drm_agp_ttm_priv *) backend->private; if (agp_priv) { if (agp_priv->mem) { - drm_agp_clear_ttm(backend); + backend->clear(backend); } drm_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS); } - drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); + if (backend->needs_free) + drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); } } -drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev) { +drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev, + drm_ttm_backend_t *backend) { drm_ttm_backend_t *agp_be; drm_agp_ttm_priv *agp_priv; - agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); + agp_be = (backend != NULL) ? backend: + drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); if (!agp_be) return NULL; @@ -681,16 +682,20 @@ drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev) { agp_be->bind = drm_agp_bind_ttm; agp_be->unbind = drm_agp_unbind_ttm; agp_be->destroy = drm_agp_destroy_ttm; + agp_be->needs_free = (backend == NULL); return agp_be; } EXPORT_SYMBOL(drm_agp_init_ttm_uncached); -drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) { +drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev, + drm_ttm_backend_t *backend) { drm_ttm_backend_t *agp_be; drm_agp_ttm_priv *agp_priv; - agp_be = drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); + + agp_be = (backend != NULL) ? backend: + drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); if (!agp_be) return NULL; @@ -714,6 +719,7 @@ drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev) { agp_be->bind = drm_agp_bind_ttm; agp_be->unbind = drm_agp_unbind_ttm; agp_be->destroy = drm_agp_destroy_ttm; + agp_be->needs_free = (backend == NULL); return agp_be; } EXPORT_SYMBOL(drm_agp_init_ttm_cached); -- cgit v1.2.3 From 235f6fc650e9974211843b9196a903963dae0211 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 27 Sep 2006 09:27:31 +0200 Subject: Adapt to architecture-specific hooks for gatt pages. --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 22987b07..2dd80162 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -586,7 +586,7 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count); mem->page_count = 0; for (cur_page = pages; cur_page < last_page; ++cur_page) { - mem->memory[mem->page_count++] = page_to_phys(*cur_page); + mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*cur_page)); } agp_priv->mem = mem; return 0; -- cgit v1.2.3 From f2db76e2f206d2017f710eaddc4b33add4498898 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 11 Oct 2006 13:40:35 +0200 Subject: Big update: Adapt for new functions in the 2.6.19 kernel. Remove the ability to have multiple regions in one TTM. This simplifies a lot of code. Remove the ability to access TTMs from user space. We don't need it anymore without ttm regions. Don't change caching policy for evicted buffers. Instead change it only when the buffer is accessed by the CPU (on the first page fault). This tremendously speeds up eviction rates. Current code is safe for kernels <= 2.6.14. Should also be OK with 2.6.19 and above. --- linux-core/drm_agpsupport.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 2dd80162..77994d5c 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -683,6 +683,7 @@ drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev, agp_be->unbind = drm_agp_unbind_ttm; agp_be->destroy = drm_agp_destroy_ttm; agp_be->needs_free = (backend == NULL); + agp_be->drm_map_type = _DRM_AGP; return agp_be; } EXPORT_SYMBOL(drm_agp_init_ttm_uncached); @@ -720,6 +721,7 @@ drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev, agp_be->unbind = drm_agp_unbind_ttm; agp_be->destroy = drm_agp_destroy_ttm; agp_be->needs_free = (backend == NULL); + agp_be->drm_map_type = _DRM_AGP; return agp_be; } EXPORT_SYMBOL(drm_agp_init_ttm_cached); -- cgit v1.2.3 From 10150df02b7062b9975661ccd82b475cd23c8839 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 12 Oct 2006 12:09:16 +0200 Subject: Simplify the AGP backend interface somewhat. Fix buffer bound caching policy changing, Allow on-the-fly changing of caching policy on bound buffers if the hardware supports it. Allow drivers to use driver-specific AGP memory types for TTM AGP pages. Will make AGP drivers much easier to migrate. --- linux-core/drm_agpsupport.c | 85 +++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 57 deletions(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 77994d5c..902b8947 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -552,20 +552,16 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle) return agp_unbind_memory(handle); } + + /* * AGP ttm backend interface. */ -static int drm_agp_needs_cache_adjust_true(drm_ttm_backend_t *backend) { - return TRUE; +static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) { + return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 1 : 0); } -static int drm_agp_needs_cache_adjust_false(drm_ttm_backend_t *backend) { - return FALSE; -} - -#define AGP_MEM_USER (1 << 16) -#define AGP_MEM_UCACHED (2 << 16) static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, struct page **pages) { @@ -576,9 +572,9 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, DRM_DEBUG("drm_agp_populate_ttm\n"); #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11) - mem = drm_agp_allocate_memory(num_pages, agp_priv->mem_type); + mem = drm_agp_allocate_memory(num_pages, agp_priv->alloc_type); #else - mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->mem_type); + mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->alloc_type); #endif if (!mem) return -1; @@ -592,14 +588,19 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, return 0; } -static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, unsigned long offset) { - +static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, + unsigned long offset, + int cached) +{ drm_agp_ttm_priv *agp_priv = (drm_agp_ttm_priv *) backend->private; DRM_AGP_MEM *mem = agp_priv->mem; int ret; DRM_DEBUG("drm_agp_bind_ttm\n"); + DRM_MASK_VAL(backend->flags, DRM_BE_FLAG_BOUND_CACHED, + (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0); mem->is_flushed = FALSE; + mem->type = (cached) ? agp_priv->cached_type : agp_priv->uncached_type; ret = drm_agp_bind_memory(mem, offset); if (ret) { DRM_ERROR("AGP Bind memory failed\n"); @@ -645,56 +646,21 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) { } drm_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS); } - if (backend->needs_free) + if (backend->flags & DRM_BE_FLAG_NEEDS_FREE) drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); } } -drm_ttm_backend_t *drm_agp_init_ttm_uncached(struct drm_device *dev, - drm_ttm_backend_t *backend) { - - drm_ttm_backend_t *agp_be; - drm_agp_ttm_priv *agp_priv; - - agp_be = (backend != NULL) ? backend: - drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); - - if (!agp_be) - return NULL; - - agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS); - - if (!agp_priv) { - drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS); - return NULL; - } - - agp_priv->mem = NULL; - agp_priv->mem_type = AGP_MEM_USER; - agp_priv->bridge = dev->agp->bridge; - agp_priv->populated = FALSE; - agp_be->aperture_base = dev->agp->agp_info.aper_base; - agp_be->private = (void *) agp_priv; - agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_true; - agp_be->populate = drm_agp_populate; - agp_be->clear = drm_agp_clear_ttm; - agp_be->bind = drm_agp_bind_ttm; - agp_be->unbind = drm_agp_unbind_ttm; - agp_be->destroy = drm_agp_destroy_ttm; - agp_be->needs_free = (backend == NULL); - agp_be->drm_map_type = _DRM_AGP; - return agp_be; -} -EXPORT_SYMBOL(drm_agp_init_ttm_uncached); - -drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev, - drm_ttm_backend_t *backend) { +drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev, + drm_ttm_backend_t *backend, + unsigned alloc_type, + unsigned cached_type, + unsigned uncached_type) { drm_ttm_backend_t *agp_be; drm_agp_ttm_priv *agp_priv; - agp_be = (backend != NULL) ? backend: drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); @@ -709,21 +675,26 @@ drm_ttm_backend_t *drm_agp_init_ttm_cached(struct drm_device *dev, } agp_priv->mem = NULL; - agp_priv->mem_type = AGP_MEM_UCACHED; + agp_priv->alloc_type = alloc_type; + agp_priv->cached_type = cached_type; + agp_priv->uncached_type = uncached_type; agp_priv->bridge = dev->agp->bridge; agp_priv->populated = FALSE; agp_be->aperture_base = dev->agp->agp_info.aper_base; agp_be->private = (void *) agp_priv; - agp_be->needs_cache_adjust = drm_agp_needs_cache_adjust_false; + agp_be->needs_ub_cache_adjust = drm_agp_needs_unbind_cache_adjust; agp_be->populate = drm_agp_populate; agp_be->clear = drm_agp_clear_ttm; agp_be->bind = drm_agp_bind_ttm; agp_be->unbind = drm_agp_unbind_ttm; agp_be->destroy = drm_agp_destroy_ttm; - agp_be->needs_free = (backend == NULL); + DRM_MASK_VAL(agp_be->flags, DRM_BE_FLAG_NEEDS_FREE, + (backend == NULL) ? DRM_BE_FLAG_NEEDS_FREE : 0); + DRM_MASK_VAL(agp_be->flags, DRM_BE_FLAG_CBA, + (dev->agp->cant_use_aperture) ? DRM_BE_FLAG_CBA : 0); agp_be->drm_map_type = _DRM_AGP; return agp_be; } -EXPORT_SYMBOL(drm_agp_init_ttm_cached); +EXPORT_SYMBOL(drm_agp_init_ttm); #endif /* __OS_HAS_AGP */ -- cgit v1.2.3 From 540c64c378daafaad1c3f63faf5af81f39388665 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 12 Oct 2006 16:10:47 +0200 Subject: Bugfixes. --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 902b8947..d9fd9c92 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -559,7 +559,7 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle) */ static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) { - return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 1 : 0); + return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1); } -- cgit v1.2.3 From d515936ea7f98f6aaa9217699796beadef9d664b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 17 Oct 2006 19:40:57 +0200 Subject: Add memory usage accounting to avoid DOS problems. --- linux-core/drm_agpsupport.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index d9fd9c92..ffbe04f8 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -570,14 +570,19 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages, struct page **cur_page, **last_page = pages + num_pages; DRM_AGP_MEM *mem; + if (drm_alloc_memctl(num_pages * sizeof(void *))) + return -1; + DRM_DEBUG("drm_agp_populate_ttm\n"); #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11) mem = drm_agp_allocate_memory(num_pages, agp_priv->alloc_type); #else mem = drm_agp_allocate_memory(agp_priv->bridge, num_pages, agp_priv->alloc_type); #endif - if (!mem) + if (!mem) { + drm_free_memctl(num_pages *sizeof(void *)); return -1; + } DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count); mem->page_count = 0; @@ -626,8 +631,10 @@ static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) { DRM_DEBUG("drm_agp_clear_ttm\n"); if (mem) { + unsigned long num_pages = mem->page_count; backend->unbind(backend); agp_free_memory(mem); + drm_free_memctl(num_pages *sizeof(void *)); } agp_priv->mem = NULL; @@ -644,10 +651,12 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) { if (agp_priv->mem) { backend->clear(backend); } - drm_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS); + drm_ctl_free(agp_priv, sizeof(*agp_priv), DRM_MEM_MAPPINGS); + backend->private = NULL; + } + if (backend->flags & DRM_BE_FLAG_NEEDS_FREE) { + drm_ctl_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); } - if (backend->flags & DRM_BE_FLAG_NEEDS_FREE) - drm_free(backend, sizeof(*backend), DRM_MEM_MAPPINGS); } } @@ -662,15 +671,15 @@ drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev, drm_agp_ttm_priv *agp_priv; agp_be = (backend != NULL) ? backend: - drm_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); + drm_ctl_calloc(1, sizeof(*agp_be), DRM_MEM_MAPPINGS); if (!agp_be) return NULL; - agp_priv = drm_calloc(1, sizeof(agp_priv), DRM_MEM_MAPPINGS); + agp_priv = drm_ctl_calloc(1, sizeof(*agp_priv), DRM_MEM_MAPPINGS); if (!agp_priv) { - drm_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS); + drm_ctl_free(agp_be, sizeof(*agp_be), DRM_MEM_MAPPINGS); return NULL; } -- cgit v1.2.3 From e172945d668f1de1243ac2ae91ab77f3b2bda40a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 18 Oct 2006 16:54:17 +0200 Subject: Avoid driver-specific AGP user-populated types, since we don't know what AGP driver we're on. Avoid global cache flushes before inserting pages. In general, they are never mapped, and not accessed through the kernel map, so a cache flush should not be necessary. The exception is pages that are bound cached. We might need a cache flush for those. --- linux-core/drm_agpsupport.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index ffbe04f8..a5f1f9ee 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -558,6 +558,12 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle) * AGP ttm backend interface. */ +#ifndef AGP_USER_TYPES +#define AGP_USER_TYPES (1 << 16) +#define AGP_USER_MEMORY (AGP_USER_TYPES) +#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) +#endif + static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) { return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1); } @@ -604,7 +610,7 @@ static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, DRM_DEBUG("drm_agp_bind_ttm\n"); DRM_MASK_VAL(backend->flags, DRM_BE_FLAG_BOUND_CACHED, (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0); - mem->is_flushed = FALSE; + mem->is_flushed = TRUE; mem->type = (cached) ? agp_priv->cached_type : agp_priv->uncached_type; ret = drm_agp_bind_memory(mem, offset); if (ret) { @@ -662,10 +668,8 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) { drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev, - drm_ttm_backend_t *backend, - unsigned alloc_type, - unsigned cached_type, - unsigned uncached_type) { + drm_ttm_backend_t *backend) +{ drm_ttm_backend_t *agp_be; drm_agp_ttm_priv *agp_priv; @@ -684,9 +688,9 @@ drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev, } agp_priv->mem = NULL; - agp_priv->alloc_type = alloc_type; - agp_priv->cached_type = cached_type; - agp_priv->uncached_type = uncached_type; + agp_priv->alloc_type = AGP_USER_MEMORY; + agp_priv->cached_type = AGP_USER_CACHED_MEMORY; + agp_priv->uncached_type = AGP_USER_MEMORY; agp_priv->bridge = dev->agp->bridge; agp_priv->populated = FALSE; agp_be->aperture_base = dev->agp->agp_info.aper_base; -- cgit v1.2.3 From 9321592149c031694c459bb05e7a31d1197fe5cb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 20 Oct 2006 15:07:21 +0200 Subject: We apparently need this global cache flush anyway. --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index a5f1f9ee..13a3ced3 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -610,7 +610,7 @@ static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, DRM_DEBUG("drm_agp_bind_ttm\n"); DRM_MASK_VAL(backend->flags, DRM_BE_FLAG_BOUND_CACHED, (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0); - mem->is_flushed = TRUE; + mem->is_flushed = FALSE; mem->type = (cached) ? agp_priv->cached_type : agp_priv->uncached_type; ret = drm_agp_bind_memory(mem, offset); if (ret) { -- cgit v1.2.3 From 9ed4656799043f24f4d64615ebb8128bedc99799 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 21 Oct 2006 14:17:51 +0200 Subject: The CPU cache must be flushed _before_ we start modifying the kernel map ptes, otherwise data will be missing, which becomes apparent when the kernel evicts batch buffers which are likely to be written into in the evicted state, and then rebound to the AGP aperture. This means we cannot rely on the AGP module to flush the cache for us. --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_agpsupport.c') diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index 13a3ced3..a5f1f9ee 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -610,7 +610,7 @@ static int drm_agp_bind_ttm(drm_ttm_backend_t *backend, DRM_DEBUG("drm_agp_bind_ttm\n"); DRM_MASK_VAL(backend->flags, DRM_BE_FLAG_BOUND_CACHED, (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0); - mem->is_flushed = FALSE; + mem->is_flushed = TRUE; mem->type = (cached) ? agp_priv->cached_type : agp_priv->uncached_type; ret = drm_agp_bind_memory(mem, offset); if (ret) { -- cgit v1.2.3