20_page

Document Sample

Shared by: fnordium
Categories
Tags
Stats
views:
139
posted:
9/26/2007
language:
English
pages:
21
/* _NVRM_COPYRIGHT_BEGIN_ * * Copyright 1999-2001 by NVIDIA Corporation. All rights reserved. All * information contained herein is proprietary and confidential to NVIDIA * Corporation. Any use, reproduction, or disclosure without the written * permission of NVIDIA Corporation is prohibited. * * _NVRM_COPYRIGHT_END_ */



#include #include #include #include #include #include



"nv-misc.h" "os-interface.h" "nv-linux.h" "nv_compiler.h" "os-agp.h" "nv-vm.h"



#ifdef MODULE_ALIAS_CHARDEV_MAJOR MODULE_ALIAS_CHARDEV_MAJOR(NV_MAJOR_DEVICE_NUMBER); #endif /* * our global state; one per device */ static U032 num_nv_devices = 0; static U032 num_probed_nv_devices = 0; static nv_linux_state_t nv_linux_devices[NV_MAX_DEVICES]; #if defined(NV_PM_SUPPORT_APM) static struct pm_dev *apm_nv_dev[NV_MAX_DEVICES] = { 0 }; #endif int nv_pat_enabled = 0; static int nv_disable_pat = 0; NV_MODULE_PARAMETER(nv_disable_pat); #if defined(NVCPU_X86) || defined(NVCPU_X86_64) NvU64 __nv_supported_pte_mask = ~_PAGE_NX; #endif /* * And one for the control device */ nv_linux_state_t nv_ctl_device = { { 0 } }; wait_queue_head_t nv_ctl_waitqueue; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_nvidia; struct proc_dir_entry *proc_nvidia_warnings; #endif static const char *__README_warning = \ "The NVIDIA graphics driver tries to detect potential problems\n" "with the host system and warns about them using the system's\n" "logging mechanisms. Important warning message are also logged\n" "to dedicated text files in this directory.\n"; #if defined(NV_SWIOTLB)



static const char *__swiotlb_warning = \ "You are probably using the kernel's SWIOTLB interface.\n\n" "Be very careful with this interface, as it is easy to exhaust\n" "its memory buffer, at which point it may panic the kernel.\n" "Please increase the default size of this buffer by specifying\n" "a larger buffer size with the \"swiotlb\" kernel parameter,\n" "e.g.: \"swiotlb=65536\".\n"; #endif #if defined(NV_CHANGE_PAGE_ATTR_BUG_PRESENT) static const char *__cpgattr_warning = \ "Your Linux kernel has known problems in its implementation of\n" "the change_page_attr() kernel interface.\n\n" "The NVIDIA graphics driver will attempt to work around these\n" "problems, but system stability may be adversely affected.\n" "It is recommended that you update to Linux 2.6.11 (or a newer\n" "Linux kernel release).\n"; #endif #if defined(NV_SG_MAP_BUFFERS) int nv_swiotlb = 0; unsigned int nv_remap_count; unsigned int nv_remap_limit; #endif #ifdef NV_CHANGE_PAGE_ATTR_PRESENT int nv_use_cpa = 1; #endif static kmem_cache_t *nv_pte_t_cache = NULL; // allow an easy way to convert all debug printfs related to events // back and forth between 'info' and 'errors' #if defined(NV_DBG_EVENTS) #define NV_DBG_EVENTINFO NV_DBG_ERRORS #else #define NV_DBG_EVENTINFO NV_DBG_INFO #endif // // // // // // verify access to pci config space wasn't disabled behind our back unfortunately, XFree86 enables/disables memory access in pci config space at various times (such as restoring initial pci config space settings during vt switches or when doing mulicard). As a result, all of our register accesses are garbage at this point. add a check to see if access was disabled and reenable any such access.



static void verify_pci_bars( nv_state_t *nv, void *dev_handle ) { U032 bar, bar_hi, bar_lo; for (bar = 0; bar bars[bar]; bar_lo = bar_hi = 0; if (tmp->offset == 0) continue; bar_lo = os_pci_read_dword(dev_handle, tmp->offset);



// add comment about X misdetecting bar overflow (0xffffffff) if ((bar_lo & NVRM_PCICFG_BAR_ADDR_MASK) != tmp->address) { // NOW we're in trouble! nv_printf(NV_DBG_USERERRORS, "NVRM: Incorrect BAR%d = 0x%08x, restoring 0x%08x\n", bar, bar_lo, tmp->address); os_pci_write_dword(dev_handle, tmp->offset, tmp->address); #if defined(DEBUG) bar_lo = os_pci_read_dword(dev_handle, tmp->offset); nv_printf(NV_DBG_USERERRORS, "NVRM: restored as 0x%08x\n", bar_lo); #endif } if ((bar_lo & NVRM_PCICFG_BAR_MEMTYPE_MASK) != NVRM_PCICFG_BAR_MEMTYPE_64BIT) continue; bar_hi = os_pci_read_dword(dev_handle, tmp->offset + 4); if ((bar_lo & NVRM_PCICFG_BAR_ADDR_MASK) == tmp->address && bar_hi == 0) continue; // NOW we're in trouble! nv_printf(NV_DBG_USERERRORS, "NVRM: Incorrect BAR%d = 0x%08x%08x, restoring 0x00000000%08x\n", bar, bar_hi, bar_lo, tmp->address); os_pci_write_dword(dev_handle, tmp->offset, tmp->address); os_pci_write_dword(dev_handle, tmp->offset + 4, 0); #if defined(DEBUG) bar_lo = os_pci_read_dword(dev_handle, tmp->offset); bar_hi = os_pci_read_dword(dev_handle, tmp->offset + 4); nv_printf(NV_DBG_USERERRORS, "NVRM: restored as 0x%08x:0x%08x\n", bar_hi, bar_lo); #endif } }



void NV_API_CALL nv_verify_pci_config(nv_state_t *nv, BOOL do_the_bars) { nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); unsigned short cmd, flag = 0; // don't do this on the control device, only the actual devices if (nv->flags & NV_FLAG_CONTROL) return; pci_read_config_word(nvl->dev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { nv_printf(NV_DBG_USERERRORS, "NVRM: restoring bus mastering!\n"); cmd |= PCI_COMMAND_MASTER; flag = 1; } if (!(cmd & PCI_COMMAND_MEMORY)) { nv_printf(NV_DBG_USERERRORS, "NVRM: restoring MEM access!\n"); cmd |= PCI_COMMAND_MEMORY; flag = 1; }



if (flag) pci_write_config_word(nvl->dev, PCI_COMMAND, cmd); if (do_the_bars && NV_MAY_SLEEP()) verify_pci_bars(nv, nvl->dev); } /*** *** STATIC functions, only in this file ***/ /* nvos_ functions.. do not take a state device parameter */ static int nvos_post_vbios(nv_ioctl_post_vbios_t *info); static void nvos_proc_create(void); static void nvos_proc_add_warning_file(const char *, const char *); static void nvos_proc_remove_all(struct proc_dir_entry *); static void nvos_proc_remove(void); static int nvos_count_devices(void); static nv_alloc_t static int *nvos_create_alloc(struct pci_dev *, int); nvos_free_alloc(nv_alloc_t *);



/* nvl_ functions.. take a linux state device pointer */ static nv_alloc_t *nvl_find_alloc(nv_linux_state_t *, unsigned long, unsigned long); static int nvl_add_alloc(nv_linux_state_t *, nv_alloc_t *); static int nvl_remove_alloc(nv_linux_state_t *, nv_alloc_t *); /* lock-related functions that should only be called from this file */ static void nv_lock_init_locks(nv_state_t *nv); #define #define #define #define #define nv_init_lock(lock) nv_lock(lock) nv_unlock(lock) nv_down(lock) nv_up(lock) spin_lock_init(&lock) spin_lock(&lock) spin_unlock(&lock) down(&lock) up(&lock) spin_lock_irqsave(&lock,flags) spin_unlock_irqrestore(&lock,flags)



#define nv_lock_irq(lock,flags) #define nv_unlock_irq(lock,flags)



/*** *** EXPORTS to Linux Kernel ***/ /* nv_kern_ functions, interfaces used by linux kernel */ void nv_kern_vma_open(struct vm_area_struct *vma); void nv_kern_vma_release(struct vm_area_struct *vma); int nv_kern_open(struct inode *, struct file *); int nv_kern_close(struct inode *, struct file *); int nv_kern_mmap(struct file *, struct vm_area_struct *); unsigned int nv_kern_poll(struct file *, poll_table *); int nv_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long); long nv_kern_compat_ioctl(struct file *, unsigned int, unsigned long); void nv_kern_isr_bh(unsigned long); irqreturn_t nv_kern_isr(int, void *, struct pt_regs *); void nv_kern_rc_timer(unsigned long); #if defined(NV_PM_SUPPORT_APM) int nv_kern_apm_event(struct pm_dev *dev, pm_request_t rqst, void *data); #endif static int nv_kern_read_cardinfo(char *, char **, off_t off, int, int *, void *);



static static static static static



int int int int int



nv_kern_read_status(char *, char **, off_t off, int, int *, void *); nv_kern_read_registry(char *, char **, off_t off, int, int *, void *); nv_kern_read_agpinfo(char *, char **, off_t off, int, int *, void *); nv_kern_read_version(char *, char **, off_t off, int, int *, void *); nv_kern_read_warning(char *, char **, off_t off, int, int *, void *);



#ifdef NV_STACKWATCH static ssize_t nv_stackwatch_read(struct file *, char *, size_t, loff_t *); static ssize_t nv_stackwatch_write(struct file *, const char *, size_t, loff_t *); #endif int int unsigned int nv_kern_ctl_open(struct inode *, struct file *); nv_kern_ctl_close(struct inode *, struct file *); nv_kern_ctl_poll(struct file *, poll_table *);



int nv_kern_probe(struct pci_dev *, const struct pci_device_id *); #if defined(NV_PM_SUPPORT_ACPI) int nv_kern_acpi_standby(struct pci_dev *, u32); int nv_kern_acpi_resume(struct pci_dev *); #endif /*** *** see nv.h for functions exported to other parts of resman ***/ static struct pci_device_id nv_pci_table[] = { { .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .class = (PCI_CLASS_DISPLAY_VGA bus == info->bus && nv->slot == info->slot) { // we assume any device was already posted and rely on // X to tell us which cards need posting. But if we've // already manually posted a card, it doesn't need to // be reposted again. if (!(nv->flags & NV_FLAG_WAS_POSTED || nv->flags & NV_FLAG_OPEN)) { nv->flags |= NV_FLAG_NEEDS_POSTING; } } } return 0; } static nv_alloc_t *nvos_create_alloc( struct pci_dev *dev, int num_pages ) { nv_alloc_t *at; unsigned int pt_size, i; NV_KMALLOC(at, sizeof(nv_alloc_t)); if (at == NULL) { nv_printf(NV_DBG_ERRORS, "NVRM: failed to allocate alloc info\n"); return NULL; } memset(at, 0, sizeof(nv_alloc_t));



pt_size = num_pages * sizeof(nv_pte_t *); if (os_alloc_mem((void **)&at->page_table, pt_size) != RM_OK) { nv_printf(NV_DBG_ERRORS, "NVRM: failed to allocate page table\n"); NV_KFREE(at, sizeof(nv_alloc_t)); return NULL; } memset(at->page_table, 0, pt_size); at->num_pages = num_pages; NV_ATOMIC_SET(at->usage_count, 0); for (i = 0; i num_pages; i++) { NV_KMEM_CACHE_ALLOC(at->page_table[i], nv_pte_t_cache, nv_pte_t); if (at->page_table[i] == NULL) { nv_printf(NV_DBG_ERRORS, "NVRM: failed to allocate page table entry\n"); nvos_free_alloc(at); return NULL; } memset(at->page_table[i], 0, sizeof(nv_pte_t)); } return at; } static int nvos_free_alloc( nv_alloc_t *at ) { unsigned int i; if (at == NULL) return -1; if (NV_ATOMIC_READ(at->usage_count)) return 1; // // // if { we keep the page_table around after freeing the pages for bookkeeping reasons. Free the page_table and assume the underlying pages are already unlocked and freed. (at->page_table != NULL) for (i = 0; i num_pages; i++) { if (at->page_table[i] != NULL) NV_KMEM_CACHE_FREE(at->page_table[i], nv_pte_t, nv_pte_t_cache); } os_free_mem(at->page_table); } NV_KFREE(at, sizeof(nv_alloc_t)); return 0; } static u8 nvos_find_agp_capability(struct pci_dev *dev) { u16 status; u8 cap_ptr, cap_id;



pci_read_config_word(dev, PCI_STATUS, &status); status &= PCI_STATUS_CAP_LIST; if (!status) return 0; switch (dev->hdr_type) { case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_BRIDGE: pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); break; default: return 0; } do { cap_ptr &= 0xfc; pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_ID, &cap_id); if (cap_id == PCI_CAP_ID_AGP) return cap_ptr; pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_NEXT, &cap_ptr); } while (cap_ptr && cap_id != 0xff); return 0; } static u8 nvos_find_pci_express_capability(struct pci_dev *dev) { u16 status; u8 cap_ptr, cap_id; pci_read_config_word(dev, PCI_STATUS, &status); status &= PCI_STATUS_CAP_LIST; if (!status) return 0; switch (dev->hdr_type) { case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_BRIDGE: pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); break; default: return 0; } do { cap_ptr &= 0xfc; pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_ID, &cap_id); if (cap_id == PCI_CAP_ID_EXP) return cap_ptr; pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_NEXT, &cap_ptr); } while (cap_ptr && cap_id != 0xff); return 0; } static struct pci_dev* nvos_get_agp_device_by_class(unsigned int class) { struct pci_dev *dev, *fdev; u32 slot, func, fn; dev = NV_PCI_GET_CLASS(class vendor_id, nv->device_id, NULL); while (dev) { if (NV_PCI_SLOT_NUMBER(dev) == nv->slot && NV_PCI_BUS_NUMBER(dev) == nv->bus) return dev; dev = NV_PCI_GET_DEVICE(nv->vendor_id, nv->device_id, dev); } return NULL; } #if defined(CONFIG_PROC_FS) && defined(NV_STACKWATCH) static struct file_operations nv_stackwatch_fops = { read: nv_stackwatch_read, write: nv_stackwatch_write, }; #endif static void nvos_proc_create(void) { #ifdef CONFIG_PROC_FS struct pci_dev *dev; U032 j, i = 0; char name[6]; struct proc_dir_entry *entry; struct proc_dir_entry *proc_nvidia_agp, *proc_nvidia_cards; /* world readable directory */ int d_flags = S_IFDIR | S_IRUGO | S_IXUGO; /* world readable file */ int flags = S_IFREG | S_IRUGO; nv_state_t *nv; nv_linux_state_t *nvl; proc_nvidia = create_proc_entry("nvidia", d_flags, proc_root_driver); if (!proc_nvidia) goto failed;



proc_nvidia_cards = create_proc_entry("cards", d_flags, proc_nvidia); if (!proc_nvidia_cards) goto failed; proc_nvidia_warnings = create_proc_entry("warnings", d_flags, proc_nvidia); if (!proc_nvidia_warnings) goto failed; /* * Set the module owner to ensure that the reference * count reflects accesses to the proc files. */ proc_nvidia->owner = THIS_MODULE; proc_nvidia_cards->owner = THIS_MODULE; proc_nvidia_warnings->owner = THIS_MODULE; for (j = 0; j data = nv; entry->read_proc = nv_kern_read_cardinfo; entry->owner = THIS_MODULE; if (nvos_find_agp_capability(dev)) { /* * Create the /proc/driver/nvidia/agp/{status,host-bridge,card} * entries now that we know there's AGP hardware. */ entry = create_proc_entry("agp", d_flags, proc_nvidia); if (!entry) { NV_PCI_DEV_PUT(dev); goto failed; } entry->owner = THIS_MODULE; proc_nvidia_agp = entry; entry = create_proc_entry("status", flags, proc_nvidia_agp); if (!entry) { NV_PCI_DEV_PUT(dev); goto failed; } entry->data = nv; entry->read_proc = nv_kern_read_status; entry->owner = THIS_MODULE; entry = create_proc_entry("host-bridge", flags, proc_nvidia_agp); if (!entry) { NV_PCI_DEV_PUT(dev);



goto failed; } entry->data = NULL; entry->read_proc = nv_kern_read_agpinfo; entry->owner = THIS_MODULE; entry = create_proc_entry("card", flags, proc_nvidia_agp); if (!entry) { NV_PCI_DEV_PUT(dev); goto failed; } entry->data = nv; entry->read_proc = nv_kern_read_agpinfo; entry->owner = THIS_MODULE; } NV_PCI_DEV_PUT(dev); } entry = create_proc_entry("version", flags, proc_nvidia); if (!entry) goto failed; entry->read_proc = nv_kern_read_version; entry->owner = THIS_MODULE; entry = create_proc_entry("registry", flags, proc_nvidia); if (!entry) goto failed; entry->read_proc = nv_kern_read_registry; entry->owner = THIS_MODULE; #ifdef NV_STACKWATCH entry = create_proc_entry("stackwatch", flags | S_IWUSR, proc_nvidia); if (!entry) goto failed; entry->owner = THIS_MODULE; entry->proc_fops = &nv_stackwatch_fops; #endif return; failed: nv_printf(NV_DBG_ERRORS, "NVRM: failed to create /proc entries!\n"); nvos_proc_remove_all(proc_nvidia); #endif } static void nvos_proc_add_warning_file( const char *filename, const char *message ) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *entry; /* world readable file */ int flags = S_IFREG | S_IRUGO;



entry = create_proc_entry(filename, flags, proc_nvidia_warnings); if (!entry) return; entry->data = (void *)message; entry->read_proc = nv_kern_read_warning; entry->owner = THIS_MODULE; #endif } #ifdef CONFIG_PROC_FS static void nvos_proc_remove_all(struct proc_dir_entry *entry) { while (entry) { struct proc_dir_entry *next = entry->next; if (entry->subdir) nvos_proc_remove_all(entry->subdir); remove_proc_entry(entry->name, entry->parent); if (entry == proc_nvidia) break; entry = next; } } #endif static void nvos_proc_remove(void) { #ifdef CONFIG_PROC_FS nvos_proc_remove_all(proc_nvidia); #endif } /* * Given a physical address (within the AGP aperture, plain physical * or 32-bit DMA'able within the IOMMU), find and return the 'at' that * owns the address, then return it to the caller. */ static nv_alloc_t *nvl_find_alloc( nv_linux_state_t *nvl, unsigned long address, unsigned long flags ) { nv_alloc_t *at; for (at = nvl->alloc_queue; at; at = at->next) { // make sure this 'at' matches the flags the caller provided // ie, don't mistake a pci allocation with an agp allocation if (!(at->flags & flags)) continue; // most mappings will be found based on the 'key' if (address == ((unsigned long) at->key_mapping)) return at; // if agp, allow the address to fall within this range if (NV_ALLOC_MAPPING_AGP(at->flags) && (address >= (unsigned long) at->key_mapping) && (address + PAGE_SIZE key_mapping + at->num_pages * PAGE_SIZE)) return at; if (at->page_table)



{ unsigned int i; for (i = 0; i num_pages; i++) { nv_pte_t *page_ptr = at->page_table[i]; if ((address >= page_ptr->phys_addr) && (address phys_addr + PAGE_SIZE))) return at; if ((address >= page_ptr->dma_addr) && (address dma_addr + PAGE_SIZE))) return at; } } } /* failure is not necessarily an error if the caller was just probing an address */ nv_printf(NV_DBG_INFO, "NVRM: could not find map for vm 0x%lx\n", address); return NULL; } static int nvl_add_alloc( nv_linux_state_t *nvl, nv_alloc_t *at ) { nv_down(nvl->at_lock); at->next = nvl->alloc_queue; nvl->alloc_queue = at; nv_up(nvl->at_lock); return 0; } static int nvl_remove_alloc( nv_linux_state_t *nvl, nv_alloc_t *at ) { nv_alloc_t *tmp, *prev; if (nvl->alloc_queue == at) { nvl->alloc_queue = nvl->alloc_queue->next; return 0; } for (tmp = prev = nvl->alloc_queue; tmp; prev = tmp, tmp = tmp->next) { if (tmp == at) { prev->next = tmp->next; return 0; } } return -1; } #if defined(NV_BUILD_NV_PAT_SUPPORT) /* * Private PAT support for use by the NVIDIA driver. This is an



* interim solution until the kernel offers PAT support. */ static int __check_pat_support (void); static void __nv_setup_pat_entries (void *); static void __nv_restore_pat_entries (void *); static int __nv_enable_pat_support (void); static void __nv_disable_pat_support (void); #define NV_READ_PAT_ENTRIES(pat1, pat2) #define NV_WRITE_PAT_ENTRIES(pat1, pat2) #define NV_PAT_ENTRY(pat, index) rdmsr(IA32_CR_PAT, (pat1), (pat2)) wrmsr(IA32_CR_PAT, (pat1), (pat2)) (((pat) & (0xff>((index)*8))



static inline void __nv_disable_caches(unsigned long *cr4) { unsigned long cr0 = read_cr0(); write_cr0(((cr0 & (0xdfffffff)) | 0x40000000)); wbinvd(); *cr4 = read_cr4(); if (*cr4 & 0x80) write_cr4(*cr4 & ~0x80); __flush_tlb(); } static inline void __nv_enable_caches(unsigned long cr4) { unsigned long cr0 = read_cr0(); wbinvd(); __flush_tlb(); write_cr0((cr0 & 0x9fffffff)); if (cr4 & 0x80) write_cr4(cr4); } static int __check_pat_support() { unsigned int pat1, pat2, i; if (!test_bit(X86_FEATURE_PAT, (volatile unsigned long *)&boot_cpu_data.x86_capability)) { nv_printf(NV_DBG_ERRORS, "NVRM: cpu does not support PAT, aborting..\n"); return 0; } NV_READ_PAT_ENTRIES(pat1, pat2); for (i = 0; i phys_addr); mm = &init_mm; // always a kernel page spin_lock(&mm->page_table_lock); pgd = NV_PGD_OFFSET(address, 1, mm); if (!NV_PGD_PRESENT(pgd)) { nv_printf(NV_DBG_ERRORS, "NVRM: pgd not present for addr 0x%lx\n", address); goto failed; } pmd = NV_PMD_OFFSET(address, pgd); if (!pmd || pmd_none(*pmd)) { nv_printf(NV_DBG_ERRORS, "NVRM: pmd not present for addr 0x%lx\n", address); goto failed; } // account for large pages if (pmd_large(*pmd)) { pte = (pte_t *)pmd; flags = pte_val(*pte) & ~(PAGE_MASK|_PAGE_PSE); NV_PMD_UNMAP(pmd); } else { pte = NV_PTE_OFFSET(address, pmd); if (!NV_PTE_PRESENT(pte)) { nv_printf(NV_DBG_ERRORS, "NVRM: pte not present for addr 0x%lx\n", address); goto failed; } flags = NV_PTE_VALUE(pte) & ~(PAGE_MASK|_PAGE_PSE); } switch (cachetype) { case NV_MEMORY_CACHED: expected = pgprot_val(PAGE_KERNEL); if ((flags & ~_PAGE_NX) == (expected & ~_PAGE_NX)) retval = 0; break; default: expected = pgprot_val(PAGE_KERNEL_NOCACHE); if ((flags & ~_PAGE_NX) == (expected & ~_PAGE_NX)) retval = 0; break; } if (retval) {



if (count page_table_lock); return retval; }



/*** *** EXPORTS to Linux Kernel ***/ static int __init nvidia_init_module(void) { int rc; U032 i, count; count = nvos_count_devices(); if (count == 0) { nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter found!\n"); return -ENODEV; } memset(nv_linux_devices, 0, sizeof(nv_linux_devices)); if (pci_register_driver(&nv_pci_driver) < 0) { pci_unregister_driver(&nv_pci_driver); // XXX ??? nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter found!\n"); return -ENODEV; } if (num_probed_nv_devices != count) { nv_printf(NV_DBG_ERRORS, "NVRM: The NVIDIA probe routine was not called for %d device(s).\n", count - num_probed_nv_devices); nv_printf(NV_DBG_ERRORS, "NVRM: This can occur when a driver such as rivafb, nvidiafb or\n", "NVRM: rivatv was loaded and obtained ownership of the NVIDIA\n", "NVRM: device(s).\n"); nv_printf(NV_DBG_ERRORS, "NVRM: Try unloading the rivafb, nvidiafb or rivatv kernel module\n" "NVRM: (and/or reconfigure your kernel without rivafb/nvidiafb\n" "NVRM: support), then try loading the NVIDIA kernel module again.\n"); } if (num_probed_nv_devices == 0)



{ pci_unregister_driver(&nv_pci_driver); nv_printf(NV_DBG_ERRORS, "NVRM: No NVIDIA graphics adapter probed!\n"); return -ENODEV; } if (num_probed_nv_devices != num_nv_devices) { nv_printf(NV_DBG_ERRORS, "NVRM: The NVIDIA probe routine failed for %d device(s).\n", num_probed_nv_devices - num_nv_devices); } if (num_nv_devices == 0) { pci_unregister_driver(&nv_pci_driver); nv_printf(NV_DBG_ERRORS, "NVRM: None of the NVIDIA graphics adapters were initialized!\n"); return -ENODEV; }




Share This Document


Related docs
Other docs by fnordium
20_page
Views: 139  |  Downloads: 1
by registering with docstoc.com you agree to our
privacy policy

You are almost ready to download!

You are almost ready to download!