From 4387418129895fd9aa2e2f6368ea69e9c4ddd0f2 Mon Sep 17 00:00:00 2001
From: Oliver Endriss <o.endriss@gmx.de>
Date: Sun, 16 May 2010 05:29:14 -0300
Subject: V4L/DVB: ngene: Implement support for MSI

Add MSI support, may be enabled with firmware version 18.

Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/dvb/ngene/ngene-core.c | 33 ++++++++++++++++++++++++++++++++-
 drivers/media/dvb/ngene/ngene.h      |  2 ++
 2 files changed, 34 insertions(+), 1 deletion(-)

(limited to 'drivers/media/dvb')

diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index 46749d6ef1ee..35bed6095b1e 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -1299,11 +1299,14 @@ static void ngene_stop(struct ngene *dev)
 	ngwritel(0, NGENE_EVENT);
 	ngwritel(0, NGENE_EVENT_HI);
 	free_irq(dev->pci_dev->irq, dev);
+	if (dev->msi_enabled)
+		pci_disable_msi(dev->pci_dev);
 }
 
 static int ngene_start(struct ngene *dev)
 {
 	int stat;
+	unsigned long flags;
 	int i;
 
 	pci_set_master(dev->pci_dev);
@@ -1333,6 +1336,28 @@ static int ngene_start(struct ngene *dev)
 	if (stat < 0)
 		goto fail;
 
+#ifdef CONFIG_PCI_MSI
+	/* enable MSI if kernel and card support it */
+	if (dev->card_info->msi_supported) {
+		ngwritel(0, NGENE_INT_ENABLE);
+		free_irq(dev->pci_dev->irq, dev);
+		stat = pci_enable_msi(dev->pci_dev);
+		if (stat) {
+			printk(KERN_INFO DEVICE_NAME
+				": MSI not available\n");
+			flags = IRQF_SHARED;
+		} else {
+			flags = 0;
+			dev->msi_enabled = true;
+		}
+		stat = request_irq(dev->pci_dev->irq, irq_handler,
+					flags, "nGene", dev);
+		if (stat < 0)
+			goto fail2;
+		ngwritel(1, NGENE_INT_ENABLE);
+	}
+#endif
+
 	stat = ngene_i2c_init(dev, 0);
 	if (stat < 0)
 		goto fail;
@@ -1358,10 +1383,16 @@ static int ngene_start(struct ngene *dev)
 			bconf = BUFFER_CONFIG_3333;
 		stat = ngene_command_config_buf(dev, bconf);
 	}
-	return stat;
+	if (!stat)
+		return stat;
+
+	/* otherwise error: fall through */
 fail:
 	ngwritel(0, NGENE_INT_ENABLE);
 	free_irq(dev->pci_dev->irq, dev);
+fail2:
+	if (dev->msi_enabled)
+		pci_disable_msi(dev->pci_dev);
 	return stat;
 }
 
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
index 676fcbb79026..b951d59e3617 100644
--- a/drivers/media/dvb/ngene/ngene.h
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -725,6 +725,7 @@ struct ngene {
 	u32                   device_version;
 	u32                   fw_interface_version;
 	u32                   icounts;
+	bool                  msi_enabled;
 
 	u8                   *CmdDoneByte;
 	int                   BootFirmware;
@@ -797,6 +798,7 @@ struct ngene_info {
 #define NGENE_VBOX_V2	 7
 
 	int   fw_version;
+	bool  msi_supported;
 	char *name;
 
 	int   io_type[MAX_STREAM];
-- 
cgit v1.2.3