[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/83948 Reviewed-by: Steven Toth <stoth@kernellabs.com> Signed-off-by: Brendan McGrath <redmcg@redmandi.dyndns.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
parent
4c12adad26
commit
77978089dd
|
@ -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)
|
||||||
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,13 +1270,22 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
|
||||||
goto fail_irq;
|
goto fail_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = request_irq(pci_dev->irq, saa7164_irq,
|
/* irq bit */
|
||||||
IRQF_SHARED, dev->name, dev);
|
if (saa7164_enable_msi(pci_dev, dev)) {
|
||||||
if (err < 0) {
|
dev->msi = true;
|
||||||
printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
|
} else {
|
||||||
pci_dev->irq);
|
/* if we have an error (i.e. we don't have an interrupt)
|
||||||
err = -EIO;
|
or msi is not enabled - fallback to shared interrupt */
|
||||||
goto fail_irq;
|
|
||||||
|
err = request_irq(pci_dev->irq, saa7164_irq,
|
||||||
|
IRQF_SHARED, dev->name, dev);
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
|
||||||
|
pci_dev->irq);
|
||||||
|
err = -EIO;
|
||||||
|
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)
|
||||||
/* 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 {
|
||||||
/* 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;
|
||||||
|
|
Loading…
Reference in a new issue