aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-09-26 19:36:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-28 15:47:56 -0400
commit4bd437ea40b81fb4c047034de6dca1b5af496fb0 (patch)
tree3d002763f892f45437f63d89f93a6b48e2b8d689 /drivers/net/wireless
parent9c655c8be9053a65886ac3e06420399a9bfdbd70 (diff)
carl9170: revamp carl9170_tx_prepare
David Miller complained about the driver's excessive use of variables in __packed structs. While I did not fully agree with his sole "performance" argument on all accounts. I do see some room for improvement in hot-paths on architectures without an efficient access to unaligned elements. This first patch (dare I say?) optimizes an important tx hot-path in the driver: carl9170_tx_prepare. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c155
1 files changed, 75 insertions, 80 deletions
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e6be5e6c1723..b575c865142d 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;