Skip to content

Commit 6cd536f

Browse files
committed
cfg80211: change internal management frame registration API
Almost all drivers below cfg80211 get the API wrong (except for cfg80211) and are unable to cope with multiple registrations for the same frame type, which is valid due to the match filter. This seems to indicate the API is wrong, and we should maintain the full information in cfg80211 instead of the drivers. Change the API to no longer inform the driver about individual registrations and unregistrations, but rather every time about the entire state of the entire wiphy and single wdev, whenever it may have changed. This also simplifies the code in cfg80211 as it no longer has to track exactly what was unregistered and can free things immediately. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com> Reviewed-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> Link: https://lore.kernel.org/r/20200417124300.f47f3828afc8.I7f81ef59c2c5a340d7075fb3c6d0e08e8aeffe07@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 9eaf183 commit 6cd536f

File tree

13 files changed

+159
-178
lines changed

13 files changed

+159
-178
lines changed

drivers/net/wireless/ath/ath6kl/cfg80211.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3249,22 +3249,19 @@ static int ath6kl_get_antenna(struct wiphy *wiphy,
32493249
return 0;
32503250
}
32513251

3252-
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
3253-
struct wireless_dev *wdev,
3254-
u16 frame_type, bool reg)
3252+
static void ath6kl_update_mgmt_frame_registrations(struct wiphy *wiphy,
3253+
struct wireless_dev *wdev,
3254+
struct mgmt_frame_regs *upd)
32553255
{
32563256
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
32573257

3258-
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
3259-
__func__, frame_type, reg);
3260-
if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
3261-
/*
3262-
* Note: This notification callback is not allowed to sleep, so
3263-
* we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
3264-
* hardcode target to report Probe Request frames all the time.
3265-
*/
3266-
vif->probe_req_report = reg;
3267-
}
3258+
/*
3259+
* FIXME: send WMI_PROBE_REQ_REPORT_CMD here instead of hardcoding
3260+
* the reporting in the target all the time, this callback
3261+
* *is* allowed to sleep after all.
3262+
*/
3263+
vif->probe_req_report =
3264+
upd->interface_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
32683265
}
32693266

32703267
static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
@@ -3464,7 +3461,8 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
34643461
.remain_on_channel = ath6kl_remain_on_channel,
34653462
.cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
34663463
.mgmt_tx = ath6kl_mgmt_tx,
3467-
.mgmt_frame_register = ath6kl_mgmt_frame_register,
3464+
.update_mgmt_frame_registrations =
3465+
ath6kl_update_mgmt_frame_registrations,
34683466
.get_antenna = ath6kl_get_antenna,
34693467
.sched_scan_start = ath6kl_cfg80211_sscan_start,
34703468
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4979,21 +4979,15 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
49794979
}
49804980

49814981
static void
4982-
brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
4983-
struct wireless_dev *wdev,
4984-
u16 frame_type, bool reg)
4982+
brcmf_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
4983+
struct wireless_dev *wdev,
4984+
struct mgmt_frame_regs *upd)
49854985
{
49864986
struct brcmf_cfg80211_vif *vif;
4987-
u16 mgmt_type;
49884987

4989-
brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
4990-
4991-
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
49924988
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
4993-
if (reg)
4994-
vif->mgmt_rx_reg |= BIT(mgmt_type);
4995-
else
4996-
vif->mgmt_rx_reg &= ~BIT(mgmt_type);
4989+
4990+
vif->mgmt_rx_reg = upd->interface_stypes;
49974991
}
49984992

49994993

@@ -5408,7 +5402,8 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
54085402
.change_station = brcmf_cfg80211_change_station,
54095403
.sched_scan_start = brcmf_cfg80211_sched_scan_start,
54105404
.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
5411-
.mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
5405+
.update_mgmt_frame_registrations =
5406+
brcmf_cfg80211_update_mgmt_frame_registrations,
54125407
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
54135408
.remain_on_channel = brcmf_p2p_remain_on_channel,
54145409
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,

drivers/net/wireless/marvell/mwifiex/cfg80211.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,17 +269,12 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
269269
* CFG802.11 operation handler to register a mgmt frame.
270270
*/
271271
static void
272-
mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
273-
struct wireless_dev *wdev,
274-
u16 frame_type, bool reg)
272+
mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
273+
struct wireless_dev *wdev,
274+
struct mgmt_frame_regs *upd)
275275
{
276276
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
277-
u32 mask;
278-
279-
if (reg)
280-
mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
281-
else
282-
mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
277+
u32 mask = upd->interface_stypes;
283278

284279
if (mask != priv->mgmt_frame_mask) {
285280
priv->mgmt_frame_mask = mask;
@@ -4189,7 +4184,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
41894184
.del_key = mwifiex_cfg80211_del_key,
41904185
.set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,
41914186
.mgmt_tx = mwifiex_cfg80211_mgmt_tx,
4192-
.mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
4187+
.update_mgmt_frame_registrations =
4188+
mwifiex_cfg80211_update_mgmt_frame_registrations,
41934189
.remain_on_channel = mwifiex_cfg80211_remain_on_channel,
41944190
.cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
41954191
.set_default_key = mwifiex_cfg80211_set_default_key,

drivers/net/wireless/quantenna/qtnfmac/cfg80211.c

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -389,55 +389,57 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed)
389389
}
390390

391391
static void
392-
qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
393-
u16 frame_type, bool reg)
392+
qtnf_update_mgmt_frame_registrations(struct wiphy *wiphy,
393+
struct wireless_dev *wdev,
394+
struct mgmt_frame_regs *upd)
394395
{
395396
struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
396-
u16 mgmt_type;
397-
u16 new_mask;
398-
u16 qlink_frame_type = 0;
397+
u16 new_mask = upd->interface_stypes;
398+
u16 old_mask = vif->mgmt_frames_bitmask;
399+
static const struct {
400+
u16 mask, qlink_type;
401+
} updates[] = {
402+
{
403+
.mask = BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
404+
BIT(IEEE80211_STYPE_ASSOC_REQ >> 4),
405+
.qlink_type = QLINK_MGMT_FRAME_ASSOC_REQ,
406+
},
407+
{
408+
.mask = BIT(IEEE80211_STYPE_AUTH >> 4),
409+
.qlink_type = QLINK_MGMT_FRAME_AUTH,
410+
},
411+
{
412+
.mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
413+
.qlink_type = QLINK_MGMT_FRAME_PROBE_REQ,
414+
},
415+
{
416+
.mask = BIT(IEEE80211_STYPE_ACTION >> 4),
417+
.qlink_type = QLINK_MGMT_FRAME_ACTION,
418+
},
419+
};
420+
unsigned int i;
399421

400-
mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
422+
if (new_mask == old_mask)
423+
return;
401424

402-
if (reg)
403-
new_mask = vif->mgmt_frames_bitmask | BIT(mgmt_type);
404-
else
405-
new_mask = vif->mgmt_frames_bitmask & ~BIT(mgmt_type);
425+
for (i = 0; i < ARRAY_SIZE(updates); i++) {
426+
u16 mask = updates[i].mask;
427+
u16 qlink_frame_type = updates[i].qlink_type;
428+
bool reg;
406429

407-
if (new_mask == vif->mgmt_frames_bitmask)
408-
return;
430+
/* the ! are here due to the assoc/reassoc merge */
431+
if (!(new_mask & mask) == !(old_mask & mask))
432+
continue;
409433

410-
switch (frame_type & IEEE80211_FCTL_STYPE) {
411-
case IEEE80211_STYPE_REASSOC_REQ:
412-
case IEEE80211_STYPE_ASSOC_REQ:
413-
qlink_frame_type = QLINK_MGMT_FRAME_ASSOC_REQ;
414-
break;
415-
case IEEE80211_STYPE_AUTH:
416-
qlink_frame_type = QLINK_MGMT_FRAME_AUTH;
417-
break;
418-
case IEEE80211_STYPE_PROBE_REQ:
419-
qlink_frame_type = QLINK_MGMT_FRAME_PROBE_REQ;
420-
break;
421-
case IEEE80211_STYPE_ACTION:
422-
qlink_frame_type = QLINK_MGMT_FRAME_ACTION;
423-
break;
424-
default:
425-
pr_warn("VIF%u.%u: unsupported frame type: %X\n",
426-
vif->mac->macid, vif->vifid,
427-
(frame_type & IEEE80211_FCTL_STYPE) >> 4);
428-
return;
429-
}
434+
reg = new_mask & mask;
430435

431-
if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg)) {
432-
pr_warn("VIF%u.%u: failed to %sregister mgmt frame type 0x%x\n",
433-
vif->mac->macid, vif->vifid, reg ? "" : "un",
434-
frame_type);
435-
return;
436+
if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg))
437+
pr_warn("VIF%u.%u: failed to %sregister qlink frame type 0x%x\n",
438+
vif->mac->macid, vif->vifid, reg ? "" : "un",
439+
qlink_frame_type);
436440
}
437441

438442
vif->mgmt_frames_bitmask = new_mask;
439-
pr_debug("VIF%u.%u: %sregistered mgmt frame type 0x%x\n",
440-
vif->mac->macid, vif->vifid, reg ? "" : "un", frame_type);
441443
}
442444

443445
static int
@@ -1017,7 +1019,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
10171019
.change_beacon = qtnf_change_beacon,
10181020
.stop_ap = qtnf_stop_ap,
10191021
.set_wiphy_params = qtnf_set_wiphy_params,
1020-
.mgmt_frame_register = qtnf_mgmt_frame_register,
1022+
.update_mgmt_frame_registrations =
1023+
qtnf_update_mgmt_frame_registrations,
10211024
.mgmt_tx = qtnf_mgmt_tx,
10221025
.change_station = qtnf_change_station,
10231026
.del_station = qtnf_del_station,

include/net/cfg80211.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3384,6 +3384,17 @@ struct cfg80211_update_owe_info {
33843384
size_t ie_len;
33853385
};
33863386

3387+
/**
3388+
* struct mgmt_frame_regs - management frame registrations data
3389+
* @global_stypes: bitmap of management frame subtypes registered
3390+
* for the entire device
3391+
* @interface_stypes: bitmap of management frame subtypes registered
3392+
* for the given interface
3393+
*/
3394+
struct mgmt_frame_regs {
3395+
u32 global_stypes, interface_stypes;
3396+
};
3397+
33873398
/**
33883399
* struct cfg80211_ops - backend description for wireless configuration
33893400
*
@@ -3608,8 +3619,8 @@ struct cfg80211_update_owe_info {
36083619
* The driver should not call cfg80211_sched_scan_stopped() for a requested
36093620
* stop (when this method returns 0).
36103621
*
3611-
* @mgmt_frame_register: Notify driver that a management frame type was
3612-
* registered. The callback is allowed to sleep.
3622+
* @update_mgmt_frame_registrations: Notify the driver that management frame
3623+
* registrations were updated. The callback is allowed to sleep.
36133624
*
36143625
* @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
36153626
* Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
@@ -3932,9 +3943,9 @@ struct cfg80211_ops {
39323943
struct net_device *dev,
39333944
u32 rate, u32 pkts, u32 intvl);
39343945

3935-
void (*mgmt_frame_register)(struct wiphy *wiphy,
3936-
struct wireless_dev *wdev,
3937-
u16 frame_type, bool reg);
3946+
void (*update_mgmt_frame_registrations)(struct wiphy *wiphy,
3947+
struct wireless_dev *wdev,
3948+
struct mgmt_frame_regs *upd);
39383949

39393950
int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
39403951
int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
@@ -5015,6 +5026,7 @@ struct cfg80211_cqm_config;
50155026
* by cfg80211 on change_interface
50165027
* @mgmt_registrations: list of registrations for management frames
50175028
* @mgmt_registrations_lock: lock for the list
5029+
* @mgmt_registrations_update_wk: update work to defer from atomic context
50185030
* @mtx: mutex used to lock data in this struct, may be used by drivers
50195031
* and some API functions require it held
50205032
* @beacon_interval: beacon interval used on this device for transmitting
@@ -5060,6 +5072,7 @@ struct wireless_dev {
50605072

50615073
struct list_head mgmt_registrations;
50625074
spinlock_t mgmt_registrations_lock;
5075+
struct work_struct mgmt_registrations_update_wk;
50635076

50645077
struct mutex mtx;
50655078

include/net/mac80211.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,7 @@ struct ieee80211_vif {
16471647
struct dentry *debugfs_dir;
16481648
#endif
16491649

1650-
unsigned int probe_req_reg;
1650+
bool probe_req_reg;
16511651

16521652
bool txqs_stopped[IEEE80211_NUM_ACS];
16531653

net/mac80211/cfg.c

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,44 +3398,35 @@ int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb,
33983398
return 0;
33993399
}
34003400

3401-
static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
3401+
static void
3402+
ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
34023403
struct wireless_dev *wdev,
3403-
u16 frame_type, bool reg)
3404+
struct mgmt_frame_regs *upd)
34043405
{
34053406
struct ieee80211_local *local = wiphy_priv(wiphy);
34063407
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
3408+
u32 preq_mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
3409+
bool global_change, intf_change;
34073410

3408-
switch (frame_type) {
3409-
case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
3410-
if (reg) {
3411-
local->probe_req_reg++;
3412-
sdata->vif.probe_req_reg++;
3413-
} else {
3414-
if (local->probe_req_reg)
3415-
local->probe_req_reg--;
3411+
global_change =
3412+
local->probe_req_reg != !!(upd->global_stypes & preq_mask);
3413+
local->probe_req_reg = upd->global_stypes & preq_mask;
34163414

3417-
if (sdata->vif.probe_req_reg)
3418-
sdata->vif.probe_req_reg--;
3419-
}
3415+
intf_change = sdata->vif.probe_req_reg !=
3416+
!!(upd->interface_stypes & preq_mask);
3417+
sdata->vif.probe_req_reg = upd->interface_stypes & preq_mask;
34203418

3421-
if (!local->open_count)
3422-
break;
3419+
if (!local->open_count)
3420+
return;
34233421

3424-
if (ieee80211_sdata_running(sdata)) {
3425-
if (sdata->vif.probe_req_reg == 1)
3426-
drv_config_iface_filter(local, sdata,
3427-
FIF_PROBE_REQ,
3428-
FIF_PROBE_REQ);
3429-
else if (sdata->vif.probe_req_reg == 0)
3430-
drv_config_iface_filter(local, sdata, 0,
3431-
FIF_PROBE_REQ);
3432-
}
3422+
if (intf_change && ieee80211_sdata_running(sdata))
3423+
drv_config_iface_filter(local, sdata,
3424+
sdata->vif.probe_req_reg ?
3425+
FIF_PROBE_REQ : 0,
3426+
FIF_PROBE_REQ);
34333427

3428+
if (global_change)
34343429
ieee80211_configure_filter(local);
3435-
break;
3436-
default:
3437-
break;
3438-
}
34393430
}
34403431

34413432
static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
@@ -4020,7 +4011,8 @@ const struct cfg80211_ops mac80211_config_ops = {
40204011
.mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
40214012
.set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
40224013
.set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
4023-
.mgmt_frame_register = ieee80211_mgmt_frame_register,
4014+
.update_mgmt_frame_registrations =
4015+
ieee80211_update_mgmt_frame_registrations,
40244016
.set_antenna = ieee80211_set_antenna,
40254017
.get_antenna = ieee80211_get_antenna,
40264018
.set_rekey_data = ieee80211_set_rekey_data,

net/mac80211/ieee80211_i.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,7 @@ struct ieee80211_local {
11671167
/* number of interfaces with corresponding FIF_ flags */
11681168
int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
11691169
fif_probe_req;
1170-
int probe_req_reg;
1170+
bool probe_req_reg;
11711171
unsigned int filter_flags; /* FIF_* */
11721172

11731173
bool wiphy_ciphers_allocated;

0 commit comments

Comments
 (0)