History

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.

Johannes Berg committed 6 years ago

Commit 6cd536f1 parent 9eaf18313 files · +159 −178Browse files

Unified · Split

13 files
  1. drivers/net/wireless/ath/ath6kl/cfg80211.c +12 −14
  2. drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +7 −12
  3. drivers/net/wireless/marvell/mwifiex/cfg80211.c +6 −10
  4. drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +43 −40
  5. include/net/cfg80211.h +18 −5
  6. include/net/mac80211.h +1 −1
  7. net/mac80211/cfg.c +21 −29
  8. net/mac80211/ieee80211_i.h +1 −1
  9. net/wireless/core.c +3 −4
  10. net/wireless/core.h +1 −5
  11. net/wireless/mlme.c +29 −43
  12. net/wireless/rdev-ops.h +7 −4
  13. net/wireless/trace.h +10 −10
drivers/net/wireless/ath/ath6kl/cfg80211.c+12−14
@@ -3249,22 +3249,19 @@ static int ath6kl_get_antenna(struct wiphy *wiphy, · 3248 unmodified lines
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 = { · 193 unmodified lines
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+7−12
@@ -4979,21 +4979,15 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, · 4978 unmodified lines
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 = { · 408 unmodified lines
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+6−10
@@ -269,17 +269,12 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, · 268 unmodified lines
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 = { · 3903 unmodified lines
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+43−40
@@ -389,55 +389,57 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed) · 388 unmodified lines
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 = { · 573 unmodified lines
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+18−5
@@ -3384,6 +3384,17 @@ struct cfg80211_update_owe_info { · 3383 unmodified lines
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 { · 218 unmodified lines
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 { · 316 unmodified lines
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; · 1074 unmodified lines
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 { · 39 unmodified lines
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+1−1
@@ -1647,7 +1647,7 @@ struct ieee80211_vif { · 1646 unmodified lines
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+21−29
@@ -3398,44 +3398,35 @@ int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb, · 3397 unmodified lines
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 = { · 578 unmodified lines
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+1−1
@@ -1167,7 +1167,7 @@ struct ieee80211_local { · 1166 unmodified lines
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;
net/wireless/core.c+3−4
@@ -480,9 +480,6 @@ use_default_name: · 479 unmodified lines
480480 INIT_LIST_HEAD(&rdev->bss_list);
481481 INIT_LIST_HEAD(&rdev->sched_scan_req_list);
482482 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
483− INIT_LIST_HEAD(&rdev->mlme_unreg);
484− spin_lock_init(&rdev->mlme_unreg_lock);
485− INIT_WORK(&rdev->mlme_unreg_wk, cfg80211_mlme_unreg_wk);
486483 INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
487484 cfg80211_dfs_channels_update_work);
488485 #ifdef CONFIG_CFG80211_WEXT
@@ -1030,7 +1027,6 @@ void wiphy_unregister(struct wiphy *wiphy) · 541 unmodified lines
10301027 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
10311028 flush_work(&rdev->destroy_work);
10321029 flush_work(&rdev->sched_scan_stop_wk);
1033− flush_work(&rdev->mlme_unreg_wk);
10341030 flush_work(&rdev->propagate_radar_detect_wk);
10351031 flush_work(&rdev->propagate_cac_done_wk);
10361032
@@ -1094,6 +1090,7 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync) · 57 unmodified lines
10941090 rdev->devlist_generation++;
10951091
10961092 cfg80211_mlme_purge_registrations(wdev);
1093+ flush_work(&wdev->mgmt_registrations_update_wk);
10971094
10981095 switch (wdev->iftype) {
10991096 case NL80211_IFTYPE_P2P_DEVICE:
@@ -1238,6 +1235,8 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, · 138 unmodified lines
12381235 spin_lock_init(&wdev->event_lock);
12391236 INIT_LIST_HEAD(&wdev->mgmt_registrations);
12401237 spin_lock_init(&wdev->mgmt_registrations_lock);
1238+ INIT_WORK(&wdev->mgmt_registrations_update_wk,
1239+ cfg80211_mgmt_registrations_update_wk);
12411240 INIT_LIST_HEAD(&wdev->pmsr_list);
12421241 spin_lock_init(&wdev->pmsr_lock);
12431242 INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
net/wireless/core.h+1−5
@@ -60,10 +60,6 @@ struct cfg80211_registered_device { · 59 unmodified lines
6060 struct list_head beacon_registrations;
6161 spinlock_t beacon_registrations_lock;
6262
63− struct list_head mlme_unreg;
64− spinlock_t mlme_unreg_lock;
65− struct work_struct mlme_unreg_wk;
66−
6763 /* protected by RTNL only */
6864 int num_running_ifaces;
6965 int num_running_monitor_ifaces;
@@ -386,7 +382,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, · 316 unmodified lines
386382 int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
387383 u16 frame_type, const u8 *match_data,
388384 int match_len, struct netlink_ext_ack *extack);
389−void cfg80211_mlme_unreg_wk(struct work_struct *wk);
385+void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk);
390386 void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
391387 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
392388 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
net/wireless/mlme.c+29−43
@@ -429,43 +429,37 @@ struct cfg80211_mgmt_registration { · 428 unmodified lines
429429 u8 match[];
430430 };
431431
432−static void
433−cfg80211_process_mlme_unregistrations(struct cfg80211_registered_device *rdev)
432+static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
434433 {
434+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
435+ struct wireless_dev *tmp;
435436 struct cfg80211_mgmt_registration *reg;
437+ struct mgmt_frame_regs upd = {};
436438
437439 ASSERT_RTNL();
438440
439− spin_lock_bh(&rdev->mlme_unreg_lock);
440− while ((reg = list_first_entry_or_null(&rdev->mlme_unreg,
441− struct cfg80211_mgmt_registration,
442− list))) {
443− list_del(&reg->list);
444− spin_unlock_bh(&rdev->mlme_unreg_lock);
445−
446− if (rdev->ops->mgmt_frame_register) {
447− u16 frame_type = le16_to_cpu(reg->frame_type);
441+ rcu_read_lock();
442+ list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
443+ list_for_each_entry_rcu(reg, &tmp->mgmt_registrations, list) {
444+ u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
448445
449− rdev_mgmt_frame_register(rdev, reg->wdev,
450− frame_type, false);
446+ upd.global_stypes |= mask;
447+ if (tmp == wdev)
448+ upd.interface_stypes |= mask;
451449 }
452−
453− kfree(reg);
454−
455− spin_lock_bh(&rdev->mlme_unreg_lock);
456450 }
457− spin_unlock_bh(&rdev->mlme_unreg_lock);
451+ rcu_read_unlock();
452+
453+ rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
458454 }
459455
460−void cfg80211_mlme_unreg_wk(struct work_struct *wk)
456+void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
461457 {
462− struct cfg80211_registered_device *rdev;
463−
464− rdev = container_of(wk, struct cfg80211_registered_device,
465− mlme_unreg_wk);
458+ struct wireless_dev *wdev = container_of(wk, struct wireless_dev,
459+ mgmt_registrations_update_wk);
466460
467461 rtnl_lock();
468− cfg80211_process_mlme_unregistrations(rdev);
462+ cfg80211_mgmt_registrations_update(wdev);
469463 rtnl_unlock();
470464 }
471465
@@ -473,8 +467,6 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 1 unmodified line
473467 u16 frame_type, const u8 *match_data,
474468 int match_len, struct netlink_ext_ack *extack)
475469 {
476− struct wiphy *wiphy = wdev->wiphy;
477− struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
478470 struct cfg80211_mgmt_registration *reg, *nreg;
479471 int err = 0;
480472 u16 mgmt_type;
@@ -534,10 +526,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 53 unmodified lines
534526 }
535527 }
536528
537− if (err) {
538− kfree(nreg);
529+ if (err)
539530 goto out;
540− }
541531
542532 memcpy(nreg->match, match_data, match_len);
543533 nreg->match_len = match_len;
@@ -547,15 +537,12 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 3 unmodified lines
547537 list_add(&nreg->list, &wdev->mgmt_registrations);
548538 spin_unlock_bh(&wdev->mgmt_registrations_lock);
549539
550− /* process all unregistrations to avoid driver confusion */
551− cfg80211_process_mlme_unregistrations(rdev);
552−
553− if (rdev->ops->mgmt_frame_register)
554− rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
540+ cfg80211_mgmt_registrations_update(wdev);
555541
556542 return 0;
557543
558544 out:
545+ kfree(nreg);
559546 spin_unlock_bh(&wdev->mgmt_registrations_lock);
560547
561548 return err;
@@ -574,11 +561,9 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 12 unmodified lines
574561 continue;
575562
576563 list_del(&reg->list);
577− spin_lock(&rdev->mlme_unreg_lock);
578− list_add_tail(&reg->list, &rdev->mlme_unreg);
579− spin_unlock(&rdev->mlme_unreg_lock);
564+ kfree(reg);
580565
581− schedule_work(&rdev->mlme_unreg_wk);
566+ schedule_work(&wdev->mgmt_registrations_update_wk);
582567 }
583568
584569 spin_unlock_bh(&wdev->mgmt_registrations_lock);
@@ -594,15 +579,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 9 unmodified lines
594579
595580 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
596581 {
597− struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
582+ struct cfg80211_mgmt_registration *reg, *tmp;
598583
599584 spin_lock_bh(&wdev->mgmt_registrations_lock);
600− spin_lock(&rdev->mlme_unreg_lock);
601− list_splice_tail_init(&wdev->mgmt_registrations, &rdev->mlme_unreg);
602− spin_unlock(&rdev->mlme_unreg_lock);
585+ list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
586+ list_del(&reg->list);
587+ kfree(reg);
588+ }
603589 spin_unlock_bh(&wdev->mgmt_registrations_lock);
604590
605− cfg80211_process_mlme_unregistrations(rdev);
591+ cfg80211_mgmt_registrations_update(wdev);
606592 }
607593
608594 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
net/wireless/rdev-ops.h+7−4
@@ -819,13 +819,16 @@ rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev, · 818 unmodified lines
819819 }
820820
821821 static inline void
822−rdev_mgmt_frame_register(struct cfg80211_registered_device *rdev,
823− struct wireless_dev *wdev, u16 frame_type, bool reg)
822+rdev_update_mgmt_frame_registrations(struct cfg80211_registered_device *rdev,
823+ struct wireless_dev *wdev,
824+ struct mgmt_frame_regs *upd)
824825 {
825826 might_sleep();
826827
827− trace_rdev_mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
828− rdev->ops->mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);
828+ trace_rdev_update_mgmt_frame_registrations(&rdev->wiphy, wdev, upd);
829+ if (rdev->ops->update_mgmt_frame_registrations)
830+ rdev->ops->update_mgmt_frame_registrations(&rdev->wiphy, wdev,
831+ upd);
829832 trace_rdev_return_void(&rdev->wiphy);
830833 }
831834
net/wireless/trace.h+10−10
@@ -1582,25 +1582,25 @@ TRACE_EVENT(rdev_set_bitrate_mask, · 1581 unmodified lines
15821582 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
15831583 );
15841584
1585−TRACE_EVENT(rdev_mgmt_frame_register,
1585+TRACE_EVENT(rdev_update_mgmt_frame_registrations,
15861586 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
1587− u16 frame_type, bool reg),
1588− TP_ARGS(wiphy, wdev, frame_type, reg),
1587+ struct mgmt_frame_regs *upd),
1588+ TP_ARGS(wiphy, wdev, upd),
15891589 TP_STRUCT__entry(
15901590 WIPHY_ENTRY
15911591 WDEV_ENTRY
1592− __field(u16, frame_type)
1593− __field(bool, reg)
1592+ __field(u16, global_stypes)
1593+ __field(u16, interface_stypes)
15941594 ),
15951595 TP_fast_assign(
15961596 WIPHY_ASSIGN;
15971597 WDEV_ASSIGN;
1598− __entry->frame_type = frame_type;
1599− __entry->reg = reg;
1598+ __entry->global_stypes = upd->global_stypes;
1599+ __entry->interface_stypes = upd->interface_stypes;
16001600 ),
1601− TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ",
1602− WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,
1603− __entry->reg ? "true" : "false")
1601+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", global: 0x%.2x, intf: 0x%.2x",
1602+ WIPHY_PR_ARG, WDEV_PR_ARG,
1603+ __entry->global_stypes, __entry->interface_stypes)
16041604 );
16051605
16061606 TRACE_EVENT(rdev_return_int_tx_rx,