From: Michael Bringmann <michael.bringm...@lsi.com>

Added a state variable to the interrupt status so the interrupt
for rapidio. This status helps to identify a clearer state
when the interrupt is processed.

Signed-off-by: Michael Bringmann <michael.bringm...@lsi.com>
---
 drivers/rapidio/devices/lsi/axxia-rio-ds.c  |    2 ++
 drivers/rapidio/devices/lsi/axxia-rio-irq.c |   48 +++++++++++++++++----------
 drivers/rapidio/devices/lsi/axxia-rio-irq.h |    2 ++
 3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/rapidio/devices/lsi/axxia-rio-ds.c 
b/drivers/rapidio/devices/lsi/axxia-rio-ds.c
index 4e55ed7..2627b07 100755
--- a/drivers/rapidio/devices/lsi/axxia-rio-ds.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio-ds.c
@@ -1819,6 +1819,7 @@ void axxia_rio_ds_port_irq_init(
                ptr_ds_priv->ob_dse_irq[i].irq_state_reg_addr =
                                RAB_INTR_STAT_ODSE;
                ptr_ds_priv->ob_dse_irq[i].irq_state_mask = (1 << i);
+               ptr_ds_priv->ob_dse_irq[i].irq_state = 0;
                ptr_ds_priv->ob_dse_irq[i].thrd_irq_fn = ob_dse_irq_handler;
                ptr_ds_priv->ob_dse_irq[i].data = NULL;
                ptr_ds_priv->ob_dse_irq[i].release_fn = release_ob_ds;
@@ -1838,6 +1839,7 @@ void axxia_rio_ds_port_irq_init(
                ptr_ds_priv->ib_dse_vsid_irq[i].irq_state_reg_addr =
                        RAB_INTR_STAT_IBSE_VSID_M;
                ptr_ds_priv->ib_dse_vsid_irq[i].irq_state_mask = (1 << i);
+               ptr_ds_priv->ib_dse_vsid_irq[i].irq_state = 0;
                ptr_ds_priv->ib_dse_vsid_irq[i].thrd_irq_fn =
                                ib_dse_vsid_m_irq_handler;
                ptr_ds_priv->ib_dse_vsid_irq[i].data = NULL;
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.c 
b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
index cb16281..9879b7e 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
@@ -348,19 +348,9 @@ static void reset_state_counters(struct rio_priv *priv)
 static irqreturn_t thrd_irq_handler(int irq, void *data)
 {
        struct rio_irq_handler *h = data;
-       struct rio_mport *mport = h->mport;
-       u32 state;
 
        atomic_inc(&thrd_handler_calls);
 
-       /**
-        * Get current interrupt state and clear latched state
-        * for interrupts handled by current thread.
-        */
-       __rio_local_read_config_32(mport, h->irq_state_reg_addr, &state);
-       state &= h->irq_state_mask;
-       __rio_local_write_config_32(mport, h->irq_state_reg_addr, state);
-
 #ifdef CONFIG_SRIO_IRQ_TIME
        if (atomic_read(&h->start_time))
                h->thrd_tb = get_tb();
@@ -370,7 +360,7 @@ static irqreturn_t thrd_irq_handler(int irq, void *data)
         * Invoke handler callback
         */
        test_and_set_bit(RIO_IRQ_ACTIVE, &h->state);
-       h->thrd_irq_fn(h, state);
+       h->thrd_irq_fn(h, h->irq_state);
        clear_bit(RIO_IRQ_ACTIVE, &h->state);
 
        return IRQ_HANDLED;
@@ -386,18 +376,25 @@ static irqreturn_t hw_irq_handler(int irq, void *data)
 {
        struct rio_irq_handler *h = data;
        struct rio_mport *mport = h->mport;
-       u32 state;
 
        atomic_inc(&hw_handler_calls);
 
-       __rio_local_read_config_32(mport, h->irq_state_reg_addr, &state);
-       if (state & h->irq_state_mask) {
+       /**
+        * Get current interrupt state and clear latched state
+        * for interrupts handled by current thread.
+        */
+       __rio_local_read_config_32(mport, h->irq_state_reg_addr, &h->irq_state);
+       h->irq_state &= h->irq_state_mask;
+       __rio_local_write_config_32(mport, h->irq_state_reg_addr, h->irq_state);
+
+       if (h->irq_state & h->irq_state_mask) {
 #ifdef CONFIG_SRIO_IRQ_TIME
                if (atomic_read(&h->start_time))
                        h->irq_tb = get_tb();
 #endif
                return IRQ_WAKE_THREAD;
        }
+
        return IRQ_NONE;
 }
 
@@ -1013,7 +1010,7 @@ static inline int choose_ob_dme(
                        if (len > sz)
                                continue;
 
-                       if (dme->entries > (dme->entries_in_use+1)) {
+                       if (dme->entries >= (dme->entries_in_use+1)) {
                                (*ob_dme) = dme;
                                (*buf_sz) = sz;
                                return ret + i;
@@ -1198,10 +1195,10 @@ static void ob_dme_irq_handler(struct rio_irq_handler 
*h, u32 state)
        struct rio_mport *mport = h->mport;
        struct rio_priv *priv = mport->priv;
        struct rio_msg_dme *mbox = h->data;
-       int i;
        u32 dme_stat, dw0, dme_no = 31 - CNTLZW(state);
        u32 dme_ctrl;
        unsigned long flags;
+       int i;
 
        /**
         * Clear latched state
@@ -1253,7 +1250,6 @@ static void ob_dme_irq_handler(struct rio_irq_handler *h, 
u32 state)
                        if (mport->outb_msg[dme_no].mcback) {
                                __ob_dme_event_dbg(priv, dme_no,
                                                1 << RIO_OB_DME_TX_DESC_READY);
-
                                mport->outb_msg[dme_no].mcback(mport,
                                                        mbox->dev_id,
                                                        dme_no,
@@ -1533,7 +1529,8 @@ static void ib_dme_irq_handler(struct rio_irq_handler *h, 
u32 state)
                                         DESC_TABLE_W0(desc->desc_no), &dw0);
                        }
 
-                       if (dw0 & DME_DESC_DW0_READY_MASK) {
+                       if ((dw0 & DME_DESC_DW0_READY_MASK) &&
+                           (dw0 & DME_DESC_DW0_VALID)) {
 
                                /* Some chips clear this bit, some don't.
                                ** Make sure in any event. */
@@ -2305,6 +2302,7 @@ int axxia_add_inb_buffer(struct rio_mport *mport, int 
mbox, void *buf)
 {
        struct rio_priv *priv = mport->priv;
        struct rio_rx_mbox *mb;
+       unsigned long iflags;
        int rc = 0;
 
        if ((mbox < 0) || (mbox >= RIO_MAX_RX_MBOX))
@@ -2313,12 +2311,15 @@ int axxia_add_inb_buffer(struct rio_mport *mport, int 
mbox, void *buf)
        mb = mbox_get(priv->ib_dme_irq[mbox].data);
        if (!mb)
                return -EINVAL;
+
+       spin_lock_irqsave(&mb->lock, iflags);
        if (mb->virt_buffer[mb->last_rx_slot])
                goto busy;
 
        mb->virt_buffer[mb->last_rx_slot] = buf;
        mb->last_rx_slot = (mb->last_rx_slot + 1) % mb->ring_size;
 done:
+       spin_unlock_irqrestore(&mb->lock, iflags);
        mbox_put(mb);
        return rc;
 busy:
@@ -2343,6 +2344,7 @@ void *axxia_get_inb_message(struct rio_mport *mport, int 
mbox, int letter,
        struct rio_priv *priv = mport->priv;
        struct rio_rx_mbox *mb;
        struct rio_msg_dme *me;
+       unsigned long iflags;
        void *buf = NULL;
 
        if ((mbox < 0) || (mbox >= RIO_MAX_RX_MBOX))
@@ -2358,6 +2360,7 @@ void *axxia_get_inb_message(struct rio_mport *mport, int 
mbox, int letter,
        if (!me)
                return ERR_PTR(-EINVAL);
 
+       spin_lock_irqsave(&mb->lock, iflags);
        if (!in_interrupt() &&
            !test_bit(RIO_IRQ_ACTIVE, &priv->ib_dme_irq[mbox].state)) {
                u32     intr;
@@ -2449,6 +2452,7 @@ void *axxia_get_inb_message(struct rio_mport *mport, int 
mbox, int letter,
                }
        }
 done:
+       spin_unlock_irqrestore(&mb->lock, iflags);
        dme_put(me);
        mbox_put(mb);
        return buf;
@@ -2476,6 +2480,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
                GRIO_INT | LL_TL_INT | UNEXP_MSG_LOG |
                UNSP_RIO_REQ_INT | UNEXP_MSG_INT;
 #endif
+       priv->misc_irq.irq_state = 0;
        priv->misc_irq.thrd_irq_fn = misc_irq_handler;
        priv->misc_irq.data = NULL;
        priv->misc_irq.release_fn = NULL;
@@ -2488,6 +2493,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
        priv->linkdown_irq.irq_enab_reg_addr = 0;
        priv->linkdown_irq.irq_state_reg_addr = RAB_SRDS_STAT1;
        priv->linkdown_irq.irq_state_mask = RAB_SRDS_STAT1_LINKDOWN_INT;
+       priv->linkdown_irq.irq_state = 0;
        priv->linkdown_irq.thrd_irq_fn = linkdown_irq_handler;
        priv->linkdown_irq.data = NULL;
        priv->linkdown_irq.release_fn = NULL;
@@ -2500,6 +2506,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
        priv->pw_irq.irq_enab_reg_addr = RAB_INTR_ENAB_MISC;
        priv->pw_irq.irq_state_reg_addr = RAB_INTR_STAT_MISC;
        priv->pw_irq.irq_state_mask = PORT_WRITE_INT;
+       priv->pw_irq.irq_state = 0;
        priv->pw_irq.thrd_irq_fn = pw_irq_handler;
        priv->pw_irq.data = NULL;
        priv->pw_irq.release_fn = disable_pw;
@@ -2515,6 +2522,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
 #if defined(CONFIG_AXXIA_RIO_STAT)
        priv->db_irq.irq_state_mask |= OB_DB_DONE_INT;
 #endif
+       priv->db_irq.irq_state = 0;
        priv->db_irq.thrd_irq_fn = db_irq_handler;
        priv->db_irq.data = NULL;
        priv->db_irq.release_fn = NULL;
@@ -2528,6 +2536,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
                priv->ob_dme_irq[i].irq_enab_reg_addr = RAB_INTR_ENAB_ODME;
                priv->ob_dme_irq[i].irq_state_reg_addr = RAB_INTR_STAT_ODME;
                priv->ob_dme_irq[i].irq_state_mask = (1 << i);
+               priv->ob_dme_irq[i].irq_state = 0;
                priv->ob_dme_irq[i].thrd_irq_fn = ob_dme_irq_handler;
                priv->ob_dme_irq[i].data = NULL;
                priv->ob_dme_irq[i].release_fn = release_outb_mbox;
@@ -2542,6 +2551,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
                priv->ib_dme_irq[i].irq_enab_reg_addr = RAB_INTR_ENAB_IDME;
                priv->ib_dme_irq[i].irq_state_reg_addr = RAB_INTR_STAT_IDME;
                priv->ib_dme_irq[i].irq_state_mask = 0; /*(0xf << (i * 4));*/
+               priv->ib_dme_irq[i].irq_state = 0;
                priv->ib_dme_irq[i].thrd_irq_fn = ib_dme_irq_handler;
                priv->ib_dme_irq[i].data = NULL;
                priv->ib_dme_irq[i].release_fn = release_inb_mbox;
@@ -2560,6 +2570,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
 #else
        priv->apio_irq.irq_state_mask = 0;
 #endif
+       priv->apio_irq.irq_state = 0;
        priv->apio_irq.thrd_irq_fn = apio_irq_handler;
        priv->apio_irq.data = NULL;
        priv->apio_irq.release_fn = NULL;
@@ -2573,6 +2584,7 @@ void axxia_rio_port_irq_init(struct rio_mport *mport)
 #else
        priv->rpio_irq.irq_state_mask = 0;
 #endif
+       priv->rpio_irq.irq_state = 0;
        priv->rpio_irq.thrd_irq_fn = rpio_irq_handler;
        priv->rpio_irq.data = NULL;
        priv->rpio_irq.release_fn = NULL;
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.h 
b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
index d98ebfd..fde7140 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.h
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
@@ -235,6 +235,7 @@ struct rio_msg_dme {
 };
 
 struct rio_rx_mbox {
+       spinlock_t lock;
        int mbox_no;
        char name[16];
        struct kref kref;
@@ -266,6 +267,7 @@ struct rio_irq_handler {
        u32 irq_enab_reg_addr;
        u32 irq_state_reg_addr;
        u32 irq_state_mask;
+       u32 irq_state;
        void (*thrd_irq_fn)(struct rio_irq_handler *h, u32 state);
        void (*release_fn)(struct rio_irq_handler *h);
        void *data;
-- 
1.7.9.5

-- 
_______________________________________________
linux-yocto mailing list
linux-yo...@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to