summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
diff options
context:
space:
mode:
authorArend Van Spriel <arend.vanspriel@broadcom.com>2017-06-09 13:19:21 +0200
committerKalle Valo <kvalo@codeaurora.org>2017-06-13 08:57:50 +0200
commit42596f761449595e3f0f18ce57c88472ad2d6160 (patch)
tree36b70e786fe2d03fb1d029bff8d3d1a457b79897 /drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
parentbrcmfmac: add support multi-scheduled scan (diff)
downloadlinux-42596f761449595e3f0f18ce57c88472ad2d6160.tar.xz
linux-42596f761449595e3f0f18ce57c88472ad2d6160.zip
brcmfmac: add mutex to protect pno requests
The request references kept in pno are accessed in user-space context and in firmware event handler context. As such we need to protect it with a lock. As both context allow sleep a mutex seems appropriate. Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com> Reviewed-by: Franky Lin <franky.lin@broadcom.com> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c')
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
index a4207754075b..e488bebd01e1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -43,6 +43,7 @@
struct brcmf_pno_info {
int n_reqs;
struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS];
+ struct mutex req_lock;
};
#define ifp_to_pno(_ifp) ((_ifp)->drvr->config->pno)
@@ -55,13 +56,17 @@ static int brcmf_pno_store_request(struct brcmf_pno_info *pi,
return -ENOSPC;
brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid);
+ mutex_lock(&pi->req_lock);
pi->reqs[pi->n_reqs++] = req;
+ mutex_unlock(&pi->req_lock);
return 0;
}
static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
{
- int i;
+ int i, err = 0;
+
+ mutex_lock(&pi->req_lock);
/* find request */
for (i = 0; i < pi->n_reqs; i++) {
@@ -70,7 +75,8 @@ static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
}
/* request not found */
if (WARN(i == pi->n_reqs, "reqid not found\n")) {
- return -ENOENT;
+ err = -ENOENT;
+ goto done;
}
brcmf_dbg(SCAN, "reqid=%llu\n", reqid);
@@ -78,14 +84,17 @@ static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
/* if last we are done */
if (!pi->n_reqs || i == pi->n_reqs)
- return 0;
+ goto done;
/* fill the gap with remaining requests */
while (i <= pi->n_reqs - 1) {
pi->reqs[i] = pi->reqs[i + 1];
i++;
}
- return 0;
+
+done:
+ mutex_unlock(&pi->req_lock);
+ return err;
}
static int brcmf_pno_channel_config(struct brcmf_if *ifp,
@@ -488,6 +497,7 @@ int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg)
return -ENOMEM;
cfg->pno = pi;
+ mutex_init(&pi->req_lock);
return 0;
}
@@ -500,6 +510,7 @@ void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg)
cfg->pno = NULL;
WARN_ON(pi->n_reqs);
+ mutex_destroy(&pi->req_lock);
kfree(pi);
}
@@ -515,11 +526,15 @@ void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket)
{
- /* bucket appears to be gone */
- if (bucket >= pi->n_reqs)
- return 0;
+ u64 reqid = 0;
+
+ mutex_lock(&pi->req_lock);
+
+ if (bucket < pi->n_reqs)
+ reqid = pi->reqs[bucket]->reqid;
- return pi->reqs[bucket]->reqid;
+ mutex_unlock(&pi->req_lock);
+ return reqid;
}
u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
@@ -530,6 +545,7 @@ u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
u32 bucket_map = 0;
int i, j;
+ mutex_lock(&pi->req_lock);
for (i = 0; i < pi->n_reqs; i++) {
req = pi->reqs[i];
@@ -544,5 +560,6 @@ u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
}
}
}
+ mutex_unlock(&pi->req_lock);
return bucket_map;
}