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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to