diff options
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 81 |
1 files changed, 64 insertions, 17 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 248ac5f8708e..e386a44330b8 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -35,6 +35,8 @@ | |||
35 | */ | 35 | */ |
36 | #ifdef CONFIG_DMAR | 36 | #ifdef CONFIG_DMAR |
37 | #define USE_PCI_DMA_API 1 | 37 | #define USE_PCI_DMA_API 1 |
38 | #else | ||
39 | #define USE_PCI_DMA_API 0 | ||
38 | #endif | 40 | #endif |
39 | 41 | ||
40 | /* Max amount of stolen space, anything above will be returned to Linux */ | 42 | /* Max amount of stolen space, anything above will be returned to Linux */ |
@@ -108,6 +110,8 @@ static struct _intel_private { | |||
108 | struct page *i8xx_page; | 110 | struct page *i8xx_page; |
109 | struct resource ifp_resource; | 111 | struct resource ifp_resource; |
110 | int resource_valid; | 112 | int resource_valid; |
113 | struct page *scratch_page; | ||
114 | dma_addr_t scratch_page_dma; | ||
111 | } intel_private; | 115 | } intel_private; |
112 | 116 | ||
113 | #define INTEL_GTT_GEN intel_private.driver->gen | 117 | #define INTEL_GTT_GEN intel_private.driver->gen |
@@ -115,7 +119,7 @@ static struct _intel_private { | |||
115 | #define IS_PINEVIEW intel_private.driver->is_pineview | 119 | #define IS_PINEVIEW intel_private.driver->is_pineview |
116 | #define IS_IRONLAKE intel_private.driver->is_ironlake | 120 | #define IS_IRONLAKE intel_private.driver->is_ironlake |
117 | 121 | ||
118 | #ifdef USE_PCI_DMA_API | 122 | #if USE_PCI_DMA_API |
119 | static int intel_agp_map_page(struct page *page, dma_addr_t *ret) | 123 | static int intel_agp_map_page(struct page *page, dma_addr_t *ret) |
120 | { | 124 | { |
121 | *ret = pci_map_page(intel_private.pcidev, page, 0, | 125 | *ret = pci_map_page(intel_private.pcidev, page, 0, |
@@ -540,6 +544,32 @@ static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, | |||
540 | return addr | bridge->driver->masks[type].mask; | 544 | return addr | bridge->driver->masks[type].mask; |
541 | } | 545 | } |
542 | 546 | ||
547 | static int intel_gtt_setup_scratch_page(void) | ||
548 | { | ||
549 | struct page *page; | ||
550 | dma_addr_t dma_addr; | ||
551 | |||
552 | page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); | ||
553 | if (page == NULL) | ||
554 | return -ENOMEM; | ||
555 | get_page(page); | ||
556 | set_pages_uc(page, 1); | ||
557 | |||
558 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { | ||
559 | dma_addr = pci_map_page(intel_private.pcidev, page, 0, | ||
560 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
561 | if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) | ||
562 | return -EINVAL; | ||
563 | |||
564 | intel_private.scratch_page_dma = dma_addr; | ||
565 | } else | ||
566 | intel_private.scratch_page_dma = page_to_phys(page); | ||
567 | |||
568 | intel_private.scratch_page = page; | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
543 | static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { | 573 | static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { |
544 | {128, 32768, 5}, | 574 | {128, 32768, 5}, |
545 | /* The 64M mode still requires a 128k gatt */ | 575 | /* The 64M mode still requires a 128k gatt */ |
@@ -794,6 +824,29 @@ static unsigned int intel_gtt_mappable_entries(void) | |||
794 | return aperture_size >> PAGE_SHIFT; | 824 | return aperture_size >> PAGE_SHIFT; |
795 | } | 825 | } |
796 | 826 | ||
827 | static void intel_gtt_teardown_scratch_page(void) | ||
828 | { | ||
829 | set_pages_wb(intel_private.scratch_page, 1); | ||
830 | pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, | ||
831 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
832 | put_page(intel_private.scratch_page); | ||
833 | __free_page(intel_private.scratch_page); | ||
834 | } | ||
835 | |||
836 | static void intel_gtt_cleanup(void) | ||
837 | { | ||
838 | if (intel_private.i9xx_flush_page) | ||
839 | iounmap(intel_private.i9xx_flush_page); | ||
840 | if (intel_private.resource_valid) | ||
841 | release_resource(&intel_private.ifp_resource); | ||
842 | intel_private.ifp_resource.start = 0; | ||
843 | intel_private.resource_valid = 0; | ||
844 | iounmap(intel_private.gtt); | ||
845 | iounmap(intel_private.registers); | ||
846 | |||
847 | intel_gtt_teardown_scratch_page(); | ||
848 | } | ||
849 | |||
797 | static int intel_gtt_init(void) | 850 | static int intel_gtt_init(void) |
798 | { | 851 | { |
799 | u32 gtt_map_size; | 852 | u32 gtt_map_size; |
@@ -825,6 +878,12 @@ static int intel_gtt_init(void) | |||
825 | return -ENOMEM; | 878 | return -ENOMEM; |
826 | } | 879 | } |
827 | 880 | ||
881 | ret = intel_gtt_setup_scratch_page(); | ||
882 | if (ret != 0) { | ||
883 | intel_gtt_cleanup(); | ||
884 | return ret; | ||
885 | } | ||
886 | |||
828 | return 0; | 887 | return 0; |
829 | } | 888 | } |
830 | 889 | ||
@@ -1174,18 +1233,6 @@ static int intel_i9xx_configure(void) | |||
1174 | return 0; | 1233 | return 0; |
1175 | } | 1234 | } |
1176 | 1235 | ||
1177 | static void intel_gtt_cleanup(void) | ||
1178 | { | ||
1179 | if (intel_private.i9xx_flush_page) | ||
1180 | iounmap(intel_private.i9xx_flush_page); | ||
1181 | if (intel_private.resource_valid) | ||
1182 | release_resource(&intel_private.ifp_resource); | ||
1183 | intel_private.ifp_resource.start = 0; | ||
1184 | intel_private.resource_valid = 0; | ||
1185 | iounmap(intel_private.gtt); | ||
1186 | iounmap(intel_private.registers); | ||
1187 | } | ||
1188 | |||
1189 | static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) | 1236 | static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) |
1190 | { | 1237 | { |
1191 | if (intel_private.i9xx_flush_page) | 1238 | if (intel_private.i9xx_flush_page) |
@@ -1416,7 +1463,7 @@ static const struct agp_bridge_driver intel_915_driver = { | |||
1416 | .agp_destroy_pages = agp_generic_destroy_pages, | 1463 | .agp_destroy_pages = agp_generic_destroy_pages, |
1417 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1464 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1418 | .chipset_flush = intel_i915_chipset_flush, | 1465 | .chipset_flush = intel_i915_chipset_flush, |
1419 | #ifdef USE_PCI_DMA_API | 1466 | #if USE_PCI_DMA_API |
1420 | .agp_map_page = intel_agp_map_page, | 1467 | .agp_map_page = intel_agp_map_page, |
1421 | .agp_unmap_page = intel_agp_unmap_page, | 1468 | .agp_unmap_page = intel_agp_unmap_page, |
1422 | .agp_map_memory = intel_agp_map_memory, | 1469 | .agp_map_memory = intel_agp_map_memory, |
@@ -1449,7 +1496,7 @@ static const struct agp_bridge_driver intel_i965_driver = { | |||
1449 | .agp_destroy_pages = agp_generic_destroy_pages, | 1496 | .agp_destroy_pages = agp_generic_destroy_pages, |
1450 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1497 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1451 | .chipset_flush = intel_i915_chipset_flush, | 1498 | .chipset_flush = intel_i915_chipset_flush, |
1452 | #ifdef USE_PCI_DMA_API | 1499 | #if USE_PCI_DMA_API |
1453 | .agp_map_page = intel_agp_map_page, | 1500 | .agp_map_page = intel_agp_map_page, |
1454 | .agp_unmap_page = intel_agp_unmap_page, | 1501 | .agp_unmap_page = intel_agp_unmap_page, |
1455 | .agp_map_memory = intel_agp_map_memory, | 1502 | .agp_map_memory = intel_agp_map_memory, |
@@ -1482,7 +1529,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { | |||
1482 | .agp_destroy_pages = agp_generic_destroy_pages, | 1529 | .agp_destroy_pages = agp_generic_destroy_pages, |
1483 | .agp_type_to_mask_type = intel_gen6_type_to_mask_type, | 1530 | .agp_type_to_mask_type = intel_gen6_type_to_mask_type, |
1484 | .chipset_flush = intel_i915_chipset_flush, | 1531 | .chipset_flush = intel_i915_chipset_flush, |
1485 | #ifdef USE_PCI_DMA_API | 1532 | #if USE_PCI_DMA_API |
1486 | .agp_map_page = intel_agp_map_page, | 1533 | .agp_map_page = intel_agp_map_page, |
1487 | .agp_unmap_page = intel_agp_unmap_page, | 1534 | .agp_unmap_page = intel_agp_unmap_page, |
1488 | .agp_map_memory = intel_agp_map_memory, | 1535 | .agp_map_memory = intel_agp_map_memory, |
@@ -1515,7 +1562,7 @@ static const struct agp_bridge_driver intel_g33_driver = { | |||
1515 | .agp_destroy_pages = agp_generic_destroy_pages, | 1562 | .agp_destroy_pages = agp_generic_destroy_pages, |
1516 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1563 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1517 | .chipset_flush = intel_i915_chipset_flush, | 1564 | .chipset_flush = intel_i915_chipset_flush, |
1518 | #ifdef USE_PCI_DMA_API | 1565 | #if USE_PCI_DMA_API |
1519 | .agp_map_page = intel_agp_map_page, | 1566 | .agp_map_page = intel_agp_map_page, |
1520 | .agp_unmap_page = intel_agp_unmap_page, | 1567 | .agp_unmap_page = intel_agp_unmap_page, |
1521 | .agp_map_memory = intel_agp_map_memory, | 1568 | .agp_map_memory = intel_agp_map_memory, |