aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom2008-02-28 06:47:15 -0600
committerThomas Hellstrom2008-02-28 06:47:15 -0600
commit40c9e6a26dd251fe2bf207bb259ba7e4a7704fbe (patch)
treea1cb1e00d162d3c7dbf8ba02b8005dbd4fb20948 /linux-core
parent72983ff30183745cd96760aa07b857c44daebde7 (diff)
downloadexternal-libdrm-40c9e6a26dd251fe2bf207bb259ba7e4a7704fbe.tar.gz
external-libdrm-40c9e6a26dd251fe2bf207bb259ba7e4a7704fbe.tar.xz
external-libdrm-40c9e6a26dd251fe2bf207bb259ba7e4a7704fbe.zip
Add a compat kmap_atomic_prot_pfn to do quick kernel map / unmaps of
PCI- or high memory. This is substantially more efficient than drm_bo_kmap, since the mapping only lives on a single processor. Unmapping is done use kunmap_atomic(). Flushes only a single tlb() entry. Add a support utility int drm_bo_pfn_prot() that returns the pfn and desired page protection for a given bo offset. This is all intended for relocations in bound TTMS or vram. Mapping-accessing-unmapping must be atomic, either using preempt_xx() macros or a spinlock.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_bo_move.c33
-rw-r--r--linux-core/drm_compat.c32
-rw-r--r--linux-core/drm_compat.h5
-rw-r--r--linux-core/drm_objects.h4
4 files changed, 74 insertions, 0 deletions
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index b06a09f0..30e0f43f 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -595,3 +595,36 @@ void drm_bo_kunmap(struct drm_bo_kmap_obj *map)
595 map->page = NULL; 595 map->page = NULL;
596} 596}
597EXPORT_SYMBOL(drm_bo_kunmap); 597EXPORT_SYMBOL(drm_bo_kunmap);
598
599int drm_bo_pfn_prot(struct drm_buffer_object *bo,
600 unsigned long dst_offset,
601 unsigned long *pfn,
602 pgprot_t *prot)
603{
604 struct drm_bo_mem_reg *mem = &bo->mem;
605 struct drm_device *dev = bo->dev;
606 unsigned long bus_offset;
607 unsigned long bus_size;
608 unsigned long bus_base;
609 struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
610 int ret;
611
612 ret = drm_bo_pci_offset(dev, mem, &bus_base, &bus_offset,
613 &bus_size);
614 if (ret)
615 return -EINVAL;
616
617 if (bus_size != 0)
618 *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT;
619 else if (!bo->ttm)
620 return -EINVAL;
621 else
622 *pfn = page_to_pfn(drm_ttm_get_page(bo->ttm, dst_offset >> PAGE_SHIFT));
623
624 *prot = (mem->flags & DRM_BO_FLAG_CACHED) ?
625 PAGE_KERNEL : drm_kernel_io_prot(man->drm_bus_maptype);
626
627 return 0;
628}
629EXPORT_SYMBOL(drm_bo_pfn_prot);
630
diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c
index a745a7d9..32e43a0a 100644
--- a/linux-core/drm_compat.c
+++ b/linux-core/drm_compat.c
@@ -729,3 +729,35 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
729} 729}
730EXPORT_SYMBOL(idr_replace); 730EXPORT_SYMBOL(idr_replace);
731#endif 731#endif
732
733#if defined(CONFIG_X86)
734
735#define drm_kmap_get_fixmap_pte(vaddr) \
736 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
737
738void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
739 pgprot_t protection)
740{
741 enum fixed_addresses idx;
742 unsigned long vaddr;
743 static pte_t *km_pte;
744 static int initialized = 0;
745
746 if (unlikely(!initialized)) {
747 km_pte = drm_kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
748 initialized = 1;
749 }
750
751 pagefault_disable();
752 idx = type + KM_TYPE_NR*smp_processor_id();
753 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
754 set_pte(km_pte-idx, pfn_pte(pfn, protection));
755
756 return (void*) vaddr;
757}
758
759EXPORT_SYMBOL(kmap_atomic_prot_pfn);
760
761#endif
762
763
diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h
index f8933e0c..39027cf4 100644
--- a/linux-core/drm_compat.h
+++ b/linux-core/drm_compat.h
@@ -328,4 +328,9 @@ void *idr_replace(struct idr *idp, void *ptr, int id);
328typedef _Bool bool; 328typedef _Bool bool;
329#endif 329#endif
330 330
331#if defined(CONFIG_X86)
332#define DRM_KMAP_ATOMIC_PROT_PFN
333extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
334 pgprot_t protection);
335#endif
331#endif 336#endif
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index e43e8dfd..8055afe1 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -738,6 +738,10 @@ static inline void *drm_bmo_virtual(struct drm_bo_kmap_obj *map, int *is_iomem)
738extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map); 738extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
739extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page, 739extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
740 unsigned long num_pages, struct drm_bo_kmap_obj *map); 740 unsigned long num_pages, struct drm_bo_kmap_obj *map);
741extern int drm_bo_pfn_prot(struct drm_buffer_object *bo,
742 unsigned long dst_offset,
743 unsigned long *pfn,
744 pgprot_t *prot);
741 745
742 746
743/* 747/*