aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:17:04 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:17:04 -0500
commitf8abea8f8c24ecdad6d6861bffb912f23f2741cd (patch)
tree7d5af9c3d92b3afd0d585aabd6537db36c8095ae
parentef29498655b18d2bfd69048e20835d19333981ab (diff)
parent1c14cfbbe7a9f2240c73f420c3c6336fc521cd64 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
* master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart: [AGPGART] allow drm populated agp memory types cleanups [AGPGART] intel-agp: Use ARRAY_SIZE macro when appropriate [AGPGART] Add agp-type-to-mask-type method missing from some drivers. [AGPGART] Don't try to remap i810 registers on resume. [AGPGART] Allow drm-populated agp memory types [AGPGART] compat ioctl
-rw-r--r--drivers/char/agp/Makefile1
-rw-r--r--drivers/char/agp/agp.h12
-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/compat_ioctl.c282
-rw-r--r--drivers/char/agp/compat_ioctl.h105
-rw-r--r--drivers/char/agp/efficeon-agp.c1
-rw-r--r--drivers/char/agp/frontend.c34
-rw-r--r--drivers/char/agp/generic.c125
-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.c202
-rw-r--r--drivers/char/agp/nvidia-agp.c1
-rw-r--r--drivers/char/agp/parisc-agp.c1
-rw-r--r--drivers/char/agp/sgi-agp.c1
-rw-r--r--drivers/char/agp/sis-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
24 files changed, 707 insertions, 98 deletions
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 3e581603d0a8..a0d04a23dacd 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -1,6 +1,7 @@
1agpgart-y := backend.o frontend.o generic.o isoch.o 1agpgart-y := backend.o frontend.o generic.o isoch.o
2 2
3obj-$(CONFIG_AGP) += agpgart.o 3obj-$(CONFIG_AGP) += agpgart.o
4obj-$(CONFIG_COMPAT) += compat_ioctl.o
4obj-$(CONFIG_AGP_ALI) += ali-agp.o 5obj-$(CONFIG_AGP_ALI) += ali-agp.o
5obj-$(CONFIG_AGP_ATI) += ati-agp.o 6obj-$(CONFIG_AGP_ATI) += ati-agp.o
6obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o 7obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 1d59e2a5b9aa..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);
@@ -288,6 +298,8 @@ extern struct aper_size_info_16 agp3_generic_sizes[];
288extern int agp_off; 298extern int agp_off;
289extern int agp_try_unsupported_boot; 299extern int agp_try_unsupported_boot;
290 300
301long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
302
291/* Chipset independant registers (from AGP Spec) */ 303/* Chipset independant registers (from AGP Spec) */
292#define AGP_APBASE 0x10 304#define AGP_APBASE 0x10
293 305
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/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
new file mode 100644
index 000000000000..fcb4b1bf0d4e
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.c
@@ -0,0 +1,282 @@
1/*
2 * AGPGART driver frontend compatibility ioctls
3 * Copyright (C) 2004 Silicon Graphics, Inc.
4 * Copyright (C) 2002-2003 Dave Jones
5 * Copyright (C) 1999 Jeff Hartmann
6 * Copyright (C) 1999 Precision Insight, Inc.
7 * Copyright (C) 1999 Xi Graphics, Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 */
28
29#include <linux/kernel.h>
30#include <linux/pci.h>
31#include <linux/agpgart.h>
32#include <asm/uaccess.h>
33#include "agp.h"
34#include "compat_ioctl.h"
35
36static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
37{
38 struct agp_info32 userinfo;
39 struct agp_kern_info kerninfo;
40
41 agp_copy_info(agp_bridge, &kerninfo);
42
43 userinfo.version.major = kerninfo.version.major;
44 userinfo.version.minor = kerninfo.version.minor;
45 userinfo.bridge_id = kerninfo.device->vendor |
46 (kerninfo.device->device << 16);
47 userinfo.agp_mode = kerninfo.mode;
48 userinfo.aper_base = (compat_long_t)kerninfo.aper_base;
49 userinfo.aper_size = kerninfo.aper_size;
50 userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
51 userinfo.pg_used = kerninfo.current_memory;
52
53 if (copy_to_user(arg, &userinfo, sizeof(userinfo)))
54 return -EFAULT;
55
56 return 0;
57}
58
59static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
60{
61 struct agp_region32 ureserve;
62 struct agp_region kreserve;
63 struct agp_client *client;
64 struct agp_file_private *client_priv;
65
66 DBG("");
67 if (copy_from_user(&ureserve, arg, sizeof(ureserve)))
68 return -EFAULT;
69
70 if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32))
71 return -EFAULT;
72
73 kreserve.pid = ureserve.pid;
74 kreserve.seg_count = ureserve.seg_count;
75
76 client = agp_find_client_by_pid(kreserve.pid);
77
78 if (kreserve.seg_count == 0) {
79 /* remove a client */
80 client_priv = agp_find_private(kreserve.pid);
81
82 if (client_priv != NULL) {
83 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
84 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
85 }
86 if (client == NULL) {
87 /* client is already removed */
88 return 0;
89 }
90 return agp_remove_client(kreserve.pid);
91 } else {
92 struct agp_segment32 *usegment;
93 struct agp_segment *ksegment;
94 int seg;
95
96 if (ureserve.seg_count >= 16384)
97 return -EINVAL;
98
99 usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
100 if (!usegment)
101 return -ENOMEM;
102
103 ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
104 if (!ksegment) {
105 kfree(usegment);
106 return -ENOMEM;
107 }
108
109 if (copy_from_user(usegment, (void __user *) ureserve.seg_list,
110 sizeof(*usegment) * ureserve.seg_count)) {
111 kfree(usegment);
112 kfree(ksegment);
113 return -EFAULT;
114 }
115
116 for (seg = 0; seg < ureserve.seg_count; seg++) {
117 ksegment[seg].pg_start = usegment[seg].pg_start;
118 ksegment[seg].pg_count = usegment[seg].pg_count;
119 ksegment[seg].prot = usegment[seg].prot;
120 }
121
122 kfree(usegment);
123 kreserve.seg_list = ksegment;
124
125 if (client == NULL) {
126 /* Create the client and add the segment */
127 client = agp_create_client(kreserve.pid);
128
129 if (client == NULL) {
130 kfree(ksegment);
131 return -ENOMEM;
132 }
133 client_priv = agp_find_private(kreserve.pid);
134
135 if (client_priv != NULL) {
136 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
137 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
138 }
139 }
140 return agp_create_segment(client, &kreserve);
141 }
142 /* Will never really happen */
143 return -EINVAL;
144}
145
146static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
147{
148 struct agp_memory *memory;
149 struct agp_allocate32 alloc;
150
151 DBG("");
152 if (copy_from_user(&alloc, arg, sizeof(alloc)))
153 return -EFAULT;
154
155 memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
156
157 if (memory == NULL)
158 return -ENOMEM;
159
160 alloc.key = memory->key;
161 alloc.physical = memory->physical;
162
163 if (copy_to_user(arg, &alloc, sizeof(alloc))) {
164 agp_free_memory_wrap(memory);
165 return -EFAULT;
166 }
167 return 0;
168}
169
170static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
171{
172 struct agp_bind32 bind_info;
173 struct agp_memory *memory;
174
175 DBG("");
176 if (copy_from_user(&bind_info, arg, sizeof(bind_info)))
177 return -EFAULT;
178
179 memory = agp_find_mem_by_key(bind_info.key);
180
181 if (memory == NULL)
182 return -EINVAL;
183
184 return agp_bind_memory(memory, bind_info.pg_start);
185}
186
187static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
188{
189 struct agp_memory *memory;
190 struct agp_unbind32 unbind;
191
192 DBG("");
193 if (copy_from_user(&unbind, arg, sizeof(unbind)))
194 return -EFAULT;
195
196 memory = agp_find_mem_by_key(unbind.key);
197
198 if (memory == NULL)
199 return -EINVAL;
200
201 return agp_unbind_memory(memory);
202}
203
204long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
205{
206 struct agp_file_private *curr_priv = file->private_data;
207 int ret_val = -ENOTTY;
208
209 mutex_lock(&(agp_fe.agp_mutex));
210
211 if ((agp_fe.current_controller == NULL) &&
212 (cmd != AGPIOC_ACQUIRE32)) {
213 ret_val = -EINVAL;
214 goto ioctl_out;
215 }
216 if ((agp_fe.backend_acquired != TRUE) &&
217 (cmd != AGPIOC_ACQUIRE32)) {
218 ret_val = -EBUSY;
219 goto ioctl_out;
220 }
221 if (cmd != AGPIOC_ACQUIRE32) {
222 if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
223 ret_val = -EPERM;
224 goto ioctl_out;
225 }
226 /* Use the original pid of the controller,
227 * in case it's threaded */
228
229 if (agp_fe.current_controller->pid != curr_priv->my_pid) {
230 ret_val = -EBUSY;
231 goto ioctl_out;
232 }
233 }
234
235 switch (cmd) {
236 case AGPIOC_INFO32:
237 ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg);
238 break;
239
240 case AGPIOC_ACQUIRE32:
241 ret_val = agpioc_acquire_wrap(curr_priv);
242 break;
243
244 case AGPIOC_RELEASE32:
245 ret_val = agpioc_release_wrap(curr_priv);
246 break;
247
248 case AGPIOC_SETUP32:
249 ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
250 break;
251
252 case AGPIOC_RESERVE32:
253 ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg);
254 break;
255
256 case AGPIOC_PROTECT32:
257 ret_val = agpioc_protect_wrap(curr_priv);
258 break;
259
260 case AGPIOC_ALLOCATE32:
261 ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg);
262 break;
263
264 case AGPIOC_DEALLOCATE32:
265 ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
266 break;
267
268 case AGPIOC_BIND32:
269 ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg);
270 break;
271
272 case AGPIOC_UNBIND32:
273 ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg);
274 break;
275 }
276
277ioctl_out:
278 DBG("ioctl returns %d\n", ret_val);
279 mutex_unlock(&(agp_fe.agp_mutex));
280 return ret_val;
281}
282
diff --git a/drivers/char/agp/compat_ioctl.h b/drivers/char/agp/compat_ioctl.h
new file mode 100644
index 000000000000..71939d637236
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.h
@@ -0,0 +1,105 @@
1/*
2 * Copyright (C) 1999 Jeff Hartmann
3 * Copyright (C) 1999 Precision Insight, Inc.
4 * Copyright (C) 1999 Xi Graphics, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26#ifndef _AGP_COMPAT_IOCTL_H
27#define _AGP_COMPAT_IOCTL_H
28
29#include <linux/compat.h>
30#include <linux/agpgart.h>
31
32#define AGPIOC_INFO32 _IOR (AGPIOC_BASE, 0, compat_uptr_t)
33#define AGPIOC_ACQUIRE32 _IO (AGPIOC_BASE, 1)
34#define AGPIOC_RELEASE32 _IO (AGPIOC_BASE, 2)
35#define AGPIOC_SETUP32 _IOW (AGPIOC_BASE, 3, compat_uptr_t)
36#define AGPIOC_RESERVE32 _IOW (AGPIOC_BASE, 4, compat_uptr_t)
37#define AGPIOC_PROTECT32 _IOW (AGPIOC_BASE, 5, compat_uptr_t)
38#define AGPIOC_ALLOCATE32 _IOWR(AGPIOC_BASE, 6, compat_uptr_t)
39#define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t)
40#define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t)
41#define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t)
42
43struct agp_info32 {
44 struct agp_version version; /* version of the driver */
45 u32 bridge_id; /* bridge vendor/device */
46 u32 agp_mode; /* mode info of bridge */
47 compat_long_t aper_base; /* base of aperture */
48 compat_size_t aper_size; /* size of aperture */
49 compat_size_t pg_total; /* max pages (swap + system) */
50 compat_size_t pg_system; /* max pages (system) */
51 compat_size_t pg_used; /* current pages used */
52};
53
54/*
55 * The "prot" down below needs still a "sleep" flag somehow ...
56 */
57struct agp_segment32 {
58 compat_off_t pg_start; /* starting page to populate */
59 compat_size_t pg_count; /* number of pages */
60 compat_int_t prot; /* prot flags for mmap */
61};
62
63struct agp_region32 {
64 compat_pid_t pid; /* pid of process */
65 compat_size_t seg_count; /* number of segments */
66 struct agp_segment32 *seg_list;
67};
68
69struct agp_allocate32 {
70 compat_int_t key; /* tag of allocation */
71 compat_size_t pg_count; /* number of pages */
72 u32 type; /* 0 == normal, other devspec */
73 u32 physical; /* device specific (some devices
74 * need a phys address of the
75 * actual page behind the gatt
76 * table) */
77};
78
79struct agp_bind32 {
80 compat_int_t key; /* tag of allocation */
81 compat_off_t pg_start; /* starting page to populate */
82};
83
84struct agp_unbind32 {
85 compat_int_t key; /* tag of allocation */
86 u32 priority; /* priority for paging out */
87};
88
89extern struct agp_front_data agp_fe;
90
91int agpioc_acquire_wrap(struct agp_file_private *priv);
92int agpioc_release_wrap(struct agp_file_private *priv);
93int agpioc_protect_wrap(struct agp_file_private *priv);
94int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg);
95int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg);
96struct agp_file_private *agp_find_private(pid_t pid);
97struct agp_client *agp_create_client(pid_t id);
98int agp_remove_client(pid_t id);
99int agp_create_segment(struct agp_client *client, struct agp_region *region);
100void agp_free_memory_wrap(struct agp_memory *memory);
101struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
102struct agp_memory *agp_find_mem_by_key(int key);
103struct agp_client *agp_find_client_by_pid(pid_t id);
104
105#endif /* _AGP_COMPAT_H */
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 0f2ed2aa2d81..679d7f972439 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -41,9 +41,9 @@
41#include <asm/pgtable.h> 41#include <asm/pgtable.h>
42#include "agp.h" 42#include "agp.h"
43 43
44static struct agp_front_data agp_fe; 44struct agp_front_data agp_fe;
45 45
46static struct agp_memory *agp_find_mem_by_key(int key) 46struct agp_memory *agp_find_mem_by_key(int key)
47{ 47{
48 struct agp_memory *curr; 48 struct agp_memory *curr;
49 49
@@ -159,7 +159,7 @@ static pgprot_t agp_convert_mmap_flags(int prot)
159 return vm_get_page_prot(prot_bits); 159 return vm_get_page_prot(prot_bits);
160} 160}
161 161
162static int agp_create_segment(struct agp_client *client, struct agp_region *region) 162int agp_create_segment(struct agp_client *client, struct agp_region *region)
163{ 163{
164 struct agp_segment_priv **ret_seg; 164 struct agp_segment_priv **ret_seg;
165 struct agp_segment_priv *seg; 165 struct agp_segment_priv *seg;
@@ -211,7 +211,7 @@ static void agp_insert_into_pool(struct agp_memory * temp)
211 211
212/* File private list routines */ 212/* File private list routines */
213 213
214static struct agp_file_private *agp_find_private(pid_t pid) 214struct agp_file_private *agp_find_private(pid_t pid)
215{ 215{
216 struct agp_file_private *curr; 216 struct agp_file_private *curr;
217 217
@@ -266,13 +266,13 @@ static void agp_remove_file_private(struct agp_file_private * priv)
266 * Wrappers for agp_free_memory & agp_allocate_memory 266 * Wrappers for agp_free_memory & agp_allocate_memory
267 * These make sure that internal lists are kept updated. 267 * These make sure that internal lists are kept updated.
268 */ 268 */
269static void agp_free_memory_wrap(struct agp_memory *memory) 269void agp_free_memory_wrap(struct agp_memory *memory)
270{ 270{
271 agp_remove_from_pool(memory); 271 agp_remove_from_pool(memory);
272 agp_free_memory(memory); 272 agp_free_memory(memory);
273} 273}
274 274
275static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 275struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
276{ 276{
277 struct agp_memory *memory; 277 struct agp_memory *memory;
278 278
@@ -484,7 +484,7 @@ static struct agp_controller *agp_find_controller_for_client(pid_t id)
484 return NULL; 484 return NULL;
485} 485}
486 486
487static struct agp_client *agp_find_client_by_pid(pid_t id) 487struct agp_client *agp_find_client_by_pid(pid_t id)
488{ 488{
489 struct agp_client *temp; 489 struct agp_client *temp;
490 490
@@ -509,7 +509,7 @@ static void agp_insert_client(struct agp_client *client)
509 agp_fe.current_controller->num_clients++; 509 agp_fe.current_controller->num_clients++;
510} 510}
511 511
512static struct agp_client *agp_create_client(pid_t id) 512struct agp_client *agp_create_client(pid_t id)
513{ 513{
514 struct agp_client *new_client; 514 struct agp_client *new_client;
515 515
@@ -522,7 +522,7 @@ static struct agp_client *agp_create_client(pid_t id)
522 return new_client; 522 return new_client;
523} 523}
524 524
525static int agp_remove_client(pid_t id) 525int agp_remove_client(pid_t id)
526{ 526{
527 struct agp_client *client; 527 struct agp_client *client;
528 struct agp_client *prev_client; 528 struct agp_client *prev_client;
@@ -746,7 +746,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
746 return 0; 746 return 0;
747} 747}
748 748
749static int agpioc_acquire_wrap(struct agp_file_private *priv) 749int agpioc_acquire_wrap(struct agp_file_private *priv)
750{ 750{
751 struct agp_controller *controller; 751 struct agp_controller *controller;
752 752
@@ -789,14 +789,14 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
789 return 0; 789 return 0;
790} 790}
791 791
792static int agpioc_release_wrap(struct agp_file_private *priv) 792int agpioc_release_wrap(struct agp_file_private *priv)
793{ 793{
794 DBG(""); 794 DBG("");
795 agp_controller_release_current(agp_fe.current_controller, priv); 795 agp_controller_release_current(agp_fe.current_controller, priv);
796 return 0; 796 return 0;
797} 797}
798 798
799static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 799int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
800{ 800{
801 struct agp_setup mode; 801 struct agp_setup mode;
802 802
@@ -876,7 +876,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
876 return -EINVAL; 876 return -EINVAL;
877} 877}
878 878
879static int agpioc_protect_wrap(struct agp_file_private *priv) 879int agpioc_protect_wrap(struct agp_file_private *priv)
880{ 880{
881 DBG(""); 881 DBG("");
882 /* This function is not currently implemented */ 882 /* This function is not currently implemented */
@@ -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)
@@ -907,7 +910,7 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
907 return 0; 910 return 0;
908} 911}
909 912
910static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 913int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
911{ 914{
912 struct agp_memory *memory; 915 struct agp_memory *memory;
913 916
@@ -1043,6 +1046,9 @@ static const struct file_operations agp_fops =
1043 .read = agp_read, 1046 .read = agp_read,
1044 .write = agp_write, 1047 .write = agp_write,
1045 .ioctl = agp_ioctl, 1048 .ioctl = agp_ioctl,
1049#ifdef CONFIG_COMPAT
1050 .compat_ioctl = compat_agp_ioctl,
1051#endif
1046 .mmap = agp_mmap, 1052 .mmap = agp_mmap,
1047 .open = agp_open, 1053 .open = agp_open,
1048 .release = agp_release, 1054 .release = agp_release,
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 3491d6f84bc6..7923337c3d26 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -101,6 +101,63 @@ 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 if (mem->memory == NULL) {
118 mem->memory = vmalloc(size);
119 mem->vmalloc_flag = 1;
120 }
121}
122EXPORT_SYMBOL(agp_alloc_page_array);
123
124void agp_free_page_array(struct agp_memory *mem)
125{
126 if (mem->vmalloc_flag) {
127 vfree(mem->memory);
128 } else {
129 kfree(mem->memory);
130 }
131}
132EXPORT_SYMBOL(agp_free_page_array);
133
134
135static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
136{
137 struct agp_memory *new;
138 unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
139
140 new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
141 if (new == NULL)
142 return NULL;
143
144 new->key = agp_get_key();
145
146 if (new->key < 0) {
147 kfree(new);
148 return NULL;
149 }
150
151 agp_alloc_page_array(alloc_size, new);
152
153 if (new->memory == NULL) {
154 agp_free_key(new->key);
155 kfree(new);
156 return NULL;
157 }
158 new->num_scratch_pages = 0;
159 return new;
160}
104 161
105struct agp_memory *agp_create_memory(int scratch_pages) 162struct agp_memory *agp_create_memory(int scratch_pages)
106{ 163{
@@ -116,7 +173,8 @@ struct agp_memory *agp_create_memory(int scratch_pages)
116 kfree(new); 173 kfree(new);
117 return NULL; 174 return NULL;
118 } 175 }
119 new->memory = vmalloc(PAGE_SIZE * scratch_pages); 176
177 agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
120 178
121 if (new->memory == NULL) { 179 if (new->memory == NULL) {
122 agp_free_key(new->key); 180 agp_free_key(new->key);
@@ -124,6 +182,7 @@ struct agp_memory *agp_create_memory(int scratch_pages)
124 return NULL; 182 return NULL;
125 } 183 }
126 new->num_scratch_pages = scratch_pages; 184 new->num_scratch_pages = scratch_pages;
185 new->type = AGP_NORMAL_MEMORY;
127 return new; 186 return new;
128} 187}
129EXPORT_SYMBOL(agp_create_memory); 188EXPORT_SYMBOL(agp_create_memory);
@@ -146,6 +205,11 @@ void agp_free_memory(struct agp_memory *curr)
146 if (curr->is_bound == TRUE) 205 if (curr->is_bound == TRUE)
147 agp_unbind_memory(curr); 206 agp_unbind_memory(curr);
148 207
208 if (curr->type >= AGP_USER_TYPES) {
209 agp_generic_free_by_type(curr);
210 return;
211 }
212
149 if (curr->type != 0) { 213 if (curr->type != 0) {
150 curr->bridge->driver->free_by_type(curr); 214 curr->bridge->driver->free_by_type(curr);
151 return; 215 return;
@@ -157,7 +221,7 @@ void agp_free_memory(struct agp_memory *curr)
157 flush_agp_mappings(); 221 flush_agp_mappings();
158 } 222 }
159 agp_free_key(curr->key); 223 agp_free_key(curr->key);
160 vfree(curr->memory); 224 agp_free_page_array(curr);
161 kfree(curr); 225 kfree(curr);
162} 226}
163EXPORT_SYMBOL(agp_free_memory); 227EXPORT_SYMBOL(agp_free_memory);
@@ -188,6 +252,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) 252 if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
189 return NULL; 253 return NULL;
190 254
255 if (type >= AGP_USER_TYPES) {
256 new = agp_generic_alloc_user(page_count, type);
257 if (new)
258 new->bridge = bridge;
259 return new;
260 }
261
191 if (type != 0) { 262 if (type != 0) {
192 new = bridge->driver->alloc_by_type(page_count, type); 263 new = bridge->driver->alloc_by_type(page_count, type);
193 if (new) 264 if (new)
@@ -960,6 +1031,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
960 off_t j; 1031 off_t j;
961 void *temp; 1032 void *temp;
962 struct agp_bridge_data *bridge; 1033 struct agp_bridge_data *bridge;
1034 int mask_type;
963 1035
964 bridge = mem->bridge; 1036 bridge = mem->bridge;
965 if (!bridge) 1037 if (!bridge)
@@ -995,7 +1067,11 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
995 num_entries -= agp_memory_reserved/PAGE_SIZE; 1067 num_entries -= agp_memory_reserved/PAGE_SIZE;
996 if (num_entries < 0) num_entries = 0; 1068 if (num_entries < 0) num_entries = 0;
997 1069
998 if (type != 0 || mem->type != 0) { 1070 if (type != mem->type)
1071 return -EINVAL;
1072
1073 mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
1074 if (mask_type != 0) {
999 /* The generic routines know nothing of memory types */ 1075 /* The generic routines know nothing of memory types */
1000 return -EINVAL; 1076 return -EINVAL;
1001 } 1077 }
@@ -1018,7 +1094,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
1018 } 1094 }
1019 1095
1020 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1096 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); 1097 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
1098 bridge->gatt_table+j);
1022 } 1099 }
1023 readl(bridge->gatt_table+j-1); /* PCI Posting. */ 1100 readl(bridge->gatt_table+j-1); /* PCI Posting. */
1024 1101
@@ -1032,6 +1109,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1032{ 1109{
1033 size_t i; 1110 size_t i;
1034 struct agp_bridge_data *bridge; 1111 struct agp_bridge_data *bridge;
1112 int mask_type;
1035 1113
1036 bridge = mem->bridge; 1114 bridge = mem->bridge;
1037 if (!bridge) 1115 if (!bridge)
@@ -1040,7 +1118,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1040 if (mem->page_count == 0) 1118 if (mem->page_count == 0)
1041 return 0; 1119 return 0;
1042 1120
1043 if (type != 0 || mem->type != 0) { 1121 if (type != mem->type)
1122 return -EINVAL;
1123
1124 mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
1125 if (mask_type != 0) {
1044 /* The generic routines know nothing of memory types */ 1126 /* The generic routines know nothing of memory types */
1045 return -EINVAL; 1127 return -EINVAL;
1046 } 1128 }
@@ -1056,22 +1138,40 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1056} 1138}
1057EXPORT_SYMBOL(agp_generic_remove_memory); 1139EXPORT_SYMBOL(agp_generic_remove_memory);
1058 1140
1059
1060struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) 1141struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type)
1061{ 1142{
1062 return NULL; 1143 return NULL;
1063} 1144}
1064EXPORT_SYMBOL(agp_generic_alloc_by_type); 1145EXPORT_SYMBOL(agp_generic_alloc_by_type);
1065 1146
1066
1067void agp_generic_free_by_type(struct agp_memory *curr) 1147void agp_generic_free_by_type(struct agp_memory *curr)
1068{ 1148{
1069 vfree(curr->memory); 1149 agp_free_page_array(curr);
1070 agp_free_key(curr->key); 1150 agp_free_key(curr->key);
1071 kfree(curr); 1151 kfree(curr);
1072} 1152}
1073EXPORT_SYMBOL(agp_generic_free_by_type); 1153EXPORT_SYMBOL(agp_generic_free_by_type);
1074 1154
1155struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
1156{
1157 struct agp_memory *new;
1158 int i;
1159 int pages;
1160
1161 pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
1162 new = agp_create_user_memory(page_count);
1163 if (new == NULL)
1164 return NULL;
1165
1166 for (i = 0; i < page_count; i++)
1167 new->memory[i] = 0;
1168 new->page_count = 0;
1169 new->type = type;
1170 new->num_scratch_pages = pages;
1171
1172 return new;
1173}
1174EXPORT_SYMBOL(agp_generic_alloc_user);
1075 1175
1076/* 1176/*
1077 * Basic Page Allocation Routines - 1177 * Basic Page Allocation Routines -
@@ -1165,6 +1265,15 @@ unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
1165} 1265}
1166EXPORT_SYMBOL(agp_generic_mask_memory); 1266EXPORT_SYMBOL(agp_generic_mask_memory);
1167 1267
1268int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
1269 int type)
1270{
1271 if (type >= AGP_USER_TYPES)
1272 return 0;
1273 return type;
1274}
1275EXPORT_SYMBOL(agp_generic_type_to_mask_type);
1276
1168/* 1277/*
1169 * These functions are implemented according to the AGPv3 spec, 1278 * These functions are implemented according to the AGPv3 spec,
1170 * which covers implementation details that had previously been 1279 * 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..06b0bb6d982f 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -5,6 +5,7 @@
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/pci.h> 6#include <linux/pci.h>
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/kernel.h>
8#include <linux/pagemap.h> 9#include <linux/pagemap.h>
9#include <linux/agp_backend.h> 10#include <linux/agp_backend.h>
10#include "agp.h" 11#include "agp.h"
@@ -24,6 +25,9 @@
24 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB) 25 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
25 26
26 27
28extern int agp_memory_reserved;
29
30
27/* Intel 815 register */ 31/* Intel 815 register */
28#define INTEL_815_APCONT 0x51 32#define INTEL_815_APCONT 0x51
29#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF 33#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
@@ -68,12 +72,15 @@ static struct aper_size_info_fixed intel_i810_sizes[] =
68 72
69#define AGP_DCACHE_MEMORY 1 73#define AGP_DCACHE_MEMORY 1
70#define AGP_PHYS_MEMORY 2 74#define AGP_PHYS_MEMORY 2
75#define INTEL_AGP_CACHED_MEMORY 3
71 76
72static struct gatt_mask intel_i810_masks[] = 77static struct gatt_mask intel_i810_masks[] =
73{ 78{
74 {.mask = I810_PTE_VALID, .type = 0}, 79 {.mask = I810_PTE_VALID, .type = 0},
75 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, 80 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
76 {.mask = I810_PTE_VALID, .type = 0} 81 {.mask = I810_PTE_VALID, .type = 0},
82 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
83 .type = INTEL_AGP_CACHED_MEMORY}
77}; 84};
78 85
79static struct _intel_i810_private { 86static struct _intel_i810_private {
@@ -117,13 +124,15 @@ static int intel_i810_configure(void)
117 124
118 current_size = A_SIZE_FIX(agp_bridge->current_size); 125 current_size = A_SIZE_FIX(agp_bridge->current_size);
119 126
120 pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
121 temp &= 0xfff80000;
122
123 intel_i810_private.registers = ioremap(temp, 128 * 4096);
124 if (!intel_i810_private.registers) { 127 if (!intel_i810_private.registers) {
125 printk(KERN_ERR PFX "Unable to remap memory.\n"); 128 pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
126 return -ENOMEM; 129 temp &= 0xfff80000;
130
131 intel_i810_private.registers = ioremap(temp, 128 * 4096);
132 if (!intel_i810_private.registers) {
133 printk(KERN_ERR PFX "Unable to remap memory.\n");
134 return -ENOMEM;
135 }
127 } 136 }
128 137
129 if ((readl(intel_i810_private.registers+I810_DRAM_CTL) 138 if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
@@ -201,62 +210,79 @@ static void i8xx_destroy_pages(void *addr)
201 atomic_dec(&agp_bridge->current_memory_agp); 210 atomic_dec(&agp_bridge->current_memory_agp);
202} 211}
203 212
213static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
214 int type)
215{
216 if (type < AGP_USER_TYPES)
217 return type;
218 else if (type == AGP_USER_CACHED_MEMORY)
219 return INTEL_AGP_CACHED_MEMORY;
220 else
221 return 0;
222}
223
204static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, 224static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
205 int type) 225 int type)
206{ 226{
207 int i, j, num_entries; 227 int i, j, num_entries;
208 void *temp; 228 void *temp;
229 int ret = -EINVAL;
230 int mask_type;
209 231
210 if (mem->page_count == 0) 232 if (mem->page_count == 0)
211 return 0; 233 goto out;
212 234
213 temp = agp_bridge->current_size; 235 temp = agp_bridge->current_size;
214 num_entries = A_SIZE_FIX(temp)->num_entries; 236 num_entries = A_SIZE_FIX(temp)->num_entries;
215 237
216 if ((pg_start + mem->page_count) > num_entries) 238 if ((pg_start + mem->page_count) > num_entries)
217 return -EINVAL; 239 goto out_err;
218 240
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 241
224 if (type != 0 || mem->type != 0) { 242 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
225 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { 243 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
226 /* special insert */ 244 ret = -EBUSY;
227 if (!mem->is_flushed) { 245 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 } 246 }
240 if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
241 goto insert;
242 return -EINVAL;
243 } 247 }
244 248
245insert: 249 if (type != mem->type)
246 if (!mem->is_flushed) { 250 goto out_err;
247 global_cache_flush();
248 mem->is_flushed = TRUE;
249 }
250 251
251 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 252 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
252 writel(agp_bridge->driver->mask_memory(agp_bridge, 253
253 mem->memory[i], mem->type), 254 switch (mask_type) {
254 intel_i810_private.registers+I810_PTE_BASE+(j*4)); 255 case AGP_DCACHE_MEMORY:
256 if (!mem->is_flushed)
257 global_cache_flush();
258 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
259 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
260 intel_i810_private.registers+I810_PTE_BASE+(i*4));
261 }
262 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
263 break;
264 case AGP_PHYS_MEMORY:
265 case AGP_NORMAL_MEMORY:
266 if (!mem->is_flushed)
267 global_cache_flush();
268 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
269 writel(agp_bridge->driver->mask_memory(agp_bridge,
270 mem->memory[i],
271 mask_type),
272 intel_i810_private.registers+I810_PTE_BASE+(j*4));
273 }
274 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
275 break;
276 default:
277 goto out_err;
255 } 278 }
256 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
257 279
258 agp_bridge->driver->tlb_flush(mem); 280 agp_bridge->driver->tlb_flush(mem);
259 return 0; 281out:
282 ret = 0;
283out_err:
284 mem->is_flushed = 1;
285 return ret;
260} 286}
261 287
262static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, 288static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
@@ -337,12 +363,11 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
337 new->type = AGP_DCACHE_MEMORY; 363 new->type = AGP_DCACHE_MEMORY;
338 new->page_count = pg_count; 364 new->page_count = pg_count;
339 new->num_scratch_pages = 0; 365 new->num_scratch_pages = 0;
340 vfree(new->memory); 366 agp_free_page_array(new);
341 return new; 367 return new;
342 } 368 }
343 if (type == AGP_PHYS_MEMORY) 369 if (type == AGP_PHYS_MEMORY)
344 return alloc_agpphysmem_i8xx(pg_count, type); 370 return alloc_agpphysmem_i8xx(pg_count, type);
345
346 return NULL; 371 return NULL;
347} 372}
348 373
@@ -357,7 +382,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
357 gart_to_virt(curr->memory[0])); 382 gart_to_virt(curr->memory[0]));
358 global_flush_tlb(); 383 global_flush_tlb();
359 } 384 }
360 vfree(curr->memory); 385 agp_free_page_array(curr);
361 } 386 }
362 kfree(curr); 387 kfree(curr);
363} 388}
@@ -619,9 +644,11 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
619{ 644{
620 int i,j,num_entries; 645 int i,j,num_entries;
621 void *temp; 646 void *temp;
647 int ret = -EINVAL;
648 int mask_type;
622 649
623 if (mem->page_count == 0) 650 if (mem->page_count == 0)
624 return 0; 651 goto out;
625 652
626 temp = agp_bridge->current_size; 653 temp = agp_bridge->current_size;
627 num_entries = A_SIZE_FIX(temp)->num_entries; 654 num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -631,34 +658,41 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
631 pg_start,intel_i830_private.gtt_entries); 658 pg_start,intel_i830_private.gtt_entries);
632 659
633 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); 660 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
634 return -EINVAL; 661 goto out_err;
635 } 662 }
636 663
637 if ((pg_start + mem->page_count) > num_entries) 664 if ((pg_start + mem->page_count) > num_entries)
638 return -EINVAL; 665 goto out_err;
639 666
640 /* The i830 can't check the GTT for entries since its read only, 667 /* The i830 can't check the GTT for entries since its read only,
641 * depend on the caller to make the correct offset decisions. 668 * depend on the caller to make the correct offset decisions.
642 */ 669 */
643 670
644 if ((type != 0 && type != AGP_PHYS_MEMORY) || 671 if (type != mem->type)
645 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 672 goto out_err;
646 return -EINVAL; 673
674 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
647 675
648 if (!mem->is_flushed) { 676 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
677 mask_type != INTEL_AGP_CACHED_MEMORY)
678 goto out_err;
679
680 if (!mem->is_flushed)
649 global_cache_flush(); 681 global_cache_flush();
650 mem->is_flushed = TRUE;
651 }
652 682
653 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 683 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
654 writel(agp_bridge->driver->mask_memory(agp_bridge, 684 writel(agp_bridge->driver->mask_memory(agp_bridge,
655 mem->memory[i], mem->type), 685 mem->memory[i], mask_type),
656 intel_i830_private.registers+I810_PTE_BASE+(j*4)); 686 intel_i830_private.registers+I810_PTE_BASE+(j*4));
657 } 687 }
658 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); 688 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
659
660 agp_bridge->driver->tlb_flush(mem); 689 agp_bridge->driver->tlb_flush(mem);
661 return 0; 690
691out:
692 ret = 0;
693out_err:
694 mem->is_flushed = 1;
695 return ret;
662} 696}
663 697
664static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, 698static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -687,7 +721,6 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
687{ 721{
688 if (type == AGP_PHYS_MEMORY) 722 if (type == AGP_PHYS_MEMORY)
689 return alloc_agpphysmem_i8xx(pg_count, type); 723 return alloc_agpphysmem_i8xx(pg_count, type);
690
691 /* always return NULL for other allocation types for now */ 724 /* always return NULL for other allocation types for now */
692 return NULL; 725 return NULL;
693} 726}
@@ -734,9 +767,11 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
734{ 767{
735 int i,j,num_entries; 768 int i,j,num_entries;
736 void *temp; 769 void *temp;
770 int ret = -EINVAL;
771 int mask_type;
737 772
738 if (mem->page_count == 0) 773 if (mem->page_count == 0)
739 return 0; 774 goto out;
740 775
741 temp = agp_bridge->current_size; 776 temp = agp_bridge->current_size;
742 num_entries = A_SIZE_FIX(temp)->num_entries; 777 num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -746,33 +781,41 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
746 pg_start,intel_i830_private.gtt_entries); 781 pg_start,intel_i830_private.gtt_entries);
747 782
748 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); 783 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
749 return -EINVAL; 784 goto out_err;
750 } 785 }
751 786
752 if ((pg_start + mem->page_count) > num_entries) 787 if ((pg_start + mem->page_count) > num_entries)
753 return -EINVAL; 788 goto out_err;
754 789
755 /* The i830 can't check the GTT for entries since its read only, 790 /* The i915 can't check the GTT for entries since its read only,
756 * depend on the caller to make the correct offset decisions. 791 * depend on the caller to make the correct offset decisions.
757 */ 792 */
758 793
759 if ((type != 0 && type != AGP_PHYS_MEMORY) || 794 if (type != mem->type)
760 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 795 goto out_err;
761 return -EINVAL; 796
797 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
762 798
763 if (!mem->is_flushed) { 799 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
800 mask_type != INTEL_AGP_CACHED_MEMORY)
801 goto out_err;
802
803 if (!mem->is_flushed)
764 global_cache_flush(); 804 global_cache_flush();
765 mem->is_flushed = TRUE;
766 }
767 805
768 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 806 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
769 writel(agp_bridge->driver->mask_memory(agp_bridge, 807 writel(agp_bridge->driver->mask_memory(agp_bridge,
770 mem->memory[i], mem->type), intel_i830_private.gtt+j); 808 mem->memory[i], mask_type), intel_i830_private.gtt+j);
771 } 809 }
772 readl(intel_i830_private.gtt+j-1);
773 810
811 readl(intel_i830_private.gtt+j-1);
774 agp_bridge->driver->tlb_flush(mem); 812 agp_bridge->driver->tlb_flush(mem);
775 return 0; 813
814 out:
815 ret = 0;
816 out_err:
817 mem->is_flushed = 1;
818 return ret;
776} 819}
777 820
778static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, 821static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -803,7 +846,7 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
803 */ 846 */
804static int intel_i9xx_fetch_size(void) 847static int intel_i9xx_fetch_size(void)
805{ 848{
806 int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes); 849 int num_sizes = ARRAY_SIZE(intel_i830_sizes);
807 int aper_size; /* size in megabytes */ 850 int aper_size; /* size in megabytes */
808 int i; 851 int i;
809 852
@@ -1384,6 +1427,7 @@ static struct agp_bridge_driver intel_generic_driver = {
1384 .free_by_type = agp_generic_free_by_type, 1427 .free_by_type = agp_generic_free_by_type,
1385 .agp_alloc_page = agp_generic_alloc_page, 1428 .agp_alloc_page = agp_generic_alloc_page,
1386 .agp_destroy_page = agp_generic_destroy_page, 1429 .agp_destroy_page = agp_generic_destroy_page,
1430 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1387}; 1431};
1388 1432
1389static struct agp_bridge_driver intel_810_driver = { 1433static struct agp_bridge_driver intel_810_driver = {
@@ -1408,6 +1452,7 @@ static struct agp_bridge_driver intel_810_driver = {
1408 .free_by_type = intel_i810_free_by_type, 1452 .free_by_type = intel_i810_free_by_type,
1409 .agp_alloc_page = agp_generic_alloc_page, 1453 .agp_alloc_page = agp_generic_alloc_page,
1410 .agp_destroy_page = agp_generic_destroy_page, 1454 .agp_destroy_page = agp_generic_destroy_page,
1455 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1411}; 1456};
1412 1457
1413static struct agp_bridge_driver intel_815_driver = { 1458static struct agp_bridge_driver intel_815_driver = {
@@ -1431,6 +1476,7 @@ static struct agp_bridge_driver intel_815_driver = {
1431 .free_by_type = agp_generic_free_by_type, 1476 .free_by_type = agp_generic_free_by_type,
1432 .agp_alloc_page = agp_generic_alloc_page, 1477 .agp_alloc_page = agp_generic_alloc_page,
1433 .agp_destroy_page = agp_generic_destroy_page, 1478 .agp_destroy_page = agp_generic_destroy_page,
1479 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1434}; 1480};
1435 1481
1436static struct agp_bridge_driver intel_830_driver = { 1482static struct agp_bridge_driver intel_830_driver = {
@@ -1455,6 +1501,7 @@ static struct agp_bridge_driver intel_830_driver = {
1455 .free_by_type = intel_i810_free_by_type, 1501 .free_by_type = intel_i810_free_by_type,
1456 .agp_alloc_page = agp_generic_alloc_page, 1502 .agp_alloc_page = agp_generic_alloc_page,
1457 .agp_destroy_page = agp_generic_destroy_page, 1503 .agp_destroy_page = agp_generic_destroy_page,
1504 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1458}; 1505};
1459 1506
1460static struct agp_bridge_driver intel_820_driver = { 1507static struct agp_bridge_driver intel_820_driver = {
@@ -1478,6 +1525,7 @@ static struct agp_bridge_driver intel_820_driver = {
1478 .free_by_type = agp_generic_free_by_type, 1525 .free_by_type = agp_generic_free_by_type,
1479 .agp_alloc_page = agp_generic_alloc_page, 1526 .agp_alloc_page = agp_generic_alloc_page,
1480 .agp_destroy_page = agp_generic_destroy_page, 1527 .agp_destroy_page = agp_generic_destroy_page,
1528 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1481}; 1529};
1482 1530
1483static struct agp_bridge_driver intel_830mp_driver = { 1531static struct agp_bridge_driver intel_830mp_driver = {
@@ -1501,6 +1549,7 @@ static struct agp_bridge_driver intel_830mp_driver = {
1501 .free_by_type = agp_generic_free_by_type, 1549 .free_by_type = agp_generic_free_by_type,
1502 .agp_alloc_page = agp_generic_alloc_page, 1550 .agp_alloc_page = agp_generic_alloc_page,
1503 .agp_destroy_page = agp_generic_destroy_page, 1551 .agp_destroy_page = agp_generic_destroy_page,
1552 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1504}; 1553};
1505 1554
1506static struct agp_bridge_driver intel_840_driver = { 1555static struct agp_bridge_driver intel_840_driver = {
@@ -1524,6 +1573,7 @@ static struct agp_bridge_driver intel_840_driver = {
1524 .free_by_type = agp_generic_free_by_type, 1573 .free_by_type = agp_generic_free_by_type,
1525 .agp_alloc_page = agp_generic_alloc_page, 1574 .agp_alloc_page = agp_generic_alloc_page,
1526 .agp_destroy_page = agp_generic_destroy_page, 1575 .agp_destroy_page = agp_generic_destroy_page,
1576 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1527}; 1577};
1528 1578
1529static struct agp_bridge_driver intel_845_driver = { 1579static struct agp_bridge_driver intel_845_driver = {
@@ -1547,6 +1597,7 @@ static struct agp_bridge_driver intel_845_driver = {
1547 .free_by_type = agp_generic_free_by_type, 1597 .free_by_type = agp_generic_free_by_type,
1548 .agp_alloc_page = agp_generic_alloc_page, 1598 .agp_alloc_page = agp_generic_alloc_page,
1549 .agp_destroy_page = agp_generic_destroy_page, 1599 .agp_destroy_page = agp_generic_destroy_page,
1600 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1550}; 1601};
1551 1602
1552static struct agp_bridge_driver intel_850_driver = { 1603static struct agp_bridge_driver intel_850_driver = {
@@ -1570,6 +1621,7 @@ static struct agp_bridge_driver intel_850_driver = {
1570 .free_by_type = agp_generic_free_by_type, 1621 .free_by_type = agp_generic_free_by_type,
1571 .agp_alloc_page = agp_generic_alloc_page, 1622 .agp_alloc_page = agp_generic_alloc_page,
1572 .agp_destroy_page = agp_generic_destroy_page, 1623 .agp_destroy_page = agp_generic_destroy_page,
1624 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1573}; 1625};
1574 1626
1575static struct agp_bridge_driver intel_860_driver = { 1627static struct agp_bridge_driver intel_860_driver = {
@@ -1593,6 +1645,7 @@ static struct agp_bridge_driver intel_860_driver = {
1593 .free_by_type = agp_generic_free_by_type, 1645 .free_by_type = agp_generic_free_by_type,
1594 .agp_alloc_page = agp_generic_alloc_page, 1646 .agp_alloc_page = agp_generic_alloc_page,
1595 .agp_destroy_page = agp_generic_destroy_page, 1647 .agp_destroy_page = agp_generic_destroy_page,
1648 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1596}; 1649};
1597 1650
1598static struct agp_bridge_driver intel_915_driver = { 1651static struct agp_bridge_driver intel_915_driver = {
@@ -1617,6 +1670,7 @@ static struct agp_bridge_driver intel_915_driver = {
1617 .free_by_type = intel_i810_free_by_type, 1670 .free_by_type = intel_i810_free_by_type,
1618 .agp_alloc_page = agp_generic_alloc_page, 1671 .agp_alloc_page = agp_generic_alloc_page,
1619 .agp_destroy_page = agp_generic_destroy_page, 1672 .agp_destroy_page = agp_generic_destroy_page,
1673 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1620}; 1674};
1621 1675
1622static struct agp_bridge_driver intel_i965_driver = { 1676static struct agp_bridge_driver intel_i965_driver = {
@@ -1641,6 +1695,7 @@ static struct agp_bridge_driver intel_i965_driver = {
1641 .free_by_type = intel_i810_free_by_type, 1695 .free_by_type = intel_i810_free_by_type,
1642 .agp_alloc_page = agp_generic_alloc_page, 1696 .agp_alloc_page = agp_generic_alloc_page,
1643 .agp_destroy_page = agp_generic_destroy_page, 1697 .agp_destroy_page = agp_generic_destroy_page,
1698 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1644}; 1699};
1645 1700
1646static struct agp_bridge_driver intel_7505_driver = { 1701static struct agp_bridge_driver intel_7505_driver = {
@@ -1664,6 +1719,7 @@ static struct agp_bridge_driver intel_7505_driver = {
1664 .free_by_type = agp_generic_free_by_type, 1719 .free_by_type = agp_generic_free_by_type,
1665 .agp_alloc_page = agp_generic_alloc_page, 1720 .agp_alloc_page = agp_generic_alloc_page,
1666 .agp_destroy_page = agp_generic_destroy_page, 1721 .agp_destroy_page = agp_generic_destroy_page,
1722 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1667}; 1723};
1668 1724
1669static int find_i810(u16 device) 1725static 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/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index 17c50b0f83f0..b7b4590673ae 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -228,6 +228,7 @@ struct agp_bridge_driver parisc_agp_driver = {
228 .free_by_type = agp_generic_free_by_type, 228 .free_by_type = agp_generic_free_by_type,
229 .agp_alloc_page = agp_generic_alloc_page, 229 .agp_alloc_page = agp_generic_alloc_page,
230 .agp_destroy_page = agp_generic_destroy_page, 230 .agp_destroy_page = agp_generic_destroy_page,
231 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
231 .cant_use_aperture = 1, 232 .cant_use_aperture = 1,
232}; 233};
233 234
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/sis-agp.c b/drivers/char/agp/sis-agp.c
index a00fd48a6f05..60342b708152 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -140,6 +140,7 @@ static struct agp_bridge_driver sis_driver = {
140 .free_by_type = agp_generic_free_by_type, 140 .free_by_type = agp_generic_free_by_type,
141 .agp_alloc_page = agp_generic_alloc_page, 141 .agp_alloc_page = agp_generic_alloc_page,
142 .agp_destroy_page = agp_generic_destroy_page, 142 .agp_destroy_page = agp_generic_destroy_page,
143 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
143}; 144};
144 145
145static struct agp_device_ids sis_agp_device_ids[] __devinitdata = 146static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
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