76 lines
2.6 KiB
Diff
76 lines
2.6 KiB
Diff
|
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)
|