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