b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> |
| 2 | Date: Thu, 9 Jul 2015 00:07:59 +0200 |
| 3 | Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state |
| 4 | MIME-Version: 1.0 |
| 5 | Content-Type: text/plain; charset=UTF-8 |
| 6 | Content-Transfer-Encoding: 8bit |
| 7 | |
| 8 | Signed-off-by: Rafał Miłecki <zajec5@gmail.com> |
| 9 | --- |
| 10 | |
| 11 | --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c |
| 12 | +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c |
| 13 | @@ -718,8 +718,36 @@ static struct wireless_dev *brcmf_cfg802 |
| 14 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 15 | struct brcmf_pub *drvr = cfg->pub; |
| 16 | struct wireless_dev *wdev; |
| 17 | + struct net_device *dev; |
| 18 | int err; |
| 19 | |
| 20 | + /* |
| 21 | + * There is a bug with in-firmware BSS management. When adding virtual |
| 22 | + * interface brcmfmac first tells firmware to create new BSS and then |
| 23 | + * it creates new struct net_device. |
| 24 | + * |
| 25 | + * If creating/registering netdev(ice) fails, BSS remains in some bugged |
| 26 | + * state. It conflicts with existing BSSes by overtaking their auth |
| 27 | + * requests. |
| 28 | + * |
| 29 | + * It results in one BSS (addresss X) sending beacons and another BSS |
| 30 | + * (address Y) replying to authentication requests. This makes interface |
| 31 | + * unusable as AP. |
| 32 | + * |
| 33 | + * To workaround this bug we may try to guess if register_netdev(ice) |
| 34 | + * will fail. The most obvious case is using interface name that already |
| 35 | + * exists. This is actually quite likely with brcmfmac & some user space |
| 36 | + * scripts as brcmfmac doesn't allow deleting virtual interfaces. |
| 37 | + * So this bug can be triggered even by something trivial like: |
| 38 | + * iw dev wlan0 delete |
| 39 | + * iw phy phy0 interface add wlan0 type __ap |
| 40 | + */ |
| 41 | + dev = dev_get_by_name(&init_net, name); |
| 42 | + if (dev) { |
| 43 | + dev_put(dev); |
| 44 | + return ERR_PTR(-ENFILE); |
| 45 | + } |
| 46 | + |
| 47 | brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); |
| 48 | err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); |
| 49 | if (err) { |