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;
}
Пример #2
0
/*
 * 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);
}
Пример #3
0
/**
 * 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");
}
Пример #4
0
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
0
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 */
}