Commit 77978089 authored by Brendan McGrath's avatar Brendan McGrath Committed by Mauro Carvalho Chehab

[media] saa7164: use an MSI interrupt when available

Enhances driver to use an MSI interrupt when available.

Adds the module option 'enable_msi' (type bool) which by default is
enabled. Can be set to 'N' to disable.

Fixes (or can reduce the occurrence of) a crash which is most commonly
reported when both digital tuners of the saa7164 chip is in use. A
reported example can be found here:
http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/83948Reviewed-by: default avatarSteven Toth <stoth@kernellabs.com>
Signed-off-by: default avatarBrendan McGrath <redmcg@redmandi.dyndns.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 4c12adad
...@@ -85,6 +85,11 @@ module_param(guard_checking, int, 0644); ...@@ -85,6 +85,11 @@ module_param(guard_checking, int, 0644);
MODULE_PARM_DESC(guard_checking, MODULE_PARM_DESC(guard_checking,
"enable dma sanity checking for buffer overruns"); "enable dma sanity checking for buffer overruns");
static bool enable_msi = true;
module_param(enable_msi, bool, 0444);
MODULE_PARM_DESC(enable_msi,
"enable the use of an msi interrupt if available");
static unsigned int saa7164_devcount; static unsigned int saa7164_devcount;
static DEFINE_MUTEX(devlist); static DEFINE_MUTEX(devlist);
...@@ -1186,6 +1191,39 @@ static int saa7164_thread_function(void *data) ...@@ -1186,6 +1191,39 @@ static int saa7164_thread_function(void *data)
return 0; return 0;
} }
static bool saa7164_enable_msi(struct pci_dev *pci_dev, struct saa7164_dev *dev)
{
int err;
if (!enable_msi) {
printk(KERN_WARNING "%s() MSI disabled by module parameter 'enable_msi'"
, __func__);
return false;
}
err = pci_enable_msi(pci_dev);
if (err) {
printk(KERN_ERR "%s() Failed to enable MSI interrupt."
" Falling back to a shared IRQ\n", __func__);
return false;
}
/* no error - so request an msi interrupt */
err = request_irq(pci_dev->irq, saa7164_irq, 0,
dev->name, dev);
if (err) {
/* fall back to legacy interrupt */
printk(KERN_ERR "%s() Failed to get an MSI interrupt."
" Falling back to a shared IRQ\n", __func__);
pci_disable_msi(pci_dev);
return false;
}
return true;
}
static int saa7164_initdev(struct pci_dev *pci_dev, static int saa7164_initdev(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
...@@ -1232,14 +1270,23 @@ static int saa7164_initdev(struct pci_dev *pci_dev, ...@@ -1232,14 +1270,23 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
goto fail_irq; goto fail_irq;
} }
/* irq bit */
if (saa7164_enable_msi(pci_dev, dev)) {
dev->msi = true;
} else {
/* if we have an error (i.e. we don't have an interrupt)
or msi is not enabled - fallback to shared interrupt */
err = request_irq(pci_dev->irq, saa7164_irq, err = request_irq(pci_dev->irq, saa7164_irq,
IRQF_SHARED, dev->name, dev); IRQF_SHARED, dev->name, dev);
if (err < 0) { if (err < 0) {
printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
pci_dev->irq); pci_dev->irq);
err = -EIO; err = -EIO;
goto fail_irq; goto fail_irq;
} }
}
pci_set_drvdata(pci_dev, dev); pci_set_drvdata(pci_dev, dev);
...@@ -1441,6 +1488,11 @@ static void saa7164_finidev(struct pci_dev *pci_dev) ...@@ -1441,6 +1488,11 @@ static void saa7164_finidev(struct pci_dev *pci_dev)
/* unregister stuff */ /* unregister stuff */
free_irq(pci_dev->irq, dev); free_irq(pci_dev->irq, dev);
if (dev->msi) {
pci_disable_msi(pci_dev);
dev->msi = false;
}
pci_disable_device(pci_dev); pci_disable_device(pci_dev);
mutex_lock(&devlist); mutex_lock(&devlist);
......
...@@ -464,6 +464,7 @@ struct saa7164_dev { ...@@ -464,6 +464,7 @@ struct saa7164_dev {
/* Interrupt status and ack registers */ /* Interrupt status and ack registers */
u32 int_status; u32 int_status;
u32 int_ack; u32 int_ack;
bool msi;
struct cmd cmds[SAA_CMD_MAX_MSG_UNITS]; struct cmd cmds[SAA_CMD_MAX_MSG_UNITS];
struct mutex lock; struct mutex lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment