From dd733dea3856e7ddbba7c4c3928ccaba909b4535 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 1 Feb 2007 13:19:05 +0100 Subject: Fix missing ttm_open_vma call from previous commit. Honour the ttm backend cant-use-aperture flag. --- linux-core/drm_ttm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index c17c41cb..f1e3ea40 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -162,7 +162,7 @@ int drm_destroy_ttm(drm_ttm_t * ttm) DRM_DEBUG("Destroying a ttm\n"); -#ifdef DRM_TTM_ODD_COMPAT +#ifdef DRM_ODD_MM_COMPAT BUG_ON(!list_empty(&ttm->vma_list)); BUG_ON(!list_empty(&ttm->p_mm_list)); #endif @@ -364,6 +364,7 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) ret = drm_ttm_populate(ttm); if (ret) return ret; + if (ttm->state == ttm_unbound && !cached) { ret = unmap_vma_pages(ttm); if (ret) -- cgit v1.2.3 From c269d560e4d71448cfc9c2ea51eee3d5feafaad4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 2 Feb 2007 14:47:44 +0100 Subject: Make vm handle buffer objects instead of ttm objects. Remove ttm objects. Make vm aware of PCI memory type buffer objects. (Only works for pre 2.6.16 kernels for now). --- linux-core/drm_ttm.c | 202 ++++++--------------------------------------------- 1 file changed, 24 insertions(+), 178 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index f1e3ea40..6699a0dd 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -79,29 +79,28 @@ static void ttm_free_pages(drm_ttm_t *ttm) ttm->pages = NULL; } -/* - * Unmap all vma pages from vmas mapping this ttm. - */ -static int unmap_vma_pages(drm_ttm_t * ttm) +struct page *drm_ttm_alloc_page(void) { - drm_device_t *dev = ttm->dev; - loff_t offset = ((loff_t) ttm->mapping_offset) << PAGE_SHIFT; - loff_t holelen = ((loff_t) ttm->num_pages) << PAGE_SHIFT; + struct page *page; -#ifdef DRM_ODD_MM_COMPAT - int ret; - ret = drm_ttm_lock_mm(ttm); - if (ret) - return ret; -#endif - unmap_mapping_range(dev->dev_mapping, offset, holelen, 1); -#ifdef DRM_ODD_MM_COMPAT - drm_ttm_finish_unmap(ttm); + if (drm_alloc_memctl(PAGE_SIZE)) { + return NULL; + } + page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); + if (!page) { + drm_free_memctl(PAGE_SIZE); + return NULL; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + SetPageLocked(page); +#else + SetPageReserved(page); #endif - return 0; + return page; } + /* * Change caching policy for the linear kernel map * for range of pages in a ttm. @@ -154,13 +153,7 @@ int drm_destroy_ttm(drm_ttm_t * ttm) if (!ttm) return 0; - if (atomic_read(&ttm->vma_count) > 0) { - ttm->destroy = 1; - DRM_ERROR("VMAs are still alive. Skipping destruction.\n"); - return -EBUSY; - } - - DRM_DEBUG("Destroying a ttm\n"); + DRM_ERROR("Drm destroy ttm\n"); #ifdef DRM_ODD_MM_COMPAT BUG_ON(!list_empty(&ttm->vma_list)); @@ -193,11 +186,6 @@ int drm_destroy_ttm(drm_ttm_t * ttm) DRM_ERROR("Erroneous map count. " "Leaking page mappings.\n"); } - - /* - * End debugging. - */ - __free_page(*cur_page); drm_free_memctl(PAGE_SIZE); --bm->cur_pages; @@ -225,19 +213,9 @@ static int drm_ttm_populate(drm_ttm_t * ttm) for (i = 0; i < ttm->num_pages; ++i) { page = ttm->pages[i]; if (!page) { - if (drm_alloc_memctl(PAGE_SIZE)) { + page = drm_ttm_alloc_page(); + if (!page) return -ENOMEM; - } - page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); - if (!page) { - drm_free_memctl(PAGE_SIZE); - return -ENOMEM; - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) - SetPageLocked(page); -#else - SetPageReserved(page); -#endif ttm->pages[i] = page; ++bm->cur_pages; } @@ -251,7 +229,7 @@ static int drm_ttm_populate(drm_ttm_t * ttm) * Initialize a ttm. */ -static drm_ttm_t *drm_init_ttm(struct drm_device *dev, unsigned long size) +drm_ttm_t *drm_ttm_init(struct drm_device *dev, unsigned long size) { drm_bo_driver_t *bo_driver = dev->driver->bo_driver; drm_ttm_t *ttm; @@ -303,26 +281,15 @@ static drm_ttm_t *drm_init_ttm(struct drm_device *dev, unsigned long size) int drm_evict_ttm(drm_ttm_t * ttm) { drm_ttm_backend_t *be = ttm->be; - int ret; - switch (ttm->state) { - case ttm_bound: - if (be->needs_ub_cache_adjust(be)) { - ret = unmap_vma_pages(ttm); - if (ret) { - return ret; - } - } + if (ttm->state == ttm_bound) be->unbind(be); - break; - default: - break; - } + ttm->state = ttm_evicted; return 0; } -void drm_fixup_ttm_caching(drm_ttm_t * ttm) +void drm_ttm_fixup_caching(drm_ttm_t * ttm) { if (ttm->state == ttm_evicted) { @@ -344,7 +311,7 @@ int drm_unbind_ttm(drm_ttm_t * ttm) if (ret) return ret; - drm_fixup_ttm_caching(ttm); + drm_ttm_fixup_caching(ttm); return 0; } @@ -366,10 +333,6 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) return ret; if (ttm->state == ttm_unbound && !cached) { - ret = unmap_vma_pages(ttm); - if (ret) - return ret; - drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED); } #ifdef DRM_ODD_MM_COMPAT @@ -402,120 +365,3 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) return 0; } - -/* - * dev->struct_mutex locked. - */ -static void drm_ttm_object_remove(drm_device_t * dev, drm_ttm_object_t * object) -{ - drm_map_list_t *list = &object->map_list; - drm_local_map_t *map; - - if (list->user_token) - drm_ht_remove_item(&dev->map_hash, &list->hash); - - if (list->file_offset_node) { - drm_mm_put_block(list->file_offset_node); - list->file_offset_node = NULL; - } - - map = list->map; - - if (map) { - drm_ttm_t *ttm = (drm_ttm_t *) map->offset; - if (ttm) { - if (drm_destroy_ttm(ttm) != -EBUSY) { - drm_ctl_free(map, sizeof(*map), DRM_MEM_TTM); - } - } else { - drm_ctl_free(map, sizeof(*map), DRM_MEM_TTM); - } - } - - drm_ctl_free(object, sizeof(*object), DRM_MEM_TTM); -} - -void drm_ttm_object_deref_locked(drm_device_t * dev, drm_ttm_object_t * to) -{ - if (atomic_dec_and_test(&to->usage)) { - drm_ttm_object_remove(dev, to); - } -} - -void drm_ttm_object_deref_unlocked(drm_device_t * dev, drm_ttm_object_t * to) -{ - if (atomic_dec_and_test(&to->usage)) { - mutex_lock(&dev->struct_mutex); - if (atomic_read(&to->usage) == 0) - drm_ttm_object_remove(dev, to); - mutex_unlock(&dev->struct_mutex); - } -} - -/* - * Create a ttm and add it to the drm book-keeping. - * dev->struct_mutex locked. - */ - -int drm_ttm_object_create(drm_device_t * dev, unsigned long size, - uint32_t flags, drm_ttm_object_t ** ttm_object) -{ - drm_ttm_object_t *object; - drm_map_list_t *list; - drm_local_map_t *map; - drm_ttm_t *ttm; - - object = drm_ctl_calloc(1, sizeof(*object), DRM_MEM_TTM); - if (!object) - return -ENOMEM; - object->flags = flags; - list = &object->map_list; - - list->map = drm_ctl_calloc(1, sizeof(*map), DRM_MEM_TTM); - if (!list->map) { - drm_ttm_object_remove(dev, object); - return -ENOMEM; - } - map = list->map; - - ttm = drm_init_ttm(dev, size); - if (!ttm) { - DRM_ERROR("Could not create ttm\n"); - drm_ttm_object_remove(dev, object); - return -ENOMEM; - } - - map->offset = (unsigned long)ttm; - map->type = _DRM_TTM; - map->flags = _DRM_REMOVABLE; - map->size = ttm->num_pages * PAGE_SIZE; - map->handle = (void *)object; - - /* - * Add a one-page "hole" to the block size to avoid the mm subsystem - * merging vmas. - * FIXME: Is this really needed? - */ - - list->file_offset_node = drm_mm_search_free(&dev->offset_manager, - ttm->num_pages + 1, 0, 0); - if (!list->file_offset_node) { - drm_ttm_object_remove(dev, object); - return -ENOMEM; - } - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - ttm->num_pages + 1, 0); - - list->hash.key = list->file_offset_node->start; - - if (drm_ht_insert_item(&dev->map_hash, &list->hash)) { - drm_ttm_object_remove(dev, object); - return -ENOMEM; - } - - list->user_token = ((drm_u64_t) list->hash.key) << PAGE_SHIFT; - ttm->mapping_offset = list->hash.key; - atomic_set(&object->usage, 1); - *ttm_object = object; - return 0; -} -- cgit v1.2.3 From 63f2abd721c40f1cddae555c79b4ab4c55aae006 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 2 Feb 2007 19:49:11 +0100 Subject: Make also later kernels work with buffer object vm and clean up some function names. --- linux-core/drm_ttm.c | 51 +++++++++------------------------------------------ 1 file changed, 9 insertions(+), 42 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 6699a0dd..9a2ce5cd 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -153,12 +153,6 @@ int drm_destroy_ttm(drm_ttm_t * ttm) if (!ttm) return 0; - DRM_ERROR("Drm destroy ttm\n"); - -#ifdef DRM_ODD_MM_COMPAT - BUG_ON(!list_empty(&ttm->vma_list)); - BUG_ON(!list_empty(&ttm->p_mm_list)); -#endif be = ttm->be; if (be) { be->destroy(be); @@ -241,11 +235,6 @@ drm_ttm_t *drm_ttm_init(struct drm_device *dev, unsigned long size) if (!ttm) return NULL; -#ifdef DRM_ODD_MM_COMPAT - INIT_LIST_HEAD(&ttm->p_mm_list); - INIT_LIST_HEAD(&ttm->vma_list); -#endif - ttm->dev = dev; atomic_set(&ttm->vma_count, 0); @@ -278,15 +267,17 @@ drm_ttm_t *drm_ttm_init(struct drm_device *dev, unsigned long size) * Unbind a ttm region from the aperture. */ -int drm_evict_ttm(drm_ttm_t * ttm) +void drm_ttm_evict(drm_ttm_t * ttm) { drm_ttm_backend_t *be = ttm->be; + int ret; - if (ttm->state == ttm_bound) - be->unbind(be); + if (ttm->state == ttm_bound) { + ret = be->unbind(be); + BUG_ON(ret); + } ttm->state = ttm_evicted; - return 0; } void drm_ttm_fixup_caching(drm_ttm_t * ttm) @@ -301,18 +292,12 @@ void drm_ttm_fixup_caching(drm_ttm_t * ttm) } } -int drm_unbind_ttm(drm_ttm_t * ttm) +void drm_ttm_unbind(drm_ttm_t * ttm) { - int ret = 0; - if (ttm->state == ttm_bound) - ret = drm_evict_ttm(ttm); - - if (ret) - return ret; + drm_ttm_evict(ttm); drm_ttm_fixup_caching(ttm); - return 0; } int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) @@ -335,19 +320,9 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) if (ttm->state == ttm_unbound && !cached) { drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED); } -#ifdef DRM_ODD_MM_COMPAT - else if (ttm->state == ttm_evicted && !cached) { - ret = drm_ttm_lock_mm(ttm); - if (ret) - return ret; - } -#endif + if ((ret = be->bind(be, aper_offset, cached))) { ttm->state = ttm_evicted; -#ifdef DRM_ODD_MM_COMPAT - if (be->needs_ub_cache_adjust(be)) - drm_ttm_unlock_mm(ttm); -#endif DRM_ERROR("Couldn't bind backend.\n"); return ret; } @@ -355,13 +330,5 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) ttm->aper_offset = aper_offset; ttm->state = ttm_bound; -#ifdef DRM_ODD_MM_COMPAT - if (be->needs_ub_cache_adjust(be)) { - ret = drm_ttm_remap_bound(ttm); - if (ret) - return ret; - } -#endif - return 0; } -- cgit v1.2.3 From c1fbd8a56653b91af57a408bbcf20a760a2bd8c8 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 7 Feb 2007 17:25:13 +0100 Subject: Checkpoint commit. Flag handling and memory type selection cleanup. glxgears won't start. --- linux-core/drm_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 9a2ce5cd..34282292 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -134,7 +134,7 @@ static int drm_set_caching(drm_ttm_t * ttm, int noncached) if (do_tlbflush) flush_agp_mappings(); - DRM_MASK_VAL(ttm->page_flags, DRM_TTM_PAGE_UNCACHED, noncached); + DRM_FLAG_MASKED(ttm->page_flags, noncached, DRM_TTM_PAGE_UNCACHED); return 0; } -- cgit v1.2.3 From 1257907fa9a24de7aa95485e1b3ab509fdc4d4e6 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 8 Feb 2007 13:29:08 +0100 Subject: Simplify external ttm page allocation. Implement a memcpy fallback for copying between buffers. --- linux-core/drm_ttm.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 34282292..5c270bee 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -80,7 +80,7 @@ static void ttm_free_pages(drm_ttm_t *ttm) } -struct page *drm_ttm_alloc_page(void) +static struct page *drm_ttm_alloc_page(void) { struct page *page; @@ -192,27 +192,37 @@ int drm_destroy_ttm(drm_ttm_t * ttm) return 0; } +struct page *drm_ttm_get_page(drm_ttm_t *ttm, int index) +{ + struct page *p; + drm_buffer_manager_t *bm = &ttm->dev->bm; + + p = ttm->pages[index]; + if (!p) { + p = drm_ttm_alloc_page(); + if (!p) + return NULL; + ttm->pages[index] = p; + ++bm->cur_pages; + } + return p; +} + + static int drm_ttm_populate(drm_ttm_t * ttm) { struct page *page; unsigned long i; - drm_buffer_manager_t *bm; drm_ttm_backend_t *be; if (ttm->state != ttm_unpopulated) return 0; - bm = &ttm->dev->bm; be = ttm->be; for (i = 0; i < ttm->num_pages; ++i) { - page = ttm->pages[i]; - if (!page) { - page = drm_ttm_alloc_page(); - if (!page) - return -ENOMEM; - ttm->pages[i] = page; - ++bm->cur_pages; - } + page = drm_ttm_get_page(ttm, i); + if (!page) + return -ENOMEM; } be->populate(be, ttm->num_pages, ttm->pages); ttm->state = ttm_unbound; -- cgit v1.2.3 From 99acdaee482fc8a2fc6718317e2f546401e93739 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Feb 2007 00:07:29 +0100 Subject: Fix copyright statements. --- linux-core/drm_ttm.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 5c270bee..fa55a8b4 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -11,6 +11,10 @@ * 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 NON-INFRINGEMENT. IN NO EVENT SHALL @@ -18,13 +22,11 @@ * 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * * **************************************************************************/ +/* + * Authors: Thomas Hellström + */ #include "drmP.h" -- cgit v1.2.3 From 53aee3122a1821b8ca24ed2bc5c1940cb0f2ff8e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 9 Feb 2007 16:36:53 +0100 Subject: I915 accelerated blit copy functional. Fixed - to System memory copies are implemented by flipping in a cache-coherent TTM, blitting to it, and then flipping it out. --- linux-core/drm_ttm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index fa55a8b4..8cd961d7 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -344,3 +344,4 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) return 0; } +EXPORT_SYMBOL(drm_bind_ttm); -- cgit v1.2.3 From 398913dc0e632c71e3095a7d50dae911aed18884 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 12 Feb 2007 20:34:50 +0100 Subject: Lindent. --- linux-core/drm_ttm.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'linux-core/drm_ttm.c') diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index 8cd961d7..e67719e2 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -35,18 +35,17 @@ static void drm_ttm_ipi_handler(void *null) flush_agp_cache(); } -static void drm_ttm_cache_flush(void) +static void drm_ttm_cache_flush(void) { if (on_each_cpu(drm_ttm_ipi_handler, NULL, 1, 1) != 0) DRM_ERROR("Timed out waiting for drm cache flush.\n"); } - /* * Use kmalloc if possible. Otherwise fall back to vmalloc. */ -static void ttm_alloc_pages(drm_ttm_t *ttm) +static void ttm_alloc_pages(drm_ttm_t * ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); ttm->pages = NULL; @@ -67,7 +66,7 @@ static void ttm_alloc_pages(drm_ttm_t *ttm) } } -static void ttm_free_pages(drm_ttm_t *ttm) +static void ttm_free_pages(drm_ttm_t * ttm) { unsigned long size = ttm->num_pages * sizeof(*ttm->pages); @@ -81,7 +80,6 @@ static void ttm_free_pages(drm_ttm_t *ttm) ttm->pages = NULL; } - static struct page *drm_ttm_alloc_page(void) { struct page *page; @@ -102,7 +100,6 @@ static struct page *drm_ttm_alloc_page(void) return page; } - /* * Change caching policy for the linear kernel map * for range of pages in a ttm. @@ -117,7 +114,7 @@ static int drm_set_caching(drm_ttm_t * ttm, int noncached) if ((ttm->page_flags & DRM_TTM_PAGE_UNCACHED) == noncached) return 0; - if (noncached) + if (noncached) drm_ttm_cache_flush(); for (i = 0; i < ttm->num_pages; ++i) { @@ -194,7 +191,7 @@ int drm_destroy_ttm(drm_ttm_t * ttm) return 0; } -struct page *drm_ttm_get_page(drm_ttm_t *ttm, int index) +struct page *drm_ttm_get_page(drm_ttm_t * ttm, int index) { struct page *p; drm_buffer_manager_t *bm = &ttm->dev->bm; @@ -210,7 +207,6 @@ struct page *drm_ttm_get_page(drm_ttm_t *ttm, int index) return p; } - static int drm_ttm_populate(drm_ttm_t * ttm) { struct page *page; @@ -235,7 +231,7 @@ static int drm_ttm_populate(drm_ttm_t * ttm) * Initialize a ttm. */ -drm_ttm_t *drm_ttm_init(struct drm_device *dev, unsigned long size) +drm_ttm_t *drm_ttm_init(struct drm_device * dev, unsigned long size) { drm_bo_driver_t *bo_driver = dev->driver->bo_driver; drm_ttm_t *ttm; @@ -344,4 +340,5 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) return 0; } + EXPORT_SYMBOL(drm_bind_ttm); -- cgit v1.2.3