From 0cb4d4dceb4b7a31c6af0159cac2cec5fbe294a2 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 13 Jan 2014 19:42:58 +0200 Subject: mac80211: refactor ieee80211_mesh_process_chanswitch() Refactor ieee80211_mesh_process_chanswitch() to use ieee80211_channel_switch() and avoid code duplication. Tested-by: Simon Wunderlich Acked-by: Simon Wunderlich Signed-off-by: Luciano Coelho Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f9ae9b85d4c1..f111f8df4e65 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3164,15 +3164,18 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, params->chandef.chan->band) return -EINVAL; - ifmsh->chsw_init = true; if (!ifmsh->pre_value) ifmsh->pre_value = 1; else ifmsh->pre_value++; - err = ieee80211_mesh_csa_beacon(sdata, params, true); + if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) + ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; + + err = ieee80211_mesh_csa_beacon(sdata, params, + (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)); if (err < 0) { - ifmsh->chsw_init = false; + ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; return err; } break; -- cgit v1.2.3 From 66e01cf99e0a9d0cbff21b0288c049654d5acf3e Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 13 Jan 2014 19:43:00 +0200 Subject: mac80211: only set CSA beacon when at least one beacon must be transmitted A beacon should never have a Channel Switch Announcement information element with a count of 0, because a count of 1 means switch just before the next beacon. So, if a count of 0 was valid in a beacon, it would have been transmitted in the next channel already, which is useless. A CSA count equal to zero is only meaningful in action frames or probe_responses. Fix the ieee80211_csa_is_complete() and ieee80211_update_csa() functions accordingly. With a CSA count of 0, we won't transmit any CSA beacons, because the switch will happen before the next TBTT. To avoid extra work and potential confusion in the drivers, complete the CSA immediately, instead of waiting for the driver to call ieee80211_csa_finish(). To keep things simpler, we also switch immediately when the CSA count is 1, while in theory we should delay the switch until just before the next TBTT. Additionally, move the ieee80211_csa_finish() function to cfg.c, where it makes more sense. Tested-by: Simon Wunderlich Acked-by: Simon Wunderlich Signed-off-by: Luciano Coelho Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 115 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 30 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f111f8df4e65..032081c4cc65 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2988,28 +2988,26 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) return new_beacon; } -void ieee80211_csa_finalize_work(struct work_struct *work) +void ieee80211_csa_finish(struct ieee80211_vif *vif) { - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, - csa_finalize_work); - struct ieee80211_local *local = sdata->local; - int err, changed = 0; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - sdata_lock(sdata); - /* AP might have been stopped while waiting for the lock. */ - if (!sdata->vif.csa_active) - goto unlock; + ieee80211_queue_work(&sdata->local->hw, + &sdata->csa_finalize_work); +} +EXPORT_SYMBOL(ieee80211_csa_finish); - if (!ieee80211_sdata_running(sdata)) - goto unlock; +static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + int err, changed = 0; sdata->radar_required = sdata->csa_radar_required; mutex_lock(&local->mtx); err = ieee80211_vif_change_channel(sdata, &changed); mutex_unlock(&local->mtx); if (WARN_ON(err < 0)) - goto unlock; + return; if (!local->use_chanctx) { local->_oper_chandef = sdata->csa_chandef; @@ -3023,7 +3021,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work) case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); if (err < 0) - goto unlock; + return; changed |= err; kfree(sdata->u.ap.next_beacon); @@ -3038,12 +3036,12 @@ void ieee80211_csa_finalize_work(struct work_struct *work) case NL80211_IFTYPE_MESH_POINT: err = ieee80211_mesh_finish_csa(sdata); if (err < 0) - goto unlock; + return; break; #endif default: WARN_ON(1); - goto unlock; + return; } ieee80211_wake_queues_by_reason(&sdata->local->hw, @@ -3051,6 +3049,23 @@ void ieee80211_csa_finalize_work(struct work_struct *work) IEEE80211_QUEUE_STOP_REASON_CSA); cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); +} + +void ieee80211_csa_finalize_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, + csa_finalize_work); + + sdata_lock(sdata); + /* AP might have been stopped while waiting for the lock. */ + if (!sdata->vif.csa_active) + goto unlock; + + if (!ieee80211_sdata_running(sdata)) + goto unlock; + + ieee80211_csa_finalize(sdata); unlock: sdata_unlock(sdata); @@ -3064,7 +3079,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx *chanctx; struct ieee80211_if_mesh __maybe_unused *ifmsh; - int err, num_chanctx; + int err, num_chanctx, changed = 0; lockdep_assert_held(&sdata->wdev.mtx); @@ -3105,19 +3120,40 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, switch (sdata->vif.type) { case NL80211_IFTYPE_AP: - sdata->csa_counter_offset_beacon = - params->counter_offset_beacon; - sdata->csa_counter_offset_presp = params->counter_offset_presp; sdata->u.ap.next_beacon = cfg80211_beacon_dup(¶ms->beacon_after); if (!sdata->u.ap.next_beacon) return -ENOMEM; + /* + * With a count of 0, we don't have to wait for any + * TBTT before switching, so complete the CSA + * immediately. In theory, with a count == 1 we + * should delay the switch until just before the next + * TBTT, but that would complicate things so we switch + * immediately too. If we would delay the switch + * until the next TBTT, we would have to set the probe + * response here. + * + * TODO: A channel switch with count <= 1 without + * sending a CSA action frame is kind of useless, + * because the clients won't know we're changing + * channels. The action frame must be implemented + * either here or in the userspace. + */ + if (params->count <= 1) + break; + + sdata->csa_counter_offset_beacon = + params->counter_offset_beacon; + sdata->csa_counter_offset_presp = params->counter_offset_presp; err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); if (err < 0) { kfree(sdata->u.ap.next_beacon); return err; } + changed |= err; + break; case NL80211_IFTYPE_ADHOC: if (!sdata->vif.bss_conf.ibss_joined) @@ -3145,9 +3181,16 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, params->chandef.chan->band) return -EINVAL; - err = ieee80211_ibss_csa_beacon(sdata, params); - if (err < 0) - return err; + /* see comments in the NL80211_IFTYPE_AP block */ + if (params->count > 1) { + err = ieee80211_ibss_csa_beacon(sdata, params); + if (err < 0) + return err; + changed |= err; + } + + ieee80211_send_action_csa(sdata, params); + break; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: @@ -3172,12 +3215,19 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; - err = ieee80211_mesh_csa_beacon(sdata, params, - (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)); - if (err < 0) { - ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; - return err; + /* see comments in the NL80211_IFTYPE_AP block */ + if (params->count > 1) { + err = ieee80211_mesh_csa_beacon(sdata, params); + if (err < 0) { + ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; + return err; + } + changed |= err; } + + if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) + ieee80211_send_action_csa(sdata, params); + break; #endif default: @@ -3194,8 +3244,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, sdata->csa_chandef = params->chandef; sdata->vif.csa_active = true; - ieee80211_bss_info_change_notify(sdata, err); - drv_channel_switch_beacon(sdata, ¶ms->chandef); + if (changed) { + ieee80211_bss_info_change_notify(sdata, changed); + drv_channel_switch_beacon(sdata, ¶ms->chandef); + } else { + /* if the beacon didn't change, we can finalize immediately */ + ieee80211_csa_finalize(sdata); + } return 0; } -- cgit v1.2.3 From c782bf8caae59a6cdd17ed1b99c126167dae49b2 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 22 Jan 2014 14:53:04 +0800 Subject: mac80211: fix the increment of mesh precedence value The mesh precedence value in ieee80211_channel_switch should be incremented or set to 1 only if this is the initiator of mesh channel switch. For non-initiator, the precedence value has updated using the Mesh Channel Switch Parameters element. Fix this. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 032081c4cc65..e948b382cd45 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3207,13 +3207,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, params->chandef.chan->band) return -EINVAL; - if (!ifmsh->pre_value) - ifmsh->pre_value = 1; - else - ifmsh->pre_value++; - - if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) + if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) { ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; + if (!ifmsh->pre_value) + ifmsh->pre_value = 1; + else + ifmsh->pre_value++; + } /* see comments in the NL80211_IFTYPE_AP block */ if (params->count > 1) { -- cgit v1.2.3 From 80e207c32bff0f9e990f4ff629c809bd20c7950a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Jan 2014 21:04:00 +0100 Subject: mac80211: mesh: remove mesh_id check The mesh_id is an array so can't ever be NULL, it looks like mesh_id_len check was intended instead. However, since the previous patch, cfg80211 does the check, so just remove it here. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e948b382cd45..cf961a5f3aa9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3196,9 +3196,6 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, case NL80211_IFTYPE_MESH_POINT: ifmsh = &sdata->u.mesh; - if (!ifmsh->mesh_id) - return -EINVAL; - if (params->chandef.width != sdata->vif.bss_conf.chandef.width) return -EINVAL; -- cgit v1.2.3 From 2fae062e503bd087d1ef7aebfd5c6707c6ec5564 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 19 Dec 2013 13:25:29 +0200 Subject: mac80211: Fix ROC duration == 0 handling In case the given ROC duration is 0, update it to a minimal value before setting the ieee80211_roc_work parameters, so it also would be valid for cases where scan is in progress or there are other ROCs queued. Signed-off-by: Ilan Peer Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index cf961a5f3aa9..d2125a37014a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2628,6 +2628,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, if (!roc) return -ENOMEM; + /* + * If the duration is zero, then the driver + * wouldn't actually do anything. Set it to + * 10 for now. + * + * TODO: cancel the off-channel operation + * when we get the SKB's TX status and + * the wait time was zero before. + */ + if (!duration) + duration = 10; + roc->chan = channel; roc->duration = duration; roc->req_duration = duration; @@ -2651,18 +2663,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, /* otherwise actually kick it off here (for error handling) */ - /* - * If the duration is zero, then the driver - * wouldn't actually do anything. Set it to - * 10 for now. - * - * TODO: cancel the off-channel operation - * when we get the SKB's TX status and - * the wait time was zero before. - */ - if (!duration) - duration = 10; - ret = drv_remain_on_channel(local, sdata, channel, duration, type); if (ret) { kfree(roc); -- cgit v1.2.3 From 8a47cea7d4a25babf14d02be8aabb98949dd2bed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Jan 2014 23:55:44 +0100 Subject: mac80211: make cfg80211 ops and privid const The wiphy privid (to identify wiphys) and the cfg80211 ops should both be const, so change them to be. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d2125a37014a..cf27c623394a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3918,7 +3918,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy, return 0; } -struct cfg80211_ops mac80211_config_ops = { +const struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, .change_virtual_intf = ieee80211_change_iface, -- cgit v1.2.3 From faf046e7231bf008715bbffe5cca2ed3aa31be1b Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 29 Jan 2014 07:56:17 +0100 Subject: mac80211: batch CSA bss info notification Instead of having ieee80211_bss_info_change_notify() scattered all over the place just call it once when finalizing CSA. As a side effect this patch adds missing error checking for IBSS CSA beacon update. Signed-off-by: Michal Kazior Reviewed-by: Luciano Coelho [fix err vs. changed variable usage in ieee80211_csa_finalize()] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index cf27c623394a..f215ad48985a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3014,29 +3014,28 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ieee80211_hw_config(local, 0); } - ieee80211_bss_info_change_notify(sdata, changed); - sdata->vif.csa_active = false; switch (sdata->vif.type) { case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); if (err < 0) return; - changed |= err; kfree(sdata->u.ap.next_beacon); sdata->u.ap.next_beacon = NULL; - - ieee80211_bss_info_change_notify(sdata, err); break; case NL80211_IFTYPE_ADHOC: - ieee80211_ibss_finish_csa(sdata); + err = ieee80211_ibss_finish_csa(sdata); + if (err < 0) + return; + changed |= err; break; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: err = ieee80211_mesh_finish_csa(sdata); if (err < 0) return; + changed |= err; break; #endif default: @@ -3044,6 +3043,8 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) return; } + ieee80211_bss_info_change_notify(sdata, changed); + ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA); -- cgit v1.2.3 From 97518af1260553d2cad71b37a76b597360519e8a Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 29 Jan 2014 07:56:18 +0100 Subject: mac80211: fix possible memory leak on AP CSA failure If CSA for AP interface failed and the interface was not stopped afterwards another CSA request would leak sdata->u.ap.next_beacon. Signed-off-by: Michal Kazior Reviewed-by: Luciano Coelho Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f215ad48985a..b98dc8ce8e25 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3018,11 +3018,12 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) switch (sdata->vif.type) { case NL80211_IFTYPE_AP: err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; + if (err < 0) return; changed |= err; - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; break; case NL80211_IFTYPE_ADHOC: err = ieee80211_ibss_finish_csa(sdata); -- cgit v1.2.3 From cc901de1bcb0372583466075bfa62e3049dc6288 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 29 Jan 2014 07:56:20 +0100 Subject: mac80211: fix sdata->radar_required locking radar_required setting wasn't protected by local->mtx in some places. This should prevent from scanning/radar detection/roc colliding. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b98dc8ce8e25..27fa53bfed0d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, /* TODO: make hostapd tell us what it wants */ sdata->smps_mode = IEEE80211_SMPS_OFF; sdata->needed_rx_chains = sdata->local->rx_chains; - sdata->radar_required = params->radar_required; mutex_lock(&local->mtx); + sdata->radar_required = params->radar_required; err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, IEEE80211_CHANCTX_SHARED); mutex_unlock(&local->mtx); @@ -3002,8 +3002,8 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; int err, changed = 0; - sdata->radar_required = sdata->csa_radar_required; mutex_lock(&local->mtx); + sdata->radar_required = sdata->csa_radar_required; err = ieee80211_vif_change_channel(sdata, &changed); mutex_unlock(&local->mtx); if (WARN_ON(err < 0)) -- cgit v1.2.3 From dbd72850dcc9738b42a9762ef8c4a1a66b30d897 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 29 Jan 2014 07:56:21 +0100 Subject: mac80211: add missing CSA locking The patch adds a missing sdata lock and adds a few lockdeps for easier maintenance. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 27fa53bfed0d..875e63d3d9c5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1053,6 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, int err; sdata = IEEE80211_DEV_TO_SUB_IF(dev); + sdata_assert_lock(sdata); /* don't allow changing the beacon while CSA is in place - offset * of channel switch counter may change @@ -1080,6 +1081,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) struct probe_resp *old_probe_resp; struct cfg80211_chan_def chandef; + sdata_assert_lock(sdata); + old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); if (!old_beacon) return -ENOENT; @@ -3002,6 +3005,8 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; int err, changed = 0; + sdata_assert_lock(sdata); + mutex_lock(&local->mtx); sdata->radar_required = sdata->csa_radar_required; err = ieee80211_vif_change_channel(sdata, &changed); @@ -3083,7 +3088,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_if_mesh __maybe_unused *ifmsh; int err, num_chanctx, changed = 0; - lockdep_assert_held(&sdata->wdev.mtx); + sdata_assert_lock(sdata); if (!list_empty(&local->roc_list) || local->scanning) return -EBUSY; -- cgit v1.2.3 From b1bce14a7954790d0fd3bba29375a65aa96fc57c Mon Sep 17 00:00:00 2001 From: Marek Kwaczynski Date: Mon, 3 Feb 2014 14:44:44 +0100 Subject: mac80211: update opmode when adding new station Update the operating mode field is needed when an association request contains the operating mode notification element and it's not just changed later on the fly. Signed-off-by: Marek Kwaczynski [clarify commit log, comments & fix whitespace] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 875e63d3d9c5..8192093f1e8b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1344,6 +1344,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, params->vht_capa, sta); + if (params->opmode_notif_used) { + enum ieee80211_band band = + ieee80211_get_sdata_band(sdata); + + /* returned value is only needed for rc update, but the + * rc isn't initialized here yet, so ignore it + */ + __ieee80211_vht_handle_opmode(sdata, sta, + params->opmode_notif, + band, false); + } + if (ieee80211_vif_is_mesh(&sdata->vif)) { #ifdef CONFIG_MAC80211_MESH u32 changed = 0; -- cgit v1.2.3 From 1b8d242adbea881658071efc31d2c0dcf8a44fb7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 5 Feb 2014 16:37:11 +0200 Subject: mac80211: move VHT related RX_FLAG to another variable ieee80211_rx_status.flags is full. Define a new vht_flag variable to be able to set more VHT related flags and make room in flags. Signed-off-by: Emmanuel Grumbach Acked-by: Kalle Valo [ath10k] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8192093f1e8b..6973ccdd230b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -451,11 +451,11 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; - if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) + if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) + if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ) rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; - if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) + if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; } -- cgit v1.2.3 From 4bf332c785bc14e6decb6ea4949a831e7e199b8b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Feb 2014 16:50:34 +0100 Subject: mac80211: remove superfluous band variable We already have a band variable, so the new one is just shadowing it, but the existing one already holds the same value so just remove the inner one. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6973ccdd230b..7f01f2aec7b5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1345,9 +1345,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, params->vht_capa, sta); if (params->opmode_notif_used) { - enum ieee80211_band band = - ieee80211_get_sdata_band(sdata); - /* returned value is only needed for rc update, but the * rc isn't initialized here yet, so ignore it */ -- cgit v1.2.3 From df942e7ba70cd0a7aa9e0432b8a6a328de2c5574 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Undekari Date: Thu, 20 Feb 2014 16:22:09 +0530 Subject: cfg80211: Pass TDLS peer capability information in tdls_mgmt While framing the TDLS Setup Confirmation frame, the driver needs to know if the TDLS peer is VHT/HT/WMM capable and thus shall construct the VHT/HT operation / WMM parameter elements accordingly. Supplicant determines if the TDLS peer is VHT/HT/WMM capable based on the presence of the respective IEs in the received TDLS Setup Response frame. The host driver should not need to parse the received TDLS Response frame and thus, should be able to rely on the supplicant to indicate the capability of the peer through additional flags while transmitting the TDLS Setup Confirmation frame through tdls_mgmt operations. Signed-off-by: Sunil Dutt Undekari Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3849fd07a321..1acb29109b45 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3644,8 +3644,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len) + u16 status_code, u32 peer_capability, + const u8 *extra_ies, size_t extra_ies_len) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; -- cgit v1.2.3 From 31559f35c5724976fd975e5d7e90cdb693b8dd27 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Fri, 21 Feb 2014 19:46:13 +0100 Subject: cfg80211: DFS get CAC time from regulatory database Send Channel Availability Check time as a parameter of start_radar_detection() callback. Get CAC time from regulatory database. Signed-off-by: Janusz Dziedzic Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1acb29109b45..80534f524fd6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, static int ieee80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_chan_def *chandef) + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - unsigned long timeout; int err; mutex_lock(&local->mtx); @@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, if (err) goto out_unlock; - timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); ieee80211_queue_delayed_work(&sdata->local->hw, - &sdata->dfs_cac_timer_work, timeout); + &sdata->dfs_cac_timer_work, + msecs_to_jiffies(cac_time_ms)); out_unlock: mutex_unlock(&local->mtx); -- cgit v1.2.3 From 37fa2bdd16a12fef7804606f56525ba5747bf172 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 28 Feb 2014 15:59:06 +0100 Subject: mac80211: refactor channel switch function The function was quite big. This splits out beacon updating into a separate function for improved maintenance and extension. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 113 +++++++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 50 deletions(-) (limited to 'net/mac80211/cfg.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 80534f524fd6..aaa59d719592 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3089,52 +3089,11 @@ unlock: sdata_unlock(sdata); } -int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_csa_settings *params) +static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, + struct cfg80211_csa_settings *params, + u32 *changed) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; - struct ieee80211_chanctx_conf *chanctx_conf; - struct ieee80211_chanctx *chanctx; - struct ieee80211_if_mesh __maybe_unused *ifmsh; - int err, num_chanctx, changed = 0; - - sdata_assert_lock(sdata); - - if (!list_empty(&local->roc_list) || local->scanning) - return -EBUSY; - - if (sdata->wdev.cac_started) - return -EBUSY; - - if (cfg80211_chandef_identical(¶ms->chandef, - &sdata->vif.bss_conf.chandef)) - return -EINVAL; - - rcu_read_lock(); - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (!chanctx_conf) { - rcu_read_unlock(); - return -EBUSY; - } - - /* don't handle for multi-VIF cases */ - chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); - if (chanctx->refcount > 1) { - rcu_read_unlock(); - return -EBUSY; - } - num_chanctx = 0; - list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) - num_chanctx++; - rcu_read_unlock(); - - if (num_chanctx > 1) - return -EBUSY; - - /* don't allow another channel switch if one is already active. */ - if (sdata->vif.csa_active) - return -EBUSY; + int err; switch (sdata->vif.type) { case NL80211_IFTYPE_AP: @@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, kfree(sdata->u.ap.next_beacon); return err; } - changed |= err; + *changed |= err; break; case NL80211_IFTYPE_ADHOC: @@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, err = ieee80211_ibss_csa_beacon(sdata, params); if (err < 0) return err; - changed |= err; + *changed |= err; } ieee80211_send_action_csa(sdata, params); break; #ifdef CONFIG_MAC80211_MESH - case NL80211_IFTYPE_MESH_POINT: - ifmsh = &sdata->u.mesh; + case NL80211_IFTYPE_MESH_POINT: { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; if (params->chandef.width != sdata->vif.bss_conf.chandef.width) return -EINVAL; @@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; return err; } - changed |= err; + *changed |= err; } if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) ieee80211_send_action_csa(sdata, params); break; + } #endif default: return -EOPNOTSUPP; } + return 0; +} + +int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_csa_settings *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_chanctx *chanctx; + int err, num_chanctx, changed = 0; + + sdata_assert_lock(sdata); + + if (!list_empty(&local->roc_list) || local->scanning) + return -EBUSY; + + if (sdata->wdev.cac_started) + return -EBUSY; + + if (cfg80211_chandef_identical(¶ms->chandef, + &sdata->vif.bss_conf.chandef)) + return -EINVAL; + + rcu_read_lock(); + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (!chanctx_conf) { + rcu_read_unlock(); + return -EBUSY; + } + + /* don't handle for multi-VIF cases */ + chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); + if (chanctx->refcount > 1) { + rcu_read_unlock(); + return -EBUSY; + } + num_chanctx = 0; + list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) + num_chanctx++; + rcu_read_unlock(); + + if (num_chanctx > 1) + return -EBUSY; + + /* don't allow another channel switch if one is already active. */ + if (sdata->vif.csa_active) + return -EBUSY; + + err = ieee80211_set_csa_beacon(sdata, params, &changed); + if (err) + return err; + sdata->csa_radar_required = params->radar_required; if (params->block_tx) -- cgit v1.2.3