Commit a2044d91 authored by Hante Meuleman's avatar Hante Meuleman Committed by Kalle Valo

brcmfmac: Fix race condition bug when deleting p2p interface.

When p2p device interface gets deleted by deinitialising discovery
it will result in an event which removes the interface, but that is
also done by delete p2p interface code. This results in race
condition which sometimes results in lockup/crash. With this patch
the delete device interface will wait for the event (with timeout)
removing the possible race condition. Also on the stop device call
from cfg80211 the deinitialisation of the discovery device should
be avoided as it can result in a similar situation.
Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 8268c201
...@@ -2241,6 +2241,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2241,6 +2241,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
brcmf_dbg(TRACE, "delete P2P vif\n"); brcmf_dbg(TRACE, "delete P2P vif\n");
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
brcmf_cfg80211_arm_vif_event(cfg, vif);
switch (vif->wdev.iftype) { switch (vif->wdev.iftype) {
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state)) if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
...@@ -2257,8 +2258,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2257,8 +2258,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
return 0; return 0;
brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_cancel_remain_on_channel(vif->ifp);
brcmf_p2p_deinit_discovery(p2p); brcmf_p2p_deinit_discovery(p2p);
brcmf_remove_interface(vif->ifp);
return 0;
default: default:
return -ENOTSUPP; return -ENOTSUPP;
} }
...@@ -2270,10 +2269,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2270,10 +2269,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
wait_for_completion_timeout(&cfg->vif_disabled, wait_for_completion_timeout(&cfg->vif_disabled,
msecs_to_jiffies(500)); msecs_to_jiffies(500));
brcmf_vif_clear_mgmt_ies(vif); err = 0;
if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) {
brcmf_cfg80211_arm_vif_event(cfg, vif); brcmf_vif_clear_mgmt_ies(vif);
err = brcmf_p2p_release_p2p_if(vif); err = brcmf_p2p_release_p2p_if(vif);
}
if (!err) { if (!err) {
/* wait for firmware event */ /* wait for firmware event */
err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL, err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
...@@ -2283,8 +2283,12 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2283,8 +2283,12 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
else else
err = 0; err = 0;
} }
if (err)
brcmf_remove_interface(vif->ifp);
brcmf_cfg80211_arm_vif_event(cfg, NULL); brcmf_cfg80211_arm_vif_event(cfg, NULL);
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
return err; return err;
} }
...@@ -2333,7 +2337,9 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2333,7 +2337,9 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
*/ */
if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) { if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) {
mutex_lock(&cfg->usr_sync); mutex_lock(&cfg->usr_sync);
(void)brcmf_p2p_deinit_discovery(p2p); /* Set the discovery state to SCAN */
(void)brcmf_p2p_set_discover_state(vif->ifp,
WL_P2P_DISC_ST_SCAN, 0, 0);
brcmf_abort_scanning(cfg); brcmf_abort_scanning(cfg);
clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
mutex_unlock(&cfg->usr_sync); mutex_unlock(&cfg->usr_sync);
......
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