aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/agp/intel-gtt.c81
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
119static int intel_agp_map_page(struct page *page, dma_addr_t *ret) 123static 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
547static 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
543static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { 573static 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
827static 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
836static 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
797static int intel_gtt_init(void) 850static 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
1177static 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
1189static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 1236static 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,