root/drivers/char/agp/frontend.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. agp_find_mem_by_key
  2. agp_remove_from_pool
  3. agp_find_seg_in_client
  4. agp_remove_seg_from_client
  5. agp_add_seg_to_client
  6. agp_convert_mmap_flags
  7. agp_create_segment
  8. agp_insert_into_pool
  9. agp_find_private
  10. agp_insert_file_private
  11. agp_remove_file_private
  12. agp_free_memory_wrap
  13. agp_allocate_memory_wrap
  14. agp_find_controller_by_pid
  15. agp_create_controller
  16. agp_insert_controller
  17. agp_remove_all_clients
  18. agp_remove_all_memory
  19. agp_remove_controller
  20. agp_controller_make_current
  21. agp_controller_release_current
  22. agp_find_client_in_controller
  23. agp_find_controller_for_client
  24. agp_find_client_by_pid
  25. agp_insert_client
  26. agp_create_client
  27. agp_remove_client
  28. agp_mmap
  29. agp_release
  30. agp_open
  31. agpioc_info_wrap
  32. agpioc_acquire_wrap
  33. agpioc_release_wrap
  34. agpioc_setup_wrap
  35. agpioc_reserve_wrap
  36. agpioc_protect_wrap
  37. agpioc_allocate_wrap
  38. agpioc_deallocate_wrap
  39. agpioc_bind_wrap
  40. agpioc_unbind_wrap
  41. agp_ioctl
  42. agp_frontend_initialize
  43. agp_frontend_cleanup

   1 /*
   2  * AGPGART driver frontend
   3  * Copyright (C) 2004 Silicon Graphics, Inc.
   4  * Copyright (C) 2002-2003 Dave Jones
   5  * Copyright (C) 1999 Jeff Hartmann
   6  * Copyright (C) 1999 Precision Insight, Inc.
   7  * Copyright (C) 1999 Xi Graphics, Inc.
   8  *
   9  * Permission is hereby granted, free of charge, to any person obtaining a
  10  * copy of this software and associated documentation files (the "Software"),
  11  * to deal in the Software without restriction, including without limitation
  12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13  * and/or sell copies of the Software, and to permit persons to whom the
  14  * Software is furnished to do so, subject to the following conditions:
  15  *
  16  * The above copyright notice and this permission notice shall be included
  17  * in all copies or substantial portions of the Software.
  18  *
  19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22  * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
  23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  25  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26  *
  27  */
  28 
  29 #include <linux/types.h>
  30 #include <linux/kernel.h>
  31 #include <linux/module.h>
  32 #include <linux/mman.h>
  33 #include <linux/pci.h>
  34 #include <linux/miscdevice.h>
  35 #include <linux/agp_backend.h>
  36 #include <linux/agpgart.h>
  37 #include <linux/slab.h>
  38 #include <linux/mm.h>
  39 #include <linux/fs.h>
  40 #include <linux/sched.h>
  41 #include <linux/uaccess.h>
  42 #include <asm/pgtable.h>
  43 #include "agp.h"
  44 
  45 struct agp_front_data agp_fe;
  46 
  47 struct agp_memory *agp_find_mem_by_key(int key)
  48 {
  49         struct agp_memory *curr;
  50 
  51         if (agp_fe.current_controller == NULL)
  52                 return NULL;
  53 
  54         curr = agp_fe.current_controller->pool;
  55 
  56         while (curr != NULL) {
  57                 if (curr->key == key)
  58                         break;
  59                 curr = curr->next;
  60         }
  61 
  62         DBG("key=%d -> mem=%p", key, curr);
  63         return curr;
  64 }
  65 
  66 static void agp_remove_from_pool(struct agp_memory *temp)
  67 {
  68         struct agp_memory *prev;
  69         struct agp_memory *next;
  70 
  71         /* Check to see if this is even in the memory pool */
  72 
  73         DBG("mem=%p", temp);
  74         if (agp_find_mem_by_key(temp->key) != NULL) {
  75                 next = temp->next;
  76                 prev = temp->prev;
  77 
  78                 if (prev != NULL) {
  79                         prev->next = next;
  80                         if (next != NULL)
  81                                 next->prev = prev;
  82 
  83                 } else {
  84                         /* This is the first item on the list */
  85                         if (next != NULL)
  86                                 next->prev = NULL;
  87 
  88                         agp_fe.current_controller->pool = next;
  89                 }
  90         }
  91 }
  92 
  93 /*
  94  * Routines for managing each client's segment list -
  95  * These routines handle adding and removing segments
  96  * to each auth'ed client.
  97  */
  98 
  99 static struct
 100 agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,
 101                                                 unsigned long offset,
 102                                             int size, pgprot_t page_prot)
 103 {
 104         struct agp_segment_priv *seg;
 105         int num_segments, i;
 106         off_t pg_start;
 107         size_t pg_count;
 108 
 109         pg_start = offset / 4096;
 110         pg_count = size / 4096;
 111         seg = *(client->segments);
 112         num_segments = client->num_segments;
 113 
 114         for (i = 0; i < client->num_segments; i++) {
 115                 if ((seg[i].pg_start == pg_start) &&
 116                     (seg[i].pg_count == pg_count) &&
 117                     (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) {
 118                         return seg + i;
 119                 }
 120         }
 121 
 122         return NULL;
 123 }
 124 
 125 static void agp_remove_seg_from_client(struct agp_client *client)
 126 {
 127         DBG("client=%p", client);
 128 
 129         if (client->segments != NULL) {
 130                 if (*(client->segments) != NULL) {
 131                         DBG("Freeing %p from client %p", *(client->segments), client);
 132                         kfree(*(client->segments));
 133                 }
 134                 DBG("Freeing %p from client %p", client->segments, client);
 135                 kfree(client->segments);
 136                 client->segments = NULL;
 137         }
 138 }
 139 
 140 static void agp_add_seg_to_client(struct agp_client *client,
 141                                struct agp_segment_priv ** seg, int num_segments)
 142 {
 143         struct agp_segment_priv **prev_seg;
 144 
 145         prev_seg = client->segments;
 146 
 147         if (prev_seg != NULL)
 148                 agp_remove_seg_from_client(client);
 149 
 150         DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
 151         client->num_segments = num_segments;
 152         client->segments = seg;
 153 }
 154 
 155 static pgprot_t agp_convert_mmap_flags(int prot)
 156 {
 157         unsigned long prot_bits;
 158 
 159         prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED;
 160         return vm_get_page_prot(prot_bits);
 161 }
 162 
 163 int agp_create_segment(struct agp_client *client, struct agp_region *region)
 164 {
 165         struct agp_segment_priv **ret_seg;
 166         struct agp_segment_priv *seg;
 167         struct agp_segment *user_seg;
 168         size_t i;
 169 
 170         seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);
 171         if (seg == NULL) {
 172                 kfree(region->seg_list);
 173                 region->seg_list = NULL;
 174                 return -ENOMEM;
 175         }
 176         user_seg = region->seg_list;
 177 
 178         for (i = 0; i < region->seg_count; i++) {
 179                 seg[i].pg_start = user_seg[i].pg_start;
 180                 seg[i].pg_count = user_seg[i].pg_count;
 181                 seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
 182         }
 183         kfree(region->seg_list);
 184         region->seg_list = NULL;
 185 
 186         ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
 187         if (ret_seg == NULL) {
 188                 kfree(seg);
 189                 return -ENOMEM;
 190         }
 191         *ret_seg = seg;
 192         agp_add_seg_to_client(client, ret_seg, region->seg_count);
 193         return 0;
 194 }
 195 
 196 /* End - Routines for managing each client's segment list */
 197 
 198 /* This function must only be called when current_controller != NULL */
 199 static void agp_insert_into_pool(struct agp_memory * temp)
 200 {
 201         struct agp_memory *prev;
 202 
 203         prev = agp_fe.current_controller->pool;
 204 
 205         if (prev != NULL) {
 206                 prev->prev = temp;
 207                 temp->next = prev;
 208         }
 209         agp_fe.current_controller->pool = temp;
 210 }
 211 
 212 
 213 /* File private list routines */
 214 
 215 struct agp_file_private *agp_find_private(pid_t pid)
 216 {
 217         struct agp_file_private *curr;
 218 
 219         curr = agp_fe.file_priv_list;
 220 
 221         while (curr != NULL) {
 222                 if (curr->my_pid == pid)
 223                         return curr;
 224                 curr = curr->next;
 225         }
 226 
 227         return NULL;
 228 }
 229 
 230 static void agp_insert_file_private(struct agp_file_private * priv)
 231 {
 232         struct agp_file_private *prev;
 233 
 234         prev = agp_fe.file_priv_list;
 235 
 236         if (prev != NULL)
 237                 prev->prev = priv;
 238         priv->next = prev;
 239         agp_fe.file_priv_list = priv;
 240 }
 241 
 242 static void agp_remove_file_private(struct agp_file_private * priv)
 243 {
 244         struct agp_file_private *next;
 245         struct agp_file_private *prev;
 246 
 247         next = priv->next;
 248         prev = priv->prev;
 249 
 250         if (prev != NULL) {
 251                 prev->next = next;
 252 
 253                 if (next != NULL)
 254                         next->prev = prev;
 255 
 256         } else {
 257                 if (next != NULL)
 258                         next->prev = NULL;
 259 
 260                 agp_fe.file_priv_list = next;
 261         }
 262 }
 263 
 264 /* End - File flag list routines */
 265 
 266 /*
 267  * Wrappers for agp_free_memory & agp_allocate_memory
 268  * These make sure that internal lists are kept updated.
 269  */
 270 void agp_free_memory_wrap(struct agp_memory *memory)
 271 {
 272         agp_remove_from_pool(memory);
 273         agp_free_memory(memory);
 274 }
 275 
 276 struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
 277 {
 278         struct agp_memory *memory;
 279 
 280         memory = agp_allocate_memory(agp_bridge, pg_count, type);
 281         if (memory == NULL)
 282                 return NULL;
 283 
 284         agp_insert_into_pool(memory);
 285         return memory;
 286 }
 287 
 288 /* Routines for managing the list of controllers -
 289  * These routines manage the current controller, and the list of
 290  * controllers
 291  */
 292 
 293 static struct agp_controller *agp_find_controller_by_pid(pid_t id)
 294 {
 295         struct agp_controller *controller;
 296 
 297         controller = agp_fe.controllers;
 298 
 299         while (controller != NULL) {
 300                 if (controller->pid == id)
 301                         return controller;
 302                 controller = controller->next;
 303         }
 304 
 305         return NULL;
 306 }
 307 
 308 static struct agp_controller *agp_create_controller(pid_t id)
 309 {
 310         struct agp_controller *controller;
 311 
 312         controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL);
 313         if (controller == NULL)
 314                 return NULL;
 315 
 316         controller->pid = id;
 317         return controller;
 318 }
 319 
 320 static int agp_insert_controller(struct agp_controller *controller)
 321 {
 322         struct agp_controller *prev_controller;
 323 
 324         prev_controller = agp_fe.controllers;
 325         controller->next = prev_controller;
 326 
 327         if (prev_controller != NULL)
 328                 prev_controller->prev = controller;
 329 
 330         agp_fe.controllers = controller;
 331 
 332         return 0;
 333 }
 334 
 335 static void agp_remove_all_clients(struct agp_controller *controller)
 336 {
 337         struct agp_client *client;
 338         struct agp_client *temp;
 339 
 340         client = controller->clients;
 341 
 342         while (client) {
 343                 struct agp_file_private *priv;
 344 
 345                 temp = client;
 346                 agp_remove_seg_from_client(temp);
 347                 priv = agp_find_private(temp->pid);
 348 
 349                 if (priv != NULL) {
 350                         clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
 351                         clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
 352                 }
 353                 client = client->next;
 354                 kfree(temp);
 355         }
 356 }
 357 
 358 static void agp_remove_all_memory(struct agp_controller *controller)
 359 {
 360         struct agp_memory *memory;
 361         struct agp_memory *temp;
 362 
 363         memory = controller->pool;
 364 
 365         while (memory) {
 366                 temp = memory;
 367                 memory = memory->next;
 368                 agp_free_memory_wrap(temp);
 369         }
 370 }
 371 
 372 static int agp_remove_controller(struct agp_controller *controller)
 373 {
 374         struct agp_controller *prev_controller;
 375         struct agp_controller *next_controller;
 376 
 377         prev_controller = controller->prev;
 378         next_controller = controller->next;
 379 
 380         if (prev_controller != NULL) {
 381                 prev_controller->next = next_controller;
 382                 if (next_controller != NULL)
 383                         next_controller->prev = prev_controller;
 384 
 385         } else {
 386                 if (next_controller != NULL)
 387                         next_controller->prev = NULL;
 388 
 389                 agp_fe.controllers = next_controller;
 390         }
 391 
 392         agp_remove_all_memory(controller);
 393         agp_remove_all_clients(controller);
 394 
 395         if (agp_fe.current_controller == controller) {
 396                 agp_fe.current_controller = NULL;
 397                 agp_fe.backend_acquired = false;
 398                 agp_backend_release(agp_bridge);
 399         }
 400         kfree(controller);
 401         return 0;
 402 }
 403 
 404 static void agp_controller_make_current(struct agp_controller *controller)
 405 {
 406         struct agp_client *clients;
 407 
 408         clients = controller->clients;
 409 
 410         while (clients != NULL) {
 411                 struct agp_file_private *priv;
 412 
 413                 priv = agp_find_private(clients->pid);
 414 
 415                 if (priv != NULL) {
 416                         set_bit(AGP_FF_IS_VALID, &priv->access_flags);
 417                         set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
 418                 }
 419                 clients = clients->next;
 420         }
 421 
 422         agp_fe.current_controller = controller;
 423 }
 424 
 425 static void agp_controller_release_current(struct agp_controller *controller,
 426                                       struct agp_file_private *controller_priv)
 427 {
 428         struct agp_client *clients;
 429 
 430         clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);
 431         clients = controller->clients;
 432 
 433         while (clients != NULL) {
 434                 struct agp_file_private *priv;
 435 
 436                 priv = agp_find_private(clients->pid);
 437 
 438                 if (priv != NULL)
 439                         clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
 440 
 441                 clients = clients->next;
 442         }
 443 
 444         agp_fe.current_controller = NULL;
 445         agp_fe.used_by_controller = false;
 446         agp_backend_release(agp_bridge);
 447 }
 448 
 449 /*
 450  * Routines for managing client lists -
 451  * These routines are for managing the list of auth'ed clients.
 452  */
 453 
 454 static struct agp_client
 455 *agp_find_client_in_controller(struct agp_controller *controller, pid_t id)
 456 {
 457         struct agp_client *client;
 458 
 459         if (controller == NULL)
 460                 return NULL;
 461 
 462         client = controller->clients;
 463 
 464         while (client != NULL) {
 465                 if (client->pid == id)
 466                         return client;
 467                 client = client->next;
 468         }
 469 
 470         return NULL;
 471 }
 472 
 473 static struct agp_controller *agp_find_controller_for_client(pid_t id)
 474 {
 475         struct agp_controller *controller;
 476 
 477         controller = agp_fe.controllers;
 478 
 479         while (controller != NULL) {
 480                 if ((agp_find_client_in_controller(controller, id)) != NULL)
 481                         return controller;
 482                 controller = controller->next;
 483         }
 484 
 485         return NULL;
 486 }
 487 
 488 struct agp_client *agp_find_client_by_pid(pid_t id)
 489 {
 490         struct agp_client *temp;
 491 
 492         if (agp_fe.current_controller == NULL)
 493                 return NULL;
 494 
 495         temp = agp_find_client_in_controller(agp_fe.current_controller, id);
 496         return temp;
 497 }
 498 
 499 static void agp_insert_client(struct agp_client *client)
 500 {
 501         struct agp_client *prev_client;
 502 
 503         prev_client = agp_fe.current_controller->clients;
 504         client->next = prev_client;
 505 
 506         if (prev_client != NULL)
 507                 prev_client->prev = client;
 508 
 509         agp_fe.current_controller->clients = client;
 510         agp_fe.current_controller->num_clients++;
 511 }
 512 
 513 struct agp_client *agp_create_client(pid_t id)
 514 {
 515         struct agp_client *new_client;
 516 
 517         new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL);
 518         if (new_client == NULL)
 519                 return NULL;
 520 
 521         new_client->pid = id;
 522         agp_insert_client(new_client);
 523         return new_client;
 524 }
 525 
 526 int agp_remove_client(pid_t id)
 527 {
 528         struct agp_client *client;
 529         struct agp_client *prev_client;
 530         struct agp_client *next_client;
 531         struct agp_controller *controller;
 532 
 533         controller = agp_find_controller_for_client(id);
 534         if (controller == NULL)
 535                 return -EINVAL;
 536 
 537         client = agp_find_client_in_controller(controller, id);
 538         if (client == NULL)
 539                 return -EINVAL;
 540 
 541         prev_client = client->prev;
 542         next_client = client->next;
 543 
 544         if (prev_client != NULL) {
 545                 prev_client->next = next_client;
 546                 if (next_client != NULL)
 547                         next_client->prev = prev_client;
 548 
 549         } else {
 550                 if (next_client != NULL)
 551                         next_client->prev = NULL;
 552                 controller->clients = next_client;
 553         }
 554 
 555         controller->num_clients--;
 556         agp_remove_seg_from_client(client);
 557         kfree(client);
 558         return 0;
 559 }
 560 
 561 /* End - Routines for managing client lists */
 562 
 563 /* File Operations */
 564 
 565 static int agp_mmap(struct file *file, struct vm_area_struct *vma)
 566 {
 567         unsigned int size, current_size;
 568         unsigned long offset;
 569         struct agp_client *client;
 570         struct agp_file_private *priv = file->private_data;
 571         struct agp_kern_info kerninfo;
 572 
 573         mutex_lock(&(agp_fe.agp_mutex));
 574 
 575         if (agp_fe.backend_acquired != true)
 576                 goto out_eperm;
 577 
 578         if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
 579                 goto out_eperm;
 580 
 581         agp_copy_info(agp_bridge, &kerninfo);
 582         size = vma->vm_end - vma->vm_start;
 583         current_size = kerninfo.aper_size;
 584         current_size = current_size * 0x100000;
 585         offset = vma->vm_pgoff << PAGE_SHIFT;
 586         DBG("%lx:%lx", offset, offset+size);
 587 
 588         if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
 589                 if ((size + offset) > current_size)
 590                         goto out_inval;
 591 
 592                 client = agp_find_client_by_pid(current->pid);
 593 
 594                 if (client == NULL)
 595                         goto out_eperm;
 596 
 597                 if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
 598                         goto out_inval;
 599 
 600                 DBG("client vm_ops=%p", kerninfo.vm_ops);
 601                 if (kerninfo.vm_ops) {
 602                         vma->vm_ops = kerninfo.vm_ops;
 603                 } else if (io_remap_pfn_range(vma, vma->vm_start,
 604                                 (kerninfo.aper_base + offset) >> PAGE_SHIFT,
 605                                 size,
 606                                 pgprot_writecombine(vma->vm_page_prot))) {
 607                         goto out_again;
 608                 }
 609                 mutex_unlock(&(agp_fe.agp_mutex));
 610                 return 0;
 611         }
 612 
 613         if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
 614                 if (size != current_size)
 615                         goto out_inval;
 616 
 617                 DBG("controller vm_ops=%p", kerninfo.vm_ops);
 618                 if (kerninfo.vm_ops) {
 619                         vma->vm_ops = kerninfo.vm_ops;
 620                 } else if (io_remap_pfn_range(vma, vma->vm_start,
 621                                 kerninfo.aper_base >> PAGE_SHIFT,
 622                                 size,
 623                                 pgprot_writecombine(vma->vm_page_prot))) {
 624                         goto out_again;
 625                 }
 626                 mutex_unlock(&(agp_fe.agp_mutex));
 627                 return 0;
 628         }
 629 
 630 out_eperm:
 631         mutex_unlock(&(agp_fe.agp_mutex));
 632         return -EPERM;
 633 
 634 out_inval:
 635         mutex_unlock(&(agp_fe.agp_mutex));
 636         return -EINVAL;
 637 
 638 out_again:
 639         mutex_unlock(&(agp_fe.agp_mutex));
 640         return -EAGAIN;
 641 }
 642 
 643 static int agp_release(struct inode *inode, struct file *file)
 644 {
 645         struct agp_file_private *priv = file->private_data;
 646 
 647         mutex_lock(&(agp_fe.agp_mutex));
 648 
 649         DBG("priv=%p", priv);
 650 
 651         if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
 652                 struct agp_controller *controller;
 653 
 654                 controller = agp_find_controller_by_pid(priv->my_pid);
 655 
 656                 if (controller != NULL) {
 657                         if (controller == agp_fe.current_controller)
 658                                 agp_controller_release_current(controller, priv);
 659                         agp_remove_controller(controller);
 660                         controller = NULL;
 661                 }
 662         }
 663 
 664         if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
 665                 agp_remove_client(priv->my_pid);
 666 
 667         agp_remove_file_private(priv);
 668         kfree(priv);
 669         file->private_data = NULL;
 670         mutex_unlock(&(agp_fe.agp_mutex));
 671         return 0;
 672 }
 673 
 674 static int agp_open(struct inode *inode, struct file *file)
 675 {
 676         int minor = iminor(inode);
 677         struct agp_file_private *priv;
 678         struct agp_client *client;
 679 
 680         if (minor != AGPGART_MINOR)
 681                 return -ENXIO;
 682 
 683         mutex_lock(&(agp_fe.agp_mutex));
 684 
 685         priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
 686         if (priv == NULL) {
 687                 mutex_unlock(&(agp_fe.agp_mutex));
 688                 return -ENOMEM;
 689         }
 690 
 691         set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
 692         priv->my_pid = current->pid;
 693 
 694         if (capable(CAP_SYS_RAWIO))
 695                 /* Root priv, can be controller */
 696                 set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
 697 
 698         client = agp_find_client_by_pid(current->pid);
 699 
 700         if (client != NULL) {
 701                 set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
 702                 set_bit(AGP_FF_IS_VALID, &priv->access_flags);
 703         }
 704         file->private_data = (void *) priv;
 705         agp_insert_file_private(priv);
 706         DBG("private=%p, client=%p", priv, client);
 707 
 708         mutex_unlock(&(agp_fe.agp_mutex));
 709 
 710         return 0;
 711 }
 712 
 713 static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
 714 {
 715         struct agp_info userinfo;
 716         struct agp_kern_info kerninfo;
 717 
 718         agp_copy_info(agp_bridge, &kerninfo);
 719 
 720         memset(&userinfo, 0, sizeof(userinfo));
 721         userinfo.version.major = kerninfo.version.major;
 722         userinfo.version.minor = kerninfo.version.minor;
 723         userinfo.bridge_id = kerninfo.device->vendor |
 724             (kerninfo.device->device << 16);
 725         userinfo.agp_mode = kerninfo.mode;
 726         userinfo.aper_base = kerninfo.aper_base;
 727         userinfo.aper_size = kerninfo.aper_size;
 728         userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
 729         userinfo.pg_used = kerninfo.current_memory;
 730 
 731         if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
 732                 return -EFAULT;
 733 
 734         return 0;
 735 }
 736 
 737 int agpioc_acquire_wrap(struct agp_file_private *priv)
 738 {
 739         struct agp_controller *controller;
 740 
 741         DBG("");
 742 
 743         if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
 744                 return -EPERM;
 745 
 746         if (agp_fe.current_controller != NULL)
 747                 return -EBUSY;
 748 
 749         if (!agp_bridge)
 750                 return -ENODEV;
 751 
 752         if (atomic_read(&agp_bridge->agp_in_use))
 753                 return -EBUSY;
 754 
 755         atomic_inc(&agp_bridge->agp_in_use);
 756 
 757         agp_fe.backend_acquired = true;
 758 
 759         controller = agp_find_controller_by_pid(priv->my_pid);
 760 
 761         if (controller != NULL) {
 762                 agp_controller_make_current(controller);
 763         } else {
 764                 controller = agp_create_controller(priv->my_pid);
 765 
 766                 if (controller == NULL) {
 767                         agp_fe.backend_acquired = false;
 768                         agp_backend_release(agp_bridge);
 769                         return -ENOMEM;
 770                 }
 771                 agp_insert_controller(controller);
 772                 agp_controller_make_current(controller);
 773         }
 774 
 775         set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
 776         set_bit(AGP_FF_IS_VALID, &priv->access_flags);
 777         return 0;
 778 }
 779 
 780 int agpioc_release_wrap(struct agp_file_private *priv)
 781 {
 782         DBG("");
 783         agp_controller_release_current(agp_fe.current_controller, priv);
 784         return 0;
 785 }
 786 
 787 int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
 788 {
 789         struct agp_setup mode;
 790 
 791         DBG("");
 792         if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
 793                 return -EFAULT;
 794 
 795         agp_enable(agp_bridge, mode.agp_mode);
 796         return 0;
 797 }
 798 
 799 static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
 800 {
 801         struct agp_region reserve;
 802         struct agp_client *client;
 803         struct agp_file_private *client_priv;
 804 
 805         DBG("");
 806         if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
 807                 return -EFAULT;
 808 
 809         if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
 810                 return -EFAULT;
 811 
 812         client = agp_find_client_by_pid(reserve.pid);
 813 
 814         if (reserve.seg_count == 0) {
 815                 /* remove a client */
 816                 client_priv = agp_find_private(reserve.pid);
 817 
 818                 if (client_priv != NULL) {
 819                         set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
 820                         set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
 821                 }
 822                 if (client == NULL) {
 823                         /* client is already removed */
 824                         return 0;
 825                 }
 826                 return agp_remove_client(reserve.pid);
 827         } else {
 828                 struct agp_segment *segment;
 829 
 830                 if (reserve.seg_count >= 16384)
 831                         return -EINVAL;
 832 
 833                 segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
 834                                   GFP_KERNEL);
 835 
 836                 if (segment == NULL)
 837                         return -ENOMEM;
 838 
 839                 if (copy_from_user(segment, (void __user *) reserve.seg_list,
 840                                    sizeof(struct agp_segment) * reserve.seg_count)) {
 841                         kfree(segment);
 842                         return -EFAULT;
 843                 }
 844                 reserve.seg_list = segment;
 845 
 846                 if (client == NULL) {
 847                         /* Create the client and add the segment */
 848                         client = agp_create_client(reserve.pid);
 849 
 850                         if (client == NULL) {
 851                                 kfree(segment);
 852                                 return -ENOMEM;
 853                         }
 854                         client_priv = agp_find_private(reserve.pid);
 855 
 856                         if (client_priv != NULL) {
 857                                 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
 858                                 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
 859                         }
 860                 }
 861                 return agp_create_segment(client, &reserve);
 862         }
 863         /* Will never really happen */
 864         return -EINVAL;
 865 }
 866 
 867 int agpioc_protect_wrap(struct agp_file_private *priv)
 868 {
 869         DBG("");
 870         /* This function is not currently implemented */
 871         return -EINVAL;
 872 }
 873 
 874 static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
 875 {
 876         struct agp_memory *memory;
 877         struct agp_allocate alloc;
 878 
 879         DBG("");
 880         if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
 881                 return -EFAULT;
 882 
 883         if (alloc.type >= AGP_USER_TYPES)
 884                 return -EINVAL;
 885 
 886         memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
 887 
 888         if (memory == NULL)
 889                 return -ENOMEM;
 890 
 891         alloc.key = memory->key;
 892         alloc.physical = memory->physical;
 893 
 894         if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
 895                 agp_free_memory_wrap(memory);
 896                 return -EFAULT;
 897         }
 898         return 0;
 899 }
 900 
 901 int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
 902 {
 903         struct agp_memory *memory;
 904 
 905         DBG("");
 906         memory = agp_find_mem_by_key(arg);
 907 
 908         if (memory == NULL)
 909                 return -EINVAL;
 910 
 911         agp_free_memory_wrap(memory);
 912         return 0;
 913 }
 914 
 915 static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
 916 {
 917         struct agp_bind bind_info;
 918         struct agp_memory *memory;
 919 
 920         DBG("");
 921         if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
 922                 return -EFAULT;
 923 
 924         memory = agp_find_mem_by_key(bind_info.key);
 925 
 926         if (memory == NULL)
 927                 return -EINVAL;
 928 
 929         return agp_bind_memory(memory, bind_info.pg_start);
 930 }
 931 
 932 static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
 933 {
 934         struct agp_memory *memory;
 935         struct agp_unbind unbind;
 936 
 937         DBG("");
 938         if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
 939                 return -EFAULT;
 940 
 941         memory = agp_find_mem_by_key(unbind.key);
 942 
 943         if (memory == NULL)
 944                 return -EINVAL;
 945 
 946         return agp_unbind_memory(memory);
 947 }
 948 
 949 static long agp_ioctl(struct file *file,
 950                      unsigned int cmd, unsigned long arg)
 951 {
 952         struct agp_file_private *curr_priv = file->private_data;
 953         int ret_val = -ENOTTY;
 954 
 955         DBG("priv=%p, cmd=%x", curr_priv, cmd);
 956         mutex_lock(&(agp_fe.agp_mutex));
 957 
 958         if ((agp_fe.current_controller == NULL) &&
 959             (cmd != AGPIOC_ACQUIRE)) {
 960                 ret_val = -EINVAL;
 961                 goto ioctl_out;
 962         }
 963         if ((agp_fe.backend_acquired != true) &&
 964             (cmd != AGPIOC_ACQUIRE)) {
 965                 ret_val = -EBUSY;
 966                 goto ioctl_out;
 967         }
 968         if (cmd != AGPIOC_ACQUIRE) {
 969                 if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
 970                         ret_val = -EPERM;
 971                         goto ioctl_out;
 972                 }
 973                 /* Use the original pid of the controller,
 974                  * in case it's threaded */
 975 
 976                 if (agp_fe.current_controller->pid != curr_priv->my_pid) {
 977                         ret_val = -EBUSY;
 978                         goto ioctl_out;
 979                 }
 980         }
 981 
 982         switch (cmd) {
 983         case AGPIOC_INFO:
 984                 ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
 985                 break;
 986 
 987         case AGPIOC_ACQUIRE:
 988                 ret_val = agpioc_acquire_wrap(curr_priv);
 989                 break;
 990 
 991         case AGPIOC_RELEASE:
 992                 ret_val = agpioc_release_wrap(curr_priv);
 993                 break;
 994 
 995         case AGPIOC_SETUP:
 996                 ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
 997                 break;
 998 
 999         case AGPIOC_RESERVE:
1000                 ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
1001                 break;
1002 
1003         case AGPIOC_PROTECT:
1004                 ret_val = agpioc_protect_wrap(curr_priv);
1005                 break;
1006 
1007         case AGPIOC_ALLOCATE:
1008                 ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
1009                 break;
1010 
1011         case AGPIOC_DEALLOCATE:
1012                 ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
1013                 break;
1014 
1015         case AGPIOC_BIND:
1016                 ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
1017                 break;
1018 
1019         case AGPIOC_UNBIND:
1020                 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
1021                 break;
1022                
1023         case AGPIOC_CHIPSET_FLUSH:
1024                 break;
1025         }
1026 
1027 ioctl_out:
1028         DBG("ioctl returns %d\n", ret_val);
1029         mutex_unlock(&(agp_fe.agp_mutex));
1030         return ret_val;
1031 }
1032 
1033 static const struct file_operations agp_fops =
1034 {
1035         .owner          = THIS_MODULE,
1036         .llseek         = no_llseek,
1037         .unlocked_ioctl = agp_ioctl,
1038 #ifdef CONFIG_COMPAT
1039         .compat_ioctl   = compat_agp_ioctl,
1040 #endif
1041         .mmap           = agp_mmap,
1042         .open           = agp_open,
1043         .release        = agp_release,
1044 };
1045 
1046 static struct miscdevice agp_miscdev =
1047 {
1048         .minor  = AGPGART_MINOR,
1049         .name   = "agpgart",
1050         .fops   = &agp_fops
1051 };
1052 
1053 int agp_frontend_initialize(void)
1054 {
1055         memset(&agp_fe, 0, sizeof(struct agp_front_data));
1056         mutex_init(&(agp_fe.agp_mutex));
1057 
1058         if (misc_register(&agp_miscdev)) {
1059                 printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
1060                 return -EIO;
1061         }
1062         return 0;
1063 }
1064 
1065 void agp_frontend_cleanup(void)
1066 {
1067         misc_deregister(&agp_miscdev);
1068 }

/* [<][>][^][v][top][bottom][index][help] */