Lines 16-26
Link Here
|
16 |
#include "os-agp.h" |
16 |
#include "os-agp.h" |
17 |
|
17 |
|
18 |
|
18 |
|
|
|
19 |
MODULE_LICENSE("NVIDIA"); |
20 |
|
19 |
/* |
21 |
/* |
20 |
* our global state; one per device |
22 |
* our global state; one per device |
21 |
*/ |
23 |
*/ |
22 |
|
24 |
|
23 |
nv_linux_state_t nv_linux_devices[NV_MAX_DEVICES] = { { { 0 } } }; |
25 |
nv_linux_state_t nv_linux_devices[NV_MAX_DEVICES] = { { { 0 } } }; |
|
|
26 |
static int nv_num_devices; |
24 |
|
27 |
|
25 |
#ifdef CONFIG_PM |
28 |
#ifdef CONFIG_PM |
26 |
/* XXX PM do we only need one, or one for each device? */ |
29 |
/* XXX PM do we only need one, or one for each device? */ |
Lines 36-62
Link Here
|
36 |
// keep track of opened clients and their process id so they |
39 |
// keep track of opened clients and their process id so they |
37 |
// can be free'd up on abnormal close |
40 |
// can be free'd up on abnormal close |
38 |
nv_client_t nv_clients[NV_MAX_CLIENTS]; |
41 |
nv_client_t nv_clients[NV_MAX_CLIENTS]; |
39 |
struct tq_struct nv_bottom_halves[NV_MAX_CLIENTS]; |
|
|
40 |
|
42 |
|
41 |
#ifdef CONFIG_PROC_FS |
43 |
#ifdef CONFIG_PROC_FS |
42 |
struct proc_dir_entry *proc_nvidia; |
44 |
struct proc_dir_entry *proc_nvidia; |
43 |
#endif |
45 |
#endif |
44 |
|
46 |
|
45 |
#ifdef CONFIG_DEVFS_FS |
47 |
#ifdef CONFIG_DEVFS_FS |
46 |
devfs_handle_t nv_dev_handle[NV_MAX_DEVICES]; |
48 |
devfs_handle_t nv_devfs_handles[NV_MAX_DEVICES+1]; |
47 |
devfs_handle_t nv_ctl_handle; |
|
|
48 |
#endif |
49 |
#endif |
49 |
|
50 |
|
50 |
/* |
|
|
51 |
* pick apart our minor device number |
52 |
* low 3 bits is NV device |
53 |
* if 255, then its the control device |
54 |
*/ |
55 |
|
56 |
#define NV_DEVICE_NUMBER(_minor) ((_minor) & 0x0f) |
57 |
#define NV_DEVICE_IS_CONTROL_DEVICE(_minor) \ |
58 |
(((_minor) & 0xFF) == 0xFF) |
59 |
|
60 |
// #define NV_DBG_MEM 1 |
51 |
// #define NV_DBG_MEM 1 |
61 |
#undef NV_DBG_MEM |
52 |
#undef NV_DBG_MEM |
62 |
|
53 |
|
Lines 107-116
Link Here
|
107 |
*** EXPORTS to Linux Kernel |
98 |
*** EXPORTS to Linux Kernel |
108 |
***/ |
99 |
***/ |
109 |
|
100 |
|
110 |
/* linux module interface functions (called by linux kernel) */ |
|
|
111 |
int init_module(void); |
112 |
void cleanup_module(void); |
113 |
|
114 |
/* nv_kern_ functions, interfaces used by linux kernel */ |
101 |
/* nv_kern_ functions, interfaces used by linux kernel */ |
115 |
void nv_kern_vma_open(struct vm_area_struct *vma); |
102 |
void nv_kern_vma_open(struct vm_area_struct *vma); |
116 |
void nv_kern_vma_release(struct vm_area_struct *vma); |
103 |
void nv_kern_vma_release(struct vm_area_struct *vma); |
Lines 120-127
Link Here
|
120 |
int nv_kern_mmap(struct file *, struct vm_area_struct *); |
107 |
int nv_kern_mmap(struct file *, struct vm_area_struct *); |
121 |
unsigned int nv_kern_poll(struct file *, poll_table *); |
108 |
unsigned int nv_kern_poll(struct file *, poll_table *); |
122 |
int nv_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
109 |
int nv_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long); |
123 |
void nv_kern_bh(void *); |
110 |
void nv_kern_isr_bh(unsigned long); |
124 |
void nv_kern_isr(int, void *, struct pt_regs *); |
111 |
irqreturn_t nv_kern_isr(int, void *, struct pt_regs *); |
125 |
void nv_kern_rc_timer(unsigned long); |
112 |
void nv_kern_rc_timer(unsigned long); |
126 |
#ifdef CONFIG_PM |
113 |
#ifdef CONFIG_PM |
127 |
int nv_kern_pm(struct pm_dev *dev, pm_request_t rqst, void *data); |
114 |
int nv_kern_pm(struct pm_dev *dev, pm_request_t rqst, void *data); |
Lines 144-149
Link Here
|
144 |
/* character driver entry points */ |
131 |
/* character driver entry points */ |
145 |
|
132 |
|
146 |
static struct file_operations nv_fops = { |
133 |
static struct file_operations nv_fops = { |
|
|
134 |
owner: THIS_MODULE, |
147 |
poll: nv_kern_poll, |
135 |
poll: nv_kern_poll, |
148 |
ioctl: nv_kern_ioctl, |
136 |
ioctl: nv_kern_ioctl, |
149 |
mmap: nv_kern_mmap, |
137 |
mmap: nv_kern_mmap, |
Lines 298-305
Link Here
|
298 |
{ |
286 |
{ |
299 |
nv_printf(NV_DBG_MEMINFO, " 0x%x: count %d flags 0x%x\n", |
287 |
nv_printf(NV_DBG_MEMINFO, " 0x%x: count %d flags 0x%x\n", |
300 |
*page_ptr, |
288 |
*page_ptr, |
301 |
(GET_MAP_NR(*page_ptr))->count, |
289 |
(virt_to_page(__va(*page_ptr)))->count, |
302 |
(GET_MAP_NR(*page_ptr))->flags); |
290 |
(virt_to_page(__va(*page_ptr)))->flags); |
303 |
num_pages--; |
291 |
num_pages--; |
304 |
page_ptr++; |
292 |
page_ptr++; |
305 |
} |
293 |
} |
Lines 370-376
Link Here
|
370 |
phys_addr = virt_to_phys((void *) virt_addr); |
358 |
phys_addr = virt_to_phys((void *) virt_addr); |
371 |
|
359 |
|
372 |
/* lock the page for dma purposes */ |
360 |
/* lock the page for dma purposes */ |
373 |
mem_map_reserve(GET_MAP_NR(phys_addr)); |
361 |
SetPageReserved(virt_to_page(__va(phys_addr))); |
374 |
|
362 |
|
375 |
*page_ptr++ = phys_addr; |
363 |
*page_ptr++ = phys_addr; |
376 |
pages_needed--; |
364 |
pages_needed--; |
Lines 383-389
Link Here
|
383 |
while (page_ptr != (unsigned long *) page_list) |
371 |
while (page_ptr != (unsigned long *) page_list) |
384 |
{ |
372 |
{ |
385 |
page_ptr--; |
373 |
page_ptr--; |
386 |
mem_map_unreserve(GET_MAP_NR(*page_ptr)); |
374 |
ClearPageReserved(virt_to_page(__va(*page_ptr))); |
387 |
free_page((unsigned long) phys_to_virt(*page_ptr)); |
375 |
free_page((unsigned long) phys_to_virt(*page_ptr)); |
388 |
} |
376 |
} |
389 |
|
377 |
|
Lines 403-409
Link Here
|
403 |
|
391 |
|
404 |
while (pages_left) |
392 |
while (pages_left) |
405 |
{ |
393 |
{ |
406 |
mem_map_unreserve(GET_MAP_NR(*page_list)); |
394 |
ClearPageReserved(virt_to_page(__va(*page_list))); |
407 |
page_list++; |
395 |
page_list++; |
408 |
pages_left--; |
396 |
pages_left--; |
409 |
} |
397 |
} |
Lines 569-579
Link Here
|
569 |
nv_linux_state_t *nvl; |
557 |
nv_linux_state_t *nvl; |
570 |
nv_linux_state_t *nv_max_devices; |
558 |
nv_linux_state_t *nv_max_devices; |
571 |
|
559 |
|
572 |
#if defined (KERNEL_2_2) |
|
|
573 |
struct proc_dir_entry *proc_root_driver; |
574 |
proc_root_driver = create_proc_entry("driver", flags, &proc_root); |
575 |
#endif |
576 |
|
577 |
proc_nvidia = create_proc_entry("nvidia", flags, proc_root_driver); |
560 |
proc_nvidia = create_proc_entry("nvidia", flags, proc_root_driver); |
578 |
proc_nvidia_cards = create_proc_entry("cards", flags, proc_nvidia); |
561 |
proc_nvidia_cards = create_proc_entry("cards", flags, proc_nvidia); |
579 |
proc_nvidia_agp = create_proc_entry("agp", flags, proc_nvidia); |
562 |
proc_nvidia_agp = create_proc_entry("agp", flags, proc_nvidia); |
Lines 635-643
Link Here
|
635 |
{ |
618 |
{ |
636 |
#ifdef CONFIG_PROC_FS |
619 |
#ifdef CONFIG_PROC_FS |
637 |
nvos_proc_remove_all(proc_nvidia); |
620 |
nvos_proc_remove_all(proc_nvidia); |
638 |
#if defined (KERNEL_2_2) |
|
|
639 |
remove_proc_entry("driver", &proc_root); |
640 |
#endif |
641 |
#endif |
621 |
#endif |
642 |
} |
622 |
} |
643 |
|
623 |
|
Lines 726-796
Link Here
|
726 |
*** EXPORTS to Linux Kernel |
706 |
*** EXPORTS to Linux Kernel |
727 |
***/ |
707 |
***/ |
728 |
|
708 |
|
729 |
int init_module(void) |
709 |
static int __init nvidia_init_module(void) |
730 |
{ |
710 |
{ |
731 |
nv_linux_state_t *nvl; |
711 |
int i, rc; |
732 |
int rc; |
|
|
733 |
int num_devices; |
734 |
|
712 |
|
735 |
memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); |
713 |
memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); |
736 |
num_devices = nvos_probe_devices(); |
714 |
nv_num_devices = nvos_probe_devices(); |
737 |
|
715 |
|
738 |
if (num_devices == 0) { |
716 |
if (nv_num_devices == 0) { |
739 |
nv_printf(NV_DBG_ERRORS, "nvidia: no NVIDIA graphics adapter found\n"); |
717 |
nv_printf(NV_DBG_ERRORS, "nvidia: no NVIDIA graphics adapter found\n"); |
740 |
return -ENODEV; |
718 |
return -ENODEV; |
741 |
} |
719 |
} |
742 |
|
720 |
|
743 |
nv_printf(NV_DBG_ERRORS, "nvidia: loading %s\n", pNVRM_ID); |
721 |
nv_printf(NV_DBG_ERRORS, "nvidia: loading %s\n", pNVRM_ID); |
744 |
|
722 |
|
745 |
#ifdef CONFIG_DEVFS_FS |
723 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
746 |
rc = devfs_register_chrdev(nv_major, "nvidia", &nv_fops); |
724 |
rc = devfs_register_chrdev(nv_major, "nvidia", &nv_fops); |
747 |
#else |
725 |
#else |
748 |
rc = register_chrdev(nv_major, "nvidia", &nv_fops); |
726 |
rc = register_chrdev(nv_major, "nvidia", &nv_fops); |
749 |
#endif |
727 |
#endif |
750 |
|
728 |
|
751 |
if (rc < 0) { |
729 |
if (rc < 0) { |
752 |
nv_printf(NV_DBG_ERRORS, "init_module: register failed\n"); |
730 |
nv_printf(NV_DBG_ERRORS, "nvidia_init_module: register failed\n"); |
753 |
return rc; |
731 |
return rc; |
754 |
} |
732 |
} |
755 |
|
733 |
|
756 |
#ifdef CONFIG_DEVFS_FS |
734 |
#ifdef CONFIG_DEVFS_FS |
757 |
memset(nv_dev_handle, 0, sizeof(devfs_handle_t) * NV_MAX_DEVICES); |
|
|
758 |
do { |
735 |
do { |
|
|
736 |
/* |
737 |
* XXX This code isn't pretty, but neither is dealing with the |
738 |
* various Linux devfs implemenation(s). While Linux APIs are |
739 |
* known to be anything but stable and oftentimes anything but |
740 |
* well designed, the devfs interface has been more painful to |
741 |
* deal with than most other APIs. |
742 |
*/ |
759 |
char name[10]; |
743 |
char name[10]; |
760 |
int i; |
|
|
761 |
|
744 |
|
762 |
nv_ctl_handle = devfs_register(NULL, "nvidiactl", |
745 |
nv_devfs_handles[0] = NV_DEVFS_REGISTER("nvidiactl", 255); |
763 |
DEVFS_FL_DEFAULT, nv_major, 255, |
|
|
764 |
S_IFCHR | S_IRUGO | S_IWUGO, |
765 |
&nv_fops, NULL); |
766 |
|
746 |
|
767 |
for (i = 0; i < num_devices; i++) { |
747 |
for (i = 0; i < nv_num_devices; i++) { |
768 |
sprintf(name, "nvidia%d", i); |
748 |
sprintf(name, "nvidia%d", i); |
769 |
nv_dev_handle[i] = devfs_register(NULL, name, |
749 |
nv_devfs_handles[i+1] = NV_DEVFS_REGISTER(name, i); |
770 |
DEVFS_FL_DEFAULT, nv_major, i, |
|
|
771 |
S_IFCHR | S_IRUGO | S_IWUGO, |
772 |
&nv_fops, NULL); |
773 |
} |
750 |
} |
774 |
} while(0); |
751 |
} while(0); |
775 |
#endif |
752 |
#endif |
776 |
|
753 |
|
777 |
nv_printf(NV_DBG_INFO, "init_module: major number %d\n", nv_major); |
754 |
nv_printf(NV_DBG_INFO, "nvidia_init_module: major number %d\n", nv_major); |
778 |
|
755 |
|
779 |
// init all the bottom half structures |
756 |
/* instantiate tasklets */ |
780 |
for (nvl = nv_linux_devices; nvl < nv_linux_devices + NV_MAX_DEVICES; nvl++) |
757 |
for (i = 0; i < NV_MAX_DEVICES; i++) { |
781 |
{ |
758 |
/* |
782 |
nvl->bh = &nv_bottom_halves[nvl - nv_linux_devices]; |
759 |
* We keep one tasklet per card to avoid latency issues with more |
783 |
nvl->bh->routine = nv_kern_bh; |
760 |
* than one device; no two instances of a single tasklet are ever |
784 |
nvl->bh->data = (void *) nvl; |
761 |
* executed concurrently. |
785 |
nvl->bh->sync = 0; |
762 |
*/ |
|
|
763 |
atomic_set(&nv_linux_devices[i].tasklet.count, 1); |
764 |
|
765 |
/* |
766 |
* Initialize the event queue for this device. This only needs to |
767 |
* happen once for every device. |
768 |
*/ |
769 |
init_waitqueue_head(&nv_linux_devices[i].waitqueue); |
786 |
} |
770 |
} |
787 |
|
771 |
|
788 |
// init the nvidia control device |
772 |
// init the nvidia control device |
789 |
{ |
773 |
{ |
790 |
nv_state_t *nv_ctl = NV_STATE_PTR(&nv_ctl_device); |
774 |
nv_state_t *nv_ctl = NV_STATE_PTR(&nv_ctl_device); |
791 |
nv_ctl_device.event_queue = NULL; |
|
|
792 |
nv_ctl->os_state = (void *) &nv_ctl_device; |
775 |
nv_ctl->os_state = (void *) &nv_ctl_device; |
793 |
nv_lock_init_locks(nv_ctl); |
776 |
nv_lock_init_locks(nv_ctl); |
|
|
777 |
init_waitqueue_head(&nv_ctl_device.waitqueue); |
794 |
} |
778 |
} |
795 |
|
779 |
|
796 |
#ifdef CONFIG_PM |
780 |
#ifdef CONFIG_PM |
Lines 815-828
Link Here
|
815 |
/* create /proc/driver/nvidia */ |
799 |
/* create /proc/driver/nvidia */ |
816 |
nvos_proc_create(); |
800 |
nvos_proc_create(); |
817 |
|
801 |
|
818 |
#if defined(DEBUG) && !defined(KERNEL_2_2) |
802 |
#if defined(DEBUG) |
819 |
inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices); |
803 |
inter_module_register("nv_linux_devices", THIS_MODULE, nv_linux_devices); |
820 |
#endif |
804 |
#endif |
821 |
|
805 |
|
822 |
return 0; |
806 |
return 0; |
823 |
|
807 |
|
824 |
failed: |
808 |
failed: |
825 |
#ifdef CONFIG_DEVFS_FS |
809 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
826 |
devfs_unregister_chrdev(nv_major, "nvidia"); |
810 |
devfs_unregister_chrdev(nv_major, "nvidia"); |
827 |
#else |
811 |
#else |
828 |
unregister_chrdev(nv_major, "nvidia"); |
812 |
unregister_chrdev(nv_major, "nvidia"); |
Lines 830-847
Link Here
|
830 |
return rc; |
814 |
return rc; |
831 |
} |
815 |
} |
832 |
|
816 |
|
833 |
void cleanup_module(void) |
817 |
static void __exit nvidia_exit_module(void) |
834 |
{ |
818 |
{ |
835 |
int rc; |
|
|
836 |
nv_linux_state_t *nvl; |
819 |
nv_linux_state_t *nvl; |
837 |
nv_linux_state_t *max_devices; |
820 |
nv_linux_state_t *max_devices; |
|
|
821 |
int rc; |
838 |
|
822 |
|
839 |
/* remove /proc/driver/nvidia */ |
823 |
/* remove /proc/driver/nvidia */ |
840 |
nvos_proc_remove(); |
824 |
nvos_proc_remove(); |
841 |
|
825 |
|
842 |
nv_printf(NV_DBG_INFO, "cleanup_module\n"); |
826 |
nv_printf(NV_DBG_INFO, "nvidia_exit_module\n"); |
843 |
|
827 |
|
844 |
#if defined(DEBUG) && !defined(KERNEL_2_2) |
828 |
#if defined(DEBUG) |
845 |
inter_module_unregister("nv_linux_devices"); |
829 |
inter_module_unregister("nv_linux_devices"); |
846 |
#endif |
830 |
#endif |
847 |
|
831 |
|
Lines 866-898
Link Here
|
866 |
continue; |
850 |
continue; |
867 |
|
851 |
|
868 |
nv_printf(NV_DBG_ERRORS, |
852 |
nv_printf(NV_DBG_ERRORS, |
869 |
"still have vm que at cleanup_module(): 0x%x to 0x%x\n", |
853 |
"still have vm que at nvidia_exit_module(): 0x%x to 0x%x\n", |
870 |
nvl->alloc_queue->vma->vm_start, |
854 |
nvl->alloc_queue->vma->vm_start, |
871 |
nvl->alloc_queue->vma->vm_end); |
855 |
nvl->alloc_queue->vma->vm_end); |
872 |
} |
856 |
} |
873 |
} |
857 |
} |
874 |
|
858 |
|
875 |
#ifdef CONFIG_DEVFS_FS |
859 |
#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) |
876 |
rc = devfs_unregister_chrdev(nv_major, "nvidia"); |
860 |
rc = devfs_unregister_chrdev(nv_major, "nvidia"); |
877 |
#else |
861 |
#else |
878 |
rc = unregister_chrdev(nv_major, "nvidia"); |
862 |
rc = unregister_chrdev(nv_major, "nvidia"); |
879 |
#endif |
863 |
#endif |
880 |
|
864 |
|
881 |
if (rc < 0) { |
865 |
if (rc < 0) { |
882 |
nv_printf(NV_DBG_ERRORS, "cleanup_module: unregister nv failed\n"); |
866 |
nv_printf(NV_DBG_ERRORS, "nvidia_exit_module: unregister nv failed\n"); |
883 |
} |
867 |
} |
884 |
|
868 |
|
885 |
#ifdef CONFIG_DEVFS_FS |
869 |
#ifdef CONFIG_DEVFS_FS |
886 |
do { |
870 |
do { |
887 |
int i; |
871 |
int i; |
888 |
for (i = 0; nv_dev_handle[i] != 0; i++) { |
872 |
NV_DEVFS_REMOVE_CONTROL(); |
889 |
devfs_unregister(nv_dev_handle[i]); |
873 |
for (i = 0; i < nv_num_devices; i++) |
890 |
} |
874 |
NV_DEVFS_REMOVE_DEVICE(i); |
891 |
} while(0); |
875 |
} while (0); |
892 |
devfs_unregister(nv_ctl_handle); |
|
|
893 |
#endif |
876 |
#endif |
894 |
} |
877 |
} |
895 |
|
878 |
|
|
|
879 |
module_init(nvidia_init_module); |
880 |
module_exit(nvidia_exit_module); |
896 |
|
881 |
|
897 |
/* this is only called when the vmas are duplicated. |
882 |
/* this is only called when the vmas are duplicated. |
898 |
* this appears to only happen when the process is cloned to create |
883 |
* this appears to only happen when the process is cloned to create |
Lines 906-916
Link Here
|
906 |
nv_kern_vma_open(struct vm_area_struct *vma) |
891 |
nv_kern_vma_open(struct vm_area_struct *vma) |
907 |
{ |
892 |
{ |
908 |
nv_printf(NV_DBG_MEMINFO, "vma_open for 0x%x - 0x%x, offset 0x%x\n", |
893 |
nv_printf(NV_DBG_MEMINFO, "vma_open for 0x%x - 0x%x, offset 0x%x\n", |
909 |
vma->vm_start, vma->vm_end, LINUX_VMA_OFFS(vma)); |
894 |
vma->vm_start, vma->vm_end, NV_VMA_OFFSET(vma)); |
910 |
|
895 |
|
911 |
if (VMA_PRIVATE(vma)) |
896 |
if (NV_VMA_PRIVATE(vma)) |
912 |
{ |
897 |
{ |
913 |
nv_alloc_t *at = (nv_alloc_t *) VMA_PRIVATE(vma); |
898 |
nv_alloc_t *at = (nv_alloc_t *) NV_VMA_PRIVATE(vma); |
914 |
at->usage_count++; |
899 |
at->usage_count++; |
915 |
|
900 |
|
916 |
nv_printf(NV_DBG_MEMINFO, " at 0x%x, usage count %d, page_table 0x%x\n", |
901 |
nv_printf(NV_DBG_MEMINFO, " at 0x%x, usage count %d, page_table 0x%x\n", |
Lines 918-925
Link Here
|
918 |
|
903 |
|
919 |
nvos_list_page_count(at->page_table, at->num_pages); |
904 |
nvos_list_page_count(at->page_table, at->num_pages); |
920 |
} |
905 |
} |
921 |
|
|
|
922 |
MOD_INC_USE_COUNT; |
923 |
} |
906 |
} |
924 |
|
907 |
|
925 |
|
908 |
|
Lines 927-937
Link Here
|
927 |
nv_kern_vma_release(struct vm_area_struct *vma) |
910 |
nv_kern_vma_release(struct vm_area_struct *vma) |
928 |
{ |
911 |
{ |
929 |
nv_printf(NV_DBG_MEMINFO, "vma_release for 0x%x - 0x%x, offset 0x%x\n", |
912 |
nv_printf(NV_DBG_MEMINFO, "vma_release for 0x%x - 0x%x, offset 0x%x\n", |
930 |
vma->vm_start, vma->vm_end, LINUX_VMA_OFFS(vma)); |
913 |
vma->vm_start, vma->vm_end, NV_VMA_OFFSET(vma)); |
931 |
|
914 |
|
932 |
if (VMA_PRIVATE(vma)) |
915 |
if (NV_VMA_PRIVATE(vma)) |
933 |
{ |
916 |
{ |
934 |
nv_alloc_t *at = (nv_alloc_t *) VMA_PRIVATE(vma); |
917 |
nv_alloc_t *at = (nv_alloc_t *) NV_VMA_PRIVATE(vma); |
935 |
|
918 |
|
936 |
at->usage_count--; |
919 |
at->usage_count--; |
937 |
|
920 |
|
Lines 949-983
Link Here
|
949 |
if (at->page_table) |
932 |
if (at->page_table) |
950 |
nvos_unlock_pages(at->page_table, at->num_pages); |
933 |
nvos_unlock_pages(at->page_table, at->num_pages); |
951 |
nvos_free_alloc(at); |
934 |
nvos_free_alloc(at); |
952 |
VMA_PRIVATE(vma) = NULL; |
935 |
NV_VMA_PRIVATE(vma) = NULL; |
953 |
} |
936 |
} |
954 |
} |
937 |
} |
955 |
|
|
|
956 |
MOD_DEC_USE_COUNT; |
957 |
} |
938 |
} |
958 |
|
939 |
|
959 |
|
940 |
|
960 |
/* at this point, this code just plain won't work with 2.2 kernels. |
|
|
961 |
* additionally, only ia64 & the 460GX need a nopage handler, and 2.2 doesn't |
962 |
* work on ia64 anyways. It's expected that at some point other agp chipsets |
963 |
* will work similar to the 460GX (AGP 3.0 spec), so pre-emptively make sure |
964 |
* this works on our standard ia32 driver. |
965 |
*/ |
966 |
#if !defined(KERNEL_2_2) |
967 |
|
968 |
/* AGP allocations under the 460GX are not mapped to the aperture |
941 |
/* AGP allocations under the 460GX are not mapped to the aperture |
969 |
* addresses by the CPU. This nopage handler will fault on CPU |
942 |
* addresses by the CPU. This nopage handler will fault on CPU |
970 |
* accesses to AGP memory and map the address to the correct page. |
943 |
* accesses to AGP memory and map the address to the correct page. |
971 |
*/ |
944 |
*/ |
972 |
struct page *nv_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) |
945 |
struct page *nv_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) |
973 |
{ |
946 |
{ |
|
|
947 |
#if defined(NVCPU_IA64) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)) |
974 |
nv_alloc_t *at, *tmp; |
948 |
nv_alloc_t *at, *tmp; |
975 |
nv_linux_state_t *nvl; |
949 |
nv_linux_state_t *nvl; |
976 |
nv_state_t *nv; |
950 |
nv_state_t *nv; |
977 |
struct page *page_ptr; |
951 |
struct page *page_ptr; |
978 |
int rm_status, index; |
952 |
int rm_status, index; |
979 |
|
953 |
|
980 |
at = VMA_PRIVATE(vma); |
954 |
at = NV_VMA_PRIVATE(vma); |
981 |
if (at == NULL) |
955 |
if (at == NULL) |
982 |
{ |
956 |
{ |
983 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called without an at: " |
957 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called without an at: " |
Lines 1016-1022
Link Here
|
1016 |
// far again |
990 |
// far again |
1017 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called on a freed" |
991 |
nv_printf(NV_DBG_ERRORS, "NVRM: nopage handler called on a freed" |
1018 |
"address: vm_start 0x%x, at 0x%x\n", vma->vm_start, at); |
992 |
"address: vm_start 0x%x, at 0x%x\n", vma->vm_start, at); |
1019 |
VMA_PRIVATE(vma) = NULL; |
993 |
NV_VMA_PRIVATE(vma) = NULL; |
1020 |
return NOPAGE_SIGBUS; |
994 |
return NOPAGE_SIGBUS; |
1021 |
} |
995 |
} |
1022 |
|
996 |
|
Lines 1037-1054
Link Here
|
1037 |
at->page_table[index] = (void *) ((page_ptr - mem_map) << PAGE_SHIFT); |
1011 |
at->page_table[index] = (void *) ((page_ptr - mem_map) << PAGE_SHIFT); |
1038 |
|
1012 |
|
1039 |
return page_ptr; |
1013 |
return page_ptr; |
1040 |
} |
|
|
1041 |
#endif |
1014 |
#endif |
|
|
1015 |
return NOPAGE_SIGBUS; |
1016 |
} |
1042 |
|
1017 |
|
1043 |
struct vm_operations_struct nv_vm_ops = { |
1018 |
struct vm_operations_struct nv_vm_ops = { |
1044 |
nv_kern_vma_open, |
1019 |
nv_kern_vma_open, |
1045 |
nv_kern_vma_release, /* "close" */ |
1020 |
nv_kern_vma_release, /* "close" */ |
1046 |
#if !defined(KERNEL_2_2) |
|
|
1047 |
nv_kern_vma_nopage, |
1021 |
nv_kern_vma_nopage, |
1048 |
#endif |
|
|
1049 |
}; |
1022 |
}; |
1050 |
|
1023 |
|
1051 |
|
|
|
1052 |
/* |
1024 |
/* |
1053 |
** nv_kern_open |
1025 |
** nv_kern_open |
1054 |
** |
1026 |
** |
Lines 1076-1095
Link Here
|
1076 |
|
1048 |
|
1077 |
/* for control device, just jump to its open routine */ |
1049 |
/* for control device, just jump to its open routine */ |
1078 |
/* after setting up the private data */ |
1050 |
/* after setting up the private data */ |
1079 |
if (NV_DEVICE_IS_CONTROL_DEVICE(inode->i_rdev)) |
1051 |
if (NV_IS_CONTROL_DEVICE(inode)) |
1080 |
return nv_kern_ctl_open(inode, file); |
1052 |
return nv_kern_ctl_open(inode, file); |
1081 |
|
1053 |
|
1082 |
/* what device are we talking about? */ |
1054 |
/* what device are we talking about? */ |
1083 |
devnum = NV_DEVICE_NUMBER(inode->i_rdev); |
1055 |
devnum = NV_DEVICE_NUMBER(inode); |
1084 |
if (devnum >= NV_MAX_DEVICES) |
1056 |
if (devnum >= NV_MAX_DEVICES) |
1085 |
{ |
1057 |
{ |
1086 |
rc = -ENODEV; |
1058 |
rc = -ENODEV; |
1087 |
goto failed; |
1059 |
goto failed; |
1088 |
} |
1060 |
} |
1089 |
|
1061 |
|
1090 |
|
|
|
1091 |
MOD_INC_USE_COUNT; |
1092 |
|
1093 |
nvl = &nv_linux_devices[devnum]; |
1062 |
nvl = &nv_linux_devices[devnum]; |
1094 |
nv = NV_STATE_PTR(nvl); |
1063 |
nv = NV_STATE_PTR(nvl); |
1095 |
|
1064 |
|
Lines 1137-1152
Link Here
|
1137 |
goto failed; |
1106 |
goto failed; |
1138 |
} |
1107 |
} |
1139 |
|
1108 |
|
1140 |
#if !defined (KERNEL_2_2) |
1109 |
nvl->tasklet.func = nv_kern_isr_bh; |
1141 |
NV_KMALLOC(nvl->event_queue, sizeof(struct __wait_queue_head)); |
1110 |
nvl->tasklet.data = (unsigned long) nv->pdev; |
1142 |
if (nvl->event_queue == NULL) |
1111 |
tasklet_enable(&nvl->tasklet); |
1143 |
goto failed; |
|
|
1144 |
memset(nvl->event_queue, 0, sizeof(struct __wait_queue_head)); |
1145 |
|
1146 |
init_waitqueue_head(GET_EVENT_QUEUE(nvl)); |
1147 |
#else |
1148 |
nvl->event_queue = NULL; |
1149 |
#endif |
1150 |
|
1112 |
|
1151 |
nv->flags |= NV_FLAG_OPEN; |
1113 |
nv->flags |= NV_FLAG_OPEN; |
1152 |
} |
1114 |
} |
Lines 1157-1163
Link Here
|
1157 |
return rc; |
1119 |
return rc; |
1158 |
|
1120 |
|
1159 |
failed: |
1121 |
failed: |
1160 |
MOD_DEC_USE_COUNT; |
|
|
1161 |
nv_unlock_ldata(nv); |
1122 |
nv_unlock_ldata(nv); |
1162 |
return rc; |
1123 |
return rc; |
1163 |
} |
1124 |
} |
Lines 1179-1216
Link Here
|
1179 |
|
1140 |
|
1180 |
/* for control device, just jump to its open routine */ |
1141 |
/* for control device, just jump to its open routine */ |
1181 |
/* after setting up the private data */ |
1142 |
/* after setting up the private data */ |
1182 |
if (NV_DEVICE_IS_CONTROL_DEVICE(inode->i_rdev)) |
1143 |
if (NV_IS_CONTROL_DEVICE(inode)) |
1183 |
return nv_kern_ctl_close(inode, file); |
1144 |
return nv_kern_ctl_close(inode, file); |
1184 |
|
1145 |
|
1185 |
nv_printf(NV_DBG_INFO, "nv_kern_close on device %d\n", NV_DEVICE_NUMBER(inode->i_rdev)); |
1146 |
nv_printf(NV_DBG_INFO, "nv_kern_close on device %d\n", NV_DEVICE_NUMBER(inode)); |
1186 |
|
1147 |
|
1187 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
1148 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
1188 |
|
1149 |
|
1189 |
nv_lock_ldata(nv); |
1150 |
nv_lock_ldata(nv); |
1190 |
if (--nv->usage_count == 0) |
1151 |
if (--nv->usage_count == 0) |
1191 |
{ |
1152 |
{ |
1192 |
int counter = 0; |
1153 |
/* |
1193 |
|
1154 |
* The usage count for this device has dropped to zero, it can be shut |
1194 |
/* turn off interrupts. |
1155 |
* down safely; disable its interrupts. |
1195 |
** be careful to make sure any pending bottom half gets run |
1156 |
*/ |
1196 |
** or disabled before calling rm_shutdown_adapter() since |
|
|
1197 |
** it will free up the pdev. This is hard to see on single |
1198 |
** cpu systems, but easy on dual cpu :-) |
1199 |
*/ |
1200 |
rm_disable_adapter(nv); |
1157 |
rm_disable_adapter(nv); |
1201 |
|
1158 |
|
1202 |
/* give it a moment to allow any bottom half to run */ |
1159 |
/* |
1203 |
|
1160 |
* Disable this device's tasklet to make sure that no bottom half will |
1204 |
#define MAX_BH_TASKS 10 |
1161 |
* run with undefined device state. |
1205 |
while (NV_ATOMIC_READ(nvl->bh_count) && (counter < MAX_BH_TASKS)) |
1162 |
*/ |
1206 |
{ |
1163 |
tasklet_disable(&nvl->tasklet); |
1207 |
current->state = TASK_INTERRUPTIBLE; |
|
|
1208 |
schedule_timeout(HZ/50); |
1209 |
counter++; |
1210 |
} |
1211 |
|
1164 |
|
1212 |
/* free the irq, which may block until any pending interrupts */ |
1165 |
/* |
1213 |
/* are done being processed. */ |
1166 |
* Free the IRQ, which may block until all pending interrupt processing |
|
|
1167 |
* has completed. |
1168 |
*/ |
1214 |
free_irq(nv->interrupt_line, (void *) nv); |
1169 |
free_irq(nv->interrupt_line, (void *) nv); |
1215 |
|
1170 |
|
1216 |
rm_shutdown_adapter(nv); |
1171 |
rm_shutdown_adapter(nv); |
Lines 1230-1241
Link Here
|
1230 |
} |
1185 |
} |
1231 |
} |
1186 |
} |
1232 |
|
1187 |
|
1233 |
#if !defined (KERNEL_2_2) |
|
|
1234 |
/* this only needs to be freed on 2.4 and later kernels */ |
1235 |
NV_KFREE(nvl->event_queue); |
1236 |
nvl->event_queue = NULL; |
1237 |
#endif |
1238 |
|
1239 |
/* leave INIT flag alone so we don't reinit every time */ |
1188 |
/* leave INIT flag alone so we don't reinit every time */ |
1240 |
nv->flags &= ~(NV_FLAG_OPEN | NV_FLAG_WAITING); |
1189 |
nv->flags &= ~(NV_FLAG_OPEN | NV_FLAG_WAITING); |
1241 |
} |
1190 |
} |
Lines 1246-1253
Link Here
|
1246 |
NV_KFREE(file->private_data); |
1195 |
NV_KFREE(file->private_data); |
1247 |
file->private_data = (void *) 0; |
1196 |
file->private_data = (void *) 0; |
1248 |
|
1197 |
|
1249 |
MOD_DEC_USE_COUNT; |
|
|
1250 |
|
1251 |
return 0; |
1198 |
return 0; |
1252 |
} |
1199 |
} |
1253 |
|
1200 |
|
Lines 1264-1273
Link Here
|
1264 |
nv_printf(NV_DBG_INFO, "mmap([0x%lx-0x%lx] off=0x%lx)\n", |
1211 |
nv_printf(NV_DBG_INFO, "mmap([0x%lx-0x%lx] off=0x%lx)\n", |
1265 |
vma->vm_start, |
1212 |
vma->vm_start, |
1266 |
vma->vm_end, |
1213 |
vma->vm_end, |
1267 |
LINUX_VMA_OFFS(vma)); |
1214 |
NV_VMA_OFFSET(vma)); |
1268 |
|
1215 |
|
1269 |
// be a bit paranoid for now |
1216 |
// be a bit paranoid for now |
1270 |
if ((NV_MASK_OFFSET(LINUX_VMA_OFFS(vma))) || |
1217 |
if ((NV_MASK_OFFSET(NV_VMA_OFFSET(vma))) || |
1271 |
(NV_MASK_OFFSET(vma->vm_start)) || |
1218 |
(NV_MASK_OFFSET(vma->vm_start)) || |
1272 |
(NV_MASK_OFFSET(vma->vm_end))) |
1219 |
(NV_MASK_OFFSET(vma->vm_end))) |
1273 |
{ |
1220 |
{ |
Lines 1285-1291
Link Here
|
1285 |
|
1232 |
|
1286 |
|
1233 |
|
1287 |
/* NV reg space */ |
1234 |
/* NV reg space */ |
1288 |
if (IS_REG_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1235 |
if (IS_REG_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
1289 |
{ |
1236 |
{ |
1290 |
/* truncate to size of registers */ |
1237 |
/* truncate to size of registers */ |
1291 |
if (pages > nv->regs->size / PAGE_SIZE) |
1238 |
if (pages > nv->regs->size / PAGE_SIZE) |
Lines 1293-1299
Link Here
|
1293 |
|
1240 |
|
1294 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1241 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1295 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1242 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1296 |
LINUX_VMA_OFFS(vma), |
1243 |
NV_VMA_OFFSET(vma), |
1297 |
vma->vm_end - vma->vm_start, |
1244 |
vma->vm_end - vma->vm_start, |
1298 |
vma->vm_page_prot)) |
1245 |
vma->vm_page_prot)) |
1299 |
return -EAGAIN; |
1246 |
return -EAGAIN; |
Lines 1303-1309
Link Here
|
1303 |
} |
1250 |
} |
1304 |
|
1251 |
|
1305 |
/* NV fb space */ |
1252 |
/* NV fb space */ |
1306 |
else if (IS_FB_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1253 |
else if (IS_FB_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
1307 |
{ |
1254 |
{ |
1308 |
|
1255 |
|
1309 |
/* truncate to size of framebuffer */ |
1256 |
/* truncate to size of framebuffer */ |
Lines 1312-1318
Link Here
|
1312 |
|
1259 |
|
1313 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1260 |
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
1314 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1261 |
if (NV_REMAP_PAGE_RANGE(vma->vm_start, |
1315 |
LINUX_VMA_OFFS(vma), |
1262 |
NV_VMA_OFFSET(vma), |
1316 |
vma->vm_end - vma->vm_start, |
1263 |
vma->vm_end - vma->vm_start, |
1317 |
vma->vm_page_prot)) |
1264 |
vma->vm_page_prot)) |
1318 |
return -EAGAIN; |
1265 |
return -EAGAIN; |
Lines 1322-1331
Link Here
|
1322 |
} |
1269 |
} |
1323 |
|
1270 |
|
1324 |
/* AGP allocator */ |
1271 |
/* AGP allocator */ |
1325 |
else if (IS_AGP_OFFSET(nv, LINUX_VMA_OFFS(vma), vma->vm_end - vma->vm_start)) |
1272 |
else if (IS_AGP_OFFSET(nv, NV_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) |
1326 |
{ |
1273 |
{ |
1327 |
nv_lock_at(nv); |
1274 |
nv_lock_at(nv); |
1328 |
at = nvl_find_alloc(nvl, LINUX_VMA_OFFS(vma), NV_ALLOC_TYPE_AGP); |
1275 |
at = nvl_find_alloc(nvl, NV_VMA_OFFSET(vma), NV_ALLOC_TYPE_AGP); |
1329 |
|
1276 |
|
1330 |
if (at == NULL) |
1277 |
if (at == NULL) |
1331 |
{ |
1278 |
{ |
Lines 1343-1349
Link Here
|
1343 |
} |
1290 |
} |
1344 |
|
1291 |
|
1345 |
at->vma = vma; |
1292 |
at->vma = vma; |
1346 |
VMA_PRIVATE(vma) = at; |
1293 |
NV_VMA_PRIVATE(vma) = at; |
1347 |
at->usage_count++; |
1294 |
at->usage_count++; |
1348 |
|
1295 |
|
1349 |
if (NV_OSAGP_ENABLED(nv)) |
1296 |
if (NV_OSAGP_ENABLED(nv)) |
Lines 1366-1378
Link Here
|
1366 |
} |
1313 |
} |
1367 |
|
1314 |
|
1368 |
/* Magic allocator */ |
1315 |
/* Magic allocator */ |
1369 |
else // if (LINUX_VMA_OFFS(vma) == NV_MMAP_ALLOCATION_OFFSET) |
1316 |
else // if (NV_VMA_OFFSET(vma) == NV_MMAP_ALLOCATION_OFFSET) |
1370 |
{ |
1317 |
{ |
1371 |
unsigned long page = 0, pos, start; |
1318 |
unsigned long page = 0, pos, start; |
1372 |
int i = 0; |
1319 |
int i = 0; |
1373 |
|
1320 |
|
1374 |
nv_lock_at(nv); |
1321 |
nv_lock_at(nv); |
1375 |
at = nvl_find_alloc(nvl, LINUX_VMA_OFFS(vma), NV_ALLOC_TYPE_PCI); |
1322 |
at = nvl_find_alloc(nvl, NV_VMA_OFFSET(vma), NV_ALLOC_TYPE_PCI); |
1376 |
|
1323 |
|
1377 |
if (at == NULL) |
1324 |
if (at == NULL) |
1378 |
{ |
1325 |
{ |
Lines 1390-1396
Link Here
|
1390 |
} |
1337 |
} |
1391 |
|
1338 |
|
1392 |
at->vma = vma; |
1339 |
at->vma = vma; |
1393 |
VMA_PRIVATE(vma) = at; |
1340 |
NV_VMA_PRIVATE(vma) = at; |
1394 |
at->usage_count++; |
1341 |
at->usage_count++; |
1395 |
|
1342 |
|
1396 |
nv_printf(NV_DBG_INFO, "remapping %d system pages for at 0x%x\n", pages, at); |
1343 |
nv_printf(NV_DBG_INFO, "remapping %d system pages for at 0x%x\n", pages, at); |
Lines 1412-1420
Link Here
|
1412 |
|
1359 |
|
1413 |
vma->vm_file = file; |
1360 |
vma->vm_file = file; |
1414 |
|
1361 |
|
1415 |
/* just increment usage count, rather than calling vma_open */ |
|
|
1416 |
MOD_INC_USE_COUNT; |
1417 |
|
1418 |
return 0; |
1362 |
return 0; |
1419 |
} |
1363 |
} |
1420 |
|
1364 |
|
Lines 1439-1445
Link Here
|
1439 |
return nv_kern_ctl_poll (file, wait); |
1383 |
return nv_kern_ctl_poll (file, wait); |
1440 |
|
1384 |
|
1441 |
// add us to the list |
1385 |
// add us to the list |
1442 |
poll_wait(file, GET_EVENT_QUEUE(nvl), wait); |
1386 |
poll_wait(file, &nvl->waitqueue, wait); |
1443 |
|
1387 |
|
1444 |
nv_lock_ldata(nv); |
1388 |
nv_lock_ldata(nv); |
1445 |
|
1389 |
|
Lines 1519-1530
Link Here
|
1519 |
|
1463 |
|
1520 |
switch (_IOC_NR(cmd)) |
1464 |
switch (_IOC_NR(cmd)) |
1521 |
{ |
1465 |
{ |
|
|
1466 |
#if !defined(KERNEL_2_6) |
1522 |
/* debug tool; zap the module use count so we can unload driver */ |
1467 |
/* debug tool; zap the module use count so we can unload driver */ |
1523 |
/* even if it is confused */ |
1468 |
/* even if it is confused */ |
1524 |
case _IOC_NR(NV_IOCTL_MODULE_RESET): |
1469 |
case _IOC_NR(NV_IOCTL_MODULE_RESET): |
1525 |
atomic_set(&__this_module.uc.usecount, 1); |
1470 |
atomic_set(&__this_module.uc.usecount, 1); |
1526 |
break; |
1471 |
break; |
1527 |
|
1472 |
#endif |
1528 |
/* pass out info about the card */ |
1473 |
/* pass out info about the card */ |
1529 |
case _IOC_NR(NV_IOCTL_CARD_INFO): |
1474 |
case _IOC_NR(NV_IOCTL_CARD_INFO): |
1530 |
{ |
1475 |
{ |
Lines 1651-1657
Link Here
|
1651 |
* driver receives an interrupt |
1596 |
* driver receives an interrupt |
1652 |
* if someone waiting, then hand it off. |
1597 |
* if someone waiting, then hand it off. |
1653 |
*/ |
1598 |
*/ |
1654 |
void nv_kern_isr( |
1599 |
irqreturn_t nv_kern_isr( |
1655 |
int irq, |
1600 |
int irq, |
1656 |
void *arg, |
1601 |
void *arg, |
1657 |
struct pt_regs *regs |
1602 |
struct pt_regs *regs |
Lines 1664-1684
Link Here
|
1664 |
rm_isr(nv->device_number, &need_to_run_bottom_half); |
1609 |
rm_isr(nv->device_number, &need_to_run_bottom_half); |
1665 |
if (need_to_run_bottom_half) |
1610 |
if (need_to_run_bottom_half) |
1666 |
{ |
1611 |
{ |
1667 |
NV_ATOMIC_INC(nvl->bh_count); |
1612 |
tasklet_schedule(&nvl->tasklet); |
1668 |
queue_task(nvl->bh, &tq_immediate); |
|
|
1669 |
mark_bh(IMMEDIATE_BH); |
1670 |
} |
1613 |
} |
|
|
1614 |
|
1615 |
return IRQ_HANDLED; |
1671 |
} |
1616 |
} |
1672 |
|
1617 |
|
1673 |
void nv_kern_bh( |
1618 |
void nv_kern_isr_bh(unsigned long data) |
1674 |
void *data |
|
|
1675 |
) |
1676 |
{ |
1619 |
{ |
1677 |
nv_linux_state_t *nvl = (nv_linux_state_t *) data; |
1620 |
/* |
1678 |
nv_state_t *nv = NV_STATE_PTR(nvl); |
1621 |
* XXX: This level of indirection is necessary to work around |
1679 |
|
1622 |
* problems with Linux kernels using a non-standard calling |
1680 |
NV_ATOMIC_DEC(nvl->bh_count); |
1623 |
* convention, i.e. Arjan van de Ven's/RedHat's 2.6.0 kernels. |
1681 |
rm_isr_bh(nv->pdev); |
1624 |
*/ |
|
|
1625 |
rm_isr_bh((VOID *) data); |
1682 |
} |
1626 |
} |
1683 |
|
1627 |
|
1684 |
void nv_kern_rc_timer( |
1628 |
void nv_kern_rc_timer( |
Lines 1760-1785
Link Here
|
1760 |
/* save the nv away in file->private_data */ |
1704 |
/* save the nv away in file->private_data */ |
1761 |
NV_HIDE_IN_FILEP(file, nv); |
1705 |
NV_HIDE_IN_FILEP(file, nv); |
1762 |
|
1706 |
|
1763 |
MOD_INC_USE_COUNT; |
|
|
1764 |
|
1765 |
/* if this is the first time the control device has been opened, |
1766 |
* allocate the wait queue |
1767 |
*/ |
1768 |
|
1769 |
if (! nvl->event_queue) { |
1770 |
|
1771 |
#if !defined (KERNEL_2_2) |
1772 |
NV_KMALLOC(nvl->event_queue, sizeof(struct __wait_queue_head)); |
1773 |
if (nvl->event_queue == NULL) |
1774 |
return -ENOMEM; |
1775 |
memset(nvl->event_queue, 0, sizeof(struct __wait_queue_head)); |
1776 |
|
1777 |
init_waitqueue_head(GET_EVENT_QUEUE(nvl)); |
1778 |
#else |
1779 |
nvl->event_queue = NULL; |
1780 |
#endif |
1781 |
} |
1782 |
|
1783 |
nv->flags |= NV_FLAG_OPEN + NV_FLAG_CONTROL; |
1707 |
nv->flags |= NV_FLAG_OPEN + NV_FLAG_CONTROL; |
1784 |
|
1708 |
|
1785 |
/* turn off the hotkey occurred bit */ |
1709 |
/* turn off the hotkey occurred bit */ |
Lines 1807-1821
Link Here
|
1807 |
|
1731 |
|
1808 |
nv_lock_ldata(nv); |
1732 |
nv_lock_ldata(nv); |
1809 |
if (--nv->usage_count == 0) |
1733 |
if (--nv->usage_count == 0) |
1810 |
{ |
|
|
1811 |
#if !defined (KERNEL_2_2) |
1812 |
nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); |
1813 |
/* this only needs to be freed on 2.4 and later kernels */ |
1814 |
NV_KFREE(nvl->event_queue); |
1815 |
nvl->event_queue = 0; |
1816 |
#endif |
1817 |
nv->flags = 0; |
1734 |
nv->flags = 0; |
1818 |
} |
|
|
1819 |
nv_unlock_ldata(nv); |
1735 |
nv_unlock_ldata(nv); |
1820 |
|
1736 |
|
1821 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
1737 |
rm_free_unused_clients(nv, current->pid, (void *) file); |
Lines 1825-1832
Link Here
|
1825 |
NV_KFREE(file->private_data); |
1741 |
NV_KFREE(file->private_data); |
1826 |
file->private_data = (void *) 0; |
1742 |
file->private_data = (void *) 0; |
1827 |
|
1743 |
|
1828 |
MOD_DEC_USE_COUNT; |
|
|
1829 |
|
1830 |
return 0; |
1744 |
return 0; |
1831 |
} |
1745 |
} |
1832 |
|
1746 |
|
Lines 1851-1857
Link Here
|
1851 |
if (file->f_flags & O_NONBLOCK) |
1765 |
if (file->f_flags & O_NONBLOCK) |
1852 |
return -EAGAIN; |
1766 |
return -EAGAIN; |
1853 |
|
1767 |
|
1854 |
poll_wait(file, GET_EVENT_QUEUE(nvl), wait); |
1768 |
poll_wait(file, &nvl->waitqueue, wait); |
1855 |
|
1769 |
|
1856 |
nv_lock_ldata(nv); |
1770 |
nv_lock_ldata(nv); |
1857 |
|
1771 |
|
Lines 1881-1887
Link Here
|
1881 |
nv_ctl_device.nv_state.flags |= NV_FLAG_HOTKEY_OCCURRED; |
1795 |
nv_ctl_device.nv_state.flags |= NV_FLAG_HOTKEY_OCCURRED; |
1882 |
nv_unlock_ldata(&(nv_ctl_device.nv_state)); |
1796 |
nv_unlock_ldata(&(nv_ctl_device.nv_state)); |
1883 |
|
1797 |
|
1884 |
wake_up_interruptible(GET_EVENT_QUEUE(&nv_ctl_device)); |
1798 |
wake_up_interruptible(&nv_ctl_device.waitqueue); |
1885 |
} |
1799 |
} |
1886 |
|
1800 |
|
1887 |
int nv_kern_read_cardinfo(char *page, char **start, off_t off, |
1801 |
int nv_kern_read_cardinfo(char *page, char **start, off_t off, |
Lines 1960-1966
Link Here
|
1960 |
len += sprintf(page+len, "Host Bridge: \t "); |
1874 |
len += sprintf(page+len, "Host Bridge: \t "); |
1961 |
|
1875 |
|
1962 |
#if defined(CONFIG_PCI_NAMES) |
1876 |
#if defined(CONFIG_PCI_NAMES) |
1963 |
len += sprintf(page+len, "%s\n", dev->name); |
1877 |
len += sprintf(page+len, "%s\n", NV_PCI_DEVICE_NAME(dev)); |
1964 |
#else |
1878 |
#else |
1965 |
len += sprintf(page+len, "PCI device %04x:%04x\n", |
1879 |
len += sprintf(page+len, "PCI device %04x:%04x\n", |
1966 |
dev->vendor, dev->device); |
1880 |
dev->vendor, dev->device); |
Lines 2088-2105
Link Here
|
2088 |
{ |
2002 |
{ |
2089 |
unsigned long retaddr = (unsigned long) at->page_table[i]; |
2003 |
unsigned long retaddr = (unsigned long) at->page_table[i]; |
2090 |
|
2004 |
|
2091 |
if (retaddr <= MAXMEM) |
2005 |
/* |
2092 |
{ |
2006 |
* XXX This routine should be more straight-forward; as it |
2093 |
return __va((retaddr + offset)); |
2007 |
* is, it returns a pointer into the kernel linear mapping if |
2094 |
} |
2008 |
* the incoming address belongs to a vmalloc() allocation or |
2095 |
|
2009 |
* the kernel logical mapping of the corresponding page if it |
2096 |
// if we've allocated via vmalloc on a highmem system, the |
2010 |
* was allocated with alloc_pages(); third case below. |
2097 |
// physical address may not be accessible via PAGE_OFFSET, |
2011 |
*/ |
2098 |
// that's ok, we have a simple linear pointer already. |
|
|
2099 |
if (at->flags & NV_ALLOC_TYPE_VMALLOC) |
2012 |
if (at->flags & NV_ALLOC_TYPE_VMALLOC) |
2100 |
{ |
2013 |
{ |
2101 |
return (void *)((unsigned char *) at->key_mapping + (i << PAGE_SHIFT) + offset); |
2014 |
return (void *)((unsigned char *) at->key_mapping + (i << PAGE_SHIFT) + offset); |
2102 |
} |
2015 |
} |
|
|
2016 |
else if (!(at->flags & NV_ALLOC_TYPE_CONTIG)) |
2017 |
{ |
2018 |
return __va((retaddr + offset)); |
2019 |
} |
2103 |
|
2020 |
|
2104 |
// ?? this may be a contiguous allocation, fall through |
2021 |
// ?? this may be a contiguous allocation, fall through |
2105 |
// to below? or should I just check at->flag here? |
2022 |
// to below? or should I just check at->flag here? |
Lines 2169-2177
Link Here
|
2169 |
unsigned long |
2086 |
unsigned long |
2170 |
nv_get_phys_address(unsigned long address) |
2087 |
nv_get_phys_address(unsigned long address) |
2171 |
{ |
2088 |
{ |
2172 |
pgd_t *pg_dir; |
2089 |
pgd_t *pgd; |
2173 |
pmd_t *pg_mid_dir; |
2090 |
pmd_t *pmd; |
2174 |
pte_t pte; |
2091 |
pte_t *pte; |
2175 |
|
2092 |
|
2176 |
#if defined(NVCPU_IA64) |
2093 |
#if defined(NVCPU_IA64) |
2177 |
if (address > __IA64_UNCACHED_OFFSET) |
2094 |
if (address > __IA64_UNCACHED_OFFSET) |
Lines 2184-2206
Link Here
|
2184 |
return __pa(address); |
2101 |
return __pa(address); |
2185 |
|
2102 |
|
2186 |
if (address > VMALLOC_START) |
2103 |
if (address > VMALLOC_START) |
2187 |
pg_dir = pgd_offset_k(address); |
2104 |
pgd = pgd_offset_k(address); |
2188 |
else |
2105 |
else |
2189 |
pg_dir = pgd_offset(current->mm, address); |
2106 |
pgd = pgd_offset(current->mm, address); |
2190 |
|
2107 |
|
2191 |
if (pgd_none(*pg_dir)) |
2108 |
if (!pgd || pgd_none(*pgd)) |
2192 |
goto failed; |
2109 |
goto failed; |
2193 |
|
2110 |
|
2194 |
pg_mid_dir = pmd_offset(pg_dir, address); |
2111 |
NV_PMD_OFFSET(address, pgd, pmd); |
2195 |
if (pmd_none(*pg_mid_dir)) |
2112 |
|
|
|
2113 |
if (!NV_PMD_PRESENT(pmd)) |
2196 |
goto failed; |
2114 |
goto failed; |
2197 |
|
2115 |
|
2198 |
NV_PTE_OFFSET(address, pg_mid_dir, pte); |
2116 |
NV_PTE_OFFSET(address, pmd, pte); |
2199 |
|
2117 |
|
2200 |
if (!pte_present(pte)) |
2118 |
if (!NV_PTE_PRESENT(pte)) |
2201 |
goto failed; |
2119 |
goto failed; |
2202 |
|
2120 |
|
2203 |
return ((pte_val(pte) & KERN_PAGE_MASK) | NV_MASK_OFFSET(address)); |
2121 |
return (NV_PTE_VALUE(pte) & KERN_PAGE_MASK) | NV_MASK_OFFSET(address); |
2204 |
|
2122 |
|
2205 |
failed: |
2123 |
failed: |
2206 |
return (unsigned long) NULL; |
2124 |
return (unsigned long) NULL; |
Lines 2567-2573
Link Here
|
2567 |
|
2485 |
|
2568 |
nvfp->any_fired_notifiers++; |
2486 |
nvfp->any_fired_notifiers++; |
2569 |
|
2487 |
|
2570 |
wake_up_interruptible(GET_EVENT_QUEUE(nvl)); |
2488 |
wake_up_interruptible(&nvl->waitqueue); |
2571 |
} |
2489 |
} |
2572 |
|
2490 |
|
2573 |
/* |
2491 |
/* |
Lines 2584-2590
Link Here
|
2584 |
if (nvl->waiting_for_vblank) |
2502 |
if (nvl->waiting_for_vblank) |
2585 |
nvl->vblank_notifier++; |
2503 |
nvl->vblank_notifier++; |
2586 |
|
2504 |
|
2587 |
wake_up_interruptible(GET_EVENT_QUEUE(nvl)); |
2505 |
wake_up_interruptible(&nvl->waitqueue); |
2588 |
} |
2506 |
} |
2589 |
|
2507 |
|
2590 |
|
2508 |
|
Lines 2633-2644
Link Here
|
2633 |
if ( (NV_AGP_DISABLED(nv)) && (config & NVOS_AGP_CONFIG_NVAGP) ) |
2551 |
if ( (NV_AGP_DISABLED(nv)) && (config & NVOS_AGP_CONFIG_NVAGP) ) |
2634 |
{ |
2552 |
{ |
2635 |
/* make sure the user does not have agpgart loaded */ |
2553 |
/* make sure the user does not have agpgart loaded */ |
2636 |
#if !defined (KERNEL_2_2) |
|
|
2637 |
if (inter_module_get("drm_agp")) { |
2554 |
if (inter_module_get("drm_agp")) { |
2638 |
inter_module_put("drm_agp"); |
2555 |
inter_module_put("drm_agp"); |
2639 |
#else |
|
|
2640 |
if (GET_MODULE_SYMBOL(0, __MODULE_STRING(agp_enable))) { |
2641 |
#endif |
2642 |
nv_printf(NV_DBG_WARNINGS, "NVRM: not using NVAGP, AGPGART is loaded!!\n"); |
2556 |
nv_printf(NV_DBG_WARNINGS, "NVRM: not using NVAGP, AGPGART is loaded!!\n"); |
2643 |
} else |
2557 |
} else |
2644 |
status = rm_init_agp(nv); |
2558 |
status = rm_init_agp(nv); |