diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 138 |
1 files changed, 92 insertions, 46 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a5afb79dab6e..d052f4004829 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
20 | 20 | ||
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "driver-ops.h" | ||
22 | #include "led.h" | 23 | #include "led.h" |
23 | #include "mesh.h" | 24 | #include "mesh.h" |
24 | #include "wep.h" | 25 | #include "wep.h" |
@@ -773,9 +774,7 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
773 | 774 | ||
774 | atomic_inc(&sdata->bss->num_sta_ps); | 775 | atomic_inc(&sdata->bss->num_sta_ps); |
775 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 776 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
776 | if (local->ops->sta_notify) | 777 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); |
777 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
778 | STA_NOTIFY_SLEEP, &sta->sta); | ||
779 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 778 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
780 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 779 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
781 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 780 | sdata->dev->name, sta->sta.addr, sta->sta.aid); |
@@ -792,9 +791,7 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
792 | atomic_dec(&sdata->bss->num_sta_ps); | 791 | atomic_dec(&sdata->bss->num_sta_ps); |
793 | 792 | ||
794 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 793 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
795 | if (local->ops->sta_notify) | 794 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); |
796 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
797 | STA_NOTIFY_AWAKE, &sta->sta); | ||
798 | 795 | ||
799 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 796 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
800 | sta_info_clear_tim_bit(sta); | 797 | sta_info_clear_tim_bit(sta); |
@@ -2287,6 +2284,43 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
2287 | } | 2284 | } |
2288 | 2285 | ||
2289 | 2286 | ||
2287 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | ||
2288 | struct tid_ampdu_rx *tid_agg_rx, | ||
2289 | int index) | ||
2290 | { | ||
2291 | struct ieee80211_supported_band *sband; | ||
2292 | struct ieee80211_rate *rate; | ||
2293 | struct ieee80211_rx_status status; | ||
2294 | |||
2295 | if (!tid_agg_rx->reorder_buf[index]) | ||
2296 | goto no_frame; | ||
2297 | |||
2298 | /* release the reordered frames to stack */ | ||
2299 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); | ||
2300 | sband = hw->wiphy->bands[status.band]; | ||
2301 | if (status.flag & RX_FLAG_HT) | ||
2302 | rate = sband->bitrates; /* TODO: HT rates */ | ||
2303 | else | ||
2304 | rate = &sband->bitrates[status.rate_idx]; | ||
2305 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | ||
2306 | &status, rate); | ||
2307 | tid_agg_rx->stored_mpdu_num--; | ||
2308 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2309 | |||
2310 | no_frame: | ||
2311 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | ||
2312 | } | ||
2313 | |||
2314 | |||
2315 | /* | ||
2316 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If | ||
2317 | * the skb was added to the buffer longer than this time ago, the earlier | ||
2318 | * frames that have not yet been received are assumed to be lost and the skb | ||
2319 | * can be released for processing. This may also release other skb's from the | ||
2320 | * reorder buffer if there are no additional gaps between the frames. | ||
2321 | */ | ||
2322 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | ||
2323 | |||
2290 | /* | 2324 | /* |
2291 | * As it function blongs to Rx path it must be called with | 2325 | * As it function blongs to Rx path it must be called with |
2292 | * the proper rcu_read_lock protection for its flow. | 2326 | * the proper rcu_read_lock protection for its flow. |
@@ -2298,12 +2332,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2298 | u16 mpdu_seq_num, | 2332 | u16 mpdu_seq_num, |
2299 | int bar_req) | 2333 | int bar_req) |
2300 | { | 2334 | { |
2301 | struct ieee80211_local *local = hw_to_local(hw); | ||
2302 | struct ieee80211_rx_status status; | ||
2303 | u16 head_seq_num, buf_size; | 2335 | u16 head_seq_num, buf_size; |
2304 | int index; | 2336 | int index; |
2305 | struct ieee80211_supported_band *sband; | ||
2306 | struct ieee80211_rate *rate; | ||
2307 | 2337 | ||
2308 | buf_size = tid_agg_rx->buf_size; | 2338 | buf_size = tid_agg_rx->buf_size; |
2309 | head_seq_num = tid_agg_rx->head_seq_num; | 2339 | head_seq_num = tid_agg_rx->head_seq_num; |
@@ -2328,28 +2358,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2328 | index = seq_sub(tid_agg_rx->head_seq_num, | 2358 | index = seq_sub(tid_agg_rx->head_seq_num, |
2329 | tid_agg_rx->ssn) | 2359 | tid_agg_rx->ssn) |
2330 | % tid_agg_rx->buf_size; | 2360 | % tid_agg_rx->buf_size; |
2331 | 2361 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | |
2332 | if (tid_agg_rx->reorder_buf[index]) { | 2362 | index); |
2333 | /* release the reordered frames to stack */ | ||
2334 | memcpy(&status, | ||
2335 | tid_agg_rx->reorder_buf[index]->cb, | ||
2336 | sizeof(status)); | ||
2337 | sband = local->hw.wiphy->bands[status.band]; | ||
2338 | if (status.flag & RX_FLAG_HT) { | ||
2339 | /* TODO: HT rates */ | ||
2340 | rate = sband->bitrates; | ||
2341 | } else { | ||
2342 | rate = &sband->bitrates | ||
2343 | [status.rate_idx]; | ||
2344 | } | ||
2345 | __ieee80211_rx_handle_packet(hw, | ||
2346 | tid_agg_rx->reorder_buf[index], | ||
2347 | &status, rate); | ||
2348 | tid_agg_rx->stored_mpdu_num--; | ||
2349 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2350 | } | ||
2351 | tid_agg_rx->head_seq_num = | ||
2352 | seq_inc(tid_agg_rx->head_seq_num); | ||
2353 | } | 2363 | } |
2354 | if (bar_req) | 2364 | if (bar_req) |
2355 | return 1; | 2365 | return 1; |
@@ -2376,26 +2386,50 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2376 | 2386 | ||
2377 | /* put the frame in the reordering buffer */ | 2387 | /* put the frame in the reordering buffer */ |
2378 | tid_agg_rx->reorder_buf[index] = skb; | 2388 | tid_agg_rx->reorder_buf[index] = skb; |
2389 | tid_agg_rx->reorder_time[index] = jiffies; | ||
2379 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, | 2390 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, |
2380 | sizeof(*rxstatus)); | 2391 | sizeof(*rxstatus)); |
2381 | tid_agg_rx->stored_mpdu_num++; | 2392 | tid_agg_rx->stored_mpdu_num++; |
2382 | /* release the buffer until next missing frame */ | 2393 | /* release the buffer until next missing frame */ |
2383 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2394 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
2384 | % tid_agg_rx->buf_size; | 2395 | % tid_agg_rx->buf_size; |
2385 | while (tid_agg_rx->reorder_buf[index]) { | 2396 | if (!tid_agg_rx->reorder_buf[index] && |
2386 | /* release the reordered frame back to stack */ | 2397 | tid_agg_rx->stored_mpdu_num > 1) { |
2387 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, | 2398 | /* |
2388 | sizeof(status)); | 2399 | * No buffers ready to be released, but check whether any |
2389 | sband = local->hw.wiphy->bands[status.band]; | 2400 | * frames in the reorder buffer have timed out. |
2390 | if (status.flag & RX_FLAG_HT) | 2401 | */ |
2391 | rate = sband->bitrates; /* TODO: HT rates */ | 2402 | int j; |
2392 | else | 2403 | int skipped = 1; |
2393 | rate = &sband->bitrates[status.rate_idx]; | 2404 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
2394 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2405 | j = (j + 1) % tid_agg_rx->buf_size) { |
2395 | &status, rate); | 2406 | if (tid_agg_rx->reorder_buf[j] == NULL) { |
2396 | tid_agg_rx->stored_mpdu_num--; | 2407 | skipped++; |
2397 | tid_agg_rx->reorder_buf[index] = NULL; | 2408 | continue; |
2398 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2409 | } |
2410 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
2411 | HZ / 10)) | ||
2412 | break; | ||
2413 | |||
2414 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
2415 | if (net_ratelimit()) | ||
2416 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
2417 | "frame due to timeout on earlier " | ||
2418 | "frames\n", | ||
2419 | wiphy_name(hw->wiphy)); | ||
2420 | #endif | ||
2421 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); | ||
2422 | |||
2423 | /* | ||
2424 | * Increment the head seq# also for the skipped slots. | ||
2425 | */ | ||
2426 | tid_agg_rx->head_seq_num = | ||
2427 | (tid_agg_rx->head_seq_num + skipped) & | ||
2428 | SEQ_MASK; | ||
2429 | skipped = 0; | ||
2430 | } | ||
2431 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
2432 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | ||
2399 | index = seq_sub(tid_agg_rx->head_seq_num, | 2433 | index = seq_sub(tid_agg_rx->head_seq_num, |
2400 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2434 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
2401 | } | 2435 | } |
@@ -2517,6 +2551,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2517 | return; | 2551 | return; |
2518 | } | 2552 | } |
2519 | 2553 | ||
2554 | /* | ||
2555 | * In theory, the block ack reordering should happen after duplicate | ||
2556 | * removal (ieee80211_rx_h_check(), which is an RX handler). As such, | ||
2557 | * the call to ieee80211_rx_reorder_ampdu() should really be moved to | ||
2558 | * happen as a new RX handler between ieee80211_rx_h_check and | ||
2559 | * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for | ||
2560 | * the time being, the call can be here since RX reorder buf processing | ||
2561 | * will implicitly skip duplicates. We could, in theory at least, | ||
2562 | * process frames that ieee80211_rx_h_passive_scan would drop (e.g., | ||
2563 | * frames from other than operational channel), but that should not | ||
2564 | * happen in normal networks. | ||
2565 | */ | ||
2520 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) | 2566 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) |
2521 | __ieee80211_rx_handle_packet(hw, skb, status, rate); | 2567 | __ieee80211_rx_handle_packet(hw, skb, status, rate); |
2522 | 2568 | ||