diff options
author | Dave Airlie <airlied@redhat.com> | 2009-06-18 20:52:57 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-06-18 20:52:57 -0400 |
commit | a95fe463e73b8c7b2d97606ac86ce261f1270726 (patch) | |
tree | 8917b33b34e148dc4cce53374f15766f86975770 /drivers/char | |
parent | 95934f939c46ea2b37f3c91a4f8c82e003727761 (diff) |
agp: add user mapping support to ATI AGP bridge.
This should fix TTM/KMS on some of the original ATI IGP chipsets.
(rs100/rs200)
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/ati-agp.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 4d38baa209f5..33656e144cc5 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -269,12 +269,17 @@ static int ati_insert_memory(struct agp_memory * mem, | |||
269 | int i, j, num_entries; | 269 | int i, j, num_entries; |
270 | unsigned long __iomem *cur_gatt; | 270 | unsigned long __iomem *cur_gatt; |
271 | unsigned long addr; | 271 | unsigned long addr; |
272 | int mask_type; | ||
272 | 273 | ||
273 | num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; | 274 | num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; |
274 | 275 | ||
275 | if (type != 0 || mem->type != 0) | 276 | mask_type = agp_generic_type_to_mask_type(mem->bridge, type); |
277 | if (mask_type != 0 || type != mem->type) | ||
276 | return -EINVAL; | 278 | return -EINVAL; |
277 | 279 | ||
280 | if (mem->page_count == 0) | ||
281 | return 0; | ||
282 | |||
278 | if ((pg_start + mem->page_count) > num_entries) | 283 | if ((pg_start + mem->page_count) > num_entries) |
279 | return -EINVAL; | 284 | return -EINVAL; |
280 | 285 | ||
@@ -299,8 +304,8 @@ static int ati_insert_memory(struct agp_memory * mem, | |||
299 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 304 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
300 | mem->pages[i], mem->type), | 305 | mem->pages[i], mem->type), |
301 | cur_gatt+GET_GATT_OFF(addr)); | 306 | cur_gatt+GET_GATT_OFF(addr)); |
302 | readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ | ||
303 | } | 307 | } |
308 | readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */ | ||
304 | agp_bridge->driver->tlb_flush(mem); | 309 | agp_bridge->driver->tlb_flush(mem); |
305 | return 0; | 310 | return 0; |
306 | } | 311 | } |
@@ -311,17 +316,22 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, | |||
311 | int i; | 316 | int i; |
312 | unsigned long __iomem *cur_gatt; | 317 | unsigned long __iomem *cur_gatt; |
313 | unsigned long addr; | 318 | unsigned long addr; |
319 | int mask_type; | ||
314 | 320 | ||
315 | if (type != 0 || mem->type != 0) | 321 | mask_type = agp_generic_type_to_mask_type(mem->bridge, type); |
322 | if (mask_type != 0 || type != mem->type) | ||
316 | return -EINVAL; | 323 | return -EINVAL; |
317 | 324 | ||
325 | if (mem->page_count == 0) | ||
326 | return 0; | ||
327 | |||
318 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 328 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
319 | addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; | 329 | addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; |
320 | cur_gatt = GET_GATT(addr); | 330 | cur_gatt = GET_GATT(addr); |
321 | writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); | 331 | writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); |
322 | readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ | ||
323 | } | 332 | } |
324 | 333 | ||
334 | readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */ | ||
325 | agp_bridge->driver->tlb_flush(mem); | 335 | agp_bridge->driver->tlb_flush(mem); |
326 | return 0; | 336 | return 0; |
327 | } | 337 | } |