diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-05-16 14:55:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-16 19:32:19 -0400 |
commit | e00cf3b9eb7839b952e434a75bff6b99e47337ac (patch) | |
tree | ef583ab8ac09bf703026650d4bc7777e6a3864d3 /net/mac80211 | |
parent | 1a8218e96271790a07dd7065a2ef173e0f67e328 (diff) | |
parent | 3b8ab88acaceb505aa06ef3bbf3a73b92470ae78 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
net/mac80211/sta_info.h
Diffstat (limited to 'net/mac80211')
29 files changed, 835 insertions, 422 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 0c9d0c07eae..9c0d76cdca9 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -63,7 +63,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, lockdep_assert_held(&sta->ampdu_mlme.mtx); - tid_rx = sta->ampdu_mlme.tid_rx[tid]; + tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], + lockdep_is_held(&sta->ampdu_mlme.mtx)); if (!tid_rx) return; diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 63d852cb4ca..cd5125f77cc 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -136,6 +136,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 ieee80211_tx_skb(sdata, skb); } +void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, + struct tid_ampdu_tx *tid_tx) +{ + lockdep_assert_held(&sta->ampdu_mlme.mtx); + lockdep_assert_held(&sta->lock); + rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); +} + static void kfree_tid_tx(struct rcu_head *rcu_head) { struct tid_ampdu_tx *tid_tx = @@ -149,19 +157,22 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, bool tx) { struct ieee80211_local *local = sta->local; - struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; + struct tid_ampdu_tx *tid_tx; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); - if (!tid_tx) - return -ENOENT; - spin_lock_bh(&sta->lock); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + if (!tid_tx) { + spin_unlock_bh(&sta->lock); + return -ENOENT; + } + if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* not even started yet! */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); spin_unlock_bh(&sta->lock); call_rcu(&tid_tx->rcu_head, kfree_tid_tx); return 0; @@ -283,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) { - struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; + struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; u16 start_seq_num; int ret; - lockdep_assert_held(&sta->ampdu_mlme.mtx); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* * While we're asking the driver about the aggregation, @@ -318,7 +329,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); spin_unlock_bh(&sta->lock); ieee80211_wake_queue_agg(local, tid); @@ -396,9 +407,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, goto err_unlock_sta; } - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* check if the TID is not in aggregation flow already */ - if (tid_tx) { + if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA request denied - session is not " "idle on tid %u\n", tid); @@ -433,8 +444,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, sta->ampdu_mlme.dialog_token_allocator++; tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; - /* finally, assign it to the array */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); + /* + * Finally, assign it to the start array; the work item will + * collect it and move it to the normal array. + */ + sta->ampdu_mlme.tid_start_tx[tid] = tid_tx; ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); @@ -480,16 +494,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { + struct tid_ampdu_tx *tid_tx; + lockdep_assert_held(&sta->ampdu_mlme.mtx); + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); #endif drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, - sta->ampdu_mlme.tid_tx[tid]->buf_size); + &sta->sta, tid, NULL, tid_tx->buf_size); /* * synchronize with TX path, while splicing the TX path @@ -497,13 +514,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, */ spin_lock_bh(&sta->lock); - ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); + ieee80211_agg_splice_packets(local, tid_tx, tid); /* * Now mark as operational. This will be visible * in the TX path, and lets it go lock-free in * the common case. */ - set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); + set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); ieee80211_agg_splice_finish(local, tid); spin_unlock_bh(&sta->lock); @@ -537,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) } mutex_lock(&sta->ampdu_mlme.mtx); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (WARN_ON(!tid_tx)) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -615,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) return -EINVAL; spin_lock_bh(&sta->lock); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx) { ret = -ENOENT; @@ -671,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) mutex_lock(&sta->ampdu_mlme.mtx); spin_lock_bh(&sta->lock); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -697,7 +714,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) ieee80211_agg_splice_packets(local, tid_tx, tid); /* future packets must not find the tid_tx struct any more */ - rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); + ieee80211_assign_tid_tx(sta, tid, NULL); ieee80211_agg_splice_finish(local, tid); @@ -752,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, mutex_lock(&sta->ampdu_mlme.mtx); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (!tid_tx) goto out; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 12d52cec951..be70c70d3f5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, mutex_lock(&sdata->local->sta_mtx); if (mac_addr) { - sta = sta_info_get_bss(sdata, mac_addr); + if (ieee80211_vif_is_mesh(&sdata->vif)) + sta = sta_info_get(sdata, mac_addr); + else + sta = sta_info_get_bss(sdata, mac_addr); if (!sta) { ieee80211_key_free(sdata->local, key); err = -ENOENT; @@ -157,13 +160,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, bool pairwise, const u8 *mac_addr) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; + struct ieee80211_key *key = NULL; int ret; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - mutex_lock(&sdata->local->sta_mtx); + mutex_lock(&local->sta_mtx); + mutex_lock(&local->key_mtx); if (mac_addr) { ret = -ENOENT; @@ -172,33 +176,24 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, if (!sta) goto out_unlock; - if (pairwise) { - if (sta->ptk) { - ieee80211_key_free(sdata->local, sta->ptk); - ret = 0; - } - } else { - if (sta->gtk[key_idx]) { - ieee80211_key_free(sdata->local, - sta->gtk[key_idx]); - ret = 0; - } - } - - goto out_unlock; - } + if (pairwise) + key = key_mtx_dereference(local, sta->ptk); + else + key = key_mtx_dereference(local, sta->gtk[key_idx]); + } else + key = key_mtx_dereference(local, sdata->keys[key_idx]); - if (!sdata->keys[key_idx]) { + if (!key) { ret = -ENOENT; goto out_unlock; } - ieee80211_key_free(sdata->local, sdata->keys[key_idx]); - WARN_ON(sdata->keys[key_idx]); + __ieee80211_key_free(key); ret = 0; out_unlock: - mutex_unlock(&sdata->local->sta_mtx); + mutex_unlock(&local->key_mtx); + mutex_unlock(&local->sta_mtx); return ret; } @@ -228,11 +223,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, goto out; if (pairwise) - key = sta->ptk; + key = rcu_dereference(sta->ptk); else if (key_idx < NUM_DEFAULT_KEYS) - key = sta->gtk[key_idx]; + key = rcu_dereference(sta->gtk[key_idx]); } else - key = sdata->keys[key_idx]; + key = rcu_dereference(sdata->keys[key_idx]); if (!key) goto out; @@ -468,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, int size; int err = -EINVAL; - old = sdata->u.ap.beacon; + old = rtnl_dereference(sdata->u.ap.beacon); /* head must not be zero-length */ if (params->head && !params->head_len) @@ -563,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (old) return -EALREADY; @@ -579,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (!old) return -ENOENT; @@ -594,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) sdata = IEEE80211_DEV_TO_SUB_IF(dev); - old = sdata->u.ap.beacon; - + old = rtnl_dereference(sdata->u.ap.beacon); if (!old) return -ENOENT; @@ -734,15 +726,29 @@ static void sta_apply_parameters(struct ieee80211_local *local, params->ht_capa, &sta->sta.ht_cap); - if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { - switch (params->plink_action) { - case PLINK_ACTION_OPEN: - mesh_plink_open(sta); - break; - case PLINK_ACTION_BLOCK: - mesh_plink_block(sta); - break; - } + if (ieee80211_vif_is_mesh(&sdata->vif)) { +#ifdef CONFIG_MAC80211_MESH + if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) + switch (params->plink_state) { + case NL80211_PLINK_LISTEN: + case NL80211_PLINK_ESTAB: + case NL80211_PLINK_BLOCKED: + sta->plink_state = params->plink_state; + break; + default: + /* nothing */ + break; + } + else + switch (params->plink_action) { + case PLINK_ACTION_OPEN: + mesh_plink_open(sta); + break; + case PLINK_ACTION_BLOCK: + mesh_plink_block(sta); + break; + } +#endif } } @@ -943,8 +949,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo) { - if (mpath->next_hop) - memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); + struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); + + if (next_hop_sta) + memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN); else memset(next_hop, 0, ETH_ALEN); @@ -1064,7 +1072,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; - ifmsh->is_secure = setup->is_secure; + ifmsh->security = IEEE80211_MESH_SEC_NONE; + if (setup->is_authenticated) + ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; + if (setup->is_secure) + ifmsh->security |= IEEE80211_MESH_SEC_SECURED; return 0; } @@ -1297,9 +1309,10 @@ static int ieee80211_set_channel(struct wiphy *wiphy, } #ifdef CONFIG_PM -static int ieee80211_suspend(struct wiphy *wiphy) +static int ieee80211_suspend(struct wiphy *wiphy, + struct cfg80211_wowlan *wowlan) { - return __ieee80211_suspend(wiphy_priv(wiphy)); + return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); } static int ieee80211_resume(struct wiphy *wiphy) @@ -1342,6 +1355,30 @@ static int ieee80211_scan(struct wiphy *wiphy, return ieee80211_request_scan(sdata, req); } +static int +ieee80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *req) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (!sdata->local->ops->sched_scan_start) + return -EOPNOTSUPP; + + return ieee80211_request_sched_scan_start(sdata, req); +} + +static int +ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (!sdata->local->ops->sched_scan_stop) + return -EOPNOTSUPP; + + return ieee80211_request_sched_scan_stop(sdata); +} + static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_auth_request *req) { @@ -2083,6 +2120,8 @@ struct cfg80211_ops mac80211_config_ops = { .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, + .sched_scan_start = ieee80211_sched_scan_start, + .sched_scan_stop = ieee80211_sched_scan_stop, .auth = ieee80211_auth, .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 0a602dbfdb2..186e02f7cc3 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -135,7 +135,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, struct ieee80211_local *local = file->private_data; rtnl_lock(); - __ieee80211_suspend(&local->hw); + __ieee80211_suspend(&local->hw, NULL); __ieee80211_resume(&local->hw); rtnl_unlock(); diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index f7ef3477c24..33c58b85c91 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -241,16 +241,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) if (!key->debugfs.dir) return; - rcu_read_lock(); - sta = rcu_dereference(key->sta); - if (sta) + sta = key->sta; + if (sta) { sprintf(buf, "../../stations/%pM", sta->sta.addr); - rcu_read_unlock(); - - /* using sta as a boolean is fine outside RCU lock */ - if (sta) key->debugfs.stalink = debugfs_create_symlink("station", key->debugfs.dir, buf); + } DEBUGFS_ADD(keylen); DEBUGFS_ADD(flags); @@ -286,7 +282,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&sdata->local->key_mtx); if (sdata->default_unicast_key) { - key = sdata->default_unicast_key; + key = key_mtx_dereference(sdata->local, + sdata->default_unicast_key); sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_unicast_key = debugfs_create_symlink("default_unicast_key", @@ -297,7 +294,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) } if (sdata->default_multicast_key) { - key = sdata->default_multicast_key; + key = key_mtx_dereference(sdata->local, + sdata->default_multicast_key); sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_multicast_key = debugfs_create_symlink("default_multicast_key", @@ -316,9 +314,8 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) if (!sdata->debugfs.dir) return; - /* this is running under the key lock */ - - key = sdata->default_mgmt_key; + key = key_mtx_dereference(sdata->local, + sdata->default_mgmt_key); if (key) { sprintf(buf, "../keys/%d", key->debugfs.cnt); sdata->debugfs.default_mgmt_key = diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2ddb56e5b51..eebf7a67daf 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -41,6 +41,33 @@ static inline void drv_stop(struct ieee80211_local *local) local->started = false; } +#ifdef CONFIG_PM +static inline int drv_suspend(struct ieee80211_local *local, + struct cfg80211_wowlan *wowlan) +{ + int ret; + + might_sleep(); + + trace_drv_suspend(local); + ret = local->ops->suspend(&local->hw, wowlan); + trace_drv_return_int(local, ret); + return ret; +} + +static inline int drv_resume(struct ieee80211_local *local) +{ + int ret; + + might_sleep(); + + trace_drv_resume(local); + ret = local->ops->resume(&local->hw); + trace_drv_return_int(local, ret); + return ret; +} +#endif + static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_vif *vif) { @@ -185,12 +212,39 @@ static inline int drv_hw_scan(struct ieee80211_local *local, might_sleep(); - trace_drv_hw_scan(local, sdata, req); + trace_drv_hw_scan(local, sdata); ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); trace_drv_return_int(local, ret); return ret; } +static inline int +drv_sched_scan_start(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct cfg80211_sched_scan_request *req, + struct ieee80211_sched_scan_ies *ies) +{ + int ret; + + might_sleep(); + + trace_drv_sched_scan_start(local, sdata); + ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, + req, ies); + trace_drv_return_int(local, ret); + return ret; +} + +static inline void drv_sched_scan_stop(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + might_sleep(); + + trace_drv_sched_scan_stop(local, sdata); + local->ops->sched_scan_stop(&local->hw, &sdata->vif); + trace_drv_return_void(local); +} + static inline void drv_sw_scan_start(struct ieee80211_local *local) { might_sleep(); diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 191e834ec46..ed9edcbd9aa 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -55,6 +55,70 @@ DECLARE_EVENT_CLASS(local_only_evt, TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) ); +DECLARE_EVENT_CLASS(local_sdata_addr_evt, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + __array(char, addr, 6) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + memcpy(__entry->addr, sdata->vif.addr, 6); + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", + LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr + ) +); + +DECLARE_EVENT_CLASS(local_u32_evt, + TP_PROTO(struct ieee80211_local *local, u32 value), + TP_ARGS(local, value), + + TP_STRUCT__entry( + LOCAL_ENTRY + __field(u32, value) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + __entry->value = value; + ), + + TP_printk( + LOCAL_PR_FMT " value:%d", + LOCAL_PR_ARG, __entry->value + ) +); + +DECLARE_EVENT_CLASS(local_sdata_evt, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG + ) +); + DEFINE_EVENT(local_only_evt, drv_return_void, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) @@ -108,33 +172,25 @@ DEFINE_EVENT(local_only_evt, drv_start, TP_ARGS(local) ); +DEFINE_EVENT(local_only_evt, drv_suspend, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) +); + +DEFINE_EVENT(local_only_evt, drv_resume, + TP_PROTO(struct ieee80211_local *local), + TP_ARGS(local) +); + DEFINE_EVENT(local_only_evt, drv_stop, TP_PROTO(struct ieee80211_local *local), TP_ARGS(local) ); -TRACE_EVENT(drv_add_interface, +DEFINE_EVENT(local_sdata_addr_evt, drv_add_interface, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - - TP_ARGS(local, sdata), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - __array(char, addr, 6) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - memcpy(__entry->addr, sdata->vif.addr, 6); - ), - - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr - ) + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_change_interface, @@ -165,27 +221,10 @@ TRACE_EVENT(drv_change_interface, ) ); -TRACE_EVENT(drv_remove_interface, - TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - - TP_ARGS(local, sdata), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - __array(char, addr, 6) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - memcpy(__entry->addr, sdata->vif.addr, 6); - ), - - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", - LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr - ) +DEFINE_EVENT(local_sdata_addr_evt, drv_remove_interface, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); TRACE_EVENT(drv_config, @@ -415,27 +454,22 @@ TRACE_EVENT(drv_update_tkip_key, ) ); -TRACE_EVENT(drv_hw_scan, +DEFINE_EVENT(local_sdata_evt, drv_hw_scan, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req), - - TP_ARGS(local, sdata, req), - - TP_STRUCT__entry( - LOCAL_ENTRY - VIF_ENTRY - ), + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) +); - TP_fast_assign( - LOCAL_ASSIGN; - VIF_ASSIGN; - ), +DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) +); - TP_printk( - LOCAL_PR_FMT VIF_PR_FMT, - LOCAL_PR_ARG,VIF_PR_ARG - ) +DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata), + TP_ARGS(local, sdata) ); DEFINE_EVENT(local_only_evt, drv_sw_scan_start, @@ -504,46 +538,14 @@ TRACE_EVENT(drv_get_tkip_seq, ) ); -TRACE_EVENT(drv_set_frag_threshold, +DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold, TP_PROTO(struct ieee80211_local *local, u32 value), - - TP_ARGS(local, value), - - TP_STRUCT__entry( - LOCAL_ENTRY - __field(u32, value) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - __entry->value = value; - ), - - TP_printk( - LOCAL_PR_FMT " value:%d", - LOCAL_PR_ARG, __entry->value - ) + TP_ARGS(local, value) ); -TRACE_EVENT(drv_set_rts_threshold, +DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold, TP_PROTO(struct ieee80211_local *local, u32 value), - - TP_ARGS(local, value), - - TP_STRUCT__entry( - LOCAL_ENTRY - __field(u32, value) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - __entry->value = value; - ), - - TP_printk( - LOCAL_PR_FMT " value:%d", - LOCAL_PR_ARG, __entry->value - ) + TP_ARGS(local, value) ); TRACE_EVENT(drv_set_coverage_class, @@ -1194,6 +1196,42 @@ TRACE_EVENT(api_scan_completed, ) ); +TRACE_EVENT(api_sched_scan_results, + TP_PROTO(struct ieee80211_local *local), + + TP_ARGS(local), + + TP_STRUCT__entry( + LOCAL_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT, LOCAL_PR_ARG + ) +); + +TRACE_EVENT(api_sched_scan_stopped, + TP_PROTO(struct ieee80211_local *local), + + TP_ARGS(local), + + TP_STRUCT__entry( + LOCAL_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT, LOCAL_PR_ARG + ) +); + TRACE_EVENT(api_sta_block_awake, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta, bool block), diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index b9e4b9bd217..591add22bcc 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -140,14 +140,29 @@ void ieee80211_ba_session_work(struct work_struct *work) sta, tid, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_TIMEOUT, true); - tid_tx = sta->ampdu_mlme.tid_tx[tid]; - if (!tid_tx) - continue; + tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; + if (tid_tx) { + /* + * Assign it over to the normal tid_tx array + * where it "goes live". + */ + spin_lock_bh(&sta->lock); + + sta->ampdu_mlme.tid_start_tx[tid] = NULL; + /* could there be a race? */ + if (sta->ampdu_mlme.tid_tx[tid]) + kfree(tid_tx); + else + ieee80211_assign_tid_tx(sta, tid, tid_tx); + spin_unlock_bh(&sta->lock); - if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) ieee80211_tx_ba_session_handle_start(sta, tid); - else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, - &tid_tx->state)) + continue; + } + + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + if (tid_tx && |