diff options
Diffstat (limited to 'drivers/char/agp/intel-gtt.c')
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 96 |
1 files changed, 84 insertions, 12 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 9344216183a4..d22ffb811bf2 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #define USE_PCI_DMA_API 1 | 25 | #define USE_PCI_DMA_API 1 |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | /* Max amount of stolen space, anything above will be returned to Linux */ | ||
29 | int intel_max_stolen = 32 * 1024 * 1024; | ||
30 | EXPORT_SYMBOL(intel_max_stolen); | ||
31 | |||
28 | static const struct aper_size_info_fixed intel_i810_sizes[] = | 32 | static const struct aper_size_info_fixed intel_i810_sizes[] = |
29 | { | 33 | { |
30 | {64, 16384, 4}, | 34 | {64, 16384, 4}, |
@@ -104,7 +108,7 @@ static int intel_agp_map_memory(struct agp_memory *mem) | |||
104 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); | 108 | DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); |
105 | 109 | ||
106 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) | 110 | if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) |
107 | return -ENOMEM; | 111 | goto err; |
108 | 112 | ||
109 | mem->sg_list = sg = st.sgl; | 113 | mem->sg_list = sg = st.sgl; |
110 | 114 | ||
@@ -113,11 +117,14 @@ static int intel_agp_map_memory(struct agp_memory *mem) | |||
113 | 117 | ||
114 | mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, | 118 | mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, |
115 | mem->page_count, PCI_DMA_BIDIRECTIONAL); | 119 | mem->page_count, PCI_DMA_BIDIRECTIONAL); |
116 | if (unlikely(!mem->num_sg)) { | 120 | if (unlikely(!mem->num_sg)) |
117 | intel_agp_free_sglist(mem); | 121 | goto err; |
118 | return -ENOMEM; | 122 | |
119 | } | ||
120 | return 0; | 123 | return 0; |
124 | |||
125 | err: | ||
126 | sg_free_table(&st); | ||
127 | return -ENOMEM; | ||
121 | } | 128 | } |
122 | 129 | ||
123 | static void intel_agp_unmap_memory(struct agp_memory *mem) | 130 | static void intel_agp_unmap_memory(struct agp_memory *mem) |
@@ -176,7 +183,7 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, | |||
176 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || | 183 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || |
177 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) | 184 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) |
178 | { | 185 | { |
179 | cache_bits = I830_PTE_SYSTEM_CACHED; | 186 | cache_bits = GEN6_PTE_LLC_MLC; |
180 | } | 187 | } |
181 | 188 | ||
182 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 189 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
@@ -710,7 +717,12 @@ static void intel_i830_init_gtt_entries(void) | |||
710 | break; | 717 | break; |
711 | } | 718 | } |
712 | } | 719 | } |
713 | if (gtt_entries > 0) { | 720 | if (!local && gtt_entries > intel_max_stolen) { |
721 | dev_info(&agp_bridge->dev->dev, | ||
722 | "detected %dK stolen memory, trimming to %dK\n", | ||
723 | gtt_entries / KB(1), intel_max_stolen / KB(1)); | ||
724 | gtt_entries = intel_max_stolen / KB(4); | ||
725 | } else if (gtt_entries > 0) { | ||
714 | dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", | 726 | dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", |
715 | gtt_entries / KB(1), local ? "local" : "stolen"); | 727 | gtt_entries / KB(1), local ? "local" : "stolen"); |
716 | gtt_entries /= KB(4); | 728 | gtt_entries /= KB(4); |
@@ -797,6 +809,10 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) | |||
797 | 809 | ||
798 | /* we have to call this as early as possible after the MMIO base address is known */ | 810 | /* we have to call this as early as possible after the MMIO base address is known */ |
799 | intel_i830_init_gtt_entries(); | 811 | intel_i830_init_gtt_entries(); |
812 | if (intel_private.gtt_entries == 0) { | ||
813 | iounmap(intel_private.registers); | ||
814 | return -ENOMEM; | ||
815 | } | ||
800 | 816 | ||
801 | agp_bridge->gatt_table = NULL; | 817 | agp_bridge->gatt_table = NULL; |
802 | 818 | ||
@@ -1216,17 +1232,20 @@ static int intel_i915_get_gtt_size(void) | |||
1216 | 1232 | ||
1217 | /* G33's GTT size defined in gmch_ctrl */ | 1233 | /* G33's GTT size defined in gmch_ctrl */ |
1218 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); | 1234 | pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); |
1219 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { | 1235 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { |
1220 | case G33_PGETBL_SIZE_1M: | 1236 | case I830_GMCH_GMS_STOLEN_512: |
1237 | size = 512; | ||
1238 | break; | ||
1239 | case I830_GMCH_GMS_STOLEN_1024: | ||
1221 | size = 1024; | 1240 | size = 1024; |
1222 | break; | 1241 | break; |
1223 | case G33_PGETBL_SIZE_2M: | 1242 | case I830_GMCH_GMS_STOLEN_8192: |
1224 | size = 2048; | 1243 | size = 8*1024; |
1225 | break; | 1244 | break; |
1226 | default: | 1245 | default: |
1227 | dev_info(&agp_bridge->dev->dev, | 1246 | dev_info(&agp_bridge->dev->dev, |
1228 | "unknown page table size 0x%x, assuming 512KB\n", | 1247 | "unknown page table size 0x%x, assuming 512KB\n", |
1229 | (gmch_ctrl & G33_PGETBL_SIZE_MASK)); | 1248 | (gmch_ctrl & I830_GMCH_GMS_MASK)); |
1230 | size = 512; | 1249 | size = 512; |
1231 | } | 1250 | } |
1232 | } else { | 1251 | } else { |
@@ -1279,6 +1298,11 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) | |||
1279 | 1298 | ||
1280 | /* we have to call this as early as possible after the MMIO base address is known */ | 1299 | /* we have to call this as early as possible after the MMIO base address is known */ |
1281 | intel_i830_init_gtt_entries(); | 1300 | intel_i830_init_gtt_entries(); |
1301 | if (intel_private.gtt_entries == 0) { | ||
1302 | iounmap(intel_private.gtt); | ||
1303 | iounmap(intel_private.registers); | ||
1304 | return -ENOMEM; | ||
1305 | } | ||
1282 | 1306 | ||
1283 | agp_bridge->gatt_table = NULL; | 1307 | agp_bridge->gatt_table = NULL; |
1284 | 1308 | ||
@@ -1306,6 +1330,16 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, | |||
1306 | return addr | bridge->driver->masks[type].mask; | 1330 | return addr | bridge->driver->masks[type].mask; |
1307 | } | 1331 | } |
1308 | 1332 | ||
1333 | static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, | ||
1334 | dma_addr_t addr, int type) | ||
1335 | { | ||
1336 | /* Shift high bits down */ | ||
1337 | addr |= (addr >> 28) & 0xff; | ||
1338 | |||
1339 | /* Type checking must be done elsewhere */ | ||
1340 | return addr | bridge->driver->masks[type].mask; | ||
1341 | } | ||
1342 | |||
1309 | static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) | 1343 | static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) |
1310 | { | 1344 | { |
1311 | u16 snb_gmch_ctl; | 1345 | u16 snb_gmch_ctl; |
@@ -1387,6 +1421,11 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) | |||
1387 | 1421 | ||
1388 | /* we have to call this as early as possible after the MMIO base address is known */ | 1422 | /* we have to call this as early as possible after the MMIO base address is known */ |
1389 | intel_i830_init_gtt_entries(); | 1423 | intel_i830_init_gtt_entries(); |
1424 | if (intel_private.gtt_entries == 0) { | ||
1425 | iounmap(intel_private.gtt); | ||
1426 | iounmap(intel_private.registers); | ||
1427 | return -ENOMEM; | ||
1428 | } | ||
1390 | 1429 | ||
1391 | agp_bridge->gatt_table = NULL; | 1430 | agp_bridge->gatt_table = NULL; |
1392 | 1431 | ||
@@ -1514,6 +1553,39 @@ static const struct agp_bridge_driver intel_i965_driver = { | |||
1514 | #endif | 1553 | #endif |
1515 | }; | 1554 | }; |
1516 | 1555 | ||
1556 | static const struct agp_bridge_driver intel_gen6_driver = { | ||
1557 | .owner = THIS_MODULE, | ||
1558 | .aperture_sizes = intel_i830_sizes, | ||
1559 | .size_type = FIXED_APER_SIZE, | ||
1560 | .num_aperture_sizes = 4, | ||
1561 | .needs_scratch_page = true, | ||
1562 | .configure = intel_i9xx_configure, | ||
1563 | .fetch_size = intel_i9xx_fetch_size, | ||
1564 | .cleanup = intel_i915_cleanup, | ||
1565 | .mask_memory = intel_gen6_mask_memory, | ||
1566 | .masks = intel_i810_masks, | ||
1567 | .agp_enable = intel_i810_agp_enable, | ||
1568 | .cache_flush = global_cache_flush, | ||
1569 | .create_gatt_table = intel_i965_create_gatt_table, | ||
1570 | .free_gatt_table = intel_i830_free_gatt_table, | ||
1571 | .insert_memory = intel_i915_insert_entries, | ||
1572 | .remove_memory = intel_i915_remove_entries, | ||
1573 | .alloc_by_type = intel_i830_alloc_by_type, | ||
1574 | .free_by_type = intel_i810_free_by_type, | ||
1575 | .agp_alloc_page = agp_generic_alloc_page, | ||
1576 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1577 | .agp_destroy_page = agp_generic_destroy_page, | ||
1578 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1579 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | ||
1580 | .chipset_flush = intel_i915_chipset_flush, | ||
1581 | #ifdef USE_PCI_DMA_API | ||
1582 | .agp_map_page = intel_agp_map_page, | ||
1583 | .agp_unmap_page = intel_agp_unmap_page, | ||
1584 | .agp_map_memory = intel_agp_map_memory, | ||
1585 | .agp_unmap_memory = intel_agp_unmap_memory, | ||
1586 | #endif | ||
1587 | }; | ||
1588 | |||
1517 | static const struct agp_bridge_driver intel_g33_driver = { | 1589 | static const struct agp_bridge_driver intel_g33_driver = { |
1518 | .owner = THIS_MODULE, | 1590 | .owner = THIS_MODULE, |
1519 | .aperture_sizes = intel_i830_sizes, | 1591 | .aperture_sizes = intel_i830_sizes, |