summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Noland <rnoland@2hip.net>2009-02-24 15:47:35 -0600
committerRobert Noland <rnoland@2hip.net>2009-02-24 15:47:35 -0600
commitb9b8e8f3cc61a37cce2ae48957514ce6a4f30566 (patch)
tree7e2dade5dfcea4ef6db906c6b98e1b4c19990d0e
parent153a0803db19cf8c0b4f532e0d0243747875e154 (diff)
FreeBSD: Turn on msi
There is a blacklist for devices that advertise the capability, but don't work properly.
-rw-r--r--bsd-core/drmP.h6
-rw-r--r--bsd-core/drm_drv.c89
-rw-r--r--bsd-core/drm_irq.c18
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);