[linux-yocto] [PATCH 27/28] LSI AXM55XX/rapidio: Stability and bug fix improvements , Correct boundary, Expand valid condition.

Charlie Paul cpaul.windriver at gmail.com
Fri May 2 09:22:31 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