diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/tx.c')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/tx.c | 192 |
1 files changed, 77 insertions, 115 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index e0d2374e0c7..b575c865142 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -760,8 +760,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
760 | struct carl9170_tx_info *arinfo; | 760 | struct carl9170_tx_info *arinfo; |
761 | unsigned int hw_queue; | 761 | unsigned int hw_queue; |
762 | int i; | 762 | int i; |
763 | u16 keytype = 0; | 763 | __le16 mac_tmp; |
764 | u16 len, icv = 0; | 764 | u16 len; |
765 | bool ampdu, no_ack; | 765 | bool ampdu, no_ack; |
766 | 766 | ||
767 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | 767 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); |
@@ -773,6 +773,10 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
773 | 773 | ||
774 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); | 774 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); |
775 | 775 | ||
776 | BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > | ||
777 | ((CARL9170_TX_SUPER_MISC_VIF_ID >> | ||
778 | CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); | ||
779 | |||
776 | hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; | 780 | hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; |
777 | 781 | ||
778 | hdr = (void *)skb->data; | 782 | hdr = (void *)skb->data; |
@@ -793,20 +797,37 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
793 | txc = (void *)skb_push(skb, sizeof(*txc)); | 797 | txc = (void *)skb_push(skb, sizeof(*txc)); |
794 | memset(txc, 0, sizeof(*txc)); | 798 | memset(txc, 0, sizeof(*txc)); |
795 | 799 | ||
796 | ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); | 800 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); |
801 | |||
802 | if (likely(cvif)) | ||
803 | SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id); | ||
804 | |||
805 | if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)) | ||
806 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; | ||
807 | |||
808 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) | ||
809 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; | ||
810 | |||
811 | mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | | ||
812 | AR9170_TX_MAC_BACKOFF); | ||
813 | mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) && | ||
814 | AR9170_TX_MAC_QOS); | ||
815 | |||
797 | no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); | 816 | no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); |
817 | if (unlikely(no_ack)) | ||
818 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); | ||
798 | 819 | ||
799 | if (info->control.hw_key) { | 820 | if (info->control.hw_key) { |
800 | icv = info->control.hw_key->icv_len; | 821 | len += info->control.hw_key->icv_len; |
801 | 822 | ||
802 | switch (info->control.hw_key->cipher) { | 823 | switch (info->control.hw_key->cipher) { |
803 | case WLAN_CIPHER_SUITE_WEP40: | 824 | case WLAN_CIPHER_SUITE_WEP40: |
804 | case WLAN_CIPHER_SUITE_WEP104: | 825 | case WLAN_CIPHER_SUITE_WEP104: |
805 | case WLAN_CIPHER_SUITE_TKIP: | 826 | case WLAN_CIPHER_SUITE_TKIP: |
806 | keytype = AR9170_TX_MAC_ENCR_RC4; | 827 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4); |
807 | break; | 828 | break; |
808 | case WLAN_CIPHER_SUITE_CCMP: | 829 | case WLAN_CIPHER_SUITE_CCMP: |
809 | keytype = AR9170_TX_MAC_ENCR_AES; | 830 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES); |
810 | break; | 831 | break; |
811 | default: | 832 | default: |
812 | WARN_ON(1); | 833 | WARN_ON(1); |
@@ -814,48 +835,58 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
814 | } | 835 | } |
815 | } | 836 | } |
816 | 837 | ||
817 | BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > | 838 | ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); |
818 | ((CARL9170_TX_SUPER_MISC_VIF_ID >> | 839 | if (ampdu) { |
819 | CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); | 840 | unsigned int density, factor; |
820 | |||
821 | txc->s.len = cpu_to_le16(len + sizeof(*txc)); | ||
822 | txc->f.length = cpu_to_le16(len + icv + 4); | ||
823 | SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, | ||
824 | cvif ? cvif->id : 0); | ||
825 | 841 | ||
826 | txc->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | | 842 | if (unlikely(!sta || !cvif)) |
827 | AR9170_TX_MAC_BACKOFF); | 843 | goto err_out; |
828 | 844 | ||
829 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); | 845 | factor = min_t(unsigned int, 1u, |
846 | info->control.sta->ht_cap.ampdu_factor); | ||
830 | 847 | ||
831 | txc->f.mac_control |= cpu_to_le16(hw_queue << AR9170_TX_MAC_QOS_S); | 848 | density = info->control.sta->ht_cap.ampdu_density; |
832 | txc->f.mac_control |= cpu_to_le16(keytype); | ||
833 | txc->f.phy_control = cpu_to_le32(0); | ||
834 | 849 | ||
835 | if (no_ack) | 850 | if (density) { |
836 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); | 851 | /* |
852 | * Watch out! | ||
853 | * | ||
854 | * Otus uses slightly different density values than | ||
855 | * those from the 802.11n spec. | ||
856 | */ | ||
837 | 857 | ||
838 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) | 858 | density = max_t(unsigned int, density + 1, 7u); |
839 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; | 859 | } |
840 | 860 | ||
841 | txrate = &info->control.rates[0]; | 861 | SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, |
842 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | 862 | txc->s.ampdu_settings, density); |
843 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
844 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
845 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
846 | 863 | ||
847 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); | 864 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, |
848 | txc->f.phy_control |= carl9170_tx_physet(ar, info, txrate); | 865 | txc->s.ampdu_settings, factor); |
849 | 866 | ||
850 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 867 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { |
851 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | ||
852 | txrate = &info->control.rates[i]; | 868 | txrate = &info->control.rates[i]; |
853 | if (txrate->idx >= 0) | 869 | if (txrate->idx >= 0) { |
870 | txc->s.ri[i] = | ||
871 | CARL9170_TX_SUPER_RI_AMPDU; | ||
872 | |||
873 | if (WARN_ON(!(txrate->flags & | ||
874 | IEEE80211_TX_RC_MCS))) { | ||
875 | /* | ||
876 | * Not sure if it's even possible | ||
877 | * to aggregate non-ht rates with | ||
878 | * this HW. | ||
879 | */ | ||
880 | goto err_out; | ||
881 | } | ||
854 | continue; | 882 | continue; |
883 | } | ||
855 | 884 | ||
856 | txrate->idx = 0; | 885 | txrate->idx = 0; |
857 | txrate->count = ar->hw->max_rate_tries; | 886 | txrate->count = ar->hw->max_rate_tries; |
858 | } | 887 | } |
888 | |||
889 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
859 | } | 890 | } |
860 | 891 | ||
861 | /* | 892 | /* |
@@ -878,57 +909,21 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
878 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << | 909 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << |
879 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | 910 | CARL9170_TX_SUPER_RI_ERP_PROT_S); |
880 | 911 | ||
881 | /* | ||
882 | * unaggregated fallback, in case aggregation | ||
883 | * proves to be unsuccessful and unreliable. | ||
884 | */ | ||
885 | if (ampdu && i < 3) | ||
886 | txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; | ||
887 | |||
888 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); | 912 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); |
889 | } | 913 | } |
890 | 914 | ||
891 | if (ieee80211_is_probe_resp(hdr->frame_control)) | 915 | txrate = &info->control.rates[0]; |
892 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; | 916 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); |
893 | |||
894 | if (ampdu) { | ||
895 | unsigned int density, factor; | ||
896 | |||
897 | if (unlikely(!sta || !cvif)) | ||
898 | goto err_out; | ||
899 | |||
900 | density = info->control.sta->ht_cap.ampdu_density; | ||
901 | factor = info->control.sta->ht_cap.ampdu_factor; | ||
902 | |||
903 | if (density) { | ||
904 | /* | ||
905 | * Watch out! | ||
906 | * | ||
907 | * Otus uses slightly different density values than | ||
908 | * those from the 802.11n spec. | ||
909 | */ | ||
910 | |||
911 | density = max_t(unsigned int, density + 1, 7u); | ||
912 | } | ||
913 | |||
914 | factor = min_t(unsigned int, 1u, factor); | ||
915 | |||
916 | SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, | ||
917 | txc->s.ampdu_settings, density); | ||
918 | 917 | ||
919 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, | 918 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) |
920 | txc->s.ampdu_settings, factor); | 919 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); |
920 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
921 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
921 | 922 | ||
922 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) { | 923 | txc->s.len = cpu_to_le16(skb->len); |
923 | txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | 924 | txc->f.length = cpu_to_le16(len + FCS_LEN); |
924 | } else { | 925 | txc->f.mac_control = mac_tmp; |
925 | /* | 926 | txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); |
926 | * Not sure if it's even possible to aggregate | ||
927 | * non-ht rates with this HW. | ||
928 | */ | ||
929 | WARN_ON_ONCE(1); | ||
930 | } | ||
931 | } | ||
932 | 927 | ||
933 | arinfo = (void *)info->rate_driver_data; | 928 | arinfo = (void *)info->rate_driver_data; |
934 | arinfo->timeout = jiffies; | 929 | arinfo->timeout = jiffies; |
@@ -1042,41 +1037,8 @@ retry: | |||
1042 | queue = TID_TO_WME_AC(tid_info->tid); | 1037 | queue = TID_TO_WME_AC(tid_info->tid); |
1043 | 1038 | ||
1044 | spin_lock_bh(&tid_info->lock); | 1039 | spin_lock_bh(&tid_info->lock); |
1045 | if (tid_info->state != CARL9170_TID_STATE_XMIT) { | 1040 | if (tid_info->state != CARL9170_TID_STATE_XMIT) |
1046 | first = skb_peek(&tid_info->queue); | 1041 | goto processed; |
1047 | if (first) { | ||
1048 | struct ieee80211_tx_info *txinfo; | ||
1049 | struct carl9170_tx_info *arinfo; | ||
1050 | |||
1051 | txinfo = IEEE80211_SKB_CB(first); | ||
1052 | arinfo = (void *) txinfo->rate_driver_data; | ||
1053 | |||
1054 | if (time_is_after_jiffies(arinfo->timeout + | ||
1055 | msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)) | ||
1056 | == true) | ||
1057 | goto processed; | ||
1058 | |||
1059 | /* | ||
1060 | * We've been waiting for the frame which | ||
1061 | * matches "snx" (start sequence of the | ||
1062 | * next aggregate) for some time now. | ||
1063 | * | ||
1064 | * But it never arrived. Therefore | ||
1065 | * jump to the next available frame | ||
1066 | * and kick-start the transmission. | ||
1067 | * | ||
1068 | * Note: This might induce odd latency | ||
1069 | * spikes because the receiver will be | ||
1070 | * waiting for the lost frame too. | ||
1071 | */ | ||
1072 | ar->tx_ampdu_timeout++; | ||
1073 | |||
1074 | tid_info->snx = carl9170_get_seq(first); | ||
1075 | tid_info->state = CARL9170_TID_STATE_XMIT; | ||
1076 | } else { | ||
1077 | goto processed; | ||
1078 | } | ||
1079 | } | ||
1080 | 1042 | ||
1081 | tid_info->counter++; | 1043 | tid_info->counter++; |
1082 | first = skb_peek(&tid_info->queue); | 1044 | first = skb_peek(&tid_info->queue); |