diff options
author | Thomas Hellstrom | 2008-02-28 06:47:15 -0600 |
---|---|---|
committer | Thomas Hellstrom | 2008-02-28 06:47:15 -0600 |
commit | 40c9e6a26dd251fe2bf207bb259ba7e4a7704fbe (patch) | |
tree | a1cb1e00d162d3c7dbf8ba02b8005dbd4fb20948 /linux-core | |
parent | 72983ff30183745cd96760aa07b857c44daebde7 (diff) | |
download | external-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.c | 33 | ||||
-rw-r--r-- | linux-core/drm_compat.c | 32 | ||||
-rw-r--r-- | linux-core/drm_compat.h | 5 | ||||
-rw-r--r-- | linux-core/drm_objects.h | 4 |
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 | } |
597 | EXPORT_SYMBOL(drm_bo_kunmap); | 597 | EXPORT_SYMBOL(drm_bo_kunmap); |
598 | |||
599 | int 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 | } | ||
629 | EXPORT_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 | } |
730 | EXPORT_SYMBOL(idr_replace); | 730 | EXPORT_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 | |||
738 | void *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 | |||
759 | EXPORT_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); | |||
328 | typedef _Bool bool; | 328 | typedef _Bool bool; |
329 | #endif | 329 | #endif |
330 | 330 | ||
331 | #if defined(CONFIG_X86) | ||
332 | #define DRM_KMAP_ATOMIC_PROT_PFN | ||
333 | extern 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) | |||
738 | extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map); | 738 | extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map); |
739 | extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page, | 739 | extern 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); |
741 | extern 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 | /* |