123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
- Date: Wed, 29 Jun 2016 21:54:26 +0200
- Subject: [PATCH] brcmfmac: delete interface directly in code that sent fw
- request
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- So far when receiving event about in-firmware-interface removal our
- event worker was notifying listener and afterwards it was removing Linux
- interface.
- First of all it was resulting in slightly unexpected order. The listener
- (del_virtual_intf callback) was (usually) returning with success before
- we even called unregister_netdev(ice).
- Please note this couldn't be simply fixed by changing order of calls in
- brcmf_fweh_handle_if_event as unregistering interface earlier could free
- struct brcmf_if.
- Another problem of current implementation are possible lockups. Focus on
- the time slot between calling event handler and removing Linux
- interface. During that time original caller may leave (unlocking rtnl
- semaphore) *and* another call to the same code may be done (locking it
- again). If that happens our event handler will stuck at removing Linux
- interface, it won't handle another event and will block process holding
- rtnl lock.
- This can be simply solved by unregistering interface in a proper
- callback, right after receiving confirmation event from firmware. This
- only required modifying worker to don't unregister on its own if there
- is someone waiting for the event.
- Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
- Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
- ---
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
- @@ -18,6 +18,7 @@
- #include "brcmu_wifi.h"
- #include "brcmu_utils.h"
-
- +#include "cfg80211.h"
- #include "core.h"
- #include "debug.h"
- #include "tracepoint.h"
- @@ -182,8 +183,13 @@ static void brcmf_fweh_handle_if_event(s
-
- err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
-
- - if (ifp && ifevent->action == BRCMF_E_IF_DEL)
- - brcmf_remove_interface(ifp, false);
- + if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
- + bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);
- +
- + /* Default handling in case no-one waits for this event */
- + if (!armed)
- + brcmf_remove_interface(ifp, false);
- + }
- }
-
- /**
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
- @@ -2290,8 +2290,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
- else
- err = 0;
- }
- - if (err)
- - brcmf_remove_interface(vif->ifp, true);
- + brcmf_remove_interface(vif->ifp, true);
-
- brcmf_cfg80211_arm_vif_event(cfg, NULL);
- if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
|