Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Feb 2009 18:54:35 +0000 (UTC)
From:      Robert Noland <rnoland@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189052 - head/sys/dev/drm
Message-ID:  <200902251854.n1PIsZZP005285@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rnoland
Date: Wed Feb 25 18:54:35 2009
New Revision: 189052
URL: http://svn.freebsd.org/changeset/base/189052

Log:
  Turn on MSI if the card supports it.  There is a blacklist for chips
  which report that they are capable of MSI, but don't work correctly.
  
  MFC after:	2 weeks

Modified:
  head/sys/dev/drm/drmP.h
  head/sys/dev/drm/drm_drv.c
  head/sys/dev/drm/drm_irq.c

Modified: head/sys/dev/drm/drmP.h
==============================================================================
--- head/sys/dev/drm/drmP.h	Wed Feb 25 18:50:35 2009	(r189051)
+++ head/sys/dev/drm/drmP.h	Wed Feb 25 18:54:35 2009	(r189052)
@@ -319,6 +319,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

Modified: head/sys/dev/drm/drm_drv.c
==============================================================================
--- head/sys/dev/drm/drm_drv.c	Wed Feb 25 18:50:35 2009	(r189051)
+++ head/sys/dev/drm/drm_drv.c	Wed Feb 25 18:54:35 2009	(r189052)
@@ -134,6 +134,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;
@@ -169,7 +190,7 @@ int drm_attach(device_t nbdev, drm_pci_i
 {
 	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);
@@ -189,21 +210,66 @@ int drm_attach(device_t nbdev, drm_pci_i
 			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;
 }
 
@@ -352,19 +418,6 @@ static int drm_load(struct drm_device *d
 
 	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();

Modified: head/sys/dev/drm/drm_irq.c
==============================================================================
--- head/sys/dev/drm/drm_irq.c	Wed Feb 25 18:50:35 2009	(r189051)
+++ head/sys/dev/drm/drm_irq.c	Wed Feb 25 18:54:35 2009	(r189052)
@@ -172,13 +172,6 @@ int drm_irq_install(struct drm_device *d
 	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,
@@ -200,25 +193,17 @@ int drm_irq_install(struct drm_device *d
 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);
 
@@ -226,7 +211,6 @@ int drm_irq_uninstall(struct drm_device 
 
 	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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902251854.n1PIsZZP005285>