Commit a8c84df9f71e4a7b14bdd41687a70d366c087eef
Committed by
Dave Airlie
1 parent
e3cf69511a
Exists in
master
and in
39 other branches
intel/agp: rewrite GTT on resume
On my Intel chipset (965GM), the GTT is entirely erased across suspend/resume. This patch simply re-plays the current mapping at resume time to restore the table.=20 I noticed this once I started relying on persistent GTT mappings across VT switch in our GEM work -- the old X server and DRM code carefully unbind all memory from the GTT on VT switch, but GEM does not bother. I placed the list management and rewrite code in the generic layer on the assumption that it will be needed on other hardware, but I did not add the rewrite call to anything other than the Intel resume function. Keep a list of current GATT mappings. At resume time, rewrite them into the GATT. This is needed on Intel (at least) as the entire GATT is cleared across suspend/resume. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Keith Packard <keithp@keithp.com> Cc: Dave Jones <davej@codemonkey.org.uk> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Showing 5 changed files with 43 additions and 0 deletions Side-by-side Diff
drivers/char/agp/agp.h
drivers/char/agp/backend.c
drivers/char/agp/generic.c
... | ... | @@ -429,6 +429,10 @@ |
429 | 429 | |
430 | 430 | curr->is_bound = true; |
431 | 431 | curr->pg_start = pg_start; |
432 | + spin_lock(&agp_bridge->mapped_lock); | |
433 | + list_add(&curr->mapped_list, &agp_bridge->mapped_list); | |
434 | + spin_unlock(&agp_bridge->mapped_lock); | |
435 | + | |
432 | 436 | return 0; |
433 | 437 | } |
434 | 438 | EXPORT_SYMBOL(agp_bind_memory); |
435 | 439 | |
... | ... | @@ -461,9 +465,33 @@ |
461 | 465 | |
462 | 466 | curr->is_bound = false; |
463 | 467 | curr->pg_start = 0; |
468 | + spin_lock(&curr->bridge->mapped_lock); | |
469 | + list_del(&curr->mapped_list); | |
470 | + spin_unlock(&curr->bridge->mapped_lock); | |
464 | 471 | return 0; |
465 | 472 | } |
466 | 473 | EXPORT_SYMBOL(agp_unbind_memory); |
474 | + | |
475 | +/** | |
476 | + * agp_rebind_emmory - Rewrite the entire GATT, useful on resume | |
477 | + */ | |
478 | +int agp_rebind_memory(void) | |
479 | +{ | |
480 | + struct agp_memory *curr; | |
481 | + int ret_val = 0; | |
482 | + | |
483 | + spin_lock(&agp_bridge->mapped_lock); | |
484 | + list_for_each_entry(curr, &agp_bridge->mapped_list, mapped_list) { | |
485 | + ret_val = curr->bridge->driver->insert_memory(curr, | |
486 | + curr->pg_start, | |
487 | + curr->type); | |
488 | + if (ret_val != 0) | |
489 | + break; | |
490 | + } | |
491 | + spin_unlock(&agp_bridge->mapped_lock); | |
492 | + return ret_val; | |
493 | +} | |
494 | +EXPORT_SYMBOL(agp_rebind_memory); | |
467 | 495 | |
468 | 496 | /* End - Routines for handling swapping of agp_memory into the GATT */ |
469 | 497 |
drivers/char/agp/intel-agp.c
... | ... | @@ -2244,6 +2244,7 @@ |
2244 | 2244 | static int agp_intel_resume(struct pci_dev *pdev) |
2245 | 2245 | { |
2246 | 2246 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
2247 | + int ret_val; | |
2247 | 2248 | |
2248 | 2249 | pci_restore_state(pdev); |
2249 | 2250 | |
... | ... | @@ -2270,6 +2271,10 @@ |
2270 | 2271 | intel_i810_configure(); |
2271 | 2272 | else if (bridge->driver == &intel_i965_driver) |
2272 | 2273 | intel_i915_configure(); |
2274 | + | |
2275 | + ret_val = agp_rebind_memory(); | |
2276 | + if (ret_val != 0) | |
2277 | + return ret_val; | |
2273 | 2278 | |
2274 | 2279 | return 0; |
2275 | 2280 | } |
include/linux/agp_backend.h
... | ... | @@ -30,6 +30,8 @@ |
30 | 30 | #ifndef _AGP_BACKEND_H |
31 | 31 | #define _AGP_BACKEND_H 1 |
32 | 32 | |
33 | +#include <linux/list.h> | |
34 | + | |
33 | 35 | enum chipset_type { |
34 | 36 | NOT_SUPPORTED, |
35 | 37 | SUPPORTED, |
... | ... | @@ -78,6 +80,8 @@ |
78 | 80 | bool is_bound; |
79 | 81 | bool is_flushed; |
80 | 82 | bool vmalloc_flag; |
83 | + /* list of agp_memory mapped to the aperture */ | |
84 | + struct list_head mapped_list; | |
81 | 85 | }; |
82 | 86 | |
83 | 87 | #define AGP_NORMAL_MEMORY 0 |
... | ... | @@ -96,6 +100,7 @@ |
96 | 100 | extern int agp_copy_info(struct agp_bridge_data *, struct agp_kern_info *); |
97 | 101 | extern int agp_bind_memory(struct agp_memory *, off_t); |
98 | 102 | extern int agp_unbind_memory(struct agp_memory *); |
103 | +extern int agp_rebind_memory(void); | |
99 | 104 | extern void agp_enable(struct agp_bridge_data *, u32); |
100 | 105 | extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *); |
101 | 106 | extern void agp_backend_release(struct agp_bridge_data *); |