Commit fdb28589 authored by Raja Mani's avatar Raja Mani Committed by Kalle Valo

ath6kl: Use mutex to protect dma buffer in sync read write

Firmware crashes while starting Soft AP in 32 bit x86 platform.
The reason is that the single dma buffer (ar_sdio->dma_buffer)
is used in ath6kl_sdio_read_write_sync() for unaligned buffer
handling and this function is called in the multiple context
at the same time. So, finally hits dma buffer corruption and
firmware crash.

Mutex is used to protect dma buffer to avoid data corruption.
Spin lock can not used to fix this issue since mmc stack
read/write calls may for sleep.

Observed this issue with recently commited patch
"ath6kl: Claim sdio function only at appropriate places"
861dd058

kvalo: change name of mutex to more descriptive and add a comment
about what it protects
Signed-off-by: default avatarRaja Mani <rmani@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 743b4518
...@@ -39,8 +39,12 @@ struct ath6kl_sdio { ...@@ -39,8 +39,12 @@ struct ath6kl_sdio {
struct bus_request bus_req[BUS_REQUEST_MAX_NUM]; struct bus_request bus_req[BUS_REQUEST_MAX_NUM];
struct ath6kl *ar; struct ath6kl *ar;
u8 *dma_buffer; u8 *dma_buffer;
/* protects access to dma_buffer */
struct mutex dma_buffer_mutex;
/* scatter request list head */ /* scatter request list head */
struct list_head scat_req; struct list_head scat_req;
...@@ -395,6 +399,7 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, ...@@ -395,6 +399,7 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
if (buf_needs_bounce(buf)) { if (buf_needs_bounce(buf)) {
if (!ar_sdio->dma_buffer) if (!ar_sdio->dma_buffer)
return -ENOMEM; return -ENOMEM;
mutex_lock(&ar_sdio->dma_buffer_mutex);
tbuf = ar_sdio->dma_buffer; tbuf = ar_sdio->dma_buffer;
memcpy(tbuf, buf, len); memcpy(tbuf, buf, len);
bounced = true; bounced = true;
...@@ -405,6 +410,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, ...@@ -405,6 +410,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
if ((request & HIF_READ) && bounced) if ((request & HIF_READ) && bounced)
memcpy(buf, tbuf, len); memcpy(buf, tbuf, len);
if (bounced)
mutex_unlock(&ar_sdio->dma_buffer_mutex);
return ret; return ret;
} }
...@@ -1219,6 +1227,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, ...@@ -1219,6 +1227,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
spin_lock_init(&ar_sdio->lock); spin_lock_init(&ar_sdio->lock);
spin_lock_init(&ar_sdio->scat_lock); spin_lock_init(&ar_sdio->scat_lock);
spin_lock_init(&ar_sdio->wr_async_lock); spin_lock_init(&ar_sdio->wr_async_lock);
mutex_init(&ar_sdio->dma_buffer_mutex);
INIT_LIST_HEAD(&ar_sdio->scat_req); INIT_LIST_HEAD(&ar_sdio->scat_req);
INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment