diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-09-07 16:11:15 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-21 06:30:21 -0400 |
commit | 0e87d2b06cb4651c874d0b208d31c73addbd638b (patch) | |
tree | dd933e996f74b67e0e386f1871149f40b0e94855 /drivers/char/agp/intel-gtt.c | |
parent | f13d3f7311add99d1f874a6b67d56426afa35664 (diff) |
intel-gtt: initialize our own scratch page
The intel gtt fake agp driver is the only agp driver to use dma
address remapping. So it makes sense to fold this code back into the
only user (and thus reduce the reliance on the agp code).
This patch does the first step by initializing (and remapping) the
scratch page in a new function intel_gtt_setup_scratch_page.
Unfortunately intel_gtt_cleanup had to move to avoid a forward
declaration. The new scratch page is not yet used, though.
v2: Refactor out scratch page teardown. Suggested by Chris Wilson on
irc. This makes it clear what's going on and results in a nice
symmetry between setup and teardown.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/char/agp/intel-gtt.c')
-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, |