aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/agp/generic.c')
-rw-r--r--drivers/char/agp/generic.c130
1 files changed, 124 insertions, 6 deletions
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