[linux-yocto] [PATCH 27/30] LSI AXM55XX/rapidio: Stability and bug fix improvements , Correct boundary, Expand valid condition.
Charlie Paul
cpaul.windriver at gmail.com
Thu Apr 17 19:37:15 PDT 2014
From: Michael Bringmann <michael.bringmann at 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.bringmann at 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
More information about the linux-yocto
mailing list