aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2007-01-23 04:33:43 -0500
committerDave Jones <davej@redhat.com>2007-02-03 17:16:24 -0500
commita030ce4477baa06dd9c037ccd3c8d171aac9ed44 (patch)
tree1961f175a2785cc7d5325f45139558de471c4733
parent0316fe8319ff62e527d0d91a3bc7df1c59eafae8 (diff)
[AGPGART] Allow drm-populated agp memory types
This patch allows drm to populate an agpgart structure with pages of its own. It's needed for the new drm memory manager which dynamically flips pages in and out of AGP. The patch modifies the generic functions as well as the intel agp driver. The intel drm driver is currently the only one supporting the new memory manager. Other agp drivers may need some minor fixing up once they have a corresponding memory manager enabled drm driver. AGP memory types >= AGP_USER_TYPES are not populated by the agpgart driver, but the drm is expected to do that, as well as taking care of cache- and tlb flushing when needed. It's not possible to request these types from user space using agpgart ioctls. The Intel driver also gets a new memory type for pages that can be bound cached to the intel GTT. Signed-off-by: Thomas Hellstrom <thomas@tungstengraphics.com> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--drivers/char/agp/agp.h10
-rw-r--r--drivers/char/agp/ali-agp.c2
-rw-r--r--drivers/char/agp/alpha-agp.c4
-rw-r--r--drivers/char/agp/amd-k7-agp.c1
-rw-r--r--drivers/char/agp/amd64-agp.c11
-rw-r--r--drivers/char/agp/ati-agp.c1
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/efficeon-agp.c1
-rw-r--r--drivers/char/agp/frontend.c3
-rw-r--r--drivers/char/agp/generic.c130
-rw-r--r--drivers/char/agp/hp-agp.c1
-rw-r--r--drivers/char/agp/i460-agp.c7
-rw-r--r--drivers/char/agp/intel-agp.c186
-rw-r--r--drivers/char/agp/nvidia-agp.c1
-rw-r--r--drivers/char/agp/sgi-agp.c1
-rw-r--r--drivers/char/agp/sworks-agp.c1
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/agp/via-agp.c2
-rw-r--r--include/linux/agp_backend.h5
19 files changed, 296 insertions, 75 deletions
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 7fc72d12e7be..9bd68d9f0f59 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -114,6 +114,7 @@ struct agp_bridge_driver {
114 void (*free_by_type)(struct agp_memory *); 114 void (*free_by_type)(struct agp_memory *);
115 void *(*agp_alloc_page)(struct agp_bridge_data *); 115 void *(*agp_alloc_page)(struct agp_bridge_data *);
116 void (*agp_destroy_page)(void *); 116 void (*agp_destroy_page)(void *);
117 int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
117}; 118};
118 119
119struct agp_bridge_data { 120struct agp_bridge_data {
@@ -218,6 +219,7 @@ struct agp_bridge_data {
218#define I810_PTE_MAIN_UNCACHED 0x00000000 219#define I810_PTE_MAIN_UNCACHED 0x00000000
219#define I810_PTE_LOCAL 0x00000002 220#define I810_PTE_LOCAL 0x00000002
220#define I810_PTE_VALID 0x00000001 221#define I810_PTE_VALID 0x00000001
222#define I830_PTE_SYSTEM_CACHED 0x00000006
221#define I810_SMRAM_MISCC 0x70 223#define I810_SMRAM_MISCC 0x70
222#define I810_GFX_MEM_WIN_SIZE 0x00010000 224#define I810_GFX_MEM_WIN_SIZE 0x00010000
223#define I810_GFX_MEM_WIN_32M 0x00010000 225#define I810_GFX_MEM_WIN_32M 0x00010000
@@ -270,8 +272,16 @@ void global_cache_flush(void);
270void get_agp_version(struct agp_bridge_data *bridge); 272void get_agp_version(struct agp_bridge_data *bridge);
271unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, 273unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
272 unsigned long addr, int type); 274 unsigned long addr, int type);
275int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
276 int type);
273struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev); 277struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
274 278
279/* generic functions for user-populated AGP memory types */
280struct agp_memory *agp_generic_alloc_user(size_t page_count, int type);
281void agp_alloc_page_array(size_t size, struct agp_memory *mem);
282void agp_free_page_array(struct agp_memory *mem);
283
284
275/* generic routines for agp>=3 */ 285/* generic routines for agp>=3 */
276int agp3_generic_fetch_size(void); 286int agp3_generic_fetch_size(void);
277void agp3_generic_tlbflush(struct agp_memory *mem); 287void agp3_generic_tlbflush(struct agp_memory *mem);
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 5a31ec7c62fc..98177a93076f 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -214,6 +214,7 @@ static struct agp_bridge_driver ali_generic_bridge = {
214 .free_by_type = agp_generic_free_by_type, 214 .free_by_type = agp_generic_free_by_type,
215 .agp_alloc_page = agp_generic_alloc_page, 215 .agp_alloc_page = agp_generic_alloc_page,
216 .agp_destroy_page = ali_destroy_page, 216 .agp_destroy_page = ali_destroy_page,
217 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
217}; 218};
218 219
219static struct agp_bridge_driver ali_m1541_bridge = { 220static struct agp_bridge_driver ali_m1541_bridge = {
@@ -237,6 +238,7 @@ static struct agp_bridge_driver ali_m1541_bridge = {
237 .free_by_type = agp_generic_free_by_type, 238 .free_by_type = agp_generic_free_by_type,
238 .agp_alloc_page = m1541_alloc_page, 239 .agp_alloc_page = m1541_alloc_page,
239 .agp_destroy_page = m1541_destroy_page, 240 .agp_destroy_page = m1541_destroy_page,
241 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
240}; 242};
241 243
242 244
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index b4e00a343da9..b0acf41c0db9 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -91,6 +91,9 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
91 int num_entries, status; 91 int num_entries, status;
92 void *temp; 92 void *temp;
93 93
94 if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
95 return -EINVAL;
96
94 temp = agp_bridge->current_size; 97 temp = agp_bridge->current_size;
95 num_entries = A_SIZE_FIX(temp)->num_entries; 98 num_entries = A_SIZE_FIX(temp)->num_entries;
96 if ((pg_start + mem->page_count) > num_entries) 99 if ((pg_start + mem->page_count) > num_entries)
@@ -142,6 +145,7 @@ struct agp_bridge_driver alpha_core_agp_driver = {
142 .free_by_type = agp_generic_free_by_type, 145 .free_by_type = agp_generic_free_by_type,
143 .agp_alloc_page = agp_generic_alloc_page, 146 .agp_alloc_page = agp_generic_alloc_page,
144 .agp_destroy_page = agp_generic_destroy_page, 147 .agp_destroy_page = agp_generic_destroy_page,
148 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
145}; 149};
146 150
147struct agp_bridge_data *alpha_bridge; 151struct agp_bridge_data *alpha_bridge;
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index c85c8cadb6df..3d8d448bf394 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -381,6 +381,7 @@ static struct agp_bridge_driver amd_irongate_driver = {
381 .free_by_type = agp_generic_free_by_type, 381 .free_by_type = agp_generic_free_by_type,
382 .agp_alloc_page = agp_generic_alloc_page, 382 .agp_alloc_page = agp_generic_alloc_page,
383 .agp_destroy_page = agp_generic_destroy_page, 383 .agp_destroy_page = agp_generic_destroy_page,
384 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
384}; 385};
385 386
386static struct agp_device_ids amd_agp_device_ids[] __devinitdata = 387static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 93d2209fee4c..636d984ed4a6 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -62,12 +62,18 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
62{ 62{
63 int i, j, num_entries; 63 int i, j, num_entries;
64 long long tmp; 64 long long tmp;
65 int mask_type;
66 struct agp_bridge_data *bridge = mem->bridge;
65 u32 pte; 67 u32 pte;
66 68
67 num_entries = agp_num_entries(); 69 num_entries = agp_num_entries();
68 70
69 if (type != 0 || mem->type != 0) 71 if (type != mem->type)
70 return -EINVAL; 72 return -EINVAL;
73 mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
74 if (mask_type != 0)
75 return -EINVAL;
76
71 77
72 /* Make sure we can fit the range in the gatt table. */ 78 /* Make sure we can fit the range in the gatt table. */
73 /* FIXME: could wrap */ 79 /* FIXME: could wrap */
@@ -90,7 +96,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
90 96
91 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 97 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
92 tmp = agp_bridge->driver->mask_memory(agp_bridge, 98 tmp = agp_bridge->driver->mask_memory(agp_bridge,
93 mem->memory[i], mem->type); 99 mem->memory[i], mask_type);
94 100
95 BUG_ON(tmp & 0xffffff0000000ffcULL); 101 BUG_ON(tmp & 0xffffff0000000ffcULL);
96 pte = (tmp & 0x000000ff00000000ULL) >> 28; 102 pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -247,6 +253,7 @@ static struct agp_bridge_driver amd_8151_driver = {
247 .free_by_type = agp_generic_free_by_type, 253 .free_by_type = agp_generic_free_by_type,
248 .agp_alloc_page = agp_generic_alloc_page, 254 .agp_alloc_page = agp_generic_alloc_page,
249 .agp_destroy_page = agp_generic_destroy_page, 255 .agp_destroy_page = agp_generic_destroy_page,
256 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
250}; 257};
251 258
252/* Some basic sanity checks for the aperture. */ 259/* Some basic sanity checks for the aperture. */
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 9987dc2e0c3f..77c9ad68fba9 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -431,6 +431,7 @@ static struct agp_bridge_driver ati_generic_bridge = {
431 .free_by_type = agp_generic_free_by_type, 431 .free_by_type = agp_generic_free_by_type,
432 .agp_alloc_page = agp_generic_alloc_page, 432 .agp_alloc_page = agp_generic_alloc_page,
433 .agp_destroy_page = agp_generic_destroy_page, 433 .agp_destroy_page = agp_generic_destroy_page,
434 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
434}; 435};
435 436
436 437
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index d59e037ddd12..ebdd6dd66edb 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -43,7 +43,7 @@
43 * fix some real stupidity. It's only by chance we can bump 43 * fix some real stupidity. It's only by chance we can bump
44 * past 0.99 at all due to some boolean logic error. */ 44 * past 0.99 at all due to some boolean logic error. */
45#define AGPGART_VERSION_MAJOR 0 45#define AGPGART_VERSION_MAJOR 0
46#define AGPGART_VERSION_MINOR 101 46#define AGPGART_VERSION_MINOR 102
47static const struct agp_version agp_current_version = 47static const struct agp_version agp_current_version =
48{ 48{
49 .major = AGPGART_VERSION_MAJOR, 49 .major = AGPGART_VERSION_MAJOR,
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 30f730ff81c1..658cb1a72d2c 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -335,6 +335,7 @@ static struct agp_bridge_driver efficeon_driver = {
335 .free_by_type = agp_generic_free_by_type, 335 .free_by_type = agp_generic_free_by_type,
336 .agp_alloc_page = agp_generic_alloc_page, 336 .agp_alloc_page = agp_generic_alloc_page,
337 .agp_destroy_page = agp_generic_destroy_page, 337 .agp_destroy_page = agp_generic_destroy_page,
338 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
338}; 339};
339 340
340static int __devinit agp_efficeon_probe(struct pci_dev *pdev, 341static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index ee06f382339b..679d7f972439 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -892,6 +892,9 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
892 if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate))) 892 if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
893 return -EFAULT; 893 return -EFAULT;
894 894
895 if (alloc.type >= AGP_USER_TYPES)
896 return -EINVAL;
897
895 memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 898 memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
896 899
897 if (memory == NULL) 900 if (memory == NULL)
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 3491d6f84bc6..a627b771c2eb 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -101,6 +101,67 @@ static int agp_get_key(void)
101 return -1; 101 return -1;
102} 102}
103 103
104/*
105 * Use kmalloc if possible for the page list. Otherwise fall back to
106 * vmalloc. This speeds things up and also saves memory for small AGP
107 * regions.
108 */
109
110void agp_alloc_page_array(size_t size, struct agp_memory *mem)
111{
112 mem->memory = NULL;
113 mem->vmalloc_flag = 0;
114
115 if (size <= 2*PAGE_SIZE) {
116 mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
117 }
118 if (mem->memory == NULL) {
119 mem->memory = vmalloc(size);
120 mem->vmalloc_flag = 1;
121 }
122}
123EXPORT_SYMBOL(agp_alloc_page_array);
124
125void agp_free_page_array(struct agp_memory *mem)
126{
127 if (mem->vmalloc_flag) {
128 vfree(mem->memory);
129 } else {
130 kfree(mem->memory);
131 }
132}
133EXPORT_SYMBOL(agp_free_page_array);
134
135
136static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
137{
138 struct agp_memory *new;
139 unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
140
141 new = kmalloc(sizeof(struct agp_memory), GFP_KERNEL);
142
143 if (new == NULL)
144 return NULL;
145
146 memset(new, 0, sizeof(struct agp_memory));
147 new->key = agp_get_key();
148
149 if (new->key < 0) {
150 kfree(new);
151 return NULL;
152 }
153
154 agp_alloc_page_array(alloc_size, new);
155
156 if (new->memory == NULL) {
157 agp_free_key(new->key);
158 kfree(new);
159 return NULL;
160 }
161 new->num_scratch_pages = 0;
162 return new;
163}
164
104 165
105struct agp_memory *agp_create_memory(int scratch_pages) 166struct agp_memory *agp_create_memory(int scratch_pages)
106{ 167{
@@ -116,7 +177,8 @@ struct agp_memory *agp_create_memory(int scratch_pages)
116 kfree(new); 177 kfree(new);
117 return NULL; 178 return NULL;
118 } 179 }
119 new->memory = vmalloc(PAGE_SIZE * scratch_pages); 180
181 agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
120 182
121 if (new->memory == NULL) { 183 if (new->memory == NULL) {
122 agp_free_key(new->key); 184 agp_free_key(new->key);
@@ -124,6 +186,7 @@ struct agp_memory *agp_create_memory(int scratch_pages)
124 return NULL; 186 return NULL;
125 } 187 }
126 new->num_scratch_pages = scratch_pages; 188 new->num_scratch_pages = scratch_pages;
189 new->type = AGP_NORMAL_MEMORY;
127 return new; 190 return new;
128} 191}
129EXPORT_SYMBOL(agp_create_memory); 192EXPORT_SYMBOL(agp_create_memory);
@@ -146,6 +209,11 @@ void agp_free_memory(struct agp_memory *curr)
146 if (curr->is_bound == TRUE) 209 if (curr->is_bound == TRUE)
147 agp_unbind_memory(curr); 210 agp_unbind_memory(curr);
148 211
212 if (curr->type >= AGP_USER_TYPES) {
213 agp_generic_free_by_type(curr);
214 return;
215 }
216
149 if (curr->type != 0) { 217 if (curr->type != 0) {
150 curr->bridge->driver->free_by_type(curr); 218 curr->bridge->driver->free_by_type(curr);
151 return; 219 return;
@@ -157,7 +225,7 @@ void agp_free_memory(struct agp_memory *curr)
157 flush_agp_mappings(); 225 flush_agp_mappings();
158 } 226 }
159 agp_free_key(curr->key); 227 agp_free_key(curr->key);
160 vfree(curr->memory); 228 agp_free_page_array(curr);
161 kfree(curr); 229 kfree(curr);
162} 230}
163EXPORT_SYMBOL(agp_free_memory); 231EXPORT_SYMBOL(agp_free_memory);
@@ -188,6 +256,13 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
188 if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp) 256 if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
189 return NULL; 257 return NULL;
190 258
259 if (type >= AGP_USER_TYPES) {
260 new = agp_generic_alloc_user(page_count, type);
261 if (new)
262 new->bridge = bridge;
263 return new;
264 }
265
191 if (type != 0) { 266 if (type != 0) {
192 new = bridge->driver->alloc_by_type(page_count, type); 267 new = bridge->driver->alloc_by_type(page_count, type);
193 if (new) 268 if (new)
@@ -960,6 +1035,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
960 off_t j; 1035 off_t j;
961 void *temp; 1036 void *temp;
962 struct agp_bridge_data *bridge; 1037 struct agp_bridge_data *bridge;
1038 int mask_type;
963 1039
964 bridge = mem->bridge; 1040 bridge = mem->bridge;
965 if (!bridge) 1041 if (!bridge)
@@ -995,7 +1071,12 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
995 num_entries -= agp_memory_reserved/PAGE_SIZE; 1071 num_entries -= agp_memory_reserved/PAGE_SIZE;
996 if (num_entries < 0) num_entries = 0; 1072 if (num_entries < 0) num_entries = 0;
997 1073
998 if (type != 0 || mem->type != 0) { 1074 if (type != mem->type) {
1075 return -EINVAL;
1076 }
1077
1078 mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
1079 if (mask_type != 0) {
999 /* The generic routines know nothing of memory types */ 1080 /* The generic routines know nothing of memory types */
1000 return -EINVAL; 1081 return -EINVAL;
1001 } 1082 }
@@ -1018,7 +1099,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
1018 } 1099 }
1019 1100
1020 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1101 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1021 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); 1102 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
1103 bridge->gatt_table+j);
1022 } 1104 }
1023 readl(bridge->gatt_table+j-1); /* PCI Posting. */ 1105 readl(bridge->gatt_table+j-1); /* PCI Posting. */
1024 1106
@@ -1032,6 +1114,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1032{ 1114{
1033 size_t i; 1115 size_t i;
1034 struct agp_bridge_data *bridge; 1116 struct agp_bridge_data *bridge;
1117 int mask_type;
1035 1118
1036 bridge = mem->bridge; 1119 bridge = mem->bridge;
1037 if (!bridge) 1120 if (!bridge)
@@ -1040,7 +1123,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1040 if (mem->page_count == 0) 1123 if (mem->page_count == 0)
1041 return 0; 1124 return 0;
1042 1125
1043 if (type != 0 || mem->type != 0) { 1126 if (type != mem->type)
1127 return -EINVAL;
1128
1129 mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
1130 if (mask_type != 0) {
1044 /* The generic routines know nothing of memory types */ 1131 /* The generic routines know nothing of memory types */
1045 return -EINVAL; 1132 return -EINVAL;
1046 } 1133 }
@@ -1066,12 +1153,34 @@ EXPORT_SYMBOL(agp_generic_alloc_by_type);
1066 1153
1067void agp_generic_free_by_type(struct agp_memory *curr) 1154void agp_generic_free_by_type(struct agp_memory *curr)
1068{ 1155{
1069 vfree(curr->memory); 1156 agp_free_page_array(curr);
1070 agp_free_key(curr->key); 1157 agp_free_key(curr->key);
1071 kfree(curr); 1158 kfree(curr);
1072} 1159}
1073EXPORT_SYMBOL(agp_generic_free_by_type); 1160EXPORT_SYMBOL(agp_generic_free_by_type);
1074 1161
1162struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
1163{
1164 struct agp_memory *new;
1165 int i;
1166 int pages;
1167
1168 pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
1169 new = agp_create_user_memory(page_count);
1170 if (new == NULL)
1171 return NULL;
1172
1173 for (i = 0; i < page_count; i++) {
1174 new->memory[i] = 0;
1175 }
1176 new->page_count = 0;
1177 new->type = type;
1178 new->num_scratch_pages = pages;
1179
1180 return new;
1181}
1182EXPORT_SYMBOL(agp_generic_alloc_user);
1183
1075 1184
1076/* 1185/*
1077 * Basic Page Allocation Routines - 1186 * Basic Page Allocation Routines -
@@ -1165,6 +1274,15 @@ unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
1165} 1274}
1166EXPORT_SYMBOL(agp_generic_mask_memory); 1275EXPORT_SYMBOL(agp_generic_mask_memory);
1167 1276
1277int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
1278 int type)
1279{
1280 if (type >= AGP_USER_TYPES)
1281 return 0;
1282 return type;
1283}
1284EXPORT_SYMBOL(agp_generic_type_to_mask_type);
1285
1168/* 1286/*
1169 * These functions are implemented according to the AGPv3 spec, 1287 * These functions are implemented according to the AGPv3 spec,
1170 * which covers implementation details that had previously been 1288 * which covers implementation details that had previously been
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 907fb66ec4a9..847deabf7f9b 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -438,6 +438,7 @@ struct agp_bridge_driver hp_zx1_driver = {
438 .free_by_type = agp_generic_free_by_type, 438 .free_by_type = agp_generic_free_by_type,
439 .agp_alloc_page = agp_generic_alloc_page, 439 .agp_alloc_page = agp_generic_alloc_page,
440 .agp_destroy_page = agp_generic_destroy_page, 440 .agp_destroy_page = agp_generic_destroy_page,
441 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
441 .cant_use_aperture = 1, 442 .cant_use_aperture = 1,
442}; 443};
443 444
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 91769443d8fe..3e7618653abd 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -293,6 +293,9 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
293 pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n", 293 pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
294 mem, pg_start, type, mem->memory[0]); 294 mem, pg_start, type, mem->memory[0]);
295 295
296 if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
297 return -EINVAL;
298
296 io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start; 299 io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
297 300
298 temp = agp_bridge->current_size; 301 temp = agp_bridge->current_size;
@@ -396,6 +399,9 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
396 struct lp_desc *start, *end, *lp; 399 struct lp_desc *start, *end, *lp;
397 void *temp; 400 void *temp;
398 401
402 if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
403 return -EINVAL;
404
399 temp = agp_bridge->current_size; 405 temp = agp_bridge->current_size;
400 num_entries = A_SIZE_8(temp)->num_entries; 406 num_entries = A_SIZE_8(temp)->num_entries;
401 407
@@ -572,6 +578,7 @@ struct agp_bridge_driver intel_i460_driver = {
572#endif 578#endif
573 .alloc_by_type = agp_generic_alloc_by_type, 579 .alloc_by_type = agp_generic_alloc_by_type,
574 .free_by_type = agp_generic_free_by_type, 580 .free_by_type = agp_generic_free_by_type,
581 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
575 .cant_use_aperture = 1, 582 .cant_use_aperture = 1,
576}; 583};
577 584
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index a3011de51f7c..4e455f03b4f0 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -24,6 +24,9 @@
24 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB) 24 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
25 25
26 26
27extern int agp_memory_reserved;
28
29
27/* Intel 815 register */ 30/* Intel 815 register */
28#define INTEL_815_APCONT 0x51 31#define INTEL_815_APCONT 0x51
29#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF 32#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
@@ -68,12 +71,15 @@ static struct aper_size_info_fixed intel_i810_sizes[] =
68 71
69#define AGP_DCACHE_MEMORY 1 72#define AGP_DCACHE_MEMORY 1
70#define AGP_PHYS_MEMORY 2 73#define AGP_PHYS_MEMORY 2
74#define INTEL_AGP_CACHED_MEMORY 3
71 75
72static struct gatt_mask intel_i810_masks[] = 76static struct gatt_mask intel_i810_masks[] =
73{ 77{
74 {.mask = I810_PTE_VALID, .type = 0}, 78 {.mask = I810_PTE_VALID, .type = 0},
75 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, 79 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
76 {.mask = I810_PTE_VALID, .type = 0} 80 {.mask = I810_PTE_VALID, .type = 0},
81 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
82 .type = INTEL_AGP_CACHED_MEMORY}
77}; 83};
78 84
79static struct _intel_i810_private { 85static struct _intel_i810_private {
@@ -82,6 +88,7 @@ static struct _intel_i810_private {
82 int num_dcache_entries; 88 int num_dcache_entries;
83} intel_i810_private; 89} intel_i810_private;
84 90
91
85static int intel_i810_fetch_size(void) 92static int intel_i810_fetch_size(void)
86{ 93{
87 u32 smram_miscc; 94 u32 smram_miscc;
@@ -201,62 +208,79 @@ static void i8xx_destroy_pages(void *addr)
201 atomic_dec(&agp_bridge->current_memory_agp); 208 atomic_dec(&agp_bridge->current_memory_agp);
202} 209}
203 210
211static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
212 int type)
213{
214 if (type < AGP_USER_TYPES)
215 return type;
216 else if (type == AGP_USER_CACHED_MEMORY)
217 return INTEL_AGP_CACHED_MEMORY;
218 else
219 return 0;
220}
221
204static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, 222static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
205 int type) 223 int type)
206{ 224{
207 int i, j, num_entries; 225 int i, j, num_entries;
208 void *temp; 226 void *temp;
227 int ret = -EINVAL;
228 int mask_type;
209 229
210 if (mem->page_count == 0) 230 if (mem->page_count == 0)
211 return 0; 231 goto out;
212 232
213 temp = agp_bridge->current_size; 233 temp = agp_bridge->current_size;
214 num_entries = A_SIZE_FIX(temp)->num_entries; 234 num_entries = A_SIZE_FIX(temp)->num_entries;
215 235
216 if ((pg_start + mem->page_count) > num_entries) 236 if ((pg_start + mem->page_count) > num_entries)
217 return -EINVAL; 237 goto out_err;
218 238
219 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
220 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
221 return -EBUSY;
222 }
223 239
224 if (type != 0 || mem->type != 0) { 240 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
225 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { 241 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
226 /* special insert */ 242 ret = -EBUSY;
227 if (!mem->is_flushed) { 243 goto out_err;
228 global_cache_flush();
229 mem->is_flushed = TRUE;
230 }
231
232 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
233 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
234 }
235 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
236
237 agp_bridge->driver->tlb_flush(mem);
238 return 0;
239 } 244 }
240 if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
241 goto insert;
242 return -EINVAL;
243 } 245 }
244 246
245insert: 247 if (type != mem->type)
246 if (!mem->is_flushed) { 248 goto out_err;
247 global_cache_flush();
248 mem->is_flushed = TRUE;
249 }
250 249
251 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 250 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
252 writel(agp_bridge->driver->mask_memory(agp_bridge, 251
253 mem->memory[i], mem->type), 252 switch (mask_type) {
254 intel_i810_private.registers+I810_PTE_BASE+(j*4)); 253 case AGP_DCACHE_MEMORY:
254 if (!mem->is_flushed)
255 global_cache_flush();
256 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
257 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
258 intel_i810_private.registers+I810_PTE_BASE+(i*4));
259 }
260 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
261 break;
262 case AGP_PHYS_MEMORY:
263 case AGP_NORMAL_MEMORY:
264 if (!mem->is_flushed)
265 global_cache_flush();
266 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
267 writel(agp_bridge->driver->mask_memory(agp_bridge,
268 mem->memory[i],
269 mask_type),
270 intel_i810_private.registers+I810_PTE_BASE+(j*4));
271 }
272 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
273 break;
274 default:
275 goto out_err;
255 } 276 }
256 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
257 277
258 agp_bridge->driver->tlb_flush(mem); 278 agp_bridge->driver->tlb_flush(mem);
259 return 0; 279out:
280 ret = 0;
281out_err:
282 mem->is_flushed = 1;
283 return ret;
260} 284}
261 285
262static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, 286static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
@@ -337,12 +361,11 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
337 new->type = AGP_DCACHE_MEMORY; 361 new->type = AGP_DCACHE_MEMORY;
338 new->page_count = pg_count; 362 new->page_count = pg_count;
339 new->num_scratch_pages = 0; 363 new->num_scratch_pages = 0;
340 vfree(new->memory); 364 agp_free_page_array(new);
341 return new; 365 return new;
342 } 366 }
343 if (type == AGP_PHYS_MEMORY) 367 if (type == AGP_PHYS_MEMORY)
344 return alloc_agpphysmem_i8xx(pg_count, type); 368 return alloc_agpphysmem_i8xx(pg_count, type);
345
346 return NULL; 369 return NULL;
347} 370}
348 371
@@ -357,7 +380,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
357 gart_to_virt(curr->memory[0])); 380 gart_to_virt(curr->memory[0]));
358 global_flush_tlb(); 381 global_flush_tlb();
359 } 382 }
360 vfree(curr->memory); 383 agp_free_page_array(curr);
361 } 384 }
362 kfree(curr); 385 kfree(curr);
363} 386}
@@ -619,9 +642,11 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
619{ 642{
620 int i,j,num_entries; 643 int i,j,num_entries;
621 void *temp; 644 void *temp;
645 int ret = -EINVAL;
646 int mask_type;
622 647
623 if (mem->page_count == 0) 648 if (mem->page_count == 0)
624 return 0; 649 goto out;
625 650
626 temp = agp_bridge->current_size; 651 temp = agp_bridge->current_size;
627 num_entries = A_SIZE_FIX(temp)->num_entries; 652 num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -631,34 +656,41 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
631 pg_start,intel_i830_private.gtt_entries); 656 pg_start,intel_i830_private.gtt_entries);
632 657
633 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); 658 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
634 return -EINVAL; 659 goto out_err;
635 } 660 }
636 661
637 if ((pg_start + mem->page_count) > num_entries) 662 if ((pg_start + mem->page_count) > num_entries)
638 return -EINVAL; 663 goto out_err;
639 664
640 /* The i830 can't check the GTT for entries since its read only, 665 /* The i830 can't check the GTT for entries since its read only,
641 * depend on the caller to make the correct offset decisions. 666 * depend on the caller to make the correct offset decisions.
642 */ 667 */
643 668
644 if ((type != 0 && type != AGP_PHYS_MEMORY) || 669 if (type != mem->type)
645 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 670 goto out_err;
646 return -EINVAL; 671
672 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
647 673
648 if (!mem->is_flushed) { 674 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
675 mask_type != INTEL_AGP_CACHED_MEMORY)
676 goto out_err;
677
678 if (!mem->is_flushed)
649 global_cache_flush(); 679 global_cache_flush();
650 mem->is_flushed = TRUE;
651 }
652 680
653 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 681 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
654 writel(agp_bridge->driver->mask_memory(agp_bridge, 682 writel(agp_bridge->driver->mask_memory(agp_bridge,
655 mem->memory[i], mem->type), 683 mem->memory[i], mask_type),
656 intel_i830_private.registers+I810_PTE_BASE+(j*4)); 684 intel_i830_private.registers+I810_PTE_BASE+(j*4));
657 } 685 }
658 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); 686 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
659
660 agp_bridge->driver->tlb_flush(mem); 687 agp_bridge->driver->tlb_flush(mem);
661 return 0; 688
689out:
690 ret = 0;
691out_err:
692 mem->is_flushed = 1;
693 return ret;
662} 694}
663 695
664static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, 696static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -687,7 +719,6 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
687{ 719{
688 if (type == AGP_PHYS_MEMORY) 720 if (type == AGP_PHYS_MEMORY)
689 return alloc_agpphysmem_i8xx(pg_count, type); 721 return alloc_agpphysmem_i8xx(pg_count, type);
690
691 /* always return NULL for other allocation types for now */ 722 /* always return NULL for other allocation types for now */
692 return NULL; 723 return NULL;
693} 724}
@@ -734,9 +765,11 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
734{ 765{
735 int i,j,num_entries; 766 int i,j,num_entries;
736 void *temp; 767 void *temp;
768 int ret = -EINVAL;
769 int mask_type;
737 770
738 if (mem->page_count == 0) 771 if (mem->page_count == 0)
739 return 0; 772 goto out;
740 773
741 temp = agp_bridge->current_size; 774 temp = agp_bridge->current_size;
742 num_entries = A_SIZE_FIX(temp)->num_entries; 775 num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -746,33 +779,41 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
746 pg_start,intel_i830_private.gtt_entries); 779 pg_start,intel_i830_private.gtt_entries);
747 780
748 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); 781 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
749 return -EINVAL; 782 goto out_err;
750 } 783 }
751 784
752 if ((pg_start + mem->page_count) > num_entries) 785 if ((pg_start + mem->page_count) > num_entries)
753 return -EINVAL; 786 goto out_err;
754 787
755 /* The i830 can't check the GTT for entries since its read only, 788 /* The i915 can't check the GTT for entries since its read only,
756 * depend on the caller to make the correct offset decisions. 789 * depend on the caller to make the correct offset decisions.
757 */ 790 */
758 791
759 if ((type != 0 && type != AGP_PHYS_MEMORY) || 792 if (type != mem->type)
760 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 793 goto out_err;
761 return -EINVAL; 794
795 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
762 796
763 if (!mem->is_flushed) { 797 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
798 mask_type != INTEL_AGP_CACHED_MEMORY)
799 goto out_err;
800
801 if (!mem->is_flushed)
764 global_cache_flush(); 802 global_cache_flush();
765 mem->is_flushed = TRUE;
766 }
767 803
768 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 804 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
769 writel(agp_bridge->driver->mask_memory(agp_bridge, 805 writel(agp_bridge->driver->mask_memory(agp_bridge,
770 mem->memory[i], mem->type), intel_i830_private.gtt+j); 806 mem->memory[i], mask_type), intel_i830_private.gtt+j);
771 } 807 }
772 readl(intel_i830_private.gtt+j-1);
773 808
809 readl(intel_i830_private.gtt+j-1);
774 agp_bridge->driver->tlb_flush(mem); 810 agp_bridge->driver->tlb_flush(mem);
775 return 0; 811
812 out:
813 ret = 0;
814 out_err:
815 mem->is_flushed = 1;
816 return ret;
776} 817}
777 818
778static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, 819static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -1384,6 +1425,7 @@ static struct agp_bridge_driver intel_generic_driver = {
1384 .free_by_type = agp_generic_free_by_type, 1425 .free_by_type = agp_generic_free_by_type,
1385 .agp_alloc_page = agp_generic_alloc_page, 1426 .agp_alloc_page = agp_generic_alloc_page,
1386 .agp_destroy_page = agp_generic_destroy_page, 1427 .agp_destroy_page = agp_generic_destroy_page,
1428 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1387}; 1429};
1388 1430
1389static struct agp_bridge_driver intel_810_driver = { 1431static struct agp_bridge_driver intel_810_driver = {
@@ -1408,6 +1450,7 @@ static struct agp_bridge_driver intel_810_driver = {
1408 .free_by_type = intel_i810_free_by_type, 1450 .free_by_type = intel_i810_free_by_type,
1409 .agp_alloc_page = agp_generic_alloc_page, 1451 .agp_alloc_page = agp_generic_alloc_page,
1410 .agp_destroy_page = agp_generic_destroy_page, 1452 .agp_destroy_page = agp_generic_destroy_page,
1453 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1411}; 1454};
1412 1455
1413static struct agp_bridge_driver intel_815_driver = { 1456static struct agp_bridge_driver intel_815_driver = {
@@ -1431,6 +1474,7 @@ static struct agp_bridge_driver intel_815_driver = {
1431 .free_by_type = agp_generic_free_by_type, 1474 .free_by_type = agp_generic_free_by_type,
1432 .agp_alloc_page = agp_generic_alloc_page, 1475 .agp_alloc_page = agp_generic_alloc_page,
1433 .agp_destroy_page = agp_generic_destroy_page, 1476 .agp_destroy_page = agp_generic_destroy_page,
1477 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1434}; 1478};
1435 1479
1436static struct agp_bridge_driver intel_830_driver = { 1480static struct agp_bridge_driver intel_830_driver = {
@@ -1455,6 +1499,7 @@ static struct agp_bridge_driver intel_830_driver = {
1455 .free_by_type = intel_i810_free_by_type, 1499 .free_by_type = intel_i810_free_by_type,
1456 .agp_alloc_page = agp_generic_alloc_page, 1500 .agp_alloc_page = agp_generic_alloc_page,
1457 .agp_destroy_page = agp_generic_destroy_page, 1501 .agp_destroy_page = agp_generic_destroy_page,
1502 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1458}; 1503};
1459 1504
1460static struct agp_bridge_driver intel_820_driver = { 1505static struct agp_bridge_driver intel_820_driver = {
@@ -1478,6 +1523,7 @@ static struct agp_bridge_driver intel_820_driver = {
1478 .free_by_type = agp_generic_free_by_type, 1523 .free_by_type = agp_generic_free_by_type,
1479 .agp_alloc_page = agp_generic_alloc_page, 1524 .agp_alloc_page = agp_generic_alloc_page,
1480 .agp_destroy_page = agp_generic_destroy_page, 1525 .agp_destroy_page = agp_generic_destroy_page,
1526 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1481}; 1527};
1482 1528
1483static struct agp_bridge_driver intel_830mp_driver = { 1529static struct agp_bridge_driver intel_830mp_driver = {
@@ -1501,6 +1547,7 @@ static struct agp_bridge_driver intel_830mp_driver = {
1501 .free_by_type = agp_generic_free_by_type, 1547 .free_by_type = agp_generic_free_by_type,
1502 .agp_alloc_page = agp_generic_alloc_page, 1548 .agp_alloc_page = agp_generic_alloc_page,
1503 .agp_destroy_page = agp_generic_destroy_page, 1549 .agp_destroy_page = agp_generic_destroy_page,
1550 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1504}; 1551};
1505 1552
1506static struct agp_bridge_driver intel_840_driver = { 1553static struct agp_bridge_driver intel_840_driver = {
@@ -1524,6 +1571,7 @@ static struct agp_bridge_driver intel_840_driver = {
1524 .free_by_type = agp_generic_free_by_type, 1571 .free_by_type = agp_generic_free_by_type,
1525 .agp_alloc_page = agp_generic_alloc_page, 1572 .agp_alloc_page = agp_generic_alloc_page,
1526 .agp_destroy_page = agp_generic_destroy_page, 1573 .agp_destroy_page = agp_generic_destroy_page,
1574 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1527}; 1575};
1528 1576
1529static struct agp_bridge_driver intel_845_driver = { 1577static struct agp_bridge_driver intel_845_driver = {
@@ -1547,6 +1595,7 @@ static struct agp_bridge_driver intel_845_driver = {
1547 .free_by_type = agp_generic_free_by_type, 1595 .free_by_type = agp_generic_free_by_type,
1548 .agp_alloc_page = agp_generic_alloc_page, 1596 .agp_alloc_page = agp_generic_alloc_page,
1549 .agp_destroy_page = agp_generic_destroy_page, 1597 .agp_destroy_page = agp_generic_destroy_page,
1598 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1550}; 1599};
1551 1600
1552static struct agp_bridge_driver intel_850_driver = { 1601static struct agp_bridge_driver intel_850_driver = {
@@ -1570,6 +1619,7 @@ static struct agp_bridge_driver intel_850_driver = {
1570 .free_by_type = agp_generic_free_by_type, 1619 .free_by_type = agp_generic_free_by_type,
1571 .agp_alloc_page = agp_generic_alloc_page, 1620 .agp_alloc_page = agp_generic_alloc_page,
1572 .agp_destroy_page = agp_generic_destroy_page, 1621 .agp_destroy_page = agp_generic_destroy_page,
1622 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1573}; 1623};
1574 1624
1575static struct agp_bridge_driver intel_860_driver = { 1625static struct agp_bridge_driver intel_860_driver = {
@@ -1593,6 +1643,7 @@ static struct agp_bridge_driver intel_860_driver = {
1593 .free_by_type = agp_generic_free_by_type, 1643 .free_by_type = agp_generic_free_by_type,
1594 .agp_alloc_page = agp_generic_alloc_page, 1644 .agp_alloc_page = agp_generic_alloc_page,
1595 .agp_destroy_page = agp_generic_destroy_page, 1645 .agp_destroy_page = agp_generic_destroy_page,
1646 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1596}; 1647};
1597 1648
1598static struct agp_bridge_driver intel_915_driver = { 1649static struct agp_bridge_driver intel_915_driver = {
@@ -1617,6 +1668,7 @@ static struct agp_bridge_driver intel_915_driver = {
1617 .free_by_type = intel_i810_free_by_type, 1668 .free_by_type = intel_i810_free_by_type,
1618 .agp_alloc_page = agp_generic_alloc_page, 1669 .agp_alloc_page = agp_generic_alloc_page,
1619 .agp_destroy_page = agp_generic_destroy_page, 1670 .agp_destroy_page = agp_generic_destroy_page,
1671 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1620}; 1672};
1621 1673
1622static struct agp_bridge_driver intel_i965_driver = { 1674static struct agp_bridge_driver intel_i965_driver = {
@@ -1641,6 +1693,7 @@ static struct agp_bridge_driver intel_i965_driver = {
1641 .free_by_type = intel_i810_free_by_type, 1693 .free_by_type = intel_i810_free_by_type,
1642 .agp_alloc_page = agp_generic_alloc_page, 1694 .agp_alloc_page = agp_generic_alloc_page,
1643 .agp_destroy_page = agp_generic_destroy_page, 1695 .agp_destroy_page = agp_generic_destroy_page,
1696 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1644}; 1697};
1645 1698
1646static struct agp_bridge_driver intel_7505_driver = { 1699static struct agp_bridge_driver intel_7505_driver = {
@@ -1664,6 +1717,7 @@ static struct agp_bridge_driver intel_7505_driver = {
1664 .free_by_type = agp_generic_free_by_type, 1717 .free_by_type = agp_generic_free_by_type,
1665 .agp_alloc_page = agp_generic_alloc_page, 1718 .agp_alloc_page = agp_generic_alloc_page,
1666 .agp_destroy_page = agp_generic_destroy_page, 1719 .agp_destroy_page = agp_generic_destroy_page,
1720 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1667}; 1721};
1668 1722
1669static int find_i810(u16 device) 1723static int find_i810(u16 device)
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index df7f37b2739a..2563286b2fcf 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -310,6 +310,7 @@ static struct agp_bridge_driver nvidia_driver = {
310 .free_by_type = agp_generic_free_by_type, 310 .free_by_type = agp_generic_free_by_type,
311 .agp_alloc_page = agp_generic_alloc_page, 311 .agp_alloc_page = agp_generic_alloc_page,
312 .agp_destroy_page = agp_generic_destroy_page, 312 .agp_destroy_page = agp_generic_destroy_page,
313 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
313}; 314};
314 315
315static int __devinit agp_nvidia_probe(struct pci_dev *pdev, 316static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 902648db7efa..92d1dc45b9be 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -265,6 +265,7 @@ struct agp_bridge_driver sgi_tioca_driver = {
265 .free_by_type = agp_generic_free_by_type, 265 .free_by_type = agp_generic_free_by_type,
266 .agp_alloc_page = sgi_tioca_alloc_page, 266 .agp_alloc_page = sgi_tioca_alloc_page,
267 .agp_destroy_page = agp_generic_destroy_page, 267 .agp_destroy_page = agp_generic_destroy_page,
268 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
268 .cant_use_aperture = 1, 269 .cant_use_aperture = 1,
269 .needs_scratch_page = 0, 270 .needs_scratch_page = 0,
270 .num_aperture_sizes = 1, 271 .num_aperture_sizes = 1,
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 4f2d7d99902f..9f5ae7714f85 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -444,6 +444,7 @@ static struct agp_bridge_driver sworks_driver = {
444 .free_by_type = agp_generic_free_by_type, 444 .free_by_type = agp_generic_free_by_type,
445 .agp_alloc_page = agp_generic_alloc_page, 445 .agp_alloc_page = agp_generic_alloc_page,
446 .agp_destroy_page = agp_generic_destroy_page, 446 .agp_destroy_page = agp_generic_destroy_page,
447 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
447}; 448};
448 449
449static int __devinit agp_serverworks_probe(struct pci_dev *pdev, 450static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index dffc19382f7e..6c45702e542c 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -510,6 +510,7 @@ struct agp_bridge_driver uninorth_agp_driver = {
510 .free_by_type = agp_generic_free_by_type, 510 .free_by_type = agp_generic_free_by_type,
511 .agp_alloc_page = agp_generic_alloc_page, 511 .agp_alloc_page = agp_generic_alloc_page,
512 .agp_destroy_page = agp_generic_destroy_page, 512 .agp_destroy_page = agp_generic_destroy_page,
513 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
513 .cant_use_aperture = 1, 514 .cant_use_aperture = 1,
514}; 515};
515 516
@@ -534,6 +535,7 @@ struct agp_bridge_driver u3_agp_driver = {
534 .free_by_type = agp_generic_free_by_type, 535 .free_by_type = agp_generic_free_by_type,
535 .agp_alloc_page = agp_generic_alloc_page, 536 .agp_alloc_page = agp_generic_alloc_page,
536 .agp_destroy_page = agp_generic_destroy_page, 537 .agp_destroy_page = agp_generic_destroy_page,
538 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
537 .cant_use_aperture = 1, 539 .cant_use_aperture = 1,
538 .needs_scratch_page = 1, 540 .needs_scratch_page = 1,
539}; 541};
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 2ded7a280d7f..2e7c04370cd9 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -191,6 +191,7 @@ static struct agp_bridge_driver via_agp3_driver = {
191 .free_by_type = agp_generic_free_by_type, 191 .free_by_type = agp_generic_free_by_type,
192 .agp_alloc_page = agp_generic_alloc_page, 192 .agp_alloc_page = agp_generic_alloc_page,
193 .agp_destroy_page = agp_generic_destroy_page, 193 .agp_destroy_page = agp_generic_destroy_page,
194 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
194}; 195};
195 196
196static struct agp_bridge_driver via_driver = { 197static struct agp_bridge_driver via_driver = {
@@ -214,6 +215,7 @@ static struct agp_bridge_driver via_driver = {
214 .free_by_type = agp_generic_free_by_type, 215 .free_by_type = agp_generic_free_by_type,
215 .agp_alloc_page = agp_generic_alloc_page, 216 .agp_alloc_page = agp_generic_alloc_page,
216 .agp_destroy_page = agp_generic_destroy_page, 217 .agp_destroy_page = agp_generic_destroy_page,
218 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
217}; 219};
218 220
219static struct agp_device_ids via_agp_device_ids[] __devinitdata = 221static struct agp_device_ids via_agp_device_ids[] __devinitdata =
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index a5c8bb5d80ba..abc521cfb084 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -87,10 +87,15 @@ struct agp_memory {
87 u32 physical; 87 u32 physical;
88 u8 is_bound; 88 u8 is_bound;
89 u8 is_flushed; 89 u8 is_flushed;
90 u8 vmalloc_flag;
90}; 91};
91 92
92#define AGP_NORMAL_MEMORY 0 93#define AGP_NORMAL_MEMORY 0
93 94
95#define AGP_USER_TYPES (1 << 16)
96#define AGP_USER_MEMORY (AGP_USER_TYPES)
97#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1)
98
94extern struct agp_bridge_data *agp_bridge; 99extern struct agp_bridge_data *agp_bridge;
95extern struct list_head agp_bridges; 100extern struct list_head agp_bridges;
96 101