From 0c86980817853e4166f66c7cd18bc5fe1adeb5f7 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 22 Apr 2010 10:27:48 +0300 Subject: mac80211: Fix sta->last_tx_rate setting with no-op rate control devices The sta->last_tx_rate is traditionally updated just before transmitting a frame based on information from the rate control algorithm. However, for hardware drivers with IEEE80211_HW_HAS_RATE_CONTROL this is not performed, as the rate control algorithm is not executed, and because the used rate is not known before the frame has actually been transmitted. This causes atleast a fixed 1Mb/s to be reported to user space. A few other instances of code also rely on this information. Fix this by setting the sta->last_tx_rate in tx_status handling. There, look for last rates entry set by the driver, and use that as value for sta->last_tx_rate. Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- net/mac80211/status.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net') diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 11805a3a626f..94613af009f3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -171,6 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct net_device *prev_dev = NULL; struct sta_info *sta, *tmp; int retry_count = -1, i; + int rates_idx = -1; bool send_to_cooked; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { @@ -178,6 +179,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) if (i >= hw->max_rates) { info->status.rates[i].idx = -1; info->status.rates[i].count = 0; + } else if (info->status.rates[i].idx >= 0) { + rates_idx = i; } retry_count += info->status.rates[i].count; @@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) return; } + if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && + (rates_idx != -1)) + sta->last_tx_rate = info->status.rates[rates_idx]; + if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && (ieee80211_is_data_qos(fc))) { u16 tid, ssn; -- cgit v1.2.3 From f7917af92024d43bc20bc1afc92de27b0bd0f50b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 27 Apr 2010 00:26:34 +0200 Subject: mac80211: fix handling of 4-address-mode in ieee80211_change_iface A misplaced interface type check bails out too early if the interface is not in monitor mode. This patch moves it to the right place, so that it only covers changes to the monitor flags. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f97dda735cbb..592f07d2ae5c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -96,9 +96,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, params->mesh_id_len, params->mesh_id); - if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) - return 0; - if (type == NL80211_IFTYPE_AP_VLAN && params && params->use_4addr == 0) rcu_assign_pointer(sdata->u.vlan.sta, NULL); @@ -106,7 +103,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, params && params->use_4addr >= 0) sdata->u.mgd.use_4addr = params->use_4addr; - sdata->u.mntr_flags = *flags; + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) + sdata->u.mntr_flags = *flags; + return 0; } -- cgit v1.2.3 From fd8aaaf3519f3fd3c82594e90bc6808072b94d54 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 27 Apr 2010 01:23:35 +0200 Subject: cfg80211: add ap isolation support This is used to configure APs to not bridge traffic between connected stations. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- include/linux/nl80211.h | 5 +++++ include/net/cfg80211.h | 2 ++ net/wireless/nl80211.c | 4 ++++ 3 files changed, 11 insertions(+) (limited to 'net') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2ea3edeee7aa..f8750f9a65b8 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -709,6 +709,9 @@ enum nl80211_commands { * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, * NL80211_CMD_DISASSOCIATE. * + * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations + * connected to this BSS. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -864,6 +867,8 @@ enum nl80211_attrs { NL80211_ATTR_LOCAL_STATE_CHANGE, + NL80211_ATTR_AP_ISOLATE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5a4efe54cffd..f6b29bf925d0 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -511,6 +511,7 @@ struct mpath_info { * @basic_rates: basic rates in IEEE 802.11 format * (or NULL for no change) * @basic_rates_len: number of basic rates + * @ap_isolate: do not forward packets between connected stations */ struct bss_parameters { int use_cts_prot; @@ -518,6 +519,7 @@ struct bss_parameters { int use_short_slot_time; u8 *basic_rates; u8 basic_rates_len; + int ap_isolate; }; struct mesh_config { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index df5505b3930c..c27bef8e0c11 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -151,6 +151,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, + [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, }; /* policy for the attributes */ @@ -2441,6 +2442,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) params.use_cts_prot = -1; params.use_short_preamble = -1; params.use_short_slot_time = -1; + params.ap_isolate = -1; if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) params.use_cts_prot = @@ -2457,6 +2459,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) params.basic_rates_len = nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); } + if (info->attrs[NL80211_ATTR_AP_ISOLATE]) + params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); rtnl_lock(); -- cgit v1.2.3 From 7b7b5e56d7bdfdd0eb5ea13e6c9613b16b8eac46 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 27 Apr 2010 01:23:36 +0200 Subject: mac80211: implement ap isolation support Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 592f07d2ae5c..e13fb3a62239 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1113,6 +1113,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, changed |= BSS_CHANGED_BASIC_RATES; } + if (params->ap_isolate >= 0) { + if (params->ap_isolate) + sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; + else + sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; + } + ieee80211_bss_info_change_notify(sdata, changed); return 0; -- cgit v1.2.3 From 195e294d21e88af879da4f88db2ceeb4ec28a755 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Tue, 27 Apr 2010 12:47:40 +0300 Subject: mac80211: Determine dynamic PS timeout based on ps-qos network latency Determine the dynamic PS timeout based on the configured ps-qos network latency. For backwards wext compatibility, allow the dynamic PS timeout configured by the cfg80211 to overrule the automatically determined value. Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 ++++- net/mac80211/cfg.c | 4 ++-- net/mac80211/main.c | 2 ++ net/mac80211/mlme.c | 21 +++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7dc5a6790397..c26de6cb12f8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -668,6 +668,9 @@ enum ieee80211_smps_mode { * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the * powersave documentation below. This variable is valid only when * the CONF_PS flag is set. + * @dynamic_ps_forced_timeout: The dynamic powersave timeout (in ms) configured + * by cfg80211 (essentially, wext) If set, this value overrules the value + * chosen by mac80211 based on ps qos network latency. * * @power_level: requested transmit power (in dBm) * @@ -687,7 +690,7 @@ enum ieee80211_smps_mode { */ struct ieee80211_conf { u32 flags; - int power_level, dynamic_ps_timeout; + int power_level, dynamic_ps_timeout, dynamic_ps_forced_timeout; int max_sleep_period; u16 listen_interval; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e13fb3a62239..b575a5066219 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1404,11 +1404,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, return -EOPNOTSUPP; if (enabled == sdata->u.mgd.powersave && - timeout == conf->dynamic_ps_timeout) + timeout == conf->dynamic_ps_forced_timeout) return 0; sdata->u.mgd.powersave = enabled; - conf->dynamic_ps_timeout = timeout; + conf->dynamic_ps_forced_timeout = timeout; /* no change, but if automatic follow powersave */ mutex_lock(&sdata->u.mgd.mtx); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4afe851cf8dc..ebcca0eaf1dc 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -569,6 +569,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.conf.listen_interval = local->hw.max_listen_interval; + local->hw.conf.dynamic_ps_forced_timeout = -1; + result = sta_info_start(local); if (result < 0) goto fail_sta_info; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d811e3fa1d75..2d1a2bef366d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -475,6 +475,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) { struct ieee80211_sub_if_data *sdata, *found = NULL; int count = 0; + int timeout; if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { local->ps_sdata = NULL; @@ -508,6 +509,26 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) beaconint_us = ieee80211_tu_to_usec( found->vif.bss_conf.beacon_int); + timeout = local->hw.conf.dynamic_ps_forced_timeout; + if (timeout < 0) { + /* + * The 2 second value is there for compatibility until + * the PM_QOS_NETWORK_LATENCY is configured with real + * values. + */ + if (latency == 2000000000) + timeout = 100; + else if (latency <= 50000) + timeout = 300; + else if (latency <= 100000) + timeout = 100; + else if (latency <= 500000) + timeout = 50; + else + timeout = 0; + } + local->hw.conf.dynamic_ps_timeout = timeout; + if (beaconint_us > latency) { local->ps_sdata = NULL; } else { -- cgit v1.2.3 From 9043f3b89abebfbfe4b8d64c7b71b9ac0b9eaa0b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Tue, 27 Apr 2010 12:47:41 +0300 Subject: cfg80211: Remove default dynamic PS timeout value Now that the mac80211 is choosing dynamic ps timeouts based on the ps-qos network latency configuration, configure a default value of -1 as the dynamic ps timeout in cfg80211. This value allows the mac80211 to determine the value to be used. Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 ++ net/wireless/core.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f6b29bf925d0..7d10c0182f53 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1020,6 +1020,8 @@ struct cfg80211_pmksa { * RSN IE. It allows for faster roaming between WPA2 BSSIDs. * @del_pmksa: Delete a cached PMKID. * @flush_pmksa: Flush all cached PMKIDs. + * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 + * allows the driver to adjust the dynamic ps timeout value. * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. * */ diff --git a/net/wireless/core.c b/net/wireless/core.c index 7fdb9409ad2a..40cbbbfbccbf 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -704,7 +704,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, wdev->ps = true; else wdev->ps = false; - wdev->ps_timeout = 100; + /* allow mac80211 to determine the timeout */ + wdev->ps_timeout = -1; if (rdev->ops->set_power_mgmt) if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, -- cgit v1.2.3 From a060bbfe4ee95d115e8f9705a66894ac34e2c475 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 27 Apr 2010 11:59:34 +0200 Subject: mac80211: give virtual interface to hw_scan When scanning, it is somewhat important to scan on the correct virtual interface. All drivers that currently implement hw_scan only support a single virtual interface, but that may change and then we'd want to be ready. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 4 +++- drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++- drivers/net/wireless/mac80211_hwsim.c | 1 + drivers/net/wireless/wl12xx/wl1251_main.c | 1 + drivers/net/wireless/wl12xx/wl1271_main.c | 1 + include/net/mac80211.h | 2 +- net/mac80211/driver-ops.h | 5 +++-- net/mac80211/driver-trace.h | 9 ++++++--- net/mac80211/scan.c | 4 ++-- 10 files changed, 21 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 0fb419936dff..7a626d4e100f 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1889,6 +1889,7 @@ static void at76_dwork_hw_scan(struct work_struct *work) } static int at76_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct at76_priv *priv = hw->priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a0cc11ecbe93..727360944859 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -512,7 +512,9 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); -int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); +int iwl_mac_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 1bc1d29f2a07..447c3018296d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -312,7 +312,8 @@ static int iwl_scan_initiate(struct iwl_priv *priv) } int iwl_mac_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req) { struct iwl_priv *priv = hw->priv; int ret; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 79bb8833ddb9..d016933d7573 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -973,6 +973,7 @@ static void hw_scan_done(struct work_struct *work) } static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 390cee7e61a1..4d3be80c220e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -856,6 +856,7 @@ out: } static int wl1251_op_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct wl1251 *wl = hw->priv; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 283d5dade1ae..08ff6447dcd9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1523,6 +1523,7 @@ out: } static int wl1271_op_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct cfg80211_scan_request *req) { struct wl1271 *wl = hw->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c26de6cb12f8..a36e0df5a17c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1657,7 +1657,7 @@ struct ieee80211_ops { struct ieee80211_key_conf *conf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); - int (*hw_scan)(struct ieee80211_hw *hw, + int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); void (*sw_scan_start)(struct ieee80211_hw *hw); void (*sw_scan_complete)(struct ieee80211_hw *hw); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index d1f8a7c2225a..997008e236ff 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -154,14 +154,15 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, } static inline int drv_hw_scan(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req) { int ret; might_sleep(); - ret = local->ops->hw_scan(&local->hw, req); - trace_drv_hw_scan(local, req, ret); + ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); + trace_drv_hw_scan(local, sdata, req, ret); return ret; } diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index e209cb82ff29..ce734b58d07a 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -363,23 +363,26 @@ TRACE_EVENT(drv_update_tkip_key, TRACE_EVENT(drv_hw_scan, TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req, int ret), - TP_ARGS(local, req, ret), + TP_ARGS(local, sdata, req, ret), TP_STRUCT__entry( LOCAL_ENTRY + VIF_ENTRY __field(int, ret) ), TP_fast_assign( LOCAL_ASSIGN; + VIF_ASSIGN; __entry->ret = ret; ), TP_printk( - LOCAL_PR_FMT " ret:%d", - LOCAL_PR_ARG, __entry->ret + LOCAL_PR_FMT VIF_PR_FMT " ret:%d", + LOCAL_PR_ARG,VIF_PR_ARG, __entry->ret ) ); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index eb86a5f6e645..2b1f1f3d6a58 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -410,7 +410,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, if (local->ops->hw_scan) { WARN_ON(!ieee80211_prep_hw_scan(local)); - rc = drv_hw_scan(local, local->hw_scan_req); + rc = drv_hw_scan(local, sdata, local->hw_scan_req); } else rc = ieee80211_start_sw_scan(local); @@ -654,7 +654,7 @@ void ieee80211_scan_work(struct work_struct *work) } if (local->hw_scan_req) { - int rc = drv_hw_scan(local, local->hw_scan_req); + int rc = drv_hw_scan(local, sdata, local->hw_scan_req); mutex_unlock(&local->scan_mtx); if (rc) ieee80211_scan_completed(&local->hw, true); -- cgit v1.2.3 From a2c40249a36d0b4d76d1caf6bf806e4ae5b06e8a Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Tue, 27 Apr 2010 11:15:12 -0700 Subject: mac80211: fix rts threshold check Currently whenever rts thresold is set, every packet will use RTS protection no matter its size exceeds the threshold or not. This is due to a bug in the rts threshold check. if (len > tx->local->hw.wiphy->rts_threshold) { txrc.rts = rts = true; } Basically it is comparing an int (len) and a u32 (rts_threshold), and the variable len is assigned as: len = min_t(int, tx->skb->len + FCS_LEN, tx->local->hw.wiphy->frag_threshold); However, when frag_threshold is "-1", len is always "-1", which is 0xffffffff therefore rts is always set to true. CC: stable@kernel.org Signed-off-by: Shanyu Zhao Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e2aa972d584f..f3841f43249e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -593,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) struct ieee80211_hdr *hdr = (void *)tx->skb->data; struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; - int i, len; + int i; + u32 len; bool inval = false, rts = false, short_preamble = false; struct ieee80211_tx_rate_control txrc; u32 sta_flags; @@ -602,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; - len = min_t(int, tx->skb->len + FCS_LEN, + len = min_t(u32, tx->skb->len + FCS_LEN, tx->local->hw.wiphy->frag_threshold); /* set up the tx rate control struct we give the RC algo */ -- cgit v1.2.3 From f0b058b61711ebf5be94d6865ca7b2c259b71d37 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 28 Apr 2010 15:17:03 +0200 Subject: mac80211: do not wip out old supported rates Use old supported rates, if AP do not provide supported rates information element in a new managment frame. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- net/mac80211/scan.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 2b1f1f3d6a58..a9d40584e383 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -84,7 +84,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, { struct cfg80211_bss *cbss; struct ieee80211_bss *bss; - int clen; + int clen, srlen; s32 signal = 0; if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) @@ -113,23 +113,24 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->dtim_period = tim_ie->dtim_period; } - bss->supp_rates_len = 0; + /* replace old supported rates if we get new values */ + srlen = 0; if (elems->supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; + clen = IEEE80211_MAX_SUPP_RATES; if (clen > elems->supp_rates_len) clen = elems->supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, - clen); - bss->supp_rates_len += clen; + memcpy(bss->supp_rates, elems->supp_rates, clen); + srlen += clen; } if (elems->ext_supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; + clen = IEEE80211_MAX_SUPP_RATES - srlen; if (clen > elems->ext_supp_rates_len) clen = elems->ext_supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], - elems->ext_supp_rates, clen); - bss->supp_rates_len += clen; + memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen); + srlen += clen; } + if (srlen) + bss->supp_rates_len = srlen; bss->wmm_used = elems->wmm_param || elems->wmm_info; bss->uapsd_supported = is_uapsd_supported(elems); -- cgit v1.2.3 From 76f273640134f3eb8257179cd5b3bc6ba5fe4a96 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 28 Apr 2010 17:03:15 +0200 Subject: mac80211: fix supported rates IE if AP doesn't give us it's rates If AP do not provide us supported rates before assiociation, send all rates we are supporting instead of empty information element. v1 -> v2: Add comment. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- net/mac80211/work.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 7bd8670379de..4c7de72c27e7 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -212,15 +212,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[wk->chan->band]; - /* - * Get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode)... - */ - rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, - wk->assoc.supp_rates_len, - sband, &rates); + if (wk->assoc.supp_rates_len) { + /* + * Get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode)... + */ + rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, + wk->assoc.supp_rates_len, + sband, &rates); + } else { + /* + * In case AP not provide any supported rates information + * before association, we send information element(s) with + * all rates that we support. + */ + rates = ~0; + rates_len = sband->n_bitrates; + } skb = alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + /* bit too much but doesn't matter */ -- cgit v1.2.3 From 8fc214ba958648ab111a173f2db7b0e1dfed5b11 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 28 Apr 2010 17:40:43 +0200 Subject: mac80211: notify driver about IBSS status Some drivers (e.g. iwlwifi) need to know and try to figure it out based on other things, but making it explicit is definitely better. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 +++++- net/mac80211/ibss.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a36e0df5a17c..2879c8ef5571 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -145,6 +145,7 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be * enabled/disabled (beaconing modes) * @BSS_CHANGED_CQM: Connection quality monitor config changed + * @BSS_CHANGED_IBSS: IBSS join status changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -158,6 +159,7 @@ enum ieee80211_bss_change { BSS_CHANGED_BEACON = 1<<8, BSS_CHANGED_BEACON_ENABLED = 1<<9, BSS_CHANGED_CQM = 1<<10, + BSS_CHANGED_IBSS = 1<<11, }; /** @@ -167,6 +169,8 @@ enum ieee80211_bss_change { * to that BSS) that can change during the lifetime of the BSS. * * @assoc: association status + * @ibss_joined: indicates whether this station is part of an IBSS + * or not * @aid: association ID number, valid only when @assoc is true * @use_cts_prot: use CTS protection * @use_short_preamble: use 802.11b short preamble; @@ -194,7 +198,7 @@ enum ieee80211_bss_change { struct ieee80211_bss_conf { const u8 *bssid; /* association related data */ - bool assoc; + bool assoc, ibss_joined; u16 aid; /* erp related data */ bool use_cts_prot; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 01974c2510a8..a87e309e3b99 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -170,6 +170,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, bss_change |= BSS_CHANGED_BSSID; bss_change |= BSS_CHANGED_BEACON; bss_change |= BSS_CHANGED_BEACON_ENABLED; + bss_change |= BSS_CHANGED_IBSS; + sdata->vif.bss_conf.ibss_joined = true; ieee80211_bss_info_change_notify(sdata, bss_change); ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); @@ -950,7 +952,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) kfree(sdata->u.ibss.ie); skb = sdata->u.ibss.presp; rcu_assign_pointer(sdata->u.ibss.presp, NULL); - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + sdata->vif.bss_conf.ibss_joined = false; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_IBSS); synchronize_rcu(); kfree_skb(skb); -- cgit v1.2.3 From 49b5c7f473f1bbcb30275dcaee2c06dfb8ec2279 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 29 Apr 2010 21:34:01 +0200 Subject: mac80211: tell driver about IBSS merge My previous patch "mac80211: notify driver about IBSS status" left a problem -- when we merge with a new BSSID, we never tell the driver that we left the old one. Fix that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net') diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a87e309e3b99..c585fced8584 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -91,6 +91,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) sta_info_flush(sdata->local, sdata); + /* if merging, indicate to driver that we leave the old IBSS */ + if (sdata->vif.bss_conf.ibss_joined) { + sdata->vif.bss_conf.ibss_joined = false; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); + } + memcpy(ifibss->bssid, bssid, ETH_ALEN); sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; -- cgit v1.2.3 From f5c044e53a6b319776c7140b22fee9be3bc1f758 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 30 Apr 2010 15:37:00 -0400 Subject: mac80211: remove deprecated noise field from ieee80211_rx_status Also remove associated IEEE80211_HW_NOISE_DBM from ieee80211_hw_flags. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 3 +-- drivers/net/wireless/ath/ath5k/base.c | 3 +-- drivers/net/wireless/b43/main.c | 3 +-- drivers/net/wireless/b43legacy/main.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - drivers/net/wireless/mwl8k.c | 4 ++-- drivers/net/wireless/p54/main.c | 3 +-- drivers/net/wireless/wl12xx/wl1251_main.c | 1 - drivers/net/wireless/wl12xx/wl1271_main.c | 1 - include/net/mac80211.h | 8 +------- net/mac80211/rx.c | 2 -- 12 files changed, 8 insertions(+), 25 deletions(-) (limited to 'net') diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index cfc6a35a2c6a..dfcc055a827f 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2550,8 +2550,7 @@ void *ar9170_alloc(size_t priv_size) BIT(NL80211_IFTYPE_ADHOC); ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; if (modparam_ht) { ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 1f3e5b0986c7..feb7b9ea80ab 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -547,8 +547,7 @@ ath5k_pci_probe(struct pci_dev *pdev, SET_IEEE80211_DEV(hw, &pdev->dev); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 14cf3bd7ea51..e0575591828c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4904,8 +4904,7 @@ static int b43_wireless_init(struct ssb_device *dev) /* fill hw info */ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1d070be5a678..b2df432d3c63 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3768,8 +3768,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) /* fill hw info */ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_SIGNAL_DBM; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c22d3d8c440c..0cd338631592 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2653,7 +2653,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SPECTRUM_MGMT; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e7263ed693c4..c9da39d7c414 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3872,7 +3872,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_SPECTRUM_MGMT; if (!priv->cfg->broken_powersave) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9af6c9454605..a90bb6d2e26b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3981,8 +3981,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->queues = MWL8K_TX_QUEUES; - /* Set rssi and noise values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + /* Set rssi values to dBm */ + hw->flags |= IEEE80211_HW_SIGNAL_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); hw->sta_data_size = sizeof(struct mwl8k_sta); diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 36f4c820ad01..10a4b16f31ce 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -545,8 +545,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_BEACON_FILTER | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_REPORTS_TX_ACK_STATUS; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4d3be80c220e..b70621f63cda 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1291,7 +1291,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->channel_change_time = 10000; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_UAPSD; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index a794d5ed8c60..b0837255de6f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2275,7 +2275,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_UAPSD | diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2879c8ef5571..00502b1a9e38 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -560,7 +560,6 @@ enum mac80211_rx_flags { * @signal: signal strength when receiving this frame, either in dBm, in dB or * unspecified depending on the hardware capabilities flags * @IEEE80211_HW_SIGNAL_* - * @noise: noise when receiving this frame, in dBm (DEPRECATED). * @antenna: antenna used * @rate_idx: index of data rate into band's supported rates or MCS index if * HT rates are use (RX_FLAG_HT) @@ -571,7 +570,6 @@ struct ieee80211_rx_status { enum ieee80211_band band; int freq; int signal; - int noise __deprecated; int antenna; int rate_idx; int flag; @@ -934,10 +932,6 @@ enum ieee80211_tkip_key_type { * one milliwatt. This is the preferred method since it is standardized * between different devices. @max_signal does not need to be set. * - * @IEEE80211_HW_NOISE_DBM: - * Hardware can provide noise (radio interference) values in units dBm, - * decibel difference from one milliwatt. - * * @IEEE80211_HW_SPECTRUM_MGMT: * Hardware supports spectrum management defined in 802.11h * Measurement, Channel Switch, Quieting, TPC @@ -1001,7 +995,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, IEEE80211_HW_SIGNAL_DBM = 1<<6, - IEEE80211_HW_NOISE_DBM = 1<<7, + /* use this hole */ IEEE80211_HW_SPECTRUM_MGMT = 1<<8, IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, IEEE80211_HW_SUPPORTS_PS = 1<<10, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8ee7db193269..e4f325f68fd3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -80,8 +80,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, len += 8; if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) len += 1; - if (local->hw.flags & IEEE80211_HW_NOISE_DBM) - len += 1; if (len & 1) /* padding for RX_FLAGS if necessary */ len++; -- cgit v1.2.3 From f7c65594f7148b778f41d591a701e94bb22428e4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 13:48:36 +0200 Subject: mac80211: fix ieee80211_find_sta[_by_hw] Both of these functions can currently return a station pointer that, to the driver, is invalid (in IBSS mode only) because adding the station failed. Check for that, and also make ieee80211_find_sta() properly use the per interface station search. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3de7a2260d65..730197591ab5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -855,8 +855,12 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, struct sta_info *sta, *nxt; /* Just return a random station ... first in list ... */ - for_each_sta_info(hw_to_local(hw), addr, sta, nxt) + for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { + if (!sta->uploaded) + return NULL; return &sta->sta; + } + return NULL; } EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); @@ -864,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, const u8 *addr) { - struct ieee80211_sub_if_data *sdata; + struct sta_info *sta; if (!vif) return NULL; - sdata = vif_to_sdata(vif); + sta = sta_info_get_bss(vif_to_sdata(vif), addr); + if (!sta) + return NULL; + + if (!sta->uploaded) + return NULL; - return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); + return &sta->sta; } EXPORT_SYMBOL(ieee80211_find_sta); -- cgit v1.2.3 From a75b4363eaafa99d909da4f1192322a78b074c73 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 1 May 2010 18:53:51 +0200 Subject: mac80211: allow controlling aggregation manually This allows enabling TX and disabling both TX and RX aggregation sessions manually in debugfs. It is very useful for debugging session initiation and teardown problems since with this you don't have to force a lot of traffic to get aggregation and thus have less data to analyse. Also, to debug mac80211 code itself, make hwsim "support" aggregation sessions. It will still just transfer the frame, but go through the setup and teardown handshakes. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 3 +- net/mac80211/debugfs_sta.c | 65 ++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d016933d7573..ebcf43904291 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1299,7 +1299,8 @@ static int __init init_mac80211_hwsim(void) hw->flags = IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_STATIC_SMPS | - IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; + IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | + IEEE80211_HW_AMPDU_AGGREGATION; /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6bc9b07c3eda..e763f1529ddb 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -39,6 +39,13 @@ static const struct file_operations sta_ ##name## _ops = { \ .open = mac80211_open_file_generic, \ } +#define STA_OPS_RW(name) \ +static const struct file_operations sta_ ##name## _ops = { \ + .read = sta_##name##_read, \ + .write = sta_##name##_write, \ + .open = mac80211_open_file_generic, \ +} + #define STA_FILE(name, field, format) \ STA_READ_##format(name, field) \ STA_OPS(name) @@ -156,7 +163,63 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); } -STA_OPS(agg_status); + +static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + char _buf[12], *buf = _buf; + struct sta_info *sta = file->private_data; + bool start, tx; + unsigned long tid; + int ret; + + if (count > sizeof(_buf)) + return -EINVAL; + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[sizeof(_buf) - 1] = '\0'; + + if (strncmp(buf, "tx ", 3) == 0) { + buf += 3; + tx = true; + } else if (strncmp(buf, "rx ", 3) == 0) { + buf += 3; + tx = false; + } else + return -EINVAL; + + if (strncmp(buf, "start ", 6) == 0) { + buf += 6; + start = true; + if (!tx) + return -EINVAL; + } else if (strncmp(buf, "stop ", 5) == 0) { + buf += 5; + start = false; + } else + return -EINVAL; + + tid = simple_strtoul(buf, NULL, 0); + + if (tid >= STA_TID_NUM) + return -EINVAL; + + if (tx) { + if (start) + ret = ieee80211_start_tx_ba_session(&sta->sta, tid); + else + ret = ieee80211_stop_tx_ba_session(&sta->sta, tid, + WLAN_BACK_RECIPIENT); + } else { + __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); + ret = 0; + } + + return ret ?: count; +} +STA_OPS_RW(agg_status); static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) -- cgit v1.2.3 From be4a4b6a5d2f76393f545a2545fbaa1b65577e13 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 May 2010 08:49:48 +0200 Subject: mac80211: improve IBSS scanning When IBSS is fixed to a frequency, it can still scan to try to find the right BSSID. This makes sense if the BSSID isn't also fixed, but it need not scan all channels -- just one is sufficient. Make it do that by moving the scan setup code to ieee80211_request_internal_scan() and include a channel variable setting. Note that this can be further improved to start the IBSS right away if both frequency and BSSID are fixed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 9 ++++++--- net/mac80211/ieee80211_i.h | 3 ++- net/mac80211/main.c | 17 +---------------- net/mac80211/scan.c | 28 +++++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 21 deletions(-) (limited to 'net') diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c585fced8584..ba752362b2b2 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -488,7 +488,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->name); - ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); + ieee80211_request_internal_scan(sdata, + ifibss->ssid, ifibss->ssid_len, + ifibss->fixed_channel ? ifibss->channel : NULL); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -595,8 +597,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->name); - ieee80211_request_internal_scan(sdata, ifibss->ssid, - ifibss->ssid_len); + ieee80211_request_internal_scan(sdata, + ifibss->ssid, ifibss->ssid_len, + ifibss->fixed_channel ? ifibss->channel : NULL); } else { int interval = IEEE80211_SCAN_INTERVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4e73660ebe99..c8077a3647c6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1020,7 +1020,8 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len); + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ebcca0eaf1dc..353b6b42d9c5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -439,7 +439,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); int result; enum ieee80211_band band; - int channels, i, j, max_bitrates; + int channels, max_bitrates; bool supp_ht; static const u32 cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, @@ -605,21 +605,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_led_init(local); - /* alloc internal scan request */ - i = 0; - local->int_scan_req->ssids = &local->scan_ssid; - local->int_scan_req->n_ssids = 1; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!hw->wiphy->bands[band]) - continue; - for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { - local->int_scan_req->channels[i] = - &hw->wiphy->bands[band]->channels[j]; - i++; - } - } - local->int_scan_req->n_channels = i; - local->network_latency_notifier.notifier_call = ieee80211_max_network_latency; result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a9d40584e383..414651217b49 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -728,10 +728,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, } int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len) + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan) { struct ieee80211_local *local = sdata->local; int ret = -EBUSY; + enum nl80211_band band; mutex_lock(&local->scan_mtx); @@ -739,6 +741,30 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, if (local->scan_req) goto unlock; + /* fill internal scan request */ + if (!chan) { + int i, nchan = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; + for (i = 0; + i < local->hw.wiphy->bands[band]->n_channels; + i++) { + local->int_scan_req->channels[nchan] = + &local->hw.wiphy->bands[band]->channels[i]; + nchan++; + } + } + + local->int_scan_req->n_channels = nchan; + } else { + local->int_scan_req->channels[0] = chan; + local->int_scan_req->n_channels = 1; + } + + local->int_scan_req->ssids = &local->scan_ssid; + local->int_scan_req->n_ssids = 1; memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); local->int_scan_req->ssids[0].ssid_len = ssid_len; -- cgit v1.2.3 From adfba3c7c026a6a5560d2a43fefc9b198cb74462 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 May 2010 15:33:55 +0200 Subject: mac80211: use fixed channel in ibss join when appropriate "mac80211: improve IBSS scanning" was missing a hunk. This adds that hunk as originally intended. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net') diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ba752362b2b2..d5855ae387e8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -907,6 +907,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.channel = params->channel; sdata->u.ibss.fixed_channel = params->channel_fixed; + /* fix ourselves to that channel now already */ + if (params->channel_fixed) { + sdata->local->oper_channel = params->channel; + sdata->local->oper_channel_type = NL80211_CHAN_NO_HT; + } + if (params->ie) { sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, GFP_KERNEL); -- cgit v1.2.3