Bug #8707, 2.6.19-rc compatibility for memory manager code.

This commit is contained in:
Thomas Hellstrom 2006-10-20 15:06:31 +02:00
parent d70347bfc0
commit 3624e43282
4 changed files with 56 additions and 33 deletions

View file

@ -28,6 +28,11 @@
#include "drmP.h"
#if defined(CONFIG_X86) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
/*
* These have bad performance in the AGP module for the indicated kernel versions.
*/
int drm_map_page_into_agp(struct page *page)
{
int i;
@ -45,9 +50,15 @@ int drm_unmap_page_from_agp(struct page *page)
* performance reasons */
return i;
}
#endif
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
/*
* The protection map was exported in 2.6.19
*/
pgprot_t vm_get_page_prot(unsigned long vm_flags)
{
#ifdef MODULE
@ -62,8 +73,17 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags)
return protection_map[vm_flags & 0x0F];
#endif
};
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
/*
* vm code for kernels below 2,6,15 in which version a major vm write
* occured. This implement a simple straightforward
* version similar to what's going to be
* in kernel 2.6.20+?
*/
static int drm_pte_is_clear(struct vm_area_struct *vma,
unsigned long addr)
@ -76,12 +96,7 @@ static int drm_pte_is_clear(struct vm_area_struct *vma,
pgd_t *pgd;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
spin_lock(&mm->page_table_lock);
#else
spinlock_t *ptl;
#endif
pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd))
goto unlock;
@ -91,22 +106,13 @@ static int drm_pte_is_clear(struct vm_area_struct *vma,
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd))
goto unlock;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
pte = pte_offset_map(pmd, addr);
#else
pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
#endif
if (!pte)
goto unlock;
ret = pte_none(*pte);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
pte_unmap(pte);
unlock:
spin_unlock(&mm->page_table_lock);
#else
pte_unmap_unlock(pte, ptl);
unlock:
#endif
return ret;
}
@ -121,7 +127,6 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
return ret;
}
static struct {
spinlock_t lock;
struct page *dummy_page;
@ -154,9 +159,6 @@ void free_nopage_retry(void)
spin_unlock(&drm_np_retry.lock);
}
}
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma,
unsigned long address,
@ -186,6 +188,17 @@ struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma,
#ifdef DRM_ODD_MM_COMPAT
/*
* VM compatibility code for 2.6.15-2.6.19(?). This code implements a complicated
* workaround for a single BUG statement in do_no_page in these versions. The
* tricky thing is that we need to take the mmap_sem in exclusive mode for _all_
* vmas mapping the ttm, before dev->struct_mutex is taken. The way we do this is to
* check first take the dev->struct_mutex, and then trylock all mmap_sems. If this
* fails for a single mmap_sem, we have to release all sems and the dev->struct_mutex,
* release the cpu and retry. We also need to keep track of all vmas mapping the ttm.
* phew.
*/
typedef struct p_mm_entry {
struct list_head head;
struct mm_struct *mm;

View file

@ -231,7 +231,7 @@ static inline int remap_pfn_range(struct vm_area_struct *vma, unsigned long from
#include <linux/mm.h>
#include <asm/page.h>
#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) && \
#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)))
#define DRM_ODD_MM_COMPAT
#endif
@ -277,7 +277,18 @@ extern int drm_map_page_into_agp(struct page *page);
#define unmap_page_from_agp drm_unmap_page_from_agp
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
extern struct page *get_nopage_retry(void);
extern void free_nopage_retry(void);
struct fault_data;
extern struct page *drm_vm_ttm_fault(struct vm_area_struct *vma,
struct fault_data *data);
#define NOPAGE_REFAULT get_nopage_retry()
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
/*
* Hopefully, real NOPAGE_RETRY functionality will be in 2.6.19.
@ -295,10 +306,6 @@ struct fault_data {
int type;
};
extern struct page *get_nopage_retry(void);
extern void free_nopage_retry(void);
#define NOPAGE_REFAULT get_nopage_retry()
extern int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn, pgprot_t pgprot);
@ -307,9 +314,6 @@ extern struct page *drm_vm_ttm_nopage(struct vm_area_struct *vma,
unsigned long address,
int *type);
extern struct page *drm_vm_ttm_fault(struct vm_area_struct *vma,
struct fault_data *data);
#endif
#ifdef DRM_ODD_MM_COMPAT

View file

@ -433,7 +433,7 @@ void drm_exit(struct drm_driver *driver)
}
} else
pci_unregister_driver(&driver->pci_driver);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
free_nopage_retry();
#endif
DRM_INFO("Module unloaded\n");
@ -472,10 +472,14 @@ static void drm_free_mem_cache(kmem_cache_t *cache,
{
if (!cache)
return;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
if (kmem_cache_destroy(cache)) {
DRM_ERROR("Warning! DRM is leaking %s memory.\n",
name);
}
#else
kmem_cache_destroy(cache);
#endif
}
static void drm_free_memory_caches(void )

View file

@ -159,7 +159,9 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
}
#endif /* __OS_HAS_AGP */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) || \
LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
static
#endif
struct page *drm_vm_ttm_fault(struct vm_area_struct *vma,
@ -244,7 +246,7 @@ struct page *drm_vm_ttm_fault(struct vm_area_struct *vma,
mutex_unlock(&dev->struct_mutex);
return NULL;
}
#endif
/**
* \c nopage method for shared virtual memory.
@ -535,7 +537,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
.close = drm_vm_close,
};
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
static struct vm_operations_struct drm_vm_ttm_ops = {
.nopage = drm_vm_ttm_nopage,
.open = drm_vm_ttm_open_wrapper,