From: "Steinar H. Gunderson" <se...@samfundet.no>

Basically a lot of the members of mantis_ca were accessed from several threads
without a mutex, which is a big no-no; I've mostly changed to using atomic
operations here, although I also added some locks were it made sense
(e.g. when resetting the CAM).
---
 drivers/media/dvb/mantis/mantis_ca.c     |   14 ++++++++++++++
 drivers/media/dvb/mantis/mantis_common.h |    2 +-
 drivers/media/dvb/mantis/mantis_evm.c    |    9 +++++++--
 drivers/media/dvb/mantis/mantis_hif.c    |   25 ++++++++++++++++++++-----
 drivers/media/dvb/mantis/mantis_link.h   |    2 +-
 drivers/media/dvb/mantis/mantis_reg.h    |    6 ++++--
 6 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/drivers/media/dvb/mantis/mantis_ca.c 
b/drivers/media/dvb/mantis/mantis_ca.c
index 0f8efc7..cdff4b7 100644
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -95,11 +95,25 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 
*en50221, int slot)
        struct mantis_pci *mantis = ca->ca_priv;
 
        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
+       mutex_lock(&mantis->int_stat_lock);
+       if (test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+               dprintk(MANTIS_NOTICE, 1, "Slot(%d): Reset operation done 
before it started!", slot);
+       }
        udelay(500); /* Wait.. */
        mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
        udelay(500);
        mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
        msleep(1000);
+
+       if (wait_event_timeout(ca->hif_opdone_wq,
+                              test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, 
&ca->hif_event),
+                              msecs_to_jiffies(500)) == -ERESTARTSYS) {
+
+               dprintk(MANTIS_ERROR, 1, "Slot(%d): Reset timeout!", slot);
+       } else {
+               dprintk(MANTIS_DEBUG, 1, "Slot(%d): Reset complete", slot);
+       }
+       mutex_unlock(&mantis->int_stat_lock);
        dvb_ca_en50221_camready_irq(&ca->en50221, 0);
 
        return 0;
diff --git a/drivers/media/dvb/mantis/mantis_common.h 
b/drivers/media/dvb/mantis/mantis_common.h
index 9058d9d..0967103 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -161,7 +161,7 @@ struct mantis_pci {
         /*     A12 A13 A14             */
        u32                     gpio_status;
 
-       u32                     gpif_status;
+       volatile unsigned long  gpif_status;
 
        struct mantis_ca        *mantis_ca;
        struct mutex            int_stat_lock;
diff --git a/drivers/media/dvb/mantis/mantis_evm.c 
b/drivers/media/dvb/mantis/mantis_evm.c
index 36f2256..0fdf51c 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -20,6 +20,7 @@
 
 #include <linux/kernel.h>
 
+#include <linux/atomic.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
@@ -87,10 +88,14 @@ static void mantis_hifevm_work(struct work_struct *work)
        if (gpif_stat & MANTIS_SBUF_EMPTY)
                dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart 
Buffer Empty", mantis->num);
 
-       if (gpif_stat & MANTIS_SBUF_OPDONE) {
+       if (gpif_stat & MANTIS_SBUF_OPDONE)
                dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart 
Buffer operation complete", mantis->num);
+
+       if (gpif_stat & MANTIS_SBUF_OPDONE) {
                ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL;
-               ca->hif_event = MANTIS_SBUF_OPDONE;
+               if (test_and_set_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+                       dprintk(MANTIS_NOTICE, 1, "Operation done, but 
SBUF_OPDONE bit was already set!");
+               }
                wake_up(&ca->hif_opdone_wq);
        }
 }
diff --git a/drivers/media/dvb/mantis/mantis_hif.c 
b/drivers/media/dvb/mantis/mantis_hif.c
index c1e456c..6d42f73 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -22,6 +22,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 
+#include <linux/atomic.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -45,25 +46,23 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca)
        int rc = 0;
 
        if (wait_event_timeout(ca->hif_opdone_wq,
-                              ca->hif_event & MANTIS_SBUF_OPDONE,
+                              test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, 
&ca->hif_event),
                               msecs_to_jiffies(500)) == -ERESTARTSYS) {
 
                dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer 
operation timeout !", mantis->num);
                rc = -EREMOTEIO;
        }
        dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete");
-       ca->hif_event &= ~MANTIS_SBUF_OPDONE;
        return rc;
 }
 
 static int mantis_hif_write_wait(struct mantis_ca *ca)
 {
        struct mantis_pci *mantis = ca->ca_priv;
-       u32 opdone = 0, timeout = 0;
        int rc = 0;
 
        if (wait_event_timeout(ca->hif_write_wq,
-                              mantis->gpif_status & MANTIS_GPIF_WRACK,
+                              test_and_clear_bit(MANTIS_GPIF_WRACK_BIT, 
&mantis->gpif_status),
                               msecs_to_jiffies(500)) == -ERESTARTSYS) {
 
                dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed 
out !", mantis->num);
@@ -81,7 +80,10 @@ static int mantis_hif_write_wait(struct mantis_ca *ca)
                        break;
                }
        }
-       dprintk(MANTIS_DEBUG, 1, "HIF Write success");
+       if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
+               dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation 
timeout !", mantis->num);
+               rc = -ETIMEDOUT;
+       }
        return rc;
 }
 
@@ -94,6 +96,10 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr)
        dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read of 
0x%x", mantis->num, addr);
        mutex_lock(&mantis->int_stat_lock);
 
+       if (test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+               dprintk(MANTIS_NOTICE, 1, "Adapter(%d) Slot(0): Read operation 
done before it started!", mantis->num);
+       }
+
        hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
        hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
        hif_addr |=  MANTIS_HIF_STATUS;
@@ -123,6 +129,9 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 
data)
 
        dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", 
mantis->num);
        mutex_lock(&mantis->int_stat_lock);
+       if (test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+               dprintk(MANTIS_NOTICE, 1, "Adapter(%d) Slot(0): Write operation 
done before it started!", mantis->num);
+       }
        hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
        hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
        hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
@@ -151,6 +160,9 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr)
 
        dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read of 
0x%x", mantis->num, addr);
        mutex_lock(&mantis->int_stat_lock);
+       if (test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+               dprintk(MANTIS_NOTICE, 1, "Adapter(%d) Slot(0): I/O read 
operation done before it started!", mantis->num);
+       }
        hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
        hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
        hif_addr |=  MANTIS_HIF_STATUS;
@@ -181,6 +193,9 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 
data)
 
        dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", 
mantis->num);
        mutex_lock(&mantis->int_stat_lock);
+       if (test_and_clear_bit(MANTIS_SBUF_OPDONE_BIT, &ca->hif_event)) {
+               dprintk(MANTIS_NOTICE, 1, "Adapter(%d) Slot(0): I/O write 
operation done before it started!", mantis->num);
+       }
        hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
        hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
        hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
diff --git a/drivers/media/dvb/mantis/mantis_link.h 
b/drivers/media/dvb/mantis/mantis_link.h
index c59602d..d8fefdf 100644
--- a/drivers/media/dvb/mantis/mantis_link.h
+++ b/drivers/media/dvb/mantis/mantis_link.h
@@ -48,7 +48,7 @@ struct mantis_ca {
 
        struct work_struct              hif_evm_work;
 
-       u32                             hif_event;
+       volatile unsigned long          hif_event;
        wait_queue_head_t               hif_opdone_wq;
        wait_queue_head_t               hif_brrdyw_wq;
        wait_queue_head_t               hif_data_wq;
diff --git a/drivers/media/dvb/mantis/mantis_reg.h 
b/drivers/media/dvb/mantis/mantis_reg.h
index 7761f9d..be57b78 100644
--- a/drivers/media/dvb/mantis/mantis_reg.h
+++ b/drivers/media/dvb/mantis/mantis_reg.h
@@ -152,11 +152,13 @@
 
 #define MANTIS_GPIF_STATUS             0x9c
 #define MANTIS_SBUF_KILLOP             (0x01 << 15)
-#define MANTIS_SBUF_OPDONE             (0x01 << 14)
+#define MANTIS_SBUF_OPDONE_BIT         14
+#define MANTIS_SBUF_OPDONE             (0x01 << MANTIS_SBUF_OPDONE_BIT)
 #define MANTIS_SBUF_EMPTY              (0x01 << 13)
 #define MANTIS_GPIF_DETSTAT            (0x01 <<  9)
 #define MANTIS_GPIF_INTSTAT            (0x01 <<  8)
-#define MANTIS_GPIF_WRACK              (0x01 <<  7)
+#define MANTIS_GPIF_WRACK_BIT          7
+#define MANTIS_GPIF_WRACK              (0x01 <<  MANTIS_GPIF_WRACK_BIT)
 #define MANTIS_GPIF_BRRDY              (0x01 <<  6)
 #define MANTIS_SBUF_OVFLW              (0x01 <<  5)
 #define MANTIS_GPIF_OTHERR             (0x01 <<  4)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to