static int mtrr_setup(struct pci_dev *pdev, resource_size_t mem_start, resource_size_t mem_size) { int err = 0; int mtrr; /* Reset MTRR */ mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_UNCACHABLE, 0); if (mtrr < 0) { dev_err(&pdev->dev, "%d - %s: mtrr_add failed (%d)\n", __LINE__, __func__, mtrr); err = mtrr; goto err_out; } err = mtrr_del(mtrr, mem_start, mem_size); if (err < 0) { dev_err(&pdev->dev, "%d - %s: mtrr_del failed (%d)\n", __LINE__, __func__, err); goto err_out; } mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_WRBACK, 0); if (mtrr < 0) { /* Stop, but not an error as this may be already be setup */ dev_dbg(&pdev->dev, "%d - %s: mtrr_del failed (%d) - probably means the mtrr is already setup\n", __LINE__, __func__, err); err = 0; goto err_out; } err = mtrr_del(mtrr, mem_start, mem_size); if (err < 0) { dev_err(&pdev->dev, "%d - %s: mtrr_del failed (%d)\n", __LINE__, __func__, err); goto err_out; } if (mtrr == 0) { /* Replace 0 with a non-overlapping WRBACK mtrr */ err = mtrr_add(0, mem_start, MTRR_TYPE_WRBACK, 0); if (err < 0) { dev_err(&pdev->dev, "%d - %s: mtrr_add failed (%d)\n", __LINE__, __func__, err); goto err_out; } } mtrr = mtrr_add(mem_start, mem_size, MTRR_TYPE_WRCOMB, 0); if (mtrr < 0) dev_err(&pdev->dev, "%d - %s: mtrr_add failed (%d)\n", __LINE__, __func__, mtrr); err = 0; err_out: return err; }
/* * Delete MTRRs and free device-private data. */ void savage_driver_lastclose(drm_device_t *dev) { drm_savage_private_t *dev_priv = dev->dev_private; int i; for (i = 0; i < 3; ++i) if (dev_priv->mtrr[i].handle >= 0) mtrr_del(dev_priv->mtrr[i].handle, dev_priv->mtrr[i].base, dev_priv->mtrr[i].size); }
/** * Called via cleanup_module() at module unload time. * * Cleans up all DRM device, calling drm_lastclose(). * * \sa drm_init */ static void __exit drm_cleanup(drm_device_t * dev) { DRM_DEBUG("\n"); if (!dev) { DRM_ERROR("cleanup called no dev\n"); return; } drm_lastclose(dev); if (dev->maplist) { drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); dev->maplist = NULL; } if (!drm_fb_loaded) pci_disable_device(dev->pdev); drm_ctxbitmap_cleanup(dev); if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp && dev->agp->agp_mtrr >= 0) { int retval; retval = mtrr_del(dev->agp->agp_mtrr, dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size * 1024 * 1024); DRM_DEBUG("mtrr_del=%d\n", retval); } if (drm_core_has_AGP(dev) && dev->agp) { drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); dev->agp = NULL; } if (dev->driver->unload) dev->driver->unload(dev); drm_put_head(&dev->primary); if (drm_put_dev(dev)) DRM_ERROR("Cannot unload module\n"); }
RM_STATUS KernTeardownAGP( nv_stack_t *sp, nv_state_t *nv ) { #ifndef AGPGART return RM_ERROR; #else RM_STATUS status; nv_linux_state_t *nvl; void *bitmap; nvl = NV_GET_NVL_FROM_NV_STATE(nv); #ifdef CONFIG_MTRR if (nv_pat_mode == NV_PAT_MODE_DISABLED) mtrr_del(-1, nv->agp.address, nv->agp.size); #endif NV_AGPGART_BACKEND_RELEASE(drm_agp_p, nvl->agp_bridge); #if defined(KERNEL_2_4) inter_module_put("drm_agp"); #endif status = rm_clear_agp_bitmap(sp, nv, &bitmap); if (status != RM_OK) { nv_printf(NV_DBG_WARNINGS, "NVRM: AGPGART: failed to clear bitmap\n"); return status; } os_free_mem(bitmap); return RM_OK; #endif /* AGPGART */ }
static int tdfx_takedown(drm_device_t *dev) { int i; drm_magic_entry_t *pt, *next; drm_map_t *map; drm_vma_entry_t *vma, *vma_next; DRM_DEBUG("\n"); down(&dev->struct_sem); del_timer(&dev->timer); if (dev->devname) { drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); dev->devname = NULL; } if (dev->unique) { drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); dev->unique = NULL; dev->unique_len = 0; } /* Clear pid list */ for (i = 0; i < DRM_HASH_SIZE; i++) { for (pt = dev->magiclist[i].head; pt; pt = next) { next = pt->next; drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); } dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) /* Clear AGP information */ if (dev->agp) { drm_agp_mem_t *temp; drm_agp_mem_t *temp_next; temp = dev->agp->memory; while(temp != NULL) { temp_next = temp->next; drm_free_agp(temp->memory, temp->pages); drm_free(temp, sizeof(*temp), DRM_MEM_AGPLISTS); temp = temp_next; } if (dev->agp->acquired) _drm_agp_release(); } #endif /* Clear vma list (only built for debugging) */ if (dev->vmalist) { for (vma = dev->vmalist; vma; vma = vma_next) { vma_next = vma->next; drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); } dev->vmalist = NULL; } /* Clear map area and mtrr information */ if (dev->maplist) { for (i = 0; i < dev->map_count; i++) { map = dev->maplist[i]; switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: #ifdef CONFIG_MTRR if (map->mtrr >= 0) { int retcode; retcode = mtrr_del(map->mtrr, map->offset, map->size); DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif drm_ioremapfree(map->handle, map->size, dev); break; case _DRM_SHM: drm_free_pages((unsigned long)map->handle, drm_order(map->size) - PAGE_SHIFT, DRM_MEM_SAREA); break; case _DRM_AGP: /* Do nothing here, because this is all handled in the AGP/GART driver. */ break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); } drm_free(dev->maplist, dev->map_count * sizeof(*dev->maplist), DRM_MEM_MAPS); dev->maplist = NULL; dev->map_count = 0; } if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; wake_up_interruptible(&dev->lock.lock_queue); } up(&dev->struct_sem); return 0; }
static int i810_takedown(drm_device_t *dev) { int i; drm_magic_entry_t *pt, *next; drm_map_t *map; drm_vma_entry_t *vma, *vma_next; DRM_DEBUG("\n"); if (dev->irq) i810_irq_uninstall(dev); down(&dev->struct_sem); del_timer(&dev->timer); if (dev->devname) { drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); dev->devname = NULL; } if (dev->unique) { drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); dev->unique = NULL; dev->unique_len = 0; } /* Clear pid list */ for (i = 0; i < DRM_HASH_SIZE; i++) { for (pt = dev->magiclist[i].head; pt; pt = next) { next = pt->next; drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); } dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } /* Clear AGP information */ if (dev->agp) { drm_agp_mem_t *entry; drm_agp_mem_t *nexte; /* Remove AGP resources, but leave dev->agp intact until r128_cleanup is called. */ for (entry = dev->agp->memory; entry; entry = nexte) { nexte = entry->next; if (entry->bound) drm_unbind_agp(entry->memory); drm_free_agp(entry->memory, entry->pages); drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); } dev->agp->memory = NULL; if (dev->agp->acquired) _drm_agp_release(); dev->agp->acquired = 0; dev->agp->enabled = 0; } /* Clear vma list (only built for debugging) */ if (dev->vmalist) { for (vma = dev->vmalist; vma; vma = vma_next) { vma_next = vma->next; drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); } dev->vmalist = NULL; } /* Clear map area and mtrr information */ if (dev->maplist) { for (i = 0; i < dev->map_count; i++) { map = dev->maplist[i]; switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: #ifdef CONFIG_MTRR if (map->mtrr >= 0) { int retcode; retcode = mtrr_del(map->mtrr, map->offset, map->size); DRM_DEBUG("mtrr_del = %d\n", retcode); } #endif drm_ioremapfree(map->handle, map->size); break; case _DRM_SHM: drm_free_pages((unsigned long)map->handle, drm_order(map->size) - PAGE_SHIFT, DRM_MEM_SAREA); break; case _DRM_AGP: break; } drm_free(map, sizeof(*map), DRM_MEM_MAPS); } drm_free(dev->maplist, dev->map_count * sizeof(*dev->maplist), DRM_MEM_MAPS); dev->maplist = NULL; dev->map_count = 0; } if (dev->queuelist) { for (i = 0; i < dev->queue_count; i++) { drm_waitlist_destroy(&dev->queuelist[i]->waitlist); if (dev->queuelist[i]) { drm_free(dev->queuelist[i], sizeof(*dev->queuelist[0]), DRM_MEM_QUEUES); dev->queuelist[i] = NULL; } } drm_free(dev->queuelist, dev->queue_slots * sizeof(*dev->queuelist), DRM_MEM_QUEUES); dev->queuelist = NULL; } drm_dma_takedown(dev); dev->queue_count = 0; if (dev->lock.hw_lock) { dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.pid = 0; wake_up_interruptible(&dev->lock.lock_queue); } up(&dev->struct_sem); return 0; }
/*************************************************************************/ /*! @Function OSPCIClearResourceMTRRs @Description Clear any BIOS-configured MTRRs for a PCI memory region @Input hPVRPCI PCI device handle @Input ui32Index Address range index @Return PVRSRV_ERROR Services error code */ /**************************************************************************/ PVRSRV_ERROR OSPCIClearResourceMTRRs(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) { PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; resource_size_t start, end; int err; start = pci_resource_start(psPVRPCI->psPCIDev, ui32Index); end = pci_resource_end(psPVRPCI->psPCIDev, ui32Index) + 1; err = mtrr_add(start, end - start, MTRR_TYPE_UNCACHABLE, 0); if (err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } err = mtrr_del(err, start, end - start); if (err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } #if 1 /* Workaround for overlapping MTRRs. */ { IMG_BOOL bGotMTRR0 = IMG_FALSE; /* Current mobo BIOSes will normally set up a WRBACK MTRR spanning * 0->4GB, and then another 4GB->6GB. If the PCI card's automatic & * overlapping UNCACHABLE MTRR is deleted, we see WRBACK behaviour. * * WRBACK is incompatible with some PCI devices, so try to split * the UNCACHABLE regions up and insert a WRCOMB region instead. */ err = mtrr_add(start, end - start, MTRR_TYPE_WRBACK, 0); if (err < 0) { /* If this fails, services has probably run before and created * a write-combined MTRR for the test chip. Assume it has, and * don't return an error here. */ return PVRSRV_OK; } if(err == 0) bGotMTRR0 = IMG_TRUE; err = mtrr_del(err, start, end - start); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_del failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } if(bGotMTRR0) { /* Replace 0 with a non-overlapping WRBACK MTRR */ err = mtrr_add(0, start, MTRR_TYPE_WRBACK, 0); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } /* Add a WRCOMB MTRR for the PCI device memory bar */ err = mtrr_add(start, end - start, MTRR_TYPE_WRCOMB, 0); if(err < 0) { printk(KERN_ERR "OSPCIClearResourceMTRRs: mtrr_add failed (%d)", err); return PVRSRV_ERROR_PCI_CALL_FAILED; } } } #endif return PVRSRV_OK; }
RM_STATUS KernInitAGP( nv_stack_t *sp, nv_state_t *nv, NvU64 *ap_phys_base, NvU64 *ap_limit ) { #ifndef AGPGART return RM_ERROR; #else RM_STATUS status = RM_ERROR; nv_linux_state_t *nvl; void *bitmap; agp_kern_info agp_info; NvU32 bitmap_size; NvU32 agp_rate = (8 | 4 | 2 | 1); NvU32 enable_sba = 0; NvU32 enable_fw = 0; NvU32 agp_mode = 0; #if defined(KERNEL_2_4) if (!(drm_agp_p = inter_module_get_request("drm_agp", "agpgart"))) return RM_ERR_NOT_SUPPORTED; #endif /* NOTE: from here down, return an error code of '-1' * that indicates that agpgart is loaded, but we failed to use it * in some way. This is so we don't try to use nvagp and lock up * the memory controller. */ nvl = NV_GET_NVL_FROM_NV_STATE(nv); if (NV_AGPGART_BACKEND_ACQUIRE(drm_agp_p, nvl->agp_bridge, nvl->dev)) { nv_printf(NV_DBG_INFO, "NVRM: AGPGART: no backend available\n"); status = RM_ERR_NOT_SUPPORTED; goto bailout; } if (NV_AGPGART_COPY_INFO(drm_agp_p, nvl->agp_bridge, &agp_info)) { nv_printf(NV_DBG_ERRORS, "NVRM: AGPGART: kernel reports chipset as unsupported\n"); goto release; } if (nv_pat_mode == NV_PAT_MODE_DISABLED) { #ifdef CONFIG_MTRR /* * Failure to set a write-combining range on the AGP aperture may * be due to the presence of other memory ranges with conflicting * caching attributes. Play safe and fail AGP initialization. */ if (mtrr_add(agp_info.aper_base, agp_info.aper_size << 20, MTRR_TYPE_WRCOMB, 0) < 0) #endif { nv_printf(NV_DBG_ERRORS, "NVRM: AGPGART: unable to set MTRR write-combining\n"); goto release; } } // allocate and set the bitmap for tracking agp allocations bitmap_size = (agp_info.aper_size << 20)/PAGE_SIZE/8; if (os_alloc_mem(&bitmap, bitmap_size)) { nv_printf(NV_DBG_ERRORS, "NVRM: AGPGART: unable to allocate bitmap\n"); goto failed; } os_mem_set(bitmap, 0xff, bitmap_size); status = rm_set_agp_bitmap(sp, nv, bitmap); if (status != RM_OK) { nv_printf(NV_DBG_ERRORS, "NVRM: AGPGART: unable to set bitmap\n"); os_free_mem(bitmap); goto failed; } agp_mode = agp_info.mode; rm_read_registry_dword(sp, NULL, "NVreg", "ReqAGPRate", &agp_rate); agp_mode = NV_AGPGART_MODE_BITS_RATE(agp_mode, agp_rate); agp_mode |= 1; /* avoid 0x mode request */ if (agp_mode & 2) agp_mode &= ~1; if (agp_mode & 4) agp_mode &= ~2; rm_read_registry_dword(sp, NULL, "NVreg", "EnableAGPSBA", &enable_sba); agp_mode |= NV_AGPGART_MODE_BITS_SBA(enable_sba); rm_read_registry_dword(sp, NULL, "NVreg", "EnableAGPFW", &enable_fw); agp_mode |= NV_AGPGART_MODE_BITS_FW(enable_fw); agp_info.mode &= (0xff000000 | agp_mode); NV_AGPGART_BACKEND_ENABLE(drm_agp_p, nvl->agp_bridge, agp_info.mode); *ap_phys_base = (unsigned)agp_info.aper_base; *ap_limit = (unsigned)((agp_info.aper_size << 20) - 1); return RM_OK; failed: #ifdef CONFIG_MTRR if (nv_pat_mode == NV_PAT_MODE_DISABLED) mtrr_del(-1, agp_info.aper_base, agp_info.aper_size << 20); #endif release: NV_AGPGART_BACKEND_RELEASE(drm_agp_p, nvl->agp_bridge); bailout: #if defined(KERNEL_2_4) inter_module_put("drm_agp"); #endif return status; #endif /* AGPGART */ }