Author: tijl Date: Thu Oct 30 14:26:36 2014 New Revision: 273862 URL: https://svnweb.freebsd.org/changeset/base/273862
Log: 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 Modified: head/sys/dev/drm2/drm_agpsupport.c head/sys/dev/drm2/radeon/radeon.h head/sys/dev/drm2/radeon/radeon_device.c head/sys/dev/drm2/radeon/radeon_ttm.c head/sys/dev/drm2/ttm/ttm_agp_backend.c head/sys/dev/drm2/ttm/ttm_bo_driver.h head/sys/dev/drm2/ttm/ttm_page_alloc.c Modified: head/sys/dev/drm2/drm_agpsupport.c ============================================================================== --- head/sys/dev/drm2/drm_agpsupport.c Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/drm_agpsupport.c Thu Oct 30 14:26:36 2014 (r273862) @@ -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) Modified: head/sys/dev/drm2/radeon/radeon.h ============================================================================== --- head/sys/dev/drm2/radeon/radeon.h Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/radeon/radeon.h Thu Oct 30 14:26:36 2014 (r273862) @@ -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 */ Modified: head/sys/dev/drm2/radeon/radeon_device.c ============================================================================== --- head/sys/dev/drm2/radeon/radeon_device.c Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/radeon/radeon_device.c Thu Oct 30 14:26:36 2014 (r273862) @@ -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 Modified: head/sys/dev/drm2/radeon/radeon_ttm.c ============================================================================== --- head/sys/dev/drm2/radeon/radeon_ttm.c Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/radeon/radeon_ttm.c Thu Oct 30 14:26:36 2014 (r273862) @@ -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 Modified: head/sys/dev/drm2/ttm/ttm_agp_backend.c ============================================================================== --- head/sys/dev/drm2/ttm/ttm_agp_backend.c Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/ttm/ttm_agp_backend.c Thu Oct 30 14:26:36 2014 (r273862) @@ -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 *t { 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 { 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 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; } Modified: head/sys/dev/drm2/ttm/ttm_bo_driver.h ============================================================================== --- head/sys/dev/drm2/ttm/ttm_bo_driver.h Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/ttm/ttm_bo_driver.h Thu Oct 30 14:26:36 2014 (r273862) @@ -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); Modified: head/sys/dev/drm2/ttm/ttm_page_alloc.c ============================================================================== --- head/sys/dev/drm2/ttm/ttm_page_alloc.c Thu Oct 30 14:05:48 2014 (r273861) +++ head/sys/dev/drm2/ttm/ttm_page_alloc.c Thu Oct 30 14:26:36 2014 (r273862) @@ -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; } _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"