diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 71 |
1 files changed, 31 insertions, 40 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index de5bba7f910a..0563b6969a21 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -30,7 +30,6 @@ | |||
30 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 30 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
31 | struct tid_ampdu_rx *tid_agg_rx, | 31 | struct tid_ampdu_rx *tid_agg_rx, |
32 | struct sk_buff *skb, | 32 | struct sk_buff *skb, |
33 | struct ieee80211_rx_status *status, | ||
34 | u16 mpdu_seq_num, | 33 | u16 mpdu_seq_num, |
35 | int bar_req); | 34 | int bar_req); |
36 | /* | 35 | /* |
@@ -59,11 +58,11 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
59 | return skb; | 58 | return skb; |
60 | } | 59 | } |
61 | 60 | ||
62 | static inline int should_drop_frame(struct ieee80211_rx_status *status, | 61 | static inline int should_drop_frame(struct sk_buff *skb, |
63 | struct sk_buff *skb, | ||
64 | int present_fcs_len, | 62 | int present_fcs_len, |
65 | int radiotap_len) | 63 | int radiotap_len) |
66 | { | 64 | { |
65 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
67 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 66 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
68 | 67 | ||
69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 68 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
@@ -111,10 +110,10 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
111 | static void | 110 | static void |
112 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | 111 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, |
113 | struct sk_buff *skb, | 112 | struct sk_buff *skb, |
114 | struct ieee80211_rx_status *status, | ||
115 | struct ieee80211_rate *rate, | 113 | struct ieee80211_rate *rate, |
116 | int rtap_len) | 114 | int rtap_len) |
117 | { | 115 | { |
116 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
118 | struct ieee80211_radiotap_header *rthdr; | 117 | struct ieee80211_radiotap_header *rthdr; |
119 | unsigned char *pos; | 118 | unsigned char *pos; |
120 | 119 | ||
@@ -220,9 +219,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
220 | */ | 219 | */ |
221 | static struct sk_buff * | 220 | static struct sk_buff * |
222 | ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | 221 | ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, |
223 | struct ieee80211_rx_status *status, | ||
224 | struct ieee80211_rate *rate) | 222 | struct ieee80211_rate *rate) |
225 | { | 223 | { |
224 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); | ||
226 | struct ieee80211_sub_if_data *sdata; | 225 | struct ieee80211_sub_if_data *sdata; |
227 | int needed_headroom = 0; | 226 | int needed_headroom = 0; |
228 | struct sk_buff *skb, *skb2; | 227 | struct sk_buff *skb, *skb2; |
@@ -248,8 +247,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
248 | present_fcs_len = FCS_LEN; | 247 | present_fcs_len = FCS_LEN; |
249 | 248 | ||
250 | if (!local->monitors) { | 249 | if (!local->monitors) { |
251 | if (should_drop_frame(status, origskb, present_fcs_len, | 250 | if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { |
252 | rtap_len)) { | ||
253 | dev_kfree_skb(origskb); | 251 | dev_kfree_skb(origskb); |
254 | return NULL; | 252 | return NULL; |
255 | } | 253 | } |
@@ -257,7 +255,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
257 | return remove_monitor_info(local, origskb, rtap_len); | 255 | return remove_monitor_info(local, origskb, rtap_len); |
258 | } | 256 | } |
259 | 257 | ||
260 | if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) { | 258 | if (should_drop_frame(origskb, present_fcs_len, rtap_len)) { |
261 | /* only need to expand headroom if necessary */ | 259 | /* only need to expand headroom if necessary */ |
262 | skb = origskb; | 260 | skb = origskb; |
263 | origskb = NULL; | 261 | origskb = NULL; |
@@ -289,7 +287,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
289 | 287 | ||
290 | /* if necessary, prepend radiotap information */ | 288 | /* if necessary, prepend radiotap information */ |
291 | if (!(status->flag & RX_FLAG_RADIOTAP)) | 289 | if (!(status->flag & RX_FLAG_RADIOTAP)) |
292 | ieee80211_add_rx_radiotap_header(local, skb, status, rate, | 290 | ieee80211_add_rx_radiotap_header(local, skb, rate, |
293 | needed_headroom); | 291 | needed_headroom); |
294 | 292 | ||
295 | skb_reset_mac_header(skb); | 293 | skb_reset_mac_header(skb); |
@@ -421,12 +419,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
421 | struct sk_buff *skb = rx->skb; | 419 | struct sk_buff *skb = rx->skb; |
422 | 420 | ||
423 | if (unlikely(local->hw_scanning)) | 421 | if (unlikely(local->hw_scanning)) |
424 | return ieee80211_scan_rx(rx->sdata, skb, rx->status); | 422 | return ieee80211_scan_rx(rx->sdata, skb); |
425 | 423 | ||
426 | if (unlikely(local->sw_scanning)) { | 424 | if (unlikely(local->sw_scanning)) { |
427 | /* drop all the other packets during a software scan anyway */ | 425 | /* drop all the other packets during a software scan anyway */ |
428 | if (ieee80211_scan_rx(rx->sdata, skb, rx->status) | 426 | if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) |
429 | != RX_QUEUED) | ||
430 | dev_kfree_skb(skb); | 427 | dev_kfree_skb(skb); |
431 | return RX_QUEUED; | 428 | return RX_QUEUED; |
432 | } | 429 | } |
@@ -1620,7 +1617,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1620 | /* manage reordering buffer according to requested */ | 1617 | /* manage reordering buffer according to requested */ |
1621 | /* sequence number */ | 1618 | /* sequence number */ |
1622 | rcu_read_lock(); | 1619 | rcu_read_lock(); |
1623 | ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, NULL, | 1620 | ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, |
1624 | start_seq_num, 1); | 1621 | start_seq_num, 1); |
1625 | rcu_read_unlock(); | 1622 | rcu_read_unlock(); |
1626 | return RX_DROP_UNUSABLE; | 1623 | return RX_DROP_UNUSABLE; |
@@ -1817,13 +1814,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1817 | return RX_DROP_MONITOR; | 1814 | return RX_DROP_MONITOR; |
1818 | 1815 | ||
1819 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1816 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1820 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); | 1817 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
1821 | 1818 | ||
1822 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 1819 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1823 | return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status); | 1820 | return ieee80211_ibss_rx_mgmt(sdata, rx->skb); |
1824 | 1821 | ||
1825 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 1822 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
1826 | return ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); | 1823 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); |
1827 | 1824 | ||
1828 | return RX_DROP_MONITOR; | 1825 | return RX_DROP_MONITOR; |
1829 | } | 1826 | } |
@@ -2114,9 +2111,9 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2114 | */ | 2111 | */ |
2115 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2112 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2116 | struct sk_buff *skb, | 2113 | struct sk_buff *skb, |
2117 | struct ieee80211_rx_status *status, | ||
2118 | struct ieee80211_rate *rate) | 2114 | struct ieee80211_rate *rate) |
2119 | { | 2115 | { |
2116 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2120 | struct ieee80211_local *local = hw_to_local(hw); | 2117 | struct ieee80211_local *local = hw_to_local(hw); |
2121 | struct ieee80211_sub_if_data *sdata; | 2118 | struct ieee80211_sub_if_data *sdata; |
2122 | struct ieee80211_hdr *hdr; | 2119 | struct ieee80211_hdr *hdr; |
@@ -2227,20 +2224,21 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
2227 | { | 2224 | { |
2228 | struct ieee80211_supported_band *sband; | 2225 | struct ieee80211_supported_band *sband; |
2229 | struct ieee80211_rate *rate; | 2226 | struct ieee80211_rate *rate; |
2230 | struct ieee80211_rx_status status; | 2227 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
2228 | struct ieee80211_rx_status *status; | ||
2231 | 2229 | ||
2232 | if (!tid_agg_rx->reorder_buf[index]) | 2230 | if (!skb) |
2233 | goto no_frame; | 2231 | goto no_frame; |
2234 | 2232 | ||
2233 | status = IEEE80211_SKB_RXCB(skb); | ||
2234 | |||
2235 | /* release the reordered frames to stack */ | 2235 | /* release the reordered frames to stack */ |
2236 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); | 2236 | sband = hw->wiphy->bands[status->band]; |
2237 | sband = hw->wiphy->bands[status.band]; | 2237 | if (status->flag & RX_FLAG_HT) |
2238 | if (status.flag & RX_FLAG_HT) | ||
2239 | rate = sband->bitrates; /* TODO: HT rates */ | 2238 | rate = sband->bitrates; /* TODO: HT rates */ |
2240 | else | 2239 | else |
2241 | rate = &sband->bitrates[status.rate_idx]; | 2240 | rate = &sband->bitrates[status->rate_idx]; |
2242 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2241 | __ieee80211_rx_handle_packet(hw, skb, rate); |
2243 | &status, rate); | ||
2244 | tid_agg_rx->stored_mpdu_num--; | 2242 | tid_agg_rx->stored_mpdu_num--; |
2245 | tid_agg_rx->reorder_buf[index] = NULL; | 2243 | tid_agg_rx->reorder_buf[index] = NULL; |
2246 | 2244 | ||
@@ -2265,7 +2263,6 @@ no_frame: | |||
2265 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 2263 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
2266 | struct tid_ampdu_rx *tid_agg_rx, | 2264 | struct tid_ampdu_rx *tid_agg_rx, |
2267 | struct sk_buff *skb, | 2265 | struct sk_buff *skb, |
2268 | struct ieee80211_rx_status *rxstatus, | ||
2269 | u16 mpdu_seq_num, | 2266 | u16 mpdu_seq_num, |
2270 | int bar_req) | 2267 | int bar_req) |
2271 | { | 2268 | { |
@@ -2324,8 +2321,6 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2324 | /* put the frame in the reordering buffer */ | 2321 | /* put the frame in the reordering buffer */ |
2325 | tid_agg_rx->reorder_buf[index] = skb; | 2322 | tid_agg_rx->reorder_buf[index] = skb; |
2326 | tid_agg_rx->reorder_time[index] = jiffies; | 2323 | tid_agg_rx->reorder_time[index] = jiffies; |
2327 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, | ||
2328 | sizeof(*rxstatus)); | ||
2329 | tid_agg_rx->stored_mpdu_num++; | 2324 | tid_agg_rx->stored_mpdu_num++; |
2330 | /* release the buffer until next missing frame */ | 2325 | /* release the buffer until next missing frame */ |
2331 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2326 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
@@ -2374,8 +2369,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2374 | } | 2369 | } |
2375 | 2370 | ||
2376 | static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | 2371 | static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, |
2377 | struct sk_buff *skb, | 2372 | struct sk_buff *skb) |
2378 | struct ieee80211_rx_status *status) | ||
2379 | { | 2373 | { |
2380 | struct ieee80211_hw *hw = &local->hw; | 2374 | struct ieee80211_hw *hw = &local->hw; |
2381 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 2375 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -2424,7 +2418,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2424 | 2418 | ||
2425 | /* according to mpdu sequence number deal with reordering buffer */ | 2419 | /* according to mpdu sequence number deal with reordering buffer */ |
2426 | mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 2420 | mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
2427 | ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, status, | 2421 | ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, |
2428 | mpdu_seq_num, 0); | 2422 | mpdu_seq_num, 0); |
2429 | end_reorder: | 2423 | end_reorder: |
2430 | return ret; | 2424 | return ret; |
@@ -2434,12 +2428,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2434 | * This is the receive path handler. It is called by a low level driver when an | 2428 | * This is the receive path handler. It is called by a low level driver when an |
2435 | * 802.11 MPDU is received from the hardware. | 2429 | * 802.11 MPDU is received from the hardware. |
2436 | */ | 2430 | */ |
2437 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 2431 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) |
2438 | struct ieee80211_rx_status *status) | ||
2439 | { | 2432 | { |
2440 | struct ieee80211_local *local = hw_to_local(hw); | 2433 | struct ieee80211_local *local = hw_to_local(hw); |
2441 | struct ieee80211_rate *rate = NULL; | 2434 | struct ieee80211_rate *rate = NULL; |
2442 | struct ieee80211_supported_band *sband; | 2435 | struct ieee80211_supported_band *sband; |
2436 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2443 | 2437 | ||
2444 | if (status->band < 0 || | 2438 | if (status->band < 0 || |
2445 | status->band >= IEEE80211_NUM_BANDS) { | 2439 | status->band >= IEEE80211_NUM_BANDS) { |
@@ -2482,7 +2476,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2482 | * if it was previously present. | 2476 | * if it was previously present. |
2483 | * Also, frames with less than 16 bytes are dropped. | 2477 | * Also, frames with less than 16 bytes are dropped. |
2484 | */ | 2478 | */ |
2485 | skb = ieee80211_rx_monitor(local, skb, status, rate); | 2479 | skb = ieee80211_rx_monitor(local, skb, rate); |
2486 | if (!skb) { | 2480 | if (!skb) { |
2487 | rcu_read_unlock(); | 2481 | rcu_read_unlock(); |
2488 | return; | 2482 | return; |
@@ -2500,8 +2494,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2500 | * frames from other than operational channel), but that should not | 2494 | * frames from other than operational channel), but that should not |
2501 | * happen in normal networks. | 2495 | * happen in normal networks. |
2502 | */ | 2496 | */ |
2503 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) | 2497 | if (!ieee80211_rx_reorder_ampdu(local, skb)) |
2504 | __ieee80211_rx_handle_packet(hw, skb, status, rate); | 2498 | __ieee80211_rx_handle_packet(hw, skb, rate); |
2505 | 2499 | ||
2506 | rcu_read_unlock(); | 2500 | rcu_read_unlock(); |
2507 | } | 2501 | } |
@@ -2509,16 +2503,13 @@ EXPORT_SYMBOL(__ieee80211_rx); | |||
2509 | 2503 | ||
2510 | /* This is a version of the rx handler that can be called from hard irq | 2504 | /* This is a version of the rx handler that can be called from hard irq |
2511 | * context. Post the skb on the queue and schedule the tasklet */ | 2505 | * context. Post the skb on the queue and schedule the tasklet */ |
2512 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb, | 2506 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) |
2513 | struct ieee80211_rx_status *status) | ||
2514 | { | 2507 | { |
2515 | struct ieee80211_local *local = hw_to_local(hw); | 2508 | struct ieee80211_local *local = hw_to_local(hw); |
2516 | 2509 | ||
2517 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); | 2510 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); |
2518 | 2511 | ||
2519 | skb->dev = local->mdev; | 2512 | skb->dev = local->mdev; |
2520 | /* copy status into skb->cb for use by tasklet */ | ||
2521 | memcpy(skb->cb, status, sizeof(*status)); | ||
2522 | skb->pkt_type = IEEE80211_RX_MSG; | 2513 | skb->pkt_type = IEEE80211_RX_MSG; |
2523 | skb_queue_tail(&local->skb_queue, skb); | 2514 | skb_queue_tail(&local->skb_queue, skb); |
2524 | tasklet_schedule(&local->tasklet); | 2515 | tasklet_schedule(&local->tasklet); |