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

Add additional spinlocks/mutexes to each controller state to increase
concurrency and performance.  Fix some bound checks for full outbound
DME descriptor chains, correct a lockup/delay issue with errors in the
outbound DME chains, and remove a delay loop.

rapidio/LSI AXM55xx: Correct some boundary checks for argument values.

Also correct formatting of platform-specific function code.

LSI AXM55xx: Expand valid condition checks for inbound message DME chains.

Signed-off-by: Michael Bringmann <michael.bringm...@lsi.com>
---
 arch/arm/include/asm/axxia-rio.h            |   31 ++++--
 drivers/rapidio/devices/lsi/axxia-rio-ds.c  |   22 ++--
 drivers/rapidio/devices/lsi/axxia-rio-irq.c |  156 ++++++++-------------------
 drivers/rapidio/devices/lsi/axxia-rio-irq.h |   13 +--
 drivers/rapidio/devices/lsi/axxia-rio.c     |    3 +-
 drivers/rapidio/devices/lsi/axxia-rio.h     |   16 ++-
 6 files changed, 101 insertions(+), 140 deletions(-)

diff --git a/arch/arm/include/asm/axxia-rio.h b/arch/arm/include/asm/axxia-rio.h
index e01d6a3..492d476 100644
--- a/arch/arm/include/asm/axxia-rio.h
+++ b/arch/arm/include/asm/axxia-rio.h
@@ -94,21 +94,32 @@ static inline u32 CNTLZW(u32 val)
        int n = 0;
        if (val == 0)
                return 32;
-       if ((val & 0xFFFF0000) == 0)
-               n += 16; val = val << 16;
+
+       if ((val & 0xFFFF0000) == 0) {
+               n += 16;
+               val = val << 16;
+       }
                /* 1111 1111 1111 1111 0000 0000 0000 0000
                // 16 bits from left are zero! so we omit 16 left bits */
-       if ((val & 0xFF000000) == 0)
-               n = n + 8; val = val << 8;
+       if ((val & 0xFF000000) == 0) {
+               n = n + 8;
+               val = val << 8;
+       }
                /* 8 left bits are 0 */
-       if ((val & 0xF0000000) == 0)
-               n = n + 4; val = val << 4;
+       if ((val & 0xF0000000) == 0) {
+               n = n + 4;
+               val = val << 4;
+       }
                /* 4 left bits are 0 */
-       if ((val & 0xC0000000) == 0)
-               n = n + 2, val = val << 2;
+       if ((val & 0xC0000000) == 0) {
+               n = n + 2;
+               val = val << 2;
+       }
                /* 110000....0 2 left bits are zero */
-       if ((val & 0x80000000) == 0)
-               n = n + 1, val = val << 1;
+       if ((val & 0x80000000) == 0) {
+               n = n + 1;
+               val = val << 1;
+       }
                /* first left bit is zero */
        return n;
 }
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-ds.c 
b/drivers/rapidio/devices/lsi/axxia-rio-ds.c
index f4f44a6..02d3751 100755
--- a/drivers/rapidio/devices/lsi/axxia-rio-ds.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio-ds.c
@@ -240,9 +240,10 @@ int axxia_open_ob_data_stream(
        int                     num_header_entries,
        int                     num_data_entries)
 {
+       struct rio_priv         *priv = mport->priv;
        int     rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
 
        rc = open_ob_data_stream(mport,
                                dev_id,
@@ -250,7 +251,7 @@ int axxia_open_ob_data_stream(
                                num_header_entries,
                                num_data_entries);
 
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -747,12 +748,12 @@ int axxia_close_ob_data_stream(
        struct rio_ds_hdr_desc  *ptr_hdr_desc;
        u32    dse_ctrl, i;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
 
        ptr_dse_cfg = &(ptr_ds_priv->obds_dse_cfg[dse_id]);
 
        if (ptr_dse_cfg->in_use == RIO_DS_FALSE) {
-               axxia_api_unlock();
+               axxia_api_unlock(priv);
                return 0;
        }
 
@@ -791,7 +792,7 @@ int axxia_close_ob_data_stream(
        /* release the IRQ handler */
        release_irq_handler(&(ptr_ds_priv->ob_dse_irq[dse_id]));
 
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return 0;
 }
@@ -830,9 +831,10 @@ int axxia_open_ib_data_stream(
        int                     desc_dbuf_size,
        int                     num_entries)
 {
+       struct rio_priv *priv = mport->priv;
        int rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
 
        rc = open_ib_data_stream(mport,
                                 dev_id,
@@ -840,7 +842,7 @@ int axxia_open_ib_data_stream(
                                 cos,
                                 desc_dbuf_size,
                                 num_entries);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -1522,7 +1524,7 @@ int axxia_close_ib_data_stream(
        struct rio_ids_data_desc *ptr_data_desc;
        u8      virt_vsid;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
 
        for (i = 0; i < (ptr_ds_priv->num_ibds_virtual_m); i++) {
                ptr_virt_m_cfg = &(ptr_ds_priv->ibds_vsid_m_cfg[i]);
@@ -1537,7 +1539,7 @@ int axxia_close_ib_data_stream(
        }
 
        if (find_ava_virt_m == RIO_DS_FALSE) {
-               axxia_api_unlock();
+               axxia_api_unlock(priv);
                return 0;
        }
 
@@ -1567,7 +1569,7 @@ int axxia_close_ib_data_stream(
        if (ptr_virt_m_cfg->ptr_ibds_data_desc != NULL)
                kfree(ptr_virt_m_cfg->ptr_ibds_data_desc);
 
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return 0;
 }
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.c 
b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
index e962b0c..91175a0 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.c
@@ -44,8 +44,6 @@
 ** Local State
 */
 
-DEFINE_MUTEX(axxia_rio_api_mutex);
-
 atomic_t thrd_handler_calls = ATOMIC_INIT(0);
 atomic_t hw_handler_calls = ATOMIC_INIT(0);
 atomic_t port_irq_disabled = ATOMIC_INIT(0);
@@ -475,11 +473,11 @@ static void rio_port_down_notify(struct rio_mport *mport)
        unsigned long flags;
        struct rio_priv *priv = mport->priv;
 
-       spin_lock_irqsave(&priv->rio_lock, flags);
+       spin_lock_irqsave(&priv->port_lock, flags);
        if (priv->port_notify_cb)
                priv->port_notify_cb(mport);
 
-       spin_unlock_irqrestore(&priv->rio_lock, flags);
+       spin_unlock_irqrestore(&priv->port_lock, flags);
 }
 #else
 #define rio_port_down_notify(mport)
@@ -1018,7 +1016,7 @@ static inline int choose_ob_dme(
                        if (len > sz)
                                continue;
 
-                       if (dme->entries > dme->entries_in_use) {
+                       if (dme->entries >= (dme->entries_in_use+1)) {
                                (*ob_dme) = dme;
                                (*buf_sz) = sz;
                                return ret + i;
@@ -1209,11 +1207,9 @@ 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, pending = 0, ack_id = 0;
+       int i, ack_id = 0;
        u32 dme_stat, dw0, dme_no = 31 - CNTLZW(state);
-       u64 start, curr;
        u32 dme_ctrl;
-       u32 debug = 0;
        unsigned long flags;
 
        /**
@@ -1223,79 +1219,15 @@ static void ob_dme_irq_handler(struct rio_irq_handler 
*h, u32 state)
        __rio_local_write_config_32(mport, RAB_OB_DME_STAT(dme_no), dme_stat);
        __ob_dme_dbg(priv, dme_stat);
 
-       /**
-        * Wait for all pending transactions to finish before doing descriptor
-        * updates
-        */
        spin_lock_irqsave(&mbox->lock, flags);
 
-       start = get_tb();
-       do {
-               pending = 0;
-               for (i = 0; i < mbox->entries; i++) {
-                       struct rio_msg_desc *desc = &mbox->desc[i];
-
-                       if (!priv->internalDesc) {
-                               dw0 = *((u32 *)DESC_TABLE_W0_MEM(mbox,
-                                                               desc->desc_no));
-                       } else {
-                               __rio_local_read_config_32(mport,
-                                       DESC_TABLE_W0(desc->desc_no), &dw0);
-                       }
-                       if ((dw0 & DME_DESC_DW0_VALID) &&
-                           !(dw0 & DME_DESC_DW0_READY_MASK))
-                               pending++;
-               }
-               if (!pending) {
-                       mbox->tx_dme_tmo = 0;
-                       break;
-               }
-
-               /**
-                * Don't wait indefinitely - if something is broken
-                */
-               curr = get_tb();
-               if ((curr - start) > 200000) {
-                       dev_dbg(priv->dev,
-                               "RIO-IRQ: TO waiting for %d ob desc "
-                               "transaction to finish\n",
-                               pending);
-               }
-       } while (pending);
 
        /**
         * Try to kick back some life in the HW if it is un-responsive
         */
-       if (pending) {
-               mbox->tx_dme_tmo++;
-               if (dme_stat & RIO_OB_DME_STAT_SLEEPING)
-                       debug |= 1 << RIO_OB_DME_TX_SLEEP;
-               debug |= 1 << RIO_OB_DME_TX_PENDING;
-
-               __rio_local_read_config_32(mport, RAB_OB_DME_CTRL(dme_no),
-                                          &dme_ctrl);
-               if (mbox->tx_dme_tmo > 100) {
-                       /**
-                        * Must be in serious trouble now, don't burn more
-                        * CPU cycles.
-                        * FIXME! Notify someone that we're broken, report
-                        * state event through RIO maybe?
-                        */
-                       dev_dbg(priv->dev,
-                               "RIO-IRQ: OB DME %d disabled due to "
-                               "excessive TO events\n",
-                               dme_no);
-                       dme_ctrl &= ~(DME_WAKEUP | DME_ENABLE);
-               } else {
-                       debug |= 1 << RIO_OB_DME_TX_WAKEUP;
-                       dme_ctrl |= DME_WAKEUP | DME_ENABLE;
-               }
-               __rio_local_write_config_32(mport, RAB_OB_DME_CTRL(dme_no),
-                                           dme_ctrl);
-               __ob_dme_event_dbg(priv, dme_no, debug);
-               spin_unlock_irqrestore(&mbox->lock, flags);
-               return;
-       }
+       __rio_local_read_config_32(mport, RAB_OB_DME_CTRL(dme_no), &dme_ctrl);
+       dme_ctrl |= DME_WAKEUP | DME_ENABLE;
+       __rio_local_write_config_32(mport, RAB_OB_DME_CTRL(dme_no), dme_ctrl);
 
        /**
         * Process all completed transactions
@@ -1326,8 +1258,8 @@ static void ob_dme_irq_handler(struct rio_irq_handler *h, 
u32 state)
                                        dw0 & DME_DESC_DW0_NXT_DESC_VALID);
                        }
                        __ob_dme_dw_dbg(priv, dw0);
-                       if (dw0 & DME_DESC_DW0_DONE)
-                               mbox->entries_in_use--;
+
+                       mbox->entries_in_use--;
                }
        }
        spin_unlock_irqrestore(&mbox->lock, flags);
@@ -1375,7 +1307,7 @@ static int open_outb_mbox(struct rio_mport *mport, void 
*dev_id, int dme_no,
        u64 descChainStart, descAddr;
        int buf_sz = 0;
 
-       if (entries > priv->desc_max_entries)
+       if ((entries <= 0) || (entries > priv->desc_max_entries))
                return -EINVAL;
 
        if (test_bit(RIO_IRQ_ENABLED, &h->state))
@@ -1618,8 +1550,10 @@ 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) &&
-                           (dw0 & DME_DESC_DW0_VALID)) {
+                       if (dw0 & DME_DESC_DW0_READY_MASK) {
+
+                               /* Some chips clear this bit, some don't.
+                               ** Make sure in any event. */
                                if (!priv->internalDesc) {
                                        *((u32 *)DESC_TABLE_W0_MEM(me,
                                                         desc->desc_no)) =
@@ -1629,6 +1563,7 @@ static void ib_dme_irq_handler(struct rio_irq_handler *h, 
u32 state)
                                                DESC_TABLE_W0(desc->desc_no),
                                                dw0 & ~DME_DESC_DW0_VALID);
                                }
+
                                __ib_dme_dw_dbg(priv, dw0);
                                __ib_dme_event_dbg(priv, dme_no,
                                                   1 << RIO_IB_DME_RX_PUSH);
@@ -1730,7 +1665,7 @@ static int open_inb_mbox(struct rio_mport *mport, void 
*dev_id,
        if ((mbox < 0) || (mbox >= RIO_MAX_RX_MBOX))
                return -EINVAL;
 
-       if (entries > priv->desc_max_entries)
+       if ((entries <= 0) || (entries > priv->desc_max_entries))
                return -EINVAL;
 
        h = &priv->ib_dme_irq[mbox];
@@ -2070,12 +2005,12 @@ int axxia_rio_pw_enable(struct rio_mport *mport, int 
enable)
        struct rio_priv *priv = mport->priv;
        int rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        if (enable)
                rc = enable_pw(&priv->pw_irq);
        else
                release_irq_handler(&priv->pw_irq);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -2156,11 +2091,12 @@ int axxia_open_outb_mbox(
        int entries,
        int prio)
 {
+       struct rio_priv *priv = mport->priv;
        int rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        rc = open_outb_mbox(mport, dev_id, mboxDme, entries, prio);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -2181,9 +2117,9 @@ void axxia_close_outb_mbox(struct rio_mport *mport, int 
mboxDme)
            (mboxDme > (priv->numOutbDmes[0]+priv->numOutbDmes[0])))
                return;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        release_irq_handler(&priv->ob_dme_irq[mboxDme]);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return;
 }
@@ -2211,13 +2147,12 @@ static struct rio_msg_desc *get_ob_desc(struct 
rio_mport *mport,
                                           DESC_TABLE_W0(desc->desc_no),
                                           &dw0);
                }
-               if (!(dw0 & DME_DESC_DW0_VALID)) {
+               if (!(dw0 & DME_DESC_DW0_VALID) ||
+                   (dw0 & DME_DESC_DW0_ERROR_MASK)) {
                        if (desc_num != mb->write_idx)
-                               dev_dbg(priv->dev,
-                                       "RIO: Adding buffer descriptors "
-                                       "out of order to TX DME\n");
+                               return NULL;
                        if (desc_num == mb->write_idx)
-                               mb->write_idx = (mb->write_idx +  1) %
+                               mb->write_idx = (mb->write_idx + 1) %
                                                 mb->entries;
                        return desc;
                }
@@ -2245,7 +2180,7 @@ int axxia_add_outb_message(struct rio_mport *mport, 
struct rio_dev *rdev,
                             int mbox_dest, int letter, int flags,
                             void *buffer, size_t len, void *cookie)
 {
-       int rc = 0;
+       int rc = 0, dme;
        u32 dw0, dw1, dme_ctrl;
        u16 destid = (rdev ? rdev->destid : mport->host_deviceid);
        struct rio_priv *priv = mport->priv;
@@ -2258,9 +2193,11 @@ int axxia_add_outb_message(struct rio_mport *mport, 
struct rio_dev *rdev,
            (mbox_dest >= RIO_MAX_TX_MBOX))
                return -EINVAL;
 
-       rc = choose_ob_dme(priv, len, &mb, &buf_sz);
-       if (rc < 0)
+       dme = choose_ob_dme(priv, len, &mb, &buf_sz);
+       if (dme < 0) {
+               rc = dme;
                return rc;
+       }
 
        if ((len < 8) || (len > buf_sz))
                return -EINVAL;
@@ -2340,11 +2277,12 @@ done:
 int axxia_open_inb_mbox(struct rio_mport *mport, void *dev_id,
                        int mbox, int entries)
 {
+       struct rio_priv *priv = mport->priv;
        int rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        rc = open_inb_mbox(mport, dev_id, mbox, entries);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -2364,9 +2302,9 @@ void axxia_close_inb_mbox(struct rio_mport *mport, int 
mbox)
        if ((mbox < 0) || (mbox >= RIO_MAX_RX_MBOX))
                return;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        release_irq_handler(&priv->ib_dme_irq[mbox]);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return;
 }
@@ -2666,7 +2604,7 @@ int axxia_rio_port_notify_cb(struct rio_mport *mport,
        unsigned long flags;
        int rc = 0;
 
-       spin_lock_irqsave(&priv->rio_lock, flags);
+       spin_lock_irqsave(&priv->port_lock, flags);
        if (enable) {
                if (priv->port_notify_cb)
                        rc = -EBUSY;
@@ -2678,7 +2616,7 @@ int axxia_rio_port_notify_cb(struct rio_mport *mport,
                else
                        priv->port_notify_cb = NULL;
        }
-       spin_unlock_irqrestore(&priv->rio_lock, flags);
+       spin_unlock_irqrestore(&priv->port_lock, flags);
 
        return rc;
 }
@@ -2701,9 +2639,9 @@ int axxia_rio_apio_enable(struct rio_mport *mport, u32 
mask, u32 bits)
        struct rio_priv *priv = mport->priv;
        int rc;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        rc = enable_apio(&priv->apio_irq, mask, bits);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -2713,9 +2651,9 @@ int axxia_rio_apio_disable(struct rio_mport *mport)
 {
        struct rio_priv *priv = mport->priv;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        release_irq_handler(&priv->apio_irq);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return 0;
 }
@@ -2726,9 +2664,9 @@ int axxia_rio_rpio_enable(struct rio_mport *mport, u32 
mask, u32 bits)
        struct rio_priv *priv = mport->priv;
        int rc = 0;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        rc = enable_rpio(&priv->rpio_irq, mask, bits);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return rc;
 }
@@ -2738,9 +2676,9 @@ int axxia_rio_rpio_disable(struct rio_mport *mport)
 {
        struct rio_priv *priv = mport->priv;
 
-       axxia_api_lock();
+       axxia_api_lock(priv);
        release_irq_handler(&priv->rpio_irq);
-       axxia_api_unlock();
+       axxia_api_unlock(priv);
 
        return 0;
 }
diff --git a/drivers/rapidio/devices/lsi/axxia-rio-irq.h 
b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
index 9313ccd..b456541 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio-irq.h
+++ b/drivers/rapidio/devices/lsi/axxia-rio-irq.h
@@ -3,6 +3,7 @@
 
 /* forward declaration */
 struct rio_priv;
+struct mutex;
 
 #if !defined(CONFIG_AXXIA_RIO_STAT)
 
@@ -281,16 +282,10 @@ struct rio_irq_handler {
 #endif
 };
 
-extern struct mutex axxia_rio_api_mutex;
 
-static inline void axxia_api_lock(void)
-{
-       mutex_lock(&axxia_rio_api_mutex);
-}
-static inline void axxia_api_unlock(void)
-{
-       mutex_unlock(&axxia_rio_api_mutex);
-}
+/**********************************************/
+/* *********** External Functions *********** */
+/**********************************************/
 
 void axxia_rio_port_irq_init(struct rio_mport *mport);
 void *axxia_get_inb_message(struct rio_mport *mport, int mbox, int letter,
diff --git a/drivers/rapidio/devices/lsi/axxia-rio.c 
b/drivers/rapidio/devices/lsi/axxia-rio.c
index 0baa7fc..5868569 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio.c
+++ b/drivers/rapidio/devices/lsi/axxia-rio.c
@@ -1422,12 +1422,13 @@ static struct rio_priv *rio_priv_dtb_setup(
        if (!priv)
                return ERR_PTR(-ENOMEM);
 
-       /* mport port driver handle (bidirectional reference supported) */
+       /* master port driver handle (bidirectional reference supported) */
        mport->priv = priv;
        priv->cookie = LSI_AXXIA_RIO_COOKIE;
        priv->mport = mport;
        priv->ndx = ndx;
        priv->portNdx = portNdx;
+       mutex_init(&priv->api_mutex);
 
        /* Max descriptors */
        priv->desc_max_entries = RIO_MSG_MAX_ENTRIES;
diff --git a/drivers/rapidio/devices/lsi/axxia-rio.h 
b/drivers/rapidio/devices/lsi/axxia-rio.h
index 3659138..55955ec 100644
--- a/drivers/rapidio/devices/lsi/axxia-rio.h
+++ b/drivers/rapidio/devices/lsi/axxia-rio.h
@@ -490,7 +490,8 @@ struct rio_desc {
 struct rio_priv {
        u32     cookie;
 
-       spinlock_t rio_lock;
+       struct mutex api_mutex;
+       spinlock_t port_lock;
 
        struct rio_mport *mport;
        struct device *dev;
@@ -546,6 +547,19 @@ struct rio_priv {
 };
 
 
+/**********************************************/
+/* *********** External Functions *********** */
+/**********************************************/
+
+static inline void axxia_api_lock(struct rio_priv *priv)
+{
+       mutex_lock(&priv->api_mutex);
+}
+static inline void axxia_api_unlock(struct rio_priv *priv)
+{
+       mutex_unlock(&priv->api_mutex);
+}
+
 extern int axxia_rio_start_port(struct rio_mport *mport);
 extern void axxia_rio_set_mport_disc_mode(struct rio_mport *mport);
 extern void axxia_rio_static_win_release(struct rio_mport *mport);
-- 
1.7.9.5

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

Reply via email to