Commit 216647e6 authored by Wright Feng's avatar Wright Feng Committed by Kalle Valo

brcmfmac: fix firmware trap while dumping obss stats

When doing dump_survey, host will call "dump_obss" iovar to firmware
side. Host need to make sure the HW clock in dongle is on, or there is
high probability that firmware gets trap because register or shared
memory access failed. To fix this, we disable mpc when doing dump obss
and set it back after that.

[28350.512799] brcmfmac: brcmf_dump_obss: dump_obss error (-52)
[28743.402314] ieee80211 phy0: brcmf_fw_crashed: Firmware has halted or
crashed
[28745.869430] brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout
[28745.877546] brcmfmac: brcmf_sdio_checkdied: firmware trap in dongle
Signed-off-by: default avatarWright Feng <wright.feng@cypress.com>
Signed-off-by: default avatarChi-hsien Lin <chi-hsien.lin@infineon.com>
Signed-off-by: default avatarIan Lin <ian.lin@infineon.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220929012527.4152-3-ian.lin@infineon.com
parent 6c04deae
...@@ -7635,16 +7635,15 @@ brcmf_dump_obss(struct brcmf_if *ifp, struct cca_msrmnt_query req, ...@@ -7635,16 +7635,15 @@ brcmf_dump_obss(struct brcmf_if *ifp, struct cca_msrmnt_query req,
int err; int err;
buf = kzalloc(sizeof(char) * BRCMF_DCMD_MEDLEN, GFP_KERNEL); buf = kzalloc(sizeof(char) * BRCMF_DCMD_MEDLEN, GFP_KERNEL);
if (unlikely(!buf)) { if (!buf)
brcmf_err("%s: buf alloc failed\n", __func__);
return -ENOMEM; return -ENOMEM;
}
memcpy(buf, &req, sizeof(struct cca_msrmnt_query)); memcpy(buf, &req, sizeof(struct cca_msrmnt_query));
err = brcmf_fil_iovar_data_get(ifp, "dump_obss", err = brcmf_fil_iovar_data_get(ifp, "dump_obss",
buf, BRCMF_DCMD_MEDLEN); buf, BRCMF_DCMD_MEDLEN);
if (err < 0) { if (err) {
brcmf_err("dump_obss error (%d)\n", err); brcmf_err("dump_obss error (%d)\n", err);
err = -EINVAL;
goto exit; goto exit;
} }
results = (struct cca_stats_n_flags *)(buf); results = (struct cca_stats_n_flags *)(buf);
...@@ -7652,11 +7651,9 @@ brcmf_dump_obss(struct brcmf_if *ifp, struct cca_msrmnt_query req, ...@@ -7652,11 +7651,9 @@ brcmf_dump_obss(struct brcmf_if *ifp, struct cca_msrmnt_query req,
if (req.msrmnt_query) if (req.msrmnt_query)
brcmf_parse_dump_obss(results->buf, survey); brcmf_parse_dump_obss(results->buf, survey);
kfree(buf);
return 0;
exit: exit:
kfree(buf); kfree(buf);
return -EINVAL; return err;
} }
static s32 static s32
...@@ -7695,7 +7692,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, ...@@ -7695,7 +7692,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct cca_msrmnt_query req; struct cca_msrmnt_query req;
u32 val, noise; u32 noise;
int err; int err;
brcmf_dbg(TRACE, "Enter: channel idx=%d\n", idx); brcmf_dbg(TRACE, "Enter: channel idx=%d\n", idx);
...@@ -7721,23 +7718,20 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, ...@@ -7721,23 +7718,20 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
return 0; return 0;
} }
if (!idx) {
/* Disable mpc */ /* Disable mpc */
val = 0; brcmf_set_mpc(ifp, 0);
brcmf_set_mpc(ifp, val);
/* Set interface up, explicitly. */ /* Set interface up, explicitly. */
val = 1; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, val);
if (err) { if (err) {
brcmf_err("BRCMF_C_UP error (%d)\n", err); brcmf_err("set interface up failed, err = %d\n", err);
return -EIO; goto exit;
}
} }
/* Get noise value */ /* Get noise value */
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise); err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise);
if (err) { if (err) {
brcmf_err("Get Phy Noise failed, error = %d\n", err); brcmf_err("Get Phy Noise failed, use dummy value\n");
noise = CHAN_NOISE_DUMMY; noise = CHAN_NOISE_DUMMY;
} }
...@@ -7754,7 +7748,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, ...@@ -7754,7 +7748,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
/* Issue IOVAR to collect measurement results */ /* Issue IOVAR to collect measurement results */
req.msrmnt_query = 1; req.msrmnt_query = 1;
err = brcmf_dump_obss(ifp, req, &survey); err = brcmf_dump_obss(ifp, req, &survey);
if (err < 0) if (err)
goto exit; goto exit;
info->channel = chan; info->channel = chan;
...@@ -7775,6 +7769,8 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, ...@@ -7775,6 +7769,8 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
info->noise, info->time_busy, info->time_rx, info->time_tx); info->noise, info->time_busy, info->time_rx, info->time_tx);
exit: exit:
if (!brcmf_is_apmode(ifp->vif))
brcmf_set_mpc(ifp, 1);
return err; return err;
} }
......
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