summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei-Ning Huang <wnhuang@chromium.org>2016-05-19 03:53:43 (GMT)
committerKalle Valo <kvalo@codeaurora.org>2016-06-14 14:24:16 (GMT)
commit65c71efe1c59c111a7b9e6d9540f111663b975b2 (patch)
treece8c7ded4ae371d1cd6c545c5d64df3423b43688
parent6b128a01c67301a4733138f94ca581c706277ef5 (diff)
downloadlinux-65c71efe1c59c111a7b9e6d9540f111663b975b2.tar.xz
mwifiex: fix racing condition when downloading firmware
The action 'check for winner' and 'download firmware' should be an atomic action. This is true for btmrvl driver but not mwmfiex, which cause firmware download to fail when the following senerio happens: 1) mwifiex check winner status: true 2) btmrvl check winner status: true, and start downloading firmware 3) mwfieix tries to download firmware, but failed because btmrvl is already downloading. This won't happen if 1) and 3) is an atomic action. This patch adds sdio_claim/release_host call around those two actions to make sure it's atomic. Signed-off-by: Wei-Ning Huang <wnhuang@chromium.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 8b67a55..2b65334 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -21,6 +21,7 @@
#include "wmm.h"
#include "cfg80211.h"
#include "11n.h"
+#include "sdio.h"
#define VERSION "1.0"
@@ -514,6 +515,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
struct semaphore *sem = adapter->card_sem;
bool init_failed = false;
struct wireless_dev *wdev;
+ struct sdio_mmc_card *card = adapter->card;
if (!firmware) {
mwifiex_dbg(adapter, ERROR,
@@ -526,10 +528,16 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
fw.fw_buf = (u8 *) adapter->firmware->data;
fw.fw_len = adapter->firmware->size;
- if (adapter->if_ops.dnld_fw)
+ if (adapter->if_ops.dnld_fw) {
ret = adapter->if_ops.dnld_fw(adapter, &fw);
- else
+ } else {
+ if (adapter->iface_type == MWIFIEX_SDIO)
+ sdio_claim_host(card->func);
ret = mwifiex_dnld_fw(adapter, &fw);
+ if (adapter->iface_type == MWIFIEX_SDIO)
+ sdio_release_host(card->func);
+ }
+
if (ret == -1)
goto err_dnld_fw;