diff options
| -rw-r--r-- | bsd-core/drmP.h | 6 | ||||
| -rw-r--r-- | bsd-core/drm_drv.c | 89 | ||||
| -rw-r--r-- | bsd-core/drm_irq.c | 18 | 
3 files changed, 78 insertions, 35 deletions
| diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index fe3fc78b..f450d69f 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -324,6 +324,12 @@ typedef struct drm_pci_id_list  	char *name;  } drm_pci_id_list_t; +struct drm_msi_blacklist_entry +{ +	int vendor; +	int device; +}; +  #define DRM_AUTH	0x1  #define DRM_MASTER	0x2  #define DRM_ROOT_ONLY	0x4 diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index f4123b9b..2f47ff03 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -131,6 +131,27 @@ static struct cdevsw drm_cdevsw = {  	.d_flags =	D_TRACKCLOSE | D_NEEDGIANT  }; +static struct drm_msi_blacklist_entry drm_msi_blacklist[] = { +	{0x8086, 0x2772}, /* Intel i945G	*/ \ +	{0x8086, 0x27A2}, /* Intel i945GM	*/ \ +	{0x8086, 0x27AE}, /* Intel i945GME	*/ \ +	{0, 0} +}; + +static int drm_msi_is_blacklisted(int vendor, int device) +{ +	int i = 0; +	 +	for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) { +		if ((drm_msi_blacklist[i].vendor == vendor) && +		    (drm_msi_blacklist[i].device == device)) { +			return 1; +		} +	} + +	return 0; +} +  int drm_probe(device_t dev, drm_pci_id_list_t *idlist)  {  	drm_pci_id_list_t *id_entry; @@ -162,7 +183,7 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)  {  	struct drm_device *dev;  	drm_pci_id_list_t *id_entry; -	int unit; +	int unit, msicount;  	unit = device_get_unit(nbdev);  	dev = device_get_softc(nbdev); @@ -182,21 +203,66 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)  			DRM_DEV_MODE,  			"dri/card%d", unit); +#if __FreeBSD_version >= 700053 +	dev->pci_domain = pci_get_domain(dev->device); +#else +	dev->pci_domain = 0; +#endif +	dev->pci_bus = pci_get_bus(dev->device); +	dev->pci_slot = pci_get_slot(dev->device); +	dev->pci_func = pci_get_function(dev->device); + +	dev->pci_vendor = pci_get_vendor(dev->device); +	dev->pci_device = pci_get_device(dev->device); + +	if (!drm_msi_is_blacklisted(dev->pci_vendor, dev->pci_device)) { +		msicount = pci_msi_count(dev->device); +		DRM_DEBUG("MSI count = %d\n", msicount); +		if (msicount > 1) +			msicount = 1; + +		if (pci_alloc_msi(dev->device, &msicount) == 0) { +			DRM_INFO("MSI enabled %d message(s)\n", msicount); +			dev->msi_enabled = 1; +			dev->irqrid = 1; +		} +	} + +	dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, +	    &dev->irqrid, RF_SHAREABLE); +	if (!dev->irqr) { +		return ENOENT; +	} + +	dev->irq = (int) rman_get_start(dev->irqr); +  	mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF);  	mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);  	mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);  	mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF); -	id_entry = drm_find_description(pci_get_vendor(dev->device), -	    pci_get_device(dev->device), idlist); +	id_entry = drm_find_description(dev->pci_vendor, +	    dev->pci_device, idlist);  	dev->id_entry = id_entry;  	return drm_load(dev);  } -int drm_detach(device_t dev) +int drm_detach(device_t nbdev)  { -	drm_unload(device_get_softc(dev)); +	struct drm_device *dev; + +	dev = device_get_softc(nbdev); + +	drm_unload(dev); + +	bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); + +	if (dev->msi_enabled) { +		pci_release_msi(dev->device); +		DRM_INFO("MSI released\n"); +	} +  	return 0;  } @@ -345,19 +411,6 @@ static int drm_load(struct drm_device *dev)  	DRM_DEBUG("\n"); -	dev->irq = pci_get_irq(dev->device); -#if __FreeBSD_version >= 700053 -	dev->pci_domain = pci_get_domain(dev->device); -#else -	dev->pci_domain = 0; -#endif -	dev->pci_bus = pci_get_bus(dev->device); -	dev->pci_slot = pci_get_slot(dev->device); -	dev->pci_func = pci_get_function(dev->device); - -	dev->pci_vendor = pci_get_vendor(dev->device); -	dev->pci_device = pci_get_device(dev->device); -  	TAILQ_INIT(&dev->maplist);  	drm_mem_init(); diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index 8db1ab81..8a9d3449 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -169,13 +169,6 @@ int drm_irq_install(struct drm_device *dev)  	DRM_UNLOCK();  	/* Install handler */ -	dev->irqrid = 0; -	dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,  -				      &dev->irqrid, RF_SHAREABLE); -	if (!dev->irqr) { -		retcode = ENOENT; -		goto err; -	}  #if __FreeBSD_version >= 700031  	retcode = bus_setup_intr(dev->device, dev->irqr,  				 INTR_TYPE_TTY | INTR_MPSAFE, @@ -197,25 +190,17 @@ int drm_irq_install(struct drm_device *dev)  err:  	DRM_LOCK();  	dev->irq_enabled = 0; -	if (dev->irqrid != 0) { -		bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, -		    dev->irqr); -		dev->irqrid = 0; -	}  	DRM_UNLOCK(); +  	return retcode;  }  int drm_irq_uninstall(struct drm_device *dev)  { -	int irqrid; -  	if (!dev->irq_enabled)  		return EINVAL;  	dev->irq_enabled = 0; -	irqrid = dev->irqrid; -	dev->irqrid = 0;  	DRM_DEBUG("irq=%d\n", dev->irq); @@ -223,7 +208,6 @@ int drm_irq_uninstall(struct drm_device *dev)  	DRM_UNLOCK();  	bus_teardown_intr(dev->device, dev->irqr, dev->irqh); -	bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);  	DRM_LOCK();  	drm_vblank_cleanup(dev); | 
