diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-09-29 10:04:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-09-30 15:57:12 -0400 |
commit | 948d887dec1042a7d78ae311908113e26502062f (patch) | |
tree | e4240d0f45c0200d3625693bd6d543d243859d0a /net/mac80211 | |
parent | 60750397122fe0fb81a6e52fd790b3f749b6e010 (diff) |
mac80211: split PS buffers into ACs
For uAPSD support we'll need to have per-AC PS
buffers. As this is a major undertaking, split
the buffers before really adding support for
uAPSD. This already makes some reference to the
uapsd_queues variable, but for now that will
never be non-zero.
Since book-keeping is complicated, also change
the logic for keeping a maximum of frames only
and allow 64 frames per AC (up from 128 for a
station).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/debugfs_sta.c | 10 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 204 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 24 | ||||
-rw-r--r-- | net/mac80211/status.c | 17 | ||||
-rw-r--r-- | net/mac80211/tx.c | 42 |
5 files changed, 213 insertions, 84 deletions
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a01d2137fddc..20ec2b0cb3c1 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -78,8 +78,14 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file, | |||
78 | size_t count, loff_t *ppos) | 78 | size_t count, loff_t *ppos) |
79 | { | 79 | { |
80 | struct sta_info *sta = file->private_data; | 80 | struct sta_info *sta = file->private_data; |
81 | return mac80211_format_buffer(userbuf, count, ppos, "%u\n", | 81 | char buf[17*IEEE80211_NUM_ACS], *p = buf; |
82 | skb_queue_len(&sta->ps_tx_buf)); | 82 | int ac; |
83 | |||
84 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
85 | p += scnprintf(p, sizeof(buf)+buf-p, "AC%d: %d\n", ac, | ||
86 | skb_queue_len(&sta->ps_tx_buf[ac]) + | ||
87 | skb_queue_len(&sta->tx_filtered[ac])); | ||
88 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
83 | } | 89 | } |
84 | STA_OPS(num_ps_buf_frames); | 90 | STA_OPS(num_ps_buf_frames); |
85 | 91 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8dabe66fc37f..4d85672f0b8f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -309,8 +309,10 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
309 | */ | 309 | */ |
310 | sta->timer_to_tid[i] = i; | 310 | sta->timer_to_tid[i] = i; |
311 | } | 311 | } |
312 | skb_queue_head_init(&sta->ps_tx_buf); | 312 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
313 | skb_queue_head_init(&sta->tx_filtered); | 313 | skb_queue_head_init(&sta->ps_tx_buf[i]); |
314 | skb_queue_head_init(&sta->tx_filtered[i]); | ||
315 | } | ||
314 | 316 | ||
315 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 317 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
316 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); | 318 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); |
@@ -641,12 +643,32 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | |||
641 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | 643 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); |
642 | } | 644 | } |
643 | 645 | ||
646 | static unsigned long ieee80211_tids_for_ac(int ac) | ||
647 | { | ||
648 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ | ||
649 | switch (ac) { | ||
650 | case IEEE80211_AC_VO: | ||
651 | return BIT(6) | BIT(7); | ||
652 | case IEEE80211_AC_VI: | ||
653 | return BIT(4) | BIT(5); | ||
654 | case IEEE80211_AC_BE: | ||
655 | return BIT(0) | BIT(3); | ||
656 | case IEEE80211_AC_BK: | ||
657 | return BIT(1) | BIT(2); | ||
658 | default: | ||
659 | WARN_ON(1); | ||
660 | return 0; | ||
661 | } | ||
662 | } | ||
663 | |||
644 | void sta_info_recalc_tim(struct sta_info *sta) | 664 | void sta_info_recalc_tim(struct sta_info *sta) |
645 | { | 665 | { |
646 | struct ieee80211_local *local = sta->local; | 666 | struct ieee80211_local *local = sta->local; |
647 | struct ieee80211_if_ap *bss = sta->sdata->bss; | 667 | struct ieee80211_if_ap *bss = sta->sdata->bss; |
648 | unsigned long flags; | 668 | unsigned long flags; |
649 | bool have_data = false; | 669 | bool indicate_tim = false; |
670 | u8 ignore_for_tim = sta->sta.uapsd_queues; | ||
671 | int ac; | ||
650 | 672 | ||
651 | if (WARN_ON_ONCE(!sta->sdata->bss)) | 673 | if (WARN_ON_ONCE(!sta->sdata->bss)) |
652 | return; | 674 | return; |
@@ -658,21 +680,43 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
658 | if (sta->dead) | 680 | if (sta->dead) |
659 | goto done; | 681 | goto done; |
660 | 682 | ||
661 | have_data = test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF) || | 683 | /* |
662 | !skb_queue_empty(&sta->tx_filtered) || | 684 | * If all ACs are delivery-enabled then we should build |
663 | !skb_queue_empty(&sta->ps_tx_buf); | 685 | * the TIM bit for all ACs anyway; if only some are then |
686 | * we ignore those and build the TIM bit using only the | ||
687 | * non-enabled ones. | ||
688 | */ | ||
689 | if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) | ||
690 | ignore_for_tim = 0; | ||
691 | |||
692 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
693 | unsigned long tids; | ||
694 | |||
695 | if (ignore_for_tim & BIT(ac)) | ||
696 | continue; | ||
697 | |||
698 | indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) || | ||
699 | !skb_queue_empty(&sta->ps_tx_buf[ac]); | ||
700 | if (indicate_tim) | ||
701 | break; | ||
702 | |||
703 | tids = ieee80211_tids_for_ac(ac); | ||
704 | |||
705 | indicate_tim |= | ||
706 | sta->driver_buffered_tids & tids; | ||
707 | } | ||
664 | 708 | ||
665 | done: | 709 | done: |
666 | spin_lock_irqsave(&local->sta_lock, flags); | 710 | spin_lock_irqsave(&local->sta_lock, flags); |
667 | 711 | ||
668 | if (have_data) | 712 | if (indicate_tim) |
669 | __bss_tim_set(bss, sta->sta.aid); | 713 | __bss_tim_set(bss, sta->sta.aid); |
670 | else | 714 | else |
671 | __bss_tim_clear(bss, sta->sta.aid); | 715 | __bss_tim_clear(bss, sta->sta.aid); |
672 | 716 | ||
673 | if (local->ops->set_tim) { | 717 | if (local->ops->set_tim) { |
674 | local->tim_in_locked_section = true; | 718 | local->tim_in_locked_section = true; |
675 | drv_set_tim(local, &sta->sta, have_data); | 719 | drv_set_tim(local, &sta->sta, indicate_tim); |
676 | local->tim_in_locked_section = false; | 720 | local->tim_in_locked_section = false; |
677 | } | 721 | } |
678 | 722 | ||
@@ -699,16 +743,12 @@ static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) | |||
699 | } | 743 | } |
700 | 744 | ||
701 | 745 | ||
702 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | 746 | static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, |
703 | struct sta_info *sta) | 747 | struct sta_info *sta, int ac) |
704 | { | 748 | { |
705 | unsigned long flags; | 749 | unsigned long flags; |
706 | struct sk_buff *skb; | 750 | struct sk_buff *skb; |
707 | 751 | ||
708 | /* This is only necessary for stations on BSS interfaces */ | ||
709 | if (!sta->sdata->bss) | ||
710 | return false; | ||
711 | |||
712 | /* | 752 | /* |
713 | * First check for frames that should expire on the filtered | 753 | * First check for frames that should expire on the filtered |
714 | * queue. Frames here were rejected by the driver and are on | 754 | * queue. Frames here were rejected by the driver and are on |
@@ -717,13 +757,13 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
717 | * total_ps_buffered counter. | 757 | * total_ps_buffered counter. |
718 | */ | 758 | */ |
719 | for (;;) { | 759 | for (;;) { |
720 | spin_lock_irqsave(&sta->tx_filtered.lock, flags); | 760 | spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); |
721 | skb = skb_peek(&sta->tx_filtered); | 761 | skb = skb_peek(&sta->tx_filtered[ac]); |
722 | if (sta_info_buffer_expired(sta, skb)) | 762 | if (sta_info_buffer_expired(sta, skb)) |
723 | skb = __skb_dequeue(&sta->tx_filtered); | 763 | skb = __skb_dequeue(&sta->tx_filtered[ac]); |
724 | else | 764 | else |
725 | skb = NULL; | 765 | skb = NULL; |
726 | spin_unlock_irqrestore(&sta->tx_filtered.lock, flags); | 766 | spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); |
727 | 767 | ||
728 | /* | 768 | /* |
729 | * Frames are queued in order, so if this one | 769 | * Frames are queued in order, so if this one |
@@ -743,13 +783,13 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
743 | * buffered frames. | 783 | * buffered frames. |
744 | */ | 784 | */ |
745 | for (;;) { | 785 | for (;;) { |
746 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 786 | spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); |
747 | skb = skb_peek(&sta->ps_tx_buf); | 787 | skb = skb_peek(&sta->ps_tx_buf[ac]); |
748 | if (sta_info_buffer_expired(sta, skb)) | 788 | if (sta_info_buffer_expired(sta, skb)) |
749 | skb = __skb_dequeue(&sta->ps_tx_buf); | 789 | skb = __skb_dequeue(&sta->ps_tx_buf[ac]); |
750 | else | 790 | else |
751 | skb = NULL; | 791 | skb = NULL; |
752 | spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); | 792 | spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); |
753 | 793 | ||
754 | /* | 794 | /* |
755 | * frames are queued in order, so if this one | 795 | * frames are queued in order, so if this one |
@@ -779,8 +819,25 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
779 | * used to check whether the cleanup timer still needs to run, | 819 | * used to check whether the cleanup timer still needs to run, |
780 | * if there are no frames we don't need to rearm the timer. | 820 | * if there are no frames we don't need to rearm the timer. |
781 | */ | 821 | */ |
782 | return !(skb_queue_empty(&sta->ps_tx_buf) && | 822 | return !(skb_queue_empty(&sta->ps_tx_buf[ac]) && |
783 | skb_queue_empty(&sta->tx_filtered)); | 823 | skb_queue_empty(&sta->tx_filtered[ac])); |
824 | } | ||
825 | |||
826 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | ||
827 | struct sta_info *sta) | ||
828 | { | ||
829 | bool have_buffered = false; | ||
830 | int ac; | ||
831 | |||
832 | /* This is only necessary for stations on BSS interfaces */ | ||
833 | if (!sta->sdata->bss) | ||
834 | return false; | ||
835 | |||
836 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
837 | have_buffered |= | ||
838 | sta_info_cleanup_expire_buffered_ac(local, sta, ac); | ||
839 | |||
840 | return have_buffered; | ||
784 | } | 841 | } |
785 | 842 | ||
786 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 843 | static int __must_check __sta_info_destroy(struct sta_info *sta) |
@@ -788,7 +845,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
788 | struct ieee80211_local *local; | 845 | struct ieee80211_local *local; |
789 | struct ieee80211_sub_if_data *sdata; | 846 | struct ieee80211_sub_if_data *sdata; |
790 | unsigned long flags; | 847 | unsigned long flags; |
791 | int ret, i; | 848 | int ret, i, ac; |
792 | 849 | ||
793 | might_sleep(); | 850 | might_sleep(); |
794 | 851 | ||
@@ -856,9 +913,11 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
856 | */ | 913 | */ |
857 | synchronize_rcu(); | 914 | synchronize_rcu(); |
858 | 915 | ||
859 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf); | 916 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
860 | __skb_queue_purge(&sta->ps_tx_buf); | 917 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); |
861 | __skb_queue_purge(&sta->tx_filtered); | 918 | __skb_queue_purge(&sta->ps_tx_buf[ac]); |
919 | __skb_queue_purge(&sta->tx_filtered[ac]); | ||
920 | } | ||
862 | 921 | ||
863 | #ifdef CONFIG_MAC80211_MESH | 922 | #ifdef CONFIG_MAC80211_MESH |
864 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 923 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -1055,17 +1114,33 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1055 | { | 1114 | { |
1056 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1115 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1057 | struct ieee80211_local *local = sdata->local; | 1116 | struct ieee80211_local *local = sdata->local; |
1058 | int sent, buffered; | 1117 | struct sk_buff_head pending; |
1118 | int filtered = 0, buffered = 0, ac; | ||
1119 | |||
1120 | BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); | ||
1121 | sta->driver_buffered_tids = 0; | ||
1059 | 1122 | ||
1060 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | ||
1061 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1123 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1062 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 1124 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
1063 | 1125 | ||
1126 | skb_queue_head_init(&pending); | ||
1127 | |||
1064 | /* Send all buffered frames to the station */ | 1128 | /* Send all buffered frames to the station */ |
1065 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); | 1129 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
1066 | buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, | 1130 | int count = skb_queue_len(&pending), tmp; |
1067 | clear_sta_ps_flags, sta); | 1131 | |
1068 | sent += buffered; | 1132 | skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); |
1133 | tmp = skb_queue_len(&pending); | ||
1134 | filtered += tmp - count; | ||
1135 | count = tmp; | ||
1136 | |||
1137 | skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); | ||
1138 | tmp = skb_queue_len(&pending); | ||
1139 | buffered += tmp - count; | ||
1140 | } | ||
1141 | |||
1142 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | ||
1143 | |||
1069 | local->total_ps_buffered -= buffered; | 1144 | local->total_ps_buffered -= buffered; |
1070 | 1145 | ||
1071 | sta_info_recalc_tim(sta); | 1146 | sta_info_recalc_tim(sta); |
@@ -1073,7 +1148,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1073 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1148 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1074 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 1149 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
1075 | "since STA not sleeping anymore\n", sdata->name, | 1150 | "since STA not sleeping anymore\n", sdata->name, |
1076 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); | 1151 | sta->sta.addr, sta->sta.aid, filtered, buffered); |
1077 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1152 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1078 | } | 1153 | } |
1079 | 1154 | ||
@@ -1081,17 +1156,43 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1081 | { | 1156 | { |
1082 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1157 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1083 | struct ieee80211_local *local = sdata->local; | 1158 | struct ieee80211_local *local = sdata->local; |
1084 | struct sk_buff *skb; | 1159 | struct sk_buff *skb = NULL; |
1085 | int no_pending_pkts; | 1160 | bool more_data = false; |
1161 | int ac; | ||
1162 | u8 ignore_for_response = sta->sta.uapsd_queues; | ||
1086 | 1163 | ||
1087 | skb = skb_dequeue(&sta->tx_filtered); | 1164 | /* |
1088 | if (!skb) { | 1165 | * If all ACs are delivery-enabled then we should reply |
1089 | skb = skb_dequeue(&sta->ps_tx_buf); | 1166 | * from any of them, if only some are enabled we reply |
1090 | if (skb) | 1167 | * only from the non-enabled ones. |
1091 | local->total_ps_buffered--; | 1168 | */ |
1169 | if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) | ||
1170 | ignore_for_response = 0; | ||
1171 | |||
1172 | /* | ||
1173 | * Get response frame and more data bit for it. | ||
1174 | */ | ||
1175 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1176 | if (ignore_for_response & BIT(ac)) | ||
1177 | continue; | ||
1178 | |||
1179 | if (!skb) { | ||
1180 | skb = skb_dequeue(&sta->tx_filtered[ac]); | ||
1181 | if (!skb) { | ||
1182 | skb = skb_dequeue(&sta->ps_tx_buf[ac]); | ||
1183 | if (skb) | ||
1184 | local->total_ps_buffered--; | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* FIXME: take into account driver-buffered frames */ | ||
1189 | |||
1190 | if (!skb_queue_empty(&sta->tx_filtered[ac]) || | ||
1191 | !skb_queue_empty(&sta->ps_tx_buf[ac])) { | ||
1192 | more_data = true; | ||
1193 | break; | ||
1194 | } | ||
1092 | } | 1195 | } |
1093 | no_pending_pkts = skb_queue_empty(&sta->tx_filtered) && | ||
1094 | skb_queue_empty(&sta->ps_tx_buf); | ||
1095 | 1196 | ||
1096 | if (skb) { | 1197 | if (skb) { |
1097 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1198 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1105,14 +1206,13 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1105 | info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; | 1206 | info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; |
1106 | 1207 | ||
1107 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1208 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1108 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", | 1209 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll\n", |
1109 | sta->sta.addr, sta->sta.aid, | 1210 | sta->sta.addr, sta->sta.aid); |
1110 | skb_queue_len(&sta->ps_tx_buf)); | ||
1111 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1211 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1112 | 1212 | ||
1113 | /* Use MoreData flag to indicate whether there are more | 1213 | /* Use MoreData flag to indicate whether there are more |
1114 | * buffered frames for this STA */ | 1214 | * buffered frames for this STA */ |
1115 | if (no_pending_pkts) | 1215 | if (!more_data) |
1116 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | 1216 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); |
1117 | else | 1217 | else |
1118 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1218 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
@@ -1154,10 +1254,14 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | |||
1154 | { | 1254 | { |
1155 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1255 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1156 | 1256 | ||
1157 | if (!buffered) | 1257 | if (WARN_ON(tid >= STA_TID_NUM)) |
1158 | return; | 1258 | return; |
1159 | 1259 | ||
1160 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | 1260 | if (buffered) |
1261 | set_bit(tid, &sta->driver_buffered_tids); | ||
1262 | else | ||
1263 | clear_bit(tid, &sta->driver_buffered_tids); | ||
1264 | |||
1161 | sta_info_recalc_tim(sta); | 1265 | sta_info_recalc_tim(sta); |
1162 | } | 1266 | } |
1163 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); | 1267 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c9ffb7ce636b..8589afad3295 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -43,8 +43,6 @@ | |||
43 | * be in the queues | 43 | * be in the queues |
44 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping | 44 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
45 | * station in power-save mode, reply when the driver unblocks. | 45 | * station in power-save mode, reply when the driver unblocks. |
46 | * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal | ||
47 | * buffers. Automatically cleared on station wake-up. | ||
48 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. | 46 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
49 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | 47 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
50 | * packets. This means the link is enabled. | 48 | * packets. This means the link is enabled. |
@@ -63,7 +61,6 @@ enum ieee80211_sta_info_flags { | |||
63 | WLAN_STA_BLOCK_BA = 1<<11, | 61 | WLAN_STA_BLOCK_BA = 1<<11, |
64 | WLAN_STA_PS_DRIVER = 1<<12, | 62 | WLAN_STA_PS_DRIVER = 1<<12, |
65 | WLAN_STA_PSPOLL = 1<<13, | 63 | WLAN_STA_PSPOLL = 1<<13, |
66 | WLAN_STA_PS_DRIVER_BUF = 1<<14, | ||
67 | WLAN_STA_TDLS_PEER = 1<<15, | 64 | WLAN_STA_TDLS_PEER = 1<<15, |
68 | WLAN_STA_TDLS_PEER_AUTH = 1<<16, | 65 | WLAN_STA_TDLS_PEER_AUTH = 1<<16, |
69 | }; | 66 | }; |
@@ -212,11 +209,13 @@ struct sta_ampdu_mlme { | |||
212 | * @drv_unblock_wk: used for driver PS unblocking | 209 | * @drv_unblock_wk: used for driver PS unblocking |
213 | * @listen_interval: listen interval of this station, when we're acting as AP | 210 | * @listen_interval: listen interval of this station, when we're acting as AP |
214 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 211 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
215 | * @ps_tx_buf: buffer of frames to transmit to this station | 212 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station |
216 | * when it leaves power saving state | 213 | * when it leaves power saving state or polls |
217 | * @tx_filtered: buffer of frames we already tried to transmit | 214 | * @tx_filtered: buffers (per AC) of frames we already tried to |
218 | * but were filtered by hardware due to STA having entered | 215 | * transmit but were filtered by hardware due to STA having |
219 | * power saving state | 216 | * entered power saving state, these are also delivered to |
217 | * the station when it leaves powersave or polls for frames | ||
218 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on | ||
220 | * @rx_packets: Number of MSDUs received from this STA | 219 | * @rx_packets: Number of MSDUs received from this STA |
221 | * @rx_bytes: Number of bytes received from this STA | 220 | * @rx_bytes: Number of bytes received from this STA |
222 | * @wep_weak_iv_count: number of weak WEP IVs received from this station | 221 | * @wep_weak_iv_count: number of weak WEP IVs received from this station |
@@ -286,8 +285,9 @@ struct sta_info { | |||
286 | * STA powersave frame queues, no more than the internal | 285 | * STA powersave frame queues, no more than the internal |
287 | * locking required. | 286 | * locking required. |
288 | */ | 287 | */ |
289 | struct sk_buff_head ps_tx_buf; | 288 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; |
290 | struct sk_buff_head tx_filtered; | 289 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; |
290 | unsigned long driver_buffered_tids; | ||
291 | 291 | ||
292 | /* Updated from RX path only, no locking requirements */ | 292 | /* Updated from RX path only, no locking requirements */ |
293 | unsigned long rx_packets, rx_bytes; | 293 | unsigned long rx_packets, rx_bytes; |
@@ -434,8 +434,8 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | |||
434 | #define STA_HASH(sta) (sta[5]) | 434 | #define STA_HASH(sta) (sta[5]) |
435 | 435 | ||
436 | 436 | ||
437 | /* Maximum number of frames to buffer per power saving station */ | 437 | /* Maximum number of frames to buffer per power saving station per AC */ |
438 | #define STA_MAX_TX_BUFFER 128 | 438 | #define STA_MAX_TX_BUFFER 64 |
439 | 439 | ||
440 | /* Minimum buffered frame expiry time. If STA uses listen interval that is | 440 | /* Minimum buffered frame expiry time. If STA uses listen interval that is |
441 | * smaller than this value, the minimum value here is used instead. */ | 441 | * smaller than this value, the minimum value here is used instead. */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 783542a8ea20..c06857bbd573 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "rate.h" | 14 | #include "rate.h" |
15 | #include "mesh.h" | 15 | #include "mesh.h" |
16 | #include "led.h" | 16 | #include "led.h" |
17 | #include "wme.h" | ||
17 | 18 | ||
18 | 19 | ||
19 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 20 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
@@ -43,6 +44,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
43 | struct sk_buff *skb) | 44 | struct sk_buff *skb) |
44 | { | 45 | { |
45 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 46 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
47 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
48 | int ac; | ||
46 | 49 | ||
47 | /* | 50 | /* |
48 | * This skb 'survived' a round-trip through the driver, and | 51 | * This skb 'survived' a round-trip through the driver, and |
@@ -62,6 +65,14 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
62 | 65 | ||
63 | sta->tx_filtered_count++; | 66 | sta->tx_filtered_count++; |
64 | 67 | ||
68 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
69 | int tid = *ieee80211_get_qos_ctl(hdr) & | ||
70 | IEEE80211_QOS_CTL_TID_MASK; | ||
71 | ac = ieee802_1d_to_ac[tid & 7]; | ||
72 | } else { | ||
73 | ac = IEEE80211_AC_BE; | ||
74 | } | ||
75 | |||
65 | /* | 76 | /* |
66 | * Clear the TX filter mask for this STA when sending the next | 77 | * Clear the TX filter mask for this STA when sending the next |
67 | * packet. If the STA went to power save mode, this will happen | 78 | * packet. If the STA went to power save mode, this will happen |
@@ -104,8 +115,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
104 | * unknown. | 115 | * unknown. |
105 | */ | 116 | */ |
106 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | 117 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && |
107 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 118 | skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) { |
108 | skb_queue_tail(&sta->tx_filtered, skb); | 119 | skb_queue_tail(&sta->tx_filtered[ac], skb); |
109 | sta_info_recalc_tim(sta); | 120 | sta_info_recalc_tim(sta); |
110 | 121 | ||
111 | if (!timer_pending(&local->sta_cleanup)) | 122 | if (!timer_pending(&local->sta_cleanup)) |
@@ -127,7 +138,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
127 | if (net_ratelimit()) | 138 | if (net_ratelimit()) |
128 | wiphy_debug(local->hw.wiphy, | 139 | wiphy_debug(local->hw.wiphy, |
129 | "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", | 140 | "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", |
130 | skb_queue_len(&sta->tx_filtered), | 141 | skb_queue_len(&sta->tx_filtered[ac]), |
131 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | 142 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); |
132 | #endif | 143 | #endif |
133 | dev_kfree_skb(skb); | 144 | dev_kfree_skb(skb); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d6754908ff79..a1029449df44 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -343,13 +343,22 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
343 | total += skb_queue_len(&ap->ps_bc_buf); | 343 | total += skb_queue_len(&ap->ps_bc_buf); |
344 | } | 344 | } |
345 | 345 | ||
346 | /* | ||
347 | * Drop one frame from each station from the lowest-priority | ||
348 | * AC that has frames at all. | ||
349 | */ | ||
346 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 350 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
347 | skb = skb_dequeue(&sta->ps_tx_buf); | 351 | int ac; |
348 | if (skb) { | 352 | |
349 | purged++; | 353 | for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) { |
350 | dev_kfree_skb(skb); | 354 | skb = skb_dequeue(&sta->ps_tx_buf[ac]); |
355 | total += skb_queue_len(&sta->ps_tx_buf[ac]); | ||
356 | if (skb) { | ||
357 | purged++; | ||
358 | dev_kfree_skb(skb); | ||
359 | break; | ||
360 | } | ||
351 | } | 361 | } |
352 | total += skb_queue_len(&sta->ps_tx_buf); | ||
353 | } | 362 | } |
354 | 363 | ||
355 | rcu_read_unlock(); | 364 | rcu_read_unlock(); |
@@ -448,22 +457,21 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
448 | 457 | ||
449 | if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && | 458 | if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && |
450 | !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { | 459 | !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { |
460 | int ac = skb_get_queue_mapping(tx->skb); | ||
461 | |||
451 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 462 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
452 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " | 463 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", |
453 | "before %d)\n", | 464 | sta->sta.addr, sta->sta.aid, ac); |
454 | sta->sta.addr, sta->sta.aid, | ||
455 | skb_queue_len(&sta->ps_tx_buf)); | ||
456 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 465 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
457 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 466 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
458 | purge_old_ps_buffers(tx->local); | 467 | purge_old_ps_buffers(tx->local); |
459 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { | 468 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { |
460 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); | 469 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); |
461 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 470 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
462 | if (net_ratelimit()) { | 471 | if (net_ratelimit()) |
463 | printk(KERN_DEBUG "%s: STA %pM TX " | 472 | printk(KERN_DEBUG "%s: STA %pM TX buffer for " |
464 | "buffer full - dropping oldest frame\n", | 473 | "AC %d full - dropping oldest frame\n", |
465 | tx->sdata->name, sta->sta.addr); | 474 | tx->sdata->name, sta->sta.addr, ac); |
466 | } | ||
467 | #endif | 475 | #endif |
468 | dev_kfree_skb(old); | 476 | dev_kfree_skb(old); |
469 | } else | 477 | } else |
@@ -472,7 +480,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
472 | info->control.jiffies = jiffies; | 480 | info->control.jiffies = jiffies; |
473 | info->control.vif = &tx->sdata->vif; | 481 | info->control.vif = &tx->sdata->vif; |
474 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 482 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
475 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 483 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); |
476 | 484 | ||
477 | if (!timer_pending(&local->sta_cleanup)) | 485 | if (!timer_pending(&local->sta_cleanup)) |
478 | mod_timer(&local->sta_cleanup, | 486 | mod_timer(&local->sta_cleanup, |