aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2013-04-13 17:52:04 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-22 09:08:30 -0400
commit5ddfbbb9ca2e74d4b392ccef675641babba6b7f8 (patch)
tree8e2be3b14c057112be5d5d9fb8a708df2f06cc1e /drivers
parentcdcfe40a5fee6a3300632b9a6e7f9de596f0b450 (diff)
[media] cx88: Fix unsafe locking in suspend-resume
Legacy PCI suspend-resume handlers are called with interrupts enabled. But cx8800_suspend/cx8800_resume and cx8802_suspend_common/cx8802_resume_common use spin_lock/spin_unlock functions to acquire dev->slock, while the same lock is acquired in the corresponding irq-handlers: cx8800_irq and cx8802_irq. That means a deadlock is possible if an interrupt happens while suspend or resume owns the lock. The patch replaces spin_lock/spin_unlock with spin_lock_irqsave/spin_unlock_irqrestore. Found by Linux Driver Verification project (linuxtesting.org). [mchehab@redhat.com: Fix CodingStyle] Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/pci/cx88/cx88-mpeg.c10
-rw-r--r--drivers/media/pci/cx88/cx88-video.c10
2 files changed, 12 insertions, 8 deletions
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index c9d3182f79d5..2d3507eb4897 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -532,16 +532,17 @@ static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
532{ 532{
533 struct cx8802_dev *dev = pci_get_drvdata(pci_dev); 533 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
534 struct cx88_core *core = dev->core; 534 struct cx88_core *core = dev->core;
535 unsigned long flags;
535 536
536 /* stop mpeg dma */ 537 /* stop mpeg dma */
537 spin_lock(&dev->slock); 538 spin_lock_irqsave(&dev->slock, flags);
538 if (!list_empty(&dev->mpegq.active)) { 539 if (!list_empty(&dev->mpegq.active)) {
539 dprintk( 2, "suspend\n" ); 540 dprintk( 2, "suspend\n" );
540 printk("%s: suspend mpeg\n", core->name); 541 printk("%s: suspend mpeg\n", core->name);
541 cx8802_stop_dma(dev); 542 cx8802_stop_dma(dev);
542 del_timer(&dev->mpegq.timeout); 543 del_timer(&dev->mpegq.timeout);
543 } 544 }
544 spin_unlock(&dev->slock); 545 spin_unlock_irqrestore(&dev->slock, flags);
545 546
546 /* FIXME -- shutdown device */ 547 /* FIXME -- shutdown device */
547 cx88_shutdown(dev->core); 548 cx88_shutdown(dev->core);
@@ -558,6 +559,7 @@ static int cx8802_resume_common(struct pci_dev *pci_dev)
558{ 559{
559 struct cx8802_dev *dev = pci_get_drvdata(pci_dev); 560 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
560 struct cx88_core *core = dev->core; 561 struct cx88_core *core = dev->core;
562 unsigned long flags;
561 int err; 563 int err;
562 564
563 if (dev->state.disabled) { 565 if (dev->state.disabled) {
@@ -584,12 +586,12 @@ static int cx8802_resume_common(struct pci_dev *pci_dev)
584 cx88_reset(dev->core); 586 cx88_reset(dev->core);
585 587
586 /* restart video+vbi capture */ 588 /* restart video+vbi capture */
587 spin_lock(&dev->slock); 589 spin_lock_irqsave(&dev->slock, flags);
588 if (!list_empty(&dev->mpegq.active)) { 590 if (!list_empty(&dev->mpegq.active)) {
589 printk("%s: resume mpeg\n", core->name); 591 printk("%s: resume mpeg\n", core->name);
590 cx8802_restart_queue(dev,&dev->mpegq); 592 cx8802_restart_queue(dev,&dev->mpegq);
591 } 593 }
592 spin_unlock(&dev->slock); 594 spin_unlock_irqrestore(&dev->slock, flags);
593 595
594 return 0; 596 return 0;
595} 597}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index e3f6181d1044..1b00615fd395 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1954,9 +1954,10 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
1954{ 1954{
1955 struct cx8800_dev *dev = pci_get_drvdata(pci_dev); 1955 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
1956 struct cx88_core *core = dev->core; 1956 struct cx88_core *core = dev->core;
1957 unsigned long flags;
1957 1958
1958 /* stop video+vbi capture */ 1959 /* stop video+vbi capture */
1959 spin_lock(&dev->slock); 1960 spin_lock_irqsave(&dev->slock, flags);
1960 if (!list_empty(&dev->vidq.active)) { 1961 if (!list_empty(&dev->vidq.active)) {
1961 printk("%s/0: suspend video\n", core->name); 1962 printk("%s/0: suspend video\n", core->name);
1962 stop_video_dma(dev); 1963 stop_video_dma(dev);
@@ -1967,7 +1968,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
1967 cx8800_stop_vbi_dma(dev); 1968 cx8800_stop_vbi_dma(dev);
1968 del_timer(&dev->vbiq.timeout); 1969 del_timer(&dev->vbiq.timeout);
1969 } 1970 }
1970 spin_unlock(&dev->slock); 1971 spin_unlock_irqrestore(&dev->slock, flags);
1971 1972
1972 if (core->ir) 1973 if (core->ir)
1973 cx88_ir_stop(core); 1974 cx88_ir_stop(core);
@@ -1986,6 +1987,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
1986{ 1987{
1987 struct cx8800_dev *dev = pci_get_drvdata(pci_dev); 1988 struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
1988 struct cx88_core *core = dev->core; 1989 struct cx88_core *core = dev->core;
1990 unsigned long flags;
1989 int err; 1991 int err;
1990 1992
1991 if (dev->state.disabled) { 1993 if (dev->state.disabled) {
@@ -2016,7 +2018,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
2016 cx_set(MO_PCI_INTMSK, core->pci_irqmask); 2018 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
2017 2019
2018 /* restart video+vbi capture */ 2020 /* restart video+vbi capture */
2019 spin_lock(&dev->slock); 2021 spin_lock_irqsave(&dev->slock, flags);
2020 if (!list_empty(&dev->vidq.active)) { 2022 if (!list_empty(&dev->vidq.active)) {
2021 printk("%s/0: resume video\n", core->name); 2023 printk("%s/0: resume video\n", core->name);
2022 restart_video_queue(dev,&dev->vidq); 2024 restart_video_queue(dev,&dev->vidq);
@@ -2025,7 +2027,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
2025 printk("%s/0: resume vbi\n", core->name); 2027 printk("%s/0: resume vbi\n", core->name);
2026 cx8800_restart_vbi_queue(dev,&dev->vbiq); 2028 cx8800_restart_vbi_queue(dev,&dev->vbiq);
2027 } 2029 }
2028 spin_unlock(&dev->slock); 2030 spin_unlock_irqrestore(&dev->slock, flags);
2029 2031
2030 return 0; 2032 return 0;
2031} 2033}