diff options
author | Christian Lamparter <chunkeey@web.de> | 2008-10-18 17:18:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-10 15:10:16 -0500 |
commit | 94585b090baf982a850678a1dc3395bce0c1e302 (patch) | |
tree | d77c0abac8629b6c73b8e5d44b516b1cefe90f7d /drivers/net/wireless/p54 | |
parent | 9e7f3f8e4acdc480584d6b5e6a6be5d1f7bda8fa (diff) |
p54: put broadcast frames into the right queues
stlc45xx's specs finally brought some light what all the 4 extra queues for.
now CAB data and managment frames have their own queue.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ae8d1f666314..e93bca8263cd 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -902,6 +902,55 @@ free: | |||
902 | } | 902 | } |
903 | EXPORT_SYMBOL_GPL(p54_read_eeprom); | 903 | EXPORT_SYMBOL_GPL(p54_read_eeprom); |
904 | 904 | ||
905 | static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, | ||
906 | struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len, | ||
907 | u16 *flags, u16 *aid) | ||
908 | { | ||
909 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
910 | struct p54_common *priv = dev->priv; | ||
911 | int ret = 0; | ||
912 | |||
913 | if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { | ||
914 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
915 | *aid = 0; | ||
916 | *queue = 0; | ||
917 | *extra_len = IEEE80211_MAX_TIM_LEN; | ||
918 | *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP; | ||
919 | return 0; | ||
920 | } else if (ieee80211_is_probe_resp(hdr->frame_control)) { | ||
921 | *aid = 0; | ||
922 | *queue = 2; | ||
923 | *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP | | ||
924 | P54_HDR_FLAG_DATA_OUT_NOCANCEL; | ||
925 | return 0; | ||
926 | } else { | ||
927 | *queue = 2; | ||
928 | ret = 0; | ||
929 | } | ||
930 | } else { | ||
931 | *queue += 4; | ||
932 | ret = 1; | ||
933 | } | ||
934 | |||
935 | switch (priv->mode) { | ||
936 | case NL80211_IFTYPE_STATION: | ||
937 | *aid = 1; | ||
938 | break; | ||
939 | case NL80211_IFTYPE_AP: | ||
940 | case NL80211_IFTYPE_ADHOC: | ||
941 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
942 | *aid = 0; | ||
943 | *queue = 3; | ||
944 | return 0; | ||
945 | } | ||
946 | if (info->control.sta) | ||
947 | *aid = info->control.sta->aid; | ||
948 | else | ||
949 | *flags = P54_HDR_FLAG_DATA_OUT_NOCANCEL; | ||
950 | } | ||
951 | return ret; | ||
952 | } | ||
953 | |||
905 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 954 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
906 | { | 955 | { |
907 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 956 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -909,22 +958,26 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
909 | struct p54_common *priv = dev->priv; | 958 | struct p54_common *priv = dev->priv; |
910 | struct p54_hdr *hdr; | 959 | struct p54_hdr *hdr; |
911 | struct p54_tx_data *txhdr; | 960 | struct p54_tx_data *txhdr; |
912 | size_t padding, len; | 961 | size_t padding, len, tim_len; |
913 | int i, j, ridx; | 962 | int i, j, ridx; |
914 | u16 hdr_flags = 0; | 963 | u16 hdr_flags = 0, aid = 0; |
915 | u8 rate; | 964 | u8 rate, queue; |
916 | u8 cts_rate = 0x20; | 965 | u8 cts_rate = 0x20; |
917 | u8 rc_flags; | 966 | u8 rc_flags; |
918 | u8 calculated_tries[4]; | 967 | u8 calculated_tries[4]; |
919 | u8 nrates = 0, nremaining = 8; | 968 | u8 nrates = 0, nremaining = 8; |
920 | 969 | ||
921 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; | 970 | queue = skb_get_queue_mapping(skb); |
922 | if (unlikely(current_queue->len > current_queue->limit)) | 971 | |
923 | return NETDEV_TX_BUSY; | 972 | if (p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid)) { |
924 | current_queue->len++; | 973 | current_queue = &priv->tx_stats[queue]; |
925 | current_queue->count++; | 974 | if (unlikely(current_queue->len > current_queue->limit)) |
926 | if (current_queue->len == current_queue->limit) | 975 | return NETDEV_TX_BUSY; |
927 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | 976 | current_queue->len++; |
977 | current_queue->count++; | ||
978 | if (current_queue->len == current_queue->limit) | ||
979 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | ||
980 | } | ||
928 | 981 | ||
929 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; | 982 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; |
930 | len = skb->len; | 983 | len = skb->len; |
@@ -935,7 +988,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
935 | if (padding) | 988 | if (padding) |
936 | hdr_flags |= P54_HDR_FLAG_DATA_ALIGN; | 989 | hdr_flags |= P54_HDR_FLAG_DATA_ALIGN; |
937 | hdr->len = cpu_to_le16(len); | 990 | hdr->len = cpu_to_le16(len); |
938 | hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); | 991 | hdr->type = cpu_to_le16(aid); |
939 | hdr->rts_tries = info->control.rates[0].count; | 992 | hdr->rts_tries = info->control.rates[0].count; |
940 | 993 | ||
941 | /* | 994 | /* |
@@ -1013,7 +1066,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1013 | txhdr->rts_rate_idx = 0; | 1066 | txhdr->rts_rate_idx = 0; |
1014 | txhdr->key_type = 0; | 1067 | txhdr->key_type = 0; |
1015 | txhdr->key_len = 0; | 1068 | txhdr->key_len = 0; |
1016 | txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; | 1069 | txhdr->hw_queue = queue; |
1017 | txhdr->backlog = 32; | 1070 | txhdr->backlog = 32; |
1018 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 1071 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
1019 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? | 1072 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? |
@@ -1024,7 +1077,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1024 | txhdr->align[0] = padding; | 1077 | txhdr->align[0] = padding; |
1025 | 1078 | ||
1026 | /* modifies skb->cb and with it info, so must be last! */ | 1079 | /* modifies skb->cb and with it info, so must be last! */ |
1027 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len))) { | 1080 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) { |
1028 | skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); | 1081 | skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); |
1029 | if (current_queue) { | 1082 | if (current_queue) { |
1030 | current_queue->len--; | 1083 | current_queue->len--; |
@@ -1509,8 +1562,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
1509 | priv = dev->priv; | 1562 | priv = dev->priv; |
1510 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1563 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
1511 | skb_queue_head_init(&priv->tx_queue); | 1564 | skb_queue_head_init(&priv->tx_queue); |
1512 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ | 1565 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1513 | IEEE80211_HW_RX_INCLUDES_FCS | | ||
1514 | IEEE80211_HW_SIGNAL_DBM | | 1566 | IEEE80211_HW_SIGNAL_DBM | |
1515 | IEEE80211_HW_NOISE_DBM; | 1567 | IEEE80211_HW_NOISE_DBM; |
1516 | 1568 | ||