diff options
Diffstat (limited to 'drivers/net/wireless/b43/xmit.c')
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 2fabcf8f0474..eae9b8052658 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -46,7 +46,6 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) | |||
46 | case 0x6E: | 46 | case 0x6E: |
47 | return 3; | 47 | return 3; |
48 | } | 48 | } |
49 | B43_WARN_ON(1); | ||
50 | return -1; | 49 | return -1; |
51 | } | 50 | } |
52 | 51 | ||
@@ -73,7 +72,6 @@ static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) | |||
73 | case 0xC: | 72 | case 0xC: |
74 | return base + 7; | 73 | return base + 7; |
75 | } | 74 | } |
76 | B43_WARN_ON(1); | ||
77 | return -1; | 75 | return -1; |
78 | } | 76 | } |
79 | 77 | ||
@@ -185,7 +183,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
185 | u8 *_txhdr, | 183 | u8 *_txhdr, |
186 | const unsigned char *fragment_data, | 184 | const unsigned char *fragment_data, |
187 | unsigned int fragment_len, | 185 | unsigned int fragment_len, |
188 | const struct ieee80211_tx_info *info, | 186 | struct ieee80211_tx_info *info, |
189 | u16 cookie) | 187 | u16 cookie) |
190 | { | 188 | { |
191 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; | 189 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; |
@@ -202,6 +200,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
202 | u16 phy_ctl = 0; | 200 | u16 phy_ctl = 0; |
203 | u8 extra_ft = 0; | 201 | u8 extra_ft = 0; |
204 | struct ieee80211_rate *txrate; | 202 | struct ieee80211_rate *txrate; |
203 | struct ieee80211_tx_rate *rates; | ||
205 | 204 | ||
206 | memset(txhdr, 0, sizeof(*txhdr)); | 205 | memset(txhdr, 0, sizeof(*txhdr)); |
207 | 206 | ||
@@ -291,7 +290,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
291 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; | 290 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; |
292 | else | 291 | else |
293 | phy_ctl |= B43_TXH_PHY_ENC_CCK; | 292 | phy_ctl |= B43_TXH_PHY_ENC_CCK; |
294 | if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) | 293 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
295 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; | 294 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; |
296 | 295 | ||
297 | switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { | 296 | switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { |
@@ -314,6 +313,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
314 | B43_WARN_ON(1); | 313 | B43_WARN_ON(1); |
315 | } | 314 | } |
316 | 315 | ||
316 | rates = info->control.rates; | ||
317 | /* MAC control */ | 317 | /* MAC control */ |
318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
319 | mac_ctl |= B43_TXH_MAC_ACK; | 319 | mac_ctl |= B43_TXH_MAC_ACK; |
@@ -324,12 +324,22 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
324 | mac_ctl |= B43_TXH_MAC_STMSDU; | 324 | mac_ctl |= B43_TXH_MAC_STMSDU; |
325 | if (phy->type == B43_PHYTYPE_A) | 325 | if (phy->type == B43_PHYTYPE_A) |
326 | mac_ctl |= B43_TXH_MAC_5GHZ; | 326 | mac_ctl |= B43_TXH_MAC_5GHZ; |
327 | if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) | 327 | |
328 | /* Overwrite rates[0].count to make the retry calculation | ||
329 | * in the tx status easier. need the actual retry limit to | ||
330 | * detect whether the fallback rate was used. | ||
331 | */ | ||
332 | if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
333 | (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { | ||
334 | rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; | ||
328 | mac_ctl |= B43_TXH_MAC_LONGFRAME; | 335 | mac_ctl |= B43_TXH_MAC_LONGFRAME; |
336 | } else { | ||
337 | rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; | ||
338 | } | ||
329 | 339 | ||
330 | /* Generate the RTS or CTS-to-self frame */ | 340 | /* Generate the RTS or CTS-to-self frame */ |
331 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | 341 | if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || |
332 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { | 342 | (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { |
333 | unsigned int len; | 343 | unsigned int len; |
334 | struct ieee80211_hdr *hdr; | 344 | struct ieee80211_hdr *hdr; |
335 | int rts_rate, rts_rate_fb; | 345 | int rts_rate, rts_rate_fb; |
@@ -344,7 +354,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
344 | rts_rate_fb = b43_calc_fallback_rate(rts_rate); | 354 | rts_rate_fb = b43_calc_fallback_rate(rts_rate); |
345 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); | 355 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); |
346 | 356 | ||
347 | if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { | 357 | if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
348 | struct ieee80211_cts *cts; | 358 | struct ieee80211_cts *cts; |
349 | 359 | ||
350 | if (b43_is_old_txhdr_format(dev)) { | 360 | if (b43_is_old_txhdr_format(dev)) { |
@@ -596,6 +606,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
596 | phytype == B43_PHYTYPE_A); | 606 | phytype == B43_PHYTYPE_A); |
597 | else | 607 | else |
598 | status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); | 608 | status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); |
609 | if (unlikely(status.rate_idx == -1)) | ||
610 | goto drop; | ||
599 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); | 611 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); |
600 | 612 | ||
601 | /* | 613 | /* |
@@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev, | |||
687 | /* Fill out the mac80211 TXstatus report based on the b43-specific | 699 | /* Fill out the mac80211 TXstatus report based on the b43-specific |
688 | * txstatus report data. This returns a boolean whether the frame was | 700 | * txstatus report data. This returns a boolean whether the frame was |
689 | * successfully transmitted. */ | 701 | * successfully transmitted. */ |
690 | bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, | 702 | bool b43_fill_txstatus_report(struct b43_wldev *dev, |
703 | struct ieee80211_tx_info *report, | ||
691 | const struct b43_txstatus *status) | 704 | const struct b43_txstatus *status) |
692 | { | 705 | { |
693 | bool frame_success = 1; | 706 | bool frame_success = 1; |
707 | int retry_limit; | ||
708 | |||
709 | /* preserve the confiured retry limit before clearing the status | ||
710 | * The xmit function has overwritten the rc's value with the actual | ||
711 | * retry limit done by the hardware */ | ||
712 | retry_limit = report->status.rates[0].count; | ||
713 | ieee80211_tx_info_clear_status(report); | ||
694 | 714 | ||
695 | if (status->acked) { | 715 | if (status->acked) { |
696 | /* The frame was ACKed. */ | 716 | /* The frame was ACKed. */ |
@@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, | |||
700 | if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { | 720 | if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { |
701 | /* ...but we expected an ACK. */ | 721 | /* ...but we expected an ACK. */ |
702 | frame_success = 0; | 722 | frame_success = 0; |
703 | report->status.excessive_retries = 1; | ||
704 | } | 723 | } |
705 | } | 724 | } |
706 | if (status->frame_count == 0) { | 725 | if (status->frame_count == 0) { |
707 | /* The frame was not transmitted at all. */ | 726 | /* The frame was not transmitted at all. */ |
708 | report->status.retry_count = 0; | 727 | report->status.rates[0].count = 0; |
709 | } else | 728 | } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { |
710 | report->status.retry_count = status->frame_count - 1; | 729 | /* |
730 | * If the short retries (RTS, not data frame) have exceeded | ||
731 | * the limit, the hw will not have tried the selected rate, | ||
732 | * but will have used the fallback rate instead. | ||
733 | * Don't let the rate control count attempts for the selected | ||
734 | * rate in this case, otherwise the statistics will be off. | ||
735 | */ | ||
736 | report->status.rates[0].count = 0; | ||
737 | report->status.rates[1].count = status->frame_count; | ||
738 | } else { | ||
739 | if (status->frame_count > retry_limit) { | ||
740 | report->status.rates[0].count = retry_limit; | ||
741 | report->status.rates[1].count = status->frame_count - | ||
742 | retry_limit; | ||
743 | |||
744 | } else { | ||
745 | report->status.rates[0].count = status->frame_count; | ||
746 | report->status.rates[1].idx = -1; | ||
747 | } | ||
748 | } | ||
711 | 749 | ||
712 | return frame_success; | 750 | return frame_success; |
713 | } | 751 | } |