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
3249 return 0;3249 return 0;
3250}3250}
3251 3251
3252static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,3252static void ath6kl_update_mgmt_frame_registrations(struct wiphy *wiphy,
3253 struct wireless_dev *wdev,3253 struct wireless_dev *wdev,
3254 u16 frame_type, bool reg)3254 struct mgmt_frame_regs *upd)
3255{3255{
3256 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);3256 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
3257 3257
3258 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",3258 /*
3259 __func__, frame_type, reg);3259 * FIXME: send WMI_PROBE_REQ_REPORT_CMD here instead of hardcoding
3260 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {3260 * the reporting in the target all the time, this callback
3261 /*3261 * *is* allowed to sleep after all.
3262 * Note: This notification callback is not allowed to sleep, so3262 */
3263 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we3263 vif->probe_req_report =
3264 * hardcode target to report Probe Request frames all the time.3264 upd->interface_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
3265 */
3266 vif->probe_req_report = reg;
3267 }
3268}3265}
3269 3266
3270static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,3267static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
@@ -3464,7 +3461,8 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { · 193 unmodified lines
3464 .remain_on_channel = ath6kl_remain_on_channel,3461 .remain_on_channel = ath6kl_remain_on_channel,
3465 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,3462 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
3466 .mgmt_tx = ath6kl_mgmt_tx,3463 .mgmt_tx = ath6kl_mgmt_tx,
3467 .mgmt_frame_register = ath6kl_mgmt_frame_register,3464 .update_mgmt_frame_registrations =
3465 ath6kl_update_mgmt_frame_registrations,
3468 .get_antenna = ath6kl_get_antenna,3466 .get_antenna = ath6kl_get_antenna,
3469 .sched_scan_start = ath6kl_cfg80211_sscan_start,3467 .sched_scan_start = ath6kl_cfg80211_sscan_start,
3470 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,3468 .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
4979}4979}
4980 4980
4981static void4981static void
4982brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,4982brcmf_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
4983 struct wireless_dev *wdev,4983 struct wireless_dev *wdev,
4984 u16 frame_type, bool reg)4984 struct mgmt_frame_regs *upd)
4985{4985{
4986 struct brcmf_cfg80211_vif *vif;4986 struct brcmf_cfg80211_vif *vif;
4987 u16 mgmt_type;
4988 4987
4989 brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
4990
4991 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
4992 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);4988 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
4993 if (reg)4989
4994 vif->mgmt_rx_reg |= BIT(mgmt_type);4990 vif->mgmt_rx_reg = upd->interface_stypes;
4995 else
4996 vif->mgmt_rx_reg &= ~BIT(mgmt_type);
4997}4991}
4998 4992
4999 4993
@@ -5408,7 +5402,8 @@ static struct cfg80211_ops brcmf_cfg80211_ops = { · 408 unmodified lines
5408 .change_station = brcmf_cfg80211_change_station,5402 .change_station = brcmf_cfg80211_change_station,
5409 .sched_scan_start = brcmf_cfg80211_sched_scan_start,5403 .sched_scan_start = brcmf_cfg80211_sched_scan_start,
5410 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,5404 .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,
5412 .mgmt_tx = brcmf_cfg80211_mgmt_tx,5407 .mgmt_tx = brcmf_cfg80211_mgmt_tx,
5413 .remain_on_channel = brcmf_p2p_remain_on_channel,5408 .remain_on_channel = brcmf_p2p_remain_on_channel,
5414 .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,5409 .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
269 * CFG802.11 operation handler to register a mgmt frame.269 * CFG802.11 operation handler to register a mgmt frame.
270 */270 */
271static void271static void
272mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,272mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
273 struct wireless_dev *wdev,273 struct wireless_dev *wdev,
274 u16 frame_type, bool reg)274 struct mgmt_frame_regs *upd)
275{275{
276 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);276 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
277 u32 mask;277 u32 mask = upd->interface_stypes;
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);
283 278
284 if (mask != priv->mgmt_frame_mask) {279 if (mask != priv->mgmt_frame_mask) {
285 priv->mgmt_frame_mask = mask;280 priv->mgmt_frame_mask = mask;
@@ -4189,7 +4184,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { · 3903 unmodified lines
4189 .del_key = mwifiex_cfg80211_del_key,4184 .del_key = mwifiex_cfg80211_del_key,
4190 .set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,4185 .set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,
4191 .mgmt_tx = mwifiex_cfg80211_mgmt_tx,4186 .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,
4193 .remain_on_channel = mwifiex_cfg80211_remain_on_channel,4189 .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
4194 .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,4190 .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
4195 .set_default_key = mwifiex_cfg80211_set_default_key,4191 .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
389}389}
390 390
391static void391static void
392qtnf_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,392qtnf_update_mgmt_frame_registrations(struct wiphy *wiphy,
393 u16 frame_type, bool reg)393 struct wireless_dev *wdev,
394 struct mgmt_frame_regs *upd)
394{395{
395 struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);396 struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
396 u16 mgmt_type;397 u16 new_mask = upd->interface_stypes;
397 u16 new_mask;398 u16 old_mask = vif->mgmt_frames_bitmask;
398 u16 qlink_frame_type = 0;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;
399 421
400 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;422 if (new_mask == old_mask)
423 return;
401 424
402 if (reg)425 for (i = 0; i < ARRAY_SIZE(updates); i++) {
403 new_mask = vif->mgmt_frames_bitmask | BIT(mgmt_type);426 u16 mask = updates[i].mask;
404 else427 u16 qlink_frame_type = updates[i].qlink_type;
405 new_mask = vif->mgmt_frames_bitmask & ~BIT(mgmt_type);428 bool reg;
406 429
407 if (new_mask == vif->mgmt_frames_bitmask)430 /* the ! are here due to the assoc/reassoc merge */
408 return;431 if (!(new_mask & mask) == !(old_mask & mask))
432 continue;
409 433
410 switch (frame_type & IEEE80211_FCTL_STYPE) {434 reg = new_mask & mask;
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 }
430 435
431 if (qtnf_cmd_send_register_mgmt(vif, qlink_frame_type, reg)) {436 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",437 pr_warn("VIF%u.%u: failed to %sregister qlink frame type 0x%x\n",
433 vif->mac->macid, vif->vifid, reg ? "" : "un",438 vif->mac->macid, vif->vifid, reg ? "" : "un",
434 frame_type);439 qlink_frame_type);
435 return;
436 }440 }
437 441
438 vif->mgmt_frames_bitmask = new_mask;442 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);
441}443}
442 444
443static int445static int
@@ -1017,7 +1019,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = { · 573 unmodified lines
1017 .change_beacon = qtnf_change_beacon,1019 .change_beacon = qtnf_change_beacon,
1018 .stop_ap = qtnf_stop_ap,1020 .stop_ap = qtnf_stop_ap,
1019 .set_wiphy_params = qtnf_set_wiphy_params,1021 .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,
1021 .mgmt_tx = qtnf_mgmt_tx,1024 .mgmt_tx = qtnf_mgmt_tx,
1022 .change_station = qtnf_change_station,1025 .change_station = qtnf_change_station,
1023 .del_station = qtnf_del_station,1026 .del_station = qtnf_del_station,
include/net/cfg80211.h+18−5
@@ -3384,6 +3384,17 @@ struct cfg80211_update_owe_info { · 3383 unmodified lines
3384 size_t ie_len;3384 size_t ie_len;
3385};3385};
3386 3386
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 */
3394struct mgmt_frame_regs {
3395 u32 global_stypes, interface_stypes;
3396};
3397
3387/**3398/**
3388 * struct cfg80211_ops - backend description for wireless configuration3399 * struct cfg80211_ops - backend description for wireless configuration
3389 *3400 *
@@ -3608,8 +3619,8 @@ struct cfg80211_update_owe_info { · 218 unmodified lines
3608 * The driver should not call cfg80211_sched_scan_stopped() for a requested3619 * The driver should not call cfg80211_sched_scan_stopped() for a requested
3609 * stop (when this method returns 0).3620 * stop (when this method returns 0).
3610 *3621 *
3611 * @mgmt_frame_register: Notify driver that a management frame type was3622 * @update_mgmt_frame_registrations: Notify the driver that management frame
3612 * registered. The callback is allowed to sleep.3623 * registrations were updated. The callback is allowed to sleep.
3613 *3624 *
3614 * @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.3625 * @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
3615 * Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may3626 * Parameters are bitmaps of allowed antennas to use for TX/RX. Drivers may
@@ -3932,9 +3943,9 @@ struct cfg80211_ops { · 316 unmodified lines
3932 struct net_device *dev,3943 struct net_device *dev,
3933 u32 rate, u32 pkts, u32 intvl);3944 u32 rate, u32 pkts, u32 intvl);
3934 3945
3935 void (*mgmt_frame_register)(struct wiphy *wiphy,3946 void (*update_mgmt_frame_registrations)(struct wiphy *wiphy,
3936 struct wireless_dev *wdev,3947 struct wireless_dev *wdev,
3937 u16 frame_type, bool reg);3948 struct mgmt_frame_regs *upd);
3938 3949
3939 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);3950 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
3940 int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);3951 int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
@@ -5015,6 +5026,7 @@ struct cfg80211_cqm_config; · 1074 unmodified lines
5015 * by cfg80211 on change_interface5026 * by cfg80211 on change_interface
5016 * @mgmt_registrations: list of registrations for management frames5027 * @mgmt_registrations: list of registrations for management frames
5017 * @mgmt_registrations_lock: lock for the list5028 * @mgmt_registrations_lock: lock for the list
5029 * @mgmt_registrations_update_wk: update work to defer from atomic context
5018 * @mtx: mutex used to lock data in this struct, may be used by drivers5030 * @mtx: mutex used to lock data in this struct, may be used by drivers
5019 * and some API functions require it held5031 * and some API functions require it held
5020 * @beacon_interval: beacon interval used on this device for transmitting5032 * @beacon_interval: beacon interval used on this device for transmitting
@@ -5060,6 +5072,7 @@ struct wireless_dev { · 39 unmodified lines
5060 5072
5061 struct list_head mgmt_registrations;5073 struct list_head mgmt_registrations;
5062 spinlock_t mgmt_registrations_lock;5074 spinlock_t mgmt_registrations_lock;
5075 struct work_struct mgmt_registrations_update_wk;
5063 5076
5064 struct mutex mtx;5077 struct mutex mtx;
5065 5078
include/net/mac80211.h+1−1
@@ -1647,7 +1647,7 @@ struct ieee80211_vif { · 1646 unmodified lines
1647 struct dentry *debugfs_dir;1647 struct dentry *debugfs_dir;
1648#endif1648#endif
1649 1649
1650 unsigned int probe_req_reg;1650 bool probe_req_reg;
1651 1651
1652 bool txqs_stopped[IEEE80211_NUM_ACS];1652 bool txqs_stopped[IEEE80211_NUM_ACS];
1653 1653
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
3398 return 0;3398 return 0;
3399}3399}
3400 3400
3401static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,3401static void
3402ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
3402 struct wireless_dev *wdev,3403 struct wireless_dev *wdev,
3403 u16 frame_type, bool reg)3404 struct mgmt_frame_regs *upd)
3404{3405{
3405 struct ieee80211_local *local = wiphy_priv(wiphy);3406 struct ieee80211_local *local = wiphy_priv(wiphy);
3406 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);3407 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;
3407 3410
3408 switch (frame_type) {3411 global_change =
3409 case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:3412 local->probe_req_reg != !!(upd->global_stypes & preq_mask);
3410 if (reg) {3413 local->probe_req_reg = upd->global_stypes & preq_mask;
3411 local->probe_req_reg++;
3412 sdata->vif.probe_req_reg++;
3413 } else {
3414 if (local->probe_req_reg)
3415 local->probe_req_reg--;
3416 3414
3417 if (sdata->vif.probe_req_reg)3415 intf_change = sdata->vif.probe_req_reg !=
3418 sdata->vif.probe_req_reg--;3416 !!(upd->interface_stypes & preq_mask);
3419 }3417 sdata->vif.probe_req_reg = upd->interface_stypes & preq_mask;
3420 3418
3421 if (!local->open_count)3419 if (!local->open_count)
3422 break;3420 return;
3423 3421
3424 if (ieee80211_sdata_running(sdata)) {3422 if (intf_change && ieee80211_sdata_running(sdata))
3425 if (sdata->vif.probe_req_reg == 1)3423 drv_config_iface_filter(local, sdata,
3426 drv_config_iface_filter(local, sdata,3424 sdata->vif.probe_req_reg ?
3427 FIF_PROBE_REQ,3425 FIF_PROBE_REQ : 0,
3428 FIF_PROBE_REQ);3426 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 }
3433 3427
3428 if (global_change)
3434 ieee80211_configure_filter(local);3429 ieee80211_configure_filter(local);
3435 break;
3436 default:
3437 break;
3438 }
3439}3430}
3440 3431
3441static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)3432static 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
4020 .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,4011 .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
4021 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,4012 .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
4022 .set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,4013 .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,
4024 .set_antenna = ieee80211_set_antenna,4016 .set_antenna = ieee80211_set_antenna,
4025 .get_antenna = ieee80211_get_antenna,4017 .get_antenna = ieee80211_get_antenna,
4026 .set_rekey_data = ieee80211_set_rekey_data,4018 .set_rekey_data = ieee80211_set_rekey_data,
net/mac80211/ieee80211_i.h+1−1
@@ -1167,7 +1167,7 @@ struct ieee80211_local { · 1166 unmodified lines
1167 /* number of interfaces with corresponding FIF_ flags */1167 /* number of interfaces with corresponding FIF_ flags */
1168 int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,1168 int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
1169 fif_probe_req;1169 fif_probe_req;
1170 int probe_req_reg;1170 bool probe_req_reg;
1171 unsigned int filter_flags; /* FIF_* */1171 unsigned int filter_flags; /* FIF_* */
1172 1172
1173 bool wiphy_ciphers_allocated;1173 bool wiphy_ciphers_allocated;
net/wireless/core.c+3−4
@@ -480,9 +480,6 @@ use_default_name: · 479 unmodified lines
480 INIT_LIST_HEAD(&rdev->bss_list);480 INIT_LIST_HEAD(&rdev->bss_list);
481 INIT_LIST_HEAD(&rdev->sched_scan_req_list);481 INIT_LIST_HEAD(&rdev->sched_scan_req_list);
482 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);482 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);
486 INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,483 INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
487 cfg80211_dfs_channels_update_work);484 cfg80211_dfs_channels_update_work);
488#ifdef CONFIG_CFG80211_WEXT485#ifdef CONFIG_CFG80211_WEXT
@@ -1030,7 +1027,6 @@ void wiphy_unregister(struct wiphy *wiphy) · 541 unmodified lines
1030 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);1027 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
1031 flush_work(&rdev->destroy_work);1028 flush_work(&rdev->destroy_work);
1032 flush_work(&rdev->sched_scan_stop_wk);1029 flush_work(&rdev->sched_scan_stop_wk);
1033 flush_work(&rdev->mlme_unreg_wk);
1034 flush_work(&rdev->propagate_radar_detect_wk);1030 flush_work(&rdev->propagate_radar_detect_wk);
1035 flush_work(&rdev->propagate_cac_done_wk);1031 flush_work(&rdev->propagate_cac_done_wk);
1036 1032
@@ -1094,6 +1090,7 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync) · 57 unmodified lines
1094 rdev->devlist_generation++;1090 rdev->devlist_generation++;
1095 1091
1096 cfg80211_mlme_purge_registrations(wdev);1092 cfg80211_mlme_purge_registrations(wdev);
1093 flush_work(&wdev->mgmt_registrations_update_wk);
1097 1094
1098 switch (wdev->iftype) {1095 switch (wdev->iftype) {
1099 case NL80211_IFTYPE_P2P_DEVICE:1096 case NL80211_IFTYPE_P2P_DEVICE:
@@ -1238,6 +1235,8 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, · 138 unmodified lines
1238 spin_lock_init(&wdev->event_lock);1235 spin_lock_init(&wdev->event_lock);
1239 INIT_LIST_HEAD(&wdev->mgmt_registrations);1236 INIT_LIST_HEAD(&wdev->mgmt_registrations);
1240 spin_lock_init(&wdev->mgmt_registrations_lock);1237 spin_lock_init(&wdev->mgmt_registrations_lock);
1238 INIT_WORK(&wdev->mgmt_registrations_update_wk,
1239 cfg80211_mgmt_registrations_update_wk);
1241 INIT_LIST_HEAD(&wdev->pmsr_list);1240 INIT_LIST_HEAD(&wdev->pmsr_list);
1242 spin_lock_init(&wdev->pmsr_lock);1241 spin_lock_init(&wdev->pmsr_lock);
1243 INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);1242 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
60 struct list_head beacon_registrations;60 struct list_head beacon_registrations;
61 spinlock_t beacon_registrations_lock;61 spinlock_t beacon_registrations_lock;
62 62
63 struct list_head mlme_unreg;
64 spinlock_t mlme_unreg_lock;
65 struct work_struct mlme_unreg_wk;
66
67 /* protected by RTNL only */63 /* protected by RTNL only */
68 int num_running_ifaces;64 int num_running_ifaces;
69 int num_running_monitor_ifaces;65 int num_running_monitor_ifaces;
@@ -386,7 +382,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, · 316 unmodified lines
386int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,382int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
387 u16 frame_type, const u8 *match_data,383 u16 frame_type, const u8 *match_data,
388 int match_len, struct netlink_ext_ack *extack);384 int match_len, struct netlink_ext_ack *extack);
389void cfg80211_mlme_unreg_wk(struct work_struct *wk);385void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk);
390void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);386void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
391void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);387void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
392int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,388int 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
429 u8 match[];429 u8 match[];
430};430};
431 431
432static void432static void cfg80211_mgmt_registrations_update(struct wireless_dev *wdev)
433cfg80211_process_mlme_unregistrations(struct cfg80211_registered_device *rdev)
434{433{
434 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
435 struct wireless_dev *tmp;
435 struct cfg80211_mgmt_registration *reg;436 struct cfg80211_mgmt_registration *reg;
437 struct mgmt_frame_regs upd = {};
436 438
437 ASSERT_RTNL();439 ASSERT_RTNL();
438 440
439 spin_lock_bh(&rdev->mlme_unreg_lock);441 rcu_read_lock();
440 while ((reg = list_first_entry_or_null(&rdev->mlme_unreg,442 list_for_each_entry_rcu(tmp, &rdev->wiphy.wdev_list, list) {
441 struct cfg80211_mgmt_registration,443 list_for_each_entry_rcu(reg, &tmp->mgmt_registrations, list) {
442 list))) {444 u32 mask = BIT(le16_to_cpu(reg->frame_type) >> 4);
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);
448 445
449 rdev_mgmt_frame_register(rdev, reg->wdev,446 upd.global_stypes |= mask;
450 frame_type, false);447 if (tmp == wdev)
448 upd.interface_stypes |= mask;
451 }449 }
452
453 kfree(reg);
454
455 spin_lock_bh(&rdev->mlme_unreg_lock);
456 }450 }
457 spin_unlock_bh(&rdev->mlme_unreg_lock);451 rcu_read_unlock();
452
453 rdev_update_mgmt_frame_registrations(rdev, wdev, &upd);
458}454}
459 455
460void cfg80211_mlme_unreg_wk(struct work_struct *wk)456void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
461{457{
462 struct cfg80211_registered_device *rdev;458 struct wireless_dev *wdev = container_of(wk, struct wireless_dev,
463 459 mgmt_registrations_update_wk);
464 rdev = container_of(wk, struct cfg80211_registered_device,
465 mlme_unreg_wk);
466 460
467 rtnl_lock();461 rtnl_lock();
468 cfg80211_process_mlme_unregistrations(rdev);462 cfg80211_mgmt_registrations_update(wdev);
469 rtnl_unlock();463 rtnl_unlock();
470}464}
471 465
@@ -473,8 +467,6 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 1 unmodified line
473 u16 frame_type, const u8 *match_data,467 u16 frame_type, const u8 *match_data,
474 int match_len, struct netlink_ext_ack *extack)468 int match_len, struct netlink_ext_ack *extack)
475{469{
476 struct wiphy *wiphy = wdev->wiphy;
477 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
478 struct cfg80211_mgmt_registration *reg, *nreg;470 struct cfg80211_mgmt_registration *reg, *nreg;
479 int err = 0;471 int err = 0;
480 u16 mgmt_type;472 u16 mgmt_type;
@@ -534,10 +526,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 53 unmodified lines
534 }526 }
535 }527 }
536 528
537 if (err) {529 if (err)
538 kfree(nreg);
539 goto out;530 goto out;
540 }
541 531
542 memcpy(nreg->match, match_data, match_len);532 memcpy(nreg->match, match_data, match_len);
543 nreg->match_len = match_len;533 nreg->match_len = match_len;
@@ -547,15 +537,12 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, · 3 unmodified lines
547 list_add(&nreg->list, &wdev->mgmt_registrations);537 list_add(&nreg->list, &wdev->mgmt_registrations);
548 spin_unlock_bh(&wdev->mgmt_registrations_lock);538 spin_unlock_bh(&wdev->mgmt_registrations_lock);
549 539
550 /* process all unregistrations to avoid driver confusion */540 cfg80211_mgmt_registrations_update(wdev);
551 cfg80211_process_mlme_unregistrations(rdev);
552
553 if (rdev->ops->mgmt_frame_register)
554 rdev_mgmt_frame_register(rdev, wdev, frame_type, true);
555 541
556 return 0;542 return 0;
557 543
558 out:544 out:
545 kfree(nreg);
559 spin_unlock_bh(&wdev->mgmt_registrations_lock);546 spin_unlock_bh(&wdev->mgmt_registrations_lock);
560 547
561 return err;548 return err;
@@ -574,11 +561,9 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid) · 12 unmodified lines
574 continue;561 continue;
575 562
576 list_del(&reg->list);563 list_del(&reg->list);
577 spin_lock(&rdev->mlme_unreg_lock);564 kfree(reg);
578 list_add_tail(&reg->list, &rdev->mlme_unreg);
579 spin_unlock(&rdev->mlme_unreg_lock);
580 565
581 schedule_work(&rdev->mlme_unreg_wk);566 schedule_work(&wdev->mgmt_registrations_update_wk);
582 }567 }
583 568
584 spin_unlock_bh(&wdev->mgmt_registrations_lock);569 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
594 579
595void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)580void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
596{581{
597 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);582 struct cfg80211_mgmt_registration *reg, *tmp;
598 583
599 spin_lock_bh(&wdev->mgmt_registrations_lock);584 spin_lock_bh(&wdev->mgmt_registrations_lock);
600 spin_lock(&rdev->mlme_unreg_lock);585 list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
601 list_splice_tail_init(&wdev->mgmt_registrations, &rdev->mlme_unreg);586 list_del(&reg->list);
602 spin_unlock(&rdev->mlme_unreg_lock);587 kfree(reg);
588 }
603 spin_unlock_bh(&wdev->mgmt_registrations_lock);589 spin_unlock_bh(&wdev->mgmt_registrations_lock);
604 590
605 cfg80211_process_mlme_unregistrations(rdev);591 cfg80211_mgmt_registrations_update(wdev);
606}592}
607 593
608int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,594int 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
819}819}
820 820
821static inline void821static inline void
822rdev_mgmt_frame_register(struct cfg80211_registered_device *rdev,822rdev_update_mgmt_frame_registrations(struct cfg80211_registered_device *rdev,
823 struct wireless_dev *wdev, u16 frame_type, bool reg)823 struct wireless_dev *wdev,
824 struct mgmt_frame_regs *upd)
824{825{
825 might_sleep();826 might_sleep();
826 827
827 trace_rdev_mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);828 trace_rdev_update_mgmt_frame_registrations(&rdev->wiphy, wdev, upd);
828 rdev->ops->mgmt_frame_register(&rdev->wiphy, wdev , frame_type, reg);829 if (rdev->ops->update_mgmt_frame_registrations)
830 rdev->ops->update_mgmt_frame_registrations(&rdev->wiphy, wdev,
831 upd);
829 trace_rdev_return_void(&rdev->wiphy);832 trace_rdev_return_void(&rdev->wiphy);
830}833}
831 834
net/wireless/trace.h+10−10
@@ -1582,25 +1582,25 @@ TRACE_EVENT(rdev_set_bitrate_mask, · 1581 unmodified lines
1582 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))1582 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
1583);1583);
1584 1584
1585TRACE_EVENT(rdev_mgmt_frame_register,1585TRACE_EVENT(rdev_update_mgmt_frame_registrations,
1586 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,1586 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
1587 u16 frame_type, bool reg),1587 struct mgmt_frame_regs *upd),
1588 TP_ARGS(wiphy, wdev, frame_type, reg),1588 TP_ARGS(wiphy, wdev, upd),
1589 TP_STRUCT__entry(1589 TP_STRUCT__entry(
1590 WIPHY_ENTRY1590 WIPHY_ENTRY
1591 WDEV_ENTRY1591 WDEV_ENTRY
1592 __field(u16, frame_type)1592 __field(u16, global_stypes)
1593 __field(bool, reg)1593 __field(u16, interface_stypes)
1594 ),1594 ),
1595 TP_fast_assign(1595 TP_fast_assign(
1596 WIPHY_ASSIGN;1596 WIPHY_ASSIGN;
1597 WDEV_ASSIGN;1597 WDEV_ASSIGN;
1598 __entry->frame_type = frame_type;1598 __entry->global_stypes = upd->global_stypes;
1599 __entry->reg = reg;1599 __entry->interface_stypes = upd->interface_stypes;
1600 ),1600 ),
1601 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", frame_type: 0x%.2x, reg: %s ",1601 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", global: 0x%.2x, intf: 0x%.2x",
1602 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->frame_type,1602 WIPHY_PR_ARG, WDEV_PR_ARG,
1603 __entry->reg ? "true" : "false")1603 __entry->global_stypes, __entry->interface_stypes)
1604);1604);
1605 1605
1606TRACE_EVENT(rdev_return_int_tx_rx,1606TRACE_EVENT(rdev_return_int_tx_rx,