frontend.c revision 408b664a7d394a5e4315fbd14aca49b042cb2b08
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AGPGART driver frontend 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 Silicon Graphics, Inc. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002-2003 Dave Jones 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Jeff Hartmann 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Precision Insight, Inc. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Xi Graphics, Inc. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Permission is hereby granted, free of charge, to any person obtaining a 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * copy of this software and associated documentation files (the "Software"), 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to deal in the Software without restriction, including without limitation 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the rights to use, copy, modify, merge, publish, distribute, sublicense, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and/or sell copies of the Software, and to permit persons to whom the 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Software is furnished to do so, subject to the following conditions: 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The above copyright notice and this permission notice shall be included 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in all copies or substantial portions of the Software. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mman.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/miscdevice.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/agp_backend.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/agpgart.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "agp.h" 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_front_data agp_fe; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_memory *agp_find_mem_by_key(int key) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *curr; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.current_controller == NULL) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curr = agp_fe.current_controller->pool; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (curr != NULL) { 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curr->key == key) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curr = curr->next; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("key=%d -> mem=%p", key, curr); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return curr; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_remove_from_pool(struct agp_memory *temp) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *prev; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *next; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if this is even in the memory pool */ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("mem=%p", temp); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_find_mem_by_key(temp->key) != NULL) { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next = temp->next; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = temp->prev; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev != NULL) { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->next = next; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next != NULL) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next->prev = prev; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is the first item on the list */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next != NULL) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next->prev = NULL; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller->pool = next; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for managing each client's segment list - 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These routines handle adding and removing segments 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to each auth'ed client. 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsagp_segment_priv *agp_find_seg_in_client(const struct agp_client *client, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size, pgprot_t page_prot) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment_priv *seg; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int num_segments, i; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds off_t pg_start; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t pg_count; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pg_start = offset / 4096; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pg_count = size / 4096; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seg = *(client->segments); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_segments = client->num_segments; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < client->num_segments; i++) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((seg[i].pg_start == pg_start) && 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (seg[i].pg_count == pg_count) && 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return seg + i; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_remove_seg_from_client(struct agp_client *client) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("client=%p", client); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client->segments != NULL) { 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*(client->segments) != NULL) { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("Freeing %p from client %p", *(client->segments), client); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(*(client->segments)); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("Freeing %p from client %p", client->segments, client); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(client->segments); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client->segments = NULL; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_add_seg_to_client(struct agp_client *client, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment_priv ** seg, int num_segments) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment_priv **prev_seg; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_seg = client->segments; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev_seg != NULL) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_seg_from_client(client); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client->num_segments = num_segments; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client->segments = seg; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Originally taken from linux/mm/mmap.c from the array 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * protection_map. 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original really should be exported to modules, or 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * some routine which does the conversion for you 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const pgprot_t my_protect_map[16] = 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic pgprot_t agp_convert_mmap_flags(int prot) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _trans(x,bit1,bit2) \ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long prot_bits; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pgprot_t temp; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prot_bits = _trans(prot, PROT_READ, VM_READ) | 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _trans(prot, PROT_WRITE, VM_WRITE) | 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _trans(prot, PROT_EXEC, VM_EXEC); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prot_bits |= VM_SHARED; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = my_protect_map[prot_bits & 0x0000000f]; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return temp; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_create_segment(struct agp_client *client, struct agp_region *region) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment_priv **ret_seg; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment_priv *seg; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment *user_seg; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t i; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (seg == NULL) { 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(region->seg_list); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds region->seg_list = NULL; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count)); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds user_seg = region->seg_list; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < region->seg_count; i++) { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seg[i].pg_start = user_seg[i].pg_start; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seg[i].pg_count = user_seg[i].pg_count; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(region->seg_list); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds region->seg_list = NULL; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_seg = kmalloc(sizeof(void *), GFP_KERNEL); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret_seg == NULL) { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(seg); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ret_seg = seg; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_add_seg_to_client(client, ret_seg, region->seg_count); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* End - Routines for managing each client's segment list */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This function must only be called when current_controller != NULL */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_insert_into_pool(struct agp_memory * temp) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *prev; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = agp_fe.current_controller->pool; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev != NULL) { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->prev = temp; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp->next = prev; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller->pool = temp; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* File private list routines */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 238408b664a7d394a5e4315fbd14aca49b042cb2b08Adrian Bunkstatic struct agp_file_private *agp_find_private(pid_t pid) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *curr; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curr = agp_fe.file_priv_list; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (curr != NULL) { 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curr->my_pid == pid) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return curr; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curr = curr->next; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253408b664a7d394a5e4315fbd14aca49b042cb2b08Adrian Bunkstatic void agp_insert_file_private(struct agp_file_private * priv) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *prev; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = agp_fe.file_priv_list; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev != NULL) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->prev = priv; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->next = prev; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.file_priv_list = priv; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 265408b664a7d394a5e4315fbd14aca49b042cb2b08Adrian Bunkstatic void agp_remove_file_private(struct agp_file_private * priv) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *next; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *prev; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next = priv->next; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = priv->prev; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev != NULL) { 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->next = next; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next != NULL) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next->prev = prev; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next != NULL) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next->prev = NULL; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.file_priv_list = next; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* End - File flag list routines */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wrappers for agp_free_memory & agp_allocate_memory 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These make sure that internal lists are kept updated. 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_free_memory_wrap(struct agp_memory *memory) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_from_pool(memory); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_free_memory(memory); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = agp_allocate_memory(agp_bridge, pg_count, type); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memory == NULL) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_insert_into_pool(memory); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return memory; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Routines for managing the list of controllers - 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These routines manage the current controller, and the list of 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controllers 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_controller *agp_find_controller_by_pid(pid_t id) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_fe.controllers; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (controller != NULL) { 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller->pid == id) 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return controller; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = controller->next; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_controller *agp_create_controller(pid_t id) 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller == NULL) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(controller, 0, sizeof(struct agp_controller)); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller->pid = id; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return controller; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_insert_controller(struct agp_controller *controller) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *prev_controller; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_controller = agp_fe.controllers; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller->next = prev_controller; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev_controller != NULL) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_controller->prev = controller; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.controllers = controller; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_remove_all_clients(struct agp_controller *controller) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *temp; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = controller->clients; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (client) { 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = client; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_seg_from_client(temp); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = agp_find_private(temp->pid); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv != NULL) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = client->next; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(temp); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_remove_all_memory(struct agp_controller *controller) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *temp; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = controller->pool; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (memory) { 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = memory; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = memory->next; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_free_memory_wrap(temp); 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_remove_controller(struct agp_controller *controller) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *prev_controller; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *next_controller; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_controller = controller->prev; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_controller = controller->next; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev_controller != NULL) { 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_controller->next = next_controller; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next_controller != NULL) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_controller->prev = prev_controller; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next_controller != NULL) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_controller->prev = NULL; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.controllers = next_controller; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_all_memory(controller); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_all_clients(controller); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.current_controller == controller) { 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller = NULL; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.backend_acquired = FALSE; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_backend_release(agp_bridge); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(controller); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_controller_make_current(struct agp_controller *controller) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *clients; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clients = controller->clients; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (clients != NULL) { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = agp_find_private(clients->pid); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv != NULL) { 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_VALID, &priv->access_flags); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clients = clients->next; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller = controller; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_controller_release_current(struct agp_controller *controller, 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *controller_priv) 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *clients; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clients = controller->clients; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (clients != NULL) { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = agp_find_private(clients->pid); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv != NULL) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clients = clients->next; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller = NULL; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.used_by_controller = FALSE; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_backend_release(agp_bridge); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines for managing client lists - 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These routines are for managing the list of auth'ed clients. 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_client 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*agp_find_client_in_controller(struct agp_controller *controller, pid_t id) 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller == NULL) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = controller->clients; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (client != NULL) { 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client->pid == id) 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return client; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = client->next; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_controller *agp_find_controller_for_client(pid_t id) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_fe.controllers; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (controller != NULL) { 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((agp_find_client_in_controller(controller, id)) != NULL) 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return controller; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = controller->next; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_client *agp_find_client_by_pid(pid_t id) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *temp; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.current_controller == NULL) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = agp_find_client_in_controller(agp_fe.current_controller, id); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return temp; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void agp_insert_client(struct agp_client *client) 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *prev_client; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_client = agp_fe.current_controller->clients; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client->next = prev_client; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev_client != NULL) 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_client->prev = client; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller->clients = client; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.current_controller->num_clients++; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct agp_client *agp_create_client(pid_t id) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *new_client; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_client == NULL) 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(new_client, 0, sizeof(struct agp_client)); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_client->pid = id; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_insert_client(new_client); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return new_client; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_remove_client(pid_t id) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *prev_client; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *next_client; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_find_controller_for_client(id); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller == NULL) 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = agp_find_client_in_controller(controller, id); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client == NULL) 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_client = client->prev; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_client = client->next; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev_client != NULL) { 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev_client->next = next_client; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next_client != NULL) 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_client->prev = prev_client; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next_client != NULL) 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_client->prev = NULL; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller->clients = next_client; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller->num_clients--; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_seg_from_client(client); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(client); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* End - Routines for managing client lists */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* File Operations */ 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_mmap(struct file *file, struct vm_area_struct *vma) 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int size, current_size; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long offset; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv = file->private_data; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_kern_info kerninfo; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&(agp_fe.agp_mutex)); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.backend_acquired != TRUE) 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_eperm; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_eperm; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_copy_info(agp_bridge, &kerninfo); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = vma->vm_end - vma->vm_start; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_size = kerninfo.aper_size; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_size = current_size * 0x100000; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds offset = vma->vm_pgoff << PAGE_SHIFT; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("%lx:%lx", offset, offset+size); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((size + offset) > current_size) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_inval; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = agp_find_client_by_pid(current->pid); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client == NULL) 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_eperm; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot)) 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_inval; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("client vm_ops=%p", kerninfo.vm_ops); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kerninfo.vm_ops) { 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_ops = kerninfo.vm_ops; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (io_remap_pfn_range(vma, vma->vm_start, 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kerninfo.aper_base + offset) >> PAGE_SHIFT, 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size, vma->vm_page_prot)) { 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_again; 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (size != current_size) 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_inval; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("controller vm_ops=%p", kerninfo.vm_ops); 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kerninfo.vm_ops) { 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_ops = kerninfo.vm_ops; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (io_remap_pfn_range(vma, vma->vm_start, 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kerninfo.aper_base >> PAGE_SHIFT, 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size, vma->vm_page_prot)) { 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_again; 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_eperm: 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_inval: 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_again: 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_release(struct inode *inode, struct file *file) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv = file->private_data; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&(agp_fe.agp_mutex)); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("priv=%p", priv); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_find_controller_by_pid(priv->my_pid); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller != NULL) { 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller == agp_fe.current_controller) 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_controller_release_current(controller, priv); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_controller(controller); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = NULL; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_client(priv->my_pid); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_remove_file_private(priv); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(priv); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file->private_data = NULL; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_open(struct inode *inode, struct file *file) 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int minor = iminor(inode); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *priv; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc = -ENXIO; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&(agp_fe.agp_mutex)); 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (minor != AGPGART_MINOR) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (priv == NULL) 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_nomem; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(priv, 0, sizeof(struct agp_file_private)); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds priv->my_pid = current->pid; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((current->uid == 0) || (current->suid == 0)) { 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Root priv, can be controller */ 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = agp_find_client_by_pid(current->pid); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client != NULL) { 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_VALID, &priv->access_flags); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds file->private_data = (void *) priv; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_insert_file_private(priv); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("private=%p, client=%p", priv, client); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_nomem: 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -ENOMEM; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out: 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t agp_read(struct file *file, char __user *buf, 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count, loff_t * ppos) 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t agp_write(struct file *file, const char __user *buf, 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count, loff_t * ppos) 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_info userinfo; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_kern_info kerninfo; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_copy_info(agp_bridge, &kerninfo); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.version.major = kerninfo.version.major; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.version.minor = kerninfo.version.minor; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.bridge_id = kerninfo.device->vendor | 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kerninfo.device->device << 16); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.agp_mode = kerninfo.mode; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.aper_base = kerninfo.aper_base; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.aper_size = kerninfo.aper_size; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds userinfo.pg_used = kerninfo.current_memory; 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(arg, &userinfo, sizeof(struct agp_info))) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_acquire_wrap(struct agp_file_private *priv) 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_controller *controller; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags))) 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.current_controller != NULL) 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!agp_bridge) 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&agp_bridge->agp_in_use)) 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&agp_bridge->agp_in_use); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.backend_acquired = TRUE; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_find_controller_by_pid(priv->my_pid); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller != NULL) { 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_controller_make_current(controller); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds controller = agp_create_controller(priv->my_pid); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (controller == NULL) { 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_fe.backend_acquired = FALSE; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_backend_release(agp_bridge); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_insert_controller(controller); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_controller_make_current(controller); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_VALID, &priv->access_flags); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_release_wrap(struct agp_file_private *priv) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_controller_release_current(agp_fe.current_controller, priv); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_setup mode; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&mode, arg, sizeof(struct agp_setup))) 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_enable(agp_bridge, mode.agp_mode); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_region reserve; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_client *client; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *client_priv; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = agp_find_client_by_pid(reserve.pid); 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reserve.seg_count == 0) { 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* remove a client */ 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client_priv = agp_find_private(reserve.pid); 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client_priv != NULL) { 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client == NULL) { 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* client is already removed */ 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp_remove_client(reserve.pid); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_segment *segment; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reserve.seg_count >= 16384) 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count), 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (segment == NULL) 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(segment, (void __user *) reserve.seg_list, 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct agp_segment) * reserve.seg_count)) { 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(segment); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reserve.seg_list = segment; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client == NULL) { 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create the client and add the segment */ 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client = agp_create_client(reserve.pid); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client == NULL) { 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(segment); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client_priv = agp_find_private(reserve.pid); 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (client_priv != NULL) { 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp_create_segment(client, &reserve); 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Will never really happen */ 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_protect_wrap(struct agp_file_private *priv) 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This function is not currently implemented */ 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg) 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_allocate alloc; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate))) 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memory == NULL) 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alloc.key = memory->key; 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alloc.physical = memory->physical; 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) { 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_free_memory_wrap(memory); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = agp_find_mem_by_key(arg); 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memory == NULL) 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp_free_memory_wrap(memory); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg) 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_bind bind_info; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind))) 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = agp_find_mem_by_key(bind_info.key); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memory == NULL) 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp_bind_memory(memory, bind_info.pg_start); 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg) 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_memory *memory; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_unbind unbind; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG(""); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind))) 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory = agp_find_mem_by_key(unbind.key); 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memory == NULL) 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp_unbind_memory(memory); 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int agp_ioctl(struct inode *inode, struct file *file, 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct agp_file_private *curr_priv = file->private_data; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret_val = -ENOTTY; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("priv=%p, cmd=%x", curr_priv, cmd); 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&(agp_fe.agp_mutex)); 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((agp_fe.current_controller == NULL) && 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd != AGPIOC_ACQUIRE)) { 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = -EINVAL; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ioctl_out; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((agp_fe.backend_acquired != TRUE) && 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd != AGPIOC_ACQUIRE)) { 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = -EBUSY; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ioctl_out; 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd != AGPIOC_ACQUIRE) { 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = -EPERM; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ioctl_out; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Use the original pid of the controller, 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in case it's threaded */ 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp_fe.current_controller->pid != curr_priv->my_pid) { 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = -EBUSY; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto ioctl_out; 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_INFO: 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_ACQUIRE: 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_acquire_wrap(curr_priv); 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_RELEASE: 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_release_wrap(curr_priv); 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_SETUP: 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg); 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_RESERVE: 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_PROTECT: 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_protect_wrap(curr_priv); 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_ALLOCATE: 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg); 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_DEALLOCATE: 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg); 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_BIND: 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case AGPIOC_UNBIND: 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg); 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsioctl_out: 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG("ioctl returns %d\n", ret_val); 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&(agp_fe.agp_mutex)); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret_val; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_operations agp_fops = 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .llseek = no_llseek, 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = agp_read, 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = agp_write, 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = agp_ioctl, 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mmap = agp_mmap, 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = agp_open, 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = agp_release, 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct miscdevice agp_miscdev = 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .minor = AGPGART_MINOR, 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "agpgart", 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fops = &agp_fops 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint agp_frontend_initialize(void) 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&agp_fe, 0, sizeof(struct agp_front_data)); 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sema_init(&(agp_fe.agp_mutex), 1); 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (misc_register(&agp_miscdev)) { 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid agp_frontend_cleanup(void) 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds misc_deregister(&agp_miscdev); 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1104