diff options
Diffstat (limited to 'drivers/net/wireless/b43/xmit.c')
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 206 |
1 files changed, 106 insertions, 100 deletions
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 7caa26eb4105..19aefbfb2c93 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -30,48 +30,51 @@ | |||
30 | #include "xmit.h" | 30 | #include "xmit.h" |
31 | #include "phy.h" | 31 | #include "phy.h" |
32 | #include "dma.h" | 32 | #include "dma.h" |
33 | #include "pio.h" | ||
33 | 34 | ||
34 | 35 | ||
35 | /* Extract the bitrate out of a CCK PLCP header. */ | 36 | /* Extract the bitrate index out of a CCK PLCP header. */ |
36 | static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp) | 37 | static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) |
37 | { | 38 | { |
38 | switch (plcp->raw[0]) { | 39 | switch (plcp->raw[0]) { |
39 | case 0x0A: | 40 | case 0x0A: |
40 | return B43_CCK_RATE_1MB; | 41 | return 0; |
41 | case 0x14: | 42 | case 0x14: |
42 | return B43_CCK_RATE_2MB; | 43 | return 1; |
43 | case 0x37: | 44 | case 0x37: |
44 | return B43_CCK_RATE_5MB; | 45 | return 2; |
45 | case 0x6E: | 46 | case 0x6E: |
46 | return B43_CCK_RATE_11MB; | 47 | return 3; |
47 | } | 48 | } |
48 | B43_WARN_ON(1); | 49 | B43_WARN_ON(1); |
49 | return 0; | 50 | return -1; |
50 | } | 51 | } |
51 | 52 | ||
52 | /* Extract the bitrate out of an OFDM PLCP header. */ | 53 | /* Extract the bitrate index out of an OFDM PLCP header. */ |
53 | static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp) | 54 | static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) |
54 | { | 55 | { |
56 | int base = aphy ? 0 : 4; | ||
57 | |||
55 | switch (plcp->raw[0] & 0xF) { | 58 | switch (plcp->raw[0] & 0xF) { |
56 | case 0xB: | 59 | case 0xB: |
57 | return B43_OFDM_RATE_6MB; | 60 | return base + 0; |
58 | case 0xF: | 61 | case 0xF: |
59 | return B43_OFDM_RATE_9MB; | 62 | return base + 1; |
60 | case 0xA: | 63 | case 0xA: |
61 | return B43_OFDM_RATE_12MB; | 64 | return base + 2; |
62 | case 0xE: | 65 | case 0xE: |
63 | return B43_OFDM_RATE_18MB; | 66 | return base + 3; |
64 | case 0x9: | 67 | case 0x9: |
65 | return B43_OFDM_RATE_24MB; | 68 | return base + 4; |
66 | case 0xD: | 69 | case 0xD: |
67 | return B43_OFDM_RATE_36MB; | 70 | return base + 5; |
68 | case 0x8: | 71 | case 0x8: |
69 | return B43_OFDM_RATE_48MB; | 72 | return base + 6; |
70 | case 0xC: | 73 | case 0xC: |
71 | return B43_OFDM_RATE_54MB; | 74 | return base + 7; |
72 | } | 75 | } |
73 | B43_WARN_ON(1); | 76 | B43_WARN_ON(1); |
74 | return 0; | 77 | return -1; |
75 | } | 78 | } |
76 | 79 | ||
77 | u8 b43_plcp_get_ratecode_cck(const u8 bitrate) | 80 | u8 b43_plcp_get_ratecode_cck(const u8 bitrate) |
@@ -191,6 +194,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
191 | (const struct ieee80211_hdr *)fragment_data; | 194 | (const struct ieee80211_hdr *)fragment_data; |
192 | int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); | 195 | int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); |
193 | u16 fctl = le16_to_cpu(wlhdr->frame_control); | 196 | u16 fctl = le16_to_cpu(wlhdr->frame_control); |
197 | struct ieee80211_rate *fbrate; | ||
194 | u8 rate, rate_fb; | 198 | u8 rate, rate_fb; |
195 | int rate_ofdm, rate_fb_ofdm; | 199 | int rate_ofdm, rate_fb_ofdm; |
196 | unsigned int plcp_fragment_len; | 200 | unsigned int plcp_fragment_len; |
@@ -200,9 +204,11 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
200 | 204 | ||
201 | memset(txhdr, 0, sizeof(*txhdr)); | 205 | memset(txhdr, 0, sizeof(*txhdr)); |
202 | 206 | ||
203 | rate = txctl->tx_rate; | 207 | WARN_ON(!txctl->tx_rate); |
208 | rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB; | ||
204 | rate_ofdm = b43_is_ofdm_rate(rate); | 209 | rate_ofdm = b43_is_ofdm_rate(rate); |
205 | rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; | 210 | fbrate = txctl->alt_retry_rate ? : txctl->tx_rate; |
211 | rate_fb = fbrate->hw_value; | ||
206 | rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); | 212 | rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); |
207 | 213 | ||
208 | if (rate_ofdm) | 214 | if (rate_ofdm) |
@@ -221,11 +227,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
221 | * use the original dur_id field. */ | 227 | * use the original dur_id field. */ |
222 | txhdr->dur_fb = wlhdr->duration_id; | 228 | txhdr->dur_fb = wlhdr->duration_id; |
223 | } else { | 229 | } else { |
224 | int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb); | ||
225 | txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, | 230 | txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, |
226 | txctl->vif, | 231 | txctl->vif, |
227 | fragment_len, | 232 | fragment_len, |
228 | fbrate_base100kbps); | 233 | fbrate); |
229 | } | 234 | } |
230 | 235 | ||
231 | plcp_fragment_len = fragment_len + FCS_LEN; | 236 | plcp_fragment_len = fragment_len + FCS_LEN; |
@@ -287,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
287 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; | 292 | phy_ctl |= B43_TXH_PHY_ENC_OFDM; |
288 | else | 293 | else |
289 | phy_ctl |= B43_TXH_PHY_ENC_CCK; | 294 | phy_ctl |= B43_TXH_PHY_ENC_CCK; |
290 | if (dev->short_preamble) | 295 | if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) |
291 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; | 296 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; |
292 | 297 | ||
293 | switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { | 298 | switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { |
@@ -332,7 +337,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
332 | int rts_rate_ofdm, rts_rate_fb_ofdm; | 337 | int rts_rate_ofdm, rts_rate_fb_ofdm; |
333 | struct b43_plcp_hdr6 *plcp; | 338 | struct b43_plcp_hdr6 *plcp; |
334 | 339 | ||
335 | rts_rate = txctl->rts_cts_rate; | 340 | WARN_ON(!txctl->rts_cts_rate); |
341 | rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB; | ||
336 | rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); | 342 | rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); |
337 | rts_rate_fb = b43_calc_fallback_rate(rts_rate); | 343 | rts_rate_fb = b43_calc_fallback_rate(rts_rate); |
338 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); | 344 | rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); |
@@ -506,7 +512,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
506 | u16 phystat0, phystat3, chanstat, mactime; | 512 | u16 phystat0, phystat3, chanstat, mactime; |
507 | u32 macstat; | 513 | u32 macstat; |
508 | u16 chanid; | 514 | u16 chanid; |
509 | u8 jssi; | 515 | u16 phytype; |
510 | int padding; | 516 | int padding; |
511 | 517 | ||
512 | memset(&status, 0, sizeof(status)); | 518 | memset(&status, 0, sizeof(status)); |
@@ -514,10 +520,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
514 | /* Get metadata about the frame from the header. */ | 520 | /* Get metadata about the frame from the header. */ |
515 | phystat0 = le16_to_cpu(rxhdr->phy_status0); | 521 | phystat0 = le16_to_cpu(rxhdr->phy_status0); |
516 | phystat3 = le16_to_cpu(rxhdr->phy_status3); | 522 | phystat3 = le16_to_cpu(rxhdr->phy_status3); |
517 | jssi = rxhdr->jssi; | ||
518 | macstat = le32_to_cpu(rxhdr->mac_status); | 523 | macstat = le32_to_cpu(rxhdr->mac_status); |
519 | mactime = le16_to_cpu(rxhdr->mac_time); | 524 | mactime = le16_to_cpu(rxhdr->mac_time); |
520 | chanstat = le16_to_cpu(rxhdr->channel); | 525 | chanstat = le16_to_cpu(rxhdr->channel); |
526 | phytype = chanstat & B43_RX_CHAN_PHYTYPE; | ||
521 | 527 | ||
522 | if (macstat & B43_RX_MAC_FCSERR) | 528 | if (macstat & B43_RX_MAC_FCSERR) |
523 | dev->wl->ieee_stats.dot11FCSErrorCount++; | 529 | dev->wl->ieee_stats.dot11FCSErrorCount++; |
@@ -567,26 +573,40 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
567 | } | 573 | } |
568 | } | 574 | } |
569 | 575 | ||
570 | status.ssi = b43_rssi_postprocess(dev, jssi, | 576 | /* Link quality statistics */ |
571 | (phystat0 & B43_RX_PHYST0_OFDM), | ||
572 | (phystat0 & B43_RX_PHYST0_GAINCTL), | ||
573 | (phystat3 & B43_RX_PHYST3_TRSTATE)); | ||
574 | status.noise = dev->stats.link_noise; | 577 | status.noise = dev->stats.link_noise; |
575 | /* the next line looks wrong, but is what mac80211 wants */ | 578 | if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { |
576 | status.signal = (jssi * 100) / B43_RX_MAX_SSI; | 579 | // s8 rssi = max(rxhdr->power0, rxhdr->power1); |
580 | //TODO: Find out what the rssi value is (dBm or percentage?) | ||
581 | // and also find out what the maximum possible value is. | ||
582 | // Fill status.ssi and status.signal fields. | ||
583 | } else { | ||
584 | status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi, | ||
585 | (phystat0 & B43_RX_PHYST0_OFDM), | ||
586 | (phystat0 & B43_RX_PHYST0_GAINCTL), | ||
587 | (phystat3 & B43_RX_PHYST3_TRSTATE)); | ||
588 | /* the next line looks wrong, but is what mac80211 wants */ | ||
589 | status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; | ||
590 | } | ||
591 | |||
577 | if (phystat0 & B43_RX_PHYST0_OFDM) | 592 | if (phystat0 & B43_RX_PHYST0_OFDM) |
578 | status.rate = b43_plcp_get_bitrate_ofdm(plcp); | 593 | status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, |
594 | phytype == B43_PHYTYPE_A); | ||
579 | else | 595 | else |
580 | status.rate = b43_plcp_get_bitrate_cck(plcp); | 596 | status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); |
581 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); | 597 | status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); |
582 | 598 | ||
583 | /* | 599 | /* |
584 | * If monitors are present get full 64-bit timestamp. This | 600 | * All frames on monitor interfaces and beacons always need a full |
585 | * code assumes we get to process the packet within 16 bits | 601 | * 64-bit timestamp. Monitor interfaces need it for diagnostic |
586 | * of timestamp, i.e. about 65 milliseconds after the PHY | 602 | * purposes and beacons for IBSS merging. |
587 | * received the first symbol. | 603 | * This code assumes we get to process the packet within 16 bits |
604 | * of timestamp, i.e. about 65 milliseconds after the PHY received | ||
605 | * the first symbol. | ||
588 | */ | 606 | */ |
589 | if (dev->wl->radiotap_enabled) { | 607 | if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) |
608 | == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || | ||
609 | dev->wl->radiotap_enabled) { | ||
590 | u16 low_mactime_now; | 610 | u16 low_mactime_now; |
591 | 611 | ||
592 | b43_tsf_read(dev, &status.mactime); | 612 | b43_tsf_read(dev, &status.mactime); |
@@ -601,29 +621,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
601 | chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; | 621 | chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; |
602 | switch (chanstat & B43_RX_CHAN_PHYTYPE) { | 622 | switch (chanstat & B43_RX_CHAN_PHYTYPE) { |
603 | case B43_PHYTYPE_A: | 623 | case B43_PHYTYPE_A: |
604 | status.phymode = MODE_IEEE80211A; | 624 | status.band = IEEE80211_BAND_5GHZ; |
605 | B43_WARN_ON(1); | 625 | B43_WARN_ON(1); |
606 | /* FIXME: We don't really know which value the "chanid" contains. | 626 | /* FIXME: We don't really know which value the "chanid" contains. |
607 | * So the following assignment might be wrong. */ | 627 | * So the following assignment might be wrong. */ |
608 | status.channel = chanid; | 628 | status.freq = b43_channel_to_freq_5ghz(chanid); |
609 | status.freq = b43_channel_to_freq_5ghz(status.channel); | ||
610 | break; | 629 | break; |
611 | case B43_PHYTYPE_G: | 630 | case B43_PHYTYPE_G: |
612 | status.phymode = MODE_IEEE80211G; | 631 | status.band = IEEE80211_BAND_2GHZ; |
613 | /* chanid is the radio channel cookie value as used | 632 | /* chanid is the radio channel cookie value as used |
614 | * to tune the radio. */ | 633 | * to tune the radio. */ |
615 | status.freq = chanid + 2400; | 634 | status.freq = chanid + 2400; |
616 | status.channel = b43_freq_to_channel_2ghz(status.freq); | ||
617 | break; | 635 | break; |
618 | case B43_PHYTYPE_N: | 636 | case B43_PHYTYPE_N: |
619 | status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; | ||
620 | /* chanid is the SHM channel cookie. Which is the plain | 637 | /* chanid is the SHM channel cookie. Which is the plain |
621 | * channel number in b43. */ | 638 | * channel number in b43. */ |
622 | status.channel = chanid; | 639 | if (chanstat & B43_RX_CHAN_5GHZ) { |
623 | if (chanstat & B43_RX_CHAN_5GHZ) | 640 | status.band = IEEE80211_BAND_5GHZ; |
624 | status.freq = b43_freq_to_channel_5ghz(status.freq); | 641 | status.freq = b43_freq_to_channel_5ghz(chanid); |
625 | else | 642 | } else { |
626 | status.freq = b43_freq_to_channel_2ghz(status.freq); | 643 | status.band = IEEE80211_BAND_2GHZ; |
644 | status.freq = b43_freq_to_channel_2ghz(chanid); | ||
645 | } | ||
627 | break; | 646 | break; |
628 | default: | 647 | default: |
629 | B43_WARN_ON(1); | 648 | B43_WARN_ON(1); |
@@ -657,67 +676,54 @@ void b43_handle_txstatus(struct b43_wldev *dev, | |||
657 | dev->wl->ieee_stats.dot11RTSSuccessCount++; | 676 | dev->wl->ieee_stats.dot11RTSSuccessCount++; |
658 | } | 677 | } |
659 | 678 | ||
660 | b43_dma_handle_txstatus(dev, status); | 679 | if (b43_using_pio_transfers(dev)) |
680 | b43_pio_handle_txstatus(dev, status); | ||
681 | else | ||
682 | b43_dma_handle_txstatus(dev, status); | ||
661 | } | 683 | } |
662 | 684 | ||
663 | /* Handle TX status report as received through DMA/PIO queues */ | 685 | /* Fill out the mac80211 TXstatus report based on the b43-specific |
664 | void b43_handle_hwtxstatus(struct b43_wldev *dev, | 686 | * txstatus report data. This returns a boolean whether the frame was |
665 | const struct b43_hwtxstatus *hw) | 687 | * successfully transmitted. */ |
688 | bool b43_fill_txstatus_report(struct ieee80211_tx_status *report, | ||
689 | const struct b43_txstatus *status) | ||
666 | { | 690 | { |
667 | struct b43_txstatus status; | 691 | bool frame_success = 1; |
668 | u8 tmp; | 692 | |
669 | 693 | if (status->acked) { | |
670 | status.cookie = le16_to_cpu(hw->cookie); | 694 | /* The frame was ACKed. */ |
671 | status.seq = le16_to_cpu(hw->seq); | 695 | report->flags |= IEEE80211_TX_STATUS_ACK; |
672 | status.phy_stat = hw->phy_stat; | 696 | } else { |
673 | tmp = hw->count; | 697 | /* The frame was not ACKed... */ |
674 | status.frame_count = (tmp >> 4); | 698 | if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { |
675 | status.rts_count = (tmp & 0x0F); | 699 | /* ...but we expected an ACK. */ |
676 | tmp = hw->flags; | 700 | frame_success = 0; |
677 | status.supp_reason = ((tmp & 0x1C) >> 2); | 701 | report->excessive_retries = 1; |
678 | status.pm_indicated = !!(tmp & 0x80); | 702 | } |
679 | status.intermediate = !!(tmp & 0x40); | 703 | } |
680 | status.for_ampdu = !!(tmp & 0x20); | 704 | if (status->frame_count == 0) { |
681 | status.acked = !!(tmp & 0x02); | 705 | /* The frame was not transmitted at all. */ |
682 | 706 | report->retry_count = 0; | |
683 | b43_handle_txstatus(dev, &status); | 707 | } else |
708 | report->retry_count = status->frame_count - 1; | ||
709 | |||
710 | return frame_success; | ||
684 | } | 711 | } |
685 | 712 | ||
686 | /* Stop any TX operation on the device (suspend the hardware queues) */ | 713 | /* Stop any TX operation on the device (suspend the hardware queues) */ |
687 | void b43_tx_suspend(struct b43_wldev *dev) | 714 | void b43_tx_suspend(struct b43_wldev *dev) |
688 | { | 715 | { |
689 | b43_dma_tx_suspend(dev); | 716 | if (b43_using_pio_transfers(dev)) |
717 | b43_pio_tx_suspend(dev); | ||
718 | else | ||
719 | b43_dma_tx_suspend(dev); | ||
690 | } | 720 | } |
691 | 721 | ||
692 | /* Resume any TX operation on the device (resume the hardware queues) */ | 722 | /* Resume any TX operation on the device (resume the hardware queues) */ |
693 | void b43_tx_resume(struct b43_wldev *dev) | 723 | void b43_tx_resume(struct b43_wldev *dev) |
694 | { | 724 | { |
695 | b43_dma_tx_resume(dev); | 725 | if (b43_using_pio_transfers(dev)) |
696 | } | 726 | b43_pio_tx_resume(dev); |
697 | 727 | else | |
698 | #if 0 | 728 | b43_dma_tx_resume(dev); |
699 | static void upload_qos_parms(struct b43_wldev *dev, | ||
700 | const u16 * parms, u16 offset) | ||
701 | { | ||
702 | int i; | ||
703 | |||
704 | for (i = 0; i < B43_NR_QOSPARMS; i++) { | ||
705 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
706 | offset + (i * 2), parms[i]); | ||
707 | } | ||
708 | } | ||
709 | #endif | ||
710 | |||
711 | /* Initialize the QoS parameters */ | ||
712 | void b43_qos_init(struct b43_wldev *dev) | ||
713 | { | ||
714 | /* FIXME: This function must probably be called from the mac80211 | ||
715 | * config callback. */ | ||
716 | return; | ||
717 | |||
718 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | ||
719 | //FIXME kill magic | ||
720 | b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); | ||
721 | |||
722 | /*TODO: We might need some stack support here to get the values. */ | ||
723 | } | 729 | } |