diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-09-11 16:12:11 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-21 06:36:38 -0400 |
commit | fefaa70f0c7fa406492039e35b69b83fc13e163a (patch) | |
tree | c9f721ad19884c401774d926b65a6c4f8b08a037 /drivers/char/agp/intel-gtt.c | |
parent | 5cbecafce4ee8ab73c194911e01a77a7a07f034e (diff) |
intel-gtt: generic (insert|remove)_entries for i915
Beef up the generic version to support dmar. Otherwise like for the i830.
v2: Don't try to DMA remap on resume for already remapped pages.
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 | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index c1b766dbef4d..f05c3648017d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -124,7 +124,6 @@ static struct _intel_private { | |||
124 | #define IS_PINEVIEW intel_private.driver->is_pineview | 124 | #define IS_PINEVIEW intel_private.driver->is_pineview |
125 | #define IS_IRONLAKE intel_private.driver->is_ironlake | 125 | #define IS_IRONLAKE intel_private.driver->is_ironlake |
126 | 126 | ||
127 | #if USE_PCI_DMA_API | ||
128 | static void intel_agp_free_sglist(struct agp_memory *mem) | 127 | static void intel_agp_free_sglist(struct agp_memory *mem) |
129 | { | 128 | { |
130 | struct sg_table st; | 129 | struct sg_table st; |
@@ -144,6 +143,9 @@ static int intel_agp_map_memory(struct agp_memory *mem) | |||
144 | struct scatterlist *sg; | 143 | struct scatterlist *sg; |
145 | int i; | 144 | int i; |
146 | 145 | ||
146 | if (mem->sg_list) | ||
147 | return 0; /* already mapped (for e.g. resume */ | ||
148 | |||
147 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); | 149 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); |
148 | 150 | ||
149 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) | 151 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) |
@@ -175,6 +177,7 @@ static void intel_agp_unmap_memory(struct agp_memory *mem) | |||
175 | intel_agp_free_sglist(mem); | 177 | intel_agp_free_sglist(mem); |
176 | } | 178 | } |
177 | 179 | ||
180 | #if USE_PCI_DMA_API | ||
178 | static void intel_agp_insert_sg_entries(struct agp_memory *mem, | 181 | static void intel_agp_insert_sg_entries(struct agp_memory *mem, |
179 | off_t pg_start, int mask_type) | 182 | off_t pg_start, int mask_type) |
180 | { | 183 | { |
@@ -1051,6 +1054,31 @@ static bool i830_check_flags(unsigned int flags) | |||
1051 | return false; | 1054 | return false; |
1052 | } | 1055 | } |
1053 | 1056 | ||
1057 | static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, | ||
1058 | unsigned int sg_len, | ||
1059 | unsigned int pg_start, | ||
1060 | unsigned int flags) | ||
1061 | { | ||
1062 | struct scatterlist *sg; | ||
1063 | unsigned int len, m; | ||
1064 | int i, j; | ||
1065 | |||
1066 | j = pg_start; | ||
1067 | |||
1068 | /* sg may merge pages, but we have to separate | ||
1069 | * per-page addr for GTT */ | ||
1070 | for_each_sg(sg_list, sg, sg_len, i) { | ||
1071 | len = sg_dma_len(sg) >> PAGE_SHIFT; | ||
1072 | for (m = 0; m < len; m++) { | ||
1073 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | ||
1074 | intel_private.driver->write_entry(addr, | ||
1075 | j, flags); | ||
1076 | j++; | ||
1077 | } | ||
1078 | } | ||
1079 | readl(intel_private.gtt+j-1); | ||
1080 | } | ||
1081 | |||
1054 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, | 1082 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, |
1055 | off_t pg_start, int type) | 1083 | off_t pg_start, int type) |
1056 | { | 1084 | { |
@@ -1082,11 +1110,21 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, | |||
1082 | if (!mem->is_flushed) | 1110 | if (!mem->is_flushed) |
1083 | global_cache_flush(); | 1111 | global_cache_flush(); |
1084 | 1112 | ||
1085 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 1113 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { |
1086 | intel_private.driver->write_entry(page_to_phys(mem->pages[i]), | 1114 | ret = intel_agp_map_memory(mem); |
1087 | j, type); | 1115 | if (ret != 0) |
1116 | return ret; | ||
1117 | |||
1118 | intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, | ||
1119 | pg_start, type); | ||
1120 | } else { | ||
1121 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
1122 | dma_addr_t addr = page_to_phys(mem->pages[i]); | ||
1123 | intel_private.driver->write_entry(addr, | ||
1124 | j, type); | ||
1125 | } | ||
1126 | readl(intel_private.gtt+j-1); | ||
1088 | } | 1127 | } |
1089 | readl(intel_private.gtt+j-1); | ||
1090 | 1128 | ||
1091 | out: | 1129 | out: |
1092 | ret = 0; | 1130 | ret = 0; |
@@ -1109,6 +1147,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, | |||
1109 | return -EINVAL; | 1147 | return -EINVAL; |
1110 | } | 1148 | } |
1111 | 1149 | ||
1150 | if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) | ||
1151 | intel_agp_unmap_memory(mem); | ||
1152 | |||
1112 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 1153 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
1113 | intel_private.driver->write_entry(intel_private.scratch_page_dma, | 1154 | intel_private.driver->write_entry(intel_private.scratch_page_dma, |
1114 | i, 0); | 1155 | i, 0); |
@@ -1469,8 +1510,8 @@ static const struct agp_bridge_driver intel_915_driver = { | |||
1469 | .cache_flush = global_cache_flush, | 1510 | .cache_flush = global_cache_flush, |
1470 | .create_gatt_table = intel_fake_agp_create_gatt_table, | 1511 | .create_gatt_table = intel_fake_agp_create_gatt_table, |
1471 | .free_gatt_table = intel_fake_agp_free_gatt_table, | 1512 | .free_gatt_table = intel_fake_agp_free_gatt_table, |
1472 | .insert_memory = intel_i915_insert_entries, | 1513 | .insert_memory = intel_fake_agp_insert_entries, |
1473 | .remove_memory = intel_i915_remove_entries, | 1514 | .remove_memory = intel_fake_agp_remove_entries, |
1474 | .alloc_by_type = intel_fake_agp_alloc_by_type, | 1515 | .alloc_by_type = intel_fake_agp_alloc_by_type, |
1475 | .free_by_type = intel_i810_free_by_type, | 1516 | .free_by_type = intel_i810_free_by_type, |
1476 | .agp_alloc_page = agp_generic_alloc_page, | 1517 | .agp_alloc_page = agp_generic_alloc_page, |
@@ -1479,10 +1520,6 @@ static const struct agp_bridge_driver intel_915_driver = { | |||
1479 | .agp_destroy_pages = agp_generic_destroy_pages, | 1520 | .agp_destroy_pages = agp_generic_destroy_pages, |
1480 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1521 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1481 | .chipset_flush = intel_i915_chipset_flush, | 1522 | .chipset_flush = intel_i915_chipset_flush, |
1482 | #if USE_PCI_DMA_API | ||
1483 | .agp_map_memory = intel_agp_map_memory, | ||
1484 | .agp_unmap_memory = intel_agp_unmap_memory, | ||
1485 | #endif | ||
1486 | }; | 1523 | }; |
1487 | 1524 | ||
1488 | static const struct agp_bridge_driver intel_i965_driver = { | 1525 | static const struct agp_bridge_driver intel_i965_driver = { |
@@ -1586,6 +1623,7 @@ static const struct intel_gtt_driver i915_gtt_driver = { | |||
1586 | .setup = i9xx_setup, | 1623 | .setup = i9xx_setup, |
1587 | /* i945 is the last gpu to need phys mem (for overlay and cursors). */ | 1624 | /* i945 is the last gpu to need phys mem (for overlay and cursors). */ |
1588 | .write_entry = i830_write_entry, | 1625 | .write_entry = i830_write_entry, |
1626 | .check_flags = i830_check_flags, | ||
1589 | }; | 1627 | }; |
1590 | static const struct intel_gtt_driver g33_gtt_driver = { | 1628 | static const struct intel_gtt_driver g33_gtt_driver = { |
1591 | .gen = 3, | 1629 | .gen = 3, |