[PATCH] Synchronize smd commands

Eugene Krasnikov k.eugene.e at gmail.com
Fri Jul 5 06:30:49 EDT 2013


Add protection to smd api to make sure all smd
commands are sent sequentially.

Signed-off-by: Eugene Krasnikov <k.eugene.e at gmail.com>
---
 main.c    |  2 ++
 smd.c     | 24 ++++++++++++++++++++----
 wcn36xx.h |  6 ++++++
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/main.c b/main.c
index 0cc3e02..cb2a5d8 100644
--- a/main.c
+++ b/main.c
@@ -945,6 +945,7 @@ static int __init wcn36xx_init(void)
 	wcn->is_joining = false;
 
 	mutex_init(&wcn->pm_mutex);
+	mutex_init(&wcn->smd_mutex);
 	wcn->hw->wiphy->n_addresses = ARRAY_SIZE(wcn->addresses);
 	wcn->hw->wiphy->addresses = wcn->addresses;
 
@@ -1002,6 +1003,7 @@ static void __exit wcn36xx_exit(void)
 	struct wcn36xx *wcn = hw->priv;
 
 	mutex_destroy(&wcn->pm_mutex);
+	mutex_destroy(&wcn->smd_mutex);
 	ieee80211_unregister_hw(hw);
 	destroy_workqueue(wcn->wq);
 	iounmap(wcn->mmio);
diff --git a/smd.c b/smd.c
index ce09563..d291607 100644
--- a/smd.c
+++ b/smd.c
@@ -20,6 +20,7 @@
 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 {
 	int avail;
+	int ret = 0;
 
 	init_completion(&wcn->smd_compl);
 	avail = smd_write_avail(wcn->smd_ch);
@@ -29,19 +30,28 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 		avail = smd_write(wcn->smd_ch, wcn->smd_buf, len);
 		if (avail != len) {
 			wcn36xx_error("Cannot write to SMD channel");
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto out;
+
 		}
 	} else {
 		wcn36xx_error("SMD channel can accept only %d bytes", avail);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out;
+
 	}
 
 	if (wait_for_completion_timeout(&wcn->smd_compl,
 		msecs_to_jiffies(SMD_MSG_TIMEOUT)) <= 0) {
 		wcn36xx_error("Timeout while waiting SMD response");
-		return -ETIME;
+		ret = -ETIME;
+		goto out;
+
 	}
-	return 0;
+out:
+	mutex_unlock(&wcn->smd_mutex);
+	return ret;
+
 }
 
 #define INIT_HAL_MSG(msg_body, type) \
@@ -54,6 +64,10 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 
 #define PREPARE_HAL_BUF(send_buf, msg_body) \
 	do {							\
+		struct wcn36xx *__wcn =				\
+			container_of(&send_buf,			\
+				     struct wcn36xx, smd_buf);	\
+		mutex_lock(&__wcn->smd_mutex);                  \
 		memset(send_buf, 0, msg_body.header.len);	\
 		memcpy(send_buf, &msg_body, sizeof(msg_body));	\
 	} while (0)						\
@@ -101,6 +115,8 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 			msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
 
 		}
+		/* smd_buf must be protected with  mutex */
+		mutex_lock(&wcn->smd_mutex);
 
 		/* Add load NV request message header */
 		memcpy(wcn->smd_buf, &msg_body,	sizeof(msg_body));
diff --git a/wcn36xx.h b/wcn36xx.h
index 2c72349..653381f 100644
--- a/wcn36xx.h
+++ b/wcn36xx.h
@@ -139,7 +139,13 @@ struct wcn36xx {
 
 	/* SMD related */
 	smd_channel_t		*smd_ch;
+	/*
+	 * smd_buf must be protected with smd_mutex to garantee
+	 * that all messages are sent one after another
+	 */
 	u8			*smd_buf;
+	struct mutex            smd_mutex;
+
 	struct work_struct	smd_work;
 	struct work_struct	start_work;
 	struct work_struct	rx_ready_work;
-- 
1.7.11.3




More information about the wcn36xx mailing list