aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/debugfs_netdev.c10
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mesh.c3
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/mlme.c13
-rw-r--r--net/mac80211/rx.c5
-rw-r--r--net/mac80211/sta_info.c21
-rw-r--r--net/mac80211/tx.c6
-rw-r--r--net/mac80211/util.c18
9 files changed, 56 insertions, 28 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ee61a9f6fabc..623e6644b80c 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -48,20 +48,24 @@ static ssize_t ieee80211_if_write(
48 ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) 48 ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
49{ 49{
50 u8 *buf; 50 u8 *buf;
51 ssize_t ret = -ENODEV; 51 ssize_t ret;
52 52
53 buf = kzalloc(count, GFP_KERNEL); 53 buf = kmalloc(count, GFP_KERNEL);
54 if (!buf) 54 if (!buf)
55 return -ENOMEM; 55 return -ENOMEM;
56 56
57 ret = -EFAULT;
57 if (copy_from_user(buf, userbuf, count)) 58 if (copy_from_user(buf, userbuf, count))
58 return -EFAULT; 59 goto freebuf;
59 60
61 ret = -ENODEV;
60 rtnl_lock(); 62 rtnl_lock();
61 if (sdata->dev->reg_state == NETREG_REGISTERED) 63 if (sdata->dev->reg_state == NETREG_REGISTERED)
62 ret = (*write)(sdata, buf, count); 64 ret = (*write)(sdata, buf, count);
63 rtnl_unlock(); 65 rtnl_unlock();
64 66
67freebuf:
68 kfree(buf);
65 return ret; 69 return ret;
66} 70}
67 71
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 06c33b68d8e5..b887e484ae04 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
225 switch (sdata->vif.type) { 225 switch (sdata->vif.type) {
226 case NL80211_IFTYPE_AP: 226 case NL80211_IFTYPE_AP:
227 sdata->vif.bss_conf.enable_beacon = 227 sdata->vif.bss_conf.enable_beacon =
228 !!rcu_dereference(sdata->u.ap.beacon); 228 !!sdata->u.ap.beacon;
229 break; 229 break;
230 case NL80211_IFTYPE_ADHOC: 230 case NL80211_IFTYPE_ADHOC:
231 sdata->vif.bss_conf.enable_beacon = 231 sdata->vif.bss_conf.enable_beacon =
232 !!rcu_dereference(sdata->u.ibss.presp); 232 !!sdata->u.ibss.presp;
233 break; 233 break;
234 case NL80211_IFTYPE_MESH_POINT: 234 case NL80211_IFTYPE_MESH_POINT:
235 sdata->vif.bss_conf.enable_beacon = true; 235 sdata->vif.bss_conf.enable_beacon = true;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 61080c5fad50..7a6bebce7f2f 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -749,9 +749,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
749 749
750 switch (fc & IEEE80211_FCTL_STYPE) { 750 switch (fc & IEEE80211_FCTL_STYPE) {
751 case IEEE80211_STYPE_ACTION: 751 case IEEE80211_STYPE_ACTION:
752 if (skb->len < IEEE80211_MIN_ACTION_SIZE)
753 return RX_DROP_MONITOR;
754 /* fall through */
755 case IEEE80211_STYPE_PROBE_RESP: 752 case IEEE80211_STYPE_PROBE_RESP:
756 case IEEE80211_STYPE_BEACON: 753 case IEEE80211_STYPE_BEACON:
757 skb_queue_tail(&ifmsh->skb_queue, skb); 754 skb_queue_tail(&ifmsh->skb_queue, skb);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index ce84237ebad3..ccff6133e19a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -391,7 +391,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
391 if (SN_GT(mpath->sn, orig_sn) || 391 if (SN_GT(mpath->sn, orig_sn) ||
392 (mpath->sn == orig_sn && 392 (mpath->sn == orig_sn &&
393 action == MPATH_PREQ && 393 action == MPATH_PREQ &&
394 new_metric > mpath->metric)) { 394 new_metric >= mpath->metric)) {
395 process = false; 395 process = false;
396 fresh_info = false; 396 fresh_info = false;
397 } 397 }
@@ -611,7 +611,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
611 611
612 mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, 612 mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
613 cpu_to_le32(orig_sn), 0, target_addr, 613 cpu_to_le32(orig_sn), 0, target_addr,
614 cpu_to_le32(target_sn), mpath->next_hop->sta.addr, hopcount, 614 cpu_to_le32(target_sn), next_hop, hopcount,
615 ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), 615 ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
616 0, sdata); 616 0, sdata);
617 rcu_read_unlock(); 617 rcu_read_unlock();
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 4c189d0be4a3..461167dfa42c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -447,10 +447,12 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
447 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) 447 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
448 ieee80211_send_nullfunc(local, sdata, 1); 448 ieee80211_send_nullfunc(local, sdata, 1);
449 449
450 if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { 450 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
451 conf->flags |= IEEE80211_CONF_PS; 451 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
452 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 452 return;
453 } 453
454 conf->flags |= IEEE80211_CONF_PS;
455 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
454 } 456 }
455} 457}
456 458
@@ -569,7 +571,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
569 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) 571 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))
570 ieee80211_send_nullfunc(local, sdata, 1); 572 ieee80211_send_nullfunc(local, sdata, 1);
571 573
572 if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || 574 if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
575 (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) ||
573 (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { 576 (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
574 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 577 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
575 local->hw.conf.flags |= IEEE80211_CONF_PS; 578 local->hw.conf.flags |= IEEE80211_CONF_PS;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a33f865807f9..c0ad7e879a6e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1994,6 +1994,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1994 goto handled; 1994 goto handled;
1995 } 1995 }
1996 break; 1996 break;
1997 case MESH_PLINK_CATEGORY:
1998 case MESH_PATH_SEL_CATEGORY:
1999 if (ieee80211_vif_is_mesh(&sdata->vif))
2000 return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
2001 break;
1997 } 2002 }
1998 2003
1999 /* 2004 /*
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 5bf044b92dca..4de987cbda1c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
93 struct ieee80211_local *local = sdata->local; 93 struct ieee80211_local *local = sdata->local;
94 struct sta_info *sta; 94 struct sta_info *sta;
95 95
96 sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); 96 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
97 rcu_read_lock_held() ||
98 lockdep_is_held(&local->sta_lock) ||
99 lockdep_is_held(&local->sta_mtx));
97 while (sta) { 100 while (sta) {
98 if (sta->sdata == sdata && 101 if (sta->sdata == sdata &&
99 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 102 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
100 break; 103 break;
101 sta = rcu_dereference(sta->hnext); 104 sta = rcu_dereference_check(sta->hnext,
105 rcu_read_lock_held() ||
106 lockdep_is_held(&local->sta_lock) ||
107 lockdep_is_held(&local->sta_mtx));
102 } 108 }
103 return sta; 109 return sta;
104} 110}
@@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
113 struct ieee80211_local *local = sdata->local; 119 struct ieee80211_local *local = sdata->local;
114 struct sta_info *sta; 120 struct sta_info *sta;
115 121
116 sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); 122 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
123 rcu_read_lock_held() ||
124 lockdep_is_held(&local->sta_lock) ||
125 lockdep_is_held(&local->sta_mtx));
117 while (sta) { 126 while (sta) {
118 if ((sta->sdata == sdata || 127 if ((sta->sdata == sdata ||
119 sta->sdata->bss == sdata->bss) && 128 sta->sdata->bss == sdata->bss) &&
120 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 129 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
121 break; 130 break;
122 sta = rcu_dereference(sta->hnext); 131 sta = rcu_dereference_check(sta->hnext,
132 rcu_read_lock_held() ||
133 lockdep_is_held(&local->sta_lock) ||
134 lockdep_is_held(&local->sta_mtx));
123 } 135 }
124 return sta; 136 return sta;
125} 137}
@@ -431,6 +443,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
431 /* check if STA exists already */ 443 /* check if STA exists already */
432 if (sta_info_get_bss(sdata, sta->sta.addr)) { 444 if (sta_info_get_bss(sdata, sta->sta.addr)) {
433 spin_unlock_irqrestore(&local->sta_lock, flags); 445 spin_unlock_irqrestore(&local->sta_lock, flags);
446 mutex_unlock(&local->sta_mtx);
434 rcu_read_lock(); 447 rcu_read_lock();
435 err = -EEXIST; 448 err = -EEXIST;
436 goto out_free; 449 goto out_free;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index f7209d691c35..2cb77267f733 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1992,6 +1992,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
1992void ieee80211_tx_pending(unsigned long data) 1992void ieee80211_tx_pending(unsigned long data)
1993{ 1993{
1994 struct ieee80211_local *local = (struct ieee80211_local *)data; 1994 struct ieee80211_local *local = (struct ieee80211_local *)data;
1995 struct ieee80211_sub_if_data *sdata;
1995 unsigned long flags; 1996 unsigned long flags;
1996 int i; 1997 int i;
1997 bool txok; 1998 bool txok;
@@ -2028,6 +2029,11 @@ void ieee80211_tx_pending(unsigned long data)
2028 if (!txok) 2029 if (!txok)
2029 break; 2030 break;
2030 } 2031 }
2032
2033 if (skb_queue_empty(&local->pending[i]))
2034 list_for_each_entry_rcu(sdata, &local->interfaces, list)
2035 netif_tx_wake_queue(
2036 netdev_get_tx_queue(sdata->dev, i));
2031 } 2037 }
2032 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 2038 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
2033 2039
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7614821caed5..ad9009f717ed 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -279,13 +279,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
279 /* someone still has this queue stopped */ 279 /* someone still has this queue stopped */
280 return; 280 return;
281 281
282 if (!skb_queue_empty(&local->pending[queue])) 282 if (skb_queue_empty(&local->pending[queue])) {
283 rcu_read_lock();
284 list_for_each_entry_rcu(sdata, &local->interfaces, list)
285 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
286 rcu_read_unlock();
287 } else
283 tasklet_schedule(&local->tx_pending_tasklet); 288 tasklet_schedule(&local->tx_pending_tasklet);
284
285 rcu_read_lock();
286 list_for_each_entry_rcu(sdata, &local->interfaces, list)
287 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
288 rcu_read_unlock();
289} 289}
290 290
291void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 291void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@ -1102,9 +1102,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1102 */ 1102 */
1103 res = drv_start(local); 1103 res = drv_start(local);
1104 if (res) { 1104 if (res) {
1105 WARN(local->suspended, "Harware became unavailable " 1105 WARN(local->suspended, "Hardware became unavailable "
1106 "upon resume. This is could be a software issue" 1106 "upon resume. This could be a software issue "
1107 "prior to suspend or a hardware issue\n"); 1107 "prior to suspend or a hardware issue.\n");
1108 return res; 1108 return res;
1109 } 1109 }
1110 1110