[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