Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
backend.c
Go to the documentation of this file.
1 /*
2  * AGPGART driver backend routines.
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, DAVE JONES, 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  * TODO:
28  * - Allocate more than order 0 pages to avoid too much linear map splitting.
29  */
30 #include <linux/module.h>
31 #include <linux/pci.h>
32 #include <linux/init.h>
33 #include <linux/slab.h>
34 #include <linux/pagemap.h>
35 #include <linux/miscdevice.h>
36 #include <linux/pm.h>
37 #include <linux/agp_backend.h>
38 #include <linux/agpgart.h>
39 #include <linux/vmalloc.h>
40 #include <asm/io.h>
41 #include "agp.h"
42 
43 /* Due to XFree86 brain-damage, we can't go to 1.0 until they
44  * fix some real stupidity. It's only by chance we can bump
45  * past 0.99 at all due to some boolean logic error. */
46 #define AGPGART_VERSION_MAJOR 0
47 #define AGPGART_VERSION_MINOR 103
48 static const struct agp_version agp_current_version =
49 {
50  .major = AGPGART_VERSION_MAJOR,
51  .minor = AGPGART_VERSION_MINOR,
52 };
53 
54 struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *) =
56 
58 LIST_HEAD(agp_bridges);
59 EXPORT_SYMBOL(agp_bridge);
60 EXPORT_SYMBOL(agp_bridges);
62 
68 {
69  struct agp_bridge_data *bridge;
70 
71  bridge = agp_find_bridge(pdev);
72 
73  if (!bridge)
74  return NULL;
75 
76  if (atomic_read(&bridge->agp_in_use))
77  return NULL;
78  atomic_inc(&bridge->agp_in_use);
79  return bridge;
80 }
82 
83 
93 {
94 
95  if (bridge)
96  atomic_dec(&bridge->agp_in_use);
97 }
99 
100 
101 static const struct { int mem, agp; } maxes_table[] = {
102  {0, 0},
103  {32, 4},
104  {64, 28},
105  {128, 96},
106  {256, 204},
107  {512, 440},
108  {1024, 942},
109  {2048, 1920},
110  {4096, 3932}
111 };
112 
113 static int agp_find_max(void)
114 {
115  long memory, index, result;
116 
117 #if PAGE_SHIFT < 20
118  memory = totalram_pages >> (20 - PAGE_SHIFT);
119 #else
120  memory = totalram_pages << (PAGE_SHIFT - 20);
121 #endif
122  index = 1;
123 
124  while ((memory > maxes_table[index].mem) && (index < 8))
125  index++;
126 
127  result = maxes_table[index - 1].agp +
128  ( (memory - maxes_table[index - 1].mem) *
129  (maxes_table[index].agp - maxes_table[index - 1].agp)) /
130  (maxes_table[index].mem - maxes_table[index - 1].mem);
131 
132  result = result << (20 - PAGE_SHIFT);
133  return result;
134 }
135 
136 
137 static int agp_backend_initialize(struct agp_bridge_data *bridge)
138 {
139  int size_value, rc, got_gatt=0, got_keylist=0;
140 
141  bridge->max_memory_agp = agp_find_max();
142  bridge->version = &agp_current_version;
143 
144  if (bridge->driver->needs_scratch_page) {
145  struct page *page = bridge->driver->agp_alloc_page(bridge);
146 
147  if (!page) {
148  dev_err(&bridge->dev->dev,
149  "can't get memory for scratch page\n");
150  return -ENOMEM;
151  }
152 
153  bridge->scratch_page_page = page;
154  bridge->scratch_page_dma = page_to_phys(page);
155 
156  bridge->scratch_page = bridge->driver->mask_memory(bridge,
157  bridge->scratch_page_dma, 0);
158  }
159 
160  size_value = bridge->driver->fetch_size();
161  if (size_value == 0) {
162  dev_err(&bridge->dev->dev, "can't determine aperture size\n");
163  rc = -EINVAL;
164  goto err_out;
165  }
166  if (bridge->driver->create_gatt_table(bridge)) {
167  dev_err(&bridge->dev->dev,
168  "can't get memory for graphics translation table\n");
169  rc = -ENOMEM;
170  goto err_out;
171  }
172  got_gatt = 1;
173 
174  bridge->key_list = vzalloc(PAGE_SIZE * 4);
175  if (bridge->key_list == NULL) {
176  dev_err(&bridge->dev->dev,
177  "can't allocate memory for key lists\n");
178  rc = -ENOMEM;
179  goto err_out;
180  }
181  got_keylist = 1;
182 
183  /* FIXME vmalloc'd memory not guaranteed contiguous */
184 
185  if (bridge->driver->configure()) {
186  dev_err(&bridge->dev->dev, "error configuring host chipset\n");
187  rc = -EINVAL;
188  goto err_out;
189  }
190  INIT_LIST_HEAD(&bridge->mapped_list);
191  spin_lock_init(&bridge->mapped_lock);
192 
193  return 0;
194 
195 err_out:
196  if (bridge->driver->needs_scratch_page) {
197  struct page *page = bridge->scratch_page_page;
198 
199  bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
200  bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
201  }
202  if (got_gatt)
203  bridge->driver->free_gatt_table(bridge);
204  if (got_keylist) {
205  vfree(bridge->key_list);
206  bridge->key_list = NULL;
207  }
208  return rc;
209 }
210 
211 /* cannot be __exit b/c as it could be called from __init code */
212 static void agp_backend_cleanup(struct agp_bridge_data *bridge)
213 {
214  if (bridge->driver->cleanup)
215  bridge->driver->cleanup();
216  if (bridge->driver->free_gatt_table)
217  bridge->driver->free_gatt_table(bridge);
218 
219  vfree(bridge->key_list);
220  bridge->key_list = NULL;
221 
222  if (bridge->driver->agp_destroy_page &&
223  bridge->driver->needs_scratch_page) {
224  struct page *page = bridge->scratch_page_page;
225 
226  bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
227  bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
228  }
229 }
230 
231 /* When we remove the global variable agp_bridge from all drivers
232  * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
233  */
234 
236 {
237  struct agp_bridge_data *bridge;
238 
239  bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
240  if (!bridge)
241  return NULL;
242 
243  atomic_set(&bridge->agp_in_use, 0);
244  atomic_set(&bridge->current_memory_agp, 0);
245 
246  if (list_empty(&agp_bridges))
247  agp_bridge = bridge;
248 
249  return bridge;
250 }
252 
253 
254 void agp_put_bridge(struct agp_bridge_data *bridge)
255 {
256  kfree(bridge);
257 
258  if (list_empty(&agp_bridges))
259  agp_bridge = NULL;
260 }
262 
263 
264 int agp_add_bridge(struct agp_bridge_data *bridge)
265 {
266  int error;
267 
268  if (agp_off) {
269  error = -ENODEV;
270  goto err_put_bridge;
271  }
272 
273  if (!bridge->dev) {
274  printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
275  error = -EINVAL;
276  goto err_put_bridge;
277  }
278 
279  /* Grab reference on the chipset driver. */
280  if (!try_module_get(bridge->driver->owner)) {
281  dev_info(&bridge->dev->dev, "can't lock chipset driver\n");
282  error = -EINVAL;
283  goto err_put_bridge;
284  }
285 
286  error = agp_backend_initialize(bridge);
287  if (error) {
288  dev_info(&bridge->dev->dev,
289  "agp_backend_initialize() failed\n");
290  goto err_out;
291  }
292 
293  if (list_empty(&agp_bridges)) {
294  error = agp_frontend_initialize();
295  if (error) {
296  dev_info(&bridge->dev->dev,
297  "agp_frontend_initialize() failed\n");
298  goto frontend_err;
299  }
300 
301  dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n",
302  bridge->driver->fetch_size(), bridge->gart_bus_addr);
303 
304  }
305 
306  list_add(&bridge->list, &agp_bridges);
307  return 0;
308 
309 frontend_err:
310  agp_backend_cleanup(bridge);
311 err_out:
312  module_put(bridge->driver->owner);
313 err_put_bridge:
314  agp_put_bridge(bridge);
315  return error;
316 }
318 
319 
320 void agp_remove_bridge(struct agp_bridge_data *bridge)
321 {
322  agp_backend_cleanup(bridge);
323  list_del(&bridge->list);
324  if (list_empty(&agp_bridges))
326  module_put(bridge->driver->owner);
327 }
329 
332 EXPORT_SYMBOL(agp_off);
333 EXPORT_SYMBOL(agp_try_unsupported_boot);
334 
335 static int __init agp_init(void)
336 {
337  if (!agp_off)
338  printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
340  return 0;
341 }
342 
343 static void __exit agp_exit(void)
344 {
345 }
346 
347 #ifndef MODULE
348 static __init int agp_setup(char *s)
349 {
350  if (!strcmp(s,"off"))
351  agp_off = 1;
352  if (!strcmp(s,"try_unsupported"))
353  agp_try_unsupported_boot = 1;
354  return 1;
355 }
356 __setup("agp=", agp_setup);
357 #endif
358 
359 MODULE_AUTHOR("Dave Jones <[email protected]>");
360 MODULE_DESCRIPTION("AGP GART driver");
361 MODULE_LICENSE("GPL and additional rights");
363 
364 module_init(agp_init);
365 module_exit(agp_exit);
366