|
Lines 15-20
Link Here
|
| 15 |
#include "nv_compiler.h" |
15 |
#include "nv_compiler.h" |
| 16 |
#include "os-agp.h" |
16 |
#include "os-agp.h" |
| 17 |
|
17 |
|
|
|
18 |
MODULE_LICENSE("NVIDIA"); |
| 18 |
|
19 |
|
| 19 |
/* |
20 |
/* |
| 20 |
* our global state; one per device |
21 |
* our global state; one per device |
|
Lines 33-64
Link Here
|
| 33 |
*/ |
34 |
*/ |
| 34 |
|
35 |
|
| 35 |
nv_linux_state_t nv_ctl_device = { { 0 } }; |
36 |
nv_linux_state_t nv_ctl_device = { { 0 } }; |
| 36 |
void *nv_ctl_wqueue = NULL; |
37 |
wait_queue_head_t nv_ctl_waitqueue; |
| 37 |
|
38 |
|
| 38 |
// keep track of opened clients and their process id so they |
39 |
// keep track of opened clients and their process id so they |
| 39 |
// can be free'd up on abnormal close |
40 |
// can be free'd up on abnormal close |
| 40 |
nv_client_t nv_clients[NV_MAX_CLIENTS]; |
41 |
nv_client_t nv_clients[NV_MAX_CLIENTS]; |
| 41 |
struct tq_struct nv_bottom_halves[NV_MAX_CLIENTS]; |
|
|
| 42 |
|
42 |
|
| 43 |
#ifdef CONFIG_PROC_FS |
43 |
#ifdef CONFIG_PROC_FS |
| 44 |
struct proc_dir_entry *proc_nvidia; |
44 |
struct proc_dir_entry *proc_nvidia; |
| 45 |
#endif |
45 |
#endif |
| 46 |
|
46 |
|
| 47 |
#ifdef CONFIG_DEVFS_FS |
47 |
#ifdef CONFIG_DEVFS_FS |
| 48 |
devfs_handle_t nv_dev_handle[NV_MAX_DEVICES]; |
48 |
devfs_handle_t nv_devfs_handles[NV_MAX_DEVICES+1]; |
| 49 |
devfs_handle_t nv_ctl_handle; |
|
|
| 50 |
#endif |
49 |
#endif |
| 51 |
|
50 |
|
| 52 |
/* |
|
|
| 53 |
* pick apart our minor device number |
| 54 |
* low 3 bits is NV device |
| 55 |
* if 255, then its the control device |
| 56 |
*/ |
| 57 |
|
| 58 |
#define NV_DEVICE_NUMBER(_minor) ((_minor) & 0x0f) |
| 59 |
#define NV_DEVICE_IS_CONTROL_DEVICE(_minor) \ |
| 60 |
(((_minor) & 0xFF) == 0xFF) |
| 61 |
|
| 62 |
// #define NV_DBG_MEM 1 |
51 |
// #define NV_DBG_MEM 1 |
| 63 |
#undef NV_DBG_MEM |
52 |
#undef NV_DBG_MEM |
| 64 |
|
53 |
|
|
Lines 121-130
Link Here
|
| 121 |
*** EXPORTS to Linux Kernel |
110 |
*** EXPORTS to Linux Kernel |
| 122 |
***/ |
111 |
***/ |
| 123 |
|
112 |
|
| 124 |
/* linux module interface functions (called by linux kernel) */ |
|
|
| 125 |
int init_module(void); |
| 126 |
void cleanup_module(void); |
| 127 |
|
| 128 |
/* nv_kern_ functions, interfaces used by linux kernel */ |
113 |
/* nv_kern_ functions, interfaces used by linux kernel */ |
| 129 |
void nv_kern_vma_open(struct vm_area_struct *vma); |
114 |
void nv_kern_vma_open(struct vm_area_struct *vma); |
| 130 |
void nv_kern_vma_release(struct vm_area_struct *vma); |
115 |
void nv_kern_vma_release(struct vm_area_struct *vma); |
|
Lines 135-141
Link Here
|
| 135 |
unsigned int nv_kern_poll(struct file *, poll_table *); |
120 |
unsigned int nv_kern_poll(struct file *, poll_table *); |
| 136 |
int nv_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
121 |
int nv_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
| 137 |
void nv_kern_bh(void *); |
122 |
void nv_kern_bh(void *); |
| 138 |
void nv_kern_isr(int, void *, struct pt_regs *); |
123 |
void nv_kern_isr_bh(unsigned long); |
|
|
124 |
irqreturn_t nv_kern_isr(int, void *, struct pt_regs *); |
| 139 |
void nv_kern_rc_timer(unsigned long); |
125 |
void nv_kern_rc_timer(unsigned long); |
| 140 |
#ifdef CONFIG_PM |
126 |
#ifdef CONFIG_PM |
| 141 |
int nv_kern_pm(struct pm_dev *dev, pm_request_t rqst, void *data); |
127 |
int nv_kern_pm(struct pm_dev *dev, pm_request_t rqst, void *data); |
|
Lines 158-163
Link Here
|
| 158 |
/* character driver entry points */ |
144 |
/* character driver entry points */ |
| 159 |
|
145 |
|
| 160 |
static struct file_operations nv_fops = { |
146 |
static struct file_operations nv_fops = { |
|
|
147 |
owner: THIS_MODULE, |
| 161 |
poll: nv_kern_poll, |
148 |
poll: nv_kern_poll, |
| 162 |
ioctl: nv_kern_ioctl, |
149 |
ioctl: nv_kern_ioctl, |
| 163 |
mmap: nv_kern_mmap, |
150 |
mmap: nv_kern_mmap, |
|
Lines 329-336
Link Here
|
| 329 |
{ |
316 |
{ |
| 330 |
nv_printf(NV_DBG_MEMINFO, " 0x%x (0x%x): count %d flags 0x%x\n", |
317 |
nv_printf(NV_DBG_MEMINFO, " 0x%x (0x%x): count %d flags 0x%x\n", |
| 331 |
page_ptr->phys_addr, page_ptr->dma_addr, |
318 |
page_ptr->phys_addr, page_ptr->dma_addr, |
| 332 |
(GET_MAP_NR(page_ptr->phys_addr))->count, |
319 |
(virt_to_page(__va(page_ptr->phys_addr)))->count, |
| 333 |
(GET_MAP_NR(page_ptr->phys_addr))->flags); |
320 |
(virt_to_page(__va(page_ptr->phys_addr)))->flags); |
| 334 |
num_pages--; |
321 |
num_pages--; |
| 335 |
page_ptr++; |
322 |
page_ptr++; |
| 336 |
} |
323 |
} |
|
Lines 401-407
Link Here
|
| 401 |
phys_addr = virt_to_phys((void *) virt_addr); |
388 |
phys_addr = virt_to_phys((void *) virt_addr); |
| 402 |
|
389 |
|
| 403 |
/* lock the page for dma purposes */ |
390 |
/* lock the page for dma purposes */ |
| 404 |
mem_map_reserve(GET_MAP_NR(phys_addr)); |
391 |
SetPageReserved(virt_to_page(__va(phys_addr))); |
| 405 |
|
392 |
|
| 406 |
page_ptr->phys_addr = phys_addr; |
393 |
page_ptr->phys_addr = phys_addr; |
| 407 |
page_ptr->virt_addr = virt_addr; |
394 |
page_ptr->virt_addr = virt_addr; |
|
Lines 447-453
Link Here
|
| 447 |
// but if we failed pci_map_sg, make sure to free this page |
434 |
// but if we failed pci_map_sg, make sure to free this page |
| 448 |
if (page_ptr->virt_addr) |
435 |
if (page_ptr->virt_addr) |
| 449 |
{ |
436 |
{ |
| 450 |
mem_map_unreserve(GET_MAP_NR(page_ptr->phys_addr)); |
437 |
ClearPageReserved(virt_to_page(__va(page_ptr->phys_addr))); |
| 451 |
NV_SET_PAGE_ATTRIB_CACHED(page_ptr); |
438 |
NV_SET_PAGE_ATTRIB_CACHED(page_ptr); |
| 452 |
#if defined(NVCPU_X86_64) |
439 |
#if defined(NVCPU_X86_64) |
| 453 |
// only unmap the page if it really was mapped through |
440 |
// only unmap the page if it really was mapped through |
|
Lines 481-487
Link Here
|
| 481 |
|
468 |
|
| 482 |
while (pages_left) |
469 |
while (pages_left) |
| 483 |
{ |
470 |
{ |
| 484 |
mem_map_unreserve(GET_MAP_NR(page_ptr->phys_addr)); |
471 |
ClearPageReserved(virt_to_page(__va(page_ptr->phys_addr))); |
| 485 |
page_ptr++; |
472 |
page_ptr++; |
| 486 |
pages_left--; |
473 |
pages_left--; |
| 487 |
} |
474 |
} |
|
Lines 616-622
Link Here
|
| 616 |
return 0; |
603 |
return 0; |
| 617 |
} |
604 |
} |
| 618 |
|
605 |
|
| 619 |
static struct pci_dev* nvos_find_agp_by_class(unsigned int class) |
606 |
struct pci_dev* nvos_find_agp_by_class(unsigned int class) |
| 620 |
{ |
607 |
{ |
| 621 |
struct pci_dev *dev, *fn; |
608 |
struct pci_dev *dev, *fn; |
| 622 |
u8 cap_ptr; |
609 |
u8 cap_ptr; |
|
Lines 674-684
Link Here
|
| 674 |
nv_linux_state_t *nvl; |
661 |
nv_linux_state_t *nvl; |
| 675 |
nv_linux_state_t *nv_max_devices; |
662 |
nv_linux_state_t *nv_max_devices; |
| 676 |
|
663 |
|
| 677 |
#if defined (KERNEL_2_2) |
|
|
| 678 |
struct proc_dir_entry *proc_root_driver; |
| 679 |
proc_root_driver = create_proc_entry("driver", flags, &proc_root); |
| 680 |
#endif |
| 681 |
|
| 682 |
proc_nvidia = create_proc_entry("nvidia", flags, proc_root_driver); |
664 |
proc_nvidia = create_proc_entry("nvidia", flags, proc_root_driver); |
| 683 |
proc_nvidia_cards = create_proc_entry("cards", flags, proc_nvidia); |
665 |
proc_nvidia_cards = create_proc_entry("cards", flags, proc_nvidia); |
| 684 |
proc_nvidia_agp = create_proc_entry("agp", flags, proc_nvidia); |
666 |
proc_nvidia_agp = create_proc_entry("agp", flags, proc_nvidia); |
|
Lines 740-748
Link Here
|
| 740 |
{ |
722 |
{ |
| 741 |
#ifdef CONFIG_PROC_FS |
723 |
#ifdef CONFIG_PROC_FS |
| 742 |
nvos_proc_remove_all(proc_nvidia); |
724 |
nvos_proc_remove_all(proc_nvidia); |
| 743 |
#if defined (KERNEL_2_2) |
|
|
| 744 |
remove_proc_entry("driver", &proc_root); |
| 745 |
#endif |
| 746 |
#endif |
725 |
#endif |
| 747 |
} |
726 |
} |
| 748 |
|
727 |
|
|
Lines 831-839
Link Here
|
| 831 |
*** EXPORTS to Linux Kernel |
810 |
*** EXPORTS to Linux Kernel |
| 832 |
***/ |
811 |
***/ |
| 833 |
|
812 |
|
| 834 |
int init_module(void) |
813 |
static int __init nvidia_init_module(void) |
| 835 |
{ |
814 |
{ |
| 836 |
nv_linux_state_t *nvl; |
|
|
| 837 |
int rc, i; |
815 |
int rc, i; |
| 838 |
|
816 |
|
| 839 |
memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); |
817 |
memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); |
|
Lines 846-852
Link Here
|
| 846 |
|
824 |
|
| 847 |
nv_printf(NV_DBG_ERRORS, "nvidia: loading %s\n", pNVRM_ID); |
825 |
nv_printf(NV_DBG_ERRORS, "nvidia: loading %s\n", pNVRM_ID); |
| 848 |
|
826 |
|
| 849 |
#ifdef CONFIG_DEVFS_FS |
827 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
| 850 |
rc = devfs_register_chrdev(nv_major, "nvidia", &nv_fops); |
828 |
rc = devfs_register_chrdev(nv_major, "nvidia", &nv_fops); |
| 851 |
#else |
829 |
#else |
| 852 |
rc = register_chrdev(nv_major, "nvidia", &nv_fops); |
830 |
rc = register_chrdev(nv_major, "nvidia", &nv_fops); |
|
Lines 858-891
Link Here
|
| 858 |
} |
836 |
} |
| 859 |
|
837 |
|
| 860 |
#ifdef CONFIG_DEVFS_FS |
838 |
#ifdef CONFIG_DEVFS_FS |
| 861 |
memset(nv_dev_handle, 0, sizeof(devfs_handle_t) * NV_MAX_DEVICES); |
|
|
| 862 |
do { |
839 |
do { |
|
|
840 |
/* |
| 841 |
* XXX This code isn't pretty, but neither is dealing with the |
| 842 |
* various Linux devfs implemenation(s). While Linux APIs are |
| 843 |
* known to be anything but stable and oftentimes anything but |
| 844 |
* well designed, the devfs interface has been more painful to |
| 845 |
* deal with than most other APIs. |
| 846 |
*/ |
| 863 |
char name[10]; |
847 |
char name[10]; |
| 864 |
|
848 |
|
| 865 |
nv_ctl_handle = devfs_register(NULL, "nvidiactl", |
849 |
nv_devfs_handles[0] = NV_DEVFS_REGISTER("nvidiactl", 255); |
| 866 |
DEVFS_FL_DEFAULT, nv_major, 255, |
|
|
| 867 |
S_IFCHR | S_IRUGO | S_IWUGO, |
| 868 |
&nv_fops, NULL); |
| 869 |
|
850 |
|
| 870 |
for (i = 0; i < num_nv_devices; i++) { |
851 |
for (i = 0; i < num_nv_devices; i++) { |
| 871 |
sprintf(name, "nvidia%d", i); |
852 |
sprintf(name, "nvidia%d", i); |
| 872 |
nv_dev_handle[i] = devfs_register(NULL, name, |
853 |
nv_devfs_handles[i+1] = NV_DEVFS_REGISTER(name, i); |
| 873 |
DEVFS_FL_DEFAULT, nv_major, i, |
|
|
| 874 |
S_IFCHR | S_IRUGO | S_IWUGO, |
| 875 |
&nv_fops, NULL); |
| 876 |
} |
854 |
} |
| 877 |
} while(0); |
855 |
} while(0); |
| 878 |
#endif |
856 |
#endif |
| 879 |
|
857 |
|
| 880 |
nv_printf(NV_DBG_INFO, "init_module: major number %d\n", nv_major); |
858 |
nv_printf(NV_DBG_INFO, "nvidia_init_module: major number %d\n", nv_major); |
| 881 |
|
859 |
|
| 882 |
// init all the bottom half structures |
860 |
/* instantiate tasklets */ |
| 883 |
for (nvl = nv_linux_devices; nvl < nv_linux_devices + NV_MAX_DEVICES; nvl++) |
861 |
for (i = 0; i < NV_MAX_DEVICES; i++) { |
| 884 |
{ |
862 |
/* |
| 885 |
nvl->bh = &nv_bottom_halves[nvl - nv_linux_devices]; |
863 |
* We keep one tasklet per card to avoid latency issues with more |
| 886 |
nvl->bh->routine = nv_kern_bh; |
864 |
* than one device; no two instances of a single tasklet are ever |
| 887 |
nvl->bh->data = (void *) nvl; |
865 |
* executed concurrently. |
| 888 |
nvl->bh->sync = 0; |
866 |
*/ |
|
|
867 |
atomic_set(&nv_linux_devices[i].tasklet.count, 1); |
| 889 |
} |
868 |
} |
| 890 |
|
869 |
|
| 891 |
// init the nvidia control device |
870 |
// init the nvidia control device |
|
Lines 893-898
Link Here
|
| 893 |
nv_state_t *nv_ctl = NV_STATE_PTR(&nv_ctl_device); |
872 |
nv_state_t *nv_ctl = NV_STATE_PTR(&nv_ctl_device); |
| 894 |
nv_ctl->os_state = (void *) &nv_ctl_device; |
873 |
nv_ctl->os_state = (void *) &nv_ctl_device; |
| 895 |
nv_lock_init_locks(nv_ctl); |
874 |
nv_lock_init_locks(nv_ctl); |
|
|
875 |
init_waitqueue_head(&nv_ctl_waitqueue); |
| 896 |
} |
876 |
} |
| 897 |
|
877 |
|
| 898 |
#ifdef CONFIG_PM |
878 |
#ifdef CONFIG_PM |
|
Lines 919-932
Link Here
|
| 919 |
/* create /proc/driver/nvidia */ |
899 |
/* create /proc/driver/nvidia */ |
| 920 |
nvos_proc_create(); |
900 |
nvos_proc_create(); |
| 921 |
|
901 |
|
| 922 |
#if defined(DEBUG) && !defined(KERNEL_2_2) |
902 |
#if defined(DEBUG) |
| 923 |
inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices); |
903 |
inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices); |
| 924 |
#endif |
904 |
#endif |
| 925 |
|
905 |
|
| 926 |
return 0; |
906 |
return 0; |
| 927 |
|
907 |
|
| 928 |
failed: |
908 |
failed: |
| 929 |
#ifdef CONFIG_DEVFS_FS |
909 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
| 930 |
devfs_unregister_chrdev(nv_major, "nvidia"); |
910 |
devfs_unregister_chrdev(nv_major, "nvidia"); |
| 931 |
#else |
911 |
#else |
| 932 |
unregister_chrdev(nv_major, "nvidia"); |
912 |
unregister_chrdev(nv_major, "nvidia"); |
|
Lines 934-959
Link Here
|
| 934 |
return rc; |
914 |
return rc; |
| 935 |
} |
915 |
} |
| 936 |
|
916 |
|
| 937 |
void cleanup_module(void) |
917 |
static void __exit nvidia_exit_module(void) |
| 938 |
{ |
918 |
{ |
| 939 |
int rc, i; |
919 |
int rc; |
| 940 |
nv_linux_state_t *nvl; |
920 |
nv_linux_state_t *nvl, *max_devices; |
| 941 |
nv_linux_state_t *max_devices; |
|
|
| 942 |
|
921 |
|
| 943 |
/* remove /proc/driver/nvidia */ |
922 |
/* remove /proc/driver/nvidia */ |
| 944 |
nvos_proc_remove(); |
923 |
nvos_proc_remove(); |
| 945 |
|
924 |
|
| 946 |
nv_printf(NV_DBG_INFO, "cleanup_module\n"); |
925 |
nv_printf(NV_DBG_INFO, "nvidia_exit_module\n"); |
| 947 |
|
926 |
|
| 948 |
#if defined(DEBUG) && !defined(KERNEL_2_2) |
927 |
#if defined(DEBUG) |
| 949 |
inter_module_unregister("nv_linux_devices"); |
928 |
inter_module_unregister("nv_linux_devices"); |
| 950 |
#endif |
929 |
#endif |
| 951 |
|
930 |
|
| 952 |
#ifdef CONFIG_PM |
931 |
#ifdef CONFIG_PM |
| 953 |
for (i = 0; i < num_nv_devices; i++) |
932 |
do { |
| 954 |
{ |
933 |
int i; |
| 955 |
pm_unregister(pm_nv_dev[i]); |
934 |
for (i = 0; i < num_nv_devices; i++) { |
| 956 |
} |
935 |
pm_unregister(pm_nv_dev[i]); |
|
|
936 |
} |
| 937 |
} while (0); |
| 957 |
#endif |
938 |
#endif |
| 958 |
|
939 |
|
| 959 |
// Shutdown the resource manager |
940 |
// Shutdown the resource manager |
|
Lines 972-1001
Link Here
|
| 972 |
continue; |
953 |
continue; |
| 973 |
|
954 |
|
| 974 |
nv_printf(NV_DBG_ERRORS, |
955 |
nv_printf(NV_DBG_ERRORS, |
| 975 |
"still have vm que at cleanup_module(): 0x%x to 0x%x\n", |
956 |
"still have vm que at nvidia_exit_module(): 0x%x to 0x%x\n", |
| 976 |
nvl->alloc_queue->vma->vm_start, |
957 |
nvl->alloc_queue->vma->vm_start, |
| 977 |
nvl->alloc_queue->vma->vm_end); |
958 |
nvl->alloc_queue->vma->vm_end); |
| 978 |
} |
959 |
} |
| 979 |
} |
960 |
} |
| 980 |
|
961 |
|
| 981 |
#ifdef CONFIG_DEVFS_FS |
962 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
| 982 |
rc = devfs_unregister_chrdev(nv_major, "nvidia"); |
963 |
rc = devfs_unregister_chrdev(nv_major, "nvidia"); |
| 983 |
#else |
964 |
#else |
| 984 |
rc = unregister_chrdev(nv_major, "nvidia"); |
965 |
rc = unregister_chrdev(nv_major, "nvidia"); |
| 985 |
#endif |
966 |
#endif |
| 986 |
|
967 |
|
| 987 |
if (rc < 0) { |
968 |
if (rc < 0) { |
| 988 |
nv_printf(NV_DBG_ERRORS, "cleanup_module: unregister nv failed\n"); |
969 |
nv_printf(NV_DBG_ERRORS, "nvidia_exit_module: unregister nv failed\n"); |
| 989 |
} |
970 |
} |
| 990 |
|
971 |
|
| 991 |
#ifdef CONFIG_DEVFS_FS |
972 |
#ifdef CONFIG_DEVFS_FS |
| 992 |
do { |
973 |
do { |
| 993 |
int i; |
974 |
int i; |
| 994 |
for (i = 0; nv_dev_handle[i] != 0; i++) { |
975 |
NV_DEVFS_REMOVE_CONTROL(); |
| 995 |
devfs_unregister(nv_dev_handle[i]); |
976 |
for (i = 0; i < num_nv_devices; i++) |
| 996 |
} |
977 |
NV_DEVFS_REMOVE_DEVICE(i); |
| 997 |
} while(0); |
978 |
} while (0); |
| 998 |
devfs_unregister(nv_ctl_handle); |
|
|
| 999 |
#endif |
979 |
#endif |
| 1000 |
|
980 |
|
| 1001 |
#if NV_ENABLE_MEM_TRACKING |
981 |
#if NV_ENABLE_MEM_TRACKING |
|
Lines 1007-1012
Link Here
|
| 1007 |
#endif |
987 |
#endif |
| 1008 |
} |
988 |
} |
| 1009 |
|
989 |
|
|
|
990 |
module_init(nvidia_init_module); |
| 991 |
module_exit(nvidia_exit_module); |
| 1010 |
|
992 |
|
| 1011 |
/* this is only called when the vmas are duplicated. |
993 |
/* this is only called when the vmas are duplicated. |
| 1012 |
* this appears to only happen when the process is cloned to create |
994 |
* this appears to only happen when the process is cloned to create |
|
Lines 1020-1030
Link Here
|
| 1020 |
nv_kern_vma_open(struct vm_area_struct *vma) |
1002 |
nv_kern_vma_open(struct vm_area_struct *vma) |
| 1021 |
{ |
1003 |
{ |
| 1022 |
nv_printf(NV_DBG_MEMINFO, "vma_open for 0x%x - 0x%x, offset 0x%x\n", |
1004 |
nv_printf(NV_DBG_MEMINFO, "vma_open for 0x%x - 0x%x, offset 0x%x\n", |
| 1023 |
vma->vm_start, vma->vm_end, LINUX_VMA_OFFS(vma)); |
1005 |
vma->vm_start, vma->vm_end, NV_VMA_OFFSET(vma)); |
| 1024 |
|
1006 |
|
| 1025 |
if (VMA_PRIVATE(vma)) |
1007 |
if (NV_VMA_PRIVATE(vma)) |
| 1026 |
{ |
1008 |
{ |
| 1027 |
nv_alloc_t *at = (nv_alloc_t *) VMA_PRIVATE(vma); |
1009 |
nv_alloc_t *at = (nv_alloc_t *) NV_VMA_PRIVATE(vma); |
| 1028 |
at->usage_count++; |
1010 |
at->usage_count++; |
| 1029 |
|
1011 |
|
| 1030 |
nv_printf(NV_DBG_MEMINFO, " at 0x%x, usage count %d, page_table 0x%x\n", |
1012 |
nv_printf(NV_DBG_MEMINFO, " at 0x%x, usage count %d, page_table 0x%x\n", |
|
Lines 1032-1039
Link Here
|
| 1032 |
|
1014 |
|
| 1033 |
nvos_list_page_count(at->page_table, at->num_pages); |
1015 |
nvos_list_page_count(at->page_table, at->num_pages); |
| 1034 |
} |
1016 |
} |
| 1035 |
|
|
|
| 1036 |
MOD_INC_USE_COUNT; |
| 1037 |
} |
1017 |
} |
| 1038 |
|
1018 |
|
| 1039 |
|
1019 |
|
|
Lines 1041-1051
Link Here
|
| 1041 |
nv_kern_vma_release(struct vm_area_struct *vma) |
1021 |
nv_kern_vma_release(struct vm_area_struct *vma) |
| 1042 |
{ |
1022 |
{ |
| 1043 |
nv_printf(NV_DBG_MEMINFO, "vma_release for 0x%x - 0x%x, offset 0x%x\n", |
1023 |
nv_printf(NV_DBG_MEMINFO, "vma_release for 0x%x - 0x%x, offset 0x%x\n", |
| 1044 |
vma->vm_start, vma->vm_end, LINUX_VMA_OFFS(vma)); |
1024 |
vma->vm_start, vma->vm_end, NV_VMA_OFFSET(vma)); |
| 1045 |
|
1025 |
|
| 1046 |
if (VMA_PRIVATE(vma)) |
1026 |
if (NV_VMA_PRIVATE(vma)) |
| 1047 |
{ |
1027 |
{ |
| 1048 |
nv_alloc_t *at = (nv_alloc_t *) VMA_PRIVATE(vma); |
1028 |
nv_alloc_t *at = (nv_alloc_t *) NV_VMA_PRIVATE(vma); |
| 1049 |
|
1029 |
|
| 1050 |
at->usage_count--; |
1030 |
at->usage_count--; |
| 1051 |
|
1031 |
|
|
Lines 1063-1097
Link Here
|
| 1063 |
if (at->page_table) |
1043 |
if (at->page_table) |
| 1064 |
nvos_unlock_pages(at); |
1044 |
nvos_unlock_pages(at); |
| 1065 |
nvos_free_alloc(at); |
1045 |
nvos_free_alloc(at); |
| 1066 |
VMA_PRIVATE(vma) = NULL; |
1046 |
NV_VMA_PRIVATE(vma) = NULL; |
| 1067 |
} |
1047 |
} |
| 1068 |
} |
1048 |
} |
| 1069 |
|
|
|
| 1070 |
MOD_DEC_USE_COUNT; |
| 1071 |
} |
1049 |
} |
| 1072 |
|
1050 |
|
| 1073 |
|
1051 |
|
| 1074 |
/* at this point, this code just plain won't work with 2.2 kernels. |
|
|
| 1075 |
* additionally, only ia64 & the 460GX need a nopage handler, and 2.2 doesn't |
| 1076 |
* work on ia64 anyways. It's expected that at some point other agp chipsets |
| 1077 |
* will work similar to the 460GX (AGP 3.0 spec), so pre-emptively make sure |
| 1078 |
* this works on our standard ia32 driver. |
| 1079 |
*/ |
| 1080 |
#if !defined(KERNEL_2_2) |
| 1081 |
|
| 1082 |
/* AGP allocations under the 460GX are not mapped to the aperture |
1052 |
/* AGP allocations under the 460GX are not mapped to the aperture |
| 1083 |
* addresses by the CPU. This nopage handler will fault on CPU |
1053 |
* addresses by the CPU. This nopage handler will fault on CPU |
| 1084 |
* accesses to AGP memory and map the address to the correct page. |
1054 |
* accesses to AGP memory and map the address to the correct page. |
| 1085 |
*/ |
1055 |
*/ |
| 1086 |
struct page *nv_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) |
1056 |
struct page *nv_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) |
| 1087 |
{ |
1057 |
{ |
|
|
1058 |
#if defined(NVCPU_IA64) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)) |
| 1088 |
nv_alloc_t *at, *tmp; |
1059 |
nv_alloc_t *at, *tmp; |
| 1089 |
nv_linux_state_t *nvl; |
1060 |
nv_linux_state_t *nvl; |
| 1090 |
nv_state_t *nv; |
1061 |
nv_state_t *nv; |
| 1091 |
struct page *page_ptr; |
1062 |
struct page *page_ptr; |
| 1092 |
int rm_status, index; |
1063 |
int rm_status, index; |
| 1093 |
|
1064 |
|
| 1094 |
at = VMA_PRIVATE(vma); |
1065 |
at = NV_VMA_PRIVATE(vma); |
| 1095 |
if (at == NULL) |
1066 |
if (at == NULL) |
| 1096 |
{ |
1067 |
{ |
| 1097 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called without an at: " |
1068 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called without an at: " |
|
Lines 1130-1136
Link Here
|
| 1130 |
// far again |
1101 |
// far again |
| 1131 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called on a freed" |
1102 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called on a freed" |
| 1132 |
"address: vm_start 0x%x, at 0x%x\n", vma->vm_start, at); |
1103 |
"address: vm_start 0x%x, at 0x%x\n", vma->vm_start, at); |
| 1133 |
VMA_PRIVATE(vma) = NULL; |
1104 |
NV_VMA_PRIVATE(vma) = NULL; |
| 1134 |
return NOPAGE_SIGBUS; |
1105 |
return NOPAGE_SIGBUS; |
| 1135 |
} |
1106 |
} |
| 1136 |
|
1107 |
|
|
Lines 1154-1168
Link Here
|
| 1154 |
at->page_table[index].virt_addr = (unsigned long) __va(page_to_pfn(page_ptr) << PAGE_SHIFT); |
1125 |
at->page_table[index].virt_addr = (unsigned long) __va(page_to_pfn(page_ptr) << PAGE_SHIFT); |
| 1155 |
|
1126 |
|
| 1156 |
return page_ptr; |
1127 |
return page_ptr; |
| 1157 |
} |
|
|
| 1158 |
#endif |
1128 |
#endif |
|
|
1129 |
return NOPAGE_SIGBUS; |
| 1130 |
} |
| 1159 |
|
1131 |
|
| 1160 |
struct vm_operations_struct nv_vm_ops = { |
1132 |
struct vm_operations_struct nv_vm_ops = { |
| 1161 |
nv_kern_vma_open, |
1133 |
nv_kern_vma_open, |
| 1162 |
nv_kern_vma_release, /* "close" */ |
1134 |
nv_kern_vma_release, /* "close" */ |
| 1163 |
#if !defined(KERNEL_2_2) |
|
|
| 1164 |
nv_kern_vma_nopage, |
1135 |
nv_kern_vma_nopage, |
| 1165 |
#endif |
|
|
| 1166 |
}; |
1136 |
}; |
| 1167 |
|
1137 |
|
| 1168 |
static nv_file_private_t * |
1138 |
static nv_file_private_t * |
|
Lines 1177-1183
Link Here
|
| 1177 |
memset(nvfp, 0, sizeof(nv_file_private_t)); |
1147 |
memset(nvfp, 0, sizeof(nv_file_private_t)); |
| 1178 |
|
1148 |
|
| 1179 |
// initialize this file's event queue |
1149 |
// initialize this file's event queue |
| 1180 |
INIT_EVENT_QUEUE(nvfp->wqueue); |
1150 |
init_waitqueue_head(&nvfp->waitqueue); |
| 1181 |
|
1151 |
|
| 1182 |
nv_init_lock(nvfp->fp_lock); |
1152 |
nv_init_lock(nvfp->fp_lock); |
| 1183 |
|
1153 |
|
|
Lines 1197-1207
Link Here
|
| 1197 |
if (nvfp == NULL) |
1167 |
if (nvfp == NULL) |
| 1198 |
return; |
1168 |
return; |
| 1199 |
|
1169 |
|
| 1200 |
FREE_EVENT_QUEUE(nvfp->wqueue); |
|
|
| 1201 |
NV_VFREE(nvfp->event_fifo, sizeof(nv_event_t) * NV_EVENT_FIFO_SIZE); |
1170 |
NV_VFREE(nvfp->event_fifo, sizeof(nv_event_t) * NV_EVENT_FIFO_SIZE); |
| 1202 |
NV_VFREE(nvfp, sizeof(nv_file_private_t)); |
1171 |
NV_VFREE(nvfp, sizeof(nv_file_private_t)); |
| 1203 |
} |
1172 |
} |
| 1204 |
|
1173 |
|
|
|
1174 |
void nv_kern_isr_bh(unsigned long data) |
| 1175 |
{ |
| 1176 |
/* |
| 1177 |
* XXX: This level of indirection is necessary to work around |
| 1178 |
* problems with Linux kernels using a non-standard calling |
| 1179 |
* convention, i.e. Arjan van de Ven's/RedHat's 2.6.0 kernels. |
| 1180 |
*/ |
| 1181 |
rm_isr_bh((VOID *) data); |
| 1182 |
} |
| 1205 |
|
1183 |
|
| 1206 |
/* |
1184 |
/* |
| 1207 |
** nv_kern_open |
1185 |
** nv_kern_open |
|
Lines 1226-1236
Link Here
|
| 1226 |
|
1204 |
|
| 1227 |
/* for control device, just jump to its open routine */ |
1205 |
/* for control device, just jump to its open routine */ |
| 1228 |
/* after setting up the private data */ |
1206 |
/* after setting up the private data */ |
| 1229 |
if (NV_DEVICE_IS_CONTROL_DEVICE(inode->i_rdev)) |
1207 |
if (NV_IS_CONTROL_DEVICE(inode)) |
| 1230 |
return nv_kern_ctl_open(inode, file); |
1208 |
return nv_kern_ctl_open(inode, file); |
| 1231 |
|
1209 |
|
| 1232 |
/* what device are we talking about? */ |
1210 |
/* what device are we talking about? */ |
| 1233 |
devnum = NV_DEVICE_NUMBER(inode->i_rdev); |
1211 |
devnum = NV_DEVICE_NUMBER(inode); |
| 1234 |
if (devnum >= NV_MAX_DEVICES) |
1212 |
if (devnum >= NV_MAX_DEVICES) |
| 1235 |
{ |
1213 |
{ |
| 1236 |
rc = -ENODEV; |
1214 |
rc = -ENODEV; |
|
Lines 1283-1294
Link Here
|
| 1283 |
goto failed; |
1261 |
goto failed; |
| 1284 |
} |
1262 |
} |
| 1285 |
|
1263 |
|
|
|
1264 |
nvl->tasklet.func = nv_kern_isr_bh; |
| 1265 |
nvl->tasklet.data = (unsigned long) nv->pdev; |
| 1266 |
tasklet_enable(&nvl->tasklet); |
| 1286 |
|
1267 |
|
| 1287 |
nv->flags |= NV_FLAG_OPEN; |
1268 |
nv->flags |= NV_FLAG_OPEN; |
| 1288 |
} |
1269 |
} |
| 1289 |
|
1270 |
|
| 1290 |
nv->usage_count++; |
1271 |
nv->usage_count++; |
| 1291 |
MOD_INC_USE_COUNT; |
|
|
| 1292 |
|
1272 |
|
| 1293 |
failed: |
1273 |
failed: |
| 1294 |
nv_unlock(nvl->ldata_lock); |
1274 |
nv_unlock(nvl->ldata_lock); |
|
Lines 1319-1356
Link Here
|
| 1319 |
|
1299 |
|
| 1320 |
/* for control device, just jump to its open routine */ |
1300 |
/* for control device, just jump to its open routine */ |
| 1321 |
/* after setting up the private data */ |
1301 |
/* after setting up the private data */ |
| 1322 |
if (NV_DEVICE_IS_CONTROL_DEVICE(inode->i_rdev)) |
1302 |
if (NV_IS_CONTROL_DEVICE(inode)) |
| 1323 |
return nv_kern_ctl_close(inode, file); |
1303 |
return nv_kern_ctl_close(inode, file); |
| 1324 |
|
1304 |
|
| 1325 |
nv_printf(NV_DBG_INFO, "nv_kern_close on device %d\n", NV_DEVICE_NUMBER(inode->i_rdev)); |
1305 |
nv_printf(NV_DBG_INFO, "nv_kern_close on device %d\n", NV_DEVICE_NUMBER(inode)); |
| 1326 |
|
1306 |
|
| 1327 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
1307 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
| 1328 |
|
1308 |
|
| 1329 |
nv_lock(nvl->ldata_lock); |
1309 |
nv_lock(nvl->ldata_lock); |
| 1330 |
if (--nv->usage_count == 0) |
1310 |
if (--nv->usage_count == 0) |
| 1331 |
{ |
1311 |
{ |
| 1332 |
int counter = 0; |
1312 |
/* |
| 1333 |
|
1313 |
* The usage count for this device has dropped to zero, it can be shut |
| 1334 |
/* turn off interrupts. |
1314 |
* down safely; disable its interrupts. |
| 1335 |
** be careful to make sure any pending bottom half gets run |
1315 |
*/ |
| 1336 |
** or disabled before calling rm_shutdown_adapter() since |
|
|
| 1337 |
** it will free up the pdev. This is hard to see on single |
| 1338 |
** cpu systems, but easy on dual cpu :-) |
| 1339 |
*/ |
| 1340 |
rm_disable_adapter(nv); |
1316 |
rm_disable_adapter(nv); |
| 1341 |
|
1317 |
|
| 1342 |
/* give it a moment to allow any bottom half to run */ |
1318 |
/* |
| 1343 |
|
1319 |
* Disable this device's tasklet to make sure that no bottom half will |
| 1344 |
#define MAX_BH_TASKS 10 |
1320 |
* run with undefined device state. |
| 1345 |
while (NV_ATOMIC_READ(nvl->bh_count) && (counter < MAX_BH_TASKS)) |
1321 |
*/ |
| 1346 |
{ |
1322 |
tasklet_disable(&nvl->tasklet); |
| 1347 |
current->state = TASK_INTERRUPTIBLE; |
|
|
| 1348 |
schedule_timeout(HZ/50); |
| 1349 |
counter++; |
| 1350 |
} |
| 1351 |
|
1323 |
|
| 1352 |
/* free the irq, which may block until any pending interrupts */ |
1324 |
/* |
| 1353 |
/* are done being processed. */ |
1325 |
* Free the IRQ, which may block until all pending interrupt processing |
|
|
1326 |
* has completed. |
| 1327 |
*/ |
| 1354 |
free_irq(nv->interrupt_line, (void *) nv); |
1328 |
free_irq(nv->interrupt_line, (void *) nv); |
| 1355 |
|
1329 |
|
| 1356 |
rm_shutdown_adapter(nv); |
1330 |
rm_shutdown_adapter(nv); |
|
Lines 1381-1388
Link Here
|
| 1381 |
FILE_PRIVATE(file) = NULL; |
1355 |
FILE_PRIVATE(file) = NULL; |
| 1382 |
} |
1356 |
} |
| 1383 |
|
1357 |
|
| 1384 |
MOD_DEC_USE_COUNT; |
|
|
| 1385 |
|
| 1386 |
return 0; |
1358 |
return 0; |
| 1387 |
} |
1359 |
} |
| 1388 |
|
1360 |
|
|
Lines 1399-1408
Link Here
|
| 1399 |
nv_printf(NV_DBG_INFO, "mmap([0x%p-0x%p] off=0x%lx)\n", |
1371 |
nv_printf(NV_DBG_INFO, "mmap([0x%p-0x%p] off=0x%lx)\n", |
| 1400 |
vma->vm_start, |
1372 |
vma->vm_start, |
| 1401 |
vma->vm_end, |
1373 |
vma->vm_end, |
| 1402 |
LINUX_VMA_OFFS(vma)); |
1374 |
NV_VMA_OFFSET(vma)); |
| 1403 |
|
1375 |
|
| 1404 |
// be a bit paranoid for now |
1376 |
// be a bit paranoid for now |
| 1405 |
if ((NV_MASK_OFFSET(LINUX_VMA_OFFS(vma))) || |
1377 |
if ((NV_MASK_OFFSET(NV_VMA_OFFSET(vma))) || |
| 1406 |
(NV_MASK_OFFSET(vma->vm_start)) || |
1378 |
(NV_MASK_OFFSET(vma->vm_start)) || |
| 1407 |
(NV_MASK_OFFSET(vma->vm_end))) |
1379 |
(NV_MASK_OFFSET(vma->vm_end))) |
| 1408 |
{ |
1380 |
{ |
|
Lines 1420-1426
Link Here
|
| 1420 |
|
1392 |
|
| 1421 |
|
1393 |
|
| 1422 |
/* NV reg space */ |
1394 |
/* NV reg space */ |
| 1423 |
if (IS_REG_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1395 |
if (IS_REG_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
| 1424 |
{ |
1396 |
{ |
| 1425 |
/* truncate to size of registers */ |
1397 |
/* truncate to size of registers */ |
| 1426 |
if (pages > nv->regs->size / PAGE_SIZE) |
1398 |
if (pages > nv->regs->size / PAGE_SIZE) |
|
Lines 1428-1434
Link Here
|
| 1428 |
|
1400 |
|
| 1429 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1401 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 1430 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1402 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
| 1431 |
phys_to_uncached(LINUX_VMA_OFFS(vma)), |
1403 |
phys_to_uncached(NV_VMA_OFFSET(vma)), |
| 1432 |
vma->vm_end - vma->vm_start, |
1404 |
vma->vm_end - vma->vm_start, |
| 1433 |
vma->vm_page_prot)) |
1405 |
vma->vm_page_prot)) |
| 1434 |
return -EAGAIN; |
1406 |
return -EAGAIN; |
|
Lines 1438-1444
Link Here
|
| 1438 |
} |
1410 |
} |
| 1439 |
|
1411 |
|
| 1440 |
/* NV fb space */ |
1412 |
/* NV fb space */ |
| 1441 |
else if (IS_FB_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1413 |
else if (IS_FB_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
| 1442 |
{ |
1414 |
{ |
| 1443 |
|
1415 |
|
| 1444 |
/* truncate to size of framebuffer */ |
1416 |
/* truncate to size of framebuffer */ |
|
Lines 1447-1453
Link Here
|
| 1447 |
|
1419 |
|
| 1448 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1420 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 1449 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1421 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
| 1450 |
phys_to_uncached(LINUX_VMA_OFFS(vma)), |
1422 |
phys_to_uncached(NV_VMA_OFFSET(vma)), |
| 1451 |
vma->vm_end - vma->vm_start, |
1423 |
vma->vm_end - vma->vm_start, |
| 1452 |
vma->vm_page_prot)) |
1424 |
vma->vm_page_prot)) |
| 1453 |
return -EAGAIN; |
1425 |
return -EAGAIN; |
|
Lines 1457-1466
Link Here
|
| 1457 |
} |
1429 |
} |
| 1458 |
|
1430 |
|
| 1459 |
/* AGP allocator */ |
1431 |
/* AGP allocator */ |
| 1460 |
else if (IS_AGP_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1432 |
else if (IS_AGP_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
| 1461 |
{ |
1433 |
{ |
| 1462 |
nv_lock(nvl->at_lock); |
1434 |
nv_lock(nvl->at_lock); |
| 1463 |
at = nvl_find_alloc(nvl, LINUX_VMA_OFFS(vma), NV_ALLOC_TYPE_AGP); |
1435 |
at = nvl_find_alloc(nvl, NV_VMA_OFFSET(vma), NV_ALLOC_TYPE_AGP); |
| 1464 |
|
1436 |
|
| 1465 |
if (at == NULL) |
1437 |
if (at == NULL) |
| 1466 |
{ |
1438 |
{ |
|
Lines 1478-1484
Link Here
|
| 1478 |
} |
1450 |
} |
| 1479 |
|
1451 |
|
| 1480 |
at->vma = vma; |
1452 |
at->vma = vma; |
| 1481 |
VMA_PRIVATE(vma) = at; |
1453 |
NV_VMA_PRIVATE(vma) = at; |
| 1482 |
at->usage_count++; |
1454 |
at->usage_count++; |
| 1483 |
|
1455 |
|
| 1484 |
if (NV_OSAGP_ENABLED(nv)) |
1456 |
if (NV_OSAGP_ENABLED(nv)) |
|
Lines 1502-1514
Link Here
|
| 1502 |
} |
1474 |
} |
| 1503 |
|
1475 |
|
| 1504 |
/* Magic allocator */ |
1476 |
/* Magic allocator */ |
| 1505 |
else // if (LINUX_VMA_OFFS(vma) == NV_MMAP_ALLOCATION_OFFSET) |
1477 |
else // if (NV_VMA_OFFSET(vma) == NV_MMAP_ALLOCATION_OFFSET) |
| 1506 |
{ |
1478 |
{ |
| 1507 |
unsigned long page = 0, pos, start; |
1479 |
unsigned long page = 0, pos, start; |
| 1508 |
int i = 0; |
1480 |
int i = 0; |
| 1509 |
|
1481 |
|
| 1510 |
nv_lock(nvl->at_lock); |
1482 |
nv_lock(nvl->at_lock); |
| 1511 |
at = nvl_find_alloc(nvl, LINUX_VMA_OFFS(vma), NV_ALLOC_TYPE_PCI); |
1483 |
at = nvl_find_alloc(nvl, NV_VMA_OFFSET(vma), NV_ALLOC_TYPE_PCI); |
| 1512 |
|
1484 |
|
| 1513 |
if (at == NULL) |
1485 |
if (at == NULL) |
| 1514 |
{ |
1486 |
{ |
|
Lines 1526-1532
Link Here
|
| 1526 |
} |
1498 |
} |
| 1527 |
|
1499 |
|
| 1528 |
at->vma = vma; |
1500 |
at->vma = vma; |
| 1529 |
VMA_PRIVATE(vma) = at; |
1501 |
NV_VMA_PRIVATE(vma) = at; |
| 1530 |
at->usage_count++; |
1502 |
at->usage_count++; |
| 1531 |
|
1503 |
|
| 1532 |
nv_printf(NV_DBG_INFO, "remapping %d system pages for at 0x%x\n", pages, at); |
1504 |
nv_printf(NV_DBG_INFO, "remapping %d system pages for at 0x%x\n", pages, at); |
|
Lines 1548-1556
Link Here
|
| 1548 |
|
1520 |
|
| 1549 |
vma->vm_file = file; |
1521 |
vma->vm_file = file; |
| 1550 |
|
1522 |
|
| 1551 |
/* just increment usage count, rather than calling vma_open */ |
|
|
| 1552 |
MOD_INC_USE_COUNT; |
| 1553 |
|
| 1554 |
return 0; |
1523 |
return 0; |
| 1555 |
} |
1524 |
} |
| 1556 |
|
1525 |
|
|
Lines 1577-1583
Link Here
|
| 1577 |
{ |
1546 |
{ |
| 1578 |
nv_printf(NV_DBG_EVENTINFO, "calling poll_wait\n"); |
1547 |
nv_printf(NV_DBG_EVENTINFO, "calling poll_wait\n"); |
| 1579 |
// add us to the list |
1548 |
// add us to the list |
| 1580 |
poll_wait(file, EVENT_QUEUE(nvfp->wqueue), wait); |
1549 |
poll_wait(file, &nvfp->waitqueue, wait); |
| 1581 |
} |
1550 |
} |
| 1582 |
|
1551 |
|
| 1583 |
nv_lock_irq(nvfp->fp_lock, eflags); |
1552 |
nv_lock_irq(nvfp->fp_lock, eflags); |
|
Lines 1645-1656
Link Here
|
| 1645 |
|
1614 |
|
| 1646 |
switch (_IOC_NR(cmd)) |
1615 |
switch (_IOC_NR(cmd)) |
| 1647 |
{ |
1616 |
{ |
|
|
1617 |
#if !defined(KERNEL_2_6) |
| 1648 |
/* debug tool; zap the module use count so we can unload driver */ |
1618 |
/* debug tool; zap the module use count so we can unload driver */ |
| 1649 |
/* even if it is confused */ |
1619 |
/* even if it is confused */ |
| 1650 |
case NV_ESC_MODULE_RESET: |
1620 |
case NV_ESC_MODULE_RESET: |
| 1651 |
atomic_set(&__this_module.uc.usecount, 1); |
1621 |
atomic_set(&__this_module.uc.usecount, 1); |
| 1652 |
break; |
1622 |
break; |
| 1653 |
|
1623 |
#endif |
| 1654 |
/* pass out info about the card */ |
1624 |
/* pass out info about the card */ |
| 1655 |
case NV_ESC_CARD_INFO: |
1625 |
case NV_ESC_CARD_INFO: |
| 1656 |
{ |
1626 |
{ |
|
Lines 1777-1783
Link Here
|
| 1777 |
* driver receives an interrupt |
1747 |
* driver receives an interrupt |
| 1778 |
* if someone waiting, then hand it off. |
1748 |
* if someone waiting, then hand it off. |
| 1779 |
*/ |
1749 |
*/ |
| 1780 |
void nv_kern_isr( |
1750 |
irqreturn_t nv_kern_isr( |
| 1781 |
int irq, |
1751 |
int irq, |
| 1782 |
void *arg, |
1752 |
void *arg, |
| 1783 |
struct pt_regs *regs |
1753 |
struct pt_regs *regs |
|
Lines 1791-1799
Link Here
|
| 1791 |
if (need_to_run_bottom_half) |
1761 |
if (need_to_run_bottom_half) |
| 1792 |
{ |
1762 |
{ |
| 1793 |
NV_ATOMIC_INC(nvl->bh_count); |
1763 |
NV_ATOMIC_INC(nvl->bh_count); |
| 1794 |
queue_task(nvl->bh, &tq_immediate); |
1764 |
tasklet_schedule(&nvl->tasklet); |
| 1795 |
mark_bh(IMMEDIATE_BH); |
|
|
| 1796 |
} |
1765 |
} |
|
|
1766 |
|
| 1767 |
return IRQ_HANDLED; |
| 1797 |
} |
1768 |
} |
| 1798 |
|
1769 |
|
| 1799 |
void nv_kern_bh( |
1770 |
void nv_kern_bh( |
|
Lines 1911-1921
Link Here
|
| 1911 |
|
1882 |
|
| 1912 |
if (nv->usage_count == 0) |
1883 |
if (nv->usage_count == 0) |
| 1913 |
{ |
1884 |
{ |
| 1914 |
INIT_EVENT_QUEUE(nv_ctl_wqueue); |
1885 |
init_waitqueue_head(&nv_ctl_waitqueue); |
| 1915 |
} |
1886 |
} |
| 1916 |
|
1887 |
|
| 1917 |
MOD_INC_USE_COUNT; |
|
|
| 1918 |
|
| 1919 |
nv->flags |= NV_FLAG_OPEN + NV_FLAG_CONTROL; |
1888 |
nv->flags |= NV_FLAG_OPEN + NV_FLAG_CONTROL; |
| 1920 |
|
1889 |
|
| 1921 |
/* turn off the hotkey occurred bit */ |
1890 |
/* turn off the hotkey occurred bit */ |
|
Lines 1943-1952
Link Here
|
| 1943 |
|
1912 |
|
| 1944 |
nv_lock(nvl->ldata_lock); |
1913 |
nv_lock(nvl->ldata_lock); |
| 1945 |
if (--nv->usage_count == 0) |
1914 |
if (--nv->usage_count == 0) |
| 1946 |
{ |
|
|
| 1947 |
FREE_EVENT_QUEUE(nv_ctl_wqueue); |
| 1948 |
nv->flags = 0; |
1915 |
nv->flags = 0; |
| 1949 |
} |
1916 |
|
| 1950 |
nv_unlock(nvl->ldata_lock); |
1917 |
nv_unlock(nvl->ldata_lock); |
| 1951 |
|
1918 |
|
| 1952 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
1919 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
|
Lines 1957-1964
Link Here
|
| 1957 |
FILE_PRIVATE(file) = NULL; |
1924 |
FILE_PRIVATE(file) = NULL; |
| 1958 |
} |
1925 |
} |
| 1959 |
|
1926 |
|
| 1960 |
MOD_DEC_USE_COUNT; |
|
|
| 1961 |
|
| 1962 |
return 0; |
1927 |
return 0; |
| 1963 |
} |
1928 |
} |
| 1964 |
|
1929 |
|
|
Lines 1982-1988
Link Here
|
| 1982 |
nv = NV_STATE_PTR(nvl); |
1947 |
nv = NV_STATE_PTR(nvl); |
| 1983 |
|
1948 |
|
| 1984 |
if ( !(file->f_flags & O_NONBLOCK) ) |
1949 |
if ( !(file->f_flags & O_NONBLOCK) ) |
| 1985 |
poll_wait(file, EVENT_QUEUE(nv_ctl_wqueue), wait); |
1950 |
poll_wait(file, &nv_ctl_waitqueue, wait); |
| 1986 |
|
1951 |
|
| 1987 |
nv_lock(nvl->ldata_lock); |
1952 |
nv_lock(nvl->ldata_lock); |
| 1988 |
|
1953 |
|
|
Lines 2013-2019
Link Here
|
| 2013 |
nv_ctl_device.nv_state.flags |= NV_FLAG_HOTKEY_OCCURRED; |
1978 |
nv_ctl_device.nv_state.flags |= NV_FLAG_HOTKEY_OCCURRED; |
| 2014 |
nv_unlock(nv_ctl_device.ldata_lock); |
1979 |
nv_unlock(nv_ctl_device.ldata_lock); |
| 2015 |
|
1980 |
|
| 2016 |
wake_up_interruptible(EVENT_QUEUE(nv_ctl_wqueue)); |
1981 |
wake_up_interruptible(&nv_ctl_waitqueue); |
| 2017 |
} |
1982 |
} |
| 2018 |
|
1983 |
|
| 2019 |
int nv_kern_read_cardinfo(char *page, char **start, off_t off, |
1984 |
int nv_kern_read_cardinfo(char *page, char **start, off_t off, |
|
Lines 2092-2098
Link Here
|
| 2092 |
len += sprintf(page+len, "Host Bridge: \t "); |
2057 |
len += sprintf(page+len, "Host Bridge: \t "); |
| 2093 |
|
2058 |
|
| 2094 |
#if defined(CONFIG_PCI_NAMES) |
2059 |
#if defined(CONFIG_PCI_NAMES) |
| 2095 |
len += sprintf(page+len, "%s\n", dev->name); |
2060 |
len += sprintf(page+len, "%s\n", NV_PCI_DEVICE_NAME(dev)); |
| 2096 |
#else |
2061 |
#else |
| 2097 |
len += sprintf(page+len, "PCI device %04x:%04x\n", |
2062 |
len += sprintf(page+len, "PCI device %04x:%04x\n", |
| 2098 |
dev->vendor, dev->device); |
2063 |
dev->vendor, dev->device); |
|
Lines 2304-2330
Link Here
|
| 2304 |
int kern |
2269 |
int kern |
| 2305 |
) |
2270 |
) |
| 2306 |
{ |
2271 |
{ |
| 2307 |
pgd_t *pg_dir; |
2272 |
pgd_t *pgd; |
| 2308 |
pmd_t *pg_mid_dir; |
2273 |
pmd_t *pmd; |
| 2309 |
pte_t pte; |
2274 |
pte_t *pte; |
| 2310 |
unsigned long retval; |
2275 |
unsigned long retval; |
| 2311 |
|
2276 |
|
| 2312 |
if (kern) pg_dir = pgd_offset_k(address); |
2277 |
if (kern) |
| 2313 |
else pg_dir = pgd_offset(current->mm, address); |
2278 |
pgd = pgd_offset_k(address); |
|
|
2279 |
else |
| 2280 |
pgd = pgd_offset(current->mm, address); |
| 2314 |
|
2281 |
|
| 2315 |
if (pgd_none(*pg_dir)) |
2282 |
if (!pgd || pgd_none(*pgd)) |
| 2316 |
goto failed; |
2283 |
goto failed; |
| 2317 |
|
2284 |
|
| 2318 |
pg_mid_dir = pmd_offset(pg_dir, address); |
2285 |
NV_PMD_OFFSET(address, pgd, pmd); |
| 2319 |
if (pmd_none(*pg_mid_dir)) |
2286 |
|
|
|
2287 |
if (!NV_PMD_PRESENT(pmd)) |
| 2320 |
goto failed; |
2288 |
goto failed; |
| 2321 |
|
2289 |
|
| 2322 |
NV_PTE_OFFSET(address, pg_mid_dir, pte); |
2290 |
NV_PTE_OFFSET(address, pmd, pte); |
| 2323 |
|
2291 |
|
| 2324 |
if (!pte_present(pte)) |
2292 |
if (!NV_PTE_PRESENT(pte)) |
| 2325 |
goto failed; |
2293 |
goto failed; |
| 2326 |
|
2294 |
|
| 2327 |
retval = ((pte_val(pte) & KERN_PAGE_MASK) | NV_MASK_OFFSET(address)); |
2295 |
retval = ((NV_PTE_VALUE(pte) & KERN_PAGE_MASK) | NV_MASK_OFFSET(address)); |
| 2328 |
|
2296 |
|
| 2329 |
#if defined(NVCPU_X86_64) && defined(_PAGE_NX) |
2297 |
#if defined(NVCPU_X86_64) && defined(_PAGE_NX) |
| 2330 |
// mask out the non-executable page bit for the true physical address |
2298 |
// mask out the non-executable page bit for the true physical address |
|
Lines 2759-2765
Link Here
|
| 2759 |
|
2727 |
|
| 2760 |
if (nvfp->num_events == NV_EVENT_FIFO_SIZE) |
2728 |
if (nvfp->num_events == NV_EVENT_FIFO_SIZE) |
| 2761 |
{ |
2729 |
{ |
| 2762 |
wake_up_interruptible(EVENT_QUEUE(nvfp->wqueue)); |
2730 |
wake_up_interruptible(&nvfp->waitqueue); |
| 2763 |
nv_unlock_irq(nvfp->fp_lock, eflags); |
2731 |
nv_unlock_irq(nvfp->fp_lock, eflags); |
| 2764 |
return; |
2732 |
return; |
| 2765 |
} |
2733 |
} |
|
Lines 2776-2782
Link Here
|
| 2776 |
if (nvfp->put >= NV_EVENT_FIFO_SIZE) |
2744 |
if (nvfp->put >= NV_EVENT_FIFO_SIZE) |
| 2777 |
nvfp->put = 0; |
2745 |
nvfp->put = 0; |
| 2778 |
|
2746 |
|
| 2779 |
wake_up_interruptible(EVENT_QUEUE(nvfp->wqueue)); |
2747 |
wake_up_interruptible(&nvfp->waitqueue); |
| 2780 |
nv_unlock_irq(nvfp->fp_lock, eflags); |
2748 |
nv_unlock_irq(nvfp->fp_lock, eflags); |
| 2781 |
} |
2749 |
} |
| 2782 |
|
2750 |
|
|
Lines 2866-2877
Link Here
|
| 2866 |
if ( (NV_AGP_DISABLED(nv)) && (config & NVOS_AGP_CONFIG_NVAGP) ) |
2834 |
if ( (NV_AGP_DISABLED(nv)) && (config & NVOS_AGP_CONFIG_NVAGP) ) |
| 2867 |
{ |
2835 |
{ |
| 2868 |
/* make sure the user does not have agpgart loaded */ |
2836 |
/* make sure the user does not have agpgart loaded */ |
| 2869 |
#if !defined (KERNEL_2_2) |
|
|
| 2870 |
if (inter_module_get("drm_agp")) { |
2837 |
if (inter_module_get("drm_agp")) { |
| 2871 |
inter_module_put("drm_agp"); |
2838 |
inter_module_put("drm_agp"); |
| 2872 |
#else |
|
|
| 2873 |
if (GET_MODULE_SYMBOL(0, __MODULE_STRING(agp_enable))) { |
| 2874 |
#endif |
| 2875 |
nv_printf(NV_DBG_WARNINGS, "NVRM: not using NVAGP, AGPGART is loaded!!\n"); |
2839 |
nv_printf(NV_DBG_WARNINGS, "NVRM: not using NVAGP, AGPGART is loaded!!\n"); |
| 2876 |
} else { |
2840 |
} else { |
| 2877 |
#if defined(CONFIG_X86_64) && defined(CONFIG_GART_IOMMU) |
2841 |
#if defined(CONFIG_X86_64) && defined(CONFIG_GART_IOMMU) |