Commit 50fb2e4572141770380f5919793c6e575fa3474b
Committed by
John W. Linville
1 parent
65a0667b43
Exists in
master
and in
7 other branches
mac80211: remove rate_control_clear
"Clearing" the rate control algorithm is pointless, none of the algorithms actually uses this operation and it's not even invoked properly for all channel switching. Also, there's no need to since rate control algorithms work per station. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 8 changed files with 0 additions and 47 deletions Inline Diff
drivers/net/wireless/ath9k/rc.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Video54 Technologies, Inc. | 2 | * Copyright (c) 2004 Video54 Technologies, Inc. |
3 | * Copyright (c) 2004-2008 Atheros Communications, Inc. | 3 | * Copyright (c) 2004-2008 Atheros Communications, Inc. |
4 | * | 4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. | 7 | * copyright notice and this permission notice appear in all copies. |
8 | * | 8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * Atheros rate control algorithm | 19 | * Atheros rate control algorithm |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "core.h" | 22 | #include "core.h" |
23 | /* FIXME: remove this include! */ | 23 | /* FIXME: remove this include! */ |
24 | #include "../net/mac80211/rate.h" | 24 | #include "../net/mac80211/rate.h" |
25 | 25 | ||
26 | static u32 tx_triglevel_max; | 26 | static u32 tx_triglevel_max; |
27 | 27 | ||
28 | static struct ath_rate_table ar5416_11na_ratetable = { | 28 | static struct ath_rate_table ar5416_11na_ratetable = { |
29 | 42, | 29 | 42, |
30 | { | 30 | { |
31 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 31 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ |
32 | 5400, 0x0b, 0x00, 12, | 32 | 5400, 0x0b, 0x00, 12, |
33 | 0, 2, 1, 0, 0, 0, 0, 0 }, | 33 | 0, 2, 1, 0, 0, 0, 0, 0 }, |
34 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 34 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ |
35 | 7800, 0x0f, 0x00, 18, | 35 | 7800, 0x0f, 0x00, 18, |
36 | 0, 3, 1, 1, 1, 1, 1, 0 }, | 36 | 0, 3, 1, 1, 1, 1, 1, 0 }, |
37 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 37 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ |
38 | 10000, 0x0a, 0x00, 24, | 38 | 10000, 0x0a, 0x00, 24, |
39 | 2, 4, 2, 2, 2, 2, 2, 0 }, | 39 | 2, 4, 2, 2, 2, 2, 2, 0 }, |
40 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 40 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ |
41 | 13900, 0x0e, 0x00, 36, | 41 | 13900, 0x0e, 0x00, 36, |
42 | 2, 6, 2, 3, 3, 3, 3, 0 }, | 42 | 2, 6, 2, 3, 3, 3, 3, 0 }, |
43 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 43 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ |
44 | 17300, 0x09, 0x00, 48, | 44 | 17300, 0x09, 0x00, 48, |
45 | 4, 10, 3, 4, 4, 4, 4, 0 }, | 45 | 4, 10, 3, 4, 4, 4, 4, 0 }, |
46 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 46 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ |
47 | 23000, 0x0d, 0x00, 72, | 47 | 23000, 0x0d, 0x00, 72, |
48 | 4, 14, 3, 5, 5, 5, 5, 0 }, | 48 | 4, 14, 3, 5, 5, 5, 5, 0 }, |
49 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 49 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ |
50 | 27400, 0x08, 0x00, 96, | 50 | 27400, 0x08, 0x00, 96, |
51 | 4, 20, 3, 6, 6, 6, 6, 0 }, | 51 | 4, 20, 3, 6, 6, 6, 6, 0 }, |
52 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 52 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ |
53 | 29300, 0x0c, 0x00, 108, | 53 | 29300, 0x0c, 0x00, 108, |
54 | 4, 23, 3, 7, 7, 7, 7, 0 }, | 54 | 4, 23, 3, 7, 7, 7, 7, 0 }, |
55 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 55 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
56 | 6400, 0x80, 0x00, 0, | 56 | 6400, 0x80, 0x00, 0, |
57 | 0, 2, 3, 8, 24, 8, 24, 3216 }, | 57 | 0, 2, 3, 8, 24, 8, 24, 3216 }, |
58 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | 58 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ |
59 | 12700, 0x81, 0x00, 1, | 59 | 12700, 0x81, 0x00, 1, |
60 | 2, 4, 3, 9, 25, 9, 25, 6434 }, | 60 | 2, 4, 3, 9, 25, 9, 25, 6434 }, |
61 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 61 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
62 | 18800, 0x82, 0x00, 2, | 62 | 18800, 0x82, 0x00, 2, |
63 | 2, 6, 3, 10, 26, 10, 26, 9650 }, | 63 | 2, 6, 3, 10, 26, 10, 26, 9650 }, |
64 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | 64 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ |
65 | 25000, 0x83, 0x00, 3, | 65 | 25000, 0x83, 0x00, 3, |
66 | 4, 10, 3, 11, 27, 11, 27, 12868 }, | 66 | 4, 10, 3, 11, 27, 11, 27, 12868 }, |
67 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | 67 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ |
68 | 36700, 0x84, 0x00, 4, | 68 | 36700, 0x84, 0x00, 4, |
69 | 4, 14, 3, 12, 28, 12, 28, 19304 }, | 69 | 4, 14, 3, 12, 28, 12, 28, 19304 }, |
70 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | 70 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ |
71 | 48100, 0x85, 0x00, 5, | 71 | 48100, 0x85, 0x00, 5, |
72 | 4, 20, 3, 13, 29, 13, 29, 25740 }, | 72 | 4, 20, 3, 13, 29, 13, 29, 25740 }, |
73 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 73 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
74 | 53500, 0x86, 0x00, 6, | 74 | 53500, 0x86, 0x00, 6, |
75 | 4, 23, 3, 14, 30, 14, 30, 28956 }, | 75 | 4, 23, 3, 14, 30, 14, 30, 28956 }, |
76 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | 76 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ |
77 | 59000, 0x87, 0x00, 7, | 77 | 59000, 0x87, 0x00, 7, |
78 | 4, 25, 3, 15, 31, 15, 32, 32180 }, | 78 | 4, 25, 3, 15, 31, 15, 32, 32180 }, |
79 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | 79 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ |
80 | 12700, 0x88, 0x00, | 80 | 12700, 0x88, 0x00, |
81 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, | 81 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, |
82 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | 82 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ |
83 | 24800, 0x89, 0x00, 9, | 83 | 24800, 0x89, 0x00, 9, |
84 | 2, 4, 3, 17, 34, 17, 34, 12860 }, | 84 | 2, 4, 3, 17, 34, 17, 34, 12860 }, |
85 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | 85 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ |
86 | 36600, 0x8a, 0x00, 10, | 86 | 36600, 0x8a, 0x00, 10, |
87 | 2, 6, 3, 18, 35, 18, 35, 19300 }, | 87 | 2, 6, 3, 18, 35, 18, 35, 19300 }, |
88 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | 88 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ |
89 | 48100, 0x8b, 0x00, 11, | 89 | 48100, 0x8b, 0x00, 11, |
90 | 4, 10, 3, 19, 36, 19, 36, 25736 }, | 90 | 4, 10, 3, 19, 36, 19, 36, 25736 }, |
91 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | 91 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ |
92 | 69500, 0x8c, 0x00, 12, | 92 | 69500, 0x8c, 0x00, 12, |
93 | 4, 14, 3, 20, 37, 20, 37, 38600 }, | 93 | 4, 14, 3, 20, 37, 20, 37, 38600 }, |
94 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | 94 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ |
95 | 89500, 0x8d, 0x00, 13, | 95 | 89500, 0x8d, 0x00, 13, |
96 | 4, 20, 3, 21, 38, 21, 38, 51472 }, | 96 | 4, 20, 3, 21, 38, 21, 38, 51472 }, |
97 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | 97 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ |
98 | 98900, 0x8e, 0x00, 14, | 98 | 98900, 0x8e, 0x00, 14, |
99 | 4, 23, 3, 22, 39, 22, 39, 57890 }, | 99 | 4, 23, 3, 22, 39, 22, 39, 57890 }, |
100 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | 100 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ |
101 | 108300, 0x8f, 0x00, 15, | 101 | 108300, 0x8f, 0x00, 15, |
102 | 4, 25, 3, 23, 40, 23, 41, 64320 }, | 102 | 4, 25, 3, 23, 40, 23, 41, 64320 }, |
103 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 103 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
104 | 13200, 0x80, 0x00, 0, | 104 | 13200, 0x80, 0x00, 0, |
105 | 0, 2, 3, 8, 24, 24, 24, 6684 }, | 105 | 0, 2, 3, 8, 24, 24, 24, 6684 }, |
106 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 106 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
107 | 25900, 0x81, 0x00, 1, | 107 | 25900, 0x81, 0x00, 1, |
108 | 2, 4, 3, 9, 25, 25, 25, 13368 }, | 108 | 2, 4, 3, 9, 25, 25, 25, 13368 }, |
109 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 109 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
110 | 38600, 0x82, 0x00, 2, | 110 | 38600, 0x82, 0x00, 2, |
111 | 2, 6, 3, 10, 26, 26, 26, 20052 }, | 111 | 2, 6, 3, 10, 26, 26, 26, 20052 }, |
112 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | 112 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ |
113 | 49800, 0x83, 0x00, 3, | 113 | 49800, 0x83, 0x00, 3, |
114 | 4, 10, 3, 11, 27, 27, 27, 26738 }, | 114 | 4, 10, 3, 11, 27, 27, 27, 26738 }, |
115 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | 115 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ |
116 | 72200, 0x84, 0x00, 4, | 116 | 72200, 0x84, 0x00, 4, |
117 | 4, 14, 3, 12, 28, 28, 28, 40104 }, | 117 | 4, 14, 3, 12, 28, 28, 28, 40104 }, |
118 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | 118 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ |
119 | 92900, 0x85, 0x00, 5, | 119 | 92900, 0x85, 0x00, 5, |
120 | 4, 20, 3, 13, 29, 29, 29, 53476 }, | 120 | 4, 20, 3, 13, 29, 29, 29, 53476 }, |
121 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 121 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
122 | 102700, 0x86, 0x00, 6, | 122 | 102700, 0x86, 0x00, 6, |
123 | 4, 23, 3, 14, 30, 30, 30, 60156 }, | 123 | 4, 23, 3, 14, 30, 30, 30, 60156 }, |
124 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | 124 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ |
125 | 112000, 0x87, 0x00, 7, | 125 | 112000, 0x87, 0x00, 7, |
126 | 4, 25, 3, 15, 31, 32, 32, 66840 }, | 126 | 4, 25, 3, 15, 31, 32, 32, 66840 }, |
127 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 127 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
128 | 122000, 0x87, 0x00, 7, | 128 | 122000, 0x87, 0x00, 7, |
129 | 4, 25, 3, 15, 31, 32, 32, 74200 }, | 129 | 4, 25, 3, 15, 31, 32, 32, 74200 }, |
130 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | 130 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ |
131 | 25800, 0x88, 0x00, 8, | 131 | 25800, 0x88, 0x00, 8, |
132 | 0, 2, 3, 16, 33, 33, 33, 13360 }, | 132 | 0, 2, 3, 16, 33, 33, 33, 13360 }, |
133 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | 133 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ |
134 | 49800, 0x89, 0x00, 9, | 134 | 49800, 0x89, 0x00, 9, |
135 | 2, 4, 3, 17, 34, 34, 34, 26720 }, | 135 | 2, 4, 3, 17, 34, 34, 34, 26720 }, |
136 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | 136 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ |
137 | 71900, 0x8a, 0x00, 10, | 137 | 71900, 0x8a, 0x00, 10, |
138 | 2, 6, 3, 18, 35, 35, 35, 40080 }, | 138 | 2, 6, 3, 18, 35, 35, 35, 40080 }, |
139 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | 139 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ |
140 | 92500, 0x8b, 0x00, 11, | 140 | 92500, 0x8b, 0x00, 11, |
141 | 4, 10, 3, 19, 36, 36, 36, 53440 }, | 141 | 4, 10, 3, 19, 36, 36, 36, 53440 }, |
142 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | 142 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ |
143 | 130300, 0x8c, 0x00, 12, | 143 | 130300, 0x8c, 0x00, 12, |
144 | 4, 14, 3, 20, 37, 37, 37, 80160 }, | 144 | 4, 14, 3, 20, 37, 37, 37, 80160 }, |
145 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | 145 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ |
146 | 162800, 0x8d, 0x00, 13, | 146 | 162800, 0x8d, 0x00, 13, |
147 | 4, 20, 3, 21, 38, 38, 38, 106880 }, | 147 | 4, 20, 3, 21, 38, 38, 38, 106880 }, |
148 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | 148 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ |
149 | 178200, 0x8e, 0x00, 14, | 149 | 178200, 0x8e, 0x00, 14, |
150 | 4, 23, 3, 22, 39, 39, 39, 120240 }, | 150 | 4, 23, 3, 22, 39, 39, 39, 120240 }, |
151 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | 151 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ |
152 | 192100, 0x8f, 0x00, 15, | 152 | 192100, 0x8f, 0x00, 15, |
153 | 4, 25, 3, 23, 40, 41, 41, 133600 }, | 153 | 4, 25, 3, 23, 40, 41, 41, 133600 }, |
154 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 154 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
155 | 207000, 0x8f, 0x00, 15, | 155 | 207000, 0x8f, 0x00, 15, |
156 | 4, 25, 3, 23, 40, 41, 41, 148400 }, | 156 | 4, 25, 3, 23, 40, 41, 41, 148400 }, |
157 | }, | 157 | }, |
158 | 50, /* probe interval */ | 158 | 50, /* probe interval */ |
159 | 50, /* rssi reduce interval */ | 159 | 50, /* rssi reduce interval */ |
160 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 160 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
161 | }; | 161 | }; |
162 | 162 | ||
163 | /* TRUE_ALL - valid for 20/40/Legacy, | 163 | /* TRUE_ALL - valid for 20/40/Legacy, |
164 | * TRUE - Legacy only, | 164 | * TRUE - Legacy only, |
165 | * TRUE_20 - HT 20 only, | 165 | * TRUE_20 - HT 20 only, |
166 | * TRUE_40 - HT 40 only */ | 166 | * TRUE_40 - HT 40 only */ |
167 | 167 | ||
168 | /* 4ms frame limit not used for NG mode. The values filled | 168 | /* 4ms frame limit not used for NG mode. The values filled |
169 | * for HT are the 64K max aggregate limit */ | 169 | * for HT are the 64K max aggregate limit */ |
170 | 170 | ||
171 | static struct ath_rate_table ar5416_11ng_ratetable = { | 171 | static struct ath_rate_table ar5416_11ng_ratetable = { |
172 | 46, | 172 | 46, |
173 | { | 173 | { |
174 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 174 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */ |
175 | 900, 0x1b, 0x00, 2, | 175 | 900, 0x1b, 0x00, 2, |
176 | 0, 0, 1, 0, 0, 0, 0, 0 }, | 176 | 0, 0, 1, 0, 0, 0, 0, 0 }, |
177 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 177 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */ |
178 | 1900, 0x1a, 0x04, 4, | 178 | 1900, 0x1a, 0x04, 4, |
179 | 1, 1, 1, 1, 1, 1, 1, 0 }, | 179 | 1, 1, 1, 1, 1, 1, 1, 0 }, |
180 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 180 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ |
181 | 4900, 0x19, 0x04, 11, | 181 | 4900, 0x19, 0x04, 11, |
182 | 2, 2, 2, 2, 2, 2, 2, 0 }, | 182 | 2, 2, 2, 2, 2, 2, 2, 0 }, |
183 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 183 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */ |
184 | 8100, 0x18, 0x04, 22, | 184 | 8100, 0x18, 0x04, 22, |
185 | 3, 3, 2, 3, 3, 3, 3, 0 }, | 185 | 3, 3, 2, 3, 3, 3, 3, 0 }, |
186 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 186 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ |
187 | 5400, 0x0b, 0x00, 12, | 187 | 5400, 0x0b, 0x00, 12, |
188 | 4, 2, 1, 4, 4, 4, 4, 0 }, | 188 | 4, 2, 1, 4, 4, 4, 4, 0 }, |
189 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 189 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ |
190 | 7800, 0x0f, 0x00, 18, | 190 | 7800, 0x0f, 0x00, 18, |
191 | 4, 3, 1, 5, 5, 5, 5, 0 }, | 191 | 4, 3, 1, 5, 5, 5, 5, 0 }, |
192 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 192 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ |
193 | 10100, 0x0a, 0x00, 24, | 193 | 10100, 0x0a, 0x00, 24, |
194 | 6, 4, 1, 6, 6, 6, 6, 0 }, | 194 | 6, 4, 1, 6, 6, 6, 6, 0 }, |
195 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 195 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ |
196 | 14100, 0x0e, 0x00, 36, | 196 | 14100, 0x0e, 0x00, 36, |
197 | 6, 6, 2, 7, 7, 7, 7, 0 }, | 197 | 6, 6, 2, 7, 7, 7, 7, 0 }, |
198 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 198 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ |
199 | 17700, 0x09, 0x00, 48, | 199 | 17700, 0x09, 0x00, 48, |
200 | 8, 10, 3, 8, 8, 8, 8, 0 }, | 200 | 8, 10, 3, 8, 8, 8, 8, 0 }, |
201 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 201 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ |
202 | 23700, 0x0d, 0x00, 72, | 202 | 23700, 0x0d, 0x00, 72, |
203 | 8, 14, 3, 9, 9, 9, 9, 0 }, | 203 | 8, 14, 3, 9, 9, 9, 9, 0 }, |
204 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 204 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ |
205 | 27400, 0x08, 0x00, 96, | 205 | 27400, 0x08, 0x00, 96, |
206 | 8, 20, 3, 10, 10, 10, 10, 0 }, | 206 | 8, 20, 3, 10, 10, 10, 10, 0 }, |
207 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 207 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ |
208 | 30900, 0x0c, 0x00, 108, | 208 | 30900, 0x0c, 0x00, 108, |
209 | 8, 23, 3, 11, 11, 11, 11, 0 }, | 209 | 8, 23, 3, 11, 11, 11, 11, 0 }, |
210 | { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 210 | { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
211 | 6400, 0x80, 0x00, 0, | 211 | 6400, 0x80, 0x00, 0, |
212 | 4, 2, 3, 12, 28, 12, 28, 3216 }, | 212 | 4, 2, 3, 12, 28, 12, 28, 3216 }, |
213 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | 213 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ |
214 | 12700, 0x81, 0x00, 1, | 214 | 12700, 0x81, 0x00, 1, |
215 | 6, 4, 3, 13, 29, 13, 29, 6434 }, | 215 | 6, 4, 3, 13, 29, 13, 29, 6434 }, |
216 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 216 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
217 | 18800, 0x82, 0x00, 2, | 217 | 18800, 0x82, 0x00, 2, |
218 | 6, 6, 3, 14, 30, 14, 30, 9650 }, | 218 | 6, 6, 3, 14, 30, 14, 30, 9650 }, |
219 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | 219 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ |
220 | 25000, 0x83, 0x00, 3, | 220 | 25000, 0x83, 0x00, 3, |
221 | 8, 10, 3, 15, 31, 15, 31, 12868 }, | 221 | 8, 10, 3, 15, 31, 15, 31, 12868 }, |
222 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | 222 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ |
223 | 36700, 0x84, 0x00, 4, | 223 | 36700, 0x84, 0x00, 4, |
224 | 8, 14, 3, 16, 32, 16, 32, 19304 }, | 224 | 8, 14, 3, 16, 32, 16, 32, 19304 }, |
225 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | 225 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ |
226 | 48100, 0x85, 0x00, 5, | 226 | 48100, 0x85, 0x00, 5, |
227 | 8, 20, 3, 17, 33, 17, 33, 25740 }, | 227 | 8, 20, 3, 17, 33, 17, 33, 25740 }, |
228 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 228 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
229 | 53500, 0x86, 0x00, 6, | 229 | 53500, 0x86, 0x00, 6, |
230 | 8, 23, 3, 18, 34, 18, 34, 28956 }, | 230 | 8, 23, 3, 18, 34, 18, 34, 28956 }, |
231 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | 231 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ |
232 | 59000, 0x87, 0x00, 7, | 232 | 59000, 0x87, 0x00, 7, |
233 | 8, 25, 3, 19, 35, 19, 36, 32180 }, | 233 | 8, 25, 3, 19, 35, 19, 36, 32180 }, |
234 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | 234 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ |
235 | 12700, 0x88, 0x00, 8, | 235 | 12700, 0x88, 0x00, 8, |
236 | 4, 2, 3, 20, 37, 20, 37, 6430 }, | 236 | 4, 2, 3, 20, 37, 20, 37, 6430 }, |
237 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | 237 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ |
238 | 24800, 0x89, 0x00, 9, | 238 | 24800, 0x89, 0x00, 9, |
239 | 6, 4, 3, 21, 38, 21, 38, 12860 }, | 239 | 6, 4, 3, 21, 38, 21, 38, 12860 }, |
240 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | 240 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ |
241 | 36600, 0x8a, 0x00, 10, | 241 | 36600, 0x8a, 0x00, 10, |
242 | 6, 6, 3, 22, 39, 22, 39, 19300 }, | 242 | 6, 6, 3, 22, 39, 22, 39, 19300 }, |
243 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | 243 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ |
244 | 48100, 0x8b, 0x00, 11, | 244 | 48100, 0x8b, 0x00, 11, |
245 | 8, 10, 3, 23, 40, 23, 40, 25736 }, | 245 | 8, 10, 3, 23, 40, 23, 40, 25736 }, |
246 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | 246 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ |
247 | 69500, 0x8c, 0x00, 12, | 247 | 69500, 0x8c, 0x00, 12, |
248 | 8, 14, 3, 24, 41, 24, 41, 38600 }, | 248 | 8, 14, 3, 24, 41, 24, 41, 38600 }, |
249 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | 249 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ |
250 | 89500, 0x8d, 0x00, 13, | 250 | 89500, 0x8d, 0x00, 13, |
251 | 8, 20, 3, 25, 42, 25, 42, 51472 }, | 251 | 8, 20, 3, 25, 42, 25, 42, 51472 }, |
252 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | 252 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ |
253 | 98900, 0x8e, 0x00, 14, | 253 | 98900, 0x8e, 0x00, 14, |
254 | 8, 23, 3, 26, 43, 26, 44, 57890 }, | 254 | 8, 23, 3, 26, 43, 26, 44, 57890 }, |
255 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | 255 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ |
256 | 108300, 0x8f, 0x00, 15, | 256 | 108300, 0x8f, 0x00, 15, |
257 | 8, 25, 3, 27, 44, 27, 45, 64320 }, | 257 | 8, 25, 3, 27, 44, 27, 45, 64320 }, |
258 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 258 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
259 | 13200, 0x80, 0x00, 0, | 259 | 13200, 0x80, 0x00, 0, |
260 | 8, 2, 3, 12, 28, 28, 28, 6684 }, | 260 | 8, 2, 3, 12, 28, 28, 28, 6684 }, |
261 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 261 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
262 | 25900, 0x81, 0x00, 1, | 262 | 25900, 0x81, 0x00, 1, |
263 | 8, 4, 3, 13, 29, 29, 29, 13368 }, | 263 | 8, 4, 3, 13, 29, 29, 29, 13368 }, |
264 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 264 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
265 | 38600, 0x82, 0x00, 2, | 265 | 38600, 0x82, 0x00, 2, |
266 | 8, 6, 3, 14, 30, 30, 30, 20052 }, | 266 | 8, 6, 3, 14, 30, 30, 30, 20052 }, |
267 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | 267 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ |
268 | 49800, 0x83, 0x00, 3, | 268 | 49800, 0x83, 0x00, 3, |
269 | 8, 10, 3, 15, 31, 31, 31, 26738 }, | 269 | 8, 10, 3, 15, 31, 31, 31, 26738 }, |
270 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | 270 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ |
271 | 72200, 0x84, 0x00, 4, | 271 | 72200, 0x84, 0x00, 4, |
272 | 8, 14, 3, 16, 32, 32, 32, 40104 }, | 272 | 8, 14, 3, 16, 32, 32, 32, 40104 }, |
273 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | 273 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ |
274 | 92900, 0x85, 0x00, 5, | 274 | 92900, 0x85, 0x00, 5, |
275 | 8, 20, 3, 17, 33, 33, 33, 53476 }, | 275 | 8, 20, 3, 17, 33, 33, 33, 53476 }, |
276 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 276 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
277 | 102700, 0x86, 0x00, 6, | 277 | 102700, 0x86, 0x00, 6, |
278 | 8, 23, 3, 18, 34, 34, 34, 60156 }, | 278 | 8, 23, 3, 18, 34, 34, 34, 60156 }, |
279 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | 279 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ |
280 | 112000, 0x87, 0x00, 7, | 280 | 112000, 0x87, 0x00, 7, |
281 | 8, 23, 3, 19, 35, 36, 36, 66840 }, | 281 | 8, 23, 3, 19, 35, 36, 36, 66840 }, |
282 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 282 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
283 | 122000, 0x87, 0x00, 7, | 283 | 122000, 0x87, 0x00, 7, |
284 | 8, 25, 3, 19, 35, 36, 36, 74200 }, | 284 | 8, 25, 3, 19, 35, 36, 36, 74200 }, |
285 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | 285 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ |
286 | 25800, 0x88, 0x00, 8, | 286 | 25800, 0x88, 0x00, 8, |
287 | 8, 2, 3, 20, 37, 37, 37, 13360 }, | 287 | 8, 2, 3, 20, 37, 37, 37, 13360 }, |
288 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | 288 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ |
289 | 49800, 0x89, 0x00, 9, | 289 | 49800, 0x89, 0x00, 9, |
290 | 8, 4, 3, 21, 38, 38, 38, 26720 }, | 290 | 8, 4, 3, 21, 38, 38, 38, 26720 }, |
291 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | 291 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ |
292 | 71900, 0x8a, 0x00, 10, | 292 | 71900, 0x8a, 0x00, 10, |
293 | 8, 6, 3, 22, 39, 39, 39, 40080 }, | 293 | 8, 6, 3, 22, 39, 39, 39, 40080 }, |
294 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | 294 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ |
295 | 92500, 0x8b, 0x00, 11, | 295 | 92500, 0x8b, 0x00, 11, |
296 | 8, 10, 3, 23, 40, 40, 40, 53440 }, | 296 | 8, 10, 3, 23, 40, 40, 40, 53440 }, |
297 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | 297 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ |
298 | 130300, 0x8c, 0x00, 12, | 298 | 130300, 0x8c, 0x00, 12, |
299 | 8, 14, 3, 24, 41, 41, 41, 80160 }, | 299 | 8, 14, 3, 24, 41, 41, 41, 80160 }, |
300 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | 300 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ |
301 | 162800, 0x8d, 0x00, 13, | 301 | 162800, 0x8d, 0x00, 13, |
302 | 8, 20, 3, 25, 42, 42, 42, 106880 }, | 302 | 8, 20, 3, 25, 42, 42, 42, 106880 }, |
303 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | 303 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ |
304 | 178200, 0x8e, 0x00, 14, | 304 | 178200, 0x8e, 0x00, 14, |
305 | 8, 23, 3, 26, 43, 43, 43, 120240 }, | 305 | 8, 23, 3, 26, 43, 43, 43, 120240 }, |
306 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | 306 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ |
307 | 192100, 0x8f, 0x00, 15, | 307 | 192100, 0x8f, 0x00, 15, |
308 | 8, 23, 3, 27, 44, 45, 45, 133600 }, | 308 | 8, 23, 3, 27, 44, 45, 45, 133600 }, |
309 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 309 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
310 | 207000, 0x8f, 0x00, 15, | 310 | 207000, 0x8f, 0x00, 15, |
311 | 8, 25, 3, 27, 44, 45, 45, 148400 }, | 311 | 8, 25, 3, 27, 44, 45, 45, 148400 }, |
312 | }, | 312 | }, |
313 | 50, /* probe interval */ | 313 | 50, /* probe interval */ |
314 | 50, /* rssi reduce interval */ | 314 | 50, /* rssi reduce interval */ |
315 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 315 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static struct ath_rate_table ar5416_11a_ratetable = { | 318 | static struct ath_rate_table ar5416_11a_ratetable = { |
319 | 8, | 319 | 8, |
320 | { | 320 | { |
321 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 321 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ |
322 | 5400, 0x0b, 0x00, (0x80|12), | 322 | 5400, 0x0b, 0x00, (0x80|12), |
323 | 0, 2, 1, 0, 0 }, | 323 | 0, 2, 1, 0, 0 }, |
324 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 324 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ |
325 | 7800, 0x0f, 0x00, 18, | 325 | 7800, 0x0f, 0x00, 18, |
326 | 0, 3, 1, 1, 0 }, | 326 | 0, 3, 1, 1, 0 }, |
327 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 327 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ |
328 | 10000, 0x0a, 0x00, (0x80|24), | 328 | 10000, 0x0a, 0x00, (0x80|24), |
329 | 2, 4, 2, 2, 0 }, | 329 | 2, 4, 2, 2, 0 }, |
330 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 330 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ |
331 | 13900, 0x0e, 0x00, 36, | 331 | 13900, 0x0e, 0x00, 36, |
332 | 2, 6, 2, 3, 0 }, | 332 | 2, 6, 2, 3, 0 }, |
333 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 333 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ |
334 | 17300, 0x09, 0x00, (0x80|48), | 334 | 17300, 0x09, 0x00, (0x80|48), |
335 | 4, 10, 3, 4, 0 }, | 335 | 4, 10, 3, 4, 0 }, |
336 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 336 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ |
337 | 23000, 0x0d, 0x00, 72, | 337 | 23000, 0x0d, 0x00, 72, |
338 | 4, 14, 3, 5, 0 }, | 338 | 4, 14, 3, 5, 0 }, |
339 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 339 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ |
340 | 27400, 0x08, 0x00, 96, | 340 | 27400, 0x08, 0x00, 96, |
341 | 4, 19, 3, 6, 0 }, | 341 | 4, 19, 3, 6, 0 }, |
342 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 342 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ |
343 | 29300, 0x0c, 0x00, 108, | 343 | 29300, 0x0c, 0x00, 108, |
344 | 4, 23, 3, 7, 0 }, | 344 | 4, 23, 3, 7, 0 }, |
345 | }, | 345 | }, |
346 | 50, /* probe interval */ | 346 | 50, /* probe interval */ |
347 | 50, /* rssi reduce interval */ | 347 | 50, /* rssi reduce interval */ |
348 | 0, /* Phy rates allowed initially */ | 348 | 0, /* Phy rates allowed initially */ |
349 | }; | 349 | }; |
350 | 350 | ||
351 | static struct ath_rate_table ar5416_11a_ratetable_Half = { | 351 | static struct ath_rate_table ar5416_11a_ratetable_Half = { |
352 | 8, | 352 | 8, |
353 | { | 353 | { |
354 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 6 Mb */ | 354 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 6 Mb */ |
355 | 2700, 0x0b, 0x00, (0x80|6), | 355 | 2700, 0x0b, 0x00, (0x80|6), |
356 | 0, 2, 1, 0, 0}, | 356 | 0, 2, 1, 0, 0}, |
357 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 9 Mb */ | 357 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 9 Mb */ |
358 | 3900, 0x0f, 0x00, 9, | 358 | 3900, 0x0f, 0x00, 9, |
359 | 0, 3, 1, 1, 0 }, | 359 | 0, 3, 1, 1, 0 }, |
360 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 12 Mb */ | 360 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 12 Mb */ |
361 | 5000, 0x0a, 0x00, (0x80|12), | 361 | 5000, 0x0a, 0x00, (0x80|12), |
362 | 2, 4, 2, 2, 0 }, | 362 | 2, 4, 2, 2, 0 }, |
363 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 18 Mb */ | 363 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 18 Mb */ |
364 | 6950, 0x0e, 0x00, 18, | 364 | 6950, 0x0e, 0x00, 18, |
365 | 2, 6, 2, 3, 0 }, | 365 | 2, 6, 2, 3, 0 }, |
366 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 24 Mb */ | 366 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 24 Mb */ |
367 | 8650, 0x09, 0x00, (0x80|24), | 367 | 8650, 0x09, 0x00, (0x80|24), |
368 | 4, 10, 3, 4, 0 }, | 368 | 4, 10, 3, 4, 0 }, |
369 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 36 Mb */ | 369 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 36 Mb */ |
370 | 11500, 0x0d, 0x00, 36, | 370 | 11500, 0x0d, 0x00, 36, |
371 | 4, 14, 3, 5, 0 }, | 371 | 4, 14, 3, 5, 0 }, |
372 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 48 Mb */ | 372 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 48 Mb */ |
373 | 13700, 0x08, 0x00, 48, | 373 | 13700, 0x08, 0x00, 48, |
374 | 4, 19, 3, 6, 0 }, | 374 | 4, 19, 3, 6, 0 }, |
375 | { TRUE, TRUE, WLAN_PHY_OFDM, 27000, /* 54 Mb */ | 375 | { TRUE, TRUE, WLAN_PHY_OFDM, 27000, /* 54 Mb */ |
376 | 14650, 0x0c, 0x00, 54, | 376 | 14650, 0x0c, 0x00, 54, |
377 | 4, 23, 3, 7, 0 }, | 377 | 4, 23, 3, 7, 0 }, |
378 | }, | 378 | }, |
379 | 50, /* probe interval */ | 379 | 50, /* probe interval */ |
380 | 50, /* rssi reduce interval */ | 380 | 50, /* rssi reduce interval */ |
381 | 0, /* Phy rates allowed initially */ | 381 | 0, /* Phy rates allowed initially */ |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static struct ath_rate_table ar5416_11a_ratetable_Quarter = { | 384 | static struct ath_rate_table ar5416_11a_ratetable_Quarter = { |
385 | 8, | 385 | 8, |
386 | { | 386 | { |
387 | { TRUE, TRUE, WLAN_PHY_OFDM, 1500, /* 6 Mb */ | 387 | { TRUE, TRUE, WLAN_PHY_OFDM, 1500, /* 6 Mb */ |
388 | 1350, 0x0b, 0x00, (0x80|3), | 388 | 1350, 0x0b, 0x00, (0x80|3), |
389 | 0, 2, 1, 0, 0 }, | 389 | 0, 2, 1, 0, 0 }, |
390 | { TRUE, TRUE, WLAN_PHY_OFDM, 2250, /* 9 Mb */ | 390 | { TRUE, TRUE, WLAN_PHY_OFDM, 2250, /* 9 Mb */ |
391 | 1950, 0x0f, 0x00, 4, | 391 | 1950, 0x0f, 0x00, 4, |
392 | 0, 3, 1, 1, 0 }, | 392 | 0, 3, 1, 1, 0 }, |
393 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 12 Mb */ | 393 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 12 Mb */ |
394 | 2500, 0x0a, 0x00, (0x80|6), | 394 | 2500, 0x0a, 0x00, (0x80|6), |
395 | 2, 4, 2, 2, 0 }, | 395 | 2, 4, 2, 2, 0 }, |
396 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 18 Mb */ | 396 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 18 Mb */ |
397 | 3475, 0x0e, 0x00, 9, | 397 | 3475, 0x0e, 0x00, 9, |
398 | 2, 6, 2, 3, 0 }, | 398 | 2, 6, 2, 3, 0 }, |
399 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 25 Mb */ | 399 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 25 Mb */ |
400 | 4325, 0x09, 0x00, (0x80|12), | 400 | 4325, 0x09, 0x00, (0x80|12), |
401 | 4, 10, 3, 4, 0 }, | 401 | 4, 10, 3, 4, 0 }, |
402 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 36 Mb */ | 402 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 36 Mb */ |
403 | 5750, 0x0d, 0x00, 18, | 403 | 5750, 0x0d, 0x00, 18, |
404 | 4, 14, 3, 5, 0 }, | 404 | 4, 14, 3, 5, 0 }, |
405 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 48 Mb */ | 405 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 48 Mb */ |
406 | 6850, 0x08, 0x00, 24, | 406 | 6850, 0x08, 0x00, 24, |
407 | 4, 19, 3, 6, 0 }, | 407 | 4, 19, 3, 6, 0 }, |
408 | { TRUE, TRUE, WLAN_PHY_OFDM, 13500, /* 54 Mb */ | 408 | { TRUE, TRUE, WLAN_PHY_OFDM, 13500, /* 54 Mb */ |
409 | 7325, 0x0c, 0x00, 27, | 409 | 7325, 0x0c, 0x00, 27, |
410 | 4, 23, 3, 7, 0 }, | 410 | 4, 23, 3, 7, 0 }, |
411 | }, | 411 | }, |
412 | 50, /* probe interval */ | 412 | 50, /* probe interval */ |
413 | 50, /* rssi reduce interval */ | 413 | 50, /* rssi reduce interval */ |
414 | 0, /* Phy rates allowed initially */ | 414 | 0, /* Phy rates allowed initially */ |
415 | }; | 415 | }; |
416 | 416 | ||
417 | static struct ath_rate_table ar5416_11g_ratetable = { | 417 | static struct ath_rate_table ar5416_11g_ratetable = { |
418 | 12, | 418 | 12, |
419 | { | 419 | { |
420 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 420 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ |
421 | 900, 0x1b, 0x00, 2, | 421 | 900, 0x1b, 0x00, 2, |
422 | 0, 0, 1, 0, 0 }, | 422 | 0, 0, 1, 0, 0 }, |
423 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 423 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ |
424 | 1900, 0x1a, 0x04, 4, | 424 | 1900, 0x1a, 0x04, 4, |
425 | 1, 1, 1, 1, 0 }, | 425 | 1, 1, 1, 1, 0 }, |
426 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 426 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ |
427 | 4900, 0x19, 0x04, 11, | 427 | 4900, 0x19, 0x04, 11, |
428 | 2, 2, 2, 2, 0 }, | 428 | 2, 2, 2, 2, 0 }, |
429 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 429 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ |
430 | 8100, 0x18, 0x04, 22, | 430 | 8100, 0x18, 0x04, 22, |
431 | 3, 3, 2, 3, 0 }, | 431 | 3, 3, 2, 3, 0 }, |
432 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 432 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ |
433 | 5400, 0x0b, 0x00, 12, | 433 | 5400, 0x0b, 0x00, 12, |
434 | 4, 2, 1, 4, 0 }, | 434 | 4, 2, 1, 4, 0 }, |
435 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 435 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ |
436 | 7800, 0x0f, 0x00, 18, | 436 | 7800, 0x0f, 0x00, 18, |
437 | 4, 3, 1, 5, 0 }, | 437 | 4, 3, 1, 5, 0 }, |
438 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 438 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ |
439 | 10000, 0x0a, 0x00, 24, | 439 | 10000, 0x0a, 0x00, 24, |
440 | 6, 4, 1, 6, 0 }, | 440 | 6, 4, 1, 6, 0 }, |
441 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 441 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ |
442 | 13900, 0x0e, 0x00, 36, | 442 | 13900, 0x0e, 0x00, 36, |
443 | 6, 6, 2, 7, 0 }, | 443 | 6, 6, 2, 7, 0 }, |
444 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 444 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ |
445 | 17300, 0x09, 0x00, 48, | 445 | 17300, 0x09, 0x00, 48, |
446 | 8, 10, 3, 8, 0 }, | 446 | 8, 10, 3, 8, 0 }, |
447 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 447 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ |
448 | 23000, 0x0d, 0x00, 72, | 448 | 23000, 0x0d, 0x00, 72, |
449 | 8, 14, 3, 9, 0 }, | 449 | 8, 14, 3, 9, 0 }, |
450 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 450 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ |
451 | 27400, 0x08, 0x00, 96, | 451 | 27400, 0x08, 0x00, 96, |
452 | 8, 19, 3, 10, 0 }, | 452 | 8, 19, 3, 10, 0 }, |
453 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 453 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ |
454 | 29300, 0x0c, 0x00, 108, | 454 | 29300, 0x0c, 0x00, 108, |
455 | 8, 23, 3, 11, 0 }, | 455 | 8, 23, 3, 11, 0 }, |
456 | }, | 456 | }, |
457 | 50, /* probe interval */ | 457 | 50, /* probe interval */ |
458 | 50, /* rssi reduce interval */ | 458 | 50, /* rssi reduce interval */ |
459 | 0, /* Phy rates allowed initially */ | 459 | 0, /* Phy rates allowed initially */ |
460 | }; | 460 | }; |
461 | 461 | ||
462 | static struct ath_rate_table ar5416_11b_ratetable = { | 462 | static struct ath_rate_table ar5416_11b_ratetable = { |
463 | 4, | 463 | 4, |
464 | { | 464 | { |
465 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 465 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ |
466 | 900, 0x1b, 0x00, (0x80|2), | 466 | 900, 0x1b, 0x00, (0x80|2), |
467 | 0, 0, 1, 0, 0 }, | 467 | 0, 0, 1, 0, 0 }, |
468 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 468 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ |
469 | 1800, 0x1a, 0x04, (0x80|4), | 469 | 1800, 0x1a, 0x04, (0x80|4), |
470 | 1, 1, 1, 1, 0 }, | 470 | 1, 1, 1, 1, 0 }, |
471 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 471 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ |
472 | 4300, 0x19, 0x04, (0x80|11), | 472 | 4300, 0x19, 0x04, (0x80|11), |
473 | 1, 2, 2, 2, 0 }, | 473 | 1, 2, 2, 2, 0 }, |
474 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 474 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ |
475 | 7100, 0x18, 0x04, (0x80|22), | 475 | 7100, 0x18, 0x04, (0x80|22), |
476 | 1, 4, 100, 3, 0 }, | 476 | 1, 4, 100, 3, 0 }, |
477 | }, | 477 | }, |
478 | 100, /* probe interval */ | 478 | 100, /* probe interval */ |
479 | 100, /* rssi reduce interval */ | 479 | 100, /* rssi reduce interval */ |
480 | 0, /* Phy rates allowed initially */ | 480 | 0, /* Phy rates allowed initially */ |
481 | }; | 481 | }; |
482 | 482 | ||
483 | static void ar5416_attach_ratetables(struct ath_rate_softc *sc) | 483 | static void ar5416_attach_ratetables(struct ath_rate_softc *sc) |
484 | { | 484 | { |
485 | /* | 485 | /* |
486 | * Attach rate tables. | 486 | * Attach rate tables. |
487 | */ | 487 | */ |
488 | sc->hw_rate_table[ATH9K_MODE_11B] = &ar5416_11b_ratetable; | 488 | sc->hw_rate_table[ATH9K_MODE_11B] = &ar5416_11b_ratetable; |
489 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; | 489 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; |
490 | sc->hw_rate_table[ATH9K_MODE_11G] = &ar5416_11g_ratetable; | 490 | sc->hw_rate_table[ATH9K_MODE_11G] = &ar5416_11g_ratetable; |
491 | 491 | ||
492 | sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable; | 492 | sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable; |
493 | sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable; | 493 | sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable; |
494 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = | 494 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = |
495 | &ar5416_11na_ratetable; | 495 | &ar5416_11na_ratetable; |
496 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = | 496 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = |
497 | &ar5416_11na_ratetable; | 497 | &ar5416_11na_ratetable; |
498 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = | 498 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = |
499 | &ar5416_11ng_ratetable; | 499 | &ar5416_11ng_ratetable; |
500 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = | 500 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = |
501 | &ar5416_11ng_ratetable; | 501 | &ar5416_11ng_ratetable; |
502 | } | 502 | } |
503 | 503 | ||
504 | static void ar5416_setquarter_ratetable(struct ath_rate_softc *sc) | 504 | static void ar5416_setquarter_ratetable(struct ath_rate_softc *sc) |
505 | { | 505 | { |
506 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Quarter; | 506 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Quarter; |
507 | return; | 507 | return; |
508 | } | 508 | } |
509 | 509 | ||
510 | static void ar5416_sethalf_ratetable(struct ath_rate_softc *sc) | 510 | static void ar5416_sethalf_ratetable(struct ath_rate_softc *sc) |
511 | { | 511 | { |
512 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Half; | 512 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Half; |
513 | return; | 513 | return; |
514 | } | 514 | } |
515 | 515 | ||
516 | static void ar5416_setfull_ratetable(struct ath_rate_softc *sc) | 516 | static void ar5416_setfull_ratetable(struct ath_rate_softc *sc) |
517 | { | 517 | { |
518 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; | 518 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; |
519 | return; | 519 | return; |
520 | } | 520 | } |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * Return the median of three numbers | 523 | * Return the median of three numbers |
524 | */ | 524 | */ |
525 | static inline int8_t median(int8_t a, int8_t b, int8_t c) | 525 | static inline int8_t median(int8_t a, int8_t b, int8_t c) |
526 | { | 526 | { |
527 | if (a >= b) { | 527 | if (a >= b) { |
528 | if (b >= c) | 528 | if (b >= c) |
529 | return b; | 529 | return b; |
530 | else if (a > c) | 530 | else if (a > c) |
531 | return c; | 531 | return c; |
532 | else | 532 | else |
533 | return a; | 533 | return a; |
534 | } else { | 534 | } else { |
535 | if (a >= c) | 535 | if (a >= c) |
536 | return a; | 536 | return a; |
537 | else if (b >= c) | 537 | else if (b >= c) |
538 | return c; | 538 | return c; |
539 | else | 539 | else |
540 | return b; | 540 | return b; |
541 | } | 541 | } |
542 | } | 542 | } |
543 | 543 | ||
544 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, | 544 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, |
545 | struct ath_tx_ratectrl *rate_ctrl) | 545 | struct ath_tx_ratectrl *rate_ctrl) |
546 | { | 546 | { |
547 | u8 i, j, idx, idx_next; | 547 | u8 i, j, idx, idx_next; |
548 | 548 | ||
549 | for (i = rate_ctrl->max_valid_rate - 1; i > 0; i--) { | 549 | for (i = rate_ctrl->max_valid_rate - 1; i > 0; i--) { |
550 | for (j = 0; j <= i-1; j++) { | 550 | for (j = 0; j <= i-1; j++) { |
551 | idx = rate_ctrl->valid_rate_index[j]; | 551 | idx = rate_ctrl->valid_rate_index[j]; |
552 | idx_next = rate_ctrl->valid_rate_index[j+1]; | 552 | idx_next = rate_ctrl->valid_rate_index[j+1]; |
553 | 553 | ||
554 | if (rate_table->info[idx].ratekbps > | 554 | if (rate_table->info[idx].ratekbps > |
555 | rate_table->info[idx_next].ratekbps) { | 555 | rate_table->info[idx_next].ratekbps) { |
556 | rate_ctrl->valid_rate_index[j] = idx_next; | 556 | rate_ctrl->valid_rate_index[j] = idx_next; |
557 | rate_ctrl->valid_rate_index[j+1] = idx; | 557 | rate_ctrl->valid_rate_index[j+1] = idx; |
558 | } | 558 | } |
559 | } | 559 | } |
560 | } | 560 | } |
561 | } | 561 | } |
562 | 562 | ||
563 | /* Access functions for valid_txrate_mask */ | 563 | /* Access functions for valid_txrate_mask */ |
564 | 564 | ||
565 | static void ath_rc_init_valid_txmask(struct ath_tx_ratectrl *rate_ctrl) | 565 | static void ath_rc_init_valid_txmask(struct ath_tx_ratectrl *rate_ctrl) |
566 | { | 566 | { |
567 | u8 i; | 567 | u8 i; |
568 | 568 | ||
569 | for (i = 0; i < rate_ctrl->rate_table_size; i++) | 569 | for (i = 0; i < rate_ctrl->rate_table_size; i++) |
570 | rate_ctrl->valid_rate_index[i] = FALSE; | 570 | rate_ctrl->valid_rate_index[i] = FALSE; |
571 | } | 571 | } |
572 | 572 | ||
573 | static inline void ath_rc_set_valid_txmask(struct ath_tx_ratectrl *rate_ctrl, | 573 | static inline void ath_rc_set_valid_txmask(struct ath_tx_ratectrl *rate_ctrl, |
574 | u8 index, int valid_tx_rate) | 574 | u8 index, int valid_tx_rate) |
575 | { | 575 | { |
576 | ASSERT(index <= rate_ctrl->rate_table_size); | 576 | ASSERT(index <= rate_ctrl->rate_table_size); |
577 | rate_ctrl->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE; | 577 | rate_ctrl->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE; |
578 | } | 578 | } |
579 | 579 | ||
580 | static inline int ath_rc_isvalid_txmask(struct ath_tx_ratectrl *rate_ctrl, | 580 | static inline int ath_rc_isvalid_txmask(struct ath_tx_ratectrl *rate_ctrl, |
581 | u8 index) | 581 | u8 index) |
582 | { | 582 | { |
583 | ASSERT(index <= rate_ctrl->rate_table_size); | 583 | ASSERT(index <= rate_ctrl->rate_table_size); |
584 | return rate_ctrl->valid_rate_index[index]; | 584 | return rate_ctrl->valid_rate_index[index]; |
585 | } | 585 | } |
586 | 586 | ||
587 | /* Iterators for valid_txrate_mask */ | 587 | /* Iterators for valid_txrate_mask */ |
588 | static inline int | 588 | static inline int |
589 | ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | 589 | ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, |
590 | struct ath_tx_ratectrl *rate_ctrl, | 590 | struct ath_tx_ratectrl *rate_ctrl, |
591 | u8 cur_valid_txrate, | 591 | u8 cur_valid_txrate, |
592 | u8 *next_idx) | 592 | u8 *next_idx) |
593 | { | 593 | { |
594 | u8 i; | 594 | u8 i; |
595 | 595 | ||
596 | for (i = 0; i < rate_ctrl->max_valid_rate - 1; i++) { | 596 | for (i = 0; i < rate_ctrl->max_valid_rate - 1; i++) { |
597 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | 597 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { |
598 | *next_idx = rate_ctrl->valid_rate_index[i+1]; | 598 | *next_idx = rate_ctrl->valid_rate_index[i+1]; |
599 | return TRUE; | 599 | return TRUE; |
600 | } | 600 | } |
601 | } | 601 | } |
602 | 602 | ||
603 | /* No more valid rates */ | 603 | /* No more valid rates */ |
604 | *next_idx = 0; | 604 | *next_idx = 0; |
605 | return FALSE; | 605 | return FALSE; |
606 | } | 606 | } |
607 | 607 | ||
608 | /* Return true only for single stream */ | 608 | /* Return true only for single stream */ |
609 | 609 | ||
610 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | 610 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) |
611 | { | 611 | { |
612 | if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) | 612 | if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) |
613 | return FALSE; | 613 | return FALSE; |
614 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) | 614 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) |
615 | return FALSE; | 615 | return FALSE; |
616 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) | 616 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) |
617 | return FALSE; | 617 | return FALSE; |
618 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) | 618 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) |
619 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) | 619 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) |
620 | return FALSE; | 620 | return FALSE; |
621 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) | 621 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) |
622 | return FALSE; | 622 | return FALSE; |
623 | return TRUE; | 623 | return TRUE; |
624 | } | 624 | } |
625 | 625 | ||
626 | static inline int | 626 | static inline int |
627 | ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, | 627 | ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, |
628 | struct ath_tx_ratectrl *rate_ctrl, | 628 | struct ath_tx_ratectrl *rate_ctrl, |
629 | u8 cur_valid_txrate, u8 *next_idx) | 629 | u8 cur_valid_txrate, u8 *next_idx) |
630 | { | 630 | { |
631 | int8_t i; | 631 | int8_t i; |
632 | 632 | ||
633 | for (i = 1; i < rate_ctrl->max_valid_rate ; i++) { | 633 | for (i = 1; i < rate_ctrl->max_valid_rate ; i++) { |
634 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | 634 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { |
635 | *next_idx = rate_ctrl->valid_rate_index[i-1]; | 635 | *next_idx = rate_ctrl->valid_rate_index[i-1]; |
636 | return TRUE; | 636 | return TRUE; |
637 | } | 637 | } |
638 | } | 638 | } |
639 | return FALSE; | 639 | return FALSE; |
640 | } | 640 | } |
641 | 641 | ||
642 | /* | 642 | /* |
643 | * Initialize the Valid Rate Index from valid entries in Rate Table | 643 | * Initialize the Valid Rate Index from valid entries in Rate Table |
644 | */ | 644 | */ |
645 | static u8 | 645 | static u8 |
646 | ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, | 646 | ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, |
647 | const struct ath_rate_table *rate_table, | 647 | const struct ath_rate_table *rate_table, |
648 | u32 capflag) | 648 | u32 capflag) |
649 | { | 649 | { |
650 | struct ath_tx_ratectrl *rate_ctrl; | 650 | struct ath_tx_ratectrl *rate_ctrl; |
651 | u8 i, hi = 0; | 651 | u8 i, hi = 0; |
652 | u32 valid; | 652 | u32 valid; |
653 | 653 | ||
654 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | 654 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); |
655 | for (i = 0; i < rate_table->rate_cnt; i++) { | 655 | for (i = 0; i < rate_table->rate_cnt; i++) { |
656 | valid = (ath_rc_priv->single_stream ? | 656 | valid = (ath_rc_priv->single_stream ? |
657 | rate_table->info[i].valid_single_stream : | 657 | rate_table->info[i].valid_single_stream : |
658 | rate_table->info[i].valid); | 658 | rate_table->info[i].valid); |
659 | if (valid == TRUE) { | 659 | if (valid == TRUE) { |
660 | u32 phy = rate_table->info[i].phy; | 660 | u32 phy = rate_table->info[i].phy; |
661 | u8 valid_rate_count = 0; | 661 | u8 valid_rate_count = 0; |
662 | 662 | ||
663 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 663 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) |
664 | continue; | 664 | continue; |
665 | 665 | ||
666 | valid_rate_count = rate_ctrl->valid_phy_ratecnt[phy]; | 666 | valid_rate_count = rate_ctrl->valid_phy_ratecnt[phy]; |
667 | 667 | ||
668 | rate_ctrl->valid_phy_rateidx[phy][valid_rate_count] = i; | 668 | rate_ctrl->valid_phy_rateidx[phy][valid_rate_count] = i; |
669 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 669 | rate_ctrl->valid_phy_ratecnt[phy] += 1; |
670 | ath_rc_set_valid_txmask(rate_ctrl, i, TRUE); | 670 | ath_rc_set_valid_txmask(rate_ctrl, i, TRUE); |
671 | hi = A_MAX(hi, i); | 671 | hi = A_MAX(hi, i); |
672 | } | 672 | } |
673 | } | 673 | } |
674 | return hi; | 674 | return hi; |
675 | } | 675 | } |
676 | 676 | ||
677 | /* | 677 | /* |
678 | * Initialize the Valid Rate Index from Rate Set | 678 | * Initialize the Valid Rate Index from Rate Set |
679 | */ | 679 | */ |
680 | static u8 | 680 | static u8 |
681 | ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv, | 681 | ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv, |
682 | const struct ath_rate_table *rate_table, | 682 | const struct ath_rate_table *rate_table, |
683 | struct ath_rateset *rateset, | 683 | struct ath_rateset *rateset, |
684 | u32 capflag) | 684 | u32 capflag) |
685 | { | 685 | { |
686 | /* XXX: Clean me up and make identation friendly */ | 686 | /* XXX: Clean me up and make identation friendly */ |
687 | u8 i, j, hi = 0; | 687 | u8 i, j, hi = 0; |
688 | struct ath_tx_ratectrl *rate_ctrl = | 688 | struct ath_tx_ratectrl *rate_ctrl = |
689 | (struct ath_tx_ratectrl *)(ath_rc_priv); | 689 | (struct ath_tx_ratectrl *)(ath_rc_priv); |
690 | 690 | ||
691 | /* Use intersection of working rates and valid rates */ | 691 | /* Use intersection of working rates and valid rates */ |
692 | for (i = 0; i < rateset->rs_nrates; i++) { | 692 | for (i = 0; i < rateset->rs_nrates; i++) { |
693 | for (j = 0; j < rate_table->rate_cnt; j++) { | 693 | for (j = 0; j < rate_table->rate_cnt; j++) { |
694 | u32 phy = rate_table->info[j].phy; | 694 | u32 phy = rate_table->info[j].phy; |
695 | u32 valid = (ath_rc_priv->single_stream ? | 695 | u32 valid = (ath_rc_priv->single_stream ? |
696 | rate_table->info[j].valid_single_stream : | 696 | rate_table->info[j].valid_single_stream : |
697 | rate_table->info[j].valid); | 697 | rate_table->info[j].valid); |
698 | 698 | ||
699 | /* We allow a rate only if its valid and the | 699 | /* We allow a rate only if its valid and the |
700 | * capflag matches one of the validity | 700 | * capflag matches one of the validity |
701 | * (TRUE/TRUE_20/TRUE_40) flags */ | 701 | * (TRUE/TRUE_20/TRUE_40) flags */ |
702 | 702 | ||
703 | /* XXX: catch the negative of this branch | 703 | /* XXX: catch the negative of this branch |
704 | * first and then continue */ | 704 | * first and then continue */ |
705 | if (((rateset->rs_rates[i] & 0x7F) == | 705 | if (((rateset->rs_rates[i] & 0x7F) == |
706 | (rate_table->info[j].dot11rate & 0x7F)) && | 706 | (rate_table->info[j].dot11rate & 0x7F)) && |
707 | ((valid & WLAN_RC_CAP_MODE(capflag)) == | 707 | ((valid & WLAN_RC_CAP_MODE(capflag)) == |
708 | WLAN_RC_CAP_MODE(capflag)) && | 708 | WLAN_RC_CAP_MODE(capflag)) && |
709 | !WLAN_RC_PHY_HT(phy)) { | 709 | !WLAN_RC_PHY_HT(phy)) { |
710 | 710 | ||
711 | u8 valid_rate_count = 0; | 711 | u8 valid_rate_count = 0; |
712 | 712 | ||
713 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 713 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) |
714 | continue; | 714 | continue; |
715 | 715 | ||
716 | valid_rate_count = | 716 | valid_rate_count = |
717 | rate_ctrl->valid_phy_ratecnt[phy]; | 717 | rate_ctrl->valid_phy_ratecnt[phy]; |
718 | 718 | ||
719 | rate_ctrl->valid_phy_rateidx[phy] | 719 | rate_ctrl->valid_phy_rateidx[phy] |
720 | [valid_rate_count] = j; | 720 | [valid_rate_count] = j; |
721 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 721 | rate_ctrl->valid_phy_ratecnt[phy] += 1; |
722 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | 722 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); |
723 | hi = A_MAX(hi, j); | 723 | hi = A_MAX(hi, j); |
724 | } | 724 | } |
725 | } | 725 | } |
726 | } | 726 | } |
727 | return hi; | 727 | return hi; |
728 | } | 728 | } |
729 | 729 | ||
730 | static u8 | 730 | static u8 |
731 | ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, | 731 | ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, |
732 | const struct ath_rate_table *rate_table, | 732 | const struct ath_rate_table *rate_table, |
733 | u8 *mcs_set, u32 capflag) | 733 | u8 *mcs_set, u32 capflag) |
734 | { | 734 | { |
735 | u8 i, j, hi = 0; | 735 | u8 i, j, hi = 0; |
736 | struct ath_tx_ratectrl *rate_ctrl = | 736 | struct ath_tx_ratectrl *rate_ctrl = |
737 | (struct ath_tx_ratectrl *)(ath_rc_priv); | 737 | (struct ath_tx_ratectrl *)(ath_rc_priv); |
738 | 738 | ||
739 | /* Use intersection of working rates and valid rates */ | 739 | /* Use intersection of working rates and valid rates */ |
740 | for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) { | 740 | for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) { |
741 | for (j = 0; j < rate_table->rate_cnt; j++) { | 741 | for (j = 0; j < rate_table->rate_cnt; j++) { |
742 | u32 phy = rate_table->info[j].phy; | 742 | u32 phy = rate_table->info[j].phy; |
743 | u32 valid = (ath_rc_priv->single_stream ? | 743 | u32 valid = (ath_rc_priv->single_stream ? |
744 | rate_table->info[j].valid_single_stream : | 744 | rate_table->info[j].valid_single_stream : |
745 | rate_table->info[j].valid); | 745 | rate_table->info[j].valid); |
746 | 746 | ||
747 | if (((((struct ath_rateset *) | 747 | if (((((struct ath_rateset *) |
748 | mcs_set)->rs_rates[i] & 0x7F) != | 748 | mcs_set)->rs_rates[i] & 0x7F) != |
749 | (rate_table->info[j].dot11rate & 0x7F)) || | 749 | (rate_table->info[j].dot11rate & 0x7F)) || |
750 | !WLAN_RC_PHY_HT(phy) || | 750 | !WLAN_RC_PHY_HT(phy) || |
751 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) | 751 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) |
752 | continue; | 752 | continue; |
753 | 753 | ||
754 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 754 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) |
755 | continue; | 755 | continue; |
756 | 756 | ||
757 | rate_ctrl->valid_phy_rateidx[phy] | 757 | rate_ctrl->valid_phy_rateidx[phy] |
758 | [rate_ctrl->valid_phy_ratecnt[phy]] = j; | 758 | [rate_ctrl->valid_phy_ratecnt[phy]] = j; |
759 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 759 | rate_ctrl->valid_phy_ratecnt[phy] += 1; |
760 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | 760 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); |
761 | hi = A_MAX(hi, j); | 761 | hi = A_MAX(hi, j); |
762 | } | 762 | } |
763 | } | 763 | } |
764 | return hi; | 764 | return hi; |
765 | } | 765 | } |
766 | 766 | ||
767 | /* | 767 | /* |
768 | * Attach to a device instance. Setup the public definition | 768 | * Attach to a device instance. Setup the public definition |
769 | * of how much per-node space we need and setup the private | 769 | * of how much per-node space we need and setup the private |
770 | * phy tables that have rate control parameters. | 770 | * phy tables that have rate control parameters. |
771 | */ | 771 | */ |
772 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah) | 772 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah) |
773 | { | 773 | { |
774 | struct ath_rate_softc *asc; | 774 | struct ath_rate_softc *asc; |
775 | 775 | ||
776 | /* we are only in user context so we can sleep for memory */ | 776 | /* we are only in user context so we can sleep for memory */ |
777 | asc = kzalloc(sizeof(struct ath_rate_softc), GFP_KERNEL); | 777 | asc = kzalloc(sizeof(struct ath_rate_softc), GFP_KERNEL); |
778 | if (asc == NULL) | 778 | if (asc == NULL) |
779 | return NULL; | 779 | return NULL; |
780 | 780 | ||
781 | ar5416_attach_ratetables(asc); | 781 | ar5416_attach_ratetables(asc); |
782 | 782 | ||
783 | /* Save Maximum TX Trigger Level (used for 11n) */ | 783 | /* Save Maximum TX Trigger Level (used for 11n) */ |
784 | tx_triglevel_max = ah->ah_caps.tx_triglevel_max; | 784 | tx_triglevel_max = ah->ah_caps.tx_triglevel_max; |
785 | /* return alias for ath_rate_softc * */ | 785 | /* return alias for ath_rate_softc * */ |
786 | return asc; | 786 | return asc; |
787 | } | 787 | } |
788 | 788 | ||
789 | static struct ath_rate_node *ath_rate_node_alloc(struct ath_vap *avp, | 789 | static struct ath_rate_node *ath_rate_node_alloc(struct ath_vap *avp, |
790 | struct ath_rate_softc *rsc, | 790 | struct ath_rate_softc *rsc, |
791 | gfp_t gfp) | 791 | gfp_t gfp) |
792 | { | 792 | { |
793 | struct ath_rate_node *anode; | 793 | struct ath_rate_node *anode; |
794 | 794 | ||
795 | anode = kzalloc(sizeof(struct ath_rate_node), gfp); | 795 | anode = kzalloc(sizeof(struct ath_rate_node), gfp); |
796 | if (anode == NULL) | 796 | if (anode == NULL) |
797 | return NULL; | 797 | return NULL; |
798 | 798 | ||
799 | anode->avp = avp; | 799 | anode->avp = avp; |
800 | anode->asc = rsc; | 800 | anode->asc = rsc; |
801 | avp->rc_node = anode; | 801 | avp->rc_node = anode; |
802 | 802 | ||
803 | return anode; | 803 | return anode; |
804 | } | 804 | } |
805 | 805 | ||
806 | static void ath_rate_node_free(struct ath_rate_node *anode) | 806 | static void ath_rate_node_free(struct ath_rate_node *anode) |
807 | { | 807 | { |
808 | if (anode != NULL) | 808 | if (anode != NULL) |
809 | kfree(anode); | 809 | kfree(anode); |
810 | } | 810 | } |
811 | 811 | ||
812 | void ath_rate_detach(struct ath_rate_softc *asc) | 812 | void ath_rate_detach(struct ath_rate_softc *asc) |
813 | { | 813 | { |
814 | if (asc != NULL) | 814 | if (asc != NULL) |
815 | kfree(asc); | 815 | kfree(asc); |
816 | } | 816 | } |
817 | 817 | ||
818 | u8 ath_rate_findrateix(struct ath_softc *sc, | 818 | u8 ath_rate_findrateix(struct ath_softc *sc, |
819 | u8 dot11rate) | 819 | u8 dot11rate) |
820 | { | 820 | { |
821 | const struct ath_rate_table *ratetable; | 821 | const struct ath_rate_table *ratetable; |
822 | struct ath_rate_softc *rsc = sc->sc_rc; | 822 | struct ath_rate_softc *rsc = sc->sc_rc; |
823 | int i; | 823 | int i; |
824 | 824 | ||
825 | ratetable = rsc->hw_rate_table[sc->sc_curmode]; | 825 | ratetable = rsc->hw_rate_table[sc->sc_curmode]; |
826 | 826 | ||
827 | if (WARN_ON(!ratetable)) | 827 | if (WARN_ON(!ratetable)) |
828 | return 0; | 828 | return 0; |
829 | 829 | ||
830 | for (i = 0; i < ratetable->rate_cnt; i++) { | 830 | for (i = 0; i < ratetable->rate_cnt; i++) { |
831 | if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f)) | 831 | if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f)) |
832 | return i; | 832 | return i; |
833 | } | 833 | } |
834 | 834 | ||
835 | return 0; | 835 | return 0; |
836 | } | 836 | } |
837 | 837 | ||
838 | /* | 838 | /* |
839 | * Update rate-control state on a device state change. When | 839 | * Update rate-control state on a device state change. When |
840 | * operating as a station this includes associate/reassociate | 840 | * operating as a station this includes associate/reassociate |
841 | * with an AP. Otherwise this gets called, for example, when | 841 | * with an AP. Otherwise this gets called, for example, when |
842 | * the we transition to run state when operating as an AP. | 842 | * the we transition to run state when operating as an AP. |
843 | */ | 843 | */ |
844 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) | 844 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) |
845 | { | 845 | { |
846 | struct ath_rate_softc *asc = sc->sc_rc; | 846 | struct ath_rate_softc *asc = sc->sc_rc; |
847 | 847 | ||
848 | /* For half and quarter rate channles use different | 848 | /* For half and quarter rate channles use different |
849 | * rate tables | 849 | * rate tables |
850 | */ | 850 | */ |
851 | if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF) | 851 | if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF) |
852 | ar5416_sethalf_ratetable(asc); | 852 | ar5416_sethalf_ratetable(asc); |
853 | else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER) | 853 | else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER) |
854 | ar5416_setquarter_ratetable(asc); | 854 | ar5416_setquarter_ratetable(asc); |
855 | else /* full rate */ | 855 | else /* full rate */ |
856 | ar5416_setfull_ratetable(asc); | 856 | ar5416_setfull_ratetable(asc); |
857 | 857 | ||
858 | if (avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) { | 858 | if (avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) { |
859 | asc->fixedrix = | 859 | asc->fixedrix = |
860 | sc->sc_rixmap[avp->av_config.av_fixed_rateset & 0xff]; | 860 | sc->sc_rixmap[avp->av_config.av_fixed_rateset & 0xff]; |
861 | /* NB: check the fixed rate exists */ | 861 | /* NB: check the fixed rate exists */ |
862 | if (asc->fixedrix == 0xff) | 862 | if (asc->fixedrix == 0xff) |
863 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | 863 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; |
864 | } else { | 864 | } else { |
865 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | 865 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; |
866 | } | 866 | } |
867 | } | 867 | } |
868 | 868 | ||
869 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | 869 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, |
870 | struct ath_rate_node *ath_rc_priv, | 870 | struct ath_rate_node *ath_rc_priv, |
871 | const struct ath_rate_table *rate_table, | 871 | const struct ath_rate_table *rate_table, |
872 | int probe_allowed, int *is_probing, | 872 | int probe_allowed, int *is_probing, |
873 | int is_retry) | 873 | int is_retry) |
874 | { | 874 | { |
875 | u32 dt, best_thruput, this_thruput, now_msec; | 875 | u32 dt, best_thruput, this_thruput, now_msec; |
876 | u8 rate, next_rate, best_rate, maxindex, minindex; | 876 | u8 rate, next_rate, best_rate, maxindex, minindex; |
877 | int8_t rssi_last, rssi_reduce = 0, index = 0; | 877 | int8_t rssi_last, rssi_reduce = 0, index = 0; |
878 | struct ath_tx_ratectrl *rate_ctrl = NULL; | 878 | struct ath_tx_ratectrl *rate_ctrl = NULL; |
879 | 879 | ||
880 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv ? | 880 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv ? |
881 | (ath_rc_priv) : NULL); | 881 | (ath_rc_priv) : NULL); |
882 | 882 | ||
883 | *is_probing = FALSE; | 883 | *is_probing = FALSE; |
884 | 884 | ||
885 | rssi_last = median(rate_ctrl->rssi_last, | 885 | rssi_last = median(rate_ctrl->rssi_last, |
886 | rate_ctrl->rssi_last_prev, | 886 | rate_ctrl->rssi_last_prev, |
887 | rate_ctrl->rssi_last_prev2); | 887 | rate_ctrl->rssi_last_prev2); |
888 | 888 | ||
889 | /* | 889 | /* |
890 | * Age (reduce) last ack rssi based on how old it is. | 890 | * Age (reduce) last ack rssi based on how old it is. |
891 | * The bizarre numbers are so the delta is 160msec, | 891 | * The bizarre numbers are so the delta is 160msec, |
892 | * meaning we divide by 16. | 892 | * meaning we divide by 16. |
893 | * 0msec <= dt <= 25msec: don't derate | 893 | * 0msec <= dt <= 25msec: don't derate |
894 | * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB | 894 | * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB |
895 | * 185msec <= dt: derate by 10dB | 895 | * 185msec <= dt: derate by 10dB |
896 | */ | 896 | */ |
897 | 897 | ||
898 | now_msec = jiffies_to_msecs(jiffies); | 898 | now_msec = jiffies_to_msecs(jiffies); |
899 | dt = now_msec - rate_ctrl->rssi_time; | 899 | dt = now_msec - rate_ctrl->rssi_time; |
900 | 900 | ||
901 | if (dt >= 185) | 901 | if (dt >= 185) |
902 | rssi_reduce = 10; | 902 | rssi_reduce = 10; |
903 | else if (dt >= 25) | 903 | else if (dt >= 25) |
904 | rssi_reduce = (u8)((dt - 25) >> 4); | 904 | rssi_reduce = (u8)((dt - 25) >> 4); |
905 | 905 | ||
906 | /* Now reduce rssi_last by rssi_reduce */ | 906 | /* Now reduce rssi_last by rssi_reduce */ |
907 | if (rssi_last < rssi_reduce) | 907 | if (rssi_last < rssi_reduce) |
908 | rssi_last = 0; | 908 | rssi_last = 0; |
909 | else | 909 | else |
910 | rssi_last -= rssi_reduce; | 910 | rssi_last -= rssi_reduce; |
911 | 911 | ||
912 | /* | 912 | /* |
913 | * Now look up the rate in the rssi table and return it. | 913 | * Now look up the rate in the rssi table and return it. |
914 | * If no rates match then we return 0 (lowest rate) | 914 | * If no rates match then we return 0 (lowest rate) |
915 | */ | 915 | */ |
916 | 916 | ||
917 | best_thruput = 0; | 917 | best_thruput = 0; |
918 | maxindex = rate_ctrl->max_valid_rate-1; | 918 | maxindex = rate_ctrl->max_valid_rate-1; |
919 | 919 | ||
920 | minindex = 0; | 920 | minindex = 0; |
921 | best_rate = minindex; | 921 | best_rate = minindex; |
922 | 922 | ||
923 | /* | 923 | /* |
924 | * Try the higher rate first. It will reduce memory moving time | 924 | * Try the higher rate first. It will reduce memory moving time |
925 | * if we have very good channel characteristics. | 925 | * if we have very good channel characteristics. |
926 | */ | 926 | */ |
927 | for (index = maxindex; index >= minindex ; index--) { | 927 | for (index = maxindex; index >= minindex ; index--) { |
928 | u8 per_thres; | 928 | u8 per_thres; |
929 | 929 | ||
930 | rate = rate_ctrl->valid_rate_index[index]; | 930 | rate = rate_ctrl->valid_rate_index[index]; |
931 | if (rate > rate_ctrl->rate_max_phy) | 931 | if (rate > rate_ctrl->rate_max_phy) |
932 | continue; | 932 | continue; |
933 | 933 | ||
934 | /* | 934 | /* |
935 | * For TCP the average collision rate is around 11%, | 935 | * For TCP the average collision rate is around 11%, |
936 | * so we ignore PERs less than this. This is to | 936 | * so we ignore PERs less than this. This is to |
937 | * prevent the rate we are currently using (whose | 937 | * prevent the rate we are currently using (whose |
938 | * PER might be in the 10-15 range because of TCP | 938 | * PER might be in the 10-15 range because of TCP |
939 | * collisions) looking worse than the next lower | 939 | * collisions) looking worse than the next lower |
940 | * rate whose PER has decayed close to 0. If we | 940 | * rate whose PER has decayed close to 0. If we |
941 | * used to next lower rate, its PER would grow to | 941 | * used to next lower rate, its PER would grow to |
942 | * 10-15 and we would be worse off then staying | 942 | * 10-15 and we would be worse off then staying |
943 | * at the current rate. | 943 | * at the current rate. |
944 | */ | 944 | */ |
945 | per_thres = rate_ctrl->state[rate].per; | 945 | per_thres = rate_ctrl->state[rate].per; |
946 | if (per_thres < 12) | 946 | if (per_thres < 12) |
947 | per_thres = 12; | 947 | per_thres = 12; |
948 | 948 | ||
949 | this_thruput = rate_table->info[rate].user_ratekbps * | 949 | this_thruput = rate_table->info[rate].user_ratekbps * |
950 | (100 - per_thres); | 950 | (100 - per_thres); |
951 | 951 | ||
952 | if (best_thruput <= this_thruput) { | 952 | if (best_thruput <= this_thruput) { |
953 | best_thruput = this_thruput; | 953 | best_thruput = this_thruput; |
954 | best_rate = rate; | 954 | best_rate = rate; |
955 | } | 955 | } |
956 | } | 956 | } |
957 | 957 | ||
958 | rate = best_rate; | 958 | rate = best_rate; |
959 | 959 | ||
960 | /* if we are retrying for more than half the number | 960 | /* if we are retrying for more than half the number |
961 | * of max retries, use the min rate for the next retry | 961 | * of max retries, use the min rate for the next retry |
962 | */ | 962 | */ |
963 | if (is_retry) | 963 | if (is_retry) |
964 | rate = rate_ctrl->valid_rate_index[minindex]; | 964 | rate = rate_ctrl->valid_rate_index[minindex]; |
965 | 965 | ||
966 | rate_ctrl->rssi_last_lookup = rssi_last; | 966 | rate_ctrl->rssi_last_lookup = rssi_last; |
967 | 967 | ||
968 | /* | 968 | /* |
969 | * Must check the actual rate (ratekbps) to account for | 969 | * Must check the actual rate (ratekbps) to account for |
970 | * non-monoticity of 11g's rate table | 970 | * non-monoticity of 11g's rate table |
971 | */ | 971 | */ |
972 | 972 | ||
973 | if (rate >= rate_ctrl->rate_max_phy && probe_allowed) { | 973 | if (rate >= rate_ctrl->rate_max_phy && probe_allowed) { |
974 | rate = rate_ctrl->rate_max_phy; | 974 | rate = rate_ctrl->rate_max_phy; |
975 | 975 | ||
976 | /* Probe the next allowed phy state */ | 976 | /* Probe the next allowed phy state */ |
977 | /* FIXME:XXXX Check to make sure ratMax is checked properly */ | 977 | /* FIXME:XXXX Check to make sure ratMax is checked properly */ |
978 | if (ath_rc_get_nextvalid_txrate(rate_table, | 978 | if (ath_rc_get_nextvalid_txrate(rate_table, |
979 | rate_ctrl, rate, &next_rate) && | 979 | rate_ctrl, rate, &next_rate) && |
980 | (now_msec - rate_ctrl->probe_time > | 980 | (now_msec - rate_ctrl->probe_time > |
981 | rate_table->probe_interval) && | 981 | rate_table->probe_interval) && |
982 | (rate_ctrl->hw_maxretry_pktcnt >= 1)) { | 982 | (rate_ctrl->hw_maxretry_pktcnt >= 1)) { |
983 | rate = next_rate; | 983 | rate = next_rate; |
984 | rate_ctrl->probe_rate = rate; | 984 | rate_ctrl->probe_rate = rate; |
985 | rate_ctrl->probe_time = now_msec; | 985 | rate_ctrl->probe_time = now_msec; |
986 | rate_ctrl->hw_maxretry_pktcnt = 0; | 986 | rate_ctrl->hw_maxretry_pktcnt = 0; |
987 | *is_probing = TRUE; | 987 | *is_probing = TRUE; |
988 | } | 988 | } |
989 | } | 989 | } |
990 | 990 | ||
991 | /* | 991 | /* |
992 | * Make sure rate is not higher than the allowed maximum. | 992 | * Make sure rate is not higher than the allowed maximum. |
993 | * We should also enforce the min, but I suspect the min is | 993 | * We should also enforce the min, but I suspect the min is |
994 | * normally 1 rather than 0 because of the rate 9 vs 6 issue | 994 | * normally 1 rather than 0 because of the rate 9 vs 6 issue |
995 | * in the old code. | 995 | * in the old code. |
996 | */ | 996 | */ |
997 | if (rate > (rate_ctrl->rate_table_size - 1)) | 997 | if (rate > (rate_ctrl->rate_table_size - 1)) |
998 | rate = rate_ctrl->rate_table_size - 1; | 998 | rate = rate_ctrl->rate_table_size - 1; |
999 | 999 | ||
1000 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || | 1000 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || |
1001 | (rate_table->info[rate].valid_single_stream && | 1001 | (rate_table->info[rate].valid_single_stream && |
1002 | ath_rc_priv->single_stream)); | 1002 | ath_rc_priv->single_stream)); |
1003 | 1003 | ||
1004 | return rate; | 1004 | return rate; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , | 1007 | static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , |
1008 | struct ath_rc_series *series, | 1008 | struct ath_rc_series *series, |
1009 | u8 tries, | 1009 | u8 tries, |
1010 | u8 rix, | 1010 | u8 rix, |
1011 | int rtsctsenable) | 1011 | int rtsctsenable) |
1012 | { | 1012 | { |
1013 | series->tries = tries; | 1013 | series->tries = tries; |
1014 | series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) | | 1014 | series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) | |
1015 | (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ? | 1015 | (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ? |
1016 | ATH_RC_DS_FLAG : 0) | | 1016 | ATH_RC_DS_FLAG : 0) | |
1017 | (WLAN_RC_PHY_40(rate_table->info[rix].phy) ? | 1017 | (WLAN_RC_PHY_40(rate_table->info[rix].phy) ? |
1018 | ATH_RC_CW40_FLAG : 0) | | 1018 | ATH_RC_CW40_FLAG : 0) | |
1019 | (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ? | 1019 | (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ? |
1020 | ATH_RC_SGI_FLAG : 0); | 1020 | ATH_RC_SGI_FLAG : 0); |
1021 | 1021 | ||
1022 | series->rix = rate_table->info[rix].base_index; | 1022 | series->rix = rate_table->info[rix].base_index; |
1023 | series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen; | 1023 | series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, | 1026 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, |
1027 | struct ath_rate_node *ath_rc_priv, | 1027 | struct ath_rate_node *ath_rc_priv, |
1028 | const struct ath_rate_table *rate_table, | 1028 | const struct ath_rate_table *rate_table, |
1029 | u8 rix, u16 stepdown, | 1029 | u8 rix, u16 stepdown, |
1030 | u16 min_rate) | 1030 | u16 min_rate) |
1031 | { | 1031 | { |
1032 | u32 j; | 1032 | u32 j; |
1033 | u8 nextindex; | 1033 | u8 nextindex; |
1034 | struct ath_tx_ratectrl *rate_ctrl = | 1034 | struct ath_tx_ratectrl *rate_ctrl = |
1035 | (struct ath_tx_ratectrl *)(ath_rc_priv); | 1035 | (struct ath_tx_ratectrl *)(ath_rc_priv); |
1036 | 1036 | ||
1037 | if (min_rate) { | 1037 | if (min_rate) { |
1038 | for (j = RATE_TABLE_SIZE; j > 0; j--) { | 1038 | for (j = RATE_TABLE_SIZE; j > 0; j--) { |
1039 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | 1039 | if (ath_rc_get_nextlowervalid_txrate(rate_table, |
1040 | rate_ctrl, rix, &nextindex)) | 1040 | rate_ctrl, rix, &nextindex)) |
1041 | rix = nextindex; | 1041 | rix = nextindex; |
1042 | else | 1042 | else |
1043 | break; | 1043 | break; |
1044 | } | 1044 | } |
1045 | } else { | 1045 | } else { |
1046 | for (j = stepdown; j > 0; j--) { | 1046 | for (j = stepdown; j > 0; j--) { |
1047 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | 1047 | if (ath_rc_get_nextlowervalid_txrate(rate_table, |
1048 | rate_ctrl, rix, &nextindex)) | 1048 | rate_ctrl, rix, &nextindex)) |
1049 | rix = nextindex; | 1049 | rix = nextindex; |
1050 | else | 1050 | else |
1051 | break; | 1051 | break; |
1052 | } | 1052 | } |
1053 | } | 1053 | } |
1054 | return rix; | 1054 | return rix; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | static void ath_rc_ratefind(struct ath_softc *sc, | 1057 | static void ath_rc_ratefind(struct ath_softc *sc, |
1058 | struct ath_rate_node *ath_rc_priv, | 1058 | struct ath_rate_node *ath_rc_priv, |
1059 | int num_tries, int num_rates, unsigned int rcflag, | 1059 | int num_tries, int num_rates, unsigned int rcflag, |
1060 | struct ath_rc_series series[], int *is_probe, | 1060 | struct ath_rc_series series[], int *is_probe, |
1061 | int is_retry) | 1061 | int is_retry) |
1062 | { | 1062 | { |
1063 | u8 try_per_rate = 0, i = 0, rix, nrix; | 1063 | u8 try_per_rate = 0, i = 0, rix, nrix; |
1064 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1064 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1065 | struct ath_rate_table *rate_table; | 1065 | struct ath_rate_table *rate_table; |
1066 | 1066 | ||
1067 | rate_table = | 1067 | rate_table = |
1068 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | 1068 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; |
1069 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, | 1069 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, |
1070 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, | 1070 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, |
1071 | is_probe, is_retry); | 1071 | is_probe, is_retry); |
1072 | nrix = rix; | 1072 | nrix = rix; |
1073 | 1073 | ||
1074 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { | 1074 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { |
1075 | /* set one try for probe rates. For the | 1075 | /* set one try for probe rates. For the |
1076 | * probes don't enable rts */ | 1076 | * probes don't enable rts */ |
1077 | ath_rc_rate_set_series(rate_table, | 1077 | ath_rc_rate_set_series(rate_table, |
1078 | &series[i++], 1, nrix, FALSE); | 1078 | &series[i++], 1, nrix, FALSE); |
1079 | 1079 | ||
1080 | try_per_rate = (num_tries/num_rates); | 1080 | try_per_rate = (num_tries/num_rates); |
1081 | /* Get the next tried/allowed rate. No RTS for the next series | 1081 | /* Get the next tried/allowed rate. No RTS for the next series |
1082 | * after the probe rate | 1082 | * after the probe rate |
1083 | */ | 1083 | */ |
1084 | nrix = ath_rc_rate_getidx(sc, | 1084 | nrix = ath_rc_rate_getidx(sc, |
1085 | ath_rc_priv, rate_table, nrix, 1, FALSE); | 1085 | ath_rc_priv, rate_table, nrix, 1, FALSE); |
1086 | ath_rc_rate_set_series(rate_table, | 1086 | ath_rc_rate_set_series(rate_table, |
1087 | &series[i++], try_per_rate, nrix, 0); | 1087 | &series[i++], try_per_rate, nrix, 0); |
1088 | } else { | 1088 | } else { |
1089 | try_per_rate = (num_tries/num_rates); | 1089 | try_per_rate = (num_tries/num_rates); |
1090 | /* Set the choosen rate. No RTS for first series entry. */ | 1090 | /* Set the choosen rate. No RTS for first series entry. */ |
1091 | ath_rc_rate_set_series(rate_table, | 1091 | ath_rc_rate_set_series(rate_table, |
1092 | &series[i++], try_per_rate, nrix, FALSE); | 1092 | &series[i++], try_per_rate, nrix, FALSE); |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | /* Fill in the other rates for multirate retry */ | 1095 | /* Fill in the other rates for multirate retry */ |
1096 | for ( ; i < num_rates; i++) { | 1096 | for ( ; i < num_rates; i++) { |
1097 | u8 try_num; | 1097 | u8 try_num; |
1098 | u8 min_rate; | 1098 | u8 min_rate; |
1099 | 1099 | ||
1100 | try_num = ((i + 1) == num_rates) ? | 1100 | try_num = ((i + 1) == num_rates) ? |
1101 | num_tries - (try_per_rate * i) : try_per_rate ; | 1101 | num_tries - (try_per_rate * i) : try_per_rate ; |
1102 | min_rate = (((i + 1) == num_rates) && | 1102 | min_rate = (((i + 1) == num_rates) && |
1103 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; | 1103 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; |
1104 | 1104 | ||
1105 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | 1105 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, |
1106 | rate_table, nrix, 1, min_rate); | 1106 | rate_table, nrix, 1, min_rate); |
1107 | /* All other rates in the series have RTS enabled */ | 1107 | /* All other rates in the series have RTS enabled */ |
1108 | ath_rc_rate_set_series(rate_table, | 1108 | ath_rc_rate_set_series(rate_table, |
1109 | &series[i], try_num, nrix, TRUE); | 1109 | &series[i], try_num, nrix, TRUE); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | /* | 1112 | /* |
1113 | * NB:Change rate series to enable aggregation when operating | 1113 | * NB:Change rate series to enable aggregation when operating |
1114 | * at lower MCS rates. When first rate in series is MCS2 | 1114 | * at lower MCS rates. When first rate in series is MCS2 |
1115 | * in HT40 @ 2.4GHz, series should look like: | 1115 | * in HT40 @ 2.4GHz, series should look like: |
1116 | * | 1116 | * |
1117 | * {MCS2, MCS1, MCS0, MCS0}. | 1117 | * {MCS2, MCS1, MCS0, MCS0}. |
1118 | * | 1118 | * |
1119 | * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should | 1119 | * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should |
1120 | * look like: | 1120 | * look like: |
1121 | * | 1121 | * |
1122 | * {MCS3, MCS2, MCS1, MCS1} | 1122 | * {MCS3, MCS2, MCS1, MCS1} |
1123 | * | 1123 | * |
1124 | * So, set fourth rate in series to be same as third one for | 1124 | * So, set fourth rate in series to be same as third one for |
1125 | * above conditions. | 1125 | * above conditions. |
1126 | */ | 1126 | */ |
1127 | if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) || | 1127 | if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) || |
1128 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || | 1128 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || |
1129 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { | 1129 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { |
1130 | u8 dot11rate = rate_table->info[rix].dot11rate; | 1130 | u8 dot11rate = rate_table->info[rix].dot11rate; |
1131 | u8 phy = rate_table->info[rix].phy; | 1131 | u8 phy = rate_table->info[rix].phy; |
1132 | if (i == 4 && | 1132 | if (i == 4 && |
1133 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || | 1133 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || |
1134 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { | 1134 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { |
1135 | series[3].rix = series[2].rix; | 1135 | series[3].rix = series[2].rix; |
1136 | series[3].flags = series[2].flags; | 1136 | series[3].flags = series[2].flags; |
1137 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; | 1137 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; |
1138 | } | 1138 | } |
1139 | } | 1139 | } |
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | /* | 1142 | /* |
1143 | * Return the Tx rate series. | 1143 | * Return the Tx rate series. |
1144 | */ | 1144 | */ |
1145 | static void ath_rate_findrate(struct ath_softc *sc, | 1145 | static void ath_rate_findrate(struct ath_softc *sc, |
1146 | struct ath_rate_node *ath_rc_priv, | 1146 | struct ath_rate_node *ath_rc_priv, |
1147 | int num_tries, | 1147 | int num_tries, |
1148 | int num_rates, | 1148 | int num_rates, |
1149 | unsigned int rcflag, | 1149 | unsigned int rcflag, |
1150 | struct ath_rc_series series[], | 1150 | struct ath_rc_series series[], |
1151 | int *is_probe, | 1151 | int *is_probe, |
1152 | int is_retry) | 1152 | int is_retry) |
1153 | { | 1153 | { |
1154 | struct ath_vap *avp = ath_rc_priv->avp; | 1154 | struct ath_vap *avp = ath_rc_priv->avp; |
1155 | 1155 | ||
1156 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 1156 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1157 | 1157 | ||
1158 | if (!num_rates || !num_tries) | 1158 | if (!num_rates || !num_tries) |
1159 | return; | 1159 | return; |
1160 | 1160 | ||
1161 | if (avp->av_config.av_fixed_rateset == IEEE80211_FIXED_RATE_NONE) { | 1161 | if (avp->av_config.av_fixed_rateset == IEEE80211_FIXED_RATE_NONE) { |
1162 | ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates, | 1162 | ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates, |
1163 | rcflag, series, is_probe, is_retry); | 1163 | rcflag, series, is_probe, is_retry); |
1164 | } else { | 1164 | } else { |
1165 | /* Fixed rate */ | 1165 | /* Fixed rate */ |
1166 | int idx; | 1166 | int idx; |
1167 | u8 flags; | 1167 | u8 flags; |
1168 | u32 rix; | 1168 | u32 rix; |
1169 | struct ath_rate_softc *asc = ath_rc_priv->asc; | 1169 | struct ath_rate_softc *asc = ath_rc_priv->asc; |
1170 | struct ath_rate_table *rate_table; | 1170 | struct ath_rate_table *rate_table; |
1171 | 1171 | ||
1172 | rate_table = (struct ath_rate_table *) | 1172 | rate_table = (struct ath_rate_table *) |
1173 | asc->hw_rate_table[sc->sc_curmode]; | 1173 | asc->hw_rate_table[sc->sc_curmode]; |
1174 | 1174 | ||
1175 | for (idx = 0; idx < 4; idx++) { | 1175 | for (idx = 0; idx < 4; idx++) { |
1176 | unsigned int mcs; | 1176 | unsigned int mcs; |
1177 | u8 series_rix = 0; | 1177 | u8 series_rix = 0; |
1178 | 1178 | ||
1179 | series[idx].tries = IEEE80211_RATE_IDX_ENTRY( | 1179 | series[idx].tries = IEEE80211_RATE_IDX_ENTRY( |
1180 | avp->av_config.av_fixed_retryset, idx); | 1180 | avp->av_config.av_fixed_retryset, idx); |
1181 | 1181 | ||
1182 | mcs = IEEE80211_RATE_IDX_ENTRY( | 1182 | mcs = IEEE80211_RATE_IDX_ENTRY( |
1183 | avp->av_config.av_fixed_rateset, idx); | 1183 | avp->av_config.av_fixed_rateset, idx); |
1184 | 1184 | ||
1185 | if (idx == 3 && (mcs & 0xf0) == 0x70) | 1185 | if (idx == 3 && (mcs & 0xf0) == 0x70) |
1186 | mcs = (mcs & ~0xf0)|0x80; | 1186 | mcs = (mcs & ~0xf0)|0x80; |
1187 | 1187 | ||
1188 | if (!(mcs & 0x80)) | 1188 | if (!(mcs & 0x80)) |
1189 | flags = 0; | 1189 | flags = 0; |
1190 | else | 1190 | else |
1191 | flags = ((ath_rc_priv->ht_cap & | 1191 | flags = ((ath_rc_priv->ht_cap & |
1192 | WLAN_RC_DS_FLAG) ? | 1192 | WLAN_RC_DS_FLAG) ? |
1193 | ATH_RC_DS_FLAG : 0) | | 1193 | ATH_RC_DS_FLAG : 0) | |
1194 | ((ath_rc_priv->ht_cap & | 1194 | ((ath_rc_priv->ht_cap & |
1195 | WLAN_RC_40_FLAG) ? | 1195 | WLAN_RC_40_FLAG) ? |
1196 | ATH_RC_CW40_FLAG : 0) | | 1196 | ATH_RC_CW40_FLAG : 0) | |
1197 | ((ath_rc_priv->ht_cap & | 1197 | ((ath_rc_priv->ht_cap & |
1198 | WLAN_RC_SGI_FLAG) ? | 1198 | WLAN_RC_SGI_FLAG) ? |
1199 | ((ath_rc_priv->ht_cap & | 1199 | ((ath_rc_priv->ht_cap & |
1200 | WLAN_RC_40_FLAG) ? | 1200 | WLAN_RC_40_FLAG) ? |
1201 | ATH_RC_SGI_FLAG : 0) : 0); | 1201 | ATH_RC_SGI_FLAG : 0) : 0); |
1202 | 1202 | ||
1203 | series[idx].rix = sc->sc_rixmap[mcs]; | 1203 | series[idx].rix = sc->sc_rixmap[mcs]; |
1204 | series_rix = series[idx].rix; | 1204 | series_rix = series[idx].rix; |
1205 | 1205 | ||
1206 | /* XXX: Give me some cleanup love */ | 1206 | /* XXX: Give me some cleanup love */ |
1207 | if ((flags & ATH_RC_CW40_FLAG) && | 1207 | if ((flags & ATH_RC_CW40_FLAG) && |
1208 | (flags & ATH_RC_SGI_FLAG)) | 1208 | (flags & ATH_RC_SGI_FLAG)) |
1209 | rix = rate_table->info[series_rix].ht_index; | 1209 | rix = rate_table->info[series_rix].ht_index; |
1210 | else if (flags & ATH_RC_SGI_FLAG) | 1210 | else if (flags & ATH_RC_SGI_FLAG) |
1211 | rix = rate_table->info[series_rix].sgi_index; | 1211 | rix = rate_table->info[series_rix].sgi_index; |
1212 | else if (flags & ATH_RC_CW40_FLAG) | 1212 | else if (flags & ATH_RC_CW40_FLAG) |
1213 | rix = rate_table->info[series_rix].cw40index; | 1213 | rix = rate_table->info[series_rix].cw40index; |
1214 | else | 1214 | else |
1215 | rix = rate_table->info[series_rix].base_index; | 1215 | rix = rate_table->info[series_rix].base_index; |
1216 | series[idx].max_4ms_framelen = | 1216 | series[idx].max_4ms_framelen = |
1217 | rate_table->info[rix].max_4ms_framelen; | 1217 | rate_table->info[rix].max_4ms_framelen; |
1218 | series[idx].flags = flags; | 1218 | series[idx].flags = flags; |
1219 | } | 1219 | } |
1220 | } | 1220 | } |
1221 | } | 1221 | } |
1222 | 1222 | ||
1223 | static void ath_rc_update_ht(struct ath_softc *sc, | 1223 | static void ath_rc_update_ht(struct ath_softc *sc, |
1224 | struct ath_rate_node *ath_rc_priv, | 1224 | struct ath_rate_node *ath_rc_priv, |
1225 | struct ath_tx_info_priv *info_priv, | 1225 | struct ath_tx_info_priv *info_priv, |
1226 | int tx_rate, int xretries, int retries) | 1226 | int tx_rate, int xretries, int retries) |
1227 | { | 1227 | { |
1228 | struct ath_tx_ratectrl *rate_ctrl; | 1228 | struct ath_tx_ratectrl *rate_ctrl; |
1229 | u32 now_msec = jiffies_to_msecs(jiffies); | 1229 | u32 now_msec = jiffies_to_msecs(jiffies); |
1230 | int state_change = FALSE, rate, count; | 1230 | int state_change = FALSE, rate, count; |
1231 | u8 last_per; | 1231 | u8 last_per; |
1232 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1232 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1233 | struct ath_rate_table *rate_table = | 1233 | struct ath_rate_table *rate_table = |
1234 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | 1234 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; |
1235 | 1235 | ||
1236 | static u32 nretry_to_per_lookup[10] = { | 1236 | static u32 nretry_to_per_lookup[10] = { |
1237 | 100 * 0 / 1, | 1237 | 100 * 0 / 1, |
1238 | 100 * 1 / 4, | 1238 | 100 * 1 / 4, |
1239 | 100 * 1 / 2, | 1239 | 100 * 1 / 2, |
1240 | 100 * 3 / 4, | 1240 | 100 * 3 / 4, |
1241 | 100 * 4 / 5, | 1241 | 100 * 4 / 5, |
1242 | 100 * 5 / 6, | 1242 | 100 * 5 / 6, |
1243 | 100 * 6 / 7, | 1243 | 100 * 6 / 7, |
1244 | 100 * 7 / 8, | 1244 | 100 * 7 / 8, |
1245 | 100 * 8 / 9, | 1245 | 100 * 8 / 9, |
1246 | 100 * 9 / 10 | 1246 | 100 * 9 / 10 |
1247 | }; | 1247 | }; |
1248 | 1248 | ||
1249 | if (!ath_rc_priv) | 1249 | if (!ath_rc_priv) |
1250 | return; | 1250 | return; |
1251 | 1251 | ||
1252 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | 1252 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); |
1253 | 1253 | ||
1254 | ASSERT(tx_rate >= 0); | 1254 | ASSERT(tx_rate >= 0); |
1255 | if (tx_rate < 0) | 1255 | if (tx_rate < 0) |
1256 | return; | 1256 | return; |
1257 | 1257 | ||
1258 | /* To compensate for some imbalance between ctrl and ext. channel */ | 1258 | /* To compensate for some imbalance between ctrl and ext. channel */ |
1259 | 1259 | ||
1260 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) | 1260 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) |
1261 | info_priv->tx.ts_rssi = | 1261 | info_priv->tx.ts_rssi = |
1262 | info_priv->tx.ts_rssi < 3 ? 0 : | 1262 | info_priv->tx.ts_rssi < 3 ? 0 : |
1263 | info_priv->tx.ts_rssi - 3; | 1263 | info_priv->tx.ts_rssi - 3; |
1264 | 1264 | ||
1265 | last_per = rate_ctrl->state[tx_rate].per; | 1265 | last_per = rate_ctrl->state[tx_rate].per; |
1266 | 1266 | ||
1267 | if (xretries) { | 1267 | if (xretries) { |
1268 | /* Update the PER. */ | 1268 | /* Update the PER. */ |
1269 | if (xretries == 1) { | 1269 | if (xretries == 1) { |
1270 | rate_ctrl->state[tx_rate].per += 30; | 1270 | rate_ctrl->state[tx_rate].per += 30; |
1271 | if (rate_ctrl->state[tx_rate].per > 100) | 1271 | if (rate_ctrl->state[tx_rate].per > 100) |
1272 | rate_ctrl->state[tx_rate].per = 100; | 1272 | rate_ctrl->state[tx_rate].per = 100; |
1273 | } else { | 1273 | } else { |
1274 | /* xretries == 2 */ | 1274 | /* xretries == 2 */ |
1275 | count = sizeof(nretry_to_per_lookup) / | 1275 | count = sizeof(nretry_to_per_lookup) / |
1276 | sizeof(nretry_to_per_lookup[0]); | 1276 | sizeof(nretry_to_per_lookup[0]); |
1277 | if (retries >= count) | 1277 | if (retries >= count) |
1278 | retries = count - 1; | 1278 | retries = count - 1; |
1279 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 1279 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
1280 | rate_ctrl->state[tx_rate].per = | 1280 | rate_ctrl->state[tx_rate].per = |
1281 | (u8)(rate_ctrl->state[tx_rate].per - | 1281 | (u8)(rate_ctrl->state[tx_rate].per - |
1282 | (rate_ctrl->state[tx_rate].per >> 3) + | 1282 | (rate_ctrl->state[tx_rate].per >> 3) + |
1283 | ((100) >> 3)); | 1283 | ((100) >> 3)); |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | /* xretries == 1 or 2 */ | 1286 | /* xretries == 1 or 2 */ |
1287 | 1287 | ||
1288 | if (rate_ctrl->probe_rate == tx_rate) | 1288 | if (rate_ctrl->probe_rate == tx_rate) |
1289 | rate_ctrl->probe_rate = 0; | 1289 | rate_ctrl->probe_rate = 0; |
1290 | 1290 | ||
1291 | } else { /* xretries == 0 */ | 1291 | } else { /* xretries == 0 */ |
1292 | /* Update the PER. */ | 1292 | /* Update the PER. */ |
1293 | /* Make sure it doesn't index out of array's bounds. */ | 1293 | /* Make sure it doesn't index out of array's bounds. */ |
1294 | count = sizeof(nretry_to_per_lookup) / | 1294 | count = sizeof(nretry_to_per_lookup) / |
1295 | sizeof(nretry_to_per_lookup[0]); | 1295 | sizeof(nretry_to_per_lookup[0]); |
1296 | if (retries >= count) | 1296 | if (retries >= count) |
1297 | retries = count - 1; | 1297 | retries = count - 1; |
1298 | if (info_priv->n_bad_frames) { | 1298 | if (info_priv->n_bad_frames) { |
1299 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) | 1299 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) |
1300 | * Assuming that n_frames is not 0. The current PER | 1300 | * Assuming that n_frames is not 0. The current PER |
1301 | * from the retries is 100 * retries / (retries+1), | 1301 | * from the retries is 100 * retries / (retries+1), |
1302 | * since the first retries attempts failed, and the | 1302 | * since the first retries attempts failed, and the |
1303 | * next one worked. For the one that worked, | 1303 | * next one worked. For the one that worked, |
1304 | * n_bad_frames subframes out of n_frames wored, | 1304 | * n_bad_frames subframes out of n_frames wored, |
1305 | * so the PER for that part is | 1305 | * so the PER for that part is |
1306 | * 100 * n_bad_frames / n_frames, and it contributes | 1306 | * 100 * n_bad_frames / n_frames, and it contributes |
1307 | * 100 * n_bad_frames / (n_frames * (retries+1)) to | 1307 | * 100 * n_bad_frames / (n_frames * (retries+1)) to |
1308 | * the above PER. The expression below is a | 1308 | * the above PER. The expression below is a |
1309 | * simplified version of the sum of these two terms. | 1309 | * simplified version of the sum of these two terms. |
1310 | */ | 1310 | */ |
1311 | if (info_priv->n_frames > 0) | 1311 | if (info_priv->n_frames > 0) |
1312 | rate_ctrl->state[tx_rate].per | 1312 | rate_ctrl->state[tx_rate].per |
1313 | = (u8) | 1313 | = (u8) |
1314 | (rate_ctrl->state[tx_rate].per - | 1314 | (rate_ctrl->state[tx_rate].per - |
1315 | (rate_ctrl->state[tx_rate].per >> 3) + | 1315 | (rate_ctrl->state[tx_rate].per >> 3) + |
1316 | ((100*(retries*info_priv->n_frames + | 1316 | ((100*(retries*info_priv->n_frames + |
1317 | info_priv->n_bad_frames) / | 1317 | info_priv->n_bad_frames) / |
1318 | (info_priv->n_frames * | 1318 | (info_priv->n_frames * |
1319 | (retries+1))) >> 3)); | 1319 | (retries+1))) >> 3)); |
1320 | } else { | 1320 | } else { |
1321 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 1321 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
1322 | 1322 | ||
1323 | rate_ctrl->state[tx_rate].per = (u8) | 1323 | rate_ctrl->state[tx_rate].per = (u8) |
1324 | (rate_ctrl->state[tx_rate].per - | 1324 | (rate_ctrl->state[tx_rate].per - |
1325 | (rate_ctrl->state[tx_rate].per >> 3) + | 1325 | (rate_ctrl->state[tx_rate].per >> 3) + |
1326 | (nretry_to_per_lookup[retries] >> 3)); | 1326 | (nretry_to_per_lookup[retries] >> 3)); |
1327 | } | 1327 | } |
1328 | 1328 | ||
1329 | rate_ctrl->rssi_last_prev2 = rate_ctrl->rssi_last_prev; | 1329 | rate_ctrl->rssi_last_prev2 = rate_ctrl->rssi_last_prev; |
1330 | rate_ctrl->rssi_last_prev = rate_ctrl->rssi_last; | 1330 | rate_ctrl->rssi_last_prev = rate_ctrl->rssi_last; |
1331 | rate_ctrl->rssi_last = info_priv->tx.ts_rssi; | 1331 | rate_ctrl->rssi_last = info_priv->tx.ts_rssi; |
1332 | rate_ctrl->rssi_time = now_msec; | 1332 | rate_ctrl->rssi_time = now_msec; |
1333 | 1333 | ||
1334 | /* | 1334 | /* |
1335 | * If we got at most one retry then increase the max rate if | 1335 | * If we got at most one retry then increase the max rate if |
1336 | * this was a probe. Otherwise, ignore the probe. | 1336 | * this was a probe. Otherwise, ignore the probe. |
1337 | */ | 1337 | */ |
1338 | 1338 | ||
1339 | if (rate_ctrl->probe_rate && rate_ctrl->probe_rate == tx_rate) { | 1339 | if (rate_ctrl->probe_rate && rate_ctrl->probe_rate == tx_rate) { |
1340 | if (retries > 0 || 2 * info_priv->n_bad_frames > | 1340 | if (retries > 0 || 2 * info_priv->n_bad_frames > |
1341 | info_priv->n_frames) { | 1341 | info_priv->n_frames) { |
1342 | /* | 1342 | /* |
1343 | * Since we probed with just a single attempt, | 1343 | * Since we probed with just a single attempt, |
1344 | * any retries means the probe failed. Also, | 1344 | * any retries means the probe failed. Also, |
1345 | * if the attempt worked, but more than half | 1345 | * if the attempt worked, but more than half |
1346 | * the subframes were bad then also consider | 1346 | * the subframes were bad then also consider |
1347 | * the probe a failure. | 1347 | * the probe a failure. |
1348 | */ | 1348 | */ |
1349 | rate_ctrl->probe_rate = 0; | 1349 | rate_ctrl->probe_rate = 0; |
1350 | } else { | 1350 | } else { |
1351 | u8 probe_rate = 0; | 1351 | u8 probe_rate = 0; |
1352 | 1352 | ||
1353 | rate_ctrl->rate_max_phy = rate_ctrl->probe_rate; | 1353 | rate_ctrl->rate_max_phy = rate_ctrl->probe_rate; |
1354 | probe_rate = rate_ctrl->probe_rate; | 1354 | probe_rate = rate_ctrl->probe_rate; |
1355 | 1355 | ||
1356 | if (rate_ctrl->state[probe_rate].per > 30) | 1356 | if (rate_ctrl->state[probe_rate].per > 30) |
1357 | rate_ctrl->state[probe_rate].per = 20; | 1357 | rate_ctrl->state[probe_rate].per = 20; |
1358 | 1358 | ||
1359 | rate_ctrl->probe_rate = 0; | 1359 | rate_ctrl->probe_rate = 0; |
1360 | 1360 | ||
1361 | /* | 1361 | /* |
1362 | * Since this probe succeeded, we allow the next | 1362 | * Since this probe succeeded, we allow the next |
1363 | * probe twice as soon. This allows the maxRate | 1363 | * probe twice as soon. This allows the maxRate |
1364 | * to move up faster if the probes are | 1364 | * to move up faster if the probes are |
1365 | * succesful. | 1365 | * succesful. |
1366 | */ | 1366 | */ |
1367 | rate_ctrl->probe_time = now_msec - | 1367 | rate_ctrl->probe_time = now_msec - |
1368 | rate_table->probe_interval / 2; | 1368 | rate_table->probe_interval / 2; |
1369 | } | 1369 | } |
1370 | } | 1370 | } |
1371 | 1371 | ||
1372 | if (retries > 0) { | 1372 | if (retries > 0) { |
1373 | /* | 1373 | /* |
1374 | * Don't update anything. We don't know if | 1374 | * Don't update anything. We don't know if |
1375 | * this was because of collisions or poor signal. | 1375 | * this was because of collisions or poor signal. |
1376 | * | 1376 | * |
1377 | * Later: if rssi_ack is close to | 1377 | * Later: if rssi_ack is close to |
1378 | * rate_ctrl->state[txRate].rssi_thres and we see lots | 1378 | * rate_ctrl->state[txRate].rssi_thres and we see lots |
1379 | * of retries, then we could increase | 1379 | * of retries, then we could increase |
1380 | * rate_ctrl->state[txRate].rssi_thres. | 1380 | * rate_ctrl->state[txRate].rssi_thres. |
1381 | */ | 1381 | */ |
1382 | rate_ctrl->hw_maxretry_pktcnt = 0; | 1382 | rate_ctrl->hw_maxretry_pktcnt = 0; |
1383 | } else { | 1383 | } else { |
1384 | /* | 1384 | /* |
1385 | * It worked with no retries. First ignore bogus (small) | 1385 | * It worked with no retries. First ignore bogus (small) |
1386 | * rssi_ack values. | 1386 | * rssi_ack values. |
1387 | */ | 1387 | */ |
1388 | if (tx_rate == rate_ctrl->rate_max_phy && | 1388 | if (tx_rate == rate_ctrl->rate_max_phy && |
1389 | rate_ctrl->hw_maxretry_pktcnt < 255) { | 1389 | rate_ctrl->hw_maxretry_pktcnt < 255) { |
1390 | rate_ctrl->hw_maxretry_pktcnt++; | 1390 | rate_ctrl->hw_maxretry_pktcnt++; |
1391 | } | 1391 | } |
1392 | 1392 | ||
1393 | if (info_priv->tx.ts_rssi >= | 1393 | if (info_priv->tx.ts_rssi >= |
1394 | rate_table->info[tx_rate].rssi_ack_validmin) { | 1394 | rate_table->info[tx_rate].rssi_ack_validmin) { |
1395 | /* Average the rssi */ | 1395 | /* Average the rssi */ |
1396 | if (tx_rate != rate_ctrl->rssi_sum_rate) { | 1396 | if (tx_rate != rate_ctrl->rssi_sum_rate) { |
1397 | rate_ctrl->rssi_sum_rate = tx_rate; | 1397 | rate_ctrl->rssi_sum_rate = tx_rate; |
1398 | rate_ctrl->rssi_sum = | 1398 | rate_ctrl->rssi_sum = |
1399 | rate_ctrl->rssi_sum_cnt = 0; | 1399 | rate_ctrl->rssi_sum_cnt = 0; |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | rate_ctrl->rssi_sum += info_priv->tx.ts_rssi; | 1402 | rate_ctrl->rssi_sum += info_priv->tx.ts_rssi; |
1403 | rate_ctrl->rssi_sum_cnt++; | 1403 | rate_ctrl->rssi_sum_cnt++; |
1404 | 1404 | ||
1405 | if (rate_ctrl->rssi_sum_cnt > 4) { | 1405 | if (rate_ctrl->rssi_sum_cnt > 4) { |
1406 | int32_t rssi_ackAvg = | 1406 | int32_t rssi_ackAvg = |
1407 | (rate_ctrl->rssi_sum + 2) / 4; | 1407 | (rate_ctrl->rssi_sum + 2) / 4; |
1408 | int8_t rssi_thres = | 1408 | int8_t rssi_thres = |
1409 | rate_ctrl->state[tx_rate]. | 1409 | rate_ctrl->state[tx_rate]. |
1410 | rssi_thres; | 1410 | rssi_thres; |
1411 | int8_t rssi_ack_vmin = | 1411 | int8_t rssi_ack_vmin = |
1412 | rate_table->info[tx_rate]. | 1412 | rate_table->info[tx_rate]. |
1413 | rssi_ack_validmin; | 1413 | rssi_ack_validmin; |
1414 | 1414 | ||
1415 | rate_ctrl->rssi_sum = | 1415 | rate_ctrl->rssi_sum = |
1416 | rate_ctrl->rssi_sum_cnt = 0; | 1416 | rate_ctrl->rssi_sum_cnt = 0; |
1417 | 1417 | ||
1418 | /* Now reduce the current | 1418 | /* Now reduce the current |
1419 | * rssi threshold. */ | 1419 | * rssi threshold. */ |
1420 | if ((rssi_ackAvg < rssi_thres + 2) && | 1420 | if ((rssi_ackAvg < rssi_thres + 2) && |
1421 | (rssi_thres > rssi_ack_vmin)) { | 1421 | (rssi_thres > rssi_ack_vmin)) { |
1422 | rate_ctrl->state[tx_rate]. | 1422 | rate_ctrl->state[tx_rate]. |
1423 | rssi_thres--; | 1423 | rssi_thres--; |
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | state_change = TRUE; | 1426 | state_change = TRUE; |
1427 | } | 1427 | } |
1428 | } | 1428 | } |
1429 | } | 1429 | } |
1430 | } | 1430 | } |
1431 | 1431 | ||
1432 | /* For all cases */ | 1432 | /* For all cases */ |
1433 | 1433 | ||
1434 | /* | 1434 | /* |
1435 | * If this rate looks bad (high PER) then stop using it for | 1435 | * If this rate looks bad (high PER) then stop using it for |
1436 | * a while (except if we are probing). | 1436 | * a while (except if we are probing). |
1437 | */ | 1437 | */ |
1438 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && | 1438 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && |
1439 | rate_table->info[tx_rate].ratekbps <= | 1439 | rate_table->info[tx_rate].ratekbps <= |
1440 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { | 1440 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { |
1441 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, | 1441 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, |
1442 | (u8) tx_rate, &rate_ctrl->rate_max_phy); | 1442 | (u8) tx_rate, &rate_ctrl->rate_max_phy); |
1443 | 1443 | ||
1444 | /* Don't probe for a little while. */ | 1444 | /* Don't probe for a little while. */ |
1445 | rate_ctrl->probe_time = now_msec; | 1445 | rate_ctrl->probe_time = now_msec; |
1446 | } | 1446 | } |
1447 | 1447 | ||
1448 | if (state_change) { | 1448 | if (state_change) { |
1449 | /* | 1449 | /* |
1450 | * Make sure the rates above this have higher rssi thresholds. | 1450 | * Make sure the rates above this have higher rssi thresholds. |
1451 | * (Note: Monotonicity is kept within the OFDM rates and | 1451 | * (Note: Monotonicity is kept within the OFDM rates and |
1452 | * within the CCK rates. However, no adjustment is | 1452 | * within the CCK rates. However, no adjustment is |
1453 | * made to keep the rssi thresholds monotonically | 1453 | * made to keep the rssi thresholds monotonically |
1454 | * increasing between the CCK and OFDM rates.) | 1454 | * increasing between the CCK and OFDM rates.) |
1455 | */ | 1455 | */ |
1456 | for (rate = tx_rate; rate < | 1456 | for (rate = tx_rate; rate < |
1457 | rate_ctrl->rate_table_size - 1; rate++) { | 1457 | rate_ctrl->rate_table_size - 1; rate++) { |
1458 | if (rate_table->info[rate+1].phy != | 1458 | if (rate_table->info[rate+1].phy != |
1459 | rate_table->info[tx_rate].phy) | 1459 | rate_table->info[tx_rate].phy) |
1460 | break; | 1460 | break; |
1461 | 1461 | ||
1462 | if (rate_ctrl->state[rate].rssi_thres + | 1462 | if (rate_ctrl->state[rate].rssi_thres + |
1463 | rate_table->info[rate].rssi_ack_deltamin > | 1463 | rate_table->info[rate].rssi_ack_deltamin > |
1464 | rate_ctrl->state[rate+1].rssi_thres) { | 1464 | rate_ctrl->state[rate+1].rssi_thres) { |
1465 | rate_ctrl->state[rate+1].rssi_thres = | 1465 | rate_ctrl->state[rate+1].rssi_thres = |
1466 | rate_ctrl->state[rate]. | 1466 | rate_ctrl->state[rate]. |
1467 | rssi_thres + | 1467 | rssi_thres + |
1468 | rate_table->info[rate]. | 1468 | rate_table->info[rate]. |
1469 | rssi_ack_deltamin; | 1469 | rssi_ack_deltamin; |
1470 | } | 1470 | } |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | /* Make sure the rates below this have lower rssi thresholds. */ | 1473 | /* Make sure the rates below this have lower rssi thresholds. */ |
1474 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1474 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1475 | if (rate_table->info[rate].phy != | 1475 | if (rate_table->info[rate].phy != |
1476 | rate_table->info[tx_rate].phy) | 1476 | rate_table->info[tx_rate].phy) |
1477 | break; | 1477 | break; |
1478 | 1478 | ||
1479 | if (rate_ctrl->state[rate].rssi_thres + | 1479 | if (rate_ctrl->state[rate].rssi_thres + |
1480 | rate_table->info[rate].rssi_ack_deltamin > | 1480 | rate_table->info[rate].rssi_ack_deltamin > |
1481 | rate_ctrl->state[rate+1].rssi_thres) { | 1481 | rate_ctrl->state[rate+1].rssi_thres) { |
1482 | if (rate_ctrl->state[rate+1].rssi_thres < | 1482 | if (rate_ctrl->state[rate+1].rssi_thres < |
1483 | rate_table->info[rate]. | 1483 | rate_table->info[rate]. |
1484 | rssi_ack_deltamin) | 1484 | rssi_ack_deltamin) |
1485 | rate_ctrl->state[rate].rssi_thres = 0; | 1485 | rate_ctrl->state[rate].rssi_thres = 0; |
1486 | else { | 1486 | else { |
1487 | rate_ctrl->state[rate].rssi_thres = | 1487 | rate_ctrl->state[rate].rssi_thres = |
1488 | rate_ctrl->state[rate+1]. | 1488 | rate_ctrl->state[rate+1]. |
1489 | rssi_thres - | 1489 | rssi_thres - |
1490 | rate_table->info[rate]. | 1490 | rate_table->info[rate]. |
1491 | rssi_ack_deltamin; | 1491 | rssi_ack_deltamin; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | if (rate_ctrl->state[rate].rssi_thres < | 1494 | if (rate_ctrl->state[rate].rssi_thres < |
1495 | rate_table->info[rate]. | 1495 | rate_table->info[rate]. |
1496 | rssi_ack_validmin) { | 1496 | rssi_ack_validmin) { |
1497 | rate_ctrl->state[rate].rssi_thres = | 1497 | rate_ctrl->state[rate].rssi_thres = |
1498 | rate_table->info[rate]. | 1498 | rate_table->info[rate]. |
1499 | rssi_ack_validmin; | 1499 | rssi_ack_validmin; |
1500 | } | 1500 | } |
1501 | } | 1501 | } |
1502 | } | 1502 | } |
1503 | } | 1503 | } |
1504 | 1504 | ||
1505 | /* Make sure the rates below this have lower PER */ | 1505 | /* Make sure the rates below this have lower PER */ |
1506 | /* Monotonicity is kept only for rates below the current rate. */ | 1506 | /* Monotonicity is kept only for rates below the current rate. */ |
1507 | if (rate_ctrl->state[tx_rate].per < last_per) { | 1507 | if (rate_ctrl->state[tx_rate].per < last_per) { |
1508 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1508 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1509 | if (rate_table->info[rate].phy != | 1509 | if (rate_table->info[rate].phy != |
1510 | rate_table->info[tx_rate].phy) | 1510 | rate_table->info[tx_rate].phy) |
1511 | break; | 1511 | break; |
1512 | 1512 | ||
1513 | if (rate_ctrl->state[rate].per > | 1513 | if (rate_ctrl->state[rate].per > |
1514 | rate_ctrl->state[rate+1].per) { | 1514 | rate_ctrl->state[rate+1].per) { |
1515 | rate_ctrl->state[rate].per = | 1515 | rate_ctrl->state[rate].per = |
1516 | rate_ctrl->state[rate+1].per; | 1516 | rate_ctrl->state[rate+1].per; |
1517 | } | 1517 | } |
1518 | } | 1518 | } |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | /* Maintain monotonicity for rates above the current rate */ | 1521 | /* Maintain monotonicity for rates above the current rate */ |
1522 | for (rate = tx_rate; rate < rate_ctrl->rate_table_size - 1; rate++) { | 1522 | for (rate = tx_rate; rate < rate_ctrl->rate_table_size - 1; rate++) { |
1523 | if (rate_ctrl->state[rate+1].per < rate_ctrl->state[rate].per) | 1523 | if (rate_ctrl->state[rate+1].per < rate_ctrl->state[rate].per) |
1524 | rate_ctrl->state[rate+1].per = | 1524 | rate_ctrl->state[rate+1].per = |
1525 | rate_ctrl->state[rate].per; | 1525 | rate_ctrl->state[rate].per; |
1526 | } | 1526 | } |
1527 | 1527 | ||
1528 | /* Every so often, we reduce the thresholds and | 1528 | /* Every so often, we reduce the thresholds and |
1529 | * PER (different for CCK and OFDM). */ | 1529 | * PER (different for CCK and OFDM). */ |
1530 | if (now_msec - rate_ctrl->rssi_down_time >= | 1530 | if (now_msec - rate_ctrl->rssi_down_time >= |
1531 | rate_table->rssi_reduce_interval) { | 1531 | rate_table->rssi_reduce_interval) { |
1532 | 1532 | ||
1533 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1533 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { |
1534 | if (rate_ctrl->state[rate].rssi_thres > | 1534 | if (rate_ctrl->state[rate].rssi_thres > |
1535 | rate_table->info[rate].rssi_ack_validmin) | 1535 | rate_table->info[rate].rssi_ack_validmin) |
1536 | rate_ctrl->state[rate].rssi_thres -= 1; | 1536 | rate_ctrl->state[rate].rssi_thres -= 1; |
1537 | } | 1537 | } |
1538 | rate_ctrl->rssi_down_time = now_msec; | 1538 | rate_ctrl->rssi_down_time = now_msec; |
1539 | } | 1539 | } |
1540 | 1540 | ||
1541 | /* Every so often, we reduce the thresholds | 1541 | /* Every so often, we reduce the thresholds |
1542 | * and PER (different for CCK and OFDM). */ | 1542 | * and PER (different for CCK and OFDM). */ |
1543 | if (now_msec - rate_ctrl->per_down_time >= | 1543 | if (now_msec - rate_ctrl->per_down_time >= |
1544 | rate_table->rssi_reduce_interval) { | 1544 | rate_table->rssi_reduce_interval) { |
1545 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1545 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { |
1546 | rate_ctrl->state[rate].per = | 1546 | rate_ctrl->state[rate].per = |
1547 | 7 * rate_ctrl->state[rate].per / 8; | 1547 | 7 * rate_ctrl->state[rate].per / 8; |
1548 | } | 1548 | } |
1549 | 1549 | ||
1550 | rate_ctrl->per_down_time = now_msec; | 1550 | rate_ctrl->per_down_time = now_msec; |
1551 | } | 1551 | } |
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | /* | 1554 | /* |
1555 | * This routine is called in rate control callback tx_status() to give | 1555 | * This routine is called in rate control callback tx_status() to give |
1556 | * the status of previous frames. | 1556 | * the status of previous frames. |
1557 | */ | 1557 | */ |
1558 | static void ath_rc_update(struct ath_softc *sc, | 1558 | static void ath_rc_update(struct ath_softc *sc, |
1559 | struct ath_rate_node *ath_rc_priv, | 1559 | struct ath_rate_node *ath_rc_priv, |
1560 | struct ath_tx_info_priv *info_priv, int final_ts_idx, | 1560 | struct ath_tx_info_priv *info_priv, int final_ts_idx, |
1561 | int xretries, int long_retry) | 1561 | int xretries, int long_retry) |
1562 | { | 1562 | { |
1563 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1563 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1564 | struct ath_rate_table *rate_table; | 1564 | struct ath_rate_table *rate_table; |
1565 | struct ath_tx_ratectrl *rate_ctrl; | 1565 | struct ath_tx_ratectrl *rate_ctrl; |
1566 | struct ath_rc_series rcs[4]; | 1566 | struct ath_rc_series rcs[4]; |
1567 | u8 flags; | 1567 | u8 flags; |
1568 | u32 series = 0, rix; | 1568 | u32 series = 0, rix; |
1569 | 1569 | ||
1570 | memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0])); | 1570 | memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0])); |
1571 | rate_table = (struct ath_rate_table *) | 1571 | rate_table = (struct ath_rate_table *) |
1572 | asc->hw_rate_table[sc->sc_curmode]; | 1572 | asc->hw_rate_table[sc->sc_curmode]; |
1573 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | 1573 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); |
1574 | ASSERT(rcs[0].tries != 0); | 1574 | ASSERT(rcs[0].tries != 0); |
1575 | 1575 | ||
1576 | /* | 1576 | /* |
1577 | * If the first rate is not the final index, there | 1577 | * If the first rate is not the final index, there |
1578 | * are intermediate rate failures to be processed. | 1578 | * are intermediate rate failures to be processed. |
1579 | */ | 1579 | */ |
1580 | if (final_ts_idx != 0) { | 1580 | if (final_ts_idx != 0) { |
1581 | /* Process intermediate rates that failed.*/ | 1581 | /* Process intermediate rates that failed.*/ |
1582 | for (series = 0; series < final_ts_idx ; series++) { | 1582 | for (series = 0; series < final_ts_idx ; series++) { |
1583 | if (rcs[series].tries != 0) { | 1583 | if (rcs[series].tries != 0) { |
1584 | flags = rcs[series].flags; | 1584 | flags = rcs[series].flags; |
1585 | /* If HT40 and we have switched mode from | 1585 | /* If HT40 and we have switched mode from |
1586 | * 40 to 20 => don't update */ | 1586 | * 40 to 20 => don't update */ |
1587 | if ((flags & ATH_RC_CW40_FLAG) && | 1587 | if ((flags & ATH_RC_CW40_FLAG) && |
1588 | (rate_ctrl->rc_phy_mode != | 1588 | (rate_ctrl->rc_phy_mode != |
1589 | (flags & ATH_RC_CW40_FLAG))) | 1589 | (flags & ATH_RC_CW40_FLAG))) |
1590 | return; | 1590 | return; |
1591 | if ((flags & ATH_RC_CW40_FLAG) && | 1591 | if ((flags & ATH_RC_CW40_FLAG) && |
1592 | (flags & ATH_RC_SGI_FLAG)) | 1592 | (flags & ATH_RC_SGI_FLAG)) |
1593 | rix = rate_table->info[ | 1593 | rix = rate_table->info[ |
1594 | rcs[series].rix].ht_index; | 1594 | rcs[series].rix].ht_index; |
1595 | else if (flags & ATH_RC_SGI_FLAG) | 1595 | else if (flags & ATH_RC_SGI_FLAG) |
1596 | rix = rate_table->info[ | 1596 | rix = rate_table->info[ |
1597 | rcs[series].rix].sgi_index; | 1597 | rcs[series].rix].sgi_index; |
1598 | else if (flags & ATH_RC_CW40_FLAG) | 1598 | else if (flags & ATH_RC_CW40_FLAG) |
1599 | rix = rate_table->info[ | 1599 | rix = rate_table->info[ |
1600 | rcs[series].rix].cw40index; | 1600 | rcs[series].rix].cw40index; |
1601 | else | 1601 | else |
1602 | rix = rate_table->info[ | 1602 | rix = rate_table->info[ |
1603 | rcs[series].rix].base_index; | 1603 | rcs[series].rix].base_index; |
1604 | ath_rc_update_ht(sc, ath_rc_priv, | 1604 | ath_rc_update_ht(sc, ath_rc_priv, |
1605 | info_priv, rix, | 1605 | info_priv, rix, |
1606 | xretries ? 1 : 2, | 1606 | xretries ? 1 : 2, |
1607 | rcs[series].tries); | 1607 | rcs[series].tries); |
1608 | } | 1608 | } |
1609 | } | 1609 | } |
1610 | } else { | 1610 | } else { |
1611 | /* | 1611 | /* |
1612 | * Handle the special case of MIMO PS burst, where the second | 1612 | * Handle the special case of MIMO PS burst, where the second |
1613 | * aggregate is sent out with only one rate and one try. | 1613 | * aggregate is sent out with only one rate and one try. |
1614 | * Treating it as an excessive retry penalizes the rate | 1614 | * Treating it as an excessive retry penalizes the rate |
1615 | * inordinately. | 1615 | * inordinately. |
1616 | */ | 1616 | */ |
1617 | if (rcs[0].tries == 1 && xretries == 1) | 1617 | if (rcs[0].tries == 1 && xretries == 1) |
1618 | xretries = 2; | 1618 | xretries = 2; |
1619 | } | 1619 | } |
1620 | 1620 | ||
1621 | flags = rcs[series].flags; | 1621 | flags = rcs[series].flags; |
1622 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ | 1622 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ |
1623 | if ((flags & ATH_RC_CW40_FLAG) && | 1623 | if ((flags & ATH_RC_CW40_FLAG) && |
1624 | (rate_ctrl->rc_phy_mode != (flags & ATH_RC_CW40_FLAG))) | 1624 | (rate_ctrl->rc_phy_mode != (flags & ATH_RC_CW40_FLAG))) |
1625 | return; | 1625 | return; |
1626 | 1626 | ||
1627 | if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG)) | 1627 | if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG)) |
1628 | rix = rate_table->info[rcs[series].rix].ht_index; | 1628 | rix = rate_table->info[rcs[series].rix].ht_index; |
1629 | else if (flags & ATH_RC_SGI_FLAG) | 1629 | else if (flags & ATH_RC_SGI_FLAG) |
1630 | rix = rate_table->info[rcs[series].rix].sgi_index; | 1630 | rix = rate_table->info[rcs[series].rix].sgi_index; |
1631 | else if (flags & ATH_RC_CW40_FLAG) | 1631 | else if (flags & ATH_RC_CW40_FLAG) |
1632 | rix = rate_table->info[rcs[series].rix].cw40index; | 1632 | rix = rate_table->info[rcs[series].rix].cw40index; |
1633 | else | 1633 | else |
1634 | rix = rate_table->info[rcs[series].rix].base_index; | 1634 | rix = rate_table->info[rcs[series].rix].base_index; |
1635 | 1635 | ||
1636 | ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix, | 1636 | ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix, |
1637 | xretries, long_retry); | 1637 | xretries, long_retry); |
1638 | } | 1638 | } |
1639 | 1639 | ||
1640 | /* | 1640 | /* |
1641 | * Process a tx descriptor for a completed transmit (success or failure). | 1641 | * Process a tx descriptor for a completed transmit (success or failure). |
1642 | */ | 1642 | */ |
1643 | static void ath_rate_tx_complete(struct ath_softc *sc, | 1643 | static void ath_rate_tx_complete(struct ath_softc *sc, |
1644 | struct ath_node *an, | 1644 | struct ath_node *an, |
1645 | struct ath_rate_node *rc_priv, | 1645 | struct ath_rate_node *rc_priv, |
1646 | struct ath_tx_info_priv *info_priv) | 1646 | struct ath_tx_info_priv *info_priv) |
1647 | { | 1647 | { |
1648 | int final_ts_idx = info_priv->tx.ts_rateindex; | 1648 | int final_ts_idx = info_priv->tx.ts_rateindex; |
1649 | int tx_status = 0, is_underrun = 0; | 1649 | int tx_status = 0, is_underrun = 0; |
1650 | struct ath_vap *avp; | 1650 | struct ath_vap *avp; |
1651 | 1651 | ||
1652 | avp = rc_priv->avp; | 1652 | avp = rc_priv->avp; |
1653 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) || | 1653 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) || |
1654 | (info_priv->tx.ts_status & ATH9K_TXERR_FILT)) | 1654 | (info_priv->tx.ts_status & ATH9K_TXERR_FILT)) |
1655 | return; | 1655 | return; |
1656 | 1656 | ||
1657 | if (info_priv->tx.ts_rssi > 0) { | 1657 | if (info_priv->tx.ts_rssi > 0) { |
1658 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, | 1658 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, |
1659 | info_priv->tx.ts_rssi); | 1659 | info_priv->tx.ts_rssi); |
1660 | } | 1660 | } |
1661 | 1661 | ||
1662 | /* | 1662 | /* |
1663 | * If underrun error is seen assume it as an excessive retry only | 1663 | * If underrun error is seen assume it as an excessive retry only |
1664 | * if prefetch trigger level have reached the max (0x3f for 5416) | 1664 | * if prefetch trigger level have reached the max (0x3f for 5416) |
1665 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY | 1665 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY |
1666 | * times. This affects how ratectrl updates PER for the failed rate. | 1666 | * times. This affects how ratectrl updates PER for the failed rate. |
1667 | */ | 1667 | */ |
1668 | if (info_priv->tx.ts_flags & | 1668 | if (info_priv->tx.ts_flags & |
1669 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && | 1669 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && |
1670 | ((sc->sc_ah->ah_txTrigLevel) >= tx_triglevel_max)) { | 1670 | ((sc->sc_ah->ah_txTrigLevel) >= tx_triglevel_max)) { |
1671 | tx_status = 1; | 1671 | tx_status = 1; |
1672 | is_underrun = 1; | 1672 | is_underrun = 1; |
1673 | } | 1673 | } |
1674 | 1674 | ||
1675 | if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || | 1675 | if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || |
1676 | (info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) | 1676 | (info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) |
1677 | tx_status = 1; | 1677 | tx_status = 1; |
1678 | 1678 | ||
1679 | ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status, | 1679 | ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status, |
1680 | (is_underrun) ? ATH_11N_TXMAXTRY : | 1680 | (is_underrun) ? ATH_11N_TXMAXTRY : |
1681 | info_priv->tx.ts_longretry); | 1681 | info_priv->tx.ts_longretry); |
1682 | } | 1682 | } |
1683 | 1683 | ||
1684 | /* | 1684 | /* |
1685 | * Update the SIB's rate control information | 1685 | * Update the SIB's rate control information |
1686 | * | 1686 | * |
1687 | * This should be called when the supported rates change | 1687 | * This should be called when the supported rates change |
1688 | * (e.g. SME operation, wireless mode change) | 1688 | * (e.g. SME operation, wireless mode change) |
1689 | * | 1689 | * |
1690 | * It will determine which rates are valid for use. | 1690 | * It will determine which rates are valid for use. |
1691 | */ | 1691 | */ |
1692 | static void ath_rc_sib_update(struct ath_softc *sc, | 1692 | static void ath_rc_sib_update(struct ath_softc *sc, |
1693 | struct ath_rate_node *ath_rc_priv, | 1693 | struct ath_rate_node *ath_rc_priv, |
1694 | u32 capflag, int keep_state, | 1694 | u32 capflag, int keep_state, |
1695 | struct ath_rateset *negotiated_rates, | 1695 | struct ath_rateset *negotiated_rates, |
1696 | struct ath_rateset *negotiated_htrates) | 1696 | struct ath_rateset *negotiated_htrates) |
1697 | { | 1697 | { |
1698 | struct ath_rate_table *rate_table = NULL; | 1698 | struct ath_rate_table *rate_table = NULL; |
1699 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1699 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1700 | struct ath_rateset *rateset = negotiated_rates; | 1700 | struct ath_rateset *rateset = negotiated_rates; |
1701 | u8 *ht_mcs = (u8 *)negotiated_htrates; | 1701 | u8 *ht_mcs = (u8 *)negotiated_htrates; |
1702 | struct ath_tx_ratectrl *rate_ctrl = | 1702 | struct ath_tx_ratectrl *rate_ctrl = |
1703 | (struct ath_tx_ratectrl *)ath_rc_priv; | 1703 | (struct ath_tx_ratectrl *)ath_rc_priv; |
1704 | u8 i, j, k, hi = 0, hthi = 0; | 1704 | u8 i, j, k, hi = 0, hthi = 0; |
1705 | 1705 | ||
1706 | rate_table = (struct ath_rate_table *) | 1706 | rate_table = (struct ath_rate_table *) |
1707 | asc->hw_rate_table[sc->sc_curmode]; | 1707 | asc->hw_rate_table[sc->sc_curmode]; |
1708 | 1708 | ||
1709 | /* Initial rate table size. Will change depending | 1709 | /* Initial rate table size. Will change depending |
1710 | * on the working rate set */ | 1710 | * on the working rate set */ |
1711 | rate_ctrl->rate_table_size = MAX_TX_RATE_TBL; | 1711 | rate_ctrl->rate_table_size = MAX_TX_RATE_TBL; |
1712 | 1712 | ||
1713 | /* Initialize thresholds according to the global rate table */ | 1713 | /* Initialize thresholds according to the global rate table */ |
1714 | for (i = 0 ; (i < rate_ctrl->rate_table_size) && (!keep_state); i++) { | 1714 | for (i = 0 ; (i < rate_ctrl->rate_table_size) && (!keep_state); i++) { |
1715 | rate_ctrl->state[i].rssi_thres = | 1715 | rate_ctrl->state[i].rssi_thres = |
1716 | rate_table->info[i].rssi_ack_validmin; | 1716 | rate_table->info[i].rssi_ack_validmin; |
1717 | rate_ctrl->state[i].per = 0; | 1717 | rate_ctrl->state[i].per = 0; |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | /* Determine the valid rates */ | 1720 | /* Determine the valid rates */ |
1721 | ath_rc_init_valid_txmask(rate_ctrl); | 1721 | ath_rc_init_valid_txmask(rate_ctrl); |
1722 | 1722 | ||
1723 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { | 1723 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { |
1724 | for (j = 0; j < MAX_TX_RATE_PHY; j++) | 1724 | for (j = 0; j < MAX_TX_RATE_PHY; j++) |
1725 | rate_ctrl->valid_phy_rateidx[i][j] = 0; | 1725 | rate_ctrl->valid_phy_rateidx[i][j] = 0; |
1726 | rate_ctrl->valid_phy_ratecnt[i] = 0; | 1726 | rate_ctrl->valid_phy_ratecnt[i] = 0; |
1727 | } | 1727 | } |
1728 | rate_ctrl->rc_phy_mode = (capflag & WLAN_RC_40_FLAG); | 1728 | rate_ctrl->rc_phy_mode = (capflag & WLAN_RC_40_FLAG); |
1729 | 1729 | ||
1730 | /* Set stream capability */ | 1730 | /* Set stream capability */ |
1731 | ath_rc_priv->single_stream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; | 1731 | ath_rc_priv->single_stream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; |
1732 | 1732 | ||
1733 | if (!rateset->rs_nrates) { | 1733 | if (!rateset->rs_nrates) { |
1734 | /* No working rate, just initialize valid rates */ | 1734 | /* No working rate, just initialize valid rates */ |
1735 | hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table, | 1735 | hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table, |
1736 | capflag); | 1736 | capflag); |
1737 | } else { | 1737 | } else { |
1738 | /* Use intersection of working rates and valid rates */ | 1738 | /* Use intersection of working rates and valid rates */ |
1739 | hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table, | 1739 | hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table, |
1740 | rateset, capflag); | 1740 | rateset, capflag); |
1741 | if (capflag & WLAN_RC_HT_FLAG) { | 1741 | if (capflag & WLAN_RC_HT_FLAG) { |
1742 | hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv, | 1742 | hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv, |
1743 | rate_table, | 1743 | rate_table, |
1744 | ht_mcs, | 1744 | ht_mcs, |
1745 | capflag); | 1745 | capflag); |
1746 | } | 1746 | } |
1747 | hi = A_MAX(hi, hthi); | 1747 | hi = A_MAX(hi, hthi); |
1748 | } | 1748 | } |
1749 | 1749 | ||
1750 | rate_ctrl->rate_table_size = hi + 1; | 1750 | rate_ctrl->rate_table_size = hi + 1; |
1751 | rate_ctrl->rate_max_phy = 0; | 1751 | rate_ctrl->rate_max_phy = 0; |
1752 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | 1752 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); |
1753 | 1753 | ||
1754 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { | 1754 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { |
1755 | for (j = 0; j < rate_ctrl->valid_phy_ratecnt[i]; j++) { | 1755 | for (j = 0; j < rate_ctrl->valid_phy_ratecnt[i]; j++) { |
1756 | rate_ctrl->valid_rate_index[k++] = | 1756 | rate_ctrl->valid_rate_index[k++] = |
1757 | rate_ctrl->valid_phy_rateidx[i][j]; | 1757 | rate_ctrl->valid_phy_rateidx[i][j]; |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE) | 1760 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE) |
1761 | || !rate_ctrl->valid_phy_ratecnt[i]) | 1761 | || !rate_ctrl->valid_phy_ratecnt[i]) |
1762 | continue; | 1762 | continue; |
1763 | 1763 | ||
1764 | rate_ctrl->rate_max_phy = rate_ctrl->valid_phy_rateidx[i][j-1]; | 1764 | rate_ctrl->rate_max_phy = rate_ctrl->valid_phy_rateidx[i][j-1]; |
1765 | } | 1765 | } |
1766 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | 1766 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); |
1767 | ASSERT(k <= MAX_TX_RATE_TBL); | 1767 | ASSERT(k <= MAX_TX_RATE_TBL); |
1768 | 1768 | ||
1769 | rate_ctrl->max_valid_rate = k; | 1769 | rate_ctrl->max_valid_rate = k; |
1770 | /* | 1770 | /* |
1771 | * Some third party vendors don't send the supported rate series in | 1771 | * Some third party vendors don't send the supported rate series in |
1772 | * order. So sorting to make sure its in order, otherwise our RateFind | 1772 | * order. So sorting to make sure its in order, otherwise our RateFind |
1773 | * Algo will select wrong rates | 1773 | * Algo will select wrong rates |
1774 | */ | 1774 | */ |
1775 | ath_rc_sort_validrates(rate_table, rate_ctrl); | 1775 | ath_rc_sort_validrates(rate_table, rate_ctrl); |
1776 | rate_ctrl->rate_max_phy = rate_ctrl->valid_rate_index[k-4]; | 1776 | rate_ctrl->rate_max_phy = rate_ctrl->valid_rate_index[k-4]; |
1777 | } | 1777 | } |
1778 | 1778 | ||
1779 | /* | 1779 | /* |
1780 | * Update rate-control state on station associate/reassociate. | 1780 | * Update rate-control state on station associate/reassociate. |
1781 | */ | 1781 | */ |
1782 | static int ath_rate_newassoc(struct ath_softc *sc, | 1782 | static int ath_rate_newassoc(struct ath_softc *sc, |
1783 | struct ath_rate_node *ath_rc_priv, | 1783 | struct ath_rate_node *ath_rc_priv, |
1784 | unsigned int capflag, | 1784 | unsigned int capflag, |
1785 | struct ath_rateset *negotiated_rates, | 1785 | struct ath_rateset *negotiated_rates, |
1786 | struct ath_rateset *negotiated_htrates) | 1786 | struct ath_rateset *negotiated_htrates) |
1787 | { | 1787 | { |
1788 | 1788 | ||
1789 | 1789 | ||
1790 | ath_rc_priv->ht_cap = | 1790 | ath_rc_priv->ht_cap = |
1791 | ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) | | 1791 | ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) | |
1792 | ((capflag & ATH_RC_SGI_FLAG) ? WLAN_RC_SGI_FLAG : 0) | | 1792 | ((capflag & ATH_RC_SGI_FLAG) ? WLAN_RC_SGI_FLAG : 0) | |
1793 | ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) | | 1793 | ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) | |
1794 | ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0); | 1794 | ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0); |
1795 | 1795 | ||
1796 | ath_rc_sib_update(sc, ath_rc_priv, ath_rc_priv->ht_cap, 0, | 1796 | ath_rc_sib_update(sc, ath_rc_priv, ath_rc_priv->ht_cap, 0, |
1797 | negotiated_rates, negotiated_htrates); | 1797 | negotiated_rates, negotiated_htrates); |
1798 | 1798 | ||
1799 | return 0; | 1799 | return 0; |
1800 | } | 1800 | } |
1801 | 1801 | ||
1802 | /* | 1802 | /* |
1803 | * This routine is called to initialize the rate control parameters | 1803 | * This routine is called to initialize the rate control parameters |
1804 | * in the SIB. It is called initially during system initialization | 1804 | * in the SIB. It is called initially during system initialization |
1805 | * or when a station is associated with the AP. | 1805 | * or when a station is associated with the AP. |
1806 | */ | 1806 | */ |
1807 | static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) | 1807 | static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) |
1808 | { | 1808 | { |
1809 | struct ath_tx_ratectrl *rate_ctrl; | 1809 | struct ath_tx_ratectrl *rate_ctrl; |
1810 | 1810 | ||
1811 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | 1811 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); |
1812 | rate_ctrl->rssi_down_time = jiffies_to_msecs(jiffies); | 1812 | rate_ctrl->rssi_down_time = jiffies_to_msecs(jiffies); |
1813 | } | 1813 | } |
1814 | 1814 | ||
1815 | 1815 | ||
1816 | static void ath_setup_rates(struct ath_softc *sc, | 1816 | static void ath_setup_rates(struct ath_softc *sc, |
1817 | struct ieee80211_supported_band *sband, | 1817 | struct ieee80211_supported_band *sband, |
1818 | struct ieee80211_sta *sta, | 1818 | struct ieee80211_sta *sta, |
1819 | struct ath_rate_node *rc_priv) | 1819 | struct ath_rate_node *rc_priv) |
1820 | 1820 | ||
1821 | { | 1821 | { |
1822 | int i, j = 0; | 1822 | int i, j = 0; |
1823 | 1823 | ||
1824 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 1824 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1825 | 1825 | ||
1826 | for (i = 0; i < sband->n_bitrates; i++) { | 1826 | for (i = 0; i < sband->n_bitrates; i++) { |
1827 | if (sta->supp_rates[sband->band] & BIT(i)) { | 1827 | if (sta->supp_rates[sband->band] & BIT(i)) { |
1828 | rc_priv->neg_rates.rs_rates[j] | 1828 | rc_priv->neg_rates.rs_rates[j] |
1829 | = (sband->bitrates[i].bitrate * 2) / 10; | 1829 | = (sband->bitrates[i].bitrate * 2) / 10; |
1830 | j++; | 1830 | j++; |
1831 | } | 1831 | } |
1832 | } | 1832 | } |
1833 | rc_priv->neg_rates.rs_nrates = j; | 1833 | rc_priv->neg_rates.rs_nrates = j; |
1834 | } | 1834 | } |
1835 | 1835 | ||
1836 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) | 1836 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) |
1837 | { | 1837 | { |
1838 | struct ath_softc *sc = hw->priv; | 1838 | struct ath_softc *sc = hw->priv; |
1839 | u32 capflag = 0; | 1839 | u32 capflag = 0; |
1840 | 1840 | ||
1841 | if (hw->conf.ht.enabled) { | 1841 | if (hw->conf.ht.enabled) { |
1842 | capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; | 1842 | capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; |
1843 | if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) | 1843 | if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) |
1844 | capflag |= ATH_RC_CW40_FLAG; | 1844 | capflag |= ATH_RC_CW40_FLAG; |
1845 | } | 1845 | } |
1846 | 1846 | ||
1847 | ath_rate_newassoc(sc, rc_priv, capflag, | 1847 | ath_rate_newassoc(sc, rc_priv, capflag, |
1848 | &rc_priv->neg_rates, | 1848 | &rc_priv->neg_rates, |
1849 | &rc_priv->neg_ht_rates); | 1849 | &rc_priv->neg_ht_rates); |
1850 | 1850 | ||
1851 | } | 1851 | } |
1852 | 1852 | ||
1853 | /* Rate Control callbacks */ | 1853 | /* Rate Control callbacks */ |
1854 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | 1854 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, |
1855 | struct ieee80211_sta *sta, void *priv_sta, | 1855 | struct ieee80211_sta *sta, void *priv_sta, |
1856 | struct sk_buff *skb) | 1856 | struct sk_buff *skb) |
1857 | { | 1857 | { |
1858 | struct ath_softc *sc = priv; | 1858 | struct ath_softc *sc = priv; |
1859 | struct ath_tx_info_priv *tx_info_priv; | 1859 | struct ath_tx_info_priv *tx_info_priv; |
1860 | struct ath_node *an; | 1860 | struct ath_node *an; |
1861 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1861 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1862 | struct ieee80211_hdr *hdr; | 1862 | struct ieee80211_hdr *hdr; |
1863 | __le16 fc; | 1863 | __le16 fc; |
1864 | 1864 | ||
1865 | hdr = (struct ieee80211_hdr *)skb->data; | 1865 | hdr = (struct ieee80211_hdr *)skb->data; |
1866 | fc = hdr->frame_control; | 1866 | fc = hdr->frame_control; |
1867 | /* XXX: UGLY HACK!! */ | 1867 | /* XXX: UGLY HACK!! */ |
1868 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | 1868 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; |
1869 | 1869 | ||
1870 | spin_lock_bh(&sc->node_lock); | 1870 | spin_lock_bh(&sc->node_lock); |
1871 | an = ath_node_find(sc, hdr->addr1); | 1871 | an = ath_node_find(sc, hdr->addr1); |
1872 | spin_unlock_bh(&sc->node_lock); | 1872 | spin_unlock_bh(&sc->node_lock); |
1873 | 1873 | ||
1874 | if (tx_info_priv == NULL) | 1874 | if (tx_info_priv == NULL) |
1875 | return; | 1875 | return; |
1876 | 1876 | ||
1877 | if (an && priv_sta && ieee80211_is_data(fc)) | 1877 | if (an && priv_sta && ieee80211_is_data(fc)) |
1878 | ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); | 1878 | ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); |
1879 | 1879 | ||
1880 | kfree(tx_info_priv); | 1880 | kfree(tx_info_priv); |
1881 | tx_info->control.vif = NULL; | 1881 | tx_info->control.vif = NULL; |
1882 | } | 1882 | } |
1883 | 1883 | ||
1884 | static void ath_tx_aggr_resp(struct ath_softc *sc, | 1884 | static void ath_tx_aggr_resp(struct ath_softc *sc, |
1885 | struct ieee80211_supported_band *sband, | 1885 | struct ieee80211_supported_band *sband, |
1886 | struct ieee80211_sta *sta, | 1886 | struct ieee80211_sta *sta, |
1887 | struct ath_node *an, | 1887 | struct ath_node *an, |
1888 | u8 tidno) | 1888 | u8 tidno) |
1889 | { | 1889 | { |
1890 | struct ath_atx_tid *txtid; | 1890 | struct ath_atx_tid *txtid; |
1891 | u16 buffersize = 0; | 1891 | u16 buffersize = 0; |
1892 | int state; | 1892 | int state; |
1893 | struct sta_info *si; | 1893 | struct sta_info *si; |
1894 | 1894 | ||
1895 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | 1895 | if (!(sc->sc_flags & SC_OP_TXAGGR)) |
1896 | return; | 1896 | return; |
1897 | 1897 | ||
1898 | txtid = ATH_AN_2_TID(an, tidno); | 1898 | txtid = ATH_AN_2_TID(an, tidno); |
1899 | if (!txtid->paused) | 1899 | if (!txtid->paused) |
1900 | return; | 1900 | return; |
1901 | 1901 | ||
1902 | /* | 1902 | /* |
1903 | * XXX: This is entirely busted, we aren't supposed to | 1903 | * XXX: This is entirely busted, we aren't supposed to |
1904 | * access the sta from here because it's internal | 1904 | * access the sta from here because it's internal |
1905 | * to mac80211, and looking at the state without | 1905 | * to mac80211, and looking at the state without |
1906 | * locking is wrong too. | 1906 | * locking is wrong too. |
1907 | */ | 1907 | */ |
1908 | si = container_of(sta, struct sta_info, sta); | 1908 | si = container_of(sta, struct sta_info, sta); |
1909 | buffersize = IEEE80211_MIN_AMPDU_BUF << | 1909 | buffersize = IEEE80211_MIN_AMPDU_BUF << |
1910 | sband->ht_cap.ampdu_factor; /* FIXME */ | 1910 | sband->ht_cap.ampdu_factor; /* FIXME */ |
1911 | state = si->ampdu_mlme.tid_state_tx[tidno]; | 1911 | state = si->ampdu_mlme.tid_state_tx[tidno]; |
1912 | 1912 | ||
1913 | if (state & HT_ADDBA_RECEIVED_MSK) { | 1913 | if (state & HT_ADDBA_RECEIVED_MSK) { |
1914 | txtid->addba_exchangecomplete = 1; | 1914 | txtid->addba_exchangecomplete = 1; |
1915 | txtid->addba_exchangeinprogress = 0; | 1915 | txtid->addba_exchangeinprogress = 0; |
1916 | txtid->baw_size = buffersize; | 1916 | txtid->baw_size = buffersize; |
1917 | 1917 | ||
1918 | DPRINTF(sc, ATH_DBG_AGGR, | 1918 | DPRINTF(sc, ATH_DBG_AGGR, |
1919 | "%s: Resuming tid, buffersize: %d\n", | 1919 | "%s: Resuming tid, buffersize: %d\n", |
1920 | __func__, | 1920 | __func__, |
1921 | buffersize); | 1921 | buffersize); |
1922 | 1922 | ||
1923 | ath_tx_resume_tid(sc, txtid); | 1923 | ath_tx_resume_tid(sc, txtid); |
1924 | } | 1924 | } |
1925 | } | 1925 | } |
1926 | 1926 | ||
1927 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | 1927 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, |
1928 | struct ieee80211_tx_rate_control *txrc) | 1928 | struct ieee80211_tx_rate_control *txrc) |
1929 | { | 1929 | { |
1930 | struct ieee80211_supported_band *sband = txrc->sband; | 1930 | struct ieee80211_supported_band *sband = txrc->sband; |
1931 | struct sk_buff *skb = txrc->skb; | 1931 | struct sk_buff *skb = txrc->skb; |
1932 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1932 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1933 | struct ath_softc *sc = priv; | 1933 | struct ath_softc *sc = priv; |
1934 | struct ieee80211_hw *hw = sc->hw; | 1934 | struct ieee80211_hw *hw = sc->hw; |
1935 | struct ath_tx_info_priv *tx_info_priv; | 1935 | struct ath_tx_info_priv *tx_info_priv; |
1936 | struct ath_rate_node *ath_rc_priv = priv_sta; | 1936 | struct ath_rate_node *ath_rc_priv = priv_sta; |
1937 | struct ath_node *an; | 1937 | struct ath_node *an; |
1938 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1938 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1939 | int is_probe = FALSE, chk, ret; | 1939 | int is_probe = FALSE, chk, ret; |
1940 | s8 lowest_idx; | 1940 | s8 lowest_idx; |
1941 | __le16 fc = hdr->frame_control; | 1941 | __le16 fc = hdr->frame_control; |
1942 | u8 *qc, tid; | 1942 | u8 *qc, tid; |
1943 | 1943 | ||
1944 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 1944 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1945 | 1945 | ||
1946 | /* allocate driver private area of tx_info, XXX: UGLY HACK! */ | 1946 | /* allocate driver private area of tx_info, XXX: UGLY HACK! */ |
1947 | tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); | 1947 | tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); |
1948 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | 1948 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; |
1949 | ASSERT(tx_info_priv != NULL); | 1949 | ASSERT(tx_info_priv != NULL); |
1950 | 1950 | ||
1951 | lowest_idx = rate_lowest_index(sband, sta); | 1951 | lowest_idx = rate_lowest_index(sband, sta); |
1952 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; | 1952 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; |
1953 | /* lowest rate for management and multicast/broadcast frames */ | 1953 | /* lowest rate for management and multicast/broadcast frames */ |
1954 | if (!ieee80211_is_data(fc) || | 1954 | if (!ieee80211_is_data(fc) || |
1955 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 1955 | is_multicast_ether_addr(hdr->addr1) || !sta) { |
1956 | tx_info->control.rates[0].idx = lowest_idx; | 1956 | tx_info->control.rates[0].idx = lowest_idx; |
1957 | return; | 1957 | return; |
1958 | } | 1958 | } |
1959 | 1959 | ||
1960 | /* Find tx rate for unicast frames */ | 1960 | /* Find tx rate for unicast frames */ |
1961 | ath_rate_findrate(sc, ath_rc_priv, | 1961 | ath_rate_findrate(sc, ath_rc_priv, |
1962 | ATH_11N_TXMAXTRY, 4, | 1962 | ATH_11N_TXMAXTRY, 4, |
1963 | ATH_RC_PROBE_ALLOWED, | 1963 | ATH_RC_PROBE_ALLOWED, |
1964 | tx_info_priv->rcs, | 1964 | tx_info_priv->rcs, |
1965 | &is_probe, | 1965 | &is_probe, |
1966 | false); | 1966 | false); |
1967 | #if 0 | 1967 | #if 0 |
1968 | if (is_probe) | 1968 | if (is_probe) |
1969 | sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; | 1969 | sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; |
1970 | #endif | 1970 | #endif |
1971 | 1971 | ||
1972 | /* Ratecontrol sometimes returns invalid rate index */ | 1972 | /* Ratecontrol sometimes returns invalid rate index */ |
1973 | if (tx_info_priv->rcs[0].rix != 0xff) | 1973 | if (tx_info_priv->rcs[0].rix != 0xff) |
1974 | ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix; | 1974 | ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix; |
1975 | else | 1975 | else |
1976 | tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; | 1976 | tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; |
1977 | 1977 | ||
1978 | tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix; | 1978 | tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix; |
1979 | 1979 | ||
1980 | /* Check if aggregation has to be enabled for this tid */ | 1980 | /* Check if aggregation has to be enabled for this tid */ |
1981 | 1981 | ||
1982 | if (hw->conf.ht.enabled) { | 1982 | if (hw->conf.ht.enabled) { |
1983 | if (ieee80211_is_data_qos(fc)) { | 1983 | if (ieee80211_is_data_qos(fc)) { |
1984 | qc = ieee80211_get_qos_ctl(hdr); | 1984 | qc = ieee80211_get_qos_ctl(hdr); |
1985 | tid = qc[0] & 0xf; | 1985 | tid = qc[0] & 0xf; |
1986 | 1986 | ||
1987 | spin_lock_bh(&sc->node_lock); | 1987 | spin_lock_bh(&sc->node_lock); |
1988 | an = ath_node_find(sc, hdr->addr1); | 1988 | an = ath_node_find(sc, hdr->addr1); |
1989 | spin_unlock_bh(&sc->node_lock); | 1989 | spin_unlock_bh(&sc->node_lock); |
1990 | 1990 | ||
1991 | if (!an) { | 1991 | if (!an) { |
1992 | DPRINTF(sc, ATH_DBG_AGGR, | 1992 | DPRINTF(sc, ATH_DBG_AGGR, |
1993 | "%s: Node not found to " | 1993 | "%s: Node not found to " |
1994 | "init/chk TX aggr\n", __func__); | 1994 | "init/chk TX aggr\n", __func__); |
1995 | return; | 1995 | return; |
1996 | } | 1996 | } |
1997 | 1997 | ||
1998 | chk = ath_tx_aggr_check(sc, an, tid); | 1998 | chk = ath_tx_aggr_check(sc, an, tid); |
1999 | if (chk == AGGR_REQUIRED) { | 1999 | if (chk == AGGR_REQUIRED) { |
2000 | ret = ieee80211_start_tx_ba_session(hw, | 2000 | ret = ieee80211_start_tx_ba_session(hw, |
2001 | hdr->addr1, tid); | 2001 | hdr->addr1, tid); |
2002 | if (ret) | 2002 | if (ret) |
2003 | DPRINTF(sc, ATH_DBG_AGGR, | 2003 | DPRINTF(sc, ATH_DBG_AGGR, |
2004 | "%s: Unable to start tx " | 2004 | "%s: Unable to start tx " |
2005 | "aggr for: %pM\n", | 2005 | "aggr for: %pM\n", |
2006 | __func__, | 2006 | __func__, |
2007 | hdr->addr1); | 2007 | hdr->addr1); |
2008 | else | 2008 | else |
2009 | DPRINTF(sc, ATH_DBG_AGGR, | 2009 | DPRINTF(sc, ATH_DBG_AGGR, |
2010 | "%s: Started tx aggr for: %pM\n", | 2010 | "%s: Started tx aggr for: %pM\n", |
2011 | __func__, | 2011 | __func__, |
2012 | hdr->addr1); | 2012 | hdr->addr1); |
2013 | } else if (chk == AGGR_EXCHANGE_PROGRESS) | 2013 | } else if (chk == AGGR_EXCHANGE_PROGRESS) |
2014 | ath_tx_aggr_resp(sc, sband, sta, an, tid); | 2014 | ath_tx_aggr_resp(sc, sband, sta, an, tid); |
2015 | } | 2015 | } |
2016 | } | 2016 | } |
2017 | } | 2017 | } |
2018 | 2018 | ||
2019 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 2019 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
2020 | struct ieee80211_sta *sta, void *priv_sta) | 2020 | struct ieee80211_sta *sta, void *priv_sta) |
2021 | { | 2021 | { |
2022 | struct ath_softc *sc = priv; | 2022 | struct ath_softc *sc = priv; |
2023 | struct ath_rate_node *ath_rc_priv = priv_sta; | 2023 | struct ath_rate_node *ath_rc_priv = priv_sta; |
2024 | int i, j = 0; | 2024 | int i, j = 0; |
2025 | 2025 | ||
2026 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2026 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2027 | 2027 | ||
2028 | ath_setup_rates(sc, sband, sta, ath_rc_priv); | 2028 | ath_setup_rates(sc, sband, sta, ath_rc_priv); |
2029 | if (sc->hw->conf.ht.enabled) { | 2029 | if (sc->hw->conf.ht.enabled) { |
2030 | for (i = 0; i < 77; i++) { | 2030 | for (i = 0; i < 77; i++) { |
2031 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) | 2031 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) |
2032 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; | 2032 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; |
2033 | if (j == ATH_RATE_MAX) | 2033 | if (j == ATH_RATE_MAX) |
2034 | break; | 2034 | break; |
2035 | } | 2035 | } |
2036 | ath_rc_priv->neg_ht_rates.rs_nrates = j; | 2036 | ath_rc_priv->neg_ht_rates.rs_nrates = j; |
2037 | } | 2037 | } |
2038 | ath_rc_node_update(sc->hw, priv_sta); | 2038 | ath_rc_node_update(sc->hw, priv_sta); |
2039 | } | 2039 | } |
2040 | 2040 | ||
2041 | static void ath_rate_clear(void *priv) | ||
2042 | { | ||
2043 | return; | ||
2044 | } | ||
2045 | |||
2046 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2041 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
2047 | { | 2042 | { |
2048 | struct ath_softc *sc = hw->priv; | 2043 | struct ath_softc *sc = hw->priv; |
2049 | 2044 | ||
2050 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2045 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2051 | return hw->priv; | 2046 | return hw->priv; |
2052 | } | 2047 | } |
2053 | 2048 | ||
2054 | static void ath_rate_free(void *priv) | 2049 | static void ath_rate_free(void *priv) |
2055 | { | 2050 | { |
2056 | return; | 2051 | return; |
2057 | } | 2052 | } |
2058 | 2053 | ||
2059 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | 2054 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
2060 | { | 2055 | { |
2061 | struct ath_softc *sc = priv; | 2056 | struct ath_softc *sc = priv; |
2062 | struct ath_vap *avp = sc->sc_vaps[0]; | 2057 | struct ath_vap *avp = sc->sc_vaps[0]; |
2063 | struct ath_rate_node *rate_priv; | 2058 | struct ath_rate_node *rate_priv; |
2064 | 2059 | ||
2065 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2060 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2066 | 2061 | ||
2067 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); | 2062 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); |
2068 | if (!rate_priv) { | 2063 | if (!rate_priv) { |
2069 | DPRINTF(sc, ATH_DBG_FATAL, | 2064 | DPRINTF(sc, ATH_DBG_FATAL, |
2070 | "%s: Unable to allocate private rc structure\n", | 2065 | "%s: Unable to allocate private rc structure\n", |
2071 | __func__); | 2066 | __func__); |
2072 | return NULL; | 2067 | return NULL; |
2073 | } | 2068 | } |
2074 | ath_rc_sib_init(rate_priv); | 2069 | ath_rc_sib_init(rate_priv); |
2075 | 2070 | ||
2076 | return rate_priv; | 2071 | return rate_priv; |
2077 | } | 2072 | } |
2078 | 2073 | ||
2079 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, | 2074 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, |
2080 | void *priv_sta) | 2075 | void *priv_sta) |
2081 | { | 2076 | { |
2082 | struct ath_rate_node *rate_priv = priv_sta; | 2077 | struct ath_rate_node *rate_priv = priv_sta; |
2083 | struct ath_softc *sc = priv; | 2078 | struct ath_softc *sc = priv; |
2084 | 2079 | ||
2085 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | 2080 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); |
2086 | ath_rate_node_free(rate_priv); | 2081 | ath_rate_node_free(rate_priv); |
2087 | } | 2082 | } |
2088 | 2083 | ||
2089 | static struct rate_control_ops ath_rate_ops = { | 2084 | static struct rate_control_ops ath_rate_ops = { |
2090 | .module = NULL, | 2085 | .module = NULL, |
2091 | .name = "ath9k_rate_control", | 2086 | .name = "ath9k_rate_control", |
2092 | .tx_status = ath_tx_status, | 2087 | .tx_status = ath_tx_status, |
2093 | .get_rate = ath_get_rate, | 2088 | .get_rate = ath_get_rate, |
2094 | .rate_init = ath_rate_init, | 2089 | .rate_init = ath_rate_init, |
2095 | .clear = ath_rate_clear, | ||
2096 | .alloc = ath_rate_alloc, | 2090 | .alloc = ath_rate_alloc, |
2097 | .free = ath_rate_free, | 2091 | .free = ath_rate_free, |
2098 | .alloc_sta = ath_rate_alloc_sta, | 2092 | .alloc_sta = ath_rate_alloc_sta, |
2099 | .free_sta = ath_rate_free_sta, | 2093 | .free_sta = ath_rate_free_sta, |
2100 | }; | 2094 | }; |
2101 | 2095 | ||
2102 | int ath_rate_control_register(void) | 2096 | int ath_rate_control_register(void) |
2103 | { | 2097 | { |
2104 | return ieee80211_rate_control_register(&ath_rate_ops); | 2098 | return ieee80211_rate_control_register(&ath_rate_ops); |
2105 | } | 2099 | } |
2106 | 2100 | ||
2107 | void ath_rate_control_unregister(void) | 2101 | void ath_rate_control_unregister(void) |
2108 | { | 2102 | { |
2109 | ieee80211_rate_control_unregister(&ath_rate_ops); | 2103 | ieee80211_rate_control_unregister(&ath_rate_ops); |
2110 | } | 2104 | } |
2111 | 2105 | ||
2112 | 2106 |
drivers/net/wireless/iwlwifi/iwl-3945-rs.c
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | 9 | * This program is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License along with | 14 | * You should have received a copy of the GNU General Public License along with |
15 | * this program; if not, write to the Free Software Foundation, Inc., | 15 | * this program; if not, write to the Free Software Foundation, Inc., |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA |
17 | * | 17 | * |
18 | * The full GNU General Public License is included in this distribution in the | 18 | * The full GNU General Public License is included in this distribution in the |
19 | * file called LICENSE. | 19 | * file called LICENSE. |
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | 22 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
30 | #include <linux/wireless.h> | 30 | #include <linux/wireless.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
34 | #include <linux/etherdevice.h> | 34 | #include <linux/etherdevice.h> |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | 36 | ||
37 | #include <linux/workqueue.h> | 37 | #include <linux/workqueue.h> |
38 | 38 | ||
39 | #include "iwl-3945.h" | 39 | #include "iwl-3945.h" |
40 | 40 | ||
41 | #define RS_NAME "iwl-3945-rs" | 41 | #define RS_NAME "iwl-3945-rs" |
42 | 42 | ||
43 | struct iwl3945_rate_scale_data { | 43 | struct iwl3945_rate_scale_data { |
44 | u64 data; | 44 | u64 data; |
45 | s32 success_counter; | 45 | s32 success_counter; |
46 | s32 success_ratio; | 46 | s32 success_ratio; |
47 | s32 counter; | 47 | s32 counter; |
48 | s32 average_tpt; | 48 | s32 average_tpt; |
49 | unsigned long stamp; | 49 | unsigned long stamp; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct iwl3945_rs_sta { | 52 | struct iwl3945_rs_sta { |
53 | spinlock_t lock; | 53 | spinlock_t lock; |
54 | s32 *expected_tpt; | 54 | s32 *expected_tpt; |
55 | unsigned long last_partial_flush; | 55 | unsigned long last_partial_flush; |
56 | unsigned long last_flush; | 56 | unsigned long last_flush; |
57 | u32 flush_time; | 57 | u32 flush_time; |
58 | u32 last_tx_packets; | 58 | u32 last_tx_packets; |
59 | u32 tx_packets; | 59 | u32 tx_packets; |
60 | u8 tgg; | 60 | u8 tgg; |
61 | u8 flush_pending; | 61 | u8 flush_pending; |
62 | u8 start_rate; | 62 | u8 start_rate; |
63 | u8 ibss_sta_added; | 63 | u8 ibss_sta_added; |
64 | struct timer_list rate_scale_flush; | 64 | struct timer_list rate_scale_flush; |
65 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT]; | 65 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT]; |
66 | 66 | ||
67 | /* used to be in sta_info */ | 67 | /* used to be in sta_info */ |
68 | int last_txrate_idx; | 68 | int last_txrate_idx; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = { | 71 | static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = { |
72 | 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 | 72 | 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = { | 75 | static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = { |
76 | 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 | 76 | 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = { | 79 | static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = { |
80 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 | 80 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = { | 83 | static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = { |
84 | 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 | 84 | 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 |
85 | }; | 85 | }; |
86 | 86 | ||
87 | struct iwl3945_tpt_entry { | 87 | struct iwl3945_tpt_entry { |
88 | s8 min_rssi; | 88 | s8 min_rssi; |
89 | u8 index; | 89 | u8 index; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { | 92 | static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { |
93 | {-60, IWL_RATE_54M_INDEX}, | 93 | {-60, IWL_RATE_54M_INDEX}, |
94 | {-64, IWL_RATE_48M_INDEX}, | 94 | {-64, IWL_RATE_48M_INDEX}, |
95 | {-72, IWL_RATE_36M_INDEX}, | 95 | {-72, IWL_RATE_36M_INDEX}, |
96 | {-80, IWL_RATE_24M_INDEX}, | 96 | {-80, IWL_RATE_24M_INDEX}, |
97 | {-84, IWL_RATE_18M_INDEX}, | 97 | {-84, IWL_RATE_18M_INDEX}, |
98 | {-85, IWL_RATE_12M_INDEX}, | 98 | {-85, IWL_RATE_12M_INDEX}, |
99 | {-87, IWL_RATE_9M_INDEX}, | 99 | {-87, IWL_RATE_9M_INDEX}, |
100 | {-89, IWL_RATE_6M_INDEX} | 100 | {-89, IWL_RATE_6M_INDEX} |
101 | }; | 101 | }; |
102 | 102 | ||
103 | static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { | 103 | static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { |
104 | {-60, IWL_RATE_54M_INDEX}, | 104 | {-60, IWL_RATE_54M_INDEX}, |
105 | {-64, IWL_RATE_48M_INDEX}, | 105 | {-64, IWL_RATE_48M_INDEX}, |
106 | {-68, IWL_RATE_36M_INDEX}, | 106 | {-68, IWL_RATE_36M_INDEX}, |
107 | {-80, IWL_RATE_24M_INDEX}, | 107 | {-80, IWL_RATE_24M_INDEX}, |
108 | {-84, IWL_RATE_18M_INDEX}, | 108 | {-84, IWL_RATE_18M_INDEX}, |
109 | {-85, IWL_RATE_12M_INDEX}, | 109 | {-85, IWL_RATE_12M_INDEX}, |
110 | {-86, IWL_RATE_11M_INDEX}, | 110 | {-86, IWL_RATE_11M_INDEX}, |
111 | {-88, IWL_RATE_5M_INDEX}, | 111 | {-88, IWL_RATE_5M_INDEX}, |
112 | {-90, IWL_RATE_2M_INDEX}, | 112 | {-90, IWL_RATE_2M_INDEX}, |
113 | {-92, IWL_RATE_1M_INDEX} | 113 | {-92, IWL_RATE_1M_INDEX} |
114 | }; | 114 | }; |
115 | 115 | ||
116 | #define IWL_RATE_MAX_WINDOW 62 | 116 | #define IWL_RATE_MAX_WINDOW 62 |
117 | #define IWL_RATE_FLUSH (3*HZ/10) | 117 | #define IWL_RATE_FLUSH (3*HZ/10) |
118 | #define IWL_RATE_WIN_FLUSH (HZ/2) | 118 | #define IWL_RATE_WIN_FLUSH (HZ/2) |
119 | #define IWL_RATE_HIGH_TH 11520 | 119 | #define IWL_RATE_HIGH_TH 11520 |
120 | #define IWL_RATE_MIN_FAILURE_TH 8 | 120 | #define IWL_RATE_MIN_FAILURE_TH 8 |
121 | #define IWL_RATE_MIN_SUCCESS_TH 8 | 121 | #define IWL_RATE_MIN_SUCCESS_TH 8 |
122 | #define IWL_RATE_DECREASE_TH 1920 | 122 | #define IWL_RATE_DECREASE_TH 1920 |
123 | 123 | ||
124 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) | 124 | static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) |
125 | { | 125 | { |
126 | u32 index = 0; | 126 | u32 index = 0; |
127 | u32 table_size = 0; | 127 | u32 table_size = 0; |
128 | struct iwl3945_tpt_entry *tpt_table = NULL; | 128 | struct iwl3945_tpt_entry *tpt_table = NULL; |
129 | 129 | ||
130 | if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) | 130 | if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) |
131 | rssi = IWL_MIN_RSSI_VAL; | 131 | rssi = IWL_MIN_RSSI_VAL; |
132 | 132 | ||
133 | switch (band) { | 133 | switch (band) { |
134 | case IEEE80211_BAND_2GHZ: | 134 | case IEEE80211_BAND_2GHZ: |
135 | tpt_table = iwl3945_tpt_table_g; | 135 | tpt_table = iwl3945_tpt_table_g; |
136 | table_size = ARRAY_SIZE(iwl3945_tpt_table_g); | 136 | table_size = ARRAY_SIZE(iwl3945_tpt_table_g); |
137 | break; | 137 | break; |
138 | 138 | ||
139 | case IEEE80211_BAND_5GHZ: | 139 | case IEEE80211_BAND_5GHZ: |
140 | tpt_table = iwl3945_tpt_table_a; | 140 | tpt_table = iwl3945_tpt_table_a; |
141 | table_size = ARRAY_SIZE(iwl3945_tpt_table_a); | 141 | table_size = ARRAY_SIZE(iwl3945_tpt_table_a); |
142 | break; | 142 | break; |
143 | 143 | ||
144 | default: | 144 | default: |
145 | BUG(); | 145 | BUG(); |
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | 148 | ||
149 | while ((index < table_size) && (rssi < tpt_table[index].min_rssi)) | 149 | while ((index < table_size) && (rssi < tpt_table[index].min_rssi)) |
150 | index++; | 150 | index++; |
151 | 151 | ||
152 | index = min(index, (table_size - 1)); | 152 | index = min(index, (table_size - 1)); |
153 | 153 | ||
154 | return tpt_table[index].index; | 154 | return tpt_table[index].index; |
155 | } | 155 | } |
156 | 156 | ||
157 | static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) | 157 | static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) |
158 | { | 158 | { |
159 | window->data = 0; | 159 | window->data = 0; |
160 | window->success_counter = 0; | 160 | window->success_counter = 0; |
161 | window->success_ratio = -1; | 161 | window->success_ratio = -1; |
162 | window->counter = 0; | 162 | window->counter = 0; |
163 | window->average_tpt = IWL_INV_TPT; | 163 | window->average_tpt = IWL_INV_TPT; |
164 | window->stamp = 0; | 164 | window->stamp = 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | /** | 167 | /** |
168 | * iwl3945_rate_scale_flush_windows - flush out the rate scale windows | 168 | * iwl3945_rate_scale_flush_windows - flush out the rate scale windows |
169 | * | 169 | * |
170 | * Returns the number of windows that have gathered data but were | 170 | * Returns the number of windows that have gathered data but were |
171 | * not flushed. If there were any that were not flushed, then | 171 | * not flushed. If there were any that were not flushed, then |
172 | * reschedule the rate flushing routine. | 172 | * reschedule the rate flushing routine. |
173 | */ | 173 | */ |
174 | static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) | 174 | static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) |
175 | { | 175 | { |
176 | int unflushed = 0; | 176 | int unflushed = 0; |
177 | int i; | 177 | int i; |
178 | unsigned long flags; | 178 | unsigned long flags; |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * For each rate, if we have collected data on that rate | 181 | * For each rate, if we have collected data on that rate |
182 | * and it has been more than IWL_RATE_WIN_FLUSH | 182 | * and it has been more than IWL_RATE_WIN_FLUSH |
183 | * since we flushed, clear out the gathered statistics | 183 | * since we flushed, clear out the gathered statistics |
184 | */ | 184 | */ |
185 | for (i = 0; i < IWL_RATE_COUNT; i++) { | 185 | for (i = 0; i < IWL_RATE_COUNT; i++) { |
186 | if (!rs_sta->win[i].counter) | 186 | if (!rs_sta->win[i].counter) |
187 | continue; | 187 | continue; |
188 | 188 | ||
189 | spin_lock_irqsave(&rs_sta->lock, flags); | 189 | spin_lock_irqsave(&rs_sta->lock, flags); |
190 | if (time_after(jiffies, rs_sta->win[i].stamp + | 190 | if (time_after(jiffies, rs_sta->win[i].stamp + |
191 | IWL_RATE_WIN_FLUSH)) { | 191 | IWL_RATE_WIN_FLUSH)) { |
192 | IWL_DEBUG_RATE("flushing %d samples of rate " | 192 | IWL_DEBUG_RATE("flushing %d samples of rate " |
193 | "index %d\n", | 193 | "index %d\n", |
194 | rs_sta->win[i].counter, i); | 194 | rs_sta->win[i].counter, i); |
195 | iwl3945_clear_window(&rs_sta->win[i]); | 195 | iwl3945_clear_window(&rs_sta->win[i]); |
196 | } else | 196 | } else |
197 | unflushed++; | 197 | unflushed++; |
198 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 198 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
199 | } | 199 | } |
200 | 200 | ||
201 | return unflushed; | 201 | return unflushed; |
202 | } | 202 | } |
203 | 203 | ||
204 | #define IWL_RATE_FLUSH_MAX 5000 /* msec */ | 204 | #define IWL_RATE_FLUSH_MAX 5000 /* msec */ |
205 | #define IWL_RATE_FLUSH_MIN 50 /* msec */ | 205 | #define IWL_RATE_FLUSH_MIN 50 /* msec */ |
206 | 206 | ||
207 | static void iwl3945_bg_rate_scale_flush(unsigned long data) | 207 | static void iwl3945_bg_rate_scale_flush(unsigned long data) |
208 | { | 208 | { |
209 | struct iwl3945_rs_sta *rs_sta = (void *)data; | 209 | struct iwl3945_rs_sta *rs_sta = (void *)data; |
210 | int unflushed = 0; | 210 | int unflushed = 0; |
211 | unsigned long flags; | 211 | unsigned long flags; |
212 | u32 packet_count, duration, pps; | 212 | u32 packet_count, duration, pps; |
213 | 213 | ||
214 | IWL_DEBUG_RATE("enter\n"); | 214 | IWL_DEBUG_RATE("enter\n"); |
215 | 215 | ||
216 | unflushed = iwl3945_rate_scale_flush_windows(rs_sta); | 216 | unflushed = iwl3945_rate_scale_flush_windows(rs_sta); |
217 | 217 | ||
218 | spin_lock_irqsave(&rs_sta->lock, flags); | 218 | spin_lock_irqsave(&rs_sta->lock, flags); |
219 | 219 | ||
220 | rs_sta->flush_pending = 0; | 220 | rs_sta->flush_pending = 0; |
221 | 221 | ||
222 | /* Number of packets Rx'd since last time this timer ran */ | 222 | /* Number of packets Rx'd since last time this timer ran */ |
223 | packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; | 223 | packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; |
224 | 224 | ||
225 | rs_sta->last_tx_packets = rs_sta->tx_packets + 1; | 225 | rs_sta->last_tx_packets = rs_sta->tx_packets + 1; |
226 | 226 | ||
227 | if (unflushed) { | 227 | if (unflushed) { |
228 | duration = | 228 | duration = |
229 | jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); | 229 | jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); |
230 | /* duration = jiffies_to_msecs(rs_sta->flush_time); */ | 230 | /* duration = jiffies_to_msecs(rs_sta->flush_time); */ |
231 | 231 | ||
232 | IWL_DEBUG_RATE("Tx'd %d packets in %dms\n", | 232 | IWL_DEBUG_RATE("Tx'd %d packets in %dms\n", |
233 | packet_count, duration); | 233 | packet_count, duration); |
234 | 234 | ||
235 | /* Determine packets per second */ | 235 | /* Determine packets per second */ |
236 | if (duration) | 236 | if (duration) |
237 | pps = (packet_count * 1000) / duration; | 237 | pps = (packet_count * 1000) / duration; |
238 | else | 238 | else |
239 | pps = 0; | 239 | pps = 0; |
240 | 240 | ||
241 | if (pps) { | 241 | if (pps) { |
242 | duration = IWL_RATE_FLUSH_MAX / pps; | 242 | duration = IWL_RATE_FLUSH_MAX / pps; |
243 | if (duration < IWL_RATE_FLUSH_MIN) | 243 | if (duration < IWL_RATE_FLUSH_MIN) |
244 | duration = IWL_RATE_FLUSH_MIN; | 244 | duration = IWL_RATE_FLUSH_MIN; |
245 | } else | 245 | } else |
246 | duration = IWL_RATE_FLUSH_MAX; | 246 | duration = IWL_RATE_FLUSH_MAX; |
247 | 247 | ||
248 | rs_sta->flush_time = msecs_to_jiffies(duration); | 248 | rs_sta->flush_time = msecs_to_jiffies(duration); |
249 | 249 | ||
250 | IWL_DEBUG_RATE("new flush period: %d msec ave %d\n", | 250 | IWL_DEBUG_RATE("new flush period: %d msec ave %d\n", |
251 | duration, packet_count); | 251 | duration, packet_count); |
252 | 252 | ||
253 | mod_timer(&rs_sta->rate_scale_flush, jiffies + | 253 | mod_timer(&rs_sta->rate_scale_flush, jiffies + |
254 | rs_sta->flush_time); | 254 | rs_sta->flush_time); |
255 | 255 | ||
256 | rs_sta->last_partial_flush = jiffies; | 256 | rs_sta->last_partial_flush = jiffies; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* If there weren't any unflushed entries, we don't schedule the timer | 259 | /* If there weren't any unflushed entries, we don't schedule the timer |
260 | * to run again */ | 260 | * to run again */ |
261 | 261 | ||
262 | rs_sta->last_flush = jiffies; | 262 | rs_sta->last_flush = jiffies; |
263 | 263 | ||
264 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 264 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
265 | 265 | ||
266 | IWL_DEBUG_RATE("leave\n"); | 266 | IWL_DEBUG_RATE("leave\n"); |
267 | } | 267 | } |
268 | 268 | ||
269 | /** | 269 | /** |
270 | * iwl3945_collect_tx_data - Update the success/failure sliding window | 270 | * iwl3945_collect_tx_data - Update the success/failure sliding window |
271 | * | 271 | * |
272 | * We keep a sliding window of the last 64 packets transmitted | 272 | * We keep a sliding window of the last 64 packets transmitted |
273 | * at this rate. window->data contains the bitmask of successful | 273 | * at this rate. window->data contains the bitmask of successful |
274 | * packets. | 274 | * packets. |
275 | */ | 275 | */ |
276 | static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | 276 | static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, |
277 | struct iwl3945_rate_scale_data *window, | 277 | struct iwl3945_rate_scale_data *window, |
278 | int success, int retries) | 278 | int success, int retries) |
279 | { | 279 | { |
280 | unsigned long flags; | 280 | unsigned long flags; |
281 | 281 | ||
282 | if (!retries) { | 282 | if (!retries) { |
283 | IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); | 283 | IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | 286 | ||
287 | while (retries--) { | 287 | while (retries--) { |
288 | spin_lock_irqsave(&rs_sta->lock, flags); | 288 | spin_lock_irqsave(&rs_sta->lock, flags); |
289 | 289 | ||
290 | /* If we have filled up the window then subtract one from the | 290 | /* If we have filled up the window then subtract one from the |
291 | * success counter if the high-bit is counting toward | 291 | * success counter if the high-bit is counting toward |
292 | * success */ | 292 | * success */ |
293 | if (window->counter == IWL_RATE_MAX_WINDOW) { | 293 | if (window->counter == IWL_RATE_MAX_WINDOW) { |
294 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) | 294 | if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) |
295 | window->success_counter--; | 295 | window->success_counter--; |
296 | } else | 296 | } else |
297 | window->counter++; | 297 | window->counter++; |
298 | 298 | ||
299 | /* Slide the window to the left one bit */ | 299 | /* Slide the window to the left one bit */ |
300 | window->data = (window->data << 1); | 300 | window->data = (window->data << 1); |
301 | 301 | ||
302 | /* If this packet was a success then set the low bit high */ | 302 | /* If this packet was a success then set the low bit high */ |
303 | if (success) { | 303 | if (success) { |
304 | window->success_counter++; | 304 | window->success_counter++; |
305 | window->data |= 1; | 305 | window->data |= 1; |
306 | } | 306 | } |
307 | 307 | ||
308 | /* window->counter can't be 0 -- it is either >0 or | 308 | /* window->counter can't be 0 -- it is either >0 or |
309 | * IWL_RATE_MAX_WINDOW */ | 309 | * IWL_RATE_MAX_WINDOW */ |
310 | window->success_ratio = 12800 * window->success_counter / | 310 | window->success_ratio = 12800 * window->success_counter / |
311 | window->counter; | 311 | window->counter; |
312 | 312 | ||
313 | /* Tag this window as having been updated */ | 313 | /* Tag this window as having been updated */ |
314 | window->stamp = jiffies; | 314 | window->stamp = jiffies; |
315 | 315 | ||
316 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 316 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
317 | } | 317 | } |
318 | } | 318 | } |
319 | 319 | ||
320 | static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, | 320 | static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, |
321 | struct ieee80211_sta *sta, void *priv_sta) | 321 | struct ieee80211_sta *sta, void *priv_sta) |
322 | { | 322 | { |
323 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 323 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
324 | int i; | 324 | int i; |
325 | 325 | ||
326 | IWL_DEBUG_RATE("enter\n"); | 326 | IWL_DEBUG_RATE("enter\n"); |
327 | 327 | ||
328 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 328 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
329 | * the lowest or the highest rate.. Could consider using RSSI from | 329 | * the lowest or the highest rate.. Could consider using RSSI from |
330 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 330 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
331 | * after assoc.. */ | 331 | * after assoc.. */ |
332 | 332 | ||
333 | for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { | 333 | for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { |
334 | if (sta->supp_rates[sband->band] & (1 << i)) { | 334 | if (sta->supp_rates[sband->band] & (1 << i)) { |
335 | rs_sta->last_txrate_idx = i; | 335 | rs_sta->last_txrate_idx = i; |
336 | break; | 336 | break; |
337 | } | 337 | } |
338 | } | 338 | } |
339 | 339 | ||
340 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ | 340 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ |
341 | if (sband->band == IEEE80211_BAND_5GHZ) | 341 | if (sband->band == IEEE80211_BAND_5GHZ) |
342 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 342 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
343 | 343 | ||
344 | IWL_DEBUG_RATE("leave\n"); | 344 | IWL_DEBUG_RATE("leave\n"); |
345 | } | 345 | } |
346 | 346 | ||
347 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 347 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
348 | { | 348 | { |
349 | return hw->priv; | 349 | return hw->priv; |
350 | } | 350 | } |
351 | 351 | ||
352 | /* rate scale requires free function to be implemented */ | 352 | /* rate scale requires free function to be implemented */ |
353 | static void rs_free(void *priv) | 353 | static void rs_free(void *priv) |
354 | { | 354 | { |
355 | return; | 355 | return; |
356 | } | 356 | } |
357 | 357 | ||
358 | static void rs_clear(void *priv) | ||
359 | { | ||
360 | return; | ||
361 | } | ||
362 | |||
363 | |||
364 | static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | 358 | static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
365 | { | 359 | { |
366 | struct iwl3945_rs_sta *rs_sta; | 360 | struct iwl3945_rs_sta *rs_sta; |
367 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 361 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; |
368 | int i; | 362 | int i; |
369 | 363 | ||
370 | /* | 364 | /* |
371 | * XXX: If it's using sta->drv_priv anyway, it might | 365 | * XXX: If it's using sta->drv_priv anyway, it might |
372 | * as well just put all the information there. | 366 | * as well just put all the information there. |
373 | */ | 367 | */ |
374 | 368 | ||
375 | IWL_DEBUG_RATE("enter\n"); | 369 | IWL_DEBUG_RATE("enter\n"); |
376 | 370 | ||
377 | rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); | 371 | rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); |
378 | if (!rs_sta) { | 372 | if (!rs_sta) { |
379 | IWL_DEBUG_RATE("leave: ENOMEM\n"); | 373 | IWL_DEBUG_RATE("leave: ENOMEM\n"); |
380 | return NULL; | 374 | return NULL; |
381 | } | 375 | } |
382 | 376 | ||
383 | psta->rs_sta = rs_sta; | 377 | psta->rs_sta = rs_sta; |
384 | 378 | ||
385 | spin_lock_init(&rs_sta->lock); | 379 | spin_lock_init(&rs_sta->lock); |
386 | 380 | ||
387 | rs_sta->start_rate = IWL_RATE_INVALID; | 381 | rs_sta->start_rate = IWL_RATE_INVALID; |
388 | 382 | ||
389 | /* default to just 802.11b */ | 383 | /* default to just 802.11b */ |
390 | rs_sta->expected_tpt = iwl3945_expected_tpt_b; | 384 | rs_sta->expected_tpt = iwl3945_expected_tpt_b; |
391 | 385 | ||
392 | rs_sta->last_partial_flush = jiffies; | 386 | rs_sta->last_partial_flush = jiffies; |
393 | rs_sta->last_flush = jiffies; | 387 | rs_sta->last_flush = jiffies; |
394 | rs_sta->flush_time = IWL_RATE_FLUSH; | 388 | rs_sta->flush_time = IWL_RATE_FLUSH; |
395 | rs_sta->last_tx_packets = 0; | 389 | rs_sta->last_tx_packets = 0; |
396 | rs_sta->ibss_sta_added = 0; | 390 | rs_sta->ibss_sta_added = 0; |
397 | 391 | ||
398 | init_timer(&rs_sta->rate_scale_flush); | 392 | init_timer(&rs_sta->rate_scale_flush); |
399 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | 393 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; |
400 | rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; | 394 | rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; |
401 | 395 | ||
402 | for (i = 0; i < IWL_RATE_COUNT; i++) | 396 | for (i = 0; i < IWL_RATE_COUNT; i++) |
403 | iwl3945_clear_window(&rs_sta->win[i]); | 397 | iwl3945_clear_window(&rs_sta->win[i]); |
404 | 398 | ||
405 | IWL_DEBUG_RATE("leave\n"); | 399 | IWL_DEBUG_RATE("leave\n"); |
406 | 400 | ||
407 | return rs_sta; | 401 | return rs_sta; |
408 | } | 402 | } |
409 | 403 | ||
410 | static void rs_free_sta(void *priv, struct ieee80211_sta *sta, | 404 | static void rs_free_sta(void *priv, struct ieee80211_sta *sta, |
411 | void *priv_sta) | 405 | void *priv_sta) |
412 | { | 406 | { |
413 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 407 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; |
414 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 408 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
415 | 409 | ||
416 | psta->rs_sta = NULL; | 410 | psta->rs_sta = NULL; |
417 | 411 | ||
418 | IWL_DEBUG_RATE("enter\n"); | 412 | IWL_DEBUG_RATE("enter\n"); |
419 | del_timer_sync(&rs_sta->rate_scale_flush); | 413 | del_timer_sync(&rs_sta->rate_scale_flush); |
420 | kfree(rs_sta); | 414 | kfree(rs_sta); |
421 | IWL_DEBUG_RATE("leave\n"); | 415 | IWL_DEBUG_RATE("leave\n"); |
422 | } | 416 | } |
423 | 417 | ||
424 | 418 | ||
425 | /** | 419 | /** |
426 | * rs_tx_status - Update rate control values based on Tx results | 420 | * rs_tx_status - Update rate control values based on Tx results |
427 | * | 421 | * |
428 | * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by | 422 | * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by |
429 | * the hardware for each rate. | 423 | * the hardware for each rate. |
430 | */ | 424 | */ |
431 | static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, | 425 | static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, |
432 | struct ieee80211_sta *sta, void *priv_sta, | 426 | struct ieee80211_sta *sta, void *priv_sta, |
433 | struct sk_buff *skb) | 427 | struct sk_buff *skb) |
434 | { | 428 | { |
435 | u8 retries = 0, current_count; | 429 | u8 retries = 0, current_count; |
436 | int scale_rate_index, first_index, last_index; | 430 | int scale_rate_index, first_index, last_index; |
437 | unsigned long flags; | 431 | unsigned long flags; |
438 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; | 432 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; |
439 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 433 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
440 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 434 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
441 | int i; | 435 | int i; |
442 | 436 | ||
443 | IWL_DEBUG_RATE("enter\n"); | 437 | IWL_DEBUG_RATE("enter\n"); |
444 | 438 | ||
445 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) | 439 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) |
446 | retries += info->status.rates[i].count; | 440 | retries += info->status.rates[i].count; |
447 | retries--; | 441 | retries--; |
448 | 442 | ||
449 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; | 443 | first_index = sband->bitrates[info->status.rates[0].idx].hw_value; |
450 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { | 444 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { |
451 | IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); | 445 | IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); |
452 | return; | 446 | return; |
453 | } | 447 | } |
454 | 448 | ||
455 | if (!priv_sta) { | 449 | if (!priv_sta) { |
456 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 450 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
457 | return; | 451 | return; |
458 | } | 452 | } |
459 | 453 | ||
460 | rs_sta->tx_packets++; | 454 | rs_sta->tx_packets++; |
461 | 455 | ||
462 | scale_rate_index = first_index; | 456 | scale_rate_index = first_index; |
463 | last_index = first_index; | 457 | last_index = first_index; |
464 | 458 | ||
465 | /* | 459 | /* |
466 | * Update the window for each rate. We determine which rates | 460 | * Update the window for each rate. We determine which rates |
467 | * were Tx'd based on the total number of retries vs. the number | 461 | * were Tx'd based on the total number of retries vs. the number |
468 | * of retries configured for each rate -- currently set to the | 462 | * of retries configured for each rate -- currently set to the |
469 | * priv value 'retry_rate' vs. rate specific | 463 | * priv value 'retry_rate' vs. rate specific |
470 | * | 464 | * |
471 | * On exit from this while loop last_index indicates the rate | 465 | * On exit from this while loop last_index indicates the rate |
472 | * at which the frame was finally transmitted (or failed if no | 466 | * at which the frame was finally transmitted (or failed if no |
473 | * ACK) | 467 | * ACK) |
474 | */ | 468 | */ |
475 | while (retries > 0) { | 469 | while (retries > 0) { |
476 | if (retries < priv->retry_rate) { | 470 | if (retries < priv->retry_rate) { |
477 | current_count = retries; | 471 | current_count = retries; |
478 | last_index = scale_rate_index; | 472 | last_index = scale_rate_index; |
479 | } else { | 473 | } else { |
480 | current_count = priv->retry_rate; | 474 | current_count = priv->retry_rate; |
481 | last_index = iwl3945_rs_next_rate(priv, | 475 | last_index = iwl3945_rs_next_rate(priv, |
482 | scale_rate_index); | 476 | scale_rate_index); |
483 | } | 477 | } |
484 | 478 | ||
485 | /* Update this rate accounting for as many retries | 479 | /* Update this rate accounting for as many retries |
486 | * as was used for it (per current_count) */ | 480 | * as was used for it (per current_count) */ |
487 | iwl3945_collect_tx_data(rs_sta, | 481 | iwl3945_collect_tx_data(rs_sta, |
488 | &rs_sta->win[scale_rate_index], | 482 | &rs_sta->win[scale_rate_index], |
489 | 0, current_count); | 483 | 0, current_count); |
490 | IWL_DEBUG_RATE("Update rate %d for %d retries.\n", | 484 | IWL_DEBUG_RATE("Update rate %d for %d retries.\n", |
491 | scale_rate_index, current_count); | 485 | scale_rate_index, current_count); |
492 | 486 | ||
493 | retries -= current_count; | 487 | retries -= current_count; |
494 | 488 | ||
495 | if (retries) | 489 | if (retries) |
496 | scale_rate_index = | 490 | scale_rate_index = |
497 | iwl3945_rs_next_rate(priv, scale_rate_index); | 491 | iwl3945_rs_next_rate(priv, scale_rate_index); |
498 | } | 492 | } |
499 | 493 | ||
500 | 494 | ||
501 | /* Update the last index window with success/failure based on ACK */ | 495 | /* Update the last index window with success/failure based on ACK */ |
502 | IWL_DEBUG_RATE("Update rate %d with %s.\n", | 496 | IWL_DEBUG_RATE("Update rate %d with %s.\n", |
503 | last_index, | 497 | last_index, |
504 | (info->flags & IEEE80211_TX_STAT_ACK) ? | 498 | (info->flags & IEEE80211_TX_STAT_ACK) ? |
505 | "success" : "failure"); | 499 | "success" : "failure"); |
506 | iwl3945_collect_tx_data(rs_sta, | 500 | iwl3945_collect_tx_data(rs_sta, |
507 | &rs_sta->win[last_index], | 501 | &rs_sta->win[last_index], |
508 | info->flags & IEEE80211_TX_STAT_ACK, 1); | 502 | info->flags & IEEE80211_TX_STAT_ACK, 1); |
509 | 503 | ||
510 | /* We updated the rate scale window -- if its been more than | 504 | /* We updated the rate scale window -- if its been more than |
511 | * flush_time since the last run, schedule the flush | 505 | * flush_time since the last run, schedule the flush |
512 | * again */ | 506 | * again */ |
513 | spin_lock_irqsave(&rs_sta->lock, flags); | 507 | spin_lock_irqsave(&rs_sta->lock, flags); |
514 | 508 | ||
515 | if (!rs_sta->flush_pending && | 509 | if (!rs_sta->flush_pending && |
516 | time_after(jiffies, rs_sta->last_partial_flush + | 510 | time_after(jiffies, rs_sta->last_partial_flush + |
517 | rs_sta->flush_time)) { | 511 | rs_sta->flush_time)) { |
518 | 512 | ||
519 | rs_sta->flush_pending = 1; | 513 | rs_sta->flush_pending = 1; |
520 | mod_timer(&rs_sta->rate_scale_flush, | 514 | mod_timer(&rs_sta->rate_scale_flush, |
521 | jiffies + rs_sta->flush_time); | 515 | jiffies + rs_sta->flush_time); |
522 | } | 516 | } |
523 | 517 | ||
524 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 518 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
525 | 519 | ||
526 | IWL_DEBUG_RATE("leave\n"); | 520 | IWL_DEBUG_RATE("leave\n"); |
527 | 521 | ||
528 | return; | 522 | return; |
529 | } | 523 | } |
530 | 524 | ||
531 | static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, | 525 | static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, |
532 | u8 index, u16 rate_mask, enum ieee80211_band band) | 526 | u8 index, u16 rate_mask, enum ieee80211_band band) |
533 | { | 527 | { |
534 | u8 high = IWL_RATE_INVALID; | 528 | u8 high = IWL_RATE_INVALID; |
535 | u8 low = IWL_RATE_INVALID; | 529 | u8 low = IWL_RATE_INVALID; |
536 | 530 | ||
537 | /* 802.11A walks to the next literal adjacent rate in | 531 | /* 802.11A walks to the next literal adjacent rate in |
538 | * the rate table */ | 532 | * the rate table */ |
539 | if (unlikely(band == IEEE80211_BAND_5GHZ)) { | 533 | if (unlikely(band == IEEE80211_BAND_5GHZ)) { |
540 | int i; | 534 | int i; |
541 | u32 mask; | 535 | u32 mask; |
542 | 536 | ||
543 | /* Find the previous rate that is in the rate mask */ | 537 | /* Find the previous rate that is in the rate mask */ |
544 | i = index - 1; | 538 | i = index - 1; |
545 | for (mask = (1 << i); i >= 0; i--, mask >>= 1) { | 539 | for (mask = (1 << i); i >= 0; i--, mask >>= 1) { |
546 | if (rate_mask & mask) { | 540 | if (rate_mask & mask) { |
547 | low = i; | 541 | low = i; |
548 | break; | 542 | break; |
549 | } | 543 | } |
550 | } | 544 | } |
551 | 545 | ||
552 | /* Find the next rate that is in the rate mask */ | 546 | /* Find the next rate that is in the rate mask */ |
553 | i = index + 1; | 547 | i = index + 1; |
554 | for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { | 548 | for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { |
555 | if (rate_mask & mask) { | 549 | if (rate_mask & mask) { |
556 | high = i; | 550 | high = i; |
557 | break; | 551 | break; |
558 | } | 552 | } |
559 | } | 553 | } |
560 | 554 | ||
561 | return (high << 8) | low; | 555 | return (high << 8) | low; |
562 | } | 556 | } |
563 | 557 | ||
564 | low = index; | 558 | low = index; |
565 | while (low != IWL_RATE_INVALID) { | 559 | while (low != IWL_RATE_INVALID) { |
566 | if (rs_sta->tgg) | 560 | if (rs_sta->tgg) |
567 | low = iwl3945_rates[low].prev_rs_tgg; | 561 | low = iwl3945_rates[low].prev_rs_tgg; |
568 | else | 562 | else |
569 | low = iwl3945_rates[low].prev_rs; | 563 | low = iwl3945_rates[low].prev_rs; |
570 | if (low == IWL_RATE_INVALID) | 564 | if (low == IWL_RATE_INVALID) |
571 | break; | 565 | break; |
572 | if (rate_mask & (1 << low)) | 566 | if (rate_mask & (1 << low)) |
573 | break; | 567 | break; |
574 | IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); | 568 | IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); |
575 | } | 569 | } |
576 | 570 | ||
577 | high = index; | 571 | high = index; |
578 | while (high != IWL_RATE_INVALID) { | 572 | while (high != IWL_RATE_INVALID) { |
579 | if (rs_sta->tgg) | 573 | if (rs_sta->tgg) |
580 | high = iwl3945_rates[high].next_rs_tgg; | 574 | high = iwl3945_rates[high].next_rs_tgg; |
581 | else | 575 | else |
582 | high = iwl3945_rates[high].next_rs; | 576 | high = iwl3945_rates[high].next_rs; |
583 | if (high == IWL_RATE_INVALID) | 577 | if (high == IWL_RATE_INVALID) |
584 | break; | 578 | break; |
585 | if (rate_mask & (1 << high)) | 579 | if (rate_mask & (1 << high)) |
586 | break; | 580 | break; |
587 | IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); | 581 | IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); |
588 | } | 582 | } |
589 | 583 | ||
590 | return (high << 8) | low; | 584 | return (high << 8) | low; |
591 | } | 585 | } |
592 | 586 | ||
593 | /** | 587 | /** |
594 | * rs_get_rate - find the rate for the requested packet | 588 | * rs_get_rate - find the rate for the requested packet |
595 | * | 589 | * |
596 | * Returns the ieee80211_rate structure allocated by the driver. | 590 | * Returns the ieee80211_rate structure allocated by the driver. |
597 | * | 591 | * |
598 | * The rate control algorithm has no internal mapping between hw_mode's | 592 | * The rate control algorithm has no internal mapping between hw_mode's |
599 | * rate ordering and the rate ordering used by the rate control algorithm. | 593 | * rate ordering and the rate ordering used by the rate control algorithm. |
600 | * | 594 | * |
601 | * The rate control algorithm uses a single table of rates that goes across | 595 | * The rate control algorithm uses a single table of rates that goes across |
602 | * the entire A/B/G spectrum vs. being limited to just one particular | 596 | * the entire A/B/G spectrum vs. being limited to just one particular |
603 | * hw_mode. | 597 | * hw_mode. |
604 | * | 598 | * |
605 | * As such, we can't convert the index obtained below into the hw_mode's | 599 | * As such, we can't convert the index obtained below into the hw_mode's |
606 | * rate table and must reference the driver allocated rate table | 600 | * rate table and must reference the driver allocated rate table |
607 | * | 601 | * |
608 | */ | 602 | */ |
609 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | 603 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, |
610 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) | 604 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) |
611 | { | 605 | { |
612 | struct ieee80211_supported_band *sband = txrc->sband; | 606 | struct ieee80211_supported_band *sband = txrc->sband; |
613 | struct sk_buff *skb = txrc->skb; | 607 | struct sk_buff *skb = txrc->skb; |
614 | u8 low = IWL_RATE_INVALID; | 608 | u8 low = IWL_RATE_INVALID; |
615 | u8 high = IWL_RATE_INVALID; | 609 | u8 high = IWL_RATE_INVALID; |
616 | u16 high_low; | 610 | u16 high_low; |
617 | int index; | 611 | int index; |
618 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 612 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
619 | struct iwl3945_rate_scale_data *window = NULL; | 613 | struct iwl3945_rate_scale_data *window = NULL; |
620 | int current_tpt = IWL_INV_TPT; | 614 | int current_tpt = IWL_INV_TPT; |
621 | int low_tpt = IWL_INV_TPT; | 615 | int low_tpt = IWL_INV_TPT; |
622 | int high_tpt = IWL_INV_TPT; | 616 | int high_tpt = IWL_INV_TPT; |
623 | u32 fail_count; | 617 | u32 fail_count; |
624 | s8 scale_action = 0; | 618 | s8 scale_action = 0; |
625 | unsigned long flags; | 619 | unsigned long flags; |
626 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 620 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
627 | u16 fc, rate_mask; | 621 | u16 fc, rate_mask; |
628 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; | 622 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; |
629 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 623 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
630 | 624 | ||
631 | IWL_DEBUG_RATE("enter\n"); | 625 | IWL_DEBUG_RATE("enter\n"); |
632 | 626 | ||
633 | /* Send management frames and broadcast/multicast data using lowest | 627 | /* Send management frames and broadcast/multicast data using lowest |
634 | * rate. */ | 628 | * rate. */ |
635 | fc = le16_to_cpu(hdr->frame_control); | 629 | fc = le16_to_cpu(hdr->frame_control); |
636 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 630 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
637 | is_multicast_ether_addr(hdr->addr1) || | 631 | is_multicast_ether_addr(hdr->addr1) || |
638 | !sta || !priv_sta) { | 632 | !sta || !priv_sta) { |
639 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 633 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
640 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 634 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
641 | return; | 635 | return; |
642 | } | 636 | } |
643 | 637 | ||
644 | rate_mask = sta->supp_rates[sband->band]; | 638 | rate_mask = sta->supp_rates[sband->band]; |
645 | index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); | 639 | index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); |
646 | 640 | ||
647 | if (sband->band == IEEE80211_BAND_5GHZ) | 641 | if (sband->band == IEEE80211_BAND_5GHZ) |
648 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; | 642 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; |
649 | 643 | ||
650 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 644 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
651 | !rs_sta->ibss_sta_added) { | 645 | !rs_sta->ibss_sta_added) { |
652 | u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); | 646 | u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); |
653 | 647 | ||
654 | if (sta_id == IWL_INVALID_STATION) { | 648 | if (sta_id == IWL_INVALID_STATION) { |
655 | IWL_DEBUG_RATE("LQ: ADD station %pm\n", | 649 | IWL_DEBUG_RATE("LQ: ADD station %pm\n", |
656 | hdr->addr1); | 650 | hdr->addr1); |
657 | sta_id = iwl3945_add_station(priv, | 651 | sta_id = iwl3945_add_station(priv, |
658 | hdr->addr1, 0, CMD_ASYNC); | 652 | hdr->addr1, 0, CMD_ASYNC); |
659 | } | 653 | } |
660 | if (sta_id != IWL_INVALID_STATION) | 654 | if (sta_id != IWL_INVALID_STATION) |
661 | rs_sta->ibss_sta_added = 1; | 655 | rs_sta->ibss_sta_added = 1; |
662 | } | 656 | } |
663 | 657 | ||
664 | spin_lock_irqsave(&rs_sta->lock, flags); | 658 | spin_lock_irqsave(&rs_sta->lock, flags); |
665 | 659 | ||
666 | if (rs_sta->start_rate != IWL_RATE_INVALID) { | 660 | if (rs_sta->start_rate != IWL_RATE_INVALID) { |
667 | index = rs_sta->start_rate; | 661 | index = rs_sta->start_rate; |
668 | rs_sta->start_rate = IWL_RATE_INVALID; | 662 | rs_sta->start_rate = IWL_RATE_INVALID; |
669 | } | 663 | } |
670 | 664 | ||
671 | window = &(rs_sta->win[index]); | 665 | window = &(rs_sta->win[index]); |
672 | 666 | ||
673 | fail_count = window->counter - window->success_counter; | 667 | fail_count = window->counter - window->success_counter; |
674 | 668 | ||
675 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && | 669 | if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && |
676 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { | 670 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { |
677 | window->average_tpt = IWL_INV_TPT; | 671 | window->average_tpt = IWL_INV_TPT; |
678 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 672 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
679 | 673 | ||
680 | IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " | 674 | IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " |
681 | "counter: %d, success_counter: %d, " | 675 | "counter: %d, success_counter: %d, " |
682 | "expected_tpt is %sNULL\n", | 676 | "expected_tpt is %sNULL\n", |
683 | index, | 677 | index, |
684 | window->counter, | 678 | window->counter, |
685 | window->success_counter, | 679 | window->success_counter, |
686 | rs_sta->expected_tpt ? "not " : ""); | 680 | rs_sta->expected_tpt ? "not " : ""); |
687 | goto out; | 681 | goto out; |
688 | 682 | ||
689 | } | 683 | } |
690 | 684 | ||
691 | window->average_tpt = ((window->success_ratio * | 685 | window->average_tpt = ((window->success_ratio * |
692 | rs_sta->expected_tpt[index] + 64) / 128); | 686 | rs_sta->expected_tpt[index] + 64) / 128); |
693 | current_tpt = window->average_tpt; | 687 | current_tpt = window->average_tpt; |
694 | 688 | ||
695 | high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, | 689 | high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, |
696 | sband->band); | 690 | sband->band); |
697 | low = high_low & 0xff; | 691 | low = high_low & 0xff; |
698 | high = (high_low >> 8) & 0xff; | 692 | high = (high_low >> 8) & 0xff; |
699 | 693 | ||
700 | if (low != IWL_RATE_INVALID) | 694 | if (low != IWL_RATE_INVALID) |
701 | low_tpt = rs_sta->win[low].average_tpt; | 695 | low_tpt = rs_sta->win[low].average_tpt; |
702 | 696 | ||
703 | if (high != IWL_RATE_INVALID) | 697 | if (high != IWL_RATE_INVALID) |
704 | high_tpt = rs_sta->win[high].average_tpt; | 698 | high_tpt = rs_sta->win[high].average_tpt; |
705 | 699 | ||
706 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 700 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
707 | 701 | ||
708 | scale_action = 1; | 702 | scale_action = 1; |
709 | 703 | ||
710 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { | 704 | if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { |
711 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); | 705 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); |
712 | scale_action = -1; | 706 | scale_action = -1; |
713 | } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT)) | 707 | } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT)) |
714 | scale_action = 1; | 708 | scale_action = 1; |
715 | else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) && | 709 | else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) && |
716 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { | 710 | (low_tpt < current_tpt) && (high_tpt < current_tpt)) { |
717 | IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " | 711 | IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " |
718 | "current_tpt [%d]\n", | 712 | "current_tpt [%d]\n", |
719 | low_tpt, high_tpt, current_tpt); | 713 | low_tpt, high_tpt, current_tpt); |
720 | scale_action = 0; | 714 | scale_action = 0; |
721 | } else { | 715 | } else { |
722 | if (high_tpt != IWL_INV_TPT) { | 716 | if (high_tpt != IWL_INV_TPT) { |
723 | if (high_tpt > current_tpt) | 717 | if (high_tpt > current_tpt) |
724 | scale_action = 1; | 718 | scale_action = 1; |
725 | else { | 719 | else { |
726 | IWL_DEBUG_RATE | 720 | IWL_DEBUG_RATE |
727 | ("decrease rate because of high tpt\n"); | 721 | ("decrease rate because of high tpt\n"); |
728 | scale_action = -1; | 722 | scale_action = -1; |
729 | } | 723 | } |
730 | } else if (low_tpt != IWL_INV_TPT) { | 724 | } else if (low_tpt != IWL_INV_TPT) { |
731 | if (low_tpt > current_tpt) { | 725 | if (low_tpt > current_tpt) { |
732 | IWL_DEBUG_RATE | 726 | IWL_DEBUG_RATE |
733 | ("decrease rate because of low tpt\n"); | 727 | ("decrease rate because of low tpt\n"); |
734 | scale_action = -1; | 728 | scale_action = -1; |
735 | } else | 729 | } else |
736 | scale_action = 1; | 730 | scale_action = 1; |
737 | } | 731 | } |
738 | } | 732 | } |
739 | 733 | ||
740 | if ((window->success_ratio > IWL_RATE_HIGH_TH) || | 734 | if ((window->success_ratio > IWL_RATE_HIGH_TH) || |
741 | (current_tpt > window->average_tpt)) { | 735 | (current_tpt > window->average_tpt)) { |
742 | IWL_DEBUG_RATE("No action -- success_ratio [%d] > HIGH_TH or " | 736 | IWL_DEBUG_RATE("No action -- success_ratio [%d] > HIGH_TH or " |
743 | "current_tpt [%d] > average_tpt [%d]\n", | 737 | "current_tpt [%d] > average_tpt [%d]\n", |
744 | window->success_ratio, | 738 | window->success_ratio, |
745 | current_tpt, window->average_tpt); | 739 | current_tpt, window->average_tpt); |
746 | scale_action = 0; | 740 | scale_action = 0; |
747 | } | 741 | } |
748 | 742 | ||
749 | switch (scale_action) { | 743 | switch (scale_action) { |
750 | case -1: | 744 | case -1: |
751 | if (low != IWL_RATE_INVALID) | 745 | if (low != IWL_RATE_INVALID) |
752 | index = low; | 746 | index = low; |
753 | break; | 747 | break; |
754 | 748 | ||
755 | case 1: | 749 | case 1: |
756 | if (high != IWL_RATE_INVALID) | 750 | if (high != IWL_RATE_INVALID) |
757 | index = high; | 751 | index = high; |
758 | 752 | ||
759 | break; | 753 | break; |
760 | 754 | ||
761 | case 0: | 755 | case 0: |
762 | default: | 756 | default: |
763 | break; | 757 | break; |
764 | } | 758 | } |
765 | 759 | ||
766 | IWL_DEBUG_RATE("Selected %d (action %d) - low %d high %d\n", | 760 | IWL_DEBUG_RATE("Selected %d (action %d) - low %d high %d\n", |
767 | index, scale_action, low, high); | 761 | index, scale_action, low, high); |
768 | 762 | ||
769 | out: | 763 | out: |
770 | 764 | ||
771 | rs_sta->last_txrate_idx = index; | 765 | rs_sta->last_txrate_idx = index; |
772 | if (sband->band == IEEE80211_BAND_5GHZ) | 766 | if (sband->band == IEEE80211_BAND_5GHZ) |
773 | info->control.rates[0].idx = rs_sta->last_txrate_idx - | 767 | info->control.rates[0].idx = rs_sta->last_txrate_idx - |
774 | IWL_FIRST_OFDM_RATE; | 768 | IWL_FIRST_OFDM_RATE; |
775 | else | 769 | else |
776 | info->control.rates[0].idx = rs_sta->last_txrate_idx; | 770 | info->control.rates[0].idx = rs_sta->last_txrate_idx; |
777 | 771 | ||
778 | IWL_DEBUG_RATE("leave: %d\n", index); | 772 | IWL_DEBUG_RATE("leave: %d\n", index); |
779 | } | 773 | } |
780 | 774 | ||
781 | static struct rate_control_ops rs_ops = { | 775 | static struct rate_control_ops rs_ops = { |
782 | .module = NULL, | 776 | .module = NULL, |
783 | .name = RS_NAME, | 777 | .name = RS_NAME, |
784 | .tx_status = rs_tx_status, | 778 | .tx_status = rs_tx_status, |
785 | .get_rate = rs_get_rate, | 779 | .get_rate = rs_get_rate, |
786 | .rate_init = rs_rate_init, | 780 | .rate_init = rs_rate_init, |
787 | .clear = rs_clear, | ||
788 | .alloc = rs_alloc, | 781 | .alloc = rs_alloc, |
789 | .free = rs_free, | 782 | .free = rs_free, |
790 | .alloc_sta = rs_alloc_sta, | 783 | .alloc_sta = rs_alloc_sta, |
791 | .free_sta = rs_free_sta, | 784 | .free_sta = rs_free_sta, |
792 | }; | 785 | }; |
793 | 786 | ||
794 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | 787 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) |
795 | { | 788 | { |
796 | struct iwl3945_priv *priv = hw->priv; | 789 | struct iwl3945_priv *priv = hw->priv; |
797 | s32 rssi = 0; | 790 | s32 rssi = 0; |
798 | unsigned long flags; | 791 | unsigned long flags; |
799 | struct iwl3945_rs_sta *rs_sta; | 792 | struct iwl3945_rs_sta *rs_sta; |
800 | struct ieee80211_sta *sta; | 793 | struct ieee80211_sta *sta; |
801 | struct iwl3945_sta_priv *psta; | 794 | struct iwl3945_sta_priv *psta; |
802 | 795 | ||
803 | IWL_DEBUG_RATE("enter\n"); | 796 | IWL_DEBUG_RATE("enter\n"); |
804 | 797 | ||
805 | rcu_read_lock(); | 798 | rcu_read_lock(); |
806 | 799 | ||
807 | sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); | 800 | sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); |
808 | if (!sta) { | 801 | if (!sta) { |
809 | rcu_read_unlock(); | 802 | rcu_read_unlock(); |
810 | return; | 803 | return; |
811 | } | 804 | } |
812 | 805 | ||
813 | psta = (void *) sta->drv_priv; | 806 | psta = (void *) sta->drv_priv; |
814 | rs_sta = psta->rs_sta; | 807 | rs_sta = psta->rs_sta; |
815 | 808 | ||
816 | spin_lock_irqsave(&rs_sta->lock, flags); | 809 | spin_lock_irqsave(&rs_sta->lock, flags); |
817 | 810 | ||
818 | rs_sta->tgg = 0; | 811 | rs_sta->tgg = 0; |
819 | switch (priv->band) { | 812 | switch (priv->band) { |
820 | case IEEE80211_BAND_2GHZ: | 813 | case IEEE80211_BAND_2GHZ: |
821 | /* TODO: this always does G, not a regression */ | 814 | /* TODO: this always does G, not a regression */ |
822 | if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { | 815 | if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { |
823 | rs_sta->tgg = 1; | 816 | rs_sta->tgg = 1; |
824 | rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; | 817 | rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; |
825 | } else | 818 | } else |
826 | rs_sta->expected_tpt = iwl3945_expected_tpt_g; | 819 | rs_sta->expected_tpt = iwl3945_expected_tpt_g; |
827 | break; | 820 | break; |
828 | 821 | ||
829 | case IEEE80211_BAND_5GHZ: | 822 | case IEEE80211_BAND_5GHZ: |
830 | rs_sta->expected_tpt = iwl3945_expected_tpt_a; | 823 | rs_sta->expected_tpt = iwl3945_expected_tpt_a; |
831 | break; | 824 | break; |
832 | case IEEE80211_NUM_BANDS: | 825 | case IEEE80211_NUM_BANDS: |
833 | BUG(); | 826 | BUG(); |
834 | break; | 827 | break; |
835 | } | 828 | } |
836 | 829 | ||
837 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 830 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
838 | 831 | ||
839 | rssi = priv->last_rx_rssi; | 832 | rssi = priv->last_rx_rssi; |
840 | if (rssi == 0) | 833 | if (rssi == 0) |
841 | rssi = IWL_MIN_RSSI_VAL; | 834 | rssi = IWL_MIN_RSSI_VAL; |
842 | 835 | ||
843 | IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi); | 836 | IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi); |
844 | 837 | ||
845 | rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); | 838 | rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); |
846 | 839 | ||
847 | IWL_DEBUG_RATE("leave: rssi %d assign rate index: " | 840 | IWL_DEBUG_RATE("leave: rssi %d assign rate index: " |
848 | "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, | 841 | "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, |
849 | iwl3945_rates[rs_sta->start_rate].plcp); | 842 | iwl3945_rates[rs_sta->start_rate].plcp); |
850 | rcu_read_unlock(); | 843 | rcu_read_unlock(); |
851 | } | 844 | } |
852 | 845 | ||
853 | int iwl3945_rate_control_register(void) | 846 | int iwl3945_rate_control_register(void) |
854 | { | 847 | { |
855 | return ieee80211_rate_control_register(&rs_ops); | 848 | return ieee80211_rate_control_register(&rs_ops); |
856 | } | 849 | } |
857 | 850 | ||
858 | void iwl3945_rate_control_unregister(void) | 851 | void iwl3945_rate_control_unregister(void) |
859 | { | 852 | { |
860 | ieee80211_rate_control_unregister(&rs_ops); | 853 | ieee80211_rate_control_unregister(&rs_ops); |
861 | } | 854 | } |
862 | 855 | ||
863 | 856 | ||
864 | 857 |
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | 9 | * This program is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License along with | 14 | * You should have received a copy of the GNU General Public License along with |
15 | * this program; if not, write to the Free Software Foundation, Inc., | 15 | * this program; if not, write to the Free Software Foundation, Inc., |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA |
17 | * | 17 | * |
18 | * The full GNU General Public License is included in this distribution in the | 18 | * The full GNU General Public License is included in this distribution in the |
19 | * file called LICENSE. | 19 | * file called LICENSE. |
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | 22 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
29 | #include <linux/wireless.h> | 29 | #include <linux/wireless.h> |
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | 31 | ||
32 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
33 | #include <linux/etherdevice.h> | 33 | #include <linux/etherdevice.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | 35 | ||
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | 37 | ||
38 | #include "iwl-dev.h" | 38 | #include "iwl-dev.h" |
39 | #include "iwl-sta.h" | 39 | #include "iwl-sta.h" |
40 | #include "iwl-core.h" | 40 | #include "iwl-core.h" |
41 | #include "iwl-helpers.h" | 41 | #include "iwl-helpers.h" |
42 | 42 | ||
43 | #define RS_NAME "iwl-agn-rs" | 43 | #define RS_NAME "iwl-agn-rs" |
44 | 44 | ||
45 | #define NUM_TRY_BEFORE_ANT_TOGGLE 1 | 45 | #define NUM_TRY_BEFORE_ANT_TOGGLE 1 |
46 | #define IWL_NUMBER_TRY 1 | 46 | #define IWL_NUMBER_TRY 1 |
47 | #define IWL_HT_NUMBER_TRY 3 | 47 | #define IWL_HT_NUMBER_TRY 3 |
48 | 48 | ||
49 | #define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ | 49 | #define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ |
50 | #define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ | 50 | #define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ |
51 | #define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ | 51 | #define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ |
52 | 52 | ||
53 | /* max time to accum history 2 seconds */ | 53 | /* max time to accum history 2 seconds */ |
54 | #define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) | 54 | #define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) |
55 | 55 | ||
56 | static u8 rs_ht_to_legacy[] = { | 56 | static u8 rs_ht_to_legacy[] = { |
57 | IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, | 57 | IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, |
58 | IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, | 58 | IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, |
59 | IWL_RATE_6M_INDEX, | 59 | IWL_RATE_6M_INDEX, |
60 | IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, | 60 | IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, |
61 | IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, | 61 | IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, |
62 | IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX, | 62 | IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX, |
63 | IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX | 63 | IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static const u8 ant_toggle_lookup[] = { | 66 | static const u8 ant_toggle_lookup[] = { |
67 | /*ANT_NONE -> */ ANT_NONE, | 67 | /*ANT_NONE -> */ ANT_NONE, |
68 | /*ANT_A -> */ ANT_B, | 68 | /*ANT_A -> */ ANT_B, |
69 | /*ANT_B -> */ ANT_C, | 69 | /*ANT_B -> */ ANT_C, |
70 | /*ANT_AB -> */ ANT_BC, | 70 | /*ANT_AB -> */ ANT_BC, |
71 | /*ANT_C -> */ ANT_A, | 71 | /*ANT_C -> */ ANT_A, |
72 | /*ANT_AC -> */ ANT_AB, | 72 | /*ANT_AC -> */ ANT_AB, |
73 | /*ANT_BC -> */ ANT_AC, | 73 | /*ANT_BC -> */ ANT_AC, |
74 | /*ANT_ABC -> */ ANT_ABC, | 74 | /*ANT_ABC -> */ ANT_ABC, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * struct iwl_rate_scale_data -- tx success history for one rate | 78 | * struct iwl_rate_scale_data -- tx success history for one rate |
79 | */ | 79 | */ |
80 | struct iwl_rate_scale_data { | 80 | struct iwl_rate_scale_data { |
81 | u64 data; /* bitmap of successful frames */ | 81 | u64 data; /* bitmap of successful frames */ |
82 | s32 success_counter; /* number of frames successful */ | 82 | s32 success_counter; /* number of frames successful */ |
83 | s32 success_ratio; /* per-cent * 128 */ | 83 | s32 success_ratio; /* per-cent * 128 */ |
84 | s32 counter; /* number of frames attempted */ | 84 | s32 counter; /* number of frames attempted */ |
85 | s32 average_tpt; /* success ratio * expected throughput */ | 85 | s32 average_tpt; /* success ratio * expected throughput */ |
86 | unsigned long stamp; | 86 | unsigned long stamp; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | 90 | * struct iwl_scale_tbl_info -- tx params and success history for all rates |
91 | * | 91 | * |
92 | * There are two of these in struct iwl_lq_sta, | 92 | * There are two of these in struct iwl_lq_sta, |
93 | * one for "active", and one for "search". | 93 | * one for "active", and one for "search". |
94 | */ | 94 | */ |
95 | struct iwl_scale_tbl_info { | 95 | struct iwl_scale_tbl_info { |
96 | enum iwl_table_type lq_type; | 96 | enum iwl_table_type lq_type; |
97 | u8 ant_type; | 97 | u8 ant_type; |
98 | u8 is_SGI; /* 1 = short guard interval */ | 98 | u8 is_SGI; /* 1 = short guard interval */ |
99 | u8 is_fat; /* 1 = 40 MHz channel width */ | 99 | u8 is_fat; /* 1 = 40 MHz channel width */ |
100 | u8 is_dup; /* 1 = duplicated data streams */ | 100 | u8 is_dup; /* 1 = duplicated data streams */ |
101 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | 101 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ |
102 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 102 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
103 | u32 current_rate; /* rate_n_flags, uCode API format */ | 103 | u32 current_rate; /* rate_n_flags, uCode API format */ |
104 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | 104 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ |
105 | }; | 105 | }; |
106 | 106 | ||
107 | struct iwl_traffic_load { | 107 | struct iwl_traffic_load { |
108 | unsigned long time_stamp; /* age of the oldest statistics */ | 108 | unsigned long time_stamp; /* age of the oldest statistics */ |
109 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | 109 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time |
110 | * slice */ | 110 | * slice */ |
111 | u32 total; /* total num of packets during the | 111 | u32 total; /* total num of packets during the |
112 | * last TID_MAX_TIME_DIFF */ | 112 | * last TID_MAX_TIME_DIFF */ |
113 | u8 queue_count; /* number of queues that has | 113 | u8 queue_count; /* number of queues that has |
114 | * been used since the last cleanup */ | 114 | * been used since the last cleanup */ |
115 | u8 head; /* start of the circular buffer */ | 115 | u8 head; /* start of the circular buffer */ |
116 | }; | 116 | }; |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * struct iwl_lq_sta -- driver's rate scaling private structure | 119 | * struct iwl_lq_sta -- driver's rate scaling private structure |
120 | * | 120 | * |
121 | * Pointer to this gets passed back and forth between driver and mac80211. | 121 | * Pointer to this gets passed back and forth between driver and mac80211. |
122 | */ | 122 | */ |
123 | struct iwl_lq_sta { | 123 | struct iwl_lq_sta { |
124 | u8 active_tbl; /* index of active table, range 0-1 */ | 124 | u8 active_tbl; /* index of active table, range 0-1 */ |
125 | u8 enable_counter; /* indicates HT mode */ | 125 | u8 enable_counter; /* indicates HT mode */ |
126 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | 126 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ |
127 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | 127 | u8 search_better_tbl; /* 1: currently trying alternate mode */ |
128 | s32 last_tpt; | 128 | s32 last_tpt; |
129 | 129 | ||
130 | /* The following determine when to search for a new mode */ | 130 | /* The following determine when to search for a new mode */ |
131 | u32 table_count_limit; | 131 | u32 table_count_limit; |
132 | u32 max_failure_limit; /* # failed frames before new search */ | 132 | u32 max_failure_limit; /* # failed frames before new search */ |
133 | u32 max_success_limit; /* # successful frames before new search */ | 133 | u32 max_success_limit; /* # successful frames before new search */ |
134 | u32 table_count; | 134 | u32 table_count; |
135 | u32 total_failed; /* total failed frames, any/all rates */ | 135 | u32 total_failed; /* total failed frames, any/all rates */ |
136 | u32 total_success; /* total successful frames, any/all rates */ | 136 | u32 total_success; /* total successful frames, any/all rates */ |
137 | u32 flush_timer; /* time staying in mode before new search */ | 137 | u32 flush_timer; /* time staying in mode before new search */ |
138 | 138 | ||
139 | u8 action_counter; /* # mode-switch actions tried */ | 139 | u8 action_counter; /* # mode-switch actions tried */ |
140 | u8 is_green; | 140 | u8 is_green; |
141 | u8 is_dup; | 141 | u8 is_dup; |
142 | enum ieee80211_band band; | 142 | enum ieee80211_band band; |
143 | u8 ibss_sta_added; | 143 | u8 ibss_sta_added; |
144 | 144 | ||
145 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 145 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
146 | u32 supp_rates; | 146 | u32 supp_rates; |
147 | u16 active_legacy_rate; | 147 | u16 active_legacy_rate; |
148 | u16 active_siso_rate; | 148 | u16 active_siso_rate; |
149 | u16 active_mimo2_rate; | 149 | u16 active_mimo2_rate; |
150 | u16 active_mimo3_rate; | 150 | u16 active_mimo3_rate; |
151 | u16 active_rate_basic; | 151 | u16 active_rate_basic; |
152 | 152 | ||
153 | struct iwl_link_quality_cmd lq; | 153 | struct iwl_link_quality_cmd lq; |
154 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | 154 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ |
155 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | 155 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; |
156 | u8 tx_agg_tid_en; | 156 | u8 tx_agg_tid_en; |
157 | #ifdef CONFIG_MAC80211_DEBUGFS | 157 | #ifdef CONFIG_MAC80211_DEBUGFS |
158 | struct dentry *rs_sta_dbgfs_scale_table_file; | 158 | struct dentry *rs_sta_dbgfs_scale_table_file; |
159 | struct dentry *rs_sta_dbgfs_stats_table_file; | 159 | struct dentry *rs_sta_dbgfs_stats_table_file; |
160 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | 160 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; |
161 | u32 dbg_fixed_rate; | 161 | u32 dbg_fixed_rate; |
162 | #endif | 162 | #endif |
163 | struct iwl_priv *drv; | 163 | struct iwl_priv *drv; |
164 | 164 | ||
165 | /* used to be in sta_info */ | 165 | /* used to be in sta_info */ |
166 | int last_txrate_idx; | 166 | int last_txrate_idx; |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 169 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
170 | struct ieee80211_hdr *hdr, | 170 | struct ieee80211_hdr *hdr, |
171 | struct ieee80211_sta *sta, | 171 | struct ieee80211_sta *sta, |
172 | struct iwl_lq_sta *lq_sta); | 172 | struct iwl_lq_sta *lq_sta); |
173 | static void rs_fill_link_cmd(const struct iwl_priv *priv, | 173 | static void rs_fill_link_cmd(const struct iwl_priv *priv, |
174 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 174 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
175 | 175 | ||
176 | 176 | ||
177 | #ifdef CONFIG_MAC80211_DEBUGFS | 177 | #ifdef CONFIG_MAC80211_DEBUGFS |
178 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 178 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
179 | u32 *rate_n_flags, int index); | 179 | u32 *rate_n_flags, int index); |
180 | #else | 180 | #else |
181 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 181 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
182 | u32 *rate_n_flags, int index) | 182 | u32 *rate_n_flags, int index) |
183 | {} | 183 | {} |
184 | #endif | 184 | #endif |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * Expected throughput metrics for following rates: | 187 | * Expected throughput metrics for following rates: |
188 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits | 188 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits |
189 | * "G" is the only table that supports CCK (the first 4 rates). | 189 | * "G" is the only table that supports CCK (the first 4 rates). |
190 | */ | 190 | */ |
191 | /*FIXME:RS:need to spearate tables for MIMO2/MIMO3*/ | 191 | /*FIXME:RS:need to spearate tables for MIMO2/MIMO3*/ |
192 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { | 192 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { |
193 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 | 193 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 |
194 | }; | 194 | }; |
195 | 195 | ||
196 | static s32 expected_tpt_G[IWL_RATE_COUNT] = { | 196 | static s32 expected_tpt_G[IWL_RATE_COUNT] = { |
197 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 | 197 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 |
198 | }; | 198 | }; |
199 | 199 | ||
200 | static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { | 200 | static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { |
201 | 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 | 201 | 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 |
202 | }; | 202 | }; |
203 | 203 | ||
204 | static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { | 204 | static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { |
205 | 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 | 205 | 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 |
206 | }; | 206 | }; |
207 | 207 | ||
208 | static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { | 208 | static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { |
209 | 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 | 209 | 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 |
210 | }; | 210 | }; |
211 | 211 | ||
212 | static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { | 212 | static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { |
213 | 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 | 213 | 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { | 216 | static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { |
217 | 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 | 217 | 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 |
218 | }; | 218 | }; |
219 | 219 | ||
220 | static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { | 220 | static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { |
221 | 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 | 221 | 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { | 224 | static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { |
225 | 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 | 225 | 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 |
226 | }; | 226 | }; |
227 | 227 | ||
228 | static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { | 228 | static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { |
229 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 | 229 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 |
230 | }; | 230 | }; |
231 | 231 | ||
232 | static inline u8 rs_extract_rate(u32 rate_n_flags) | 232 | static inline u8 rs_extract_rate(u32 rate_n_flags) |
233 | { | 233 | { |
234 | return (u8)(rate_n_flags & 0xFF); | 234 | return (u8)(rate_n_flags & 0xFF); |
235 | } | 235 | } |
236 | 236 | ||
237 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | 237 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) |
238 | { | 238 | { |
239 | window->data = 0; | 239 | window->data = 0; |
240 | window->success_counter = 0; | 240 | window->success_counter = 0; |
241 | window->success_ratio = IWL_INVALID_VALUE; | 241 | window->success_ratio = IWL_INVALID_VALUE; |
242 | window->counter = 0; | 242 | window->counter = 0; |
243 | window->average_tpt = IWL_INVALID_VALUE; | 243 | window->average_tpt = IWL_INVALID_VALUE; |
244 | window->stamp = 0; | 244 | window->stamp = 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) | 247 | static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) |
248 | { | 248 | { |
249 | return (ant_type & valid_antenna) == ant_type; | 249 | return (ant_type & valid_antenna) == ant_type; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* | 252 | /* |
253 | * removes the old data from the statistics. All data that is older than | 253 | * removes the old data from the statistics. All data that is older than |
254 | * TID_MAX_TIME_DIFF, will be deleted. | 254 | * TID_MAX_TIME_DIFF, will be deleted. |
255 | */ | 255 | */ |
256 | static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time) | 256 | static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time) |
257 | { | 257 | { |
258 | /* The oldest age we want to keep */ | 258 | /* The oldest age we want to keep */ |
259 | u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; | 259 | u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; |
260 | 260 | ||
261 | while (tl->queue_count && | 261 | while (tl->queue_count && |
262 | (tl->time_stamp < oldest_time)) { | 262 | (tl->time_stamp < oldest_time)) { |
263 | tl->total -= tl->packet_count[tl->head]; | 263 | tl->total -= tl->packet_count[tl->head]; |
264 | tl->packet_count[tl->head] = 0; | 264 | tl->packet_count[tl->head] = 0; |
265 | tl->time_stamp += TID_QUEUE_CELL_SPACING; | 265 | tl->time_stamp += TID_QUEUE_CELL_SPACING; |
266 | tl->queue_count--; | 266 | tl->queue_count--; |
267 | tl->head++; | 267 | tl->head++; |
268 | if (tl->head >= TID_QUEUE_MAX_SIZE) | 268 | if (tl->head >= TID_QUEUE_MAX_SIZE) |
269 | tl->head = 0; | 269 | tl->head = 0; |
270 | } | 270 | } |
271 | } | 271 | } |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * increment traffic load value for tid and also remove | 274 | * increment traffic load value for tid and also remove |
275 | * any old values if passed the certain time period | 275 | * any old values if passed the certain time period |
276 | */ | 276 | */ |
277 | static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, | 277 | static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, |
278 | struct ieee80211_hdr *hdr) | 278 | struct ieee80211_hdr *hdr) |
279 | { | 279 | { |
280 | u32 curr_time = jiffies_to_msecs(jiffies); | 280 | u32 curr_time = jiffies_to_msecs(jiffies); |
281 | u32 time_diff; | 281 | u32 time_diff; |
282 | s32 index; | 282 | s32 index; |
283 | struct iwl_traffic_load *tl = NULL; | 283 | struct iwl_traffic_load *tl = NULL; |
284 | __le16 fc = hdr->frame_control; | 284 | __le16 fc = hdr->frame_control; |
285 | u8 tid; | 285 | u8 tid; |
286 | 286 | ||
287 | if (ieee80211_is_data_qos(fc)) { | 287 | if (ieee80211_is_data_qos(fc)) { |
288 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 288 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
289 | tid = qc[0] & 0xf; | 289 | tid = qc[0] & 0xf; |
290 | } else | 290 | } else |
291 | return MAX_TID_COUNT; | 291 | return MAX_TID_COUNT; |
292 | 292 | ||
293 | tl = &lq_data->load[tid]; | 293 | tl = &lq_data->load[tid]; |
294 | 294 | ||
295 | curr_time -= curr_time % TID_ROUND_VALUE; | 295 | curr_time -= curr_time % TID_ROUND_VALUE; |
296 | 296 | ||
297 | /* Happens only for the first packet. Initialize the data */ | 297 | /* Happens only for the first packet. Initialize the data */ |
298 | if (!(tl->queue_count)) { | 298 | if (!(tl->queue_count)) { |
299 | tl->total = 1; | 299 | tl->total = 1; |
300 | tl->time_stamp = curr_time; | 300 | tl->time_stamp = curr_time; |
301 | tl->queue_count = 1; | 301 | tl->queue_count = 1; |
302 | tl->head = 0; | 302 | tl->head = 0; |
303 | tl->packet_count[0] = 1; | 303 | tl->packet_count[0] = 1; |
304 | return MAX_TID_COUNT; | 304 | return MAX_TID_COUNT; |
305 | } | 305 | } |
306 | 306 | ||
307 | time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); | 307 | time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); |
308 | index = time_diff / TID_QUEUE_CELL_SPACING; | 308 | index = time_diff / TID_QUEUE_CELL_SPACING; |
309 | 309 | ||
310 | /* The history is too long: remove data that is older than */ | 310 | /* The history is too long: remove data that is older than */ |
311 | /* TID_MAX_TIME_DIFF */ | 311 | /* TID_MAX_TIME_DIFF */ |
312 | if (index >= TID_QUEUE_MAX_SIZE) | 312 | if (index >= TID_QUEUE_MAX_SIZE) |
313 | rs_tl_rm_old_stats(tl, curr_time); | 313 | rs_tl_rm_old_stats(tl, curr_time); |
314 | 314 | ||
315 | index = (tl->head + index) % TID_QUEUE_MAX_SIZE; | 315 | index = (tl->head + index) % TID_QUEUE_MAX_SIZE; |
316 | tl->packet_count[index] = tl->packet_count[index] + 1; | 316 | tl->packet_count[index] = tl->packet_count[index] + 1; |
317 | tl->total = tl->total + 1; | 317 | tl->total = tl->total + 1; |
318 | 318 | ||
319 | if ((index + 1) > tl->queue_count) | 319 | if ((index + 1) > tl->queue_count) |
320 | tl->queue_count = index + 1; | 320 | tl->queue_count = index + 1; |
321 | 321 | ||
322 | return tid; | 322 | return tid; |
323 | } | 323 | } |
324 | 324 | ||
325 | /* | 325 | /* |
326 | get the traffic load value for tid | 326 | get the traffic load value for tid |
327 | */ | 327 | */ |
328 | static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) | 328 | static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) |
329 | { | 329 | { |
330 | u32 curr_time = jiffies_to_msecs(jiffies); | 330 | u32 curr_time = jiffies_to_msecs(jiffies); |
331 | u32 time_diff; | 331 | u32 time_diff; |
332 | s32 index; | 332 | s32 index; |
333 | struct iwl_traffic_load *tl = NULL; | 333 | struct iwl_traffic_load *tl = NULL; |
334 | 334 | ||
335 | if (tid >= TID_MAX_LOAD_COUNT) | 335 | if (tid >= TID_MAX_LOAD_COUNT) |
336 | return 0; | 336 | return 0; |
337 | 337 | ||
338 | tl = &(lq_data->load[tid]); | 338 | tl = &(lq_data->load[tid]); |
339 | 339 | ||
340 | curr_time -= curr_time % TID_ROUND_VALUE; | 340 | curr_time -= curr_time % TID_ROUND_VALUE; |
341 | 341 | ||
342 | if (!(tl->queue_count)) | 342 | if (!(tl->queue_count)) |
343 | return 0; | 343 | return 0; |
344 | 344 | ||
345 | time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); | 345 | time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); |
346 | index = time_diff / TID_QUEUE_CELL_SPACING; | 346 | index = time_diff / TID_QUEUE_CELL_SPACING; |
347 | 347 | ||
348 | /* The history is too long: remove data that is older than */ | 348 | /* The history is too long: remove data that is older than */ |
349 | /* TID_MAX_TIME_DIFF */ | 349 | /* TID_MAX_TIME_DIFF */ |
350 | if (index >= TID_QUEUE_MAX_SIZE) | 350 | if (index >= TID_QUEUE_MAX_SIZE) |
351 | rs_tl_rm_old_stats(tl, curr_time); | 351 | rs_tl_rm_old_stats(tl, curr_time); |
352 | 352 | ||
353 | return tl->total; | 353 | return tl->total; |
354 | } | 354 | } |
355 | 355 | ||
356 | static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | 356 | static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, |
357 | struct iwl_lq_sta *lq_data, u8 tid, | 357 | struct iwl_lq_sta *lq_data, u8 tid, |
358 | struct ieee80211_sta *sta) | 358 | struct ieee80211_sta *sta) |
359 | { | 359 | { |
360 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 360 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
361 | IWL_DEBUG_HT("Starting Tx agg: STA: %pM tid: %d\n", | 361 | IWL_DEBUG_HT("Starting Tx agg: STA: %pM tid: %d\n", |
362 | sta->addr, tid); | 362 | sta->addr, tid); |
363 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); | 363 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); |
364 | } | 364 | } |
365 | } | 365 | } |
366 | 366 | ||
367 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, | 367 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, |
368 | struct iwl_lq_sta *lq_data, | 368 | struct iwl_lq_sta *lq_data, |
369 | struct ieee80211_sta *sta) | 369 | struct ieee80211_sta *sta) |
370 | { | 370 | { |
371 | if ((tid < TID_MAX_LOAD_COUNT)) | 371 | if ((tid < TID_MAX_LOAD_COUNT)) |
372 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 372 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); |
373 | else if (tid == IWL_AGG_ALL_TID) | 373 | else if (tid == IWL_AGG_ALL_TID) |
374 | for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) | 374 | for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) |
375 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 375 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); |
376 | } | 376 | } |
377 | 377 | ||
378 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | 378 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) |
379 | { | 379 | { |
380 | return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + | 380 | return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + |
381 | !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + | 381 | !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + |
382 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 382 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
383 | } | 383 | } |
384 | 384 | ||
385 | /** | 385 | /** |
386 | * rs_collect_tx_data - Update the success/failure sliding window | 386 | * rs_collect_tx_data - Update the success/failure sliding window |
387 | * | 387 | * |
388 | * We keep a sliding window of the last 62 packets transmitted | 388 | * We keep a sliding window of the last 62 packets transmitted |
389 | * at this rate. window->data contains the bitmask of successful | 389 | * at this rate. window->data contains the bitmask of successful |
390 | * packets. | 390 | * packets. |
391 | */ | 391 | */ |
392 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 392 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, |
393 | int scale_index, s32 tpt, int retries, | 393 | int scale_index, s32 tpt, int retries, |
394 | int successes) | 394 | int successes) |
395 | { | 395 | { |
396 | struct iwl_rate_scale_data *window = NULL; | 396 | struct iwl_rate_scale_data *window = NULL; |
397 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 397 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
398 | s32 fail_count; | 398 | s32 fail_count; |
399 | 399 | ||
400 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 400 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
401 | return -EINVAL; | 401 | return -EINVAL; |
402 | 402 | ||
403 | /* Select data for current tx bit rate */ | 403 | /* Select data for current tx bit rate */ |
404 | window = &(windows[scale_index]); | 404 | window = &(windows[scale_index]); |
405 | 405 | ||
406 | /* | 406 | /* |
407 | * Keep track of only the latest 62 tx frame attempts in this rate's | 407 | * Keep track of only the latest 62 tx frame attempts in this rate's |
408 | * history window; anything older isn't really relevant any more. | 408 | * history window; anything older isn't really relevant any more. |
409 | * If we have filled up the sliding window, drop the oldest attempt; | 409 | * If we have filled up the sliding window, drop the oldest attempt; |
410 | * if the oldest attempt (highest bit in bitmap) shows "success", | 410 | * if the oldest attempt (highest bit in bitmap) shows "success", |
411 | * subtract "1" from the success counter (this is the main reason | 411 | * subtract "1" from the success counter (this is the main reason |
412 | * we keep these bitmaps!). | 412 | * we keep these bitmaps!). |
413 | */ | 413 | */ |
414 | while (retries > 0) { | 414 | while (retries > 0) { |
415 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | 415 | if (window->counter >= IWL_RATE_MAX_WINDOW) { |
416 | 416 | ||
417 | /* remove earliest */ | 417 | /* remove earliest */ |
418 | window->counter = IWL_RATE_MAX_WINDOW - 1; | 418 | window->counter = IWL_RATE_MAX_WINDOW - 1; |
419 | 419 | ||
420 | if (window->data & mask) { | 420 | if (window->data & mask) { |
421 | window->data &= ~mask; | 421 | window->data &= ~mask; |
422 | window->success_counter--; | 422 | window->success_counter--; |
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | /* Increment frames-attempted counter */ | 426 | /* Increment frames-attempted counter */ |
427 | window->counter++; | 427 | window->counter++; |
428 | 428 | ||
429 | /* Shift bitmap by one frame (throw away oldest history), | 429 | /* Shift bitmap by one frame (throw away oldest history), |
430 | * OR in "1", and increment "success" if this | 430 | * OR in "1", and increment "success" if this |
431 | * frame was successful. */ | 431 | * frame was successful. */ |
432 | window->data <<= 1; | 432 | window->data <<= 1; |
433 | if (successes > 0) { | 433 | if (successes > 0) { |
434 | window->success_counter++; | 434 | window->success_counter++; |
435 | window->data |= 0x1; | 435 | window->data |= 0x1; |
436 | successes--; | 436 | successes--; |
437 | } | 437 | } |
438 | 438 | ||
439 | retries--; | 439 | retries--; |
440 | } | 440 | } |
441 | 441 | ||
442 | /* Calculate current success ratio, avoid divide-by-0! */ | 442 | /* Calculate current success ratio, avoid divide-by-0! */ |
443 | if (window->counter > 0) | 443 | if (window->counter > 0) |
444 | window->success_ratio = 128 * (100 * window->success_counter) | 444 | window->success_ratio = 128 * (100 * window->success_counter) |
445 | / window->counter; | 445 | / window->counter; |
446 | else | 446 | else |
447 | window->success_ratio = IWL_INVALID_VALUE; | 447 | window->success_ratio = IWL_INVALID_VALUE; |
448 | 448 | ||
449 | fail_count = window->counter - window->success_counter; | 449 | fail_count = window->counter - window->success_counter; |
450 | 450 | ||
451 | /* Calculate average throughput, if we have enough history. */ | 451 | /* Calculate average throughput, if we have enough history. */ |
452 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || | 452 | if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || |
453 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) | 453 | (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) |
454 | window->average_tpt = (window->success_ratio * tpt + 64) / 128; | 454 | window->average_tpt = (window->success_ratio * tpt + 64) / 128; |
455 | else | 455 | else |
456 | window->average_tpt = IWL_INVALID_VALUE; | 456 | window->average_tpt = IWL_INVALID_VALUE; |
457 | 457 | ||
458 | /* Tag this window as having been updated */ | 458 | /* Tag this window as having been updated */ |
459 | window->stamp = jiffies; | 459 | window->stamp = jiffies; |
460 | 460 | ||
461 | return 0; | 461 | return 0; |
462 | } | 462 | } |
463 | 463 | ||
464 | /* | 464 | /* |
465 | * Fill uCode API rate_n_flags field, based on "search" or "active" table. | 465 | * Fill uCode API rate_n_flags field, based on "search" or "active" table. |
466 | */ | 466 | */ |
467 | /* FIXME:RS:remove this function and put the flags statically in the table */ | 467 | /* FIXME:RS:remove this function and put the flags statically in the table */ |
468 | static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, | 468 | static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, |
469 | int index, u8 use_green) | 469 | int index, u8 use_green) |
470 | { | 470 | { |
471 | u32 rate_n_flags = 0; | 471 | u32 rate_n_flags = 0; |
472 | 472 | ||
473 | if (is_legacy(tbl->lq_type)) { | 473 | if (is_legacy(tbl->lq_type)) { |
474 | rate_n_flags = iwl_rates[index].plcp; | 474 | rate_n_flags = iwl_rates[index].plcp; |
475 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) | 475 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) |
476 | rate_n_flags |= RATE_MCS_CCK_MSK; | 476 | rate_n_flags |= RATE_MCS_CCK_MSK; |
477 | 477 | ||
478 | } else if (is_Ht(tbl->lq_type)) { | 478 | } else if (is_Ht(tbl->lq_type)) { |
479 | if (index > IWL_LAST_OFDM_RATE) { | 479 | if (index > IWL_LAST_OFDM_RATE) { |
480 | IWL_ERROR("invalid HT rate index %d\n", index); | 480 | IWL_ERROR("invalid HT rate index %d\n", index); |
481 | index = IWL_LAST_OFDM_RATE; | 481 | index = IWL_LAST_OFDM_RATE; |
482 | } | 482 | } |
483 | rate_n_flags = RATE_MCS_HT_MSK; | 483 | rate_n_flags = RATE_MCS_HT_MSK; |
484 | 484 | ||
485 | if (is_siso(tbl->lq_type)) | 485 | if (is_siso(tbl->lq_type)) |
486 | rate_n_flags |= iwl_rates[index].plcp_siso; | 486 | rate_n_flags |= iwl_rates[index].plcp_siso; |
487 | else if (is_mimo2(tbl->lq_type)) | 487 | else if (is_mimo2(tbl->lq_type)) |
488 | rate_n_flags |= iwl_rates[index].plcp_mimo2; | 488 | rate_n_flags |= iwl_rates[index].plcp_mimo2; |
489 | else | 489 | else |
490 | rate_n_flags |= iwl_rates[index].plcp_mimo3; | 490 | rate_n_flags |= iwl_rates[index].plcp_mimo3; |
491 | } else { | 491 | } else { |
492 | IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type); | 492 | IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type); |
493 | } | 493 | } |
494 | 494 | ||
495 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & | 495 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & |
496 | RATE_MCS_ANT_ABC_MSK); | 496 | RATE_MCS_ANT_ABC_MSK); |
497 | 497 | ||
498 | if (is_Ht(tbl->lq_type)) { | 498 | if (is_Ht(tbl->lq_type)) { |
499 | if (tbl->is_fat) { | 499 | if (tbl->is_fat) { |
500 | if (tbl->is_dup) | 500 | if (tbl->is_dup) |
501 | rate_n_flags |= RATE_MCS_DUP_MSK; | 501 | rate_n_flags |= RATE_MCS_DUP_MSK; |
502 | else | 502 | else |
503 | rate_n_flags |= RATE_MCS_FAT_MSK; | 503 | rate_n_flags |= RATE_MCS_FAT_MSK; |
504 | } | 504 | } |
505 | if (tbl->is_SGI) | 505 | if (tbl->is_SGI) |
506 | rate_n_flags |= RATE_MCS_SGI_MSK; | 506 | rate_n_flags |= RATE_MCS_SGI_MSK; |
507 | 507 | ||
508 | if (use_green) { | 508 | if (use_green) { |
509 | rate_n_flags |= RATE_MCS_GF_MSK; | 509 | rate_n_flags |= RATE_MCS_GF_MSK; |
510 | if (is_siso(tbl->lq_type) && tbl->is_SGI) { | 510 | if (is_siso(tbl->lq_type) && tbl->is_SGI) { |
511 | rate_n_flags &= ~RATE_MCS_SGI_MSK; | 511 | rate_n_flags &= ~RATE_MCS_SGI_MSK; |
512 | IWL_ERROR("GF was set with SGI:SISO\n"); | 512 | IWL_ERROR("GF was set with SGI:SISO\n"); |
513 | } | 513 | } |
514 | } | 514 | } |
515 | } | 515 | } |
516 | return rate_n_flags; | 516 | return rate_n_flags; |
517 | } | 517 | } |
518 | 518 | ||
519 | /* | 519 | /* |
520 | * Interpret uCode API's rate_n_flags format, | 520 | * Interpret uCode API's rate_n_flags format, |
521 | * fill "search" or "active" tx mode table. | 521 | * fill "search" or "active" tx mode table. |
522 | */ | 522 | */ |
523 | static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | 523 | static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, |
524 | enum ieee80211_band band, | 524 | enum ieee80211_band band, |
525 | struct iwl_scale_tbl_info *tbl, | 525 | struct iwl_scale_tbl_info *tbl, |
526 | int *rate_idx) | 526 | int *rate_idx) |
527 | { | 527 | { |
528 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); | 528 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); |
529 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 529 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
530 | u8 mcs; | 530 | u8 mcs; |
531 | 531 | ||
532 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 532 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
533 | 533 | ||
534 | if (*rate_idx == IWL_RATE_INVALID) { | 534 | if (*rate_idx == IWL_RATE_INVALID) { |
535 | *rate_idx = -1; | 535 | *rate_idx = -1; |
536 | return -EINVAL; | 536 | return -EINVAL; |
537 | } | 537 | } |
538 | tbl->is_SGI = 0; /* default legacy setup */ | 538 | tbl->is_SGI = 0; /* default legacy setup */ |
539 | tbl->is_fat = 0; | 539 | tbl->is_fat = 0; |
540 | tbl->is_dup = 0; | 540 | tbl->is_dup = 0; |
541 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); | 541 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); |
542 | tbl->lq_type = LQ_NONE; | 542 | tbl->lq_type = LQ_NONE; |
543 | 543 | ||
544 | /* legacy rate format */ | 544 | /* legacy rate format */ |
545 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { | 545 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { |
546 | if (num_of_ant == 1) { | 546 | if (num_of_ant == 1) { |
547 | if (band == IEEE80211_BAND_5GHZ) | 547 | if (band == IEEE80211_BAND_5GHZ) |
548 | tbl->lq_type = LQ_A; | 548 | tbl->lq_type = LQ_A; |
549 | else | 549 | else |
550 | tbl->lq_type = LQ_G; | 550 | tbl->lq_type = LQ_G; |
551 | } | 551 | } |
552 | /* HT rate format */ | 552 | /* HT rate format */ |
553 | } else { | 553 | } else { |
554 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 554 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
555 | tbl->is_SGI = 1; | 555 | tbl->is_SGI = 1; |
556 | 556 | ||
557 | if ((rate_n_flags & RATE_MCS_FAT_MSK) || | 557 | if ((rate_n_flags & RATE_MCS_FAT_MSK) || |
558 | (rate_n_flags & RATE_MCS_DUP_MSK)) | 558 | (rate_n_flags & RATE_MCS_DUP_MSK)) |
559 | tbl->is_fat = 1; | 559 | tbl->is_fat = 1; |
560 | 560 | ||
561 | if (rate_n_flags & RATE_MCS_DUP_MSK) | 561 | if (rate_n_flags & RATE_MCS_DUP_MSK) |
562 | tbl->is_dup = 1; | 562 | tbl->is_dup = 1; |
563 | 563 | ||
564 | mcs = rs_extract_rate(rate_n_flags); | 564 | mcs = rs_extract_rate(rate_n_flags); |
565 | 565 | ||
566 | /* SISO */ | 566 | /* SISO */ |
567 | if (mcs <= IWL_RATE_SISO_60M_PLCP) { | 567 | if (mcs <= IWL_RATE_SISO_60M_PLCP) { |
568 | if (num_of_ant == 1) | 568 | if (num_of_ant == 1) |
569 | tbl->lq_type = LQ_SISO; /*else NONE*/ | 569 | tbl->lq_type = LQ_SISO; /*else NONE*/ |
570 | /* MIMO2 */ | 570 | /* MIMO2 */ |
571 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { | 571 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { |
572 | if (num_of_ant == 2) | 572 | if (num_of_ant == 2) |
573 | tbl->lq_type = LQ_MIMO2; | 573 | tbl->lq_type = LQ_MIMO2; |
574 | /* MIMO3 */ | 574 | /* MIMO3 */ |
575 | } else { | 575 | } else { |
576 | if (num_of_ant == 3) | 576 | if (num_of_ant == 3) |
577 | tbl->lq_type = LQ_MIMO3; | 577 | tbl->lq_type = LQ_MIMO3; |
578 | } | 578 | } |
579 | } | 579 | } |
580 | return 0; | 580 | return 0; |
581 | } | 581 | } |
582 | 582 | ||
583 | /* switch to another antenna/antennas and return 1 */ | 583 | /* switch to another antenna/antennas and return 1 */ |
584 | /* if no other valid antenna found, return 0 */ | 584 | /* if no other valid antenna found, return 0 */ |
585 | static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | 585 | static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, |
586 | struct iwl_scale_tbl_info *tbl) | 586 | struct iwl_scale_tbl_info *tbl) |
587 | { | 587 | { |
588 | u8 new_ant_type; | 588 | u8 new_ant_type; |
589 | 589 | ||
590 | if (!tbl->ant_type || tbl->ant_type > ANT_ABC) | 590 | if (!tbl->ant_type || tbl->ant_type > ANT_ABC) |
591 | return 0; | 591 | return 0; |
592 | 592 | ||
593 | if (!rs_is_valid_ant(valid_ant, tbl->ant_type)) | 593 | if (!rs_is_valid_ant(valid_ant, tbl->ant_type)) |
594 | return 0; | 594 | return 0; |
595 | 595 | ||
596 | new_ant_type = ant_toggle_lookup[tbl->ant_type]; | 596 | new_ant_type = ant_toggle_lookup[tbl->ant_type]; |
597 | 597 | ||
598 | while ((new_ant_type != tbl->ant_type) && | 598 | while ((new_ant_type != tbl->ant_type) && |
599 | !rs_is_valid_ant(valid_ant, new_ant_type)) | 599 | !rs_is_valid_ant(valid_ant, new_ant_type)) |
600 | new_ant_type = ant_toggle_lookup[new_ant_type]; | 600 | new_ant_type = ant_toggle_lookup[new_ant_type]; |
601 | 601 | ||
602 | if (new_ant_type == tbl->ant_type) | 602 | if (new_ant_type == tbl->ant_type) |
603 | return 0; | 603 | return 0; |
604 | 604 | ||
605 | tbl->ant_type = new_ant_type; | 605 | tbl->ant_type = new_ant_type; |
606 | *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK; | 606 | *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK; |
607 | *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS; | 607 | *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS; |
608 | return 1; | 608 | return 1; |
609 | } | 609 | } |
610 | 610 | ||
611 | /* FIXME:RS: in 4965 we don't use greenfield at all */ | 611 | /* FIXME:RS: in 4965 we don't use greenfield at all */ |
612 | /* FIXME:RS: don't use greenfield for now in TX */ | 612 | /* FIXME:RS: don't use greenfield for now in TX */ |
613 | #if 0 | 613 | #if 0 |
614 | static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) | 614 | static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) |
615 | { | 615 | { |
616 | return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && | 616 | return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && |
617 | priv->current_ht_config.is_green_field && | 617 | priv->current_ht_config.is_green_field && |
618 | !priv->current_ht_config.non_GF_STA_present; | 618 | !priv->current_ht_config.non_GF_STA_present; |
619 | } | 619 | } |
620 | #endif | 620 | #endif |
621 | static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) | 621 | static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) |
622 | { | 622 | { |
623 | return 0; | 623 | return 0; |
624 | } | 624 | } |
625 | 625 | ||
626 | /** | 626 | /** |
627 | * rs_get_supported_rates - get the available rates | 627 | * rs_get_supported_rates - get the available rates |
628 | * | 628 | * |
629 | * if management frame or broadcast frame only return | 629 | * if management frame or broadcast frame only return |
630 | * basic available rates. | 630 | * basic available rates. |
631 | * | 631 | * |
632 | */ | 632 | */ |
633 | static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | 633 | static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, |
634 | struct ieee80211_hdr *hdr, | 634 | struct ieee80211_hdr *hdr, |
635 | enum iwl_table_type rate_type) | 635 | enum iwl_table_type rate_type) |
636 | { | 636 | { |
637 | if (hdr && is_multicast_ether_addr(hdr->addr1) && | 637 | if (hdr && is_multicast_ether_addr(hdr->addr1) && |
638 | lq_sta->active_rate_basic) | 638 | lq_sta->active_rate_basic) |
639 | return lq_sta->active_rate_basic; | 639 | return lq_sta->active_rate_basic; |
640 | 640 | ||
641 | if (is_legacy(rate_type)) { | 641 | if (is_legacy(rate_type)) { |
642 | return lq_sta->active_legacy_rate; | 642 | return lq_sta->active_legacy_rate; |
643 | } else { | 643 | } else { |
644 | if (is_siso(rate_type)) | 644 | if (is_siso(rate_type)) |
645 | return lq_sta->active_siso_rate; | 645 | return lq_sta->active_siso_rate; |
646 | else if (is_mimo2(rate_type)) | 646 | else if (is_mimo2(rate_type)) |
647 | return lq_sta->active_mimo2_rate; | 647 | return lq_sta->active_mimo2_rate; |
648 | else | 648 | else |
649 | return lq_sta->active_mimo3_rate; | 649 | return lq_sta->active_mimo3_rate; |
650 | } | 650 | } |
651 | } | 651 | } |
652 | 652 | ||
653 | static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, | 653 | static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, |
654 | int rate_type) | 654 | int rate_type) |
655 | { | 655 | { |
656 | u8 high = IWL_RATE_INVALID; | 656 | u8 high = IWL_RATE_INVALID; |
657 | u8 low = IWL_RATE_INVALID; | 657 | u8 low = IWL_RATE_INVALID; |
658 | 658 | ||
659 | /* 802.11A or ht walks to the next literal adjacent rate in | 659 | /* 802.11A or ht walks to the next literal adjacent rate in |
660 | * the rate table */ | 660 | * the rate table */ |
661 | if (is_a_band(rate_type) || !is_legacy(rate_type)) { | 661 | if (is_a_band(rate_type) || !is_legacy(rate_type)) { |
662 | int i; | 662 | int i; |
663 | u32 mask; | 663 | u32 mask; |
664 | 664 | ||
665 | /* Find the previous rate that is in the rate mask */ | 665 | /* Find the previous rate that is in the rate mask */ |
666 | i = index - 1; | 666 | i = index - 1; |
667 | for (mask = (1 << i); i >= 0; i--, mask >>= 1) { | 667 | for (mask = (1 << i); i >= 0; i--, mask >>= 1) { |
668 | if (rate_mask & mask) { | 668 | if (rate_mask & mask) { |
669 | low = i; | 669 | low = i; |
670 | break; | 670 | break; |
671 | } | 671 | } |
672 | } | 672 | } |
673 | 673 | ||
674 | /* Find the next rate that is in the rate mask */ | 674 | /* Find the next rate that is in the rate mask */ |
675 | i = index + 1; | 675 | i = index + 1; |
676 | for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { | 676 | for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { |
677 | if (rate_mask & mask) { | 677 | if (rate_mask & mask) { |
678 | high = i; | 678 | high = i; |
679 | break; | 679 | break; |
680 | } | 680 | } |
681 | } | 681 | } |
682 | 682 | ||
683 | return (high << 8) | low; | 683 | return (high << 8) | low; |
684 | } | 684 | } |
685 | 685 | ||
686 | low = index; | 686 | low = index; |
687 | while (low != IWL_RATE_INVALID) { | 687 | while (low != IWL_RATE_INVALID) { |
688 | low = iwl_rates[low].prev_rs; | 688 | low = iwl_rates[low].prev_rs; |
689 | if (low == IWL_RATE_INVALID) | 689 | if (low == IWL_RATE_INVALID) |
690 | break; | 690 | break; |
691 | if (rate_mask & (1 << low)) | 691 | if (rate_mask & (1 << low)) |
692 | break; | 692 | break; |
693 | IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); | 693 | IWL_DEBUG_RATE("Skipping masked lower rate: %d\n", low); |
694 | } | 694 | } |
695 | 695 | ||
696 | high = index; | 696 | high = index; |
697 | while (high != IWL_RATE_INVALID) { | 697 | while (high != IWL_RATE_INVALID) { |
698 | high = iwl_rates[high].next_rs; | 698 | high = iwl_rates[high].next_rs; |
699 | if (high == IWL_RATE_INVALID) | 699 | if (high == IWL_RATE_INVALID) |
700 | break; | 700 | break; |
701 | if (rate_mask & (1 << high)) | 701 | if (rate_mask & (1 << high)) |
702 | break; | 702 | break; |
703 | IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); | 703 | IWL_DEBUG_RATE("Skipping masked higher rate: %d\n", high); |
704 | } | 704 | } |
705 | 705 | ||
706 | return (high << 8) | low; | 706 | return (high << 8) | low; |
707 | } | 707 | } |
708 | 708 | ||
709 | static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | 709 | static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, |
710 | struct iwl_scale_tbl_info *tbl, | 710 | struct iwl_scale_tbl_info *tbl, |
711 | u8 scale_index, u8 ht_possible) | 711 | u8 scale_index, u8 ht_possible) |
712 | { | 712 | { |
713 | s32 low; | 713 | s32 low; |
714 | u16 rate_mask; | 714 | u16 rate_mask; |
715 | u16 high_low; | 715 | u16 high_low; |
716 | u8 switch_to_legacy = 0; | 716 | u8 switch_to_legacy = 0; |
717 | u8 is_green = lq_sta->is_green; | 717 | u8 is_green = lq_sta->is_green; |
718 | 718 | ||
719 | /* check if we need to switch from HT to legacy rates. | 719 | /* check if we need to switch from HT to legacy rates. |
720 | * assumption is that mandatory rates (1Mbps or 6Mbps) | 720 | * assumption is that mandatory rates (1Mbps or 6Mbps) |
721 | * are always supported (spec demand) */ | 721 | * are always supported (spec demand) */ |
722 | if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { | 722 | if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { |
723 | switch_to_legacy = 1; | 723 | switch_to_legacy = 1; |
724 | scale_index = rs_ht_to_legacy[scale_index]; | 724 | scale_index = rs_ht_to_legacy[scale_index]; |
725 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 725 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
726 | tbl->lq_type = LQ_A; | 726 | tbl->lq_type = LQ_A; |
727 | else | 727 | else |
728 | tbl->lq_type = LQ_G; | 728 | tbl->lq_type = LQ_G; |
729 | 729 | ||
730 | if (num_of_ant(tbl->ant_type) > 1) | 730 | if (num_of_ant(tbl->ant_type) > 1) |
731 | tbl->ant_type = ANT_A;/*FIXME:RS*/ | 731 | tbl->ant_type = ANT_A;/*FIXME:RS*/ |
732 | 732 | ||
733 | tbl->is_fat = 0; | 733 | tbl->is_fat = 0; |
734 | tbl->is_SGI = 0; | 734 | tbl->is_SGI = 0; |
735 | } | 735 | } |
736 | 736 | ||
737 | rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); | 737 | rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); |
738 | 738 | ||
739 | /* Mask with station rate restriction */ | 739 | /* Mask with station rate restriction */ |
740 | if (is_legacy(tbl->lq_type)) { | 740 | if (is_legacy(tbl->lq_type)) { |
741 | /* supp_rates has no CCK bits in A mode */ | 741 | /* supp_rates has no CCK bits in A mode */ |
742 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 742 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
743 | rate_mask = (u16)(rate_mask & | 743 | rate_mask = (u16)(rate_mask & |
744 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); | 744 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); |
745 | else | 745 | else |
746 | rate_mask = (u16)(rate_mask & lq_sta->supp_rates); | 746 | rate_mask = (u16)(rate_mask & lq_sta->supp_rates); |
747 | } | 747 | } |
748 | 748 | ||
749 | /* If we switched from HT to legacy, check current rate */ | 749 | /* If we switched from HT to legacy, check current rate */ |
750 | if (switch_to_legacy && (rate_mask & (1 << scale_index))) { | 750 | if (switch_to_legacy && (rate_mask & (1 << scale_index))) { |
751 | low = scale_index; | 751 | low = scale_index; |
752 | goto out; | 752 | goto out; |
753 | } | 753 | } |
754 | 754 | ||
755 | high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, | 755 | high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, |
756 | tbl->lq_type); | 756 | tbl->lq_type); |
757 | low = high_low & 0xff; | 757 | low = high_low & 0xff; |
758 | 758 | ||
759 | if (low == IWL_RATE_INVALID) | 759 | if (low == IWL_RATE_INVALID) |
760 | low = scale_index; | 760 | low = scale_index; |
761 | 761 | ||
762 | out: | 762 | out: |
763 | return rate_n_flags_from_tbl(tbl, low, is_green); | 763 | return rate_n_flags_from_tbl(tbl, low, is_green); |
764 | } | 764 | } |
765 | 765 | ||
766 | /* | 766 | /* |
767 | * mac80211 sends us Tx status | 767 | * mac80211 sends us Tx status |
768 | */ | 768 | */ |
769 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | 769 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
770 | struct ieee80211_sta *sta, void *priv_sta, | 770 | struct ieee80211_sta *sta, void *priv_sta, |
771 | struct sk_buff *skb) | 771 | struct sk_buff *skb) |
772 | { | 772 | { |
773 | int status; | 773 | int status; |
774 | u8 retries; | 774 | u8 retries; |
775 | int rs_index, index = 0; | 775 | int rs_index, index = 0; |
776 | struct iwl_lq_sta *lq_sta; | 776 | struct iwl_lq_sta *lq_sta; |
777 | struct iwl_link_quality_cmd *table; | 777 | struct iwl_link_quality_cmd *table; |
778 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 778 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
779 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 779 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
780 | struct ieee80211_hw *hw = priv->hw; | 780 | struct ieee80211_hw *hw = priv->hw; |
781 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 781 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
782 | struct iwl_rate_scale_data *window = NULL; | 782 | struct iwl_rate_scale_data *window = NULL; |
783 | struct iwl_rate_scale_data *search_win = NULL; | 783 | struct iwl_rate_scale_data *search_win = NULL; |
784 | u32 tx_rate; | 784 | u32 tx_rate; |
785 | struct iwl_scale_tbl_info tbl_type; | 785 | struct iwl_scale_tbl_info tbl_type; |
786 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 786 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; |
787 | u8 active_index = 0; | 787 | u8 active_index = 0; |
788 | __le16 fc = hdr->frame_control; | 788 | __le16 fc = hdr->frame_control; |
789 | s32 tpt = 0; | 789 | s32 tpt = 0; |
790 | 790 | ||
791 | IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); | 791 | IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); |
792 | 792 | ||
793 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) | 793 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) |
794 | return; | 794 | return; |
795 | 795 | ||
796 | /* This packet was aggregated but doesn't carry rate scale info */ | 796 | /* This packet was aggregated but doesn't carry rate scale info */ |
797 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 797 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
798 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 798 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
799 | return; | 799 | return; |
800 | 800 | ||
801 | retries = info->status.rates[0].count - 1; | 801 | retries = info->status.rates[0].count - 1; |
802 | 802 | ||
803 | if (retries > 15) | 803 | if (retries > 15) |
804 | retries = 15; | 804 | retries = 15; |
805 | 805 | ||
806 | lq_sta = (struct iwl_lq_sta *)priv_sta; | 806 | lq_sta = (struct iwl_lq_sta *)priv_sta; |
807 | 807 | ||
808 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 808 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
809 | !lq_sta->ibss_sta_added) | 809 | !lq_sta->ibss_sta_added) |
810 | goto out; | 810 | goto out; |
811 | 811 | ||
812 | table = &lq_sta->lq; | 812 | table = &lq_sta->lq; |
813 | active_index = lq_sta->active_tbl; | 813 | active_index = lq_sta->active_tbl; |
814 | 814 | ||
815 | curr_tbl = &(lq_sta->lq_info[active_index]); | 815 | curr_tbl = &(lq_sta->lq_info[active_index]); |
816 | search_tbl = &(lq_sta->lq_info[(1 - active_index)]); | 816 | search_tbl = &(lq_sta->lq_info[(1 - active_index)]); |
817 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | 817 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); |
818 | search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); | 818 | search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); |
819 | 819 | ||
820 | /* | 820 | /* |
821 | * Ignore this Tx frame response if its initial rate doesn't match | 821 | * Ignore this Tx frame response if its initial rate doesn't match |
822 | * that of latest Link Quality command. There may be stragglers | 822 | * that of latest Link Quality command. There may be stragglers |
823 | * from a previous Link Quality command, but we're no longer interested | 823 | * from a previous Link Quality command, but we're no longer interested |
824 | * in those; they're either from the "active" mode while we're trying | 824 | * in those; they're either from the "active" mode while we're trying |
825 | * to check "search" mode, or a prior "search" mode after we've moved | 825 | * to check "search" mode, or a prior "search" mode after we've moved |
826 | * to a new "search" mode (which might become the new "active" mode). | 826 | * to a new "search" mode (which might become the new "active" mode). |
827 | */ | 827 | */ |
828 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 828 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
829 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 829 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
830 | if (priv->band == IEEE80211_BAND_5GHZ) | 830 | if (priv->band == IEEE80211_BAND_5GHZ) |
831 | rs_index -= IWL_FIRST_OFDM_RATE; | 831 | rs_index -= IWL_FIRST_OFDM_RATE; |
832 | 832 | ||
833 | if ((info->status.rates[0].idx < 0) || | 833 | if ((info->status.rates[0].idx < 0) || |
834 | (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || | 834 | (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || |
835 | (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 835 | (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || |
836 | (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || | 836 | (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || |
837 | (tbl_type.ant_type != info->antenna_sel_tx) || | 837 | (tbl_type.ant_type != info->antenna_sel_tx) || |
838 | (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || | 838 | (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || |
839 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 839 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
840 | (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != | 840 | (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != |
841 | hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { | 841 | hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { |
842 | IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); | 842 | IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); |
843 | goto out; | 843 | goto out; |
844 | } | 844 | } |
845 | 845 | ||
846 | /* Update frame history window with "failure" for each Tx retry. */ | 846 | /* Update frame history window with "failure" for each Tx retry. */ |
847 | while (retries) { | 847 | while (retries) { |
848 | /* Look up the rate and other info used for each tx attempt. | 848 | /* Look up the rate and other info used for each tx attempt. |
849 | * Each tx attempt steps one entry deeper in the rate table. */ | 849 | * Each tx attempt steps one entry deeper in the rate table. */ |
850 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 850 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); |
851 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | 851 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, |
852 | &tbl_type, &rs_index); | 852 | &tbl_type, &rs_index); |
853 | 853 | ||
854 | /* If type matches "search" table, | 854 | /* If type matches "search" table, |
855 | * add failure to "search" history */ | 855 | * add failure to "search" history */ |
856 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 856 | if ((tbl_type.lq_type == search_tbl->lq_type) && |
857 | (tbl_type.ant_type == search_tbl->ant_type) && | 857 | (tbl_type.ant_type == search_tbl->ant_type) && |
858 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 858 | (tbl_type.is_SGI == search_tbl->is_SGI)) { |
859 | if (search_tbl->expected_tpt) | 859 | if (search_tbl->expected_tpt) |
860 | tpt = search_tbl->expected_tpt[rs_index]; | 860 | tpt = search_tbl->expected_tpt[rs_index]; |
861 | else | 861 | else |
862 | tpt = 0; | 862 | tpt = 0; |
863 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); | 863 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); |
864 | 864 | ||
865 | /* Else if type matches "current/active" table, | 865 | /* Else if type matches "current/active" table, |
866 | * add failure to "current/active" history */ | 866 | * add failure to "current/active" history */ |
867 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | 867 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && |
868 | (tbl_type.ant_type == curr_tbl->ant_type) && | 868 | (tbl_type.ant_type == curr_tbl->ant_type) && |
869 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | 869 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { |
870 | if (curr_tbl->expected_tpt) | 870 | if (curr_tbl->expected_tpt) |
871 | tpt = curr_tbl->expected_tpt[rs_index]; | 871 | tpt = curr_tbl->expected_tpt[rs_index]; |
872 | else | 872 | else |
873 | tpt = 0; | 873 | tpt = 0; |
874 | rs_collect_tx_data(window, rs_index, tpt, 1, 0); | 874 | rs_collect_tx_data(window, rs_index, tpt, 1, 0); |
875 | } | 875 | } |
876 | 876 | ||
877 | /* If not searching for a new mode, increment failed counter | 877 | /* If not searching for a new mode, increment failed counter |
878 | * ... this helps determine when to start searching again */ | 878 | * ... this helps determine when to start searching again */ |
879 | if (lq_sta->stay_in_tbl) | 879 | if (lq_sta->stay_in_tbl) |
880 | lq_sta->total_failed++; | 880 | lq_sta->total_failed++; |
881 | --retries; | 881 | --retries; |
882 | index++; | 882 | index++; |
883 | 883 | ||
884 | } | 884 | } |
885 | 885 | ||
886 | /* | 886 | /* |
887 | * Find (by rate) the history window to update with final Tx attempt; | 887 | * Find (by rate) the history window to update with final Tx attempt; |
888 | * if Tx was successful first try, use original rate, | 888 | * if Tx was successful first try, use original rate, |
889 | * else look up the rate that was, finally, successful. | 889 | * else look up the rate that was, finally, successful. |
890 | */ | 890 | */ |
891 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 891 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); |
892 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 892 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
893 | 893 | ||
894 | /* Update frame history window with "success" if Tx got ACKed ... */ | 894 | /* Update frame history window with "success" if Tx got ACKed ... */ |
895 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); | 895 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); |
896 | 896 | ||
897 | /* If type matches "search" table, | 897 | /* If type matches "search" table, |
898 | * add final tx status to "search" history */ | 898 | * add final tx status to "search" history */ |
899 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 899 | if ((tbl_type.lq_type == search_tbl->lq_type) && |
900 | (tbl_type.ant_type == search_tbl->ant_type) && | 900 | (tbl_type.ant_type == search_tbl->ant_type) && |
901 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 901 | (tbl_type.is_SGI == search_tbl->is_SGI)) { |
902 | if (search_tbl->expected_tpt) | 902 | if (search_tbl->expected_tpt) |
903 | tpt = search_tbl->expected_tpt[rs_index]; | 903 | tpt = search_tbl->expected_tpt[rs_index]; |
904 | else | 904 | else |
905 | tpt = 0; | 905 | tpt = 0; |
906 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 906 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
907 | rs_collect_tx_data(search_win, rs_index, tpt, | 907 | rs_collect_tx_data(search_win, rs_index, tpt, |
908 | info->status.ampdu_ack_len, | 908 | info->status.ampdu_ack_len, |
909 | info->status.ampdu_ack_map); | 909 | info->status.ampdu_ack_map); |
910 | else | 910 | else |
911 | rs_collect_tx_data(search_win, rs_index, tpt, | 911 | rs_collect_tx_data(search_win, rs_index, tpt, |
912 | 1, status); | 912 | 1, status); |
913 | /* Else if type matches "current/active" table, | 913 | /* Else if type matches "current/active" table, |
914 | * add final tx status to "current/active" history */ | 914 | * add final tx status to "current/active" history */ |
915 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | 915 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && |
916 | (tbl_type.ant_type == curr_tbl->ant_type) && | 916 | (tbl_type.ant_type == curr_tbl->ant_type) && |
917 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | 917 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { |
918 | if (curr_tbl->expected_tpt) | 918 | if (curr_tbl->expected_tpt) |
919 | tpt = curr_tbl->expected_tpt[rs_index]; | 919 | tpt = curr_tbl->expected_tpt[rs_index]; |
920 | else | 920 | else |
921 | tpt = 0; | 921 | tpt = 0; |
922 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 922 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
923 | rs_collect_tx_data(window, rs_index, tpt, | 923 | rs_collect_tx_data(window, rs_index, tpt, |
924 | info->status.ampdu_ack_len, | 924 | info->status.ampdu_ack_len, |
925 | info->status.ampdu_ack_map); | 925 | info->status.ampdu_ack_map); |
926 | else | 926 | else |
927 | rs_collect_tx_data(window, rs_index, tpt, | 927 | rs_collect_tx_data(window, rs_index, tpt, |
928 | 1, status); | 928 | 1, status); |
929 | } | 929 | } |
930 | 930 | ||
931 | /* If not searching for new mode, increment success/failed counter | 931 | /* If not searching for new mode, increment success/failed counter |
932 | * ... these help determine when to start searching again */ | 932 | * ... these help determine when to start searching again */ |
933 | if (lq_sta->stay_in_tbl) { | 933 | if (lq_sta->stay_in_tbl) { |
934 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 934 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
935 | lq_sta->total_success += info->status.ampdu_ack_map; | 935 | lq_sta->total_success += info->status.ampdu_ack_map; |
936 | lq_sta->total_failed += | 936 | lq_sta->total_failed += |
937 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | 937 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); |
938 | } else { | 938 | } else { |
939 | if (status) | 939 | if (status) |
940 | lq_sta->total_success++; | 940 | lq_sta->total_success++; |
941 | else | 941 | else |
942 | lq_sta->total_failed++; | 942 | lq_sta->total_failed++; |
943 | } | 943 | } |
944 | } | 944 | } |
945 | 945 | ||
946 | /* See if there's a better rate or modulation mode to try. */ | 946 | /* See if there's a better rate or modulation mode to try. */ |
947 | rs_rate_scale_perform(priv, hdr, sta, lq_sta); | 947 | rs_rate_scale_perform(priv, hdr, sta, lq_sta); |
948 | out: | 948 | out: |
949 | return; | 949 | return; |
950 | } | 950 | } |
951 | 951 | ||
952 | /* | 952 | /* |
953 | * Begin a period of staying with a selected modulation mode. | 953 | * Begin a period of staying with a selected modulation mode. |
954 | * Set "stay_in_tbl" flag to prevent any mode switches. | 954 | * Set "stay_in_tbl" flag to prevent any mode switches. |
955 | * Set frame tx success limits according to legacy vs. high-throughput, | 955 | * Set frame tx success limits according to legacy vs. high-throughput, |
956 | * and reset overall (spanning all rates) tx success history statistics. | 956 | * and reset overall (spanning all rates) tx success history statistics. |
957 | * These control how long we stay using same modulation mode before | 957 | * These control how long we stay using same modulation mode before |
958 | * searching for a new mode. | 958 | * searching for a new mode. |
959 | */ | 959 | */ |
960 | static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, | 960 | static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, |
961 | struct iwl_lq_sta *lq_sta) | 961 | struct iwl_lq_sta *lq_sta) |
962 | { | 962 | { |
963 | IWL_DEBUG_RATE("we are staying in the same table\n"); | 963 | IWL_DEBUG_RATE("we are staying in the same table\n"); |
964 | lq_sta->stay_in_tbl = 1; /* only place this gets set */ | 964 | lq_sta->stay_in_tbl = 1; /* only place this gets set */ |
965 | if (is_legacy) { | 965 | if (is_legacy) { |
966 | lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT; | 966 | lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT; |
967 | lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT; | 967 | lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT; |
968 | lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT; | 968 | lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT; |
969 | } else { | 969 | } else { |
970 | lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT; | 970 | lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT; |
971 | lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT; | 971 | lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT; |
972 | lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT; | 972 | lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT; |
973 | } | 973 | } |
974 | lq_sta->table_count = 0; | 974 | lq_sta->table_count = 0; |
975 | lq_sta->total_failed = 0; | 975 | lq_sta->total_failed = 0; |
976 | lq_sta->total_success = 0; | 976 | lq_sta->total_success = 0; |
977 | } | 977 | } |
978 | 978 | ||
979 | /* | 979 | /* |
980 | * Find correct throughput table for given mode of modulation | 980 | * Find correct throughput table for given mode of modulation |
981 | */ | 981 | */ |
982 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | 982 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
983 | struct iwl_scale_tbl_info *tbl) | 983 | struct iwl_scale_tbl_info *tbl) |
984 | { | 984 | { |
985 | if (is_legacy(tbl->lq_type)) { | 985 | if (is_legacy(tbl->lq_type)) { |
986 | if (!is_a_band(tbl->lq_type)) | 986 | if (!is_a_band(tbl->lq_type)) |
987 | tbl->expected_tpt = expected_tpt_G; | 987 | tbl->expected_tpt = expected_tpt_G; |
988 | else | 988 | else |
989 | tbl->expected_tpt = expected_tpt_A; | 989 | tbl->expected_tpt = expected_tpt_A; |
990 | } else if (is_siso(tbl->lq_type)) { | 990 | } else if (is_siso(tbl->lq_type)) { |
991 | if (tbl->is_fat && !lq_sta->is_dup) | 991 | if (tbl->is_fat && !lq_sta->is_dup) |
992 | if (tbl->is_SGI) | 992 | if (tbl->is_SGI) |
993 | tbl->expected_tpt = expected_tpt_siso40MHzSGI; | 993 | tbl->expected_tpt = expected_tpt_siso40MHzSGI; |
994 | else | 994 | else |
995 | tbl->expected_tpt = expected_tpt_siso40MHz; | 995 | tbl->expected_tpt = expected_tpt_siso40MHz; |
996 | else if (tbl->is_SGI) | 996 | else if (tbl->is_SGI) |
997 | tbl->expected_tpt = expected_tpt_siso20MHzSGI; | 997 | tbl->expected_tpt = expected_tpt_siso20MHzSGI; |
998 | else | 998 | else |
999 | tbl->expected_tpt = expected_tpt_siso20MHz; | 999 | tbl->expected_tpt = expected_tpt_siso20MHz; |
1000 | 1000 | ||
1001 | } else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */ | 1001 | } else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */ |
1002 | if (tbl->is_fat && !lq_sta->is_dup) | 1002 | if (tbl->is_fat && !lq_sta->is_dup) |
1003 | if (tbl->is_SGI) | 1003 | if (tbl->is_SGI) |
1004 | tbl->expected_tpt = expected_tpt_mimo40MHzSGI; | 1004 | tbl->expected_tpt = expected_tpt_mimo40MHzSGI; |
1005 | else | 1005 | else |
1006 | tbl->expected_tpt = expected_tpt_mimo40MHz; | 1006 | tbl->expected_tpt = expected_tpt_mimo40MHz; |
1007 | else if (tbl->is_SGI) | 1007 | else if (tbl->is_SGI) |
1008 | tbl->expected_tpt = expected_tpt_mimo20MHzSGI; | 1008 | tbl->expected_tpt = expected_tpt_mimo20MHzSGI; |
1009 | else | 1009 | else |
1010 | tbl->expected_tpt = expected_tpt_mimo20MHz; | 1010 | tbl->expected_tpt = expected_tpt_mimo20MHz; |
1011 | } else | 1011 | } else |
1012 | tbl->expected_tpt = expected_tpt_G; | 1012 | tbl->expected_tpt = expected_tpt_G; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | /* | 1015 | /* |
1016 | * Find starting rate for new "search" high-throughput mode of modulation. | 1016 | * Find starting rate for new "search" high-throughput mode of modulation. |
1017 | * Goal is to find lowest expected rate (under perfect conditions) that is | 1017 | * Goal is to find lowest expected rate (under perfect conditions) that is |
1018 | * above the current measured throughput of "active" mode, to give new mode | 1018 | * above the current measured throughput of "active" mode, to give new mode |
1019 | * a fair chance to prove itself without too many challenges. | 1019 | * a fair chance to prove itself without too many challenges. |
1020 | * | 1020 | * |
1021 | * This gets called when transitioning to more aggressive modulation | 1021 | * This gets called when transitioning to more aggressive modulation |
1022 | * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive | 1022 | * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive |
1023 | * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need | 1023 | * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need |
1024 | * to decrease to match "active" throughput. When moving from MIMO to SISO, | 1024 | * to decrease to match "active" throughput. When moving from MIMO to SISO, |
1025 | * bit rate will typically need to increase, but not if performance was bad. | 1025 | * bit rate will typically need to increase, but not if performance was bad. |
1026 | */ | 1026 | */ |
1027 | static s32 rs_get_best_rate(struct iwl_priv *priv, | 1027 | static s32 rs_get_best_rate(struct iwl_priv *priv, |
1028 | struct iwl_lq_sta *lq_sta, | 1028 | struct iwl_lq_sta *lq_sta, |
1029 | struct iwl_scale_tbl_info *tbl, /* "search" */ | 1029 | struct iwl_scale_tbl_info *tbl, /* "search" */ |
1030 | u16 rate_mask, s8 index) | 1030 | u16 rate_mask, s8 index) |
1031 | { | 1031 | { |
1032 | /* "active" values */ | 1032 | /* "active" values */ |
1033 | struct iwl_scale_tbl_info *active_tbl = | 1033 | struct iwl_scale_tbl_info *active_tbl = |
1034 | &(lq_sta->lq_info[lq_sta->active_tbl]); | 1034 | &(lq_sta->lq_info[lq_sta->active_tbl]); |
1035 | s32 active_sr = active_tbl->win[index].success_ratio; | 1035 | s32 active_sr = active_tbl->win[index].success_ratio; |
1036 | s32 active_tpt = active_tbl->expected_tpt[index]; | 1036 | s32 active_tpt = active_tbl->expected_tpt[index]; |
1037 | 1037 | ||
1038 | /* expected "search" throughput */ | 1038 | /* expected "search" throughput */ |
1039 | s32 *tpt_tbl = tbl->expected_tpt; | 1039 | s32 *tpt_tbl = tbl->expected_tpt; |
1040 | 1040 | ||
1041 | s32 new_rate, high, low, start_hi; | 1041 | s32 new_rate, high, low, start_hi; |
1042 | u16 high_low; | 1042 | u16 high_low; |
1043 | s8 rate = index; | 1043 | s8 rate = index; |
1044 | 1044 | ||
1045 | new_rate = high = low = start_hi = IWL_RATE_INVALID; | 1045 | new_rate = high = low = start_hi = IWL_RATE_INVALID; |
1046 | 1046 | ||
1047 | for (; ;) { | 1047 | for (; ;) { |
1048 | high_low = rs_get_adjacent_rate(priv, rate, rate_mask, | 1048 | high_low = rs_get_adjacent_rate(priv, rate, rate_mask, |
1049 | tbl->lq_type); | 1049 | tbl->lq_type); |
1050 | 1050 | ||
1051 | low = high_low & 0xff; | 1051 | low = high_low & 0xff; |
1052 | high = (high_low >> 8) & 0xff; | 1052 | high = (high_low >> 8) & 0xff; |
1053 | 1053 | ||
1054 | /* | 1054 | /* |
1055 | * Lower the "search" bit rate, to give new "search" mode | 1055 | * Lower the "search" bit rate, to give new "search" mode |
1056 | * approximately the same throughput as "active" if: | 1056 | * approximately the same throughput as "active" if: |
1057 | * | 1057 | * |
1058 | * 1) "Active" mode has been working modestly well (but not | 1058 | * 1) "Active" mode has been working modestly well (but not |
1059 | * great), and expected "search" throughput (under perfect | 1059 | * great), and expected "search" throughput (under perfect |
1060 | * conditions) at candidate rate is above the actual | 1060 | * conditions) at candidate rate is above the actual |
1061 | * measured "active" throughput (but less than expected | 1061 | * measured "active" throughput (but less than expected |
1062 | * "active" throughput under perfect conditions). | 1062 | * "active" throughput under perfect conditions). |
1063 | * OR | 1063 | * OR |
1064 | * 2) "Active" mode has been working perfectly or very well | 1064 | * 2) "Active" mode has been working perfectly or very well |
1065 | * and expected "search" throughput (under perfect | 1065 | * and expected "search" throughput (under perfect |
1066 | * conditions) at candidate rate is above expected | 1066 | * conditions) at candidate rate is above expected |
1067 | * "active" throughput (under perfect conditions). | 1067 | * "active" throughput (under perfect conditions). |
1068 | */ | 1068 | */ |
1069 | if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) && | 1069 | if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) && |
1070 | ((active_sr > IWL_RATE_DECREASE_TH) && | 1070 | ((active_sr > IWL_RATE_DECREASE_TH) && |
1071 | (active_sr <= IWL_RATE_HIGH_TH) && | 1071 | (active_sr <= IWL_RATE_HIGH_TH) && |
1072 | (tpt_tbl[rate] <= active_tpt))) || | 1072 | (tpt_tbl[rate] <= active_tpt))) || |
1073 | ((active_sr >= IWL_RATE_SCALE_SWITCH) && | 1073 | ((active_sr >= IWL_RATE_SCALE_SWITCH) && |
1074 | (tpt_tbl[rate] > active_tpt))) { | 1074 | (tpt_tbl[rate] > active_tpt))) { |
1075 | 1075 | ||
1076 | /* (2nd or later pass) | 1076 | /* (2nd or later pass) |
1077 | * If we've already tried to raise the rate, and are | 1077 | * If we've already tried to raise the rate, and are |
1078 | * now trying to lower it, use the higher rate. */ | 1078 | * now trying to lower it, use the higher rate. */ |
1079 | if (start_hi != IWL_RATE_INVALID) { | 1079 | if (start_hi != IWL_RATE_INVALID) { |
1080 | new_rate = start_hi; | 1080 | new_rate = start_hi; |
1081 | break; | 1081 | break; |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | new_rate = rate; | 1084 | new_rate = rate; |
1085 | 1085 | ||
1086 | /* Loop again with lower rate */ | 1086 | /* Loop again with lower rate */ |
1087 | if (low != IWL_RATE_INVALID) | 1087 | if (low != IWL_RATE_INVALID) |
1088 | rate = low; | 1088 | rate = low; |
1089 | 1089 | ||
1090 | /* Lower rate not available, use the original */ | 1090 | /* Lower rate not available, use the original */ |
1091 | else | 1091 | else |
1092 | break; | 1092 | break; |
1093 | 1093 | ||
1094 | /* Else try to raise the "search" rate to match "active" */ | 1094 | /* Else try to raise the "search" rate to match "active" */ |
1095 | } else { | 1095 | } else { |
1096 | /* (2nd or later pass) | 1096 | /* (2nd or later pass) |
1097 | * If we've already tried to lower the rate, and are | 1097 | * If we've already tried to lower the rate, and are |
1098 | * now trying to raise it, use the lower rate. */ | 1098 | * now trying to raise it, use the lower rate. */ |
1099 | if (new_rate != IWL_RATE_INVALID) | 1099 | if (new_rate != IWL_RATE_INVALID) |
1100 | break; | 1100 | break; |
1101 | 1101 | ||
1102 | /* Loop again with higher rate */ | 1102 | /* Loop again with higher rate */ |
1103 | else if (high != IWL_RATE_INVALID) { | 1103 | else if (high != IWL_RATE_INVALID) { |
1104 | start_hi = high; | 1104 | start_hi = high; |
1105 | rate = high; | 1105 | rate = high; |
1106 | 1106 | ||
1107 | /* Higher rate not available, use the original */ | 1107 | /* Higher rate not available, use the original */ |
1108 | } else { | 1108 | } else { |
1109 | new_rate = rate; | 1109 | new_rate = rate; |
1110 | break; | 1110 | break; |
1111 | } | 1111 | } |
1112 | } | 1112 | } |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | return new_rate; | 1115 | return new_rate; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /* | 1118 | /* |
1119 | * Set up search table for MIMO | 1119 | * Set up search table for MIMO |
1120 | */ | 1120 | */ |
1121 | static int rs_switch_to_mimo2(struct iwl_priv *priv, | 1121 | static int rs_switch_to_mimo2(struct iwl_priv *priv, |
1122 | struct iwl_lq_sta *lq_sta, | 1122 | struct iwl_lq_sta *lq_sta, |
1123 | struct ieee80211_conf *conf, | 1123 | struct ieee80211_conf *conf, |
1124 | struct ieee80211_sta *sta, | 1124 | struct ieee80211_sta *sta, |
1125 | struct iwl_scale_tbl_info *tbl, int index) | 1125 | struct iwl_scale_tbl_info *tbl, int index) |
1126 | { | 1126 | { |
1127 | u16 rate_mask; | 1127 | u16 rate_mask; |
1128 | s32 rate; | 1128 | s32 rate; |
1129 | s8 is_green = lq_sta->is_green; | 1129 | s8 is_green = lq_sta->is_green; |
1130 | 1130 | ||
1131 | if (!conf->ht.enabled || !sta->ht_cap.ht_supported) | 1131 | if (!conf->ht.enabled || !sta->ht_cap.ht_supported) |
1132 | return -1; | 1132 | return -1; |
1133 | 1133 | ||
1134 | if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) | 1134 | if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) |
1135 | == WLAN_HT_CAP_SM_PS_STATIC) | 1135 | == WLAN_HT_CAP_SM_PS_STATIC) |
1136 | return -1; | 1136 | return -1; |
1137 | 1137 | ||
1138 | /* Need both Tx chains/antennas to support MIMO */ | 1138 | /* Need both Tx chains/antennas to support MIMO */ |
1139 | if (priv->hw_params.tx_chains_num < 2) | 1139 | if (priv->hw_params.tx_chains_num < 2) |
1140 | return -1; | 1140 | return -1; |
1141 | 1141 | ||
1142 | IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n"); | 1142 | IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n"); |
1143 | 1143 | ||
1144 | tbl->lq_type = LQ_MIMO2; | 1144 | tbl->lq_type = LQ_MIMO2; |
1145 | tbl->is_dup = lq_sta->is_dup; | 1145 | tbl->is_dup = lq_sta->is_dup; |
1146 | tbl->action = 0; | 1146 | tbl->action = 0; |
1147 | rate_mask = lq_sta->active_mimo2_rate; | 1147 | rate_mask = lq_sta->active_mimo2_rate; |
1148 | 1148 | ||
1149 | if (priv->current_ht_config.supported_chan_width | 1149 | if (priv->current_ht_config.supported_chan_width |
1150 | == IWL_CHANNEL_WIDTH_40MHZ) | 1150 | == IWL_CHANNEL_WIDTH_40MHZ) |
1151 | tbl->is_fat = 1; | 1151 | tbl->is_fat = 1; |
1152 | else | 1152 | else |
1153 | tbl->is_fat = 0; | 1153 | tbl->is_fat = 0; |
1154 | 1154 | ||
1155 | /* FIXME: - don't toggle SGI here | 1155 | /* FIXME: - don't toggle SGI here |
1156 | if (tbl->is_fat) { | 1156 | if (tbl->is_fat) { |
1157 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) | 1157 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) |
1158 | tbl->is_SGI = 1; | 1158 | tbl->is_SGI = 1; |
1159 | else | 1159 | else |
1160 | tbl->is_SGI = 0; | 1160 | tbl->is_SGI = 0; |
1161 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) | 1161 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) |
1162 | tbl->is_SGI = 1; | 1162 | tbl->is_SGI = 1; |
1163 | else | 1163 | else |
1164 | tbl->is_SGI = 0; | 1164 | tbl->is_SGI = 0; |
1165 | */ | 1165 | */ |
1166 | 1166 | ||
1167 | rs_set_expected_tpt_table(lq_sta, tbl); | 1167 | rs_set_expected_tpt_table(lq_sta, tbl); |
1168 | 1168 | ||
1169 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); | 1169 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); |
1170 | 1170 | ||
1171 | IWL_DEBUG_RATE("LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); | 1171 | IWL_DEBUG_RATE("LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); |
1172 | 1172 | ||
1173 | if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { | 1173 | if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { |
1174 | IWL_DEBUG_RATE("Can't switch with index %d rate mask %x\n", | 1174 | IWL_DEBUG_RATE("Can't switch with index %d rate mask %x\n", |
1175 | rate, rate_mask); | 1175 | rate, rate_mask); |
1176 | return -1; | 1176 | return -1; |
1177 | } | 1177 | } |
1178 | tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); | 1178 | tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); |
1179 | 1179 | ||
1180 | IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", | 1180 | IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", |
1181 | tbl->current_rate, is_green); | 1181 | tbl->current_rate, is_green); |
1182 | return 0; | 1182 | return 0; |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | /* | 1185 | /* |
1186 | * Set up search table for SISO | 1186 | * Set up search table for SISO |
1187 | */ | 1187 | */ |
1188 | static int rs_switch_to_siso(struct iwl_priv *priv, | 1188 | static int rs_switch_to_siso(struct iwl_priv *priv, |
1189 | struct iwl_lq_sta *lq_sta, | 1189 | struct iwl_lq_sta *lq_sta, |
1190 | struct ieee80211_conf *conf, | 1190 | struct ieee80211_conf *conf, |
1191 | struct ieee80211_sta *sta, | 1191 | struct ieee80211_sta *sta, |
1192 | struct iwl_scale_tbl_info *tbl, int index) | 1192 | struct iwl_scale_tbl_info *tbl, int index) |
1193 | { | 1193 | { |
1194 | u16 rate_mask; | 1194 | u16 rate_mask; |
1195 | u8 is_green = lq_sta->is_green; | 1195 | u8 is_green = lq_sta->is_green; |
1196 | s32 rate; | 1196 | s32 rate; |
1197 | 1197 | ||
1198 | if (!conf->ht.enabled || !sta->ht_cap.ht_supported) | 1198 | if (!conf->ht.enabled || !sta->ht_cap.ht_supported) |
1199 | return -1; | 1199 | return -1; |
1200 | 1200 | ||
1201 | IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); | 1201 | IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); |
1202 | 1202 | ||
1203 | tbl->is_dup = lq_sta->is_dup; | 1203 | tbl->is_dup = lq_sta->is_dup; |
1204 | tbl->lq_type = LQ_SISO; | 1204 | tbl->lq_type = LQ_SISO; |
1205 | tbl->action = 0; | 1205 | tbl->action = 0; |
1206 | rate_mask = lq_sta->active_siso_rate; | 1206 | rate_mask = lq_sta->active_siso_rate; |
1207 | 1207 | ||
1208 | if (priv->current_ht_config.supported_chan_width | 1208 | if (priv->current_ht_config.supported_chan_width |
1209 | == IWL_CHANNEL_WIDTH_40MHZ) | 1209 | == IWL_CHANNEL_WIDTH_40MHZ) |
1210 | tbl->is_fat = 1; | 1210 | tbl->is_fat = 1; |
1211 | else | 1211 | else |
1212 | tbl->is_fat = 0; | 1212 | tbl->is_fat = 0; |
1213 | 1213 | ||
1214 | /* FIXME: - don't toggle SGI here | 1214 | /* FIXME: - don't toggle SGI here |
1215 | if (tbl->is_fat) { | 1215 | if (tbl->is_fat) { |
1216 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) | 1216 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) |
1217 | tbl->is_SGI = 1; | 1217 | tbl->is_SGI = 1; |
1218 | else | 1218 | else |
1219 | tbl->is_SGI = 0; | 1219 | tbl->is_SGI = 0; |
1220 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) | 1220 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) |
1221 | tbl->is_SGI = 1; | 1221 | tbl->is_SGI = 1; |
1222 | else | 1222 | else |
1223 | tbl->is_SGI = 0; | 1223 | tbl->is_SGI = 0; |
1224 | */ | 1224 | */ |
1225 | 1225 | ||
1226 | if (is_green) | 1226 | if (is_green) |
1227 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ | 1227 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ |
1228 | 1228 | ||
1229 | rs_set_expected_tpt_table(lq_sta, tbl); | 1229 | rs_set_expected_tpt_table(lq_sta, tbl); |
1230 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); | 1230 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); |
1231 | 1231 | ||
1232 | IWL_DEBUG_RATE("LQ: get best rate %d mask %X\n", rate, rate_mask); | 1232 | IWL_DEBUG_RATE("LQ: get best rate %d mask %X\n", rate, rate_mask); |
1233 | if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { | 1233 | if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { |
1234 | IWL_DEBUG_RATE("can not switch with index %d rate mask %x\n", | 1234 | IWL_DEBUG_RATE("can not switch with index %d rate mask %x\n", |
1235 | rate, rate_mask); | 1235 | rate, rate_mask); |
1236 | return -1; | 1236 | return -1; |
1237 | } | 1237 | } |
1238 | tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); | 1238 | tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); |
1239 | IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", | 1239 | IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", |
1240 | tbl->current_rate, is_green); | 1240 | tbl->current_rate, is_green); |
1241 | return 0; | 1241 | return 0; |
1242 | } | 1242 | } |
1243 | 1243 | ||
1244 | /* | 1244 | /* |
1245 | * Try to switch to new modulation mode from legacy | 1245 | * Try to switch to new modulation mode from legacy |
1246 | */ | 1246 | */ |
1247 | static int rs_move_legacy_other(struct iwl_priv *priv, | 1247 | static int rs_move_legacy_other(struct iwl_priv *priv, |
1248 | struct iwl_lq_sta *lq_sta, | 1248 | struct iwl_lq_sta *lq_sta, |
1249 | struct ieee80211_conf *conf, | 1249 | struct ieee80211_conf *conf, |
1250 | struct ieee80211_sta *sta, | 1250 | struct ieee80211_sta *sta, |
1251 | int index) | 1251 | int index) |
1252 | { | 1252 | { |
1253 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1253 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1254 | struct iwl_scale_tbl_info *search_tbl = | 1254 | struct iwl_scale_tbl_info *search_tbl = |
1255 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1255 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1256 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1256 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1257 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1257 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1258 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1258 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1259 | u8 start_action = tbl->action; | 1259 | u8 start_action = tbl->action; |
1260 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1260 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1261 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1261 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1262 | int ret = 0; | 1262 | int ret = 0; |
1263 | 1263 | ||
1264 | for (; ;) { | 1264 | for (; ;) { |
1265 | switch (tbl->action) { | 1265 | switch (tbl->action) { |
1266 | case IWL_LEGACY_SWITCH_ANTENNA1: | 1266 | case IWL_LEGACY_SWITCH_ANTENNA1: |
1267 | case IWL_LEGACY_SWITCH_ANTENNA2: | 1267 | case IWL_LEGACY_SWITCH_ANTENNA2: |
1268 | IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n"); | 1268 | IWL_DEBUG_RATE("LQ: Legacy toggle Antenna\n"); |
1269 | 1269 | ||
1270 | lq_sta->action_counter++; | 1270 | lq_sta->action_counter++; |
1271 | 1271 | ||
1272 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && | 1272 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && |
1273 | tx_chains_num <= 1) || | 1273 | tx_chains_num <= 1) || |
1274 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && | 1274 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && |
1275 | tx_chains_num <= 2)) | 1275 | tx_chains_num <= 2)) |
1276 | break; | 1276 | break; |
1277 | 1277 | ||
1278 | /* Don't change antenna if success has been great */ | 1278 | /* Don't change antenna if success has been great */ |
1279 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | 1279 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) |
1280 | break; | 1280 | break; |
1281 | 1281 | ||
1282 | /* Set up search table to try other antenna */ | 1282 | /* Set up search table to try other antenna */ |
1283 | memcpy(search_tbl, tbl, sz); | 1283 | memcpy(search_tbl, tbl, sz); |
1284 | 1284 | ||
1285 | if (rs_toggle_antenna(valid_tx_ant, | 1285 | if (rs_toggle_antenna(valid_tx_ant, |
1286 | &search_tbl->current_rate, search_tbl)) { | 1286 | &search_tbl->current_rate, search_tbl)) { |
1287 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1287 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1288 | goto out; | 1288 | goto out; |
1289 | } | 1289 | } |
1290 | break; | 1290 | break; |
1291 | case IWL_LEGACY_SWITCH_SISO: | 1291 | case IWL_LEGACY_SWITCH_SISO: |
1292 | IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n"); | 1292 | IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n"); |
1293 | 1293 | ||
1294 | /* Set up search table to try SISO */ | 1294 | /* Set up search table to try SISO */ |
1295 | memcpy(search_tbl, tbl, sz); | 1295 | memcpy(search_tbl, tbl, sz); |
1296 | search_tbl->is_SGI = 0; | 1296 | search_tbl->is_SGI = 0; |
1297 | ret = rs_switch_to_siso(priv, lq_sta, conf, sta, | 1297 | ret = rs_switch_to_siso(priv, lq_sta, conf, sta, |
1298 | search_tbl, index); | 1298 | search_tbl, index); |
1299 | if (!ret) { | 1299 | if (!ret) { |
1300 | lq_sta->action_counter = 0; | 1300 | lq_sta->action_counter = 0; |
1301 | goto out; | 1301 | goto out; |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | break; | 1304 | break; |
1305 | case IWL_LEGACY_SWITCH_MIMO2_AB: | 1305 | case IWL_LEGACY_SWITCH_MIMO2_AB: |
1306 | case IWL_LEGACY_SWITCH_MIMO2_AC: | 1306 | case IWL_LEGACY_SWITCH_MIMO2_AC: |
1307 | case IWL_LEGACY_SWITCH_MIMO2_BC: | 1307 | case IWL_LEGACY_SWITCH_MIMO2_BC: |
1308 | IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n"); | 1308 | IWL_DEBUG_RATE("LQ: Legacy switch to MIMO2\n"); |
1309 | 1309 | ||
1310 | /* Set up search table to try MIMO */ | 1310 | /* Set up search table to try MIMO */ |
1311 | memcpy(search_tbl, tbl, sz); | 1311 | memcpy(search_tbl, tbl, sz); |
1312 | search_tbl->is_SGI = 0; | 1312 | search_tbl->is_SGI = 0; |
1313 | 1313 | ||
1314 | if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) | 1314 | if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) |
1315 | search_tbl->ant_type = ANT_AB; | 1315 | search_tbl->ant_type = ANT_AB; |
1316 | else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC) | 1316 | else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC) |
1317 | search_tbl->ant_type = ANT_AC; | 1317 | search_tbl->ant_type = ANT_AC; |
1318 | else | 1318 | else |
1319 | search_tbl->ant_type = ANT_BC; | 1319 | search_tbl->ant_type = ANT_BC; |
1320 | 1320 | ||
1321 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) | 1321 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) |
1322 | break; | 1322 | break; |
1323 | 1323 | ||
1324 | ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, | 1324 | ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, |
1325 | search_tbl, index); | 1325 | search_tbl, index); |
1326 | if (!ret) { | 1326 | if (!ret) { |
1327 | lq_sta->action_counter = 0; | 1327 | lq_sta->action_counter = 0; |
1328 | goto out; | 1328 | goto out; |
1329 | } | 1329 | } |
1330 | break; | 1330 | break; |
1331 | } | 1331 | } |
1332 | tbl->action++; | 1332 | tbl->action++; |
1333 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) | 1333 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) |
1334 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1334 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1335 | 1335 | ||
1336 | if (tbl->action == start_action) | 1336 | if (tbl->action == start_action) |
1337 | break; | 1337 | break; |
1338 | 1338 | ||
1339 | } | 1339 | } |
1340 | search_tbl->lq_type = LQ_NONE; | 1340 | search_tbl->lq_type = LQ_NONE; |
1341 | return 0; | 1341 | return 0; |
1342 | 1342 | ||
1343 | out: | 1343 | out: |
1344 | lq_sta->search_better_tbl = 1; | 1344 | lq_sta->search_better_tbl = 1; |
1345 | tbl->action++; | 1345 | tbl->action++; |
1346 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) | 1346 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) |
1347 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1347 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1348 | return 0; | 1348 | return 0; |
1349 | 1349 | ||
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | /* | 1352 | /* |
1353 | * Try to switch to new modulation mode from SISO | 1353 | * Try to switch to new modulation mode from SISO |
1354 | */ | 1354 | */ |
1355 | static int rs_move_siso_to_other(struct iwl_priv *priv, | 1355 | static int rs_move_siso_to_other(struct iwl_priv *priv, |
1356 | struct iwl_lq_sta *lq_sta, | 1356 | struct iwl_lq_sta *lq_sta, |
1357 | struct ieee80211_conf *conf, | 1357 | struct ieee80211_conf *conf, |
1358 | struct ieee80211_sta *sta, int index) | 1358 | struct ieee80211_sta *sta, int index) |
1359 | { | 1359 | { |
1360 | u8 is_green = lq_sta->is_green; | 1360 | u8 is_green = lq_sta->is_green; |
1361 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1361 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1362 | struct iwl_scale_tbl_info *search_tbl = | 1362 | struct iwl_scale_tbl_info *search_tbl = |
1363 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1363 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1364 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1364 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1365 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1365 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1366 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1366 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1367 | u8 start_action = tbl->action; | 1367 | u8 start_action = tbl->action; |
1368 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1368 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1369 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1369 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1370 | int ret; | 1370 | int ret; |
1371 | 1371 | ||
1372 | for (;;) { | 1372 | for (;;) { |
1373 | lq_sta->action_counter++; | 1373 | lq_sta->action_counter++; |
1374 | switch (tbl->action) { | 1374 | switch (tbl->action) { |
1375 | case IWL_SISO_SWITCH_ANTENNA1: | 1375 | case IWL_SISO_SWITCH_ANTENNA1: |
1376 | case IWL_SISO_SWITCH_ANTENNA2: | 1376 | case IWL_SISO_SWITCH_ANTENNA2: |
1377 | IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n"); | 1377 | IWL_DEBUG_RATE("LQ: SISO toggle Antenna\n"); |
1378 | 1378 | ||
1379 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && | 1379 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && |
1380 | tx_chains_num <= 1) || | 1380 | tx_chains_num <= 1) || |
1381 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && | 1381 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && |
1382 | tx_chains_num <= 2)) | 1382 | tx_chains_num <= 2)) |
1383 | break; | 1383 | break; |
1384 | 1384 | ||
1385 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | 1385 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) |
1386 | break; | 1386 | break; |
1387 | 1387 | ||
1388 | memcpy(search_tbl, tbl, sz); | 1388 | memcpy(search_tbl, tbl, sz); |
1389 | if (rs_toggle_antenna(valid_tx_ant, | 1389 | if (rs_toggle_antenna(valid_tx_ant, |
1390 | &search_tbl->current_rate, search_tbl)) | 1390 | &search_tbl->current_rate, search_tbl)) |
1391 | goto out; | 1391 | goto out; |
1392 | break; | 1392 | break; |
1393 | case IWL_SISO_SWITCH_MIMO2_AB: | 1393 | case IWL_SISO_SWITCH_MIMO2_AB: |
1394 | case IWL_SISO_SWITCH_MIMO2_AC: | 1394 | case IWL_SISO_SWITCH_MIMO2_AC: |
1395 | case IWL_SISO_SWITCH_MIMO2_BC: | 1395 | case IWL_SISO_SWITCH_MIMO2_BC: |
1396 | IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n"); | 1396 | IWL_DEBUG_RATE("LQ: SISO switch to MIMO2\n"); |
1397 | memcpy(search_tbl, tbl, sz); | 1397 | memcpy(search_tbl, tbl, sz); |
1398 | search_tbl->is_SGI = 0; | 1398 | search_tbl->is_SGI = 0; |
1399 | 1399 | ||
1400 | if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) | 1400 | if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) |
1401 | search_tbl->ant_type = ANT_AB; | 1401 | search_tbl->ant_type = ANT_AB; |
1402 | else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC) | 1402 | else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC) |
1403 | search_tbl->ant_type = ANT_AC; | 1403 | search_tbl->ant_type = ANT_AC; |
1404 | else | 1404 | else |
1405 | search_tbl->ant_type = ANT_BC; | 1405 | search_tbl->ant_type = ANT_BC; |
1406 | 1406 | ||
1407 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) | 1407 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) |
1408 | break; | 1408 | break; |
1409 | 1409 | ||
1410 | ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, | 1410 | ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, |
1411 | search_tbl, index); | 1411 | search_tbl, index); |
1412 | if (!ret) | 1412 | if (!ret) |
1413 | goto out; | 1413 | goto out; |
1414 | break; | 1414 | break; |
1415 | case IWL_SISO_SWITCH_GI: | 1415 | case IWL_SISO_SWITCH_GI: |
1416 | if (!tbl->is_fat && | 1416 | if (!tbl->is_fat && |
1417 | !(priv->current_ht_config.sgf & | 1417 | !(priv->current_ht_config.sgf & |
1418 | HT_SHORT_GI_20MHZ)) | 1418 | HT_SHORT_GI_20MHZ)) |
1419 | break; | 1419 | break; |
1420 | if (tbl->is_fat && | 1420 | if (tbl->is_fat && |
1421 | !(priv->current_ht_config.sgf & | 1421 | !(priv->current_ht_config.sgf & |
1422 | HT_SHORT_GI_40MHZ)) | 1422 | HT_SHORT_GI_40MHZ)) |
1423 | break; | 1423 | break; |
1424 | 1424 | ||
1425 | IWL_DEBUG_RATE("LQ: SISO toggle SGI/NGI\n"); | 1425 | IWL_DEBUG_RATE("LQ: SISO toggle SGI/NGI\n"); |
1426 | 1426 | ||
1427 | memcpy(search_tbl, tbl, sz); | 1427 | memcpy(search_tbl, tbl, sz); |
1428 | if (is_green) { | 1428 | if (is_green) { |
1429 | if (!tbl->is_SGI) | 1429 | if (!tbl->is_SGI) |
1430 | break; | 1430 | break; |
1431 | else | 1431 | else |
1432 | IWL_ERROR("SGI was set in GF+SISO\n"); | 1432 | IWL_ERROR("SGI was set in GF+SISO\n"); |
1433 | } | 1433 | } |
1434 | search_tbl->is_SGI = !tbl->is_SGI; | 1434 | search_tbl->is_SGI = !tbl->is_SGI; |
1435 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1435 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1436 | if (tbl->is_SGI) { | 1436 | if (tbl->is_SGI) { |
1437 | s32 tpt = lq_sta->last_tpt / 100; | 1437 | s32 tpt = lq_sta->last_tpt / 100; |
1438 | if (tpt >= search_tbl->expected_tpt[index]) | 1438 | if (tpt >= search_tbl->expected_tpt[index]) |
1439 | break; | 1439 | break; |
1440 | } | 1440 | } |
1441 | search_tbl->current_rate = rate_n_flags_from_tbl( | 1441 | search_tbl->current_rate = rate_n_flags_from_tbl( |
1442 | search_tbl, index, is_green); | 1442 | search_tbl, index, is_green); |
1443 | goto out; | 1443 | goto out; |
1444 | } | 1444 | } |
1445 | tbl->action++; | 1445 | tbl->action++; |
1446 | if (tbl->action > IWL_SISO_SWITCH_GI) | 1446 | if (tbl->action > IWL_SISO_SWITCH_GI) |
1447 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1447 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1448 | 1448 | ||
1449 | if (tbl->action == start_action) | 1449 | if (tbl->action == start_action) |
1450 | break; | 1450 | break; |
1451 | } | 1451 | } |
1452 | search_tbl->lq_type = LQ_NONE; | 1452 | search_tbl->lq_type = LQ_NONE; |
1453 | return 0; | 1453 | return 0; |
1454 | 1454 | ||
1455 | out: | 1455 | out: |
1456 | lq_sta->search_better_tbl = 1; | 1456 | lq_sta->search_better_tbl = 1; |
1457 | tbl->action++; | 1457 | tbl->action++; |
1458 | if (tbl->action > IWL_SISO_SWITCH_GI) | 1458 | if (tbl->action > IWL_SISO_SWITCH_GI) |
1459 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1459 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1460 | return 0; | 1460 | return 0; |
1461 | } | 1461 | } |
1462 | 1462 | ||
1463 | /* | 1463 | /* |
1464 | * Try to switch to new modulation mode from MIMO | 1464 | * Try to switch to new modulation mode from MIMO |
1465 | */ | 1465 | */ |
1466 | static int rs_move_mimo_to_other(struct iwl_priv *priv, | 1466 | static int rs_move_mimo_to_other(struct iwl_priv *priv, |
1467 | struct iwl_lq_sta *lq_sta, | 1467 | struct iwl_lq_sta *lq_sta, |
1468 | struct ieee80211_conf *conf, | 1468 | struct ieee80211_conf *conf, |
1469 | struct ieee80211_sta *sta, int index) | 1469 | struct ieee80211_sta *sta, int index) |
1470 | { | 1470 | { |
1471 | s8 is_green = lq_sta->is_green; | 1471 | s8 is_green = lq_sta->is_green; |
1472 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1472 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1473 | struct iwl_scale_tbl_info *search_tbl = | 1473 | struct iwl_scale_tbl_info *search_tbl = |
1474 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1474 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1475 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1475 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1476 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1476 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1477 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1477 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1478 | u8 start_action = tbl->action; | 1478 | u8 start_action = tbl->action; |
1479 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1479 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1480 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1480 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1481 | int ret; | 1481 | int ret; |
1482 | 1482 | ||
1483 | for (;;) { | 1483 | for (;;) { |
1484 | lq_sta->action_counter++; | 1484 | lq_sta->action_counter++; |
1485 | switch (tbl->action) { | 1485 | switch (tbl->action) { |
1486 | case IWL_MIMO2_SWITCH_ANTENNA1: | 1486 | case IWL_MIMO2_SWITCH_ANTENNA1: |
1487 | case IWL_MIMO2_SWITCH_ANTENNA2: | 1487 | case IWL_MIMO2_SWITCH_ANTENNA2: |
1488 | IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n"); | 1488 | IWL_DEBUG_RATE("LQ: MIMO toggle Antennas\n"); |
1489 | 1489 | ||
1490 | if (tx_chains_num <= 2) | 1490 | if (tx_chains_num <= 2) |
1491 | break; | 1491 | break; |
1492 | 1492 | ||
1493 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | 1493 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) |
1494 | break; | 1494 | break; |
1495 | 1495 | ||
1496 | memcpy(search_tbl, tbl, sz); | 1496 | memcpy(search_tbl, tbl, sz); |
1497 | if (rs_toggle_antenna(valid_tx_ant, | 1497 | if (rs_toggle_antenna(valid_tx_ant, |
1498 | &search_tbl->current_rate, search_tbl)) | 1498 | &search_tbl->current_rate, search_tbl)) |
1499 | goto out; | 1499 | goto out; |
1500 | break; | 1500 | break; |
1501 | case IWL_MIMO2_SWITCH_SISO_A: | 1501 | case IWL_MIMO2_SWITCH_SISO_A: |
1502 | case IWL_MIMO2_SWITCH_SISO_B: | 1502 | case IWL_MIMO2_SWITCH_SISO_B: |
1503 | case IWL_MIMO2_SWITCH_SISO_C: | 1503 | case IWL_MIMO2_SWITCH_SISO_C: |
1504 | IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n"); | 1504 | IWL_DEBUG_RATE("LQ: MIMO2 switch to SISO\n"); |
1505 | 1505 | ||
1506 | /* Set up new search table for SISO */ | 1506 | /* Set up new search table for SISO */ |
1507 | memcpy(search_tbl, tbl, sz); | 1507 | memcpy(search_tbl, tbl, sz); |
1508 | 1508 | ||
1509 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) | 1509 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) |
1510 | search_tbl->ant_type = ANT_A; | 1510 | search_tbl->ant_type = ANT_A; |
1511 | else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) | 1511 | else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) |
1512 | search_tbl->ant_type = ANT_B; | 1512 | search_tbl->ant_type = ANT_B; |
1513 | else | 1513 | else |
1514 | search_tbl->ant_type = ANT_C; | 1514 | search_tbl->ant_type = ANT_C; |
1515 | 1515 | ||
1516 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) | 1516 | if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) |
1517 | break; | 1517 | break; |
1518 | 1518 | ||
1519 | ret = rs_switch_to_siso(priv, lq_sta, conf, sta, | 1519 | ret = rs_switch_to_siso(priv, lq_sta, conf, sta, |
1520 | search_tbl, index); | 1520 | search_tbl, index); |
1521 | if (!ret) | 1521 | if (!ret) |
1522 | goto out; | 1522 | goto out; |
1523 | 1523 | ||
1524 | break; | 1524 | break; |
1525 | 1525 | ||
1526 | case IWL_MIMO2_SWITCH_GI: | 1526 | case IWL_MIMO2_SWITCH_GI: |
1527 | if (!tbl->is_fat && | 1527 | if (!tbl->is_fat && |
1528 | !(priv->current_ht_config.sgf & | 1528 | !(priv->current_ht_config.sgf & |
1529 | HT_SHORT_GI_20MHZ)) | 1529 | HT_SHORT_GI_20MHZ)) |
1530 | break; | 1530 | break; |
1531 | if (tbl->is_fat && | 1531 | if (tbl->is_fat && |
1532 | !(priv->current_ht_config.sgf & | 1532 | !(priv->current_ht_config.sgf & |
1533 | HT_SHORT_GI_40MHZ)) | 1533 | HT_SHORT_GI_40MHZ)) |
1534 | break; | 1534 | break; |
1535 | 1535 | ||
1536 | IWL_DEBUG_RATE("LQ: MIMO toggle SGI/NGI\n"); | 1536 | IWL_DEBUG_RATE("LQ: MIMO toggle SGI/NGI\n"); |
1537 | 1537 | ||
1538 | /* Set up new search table for MIMO */ | 1538 | /* Set up new search table for MIMO */ |
1539 | memcpy(search_tbl, tbl, sz); | 1539 | memcpy(search_tbl, tbl, sz); |
1540 | search_tbl->is_SGI = !tbl->is_SGI; | 1540 | search_tbl->is_SGI = !tbl->is_SGI; |
1541 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1541 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1542 | /* | 1542 | /* |
1543 | * If active table already uses the fastest possible | 1543 | * If active table already uses the fastest possible |
1544 | * modulation (dual stream with short guard interval), | 1544 | * modulation (dual stream with short guard interval), |
1545 | * and it's working well, there's no need to look | 1545 | * and it's working well, there's no need to look |
1546 | * for a better type of modulation! | 1546 | * for a better type of modulation! |
1547 | */ | 1547 | */ |
1548 | if (tbl->is_SGI) { | 1548 | if (tbl->is_SGI) { |
1549 | s32 tpt = lq_sta->last_tpt / 100; | 1549 | s32 tpt = lq_sta->last_tpt / 100; |
1550 | if (tpt >= search_tbl->expected_tpt[index]) | 1550 | if (tpt >= search_tbl->expected_tpt[index]) |
1551 | break; | 1551 | break; |
1552 | } | 1552 | } |
1553 | search_tbl->current_rate = rate_n_flags_from_tbl( | 1553 | search_tbl->current_rate = rate_n_flags_from_tbl( |
1554 | search_tbl, index, is_green); | 1554 | search_tbl, index, is_green); |
1555 | goto out; | 1555 | goto out; |
1556 | 1556 | ||
1557 | } | 1557 | } |
1558 | tbl->action++; | 1558 | tbl->action++; |
1559 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | 1559 | if (tbl->action > IWL_MIMO2_SWITCH_GI) |
1560 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | 1560 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; |
1561 | 1561 | ||
1562 | if (tbl->action == start_action) | 1562 | if (tbl->action == start_action) |
1563 | break; | 1563 | break; |
1564 | } | 1564 | } |
1565 | search_tbl->lq_type = LQ_NONE; | 1565 | search_tbl->lq_type = LQ_NONE; |
1566 | return 0; | 1566 | return 0; |
1567 | out: | 1567 | out: |
1568 | lq_sta->search_better_tbl = 1; | 1568 | lq_sta->search_better_tbl = 1; |
1569 | tbl->action++; | 1569 | tbl->action++; |
1570 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | 1570 | if (tbl->action > IWL_MIMO2_SWITCH_GI) |
1571 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | 1571 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; |
1572 | return 0; | 1572 | return 0; |
1573 | 1573 | ||
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | /* | 1576 | /* |
1577 | * Check whether we should continue using same modulation mode, or | 1577 | * Check whether we should continue using same modulation mode, or |
1578 | * begin search for a new mode, based on: | 1578 | * begin search for a new mode, based on: |
1579 | * 1) # tx successes or failures while using this mode | 1579 | * 1) # tx successes or failures while using this mode |
1580 | * 2) # times calling this function | 1580 | * 2) # times calling this function |
1581 | * 3) elapsed time in this mode (not used, for now) | 1581 | * 3) elapsed time in this mode (not used, for now) |
1582 | */ | 1582 | */ |
1583 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) | 1583 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) |
1584 | { | 1584 | { |
1585 | struct iwl_scale_tbl_info *tbl; | 1585 | struct iwl_scale_tbl_info *tbl; |
1586 | int i; | 1586 | int i; |
1587 | int active_tbl; | 1587 | int active_tbl; |
1588 | int flush_interval_passed = 0; | 1588 | int flush_interval_passed = 0; |
1589 | struct iwl_priv *priv; | 1589 | struct iwl_priv *priv; |
1590 | 1590 | ||
1591 | priv = lq_sta->drv; | 1591 | priv = lq_sta->drv; |
1592 | active_tbl = lq_sta->active_tbl; | 1592 | active_tbl = lq_sta->active_tbl; |
1593 | 1593 | ||
1594 | tbl = &(lq_sta->lq_info[active_tbl]); | 1594 | tbl = &(lq_sta->lq_info[active_tbl]); |
1595 | 1595 | ||
1596 | /* If we've been disallowing search, see if we should now allow it */ | 1596 | /* If we've been disallowing search, see if we should now allow it */ |
1597 | if (lq_sta->stay_in_tbl) { | 1597 | if (lq_sta->stay_in_tbl) { |
1598 | 1598 | ||
1599 | /* Elapsed time using current modulation mode */ | 1599 | /* Elapsed time using current modulation mode */ |
1600 | if (lq_sta->flush_timer) | 1600 | if (lq_sta->flush_timer) |
1601 | flush_interval_passed = | 1601 | flush_interval_passed = |
1602 | time_after(jiffies, | 1602 | time_after(jiffies, |
1603 | (unsigned long)(lq_sta->flush_timer + | 1603 | (unsigned long)(lq_sta->flush_timer + |
1604 | IWL_RATE_SCALE_FLUSH_INTVL)); | 1604 | IWL_RATE_SCALE_FLUSH_INTVL)); |
1605 | 1605 | ||
1606 | /* | 1606 | /* |
1607 | * Check if we should allow search for new modulation mode. | 1607 | * Check if we should allow search for new modulation mode. |
1608 | * If many frames have failed or succeeded, or we've used | 1608 | * If many frames have failed or succeeded, or we've used |
1609 | * this same modulation for a long time, allow search, and | 1609 | * this same modulation for a long time, allow search, and |
1610 | * reset history stats that keep track of whether we should | 1610 | * reset history stats that keep track of whether we should |
1611 | * allow a new search. Also (below) reset all bitmaps and | 1611 | * allow a new search. Also (below) reset all bitmaps and |
1612 | * stats in active history. | 1612 | * stats in active history. |
1613 | */ | 1613 | */ |
1614 | if ((lq_sta->total_failed > lq_sta->max_failure_limit) || | 1614 | if ((lq_sta->total_failed > lq_sta->max_failure_limit) || |
1615 | (lq_sta->total_success > lq_sta->max_success_limit) || | 1615 | (lq_sta->total_success > lq_sta->max_success_limit) || |
1616 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) | 1616 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) |
1617 | && (flush_interval_passed))) { | 1617 | && (flush_interval_passed))) { |
1618 | IWL_DEBUG_RATE("LQ: stay is expired %d %d %d\n:", | 1618 | IWL_DEBUG_RATE("LQ: stay is expired %d %d %d\n:", |
1619 | lq_sta->total_failed, | 1619 | lq_sta->total_failed, |
1620 | lq_sta->total_success, | 1620 | lq_sta->total_success, |
1621 | flush_interval_passed); | 1621 | flush_interval_passed); |
1622 | 1622 | ||
1623 | /* Allow search for new mode */ | 1623 | /* Allow search for new mode */ |
1624 | lq_sta->stay_in_tbl = 0; /* only place reset */ | 1624 | lq_sta->stay_in_tbl = 0; /* only place reset */ |
1625 | lq_sta->total_failed = 0; | 1625 | lq_sta->total_failed = 0; |
1626 | lq_sta->total_success = 0; | 1626 | lq_sta->total_success = 0; |
1627 | lq_sta->flush_timer = 0; | 1627 | lq_sta->flush_timer = 0; |
1628 | 1628 | ||
1629 | /* | 1629 | /* |
1630 | * Else if we've used this modulation mode enough repetitions | 1630 | * Else if we've used this modulation mode enough repetitions |
1631 | * (regardless of elapsed time or success/failure), reset | 1631 | * (regardless of elapsed time or success/failure), reset |
1632 | * history bitmaps and rate-specific stats for all rates in | 1632 | * history bitmaps and rate-specific stats for all rates in |
1633 | * active table. | 1633 | * active table. |
1634 | */ | 1634 | */ |
1635 | } else { | 1635 | } else { |
1636 | lq_sta->table_count++; | 1636 | lq_sta->table_count++; |
1637 | if (lq_sta->table_count >= | 1637 | if (lq_sta->table_count >= |
1638 | lq_sta->table_count_limit) { | 1638 | lq_sta->table_count_limit) { |
1639 | lq_sta->table_count = 0; | 1639 | lq_sta->table_count = 0; |
1640 | 1640 | ||
1641 | IWL_DEBUG_RATE("LQ: stay in table clear win\n"); | 1641 | IWL_DEBUG_RATE("LQ: stay in table clear win\n"); |
1642 | for (i = 0; i < IWL_RATE_COUNT; i++) | 1642 | for (i = 0; i < IWL_RATE_COUNT; i++) |
1643 | rs_rate_scale_clear_window( | 1643 | rs_rate_scale_clear_window( |
1644 | &(tbl->win[i])); | 1644 | &(tbl->win[i])); |
1645 | } | 1645 | } |
1646 | } | 1646 | } |
1647 | 1647 | ||
1648 | /* If transitioning to allow "search", reset all history | 1648 | /* If transitioning to allow "search", reset all history |
1649 | * bitmaps and stats in active table (this will become the new | 1649 | * bitmaps and stats in active table (this will become the new |
1650 | * "search" table). */ | 1650 | * "search" table). */ |
1651 | if (!lq_sta->stay_in_tbl) { | 1651 | if (!lq_sta->stay_in_tbl) { |
1652 | for (i = 0; i < IWL_RATE_COUNT; i++) | 1652 | for (i = 0; i < IWL_RATE_COUNT; i++) |
1653 | rs_rate_scale_clear_window(&(tbl->win[i])); | 1653 | rs_rate_scale_clear_window(&(tbl->win[i])); |
1654 | } | 1654 | } |
1655 | } | 1655 | } |
1656 | } | 1656 | } |
1657 | 1657 | ||
1658 | /* | 1658 | /* |
1659 | * Do rate scaling and search for new modulation mode. | 1659 | * Do rate scaling and search for new modulation mode. |
1660 | */ | 1660 | */ |
1661 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 1661 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
1662 | struct ieee80211_hdr *hdr, | 1662 | struct ieee80211_hdr *hdr, |
1663 | struct ieee80211_sta *sta, | 1663 | struct ieee80211_sta *sta, |
1664 | struct iwl_lq_sta *lq_sta) | 1664 | struct iwl_lq_sta *lq_sta) |
1665 | { | 1665 | { |
1666 | struct ieee80211_hw *hw = priv->hw; | 1666 | struct ieee80211_hw *hw = priv->hw; |
1667 | struct ieee80211_conf *conf = &hw->conf; | 1667 | struct ieee80211_conf *conf = &hw->conf; |
1668 | int low = IWL_RATE_INVALID; | 1668 | int low = IWL_RATE_INVALID; |
1669 | int high = IWL_RATE_INVALID; | 1669 | int high = IWL_RATE_INVALID; |
1670 | int index; | 1670 | int index; |
1671 | int i; | 1671 | int i; |
1672 | struct iwl_rate_scale_data *window = NULL; | 1672 | struct iwl_rate_scale_data *window = NULL; |
1673 | int current_tpt = IWL_INVALID_VALUE; | 1673 | int current_tpt = IWL_INVALID_VALUE; |
1674 | int low_tpt = IWL_INVALID_VALUE; | 1674 | int low_tpt = IWL_INVALID_VALUE; |
1675 | int high_tpt = IWL_INVALID_VALUE; | 1675 | int high_tpt = IWL_INVALID_VALUE; |
1676 | u32 fail_count; | 1676 | u32 fail_count; |
1677 | s8 scale_action = 0; | 1677 | s8 scale_action = 0; |
1678 | __le16 fc; | 1678 | __le16 fc; |
1679 | u16 rate_mask; | 1679 | u16 rate_mask; |
1680 | u8 update_lq = 0; | 1680 | u8 update_lq = 0; |
1681 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1681 | struct iwl_scale_tbl_info *tbl, *tbl1; |
1682 | u16 rate_scale_index_msk = 0; | 1682 | u16 rate_scale_index_msk = 0; |
1683 | u32 rate; | 1683 | u32 rate; |
1684 | u8 is_green = 0; | 1684 | u8 is_green = 0; |
1685 | u8 active_tbl = 0; | 1685 | u8 active_tbl = 0; |
1686 | u8 done_search = 0; | 1686 | u8 done_search = 0; |
1687 | u16 high_low; | 1687 | u16 high_low; |
1688 | s32 sr; | 1688 | s32 sr; |
1689 | u8 tid = MAX_TID_COUNT; | 1689 | u8 tid = MAX_TID_COUNT; |
1690 | 1690 | ||
1691 | IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); | 1691 | IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); |
1692 | 1692 | ||
1693 | fc = hdr->frame_control; | 1693 | fc = hdr->frame_control; |
1694 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { | 1694 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { |
1695 | /* Send management frames and broadcast/multicast data using | 1695 | /* Send management frames and broadcast/multicast data using |
1696 | * lowest rate. */ | 1696 | * lowest rate. */ |
1697 | /* TODO: this could probably be improved.. */ | 1697 | /* TODO: this could probably be improved.. */ |
1698 | return; | 1698 | return; |
1699 | } | 1699 | } |
1700 | 1700 | ||
1701 | if (!sta || !lq_sta) | 1701 | if (!sta || !lq_sta) |
1702 | return; | 1702 | return; |
1703 | 1703 | ||
1704 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | 1704 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
1705 | 1705 | ||
1706 | tid = rs_tl_add_packet(lq_sta, hdr); | 1706 | tid = rs_tl_add_packet(lq_sta, hdr); |
1707 | 1707 | ||
1708 | /* | 1708 | /* |
1709 | * Select rate-scale / modulation-mode table to work with in | 1709 | * Select rate-scale / modulation-mode table to work with in |
1710 | * the rest of this function: "search" if searching for better | 1710 | * the rest of this function: "search" if searching for better |
1711 | * modulation mode, or "active" if doing rate scaling within a mode. | 1711 | * modulation mode, or "active" if doing rate scaling within a mode. |
1712 | */ | 1712 | */ |
1713 | if (!lq_sta->search_better_tbl) | 1713 | if (!lq_sta->search_better_tbl) |
1714 | active_tbl = lq_sta->active_tbl; | 1714 | active_tbl = lq_sta->active_tbl; |
1715 | else | 1715 | else |
1716 | active_tbl = 1 - lq_sta->active_tbl; | 1716 | active_tbl = 1 - lq_sta->active_tbl; |
1717 | 1717 | ||
1718 | tbl = &(lq_sta->lq_info[active_tbl]); | 1718 | tbl = &(lq_sta->lq_info[active_tbl]); |
1719 | is_green = lq_sta->is_green; | 1719 | is_green = lq_sta->is_green; |
1720 | 1720 | ||
1721 | /* current tx rate */ | 1721 | /* current tx rate */ |
1722 | index = lq_sta->last_txrate_idx; | 1722 | index = lq_sta->last_txrate_idx; |
1723 | 1723 | ||
1724 | IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, | 1724 | IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, |
1725 | tbl->lq_type); | 1725 | tbl->lq_type); |
1726 | 1726 | ||
1727 | /* rates available for this association, and for modulation mode */ | 1727 | /* rates available for this association, and for modulation mode */ |
1728 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); | 1728 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); |
1729 | 1729 | ||
1730 | IWL_DEBUG_RATE("mask 0x%04X \n", rate_mask); | 1730 | IWL_DEBUG_RATE("mask 0x%04X \n", rate_mask); |
1731 | 1731 | ||
1732 | /* mask with station rate restriction */ | 1732 | /* mask with station rate restriction */ |
1733 | if (is_legacy(tbl->lq_type)) { | 1733 | if (is_legacy(tbl->lq_type)) { |
1734 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 1734 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
1735 | /* supp_rates has no CCK bits in A mode */ | 1735 | /* supp_rates has no CCK bits in A mode */ |
1736 | rate_scale_index_msk = (u16) (rate_mask & | 1736 | rate_scale_index_msk = (u16) (rate_mask & |
1737 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); | 1737 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); |
1738 | else | 1738 | else |
1739 | rate_scale_index_msk = (u16) (rate_mask & | 1739 | rate_scale_index_msk = (u16) (rate_mask & |
1740 | lq_sta->supp_rates); | 1740 | lq_sta->supp_rates); |
1741 | 1741 | ||
1742 | } else | 1742 | } else |
1743 | rate_scale_index_msk = rate_mask; | 1743 | rate_scale_index_msk = rate_mask; |
1744 | 1744 | ||
1745 | if (!rate_scale_index_msk) | 1745 | if (!rate_scale_index_msk) |
1746 | rate_scale_index_msk = rate_mask; | 1746 | rate_scale_index_msk = rate_mask; |
1747 | 1747 | ||
1748 | if (!((1 << index) & rate_scale_index_msk)) { | 1748 | if (!((1 << index) & rate_scale_index_msk)) { |
1749 | IWL_ERROR("Current Rate is not valid\n"); | 1749 | IWL_ERROR("Current Rate is not valid\n"); |
1750 | return; | 1750 | return; |
1751 | } | 1751 | } |
1752 | 1752 | ||
1753 | /* Get expected throughput table and history window for current rate */ | 1753 | /* Get expected throughput table and history window for current rate */ |
1754 | if (!tbl->expected_tpt) { | 1754 | if (!tbl->expected_tpt) { |
1755 | IWL_ERROR("tbl->expected_tpt is NULL\n"); | 1755 | IWL_ERROR("tbl->expected_tpt is NULL\n"); |
1756 | return; | 1756 | return; |
1757 | } | 1757 | } |
1758 | 1758 | ||
1759 | window = &(tbl->win[index]); | 1759 | window = &(tbl->win[index]); |
1760 | 1760 | ||
1761 | /* | 1761 | /* |
1762 | * If there is not enough history to calculate actual average | 1762 | * If there is not enough history to calculate actual average |
1763 | * throughput, keep analyzing results of more tx frames, without | 1763 | * throughput, keep analyzing results of more tx frames, without |
1764 | * changing rate or mode (bypass most of the rest of this function). | 1764 | * changing rate or mode (bypass most of the rest of this function). |
1765 | * Set up new rate table in uCode only if old rate is not supported | 1765 | * Set up new rate table in uCode only if old rate is not supported |
1766 | * in current association (use new rate found above). | 1766 | * in current association (use new rate found above). |
1767 | */ | 1767 | */ |
1768 | fail_count = window->counter - window->success_counter; | 1768 | fail_count = window->counter - window->success_counter; |
1769 | if ((fail_count < IWL_RATE_MIN_FAILURE_TH) && | 1769 | if ((fail_count < IWL_RATE_MIN_FAILURE_TH) && |
1770 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { | 1770 | (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { |
1771 | IWL_DEBUG_RATE("LQ: still below TH. succ=%d total=%d " | 1771 | IWL_DEBUG_RATE("LQ: still below TH. succ=%d total=%d " |
1772 | "for index %d\n", | 1772 | "for index %d\n", |
1773 | window->success_counter, window->counter, index); | 1773 | window->success_counter, window->counter, index); |
1774 | 1774 | ||
1775 | /* Can't calculate this yet; not enough history */ | 1775 | /* Can't calculate this yet; not enough history */ |
1776 | window->average_tpt = IWL_INVALID_VALUE; | 1776 | window->average_tpt = IWL_INVALID_VALUE; |
1777 | 1777 | ||
1778 | /* Should we stay with this modulation mode, | 1778 | /* Should we stay with this modulation mode, |
1779 | * or search for a new one? */ | 1779 | * or search for a new one? */ |
1780 | rs_stay_in_table(lq_sta); | 1780 | rs_stay_in_table(lq_sta); |
1781 | 1781 | ||
1782 | goto out; | 1782 | goto out; |
1783 | } | 1783 | } |
1784 | 1784 | ||
1785 | /* Else we have enough samples; calculate estimate of | 1785 | /* Else we have enough samples; calculate estimate of |
1786 | * actual average throughput */ | 1786 | * actual average throughput */ |
1787 | 1787 | ||
1788 | BUG_ON(window->average_tpt != ((window->success_ratio * | 1788 | BUG_ON(window->average_tpt != ((window->success_ratio * |
1789 | tbl->expected_tpt[index] + 64) / 128)); | 1789 | tbl->expected_tpt[index] + 64) / 128)); |
1790 | 1790 | ||
1791 | /* If we are searching for better modulation mode, check success. */ | 1791 | /* If we are searching for better modulation mode, check success. */ |
1792 | if (lq_sta->search_better_tbl) { | 1792 | if (lq_sta->search_better_tbl) { |
1793 | 1793 | ||
1794 | /* If good success, continue using the "search" mode; | 1794 | /* If good success, continue using the "search" mode; |
1795 | * no need to send new link quality command, since we're | 1795 | * no need to send new link quality command, since we're |
1796 | * continuing to use the setup that we've been trying. */ | 1796 | * continuing to use the setup that we've been trying. */ |
1797 | if (window->average_tpt > lq_sta->last_tpt) { | 1797 | if (window->average_tpt > lq_sta->last_tpt) { |
1798 | 1798 | ||
1799 | IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE " | 1799 | IWL_DEBUG_RATE("LQ: SWITCHING TO NEW TABLE " |
1800 | "suc=%d cur-tpt=%d old-tpt=%d\n", | 1800 | "suc=%d cur-tpt=%d old-tpt=%d\n", |
1801 | window->success_ratio, | 1801 | window->success_ratio, |
1802 | window->average_tpt, | 1802 | window->average_tpt, |
1803 | lq_sta->last_tpt); | 1803 | lq_sta->last_tpt); |
1804 | 1804 | ||
1805 | if (!is_legacy(tbl->lq_type)) | 1805 | if (!is_legacy(tbl->lq_type)) |
1806 | lq_sta->enable_counter = 1; | 1806 | lq_sta->enable_counter = 1; |
1807 | 1807 | ||
1808 | /* Swap tables; "search" becomes "active" */ | 1808 | /* Swap tables; "search" becomes "active" */ |
1809 | lq_sta->active_tbl = active_tbl; | 1809 | lq_sta->active_tbl = active_tbl; |
1810 | current_tpt = window->average_tpt; | 1810 | current_tpt = window->average_tpt; |
1811 | 1811 | ||
1812 | /* Else poor success; go back to mode in "active" table */ | 1812 | /* Else poor success; go back to mode in "active" table */ |
1813 | } else { | 1813 | } else { |
1814 | 1814 | ||
1815 | IWL_DEBUG_RATE("LQ: GOING BACK TO THE OLD TABLE " | 1815 | IWL_DEBUG_RATE("LQ: GOING BACK TO THE OLD TABLE " |
1816 | "suc=%d cur-tpt=%d old-tpt=%d\n", | 1816 | "suc=%d cur-tpt=%d old-tpt=%d\n", |
1817 | window->success_ratio, | 1817 | window->success_ratio, |
1818 | window->average_tpt, | 1818 | window->average_tpt, |
1819 | lq_sta->last_tpt); | 1819 | lq_sta->last_tpt); |
1820 | 1820 | ||
1821 | /* Nullify "search" table */ | 1821 | /* Nullify "search" table */ |
1822 | tbl->lq_type = LQ_NONE; | 1822 | tbl->lq_type = LQ_NONE; |
1823 | 1823 | ||
1824 | /* Revert to "active" table */ | 1824 | /* Revert to "active" table */ |
1825 | active_tbl = lq_sta->active_tbl; | 1825 | active_tbl = lq_sta->active_tbl; |
1826 | tbl = &(lq_sta->lq_info[active_tbl]); | 1826 | tbl = &(lq_sta->lq_info[active_tbl]); |
1827 | 1827 | ||
1828 | /* Revert to "active" rate and throughput info */ | 1828 | /* Revert to "active" rate and throughput info */ |
1829 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 1829 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); |
1830 | current_tpt = lq_sta->last_tpt; | 1830 | current_tpt = lq_sta->last_tpt; |
1831 | 1831 | ||
1832 | /* Need to set up a new rate table in uCode */ | 1832 | /* Need to set up a new rate table in uCode */ |
1833 | update_lq = 1; | 1833 | update_lq = 1; |
1834 | } | 1834 | } |
1835 | 1835 | ||
1836 | /* Either way, we've made a decision; modulation mode | 1836 | /* Either way, we've made a decision; modulation mode |
1837 | * search is done, allow rate adjustment next time. */ | 1837 | * search is done, allow rate adjustment next time. */ |
1838 | lq_sta->search_better_tbl = 0; | 1838 | lq_sta->search_better_tbl = 0; |
1839 | done_search = 1; /* Don't switch modes below! */ | 1839 | done_search = 1; /* Don't switch modes below! */ |
1840 | goto lq_update; | 1840 | goto lq_update; |
1841 | } | 1841 | } |
1842 | 1842 | ||
1843 | /* (Else) not in search of better modulation mode, try for better | 1843 | /* (Else) not in search of better modulation mode, try for better |
1844 | * starting rate, while staying in this mode. */ | 1844 | * starting rate, while staying in this mode. */ |
1845 | high_low = rs_get_adjacent_rate(priv, index, rate_scale_index_msk, | 1845 | high_low = rs_get_adjacent_rate(priv, index, rate_scale_index_msk, |
1846 | tbl->lq_type); | 1846 | tbl->lq_type); |
1847 | low = high_low & 0xff; | 1847 | low = high_low & 0xff; |
1848 | high = (high_low >> 8) & 0xff; | 1848 | high = (high_low >> 8) & 0xff; |
1849 | 1849 | ||
1850 | sr = window->success_ratio; | 1850 | sr = window->success_ratio; |
1851 | 1851 | ||
1852 | /* Collect measured throughputs for current and adjacent rates */ | 1852 | /* Collect measured throughputs for current and adjacent rates */ |
1853 | current_tpt = window->average_tpt; | 1853 | current_tpt = window->average_tpt; |
1854 | if (low != IWL_RATE_INVALID) | 1854 | if (low != IWL_RATE_INVALID) |
1855 | low_tpt = tbl->win[low].average_tpt; | 1855 | low_tpt = tbl->win[low].average_tpt; |
1856 | if (high != IWL_RATE_INVALID) | 1856 | if (high != IWL_RATE_INVALID) |
1857 | high_tpt = tbl->win[high].average_tpt; | 1857 | high_tpt = tbl->win[high].average_tpt; |
1858 | 1858 | ||
1859 | scale_action = 0; | 1859 | scale_action = 0; |
1860 | 1860 | ||
1861 | /* Too many failures, decrease rate */ | 1861 | /* Too many failures, decrease rate */ |
1862 | if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { | 1862 | if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { |
1863 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); | 1863 | IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); |
1864 | scale_action = -1; | 1864 | scale_action = -1; |
1865 | 1865 | ||
1866 | /* No throughput measured yet for adjacent rates; try increase. */ | 1866 | /* No throughput measured yet for adjacent rates; try increase. */ |
1867 | } else if ((low_tpt == IWL_INVALID_VALUE) && | 1867 | } else if ((low_tpt == IWL_INVALID_VALUE) && |
1868 | (high_tpt == IWL_INVALID_VALUE)) { | 1868 | (high_tpt == IWL_INVALID_VALUE)) { |
1869 | 1869 | ||
1870 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) | 1870 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) |
1871 | scale_action = 1; | 1871 | scale_action = 1; |
1872 | else if (low != IWL_RATE_INVALID) | 1872 | else if (low != IWL_RATE_INVALID) |
1873 | scale_action = -1; | 1873 | scale_action = -1; |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | /* Both adjacent throughputs are measured, but neither one has better | 1876 | /* Both adjacent throughputs are measured, but neither one has better |
1877 | * throughput; we're using the best rate, don't change it! */ | 1877 | * throughput; we're using the best rate, don't change it! */ |
1878 | else if ((low_tpt != IWL_INVALID_VALUE) && | 1878 | else if ((low_tpt != IWL_INVALID_VALUE) && |
1879 | (high_tpt != IWL_INVALID_VALUE) && | 1879 | (high_tpt != IWL_INVALID_VALUE) && |
1880 | (low_tpt < current_tpt) && | 1880 | (low_tpt < current_tpt) && |
1881 | (high_tpt < current_tpt)) | 1881 | (high_tpt < current_tpt)) |
1882 | scale_action = 0; | 1882 | scale_action = 0; |
1883 | 1883 | ||
1884 | /* At least one adjacent rate's throughput is measured, | 1884 | /* At least one adjacent rate's throughput is measured, |
1885 | * and may have better performance. */ | 1885 | * and may have better performance. */ |
1886 | else { | 1886 | else { |
1887 | /* Higher adjacent rate's throughput is measured */ | 1887 | /* Higher adjacent rate's throughput is measured */ |
1888 | if (high_tpt != IWL_INVALID_VALUE) { | 1888 | if (high_tpt != IWL_INVALID_VALUE) { |
1889 | /* Higher rate has better throughput */ | 1889 | /* Higher rate has better throughput */ |
1890 | if (high_tpt > current_tpt && | 1890 | if (high_tpt > current_tpt && |
1891 | sr >= IWL_RATE_INCREASE_TH) { | 1891 | sr >= IWL_RATE_INCREASE_TH) { |
1892 | scale_action = 1; | 1892 | scale_action = 1; |
1893 | } else { | 1893 | } else { |
1894 | IWL_DEBUG_RATE | 1894 | IWL_DEBUG_RATE |
1895 | ("decrease rate because of high tpt\n"); | 1895 | ("decrease rate because of high tpt\n"); |
1896 | scale_action = -1; | 1896 | scale_action = -1; |
1897 | } | 1897 | } |
1898 | 1898 | ||
1899 | /* Lower adjacent rate's throughput is measured */ | 1899 | /* Lower adjacent rate's throughput is measured */ |
1900 | } else if (low_tpt != IWL_INVALID_VALUE) { | 1900 | } else if (low_tpt != IWL_INVALID_VALUE) { |
1901 | /* Lower rate has better throughput */ | 1901 | /* Lower rate has better throughput */ |
1902 | if (low_tpt > current_tpt) { | 1902 | if (low_tpt > current_tpt) { |
1903 | IWL_DEBUG_RATE | 1903 | IWL_DEBUG_RATE |
1904 | ("decrease rate because of low tpt\n"); | 1904 | ("decrease rate because of low tpt\n"); |
1905 | scale_action = -1; | 1905 | scale_action = -1; |
1906 | } else if (sr >= IWL_RATE_INCREASE_TH) { | 1906 | } else if (sr >= IWL_RATE_INCREASE_TH) { |
1907 | scale_action = 1; | 1907 | scale_action = 1; |
1908 | } | 1908 | } |
1909 | } | 1909 | } |
1910 | } | 1910 | } |
1911 | 1911 | ||
1912 | /* Sanity check; asked for decrease, but success rate or throughput | 1912 | /* Sanity check; asked for decrease, but success rate or throughput |
1913 | * has been good at old rate. Don't change it. */ | 1913 | * has been good at old rate. Don't change it. */ |
1914 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && | 1914 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && |
1915 | ((sr > IWL_RATE_HIGH_TH) || | 1915 | ((sr > IWL_RATE_HIGH_TH) || |
1916 | (current_tpt > (100 * tbl->expected_tpt[low])))) | 1916 | (current_tpt > (100 * tbl->expected_tpt[low])))) |
1917 | scale_action = 0; | 1917 | scale_action = 0; |
1918 | 1918 | ||
1919 | switch (scale_action) { | 1919 | switch (scale_action) { |
1920 | case -1: | 1920 | case -1: |
1921 | /* Decrease starting rate, update uCode's rate table */ | 1921 | /* Decrease starting rate, update uCode's rate table */ |
1922 | if (low != IWL_RATE_INVALID) { | 1922 | if (low != IWL_RATE_INVALID) { |
1923 | update_lq = 1; | 1923 | update_lq = 1; |
1924 | index = low; | 1924 | index = low; |
1925 | } | 1925 | } |
1926 | break; | 1926 | break; |
1927 | case 1: | 1927 | case 1: |
1928 | /* Increase starting rate, update uCode's rate table */ | 1928 | /* Increase starting rate, update uCode's rate table */ |
1929 | if (high != IWL_RATE_INVALID) { | 1929 | if (high != IWL_RATE_INVALID) { |
1930 | update_lq = 1; | 1930 | update_lq = 1; |
1931 | index = high; | 1931 | index = high; |
1932 | } | 1932 | } |
1933 | 1933 | ||
1934 | break; | 1934 | break; |
1935 | case 0: | 1935 | case 0: |
1936 | /* No change */ | 1936 | /* No change */ |
1937 | default: | 1937 | default: |
1938 | break; | 1938 | break; |
1939 | } | 1939 | } |
1940 | 1940 | ||
1941 | IWL_DEBUG_RATE("choose rate scale index %d action %d low %d " | 1941 | IWL_DEBUG_RATE("choose rate scale index %d action %d low %d " |
1942 | "high %d type %d\n", | 1942 | "high %d type %d\n", |
1943 | index, scale_action, low, high, tbl->lq_type); | 1943 | index, scale_action, low, high, tbl->lq_type); |
1944 | 1944 | ||
1945 | lq_update: | 1945 | lq_update: |
1946 | /* Replace uCode's rate table for the destination station. */ | 1946 | /* Replace uCode's rate table for the destination station. */ |
1947 | if (update_lq) { | 1947 | if (update_lq) { |
1948 | rate = rate_n_flags_from_tbl(tbl, index, is_green); | 1948 | rate = rate_n_flags_from_tbl(tbl, index, is_green); |
1949 | rs_fill_link_cmd(priv, lq_sta, rate); | 1949 | rs_fill_link_cmd(priv, lq_sta, rate); |
1950 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1950 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
1951 | } | 1951 | } |
1952 | 1952 | ||
1953 | /* Should we stay with this modulation mode, or search for a new one? */ | 1953 | /* Should we stay with this modulation mode, or search for a new one? */ |
1954 | rs_stay_in_table(lq_sta); | 1954 | rs_stay_in_table(lq_sta); |
1955 | 1955 | ||
1956 | /* | 1956 | /* |
1957 | * Search for new modulation mode if we're: | 1957 | * Search for new modulation mode if we're: |
1958 | * 1) Not changing rates right now | 1958 | * 1) Not changing rates right now |
1959 | * 2) Not just finishing up a search | 1959 | * 2) Not just finishing up a search |
1960 | * 3) Allowing a new search | 1960 | * 3) Allowing a new search |
1961 | */ | 1961 | */ |
1962 | if (!update_lq && !done_search && !lq_sta->stay_in_tbl && window->counter) { | 1962 | if (!update_lq && !done_search && !lq_sta->stay_in_tbl && window->counter) { |
1963 | /* Save current throughput to compare with "search" throughput*/ | 1963 | /* Save current throughput to compare with "search" throughput*/ |
1964 | lq_sta->last_tpt = current_tpt; | 1964 | lq_sta->last_tpt = current_tpt; |
1965 | 1965 | ||
1966 | /* Select a new "search" modulation mode to try. | 1966 | /* Select a new "search" modulation mode to try. |
1967 | * If one is found, set up the new "search" table. */ | 1967 | * If one is found, set up the new "search" table. */ |
1968 | if (is_legacy(tbl->lq_type)) | 1968 | if (is_legacy(tbl->lq_type)) |
1969 | rs_move_legacy_other(priv, lq_sta, conf, sta, index); | 1969 | rs_move_legacy_other(priv, lq_sta, conf, sta, index); |
1970 | else if (is_siso(tbl->lq_type)) | 1970 | else if (is_siso(tbl->lq_type)) |
1971 | rs_move_siso_to_other(priv, lq_sta, conf, sta, index); | 1971 | rs_move_siso_to_other(priv, lq_sta, conf, sta, index); |
1972 | else | 1972 | else |
1973 | rs_move_mimo_to_other(priv, lq_sta, conf, sta, index); | 1973 | rs_move_mimo_to_other(priv, lq_sta, conf, sta, index); |
1974 | 1974 | ||
1975 | /* If new "search" mode was selected, set up in uCode table */ | 1975 | /* If new "search" mode was selected, set up in uCode table */ |
1976 | if (lq_sta->search_better_tbl) { | 1976 | if (lq_sta->search_better_tbl) { |
1977 | /* Access the "search" table, clear its history. */ | 1977 | /* Access the "search" table, clear its history. */ |
1978 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1978 | tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1979 | for (i = 0; i < IWL_RATE_COUNT; i++) | 1979 | for (i = 0; i < IWL_RATE_COUNT; i++) |
1980 | rs_rate_scale_clear_window(&(tbl->win[i])); | 1980 | rs_rate_scale_clear_window(&(tbl->win[i])); |
1981 | 1981 | ||
1982 | /* Use new "search" start rate */ | 1982 | /* Use new "search" start rate */ |
1983 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 1983 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); |
1984 | 1984 | ||
1985 | IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n", | 1985 | IWL_DEBUG_RATE("Switch current mcs: %X index: %d\n", |
1986 | tbl->current_rate, index); | 1986 | tbl->current_rate, index); |
1987 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | 1987 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); |
1988 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1988 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
1989 | } | 1989 | } |
1990 | 1990 | ||
1991 | /* If the "active" (non-search) mode was legacy, | 1991 | /* If the "active" (non-search) mode was legacy, |
1992 | * and we've tried switching antennas, | 1992 | * and we've tried switching antennas, |
1993 | * but we haven't been able to try HT modes (not available), | 1993 | * but we haven't been able to try HT modes (not available), |
1994 | * stay with best antenna legacy modulation for a while | 1994 | * stay with best antenna legacy modulation for a while |
1995 | * before next round of mode comparisons. */ | 1995 | * before next round of mode comparisons. */ |
1996 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1996 | tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1997 | if (is_legacy(tbl1->lq_type) && !conf->ht.enabled && | 1997 | if (is_legacy(tbl1->lq_type) && !conf->ht.enabled && |
1998 | lq_sta->action_counter >= 1) { | 1998 | lq_sta->action_counter >= 1) { |
1999 | lq_sta->action_counter = 0; | 1999 | lq_sta->action_counter = 0; |
2000 | IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); | 2000 | IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); |
2001 | rs_set_stay_in_table(priv, 1, lq_sta); | 2001 | rs_set_stay_in_table(priv, 1, lq_sta); |
2002 | } | 2002 | } |
2003 | 2003 | ||
2004 | /* If we're in an HT mode, and all 3 mode switch actions | 2004 | /* If we're in an HT mode, and all 3 mode switch actions |
2005 | * have been tried and compared, stay in this best modulation | 2005 | * have been tried and compared, stay in this best modulation |
2006 | * mode for a while before next round of mode comparisons. */ | 2006 | * mode for a while before next round of mode comparisons. */ |
2007 | if (lq_sta->enable_counter && | 2007 | if (lq_sta->enable_counter && |
2008 | (lq_sta->action_counter >= IWL_ACTION_LIMIT)) { | 2008 | (lq_sta->action_counter >= IWL_ACTION_LIMIT)) { |
2009 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && | 2009 | if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && |
2010 | (lq_sta->tx_agg_tid_en & (1 << tid)) && | 2010 | (lq_sta->tx_agg_tid_en & (1 << tid)) && |
2011 | (tid != MAX_TID_COUNT)) { | 2011 | (tid != MAX_TID_COUNT)) { |
2012 | IWL_DEBUG_RATE("try to aggregate tid %d\n", tid); | 2012 | IWL_DEBUG_RATE("try to aggregate tid %d\n", tid); |
2013 | rs_tl_turn_on_agg(priv, tid, lq_sta, sta); | 2013 | rs_tl_turn_on_agg(priv, tid, lq_sta, sta); |
2014 | } | 2014 | } |
2015 | lq_sta->action_counter = 0; | 2015 | lq_sta->action_counter = 0; |
2016 | rs_set_stay_in_table(priv, 0, lq_sta); | 2016 | rs_set_stay_in_table(priv, 0, lq_sta); |
2017 | } | 2017 | } |
2018 | 2018 | ||
2019 | /* | 2019 | /* |
2020 | * Else, don't search for a new modulation mode. | 2020 | * Else, don't search for a new modulation mode. |
2021 | * Put new timestamp in stay-in-modulation-mode flush timer if: | 2021 | * Put new timestamp in stay-in-modulation-mode flush timer if: |
2022 | * 1) Not changing rates right now | 2022 | * 1) Not changing rates right now |
2023 | * 2) Not just finishing up a search | 2023 | * 2) Not just finishing up a search |
2024 | * 3) flush timer is empty | 2024 | * 3) flush timer is empty |
2025 | */ | 2025 | */ |
2026 | } else { | 2026 | } else { |
2027 | if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer)) | 2027 | if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer)) |
2028 | lq_sta->flush_timer = jiffies; | 2028 | lq_sta->flush_timer = jiffies; |
2029 | } | 2029 | } |
2030 | 2030 | ||
2031 | out: | 2031 | out: |
2032 | tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); | 2032 | tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); |
2033 | i = index; | 2033 | i = index; |
2034 | lq_sta->last_txrate_idx = i; | 2034 | lq_sta->last_txrate_idx = i; |
2035 | 2035 | ||
2036 | return; | 2036 | return; |
2037 | } | 2037 | } |
2038 | 2038 | ||
2039 | 2039 | ||
2040 | static void rs_initialize_lq(struct iwl_priv *priv, | 2040 | static void rs_initialize_lq(struct iwl_priv *priv, |
2041 | struct ieee80211_conf *conf, | 2041 | struct ieee80211_conf *conf, |
2042 | struct ieee80211_sta *sta, | 2042 | struct ieee80211_sta *sta, |
2043 | struct iwl_lq_sta *lq_sta) | 2043 | struct iwl_lq_sta *lq_sta) |
2044 | { | 2044 | { |
2045 | struct iwl_scale_tbl_info *tbl; | 2045 | struct iwl_scale_tbl_info *tbl; |
2046 | int rate_idx; | 2046 | int rate_idx; |
2047 | int i; | 2047 | int i; |
2048 | u32 rate; | 2048 | u32 rate; |
2049 | u8 use_green = rs_use_green(priv, conf); | 2049 | u8 use_green = rs_use_green(priv, conf); |
2050 | u8 active_tbl = 0; | 2050 | u8 active_tbl = 0; |
2051 | u8 valid_tx_ant; | 2051 | u8 valid_tx_ant; |
2052 | 2052 | ||
2053 | if (!sta || !lq_sta) | 2053 | if (!sta || !lq_sta) |
2054 | goto out; | 2054 | goto out; |
2055 | 2055 | ||
2056 | i = lq_sta->last_txrate_idx; | 2056 | i = lq_sta->last_txrate_idx; |
2057 | 2057 | ||
2058 | if ((lq_sta->lq.sta_id == 0xff) && | 2058 | if ((lq_sta->lq.sta_id == 0xff) && |
2059 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | 2059 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) |
2060 | goto out; | 2060 | goto out; |
2061 | 2061 | ||
2062 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2062 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2063 | 2063 | ||
2064 | if (!lq_sta->search_better_tbl) | 2064 | if (!lq_sta->search_better_tbl) |
2065 | active_tbl = lq_sta->active_tbl; | 2065 | active_tbl = lq_sta->active_tbl; |
2066 | else | 2066 | else |
2067 | active_tbl = 1 - lq_sta->active_tbl; | 2067 | active_tbl = 1 - lq_sta->active_tbl; |
2068 | 2068 | ||
2069 | tbl = &(lq_sta->lq_info[active_tbl]); | 2069 | tbl = &(lq_sta->lq_info[active_tbl]); |
2070 | 2070 | ||
2071 | if ((i < 0) || (i >= IWL_RATE_COUNT)) | 2071 | if ((i < 0) || (i >= IWL_RATE_COUNT)) |
2072 | i = 0; | 2072 | i = 0; |
2073 | 2073 | ||
2074 | /* FIXME:RS: This is also wrong in 4965 */ | 2074 | /* FIXME:RS: This is also wrong in 4965 */ |
2075 | rate = iwl_rates[i].plcp; | 2075 | rate = iwl_rates[i].plcp; |
2076 | rate |= RATE_MCS_ANT_B_MSK; | 2076 | rate |= RATE_MCS_ANT_B_MSK; |
2077 | rate &= ~RATE_MCS_ANT_A_MSK; | 2077 | rate &= ~RATE_MCS_ANT_A_MSK; |
2078 | 2078 | ||
2079 | if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE) | 2079 | if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE) |
2080 | rate |= RATE_MCS_CCK_MSK; | 2080 | rate |= RATE_MCS_CCK_MSK; |
2081 | 2081 | ||
2082 | tbl->ant_type = ANT_B; | 2082 | tbl->ant_type = ANT_B; |
2083 | rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx); | 2083 | rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx); |
2084 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) | 2084 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) |
2085 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); | 2085 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); |
2086 | 2086 | ||
2087 | rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); | 2087 | rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); |
2088 | tbl->current_rate = rate; | 2088 | tbl->current_rate = rate; |
2089 | rs_set_expected_tpt_table(lq_sta, tbl); | 2089 | rs_set_expected_tpt_table(lq_sta, tbl); |
2090 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2090 | rs_fill_link_cmd(NULL, lq_sta, rate); |
2091 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2091 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
2092 | out: | 2092 | out: |
2093 | return; | 2093 | return; |
2094 | } | 2094 | } |
2095 | 2095 | ||
2096 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | 2096 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, |
2097 | struct ieee80211_tx_rate_control *txrc) | 2097 | struct ieee80211_tx_rate_control *txrc) |
2098 | { | 2098 | { |
2099 | 2099 | ||
2100 | int i; | 2100 | int i; |
2101 | struct sk_buff *skb = txrc->skb; | 2101 | struct sk_buff *skb = txrc->skb; |
2102 | struct ieee80211_supported_band *sband = txrc->sband; | 2102 | struct ieee80211_supported_band *sband = txrc->sband; |
2103 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2103 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2104 | struct ieee80211_conf *conf = &priv->hw->conf; | 2104 | struct ieee80211_conf *conf = &priv->hw->conf; |
2105 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2105 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2106 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2106 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2107 | __le16 fc; | 2107 | __le16 fc; |
2108 | struct iwl_lq_sta *lq_sta; | 2108 | struct iwl_lq_sta *lq_sta; |
2109 | 2109 | ||
2110 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); | 2110 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); |
2111 | 2111 | ||
2112 | /* Send management frames and broadcast/multicast data using lowest | 2112 | /* Send management frames and broadcast/multicast data using lowest |
2113 | * rate. */ | 2113 | * rate. */ |
2114 | fc = hdr->frame_control; | 2114 | fc = hdr->frame_control; |
2115 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || | 2115 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || |
2116 | !sta || !priv_sta) { | 2116 | !sta || !priv_sta) { |
2117 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 2117 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
2118 | return; | 2118 | return; |
2119 | } | 2119 | } |
2120 | 2120 | ||
2121 | lq_sta = (struct iwl_lq_sta *)priv_sta; | 2121 | lq_sta = (struct iwl_lq_sta *)priv_sta; |
2122 | i = lq_sta->last_txrate_idx; | 2122 | i = lq_sta->last_txrate_idx; |
2123 | 2123 | ||
2124 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 2124 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
2125 | !lq_sta->ibss_sta_added) { | 2125 | !lq_sta->ibss_sta_added) { |
2126 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | 2126 | u8 sta_id = iwl_find_station(priv, hdr->addr1); |
2127 | 2127 | ||
2128 | if (sta_id == IWL_INVALID_STATION) { | 2128 | if (sta_id == IWL_INVALID_STATION) { |
2129 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", | 2129 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", |
2130 | hdr->addr1); | 2130 | hdr->addr1); |
2131 | sta_id = iwl_add_station_flags(priv, hdr->addr1, | 2131 | sta_id = iwl_add_station_flags(priv, hdr->addr1, |
2132 | 0, CMD_ASYNC, NULL); | 2132 | 0, CMD_ASYNC, NULL); |
2133 | } | 2133 | } |
2134 | if ((sta_id != IWL_INVALID_STATION)) { | 2134 | if ((sta_id != IWL_INVALID_STATION)) { |
2135 | lq_sta->lq.sta_id = sta_id; | 2135 | lq_sta->lq.sta_id = sta_id; |
2136 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | 2136 | lq_sta->lq.rs_table[0].rate_n_flags = 0; |
2137 | lq_sta->ibss_sta_added = 1; | 2137 | lq_sta->ibss_sta_added = 1; |
2138 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2138 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2139 | } | 2139 | } |
2140 | } | 2140 | } |
2141 | 2141 | ||
2142 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | 2142 | if ((i < 0) || (i > IWL_RATE_COUNT)) { |
2143 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 2143 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
2144 | return; | 2144 | return; |
2145 | } | 2145 | } |
2146 | 2146 | ||
2147 | if (sband->band == IEEE80211_BAND_5GHZ) | 2147 | if (sband->band == IEEE80211_BAND_5GHZ) |
2148 | i -= IWL_FIRST_OFDM_RATE; | 2148 | i -= IWL_FIRST_OFDM_RATE; |
2149 | info->control.rates[0].idx = i; | 2149 | info->control.rates[0].idx = i; |
2150 | } | 2150 | } |
2151 | 2151 | ||
2152 | static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | 2152 | static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, |
2153 | gfp_t gfp) | 2153 | gfp_t gfp) |
2154 | { | 2154 | { |
2155 | struct iwl_lq_sta *lq_sta; | 2155 | struct iwl_lq_sta *lq_sta; |
2156 | struct iwl_priv *priv; | 2156 | struct iwl_priv *priv; |
2157 | int i, j; | 2157 | int i, j; |
2158 | 2158 | ||
2159 | priv = (struct iwl_priv *)priv_rate; | 2159 | priv = (struct iwl_priv *)priv_rate; |
2160 | IWL_DEBUG_RATE("create station rate scale window\n"); | 2160 | IWL_DEBUG_RATE("create station rate scale window\n"); |
2161 | 2161 | ||
2162 | lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); | 2162 | lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); |
2163 | 2163 | ||
2164 | if (lq_sta == NULL) | 2164 | if (lq_sta == NULL) |
2165 | return NULL; | 2165 | return NULL; |
2166 | lq_sta->lq.sta_id = 0xff; | 2166 | lq_sta->lq.sta_id = 0xff; |
2167 | 2167 | ||
2168 | 2168 | ||
2169 | for (j = 0; j < LQ_SIZE; j++) | 2169 | for (j = 0; j < LQ_SIZE; j++) |
2170 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2170 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2171 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2171 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2172 | 2172 | ||
2173 | return lq_sta; | 2173 | return lq_sta; |
2174 | } | 2174 | } |
2175 | 2175 | ||
2176 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 2176 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, |
2177 | struct ieee80211_sta *sta, void *priv_sta) | 2177 | struct ieee80211_sta *sta, void *priv_sta) |
2178 | { | 2178 | { |
2179 | int i, j; | 2179 | int i, j; |
2180 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2180 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2181 | struct ieee80211_conf *conf = &priv->hw->conf; | 2181 | struct ieee80211_conf *conf = &priv->hw->conf; |
2182 | struct iwl_lq_sta *lq_sta = priv_sta; | 2182 | struct iwl_lq_sta *lq_sta = priv_sta; |
2183 | 2183 | ||
2184 | lq_sta->flush_timer = 0; | 2184 | lq_sta->flush_timer = 0; |
2185 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2185 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2186 | for (j = 0; j < LQ_SIZE; j++) | 2186 | for (j = 0; j < LQ_SIZE; j++) |
2187 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2187 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2188 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2188 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2189 | 2189 | ||
2190 | IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n"); | 2190 | IWL_DEBUG_RATE("LQ: *** rate scale station global init ***\n"); |
2191 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 2191 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
2192 | * the lowest or the highest rate.. Could consider using RSSI from | 2192 | * the lowest or the highest rate.. Could consider using RSSI from |
2193 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 2193 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
2194 | * after assoc.. */ | 2194 | * after assoc.. */ |
2195 | 2195 | ||
2196 | lq_sta->ibss_sta_added = 0; | 2196 | lq_sta->ibss_sta_added = 0; |
2197 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2197 | if (priv->iw_mode == NL80211_IFTYPE_AP) { |
2198 | u8 sta_id = iwl_find_station(priv, sta->addr); | 2198 | u8 sta_id = iwl_find_station(priv, sta->addr); |
2199 | 2199 | ||
2200 | /* for IBSS the call are from tasklet */ | 2200 | /* for IBSS the call are from tasklet */ |
2201 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); | 2201 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); |
2202 | 2202 | ||
2203 | if (sta_id == IWL_INVALID_STATION) { | 2203 | if (sta_id == IWL_INVALID_STATION) { |
2204 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); | 2204 | IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr); |
2205 | sta_id = iwl_add_station_flags(priv, sta->addr, | 2205 | sta_id = iwl_add_station_flags(priv, sta->addr, |
2206 | 0, CMD_ASYNC, NULL); | 2206 | 0, CMD_ASYNC, NULL); |
2207 | } | 2207 | } |
2208 | if ((sta_id != IWL_INVALID_STATION)) { | 2208 | if ((sta_id != IWL_INVALID_STATION)) { |
2209 | lq_sta->lq.sta_id = sta_id; | 2209 | lq_sta->lq.sta_id = sta_id; |
2210 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | 2210 | lq_sta->lq.rs_table[0].rate_n_flags = 0; |
2211 | } | 2211 | } |
2212 | /* FIXME: this is w/a remove it later */ | 2212 | /* FIXME: this is w/a remove it later */ |
2213 | priv->assoc_station_added = 1; | 2213 | priv->assoc_station_added = 1; |
2214 | } | 2214 | } |
2215 | 2215 | ||
2216 | /* Find highest tx rate supported by hardware and destination station */ | 2216 | /* Find highest tx rate supported by hardware and destination station */ |
2217 | lq_sta->last_txrate_idx = 3; | 2217 | lq_sta->last_txrate_idx = 3; |
2218 | for (i = 0; i < sband->n_bitrates; i++) | 2218 | for (i = 0; i < sband->n_bitrates; i++) |
2219 | if (sta->supp_rates[sband->band] & BIT(i)) | 2219 | if (sta->supp_rates[sband->band] & BIT(i)) |
2220 | lq_sta->last_txrate_idx = i; | 2220 | lq_sta->last_txrate_idx = i; |
2221 | 2221 | ||
2222 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ | 2222 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ |
2223 | if (sband->band == IEEE80211_BAND_5GHZ) | 2223 | if (sband->band == IEEE80211_BAND_5GHZ) |
2224 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2224 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2225 | 2225 | ||
2226 | lq_sta->is_dup = 0; | 2226 | lq_sta->is_dup = 0; |
2227 | lq_sta->is_green = rs_use_green(priv, conf); | 2227 | lq_sta->is_green = rs_use_green(priv, conf); |
2228 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2228 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
2229 | lq_sta->active_rate_basic = priv->active_rate_basic; | 2229 | lq_sta->active_rate_basic = priv->active_rate_basic; |
2230 | lq_sta->band = priv->band; | 2230 | lq_sta->band = priv->band; |
2231 | /* | 2231 | /* |
2232 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2232 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), |
2233 | * supp_rates[] does not; shift to convert format, force 9 MBits off. | 2233 | * supp_rates[] does not; shift to convert format, force 9 MBits off. |
2234 | */ | 2234 | */ |
2235 | lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1; | 2235 | lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1; |
2236 | lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1; | 2236 | lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1; |
2237 | lq_sta->active_siso_rate &= ~((u16)0x2); | 2237 | lq_sta->active_siso_rate &= ~((u16)0x2); |
2238 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | 2238 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; |
2239 | 2239 | ||
2240 | /* Same here */ | 2240 | /* Same here */ |
2241 | lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1; | 2241 | lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1; |
2242 | lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1; | 2242 | lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1; |
2243 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | 2243 | lq_sta->active_mimo2_rate &= ~((u16)0x2); |
2244 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | 2244 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; |
2245 | 2245 | ||
2246 | lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1; | 2246 | lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1; |
2247 | lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1; | 2247 | lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1; |
2248 | lq_sta->active_mimo3_rate &= ~((u16)0x2); | 2248 | lq_sta->active_mimo3_rate &= ~((u16)0x2); |
2249 | lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; | 2249 | lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; |
2250 | 2250 | ||
2251 | IWL_DEBUG_RATE("SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", | 2251 | IWL_DEBUG_RATE("SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", |
2252 | lq_sta->active_siso_rate, | 2252 | lq_sta->active_siso_rate, |
2253 | lq_sta->active_mimo2_rate, | 2253 | lq_sta->active_mimo2_rate, |
2254 | lq_sta->active_mimo3_rate); | 2254 | lq_sta->active_mimo3_rate); |
2255 | 2255 | ||
2256 | /* These values will be overriden later */ | 2256 | /* These values will be overriden later */ |
2257 | lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; | 2257 | lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; |
2258 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2258 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; |
2259 | 2259 | ||
2260 | /* as default allow aggregation for all tids */ | 2260 | /* as default allow aggregation for all tids */ |
2261 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2261 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
2262 | lq_sta->drv = priv; | 2262 | lq_sta->drv = priv; |
2263 | 2263 | ||
2264 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2264 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2265 | } | 2265 | } |
2266 | 2266 | ||
2267 | static void rs_fill_link_cmd(const struct iwl_priv *priv, | 2267 | static void rs_fill_link_cmd(const struct iwl_priv *priv, |
2268 | struct iwl_lq_sta *lq_sta, u32 new_rate) | 2268 | struct iwl_lq_sta *lq_sta, u32 new_rate) |
2269 | { | 2269 | { |
2270 | struct iwl_scale_tbl_info tbl_type; | 2270 | struct iwl_scale_tbl_info tbl_type; |
2271 | int index = 0; | 2271 | int index = 0; |
2272 | int rate_idx; | 2272 | int rate_idx; |
2273 | int repeat_rate = 0; | 2273 | int repeat_rate = 0; |
2274 | u8 ant_toggle_cnt = 0; | 2274 | u8 ant_toggle_cnt = 0; |
2275 | u8 use_ht_possible = 1; | 2275 | u8 use_ht_possible = 1; |
2276 | u8 valid_tx_ant = 0; | 2276 | u8 valid_tx_ant = 0; |
2277 | struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; | 2277 | struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; |
2278 | 2278 | ||
2279 | /* Override starting rate (index 0) if needed for debug purposes */ | 2279 | /* Override starting rate (index 0) if needed for debug purposes */ |
2280 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2280 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
2281 | 2281 | ||
2282 | /* Interpret new_rate (rate_n_flags) */ | 2282 | /* Interpret new_rate (rate_n_flags) */ |
2283 | memset(&tbl_type, 0, sizeof(tbl_type)); | 2283 | memset(&tbl_type, 0, sizeof(tbl_type)); |
2284 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, | 2284 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, |
2285 | &tbl_type, &rate_idx); | 2285 | &tbl_type, &rate_idx); |
2286 | 2286 | ||
2287 | /* How many times should we repeat the initial rate? */ | 2287 | /* How many times should we repeat the initial rate? */ |
2288 | if (is_legacy(tbl_type.lq_type)) { | 2288 | if (is_legacy(tbl_type.lq_type)) { |
2289 | ant_toggle_cnt = 1; | 2289 | ant_toggle_cnt = 1; |
2290 | repeat_rate = IWL_NUMBER_TRY; | 2290 | repeat_rate = IWL_NUMBER_TRY; |
2291 | } else { | 2291 | } else { |
2292 | repeat_rate = IWL_HT_NUMBER_TRY; | 2292 | repeat_rate = IWL_HT_NUMBER_TRY; |
2293 | } | 2293 | } |
2294 | 2294 | ||
2295 | lq_cmd->general_params.mimo_delimiter = | 2295 | lq_cmd->general_params.mimo_delimiter = |
2296 | is_mimo(tbl_type.lq_type) ? 1 : 0; | 2296 | is_mimo(tbl_type.lq_type) ? 1 : 0; |
2297 | 2297 | ||
2298 | /* Fill 1st table entry (index 0) */ | 2298 | /* Fill 1st table entry (index 0) */ |
2299 | lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); | 2299 | lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); |
2300 | 2300 | ||
2301 | if (num_of_ant(tbl_type.ant_type) == 1) { | 2301 | if (num_of_ant(tbl_type.ant_type) == 1) { |
2302 | lq_cmd->general_params.single_stream_ant_msk = | 2302 | lq_cmd->general_params.single_stream_ant_msk = |
2303 | tbl_type.ant_type; | 2303 | tbl_type.ant_type; |
2304 | } else if (num_of_ant(tbl_type.ant_type) == 2) { | 2304 | } else if (num_of_ant(tbl_type.ant_type) == 2) { |
2305 | lq_cmd->general_params.dual_stream_ant_msk = | 2305 | lq_cmd->general_params.dual_stream_ant_msk = |
2306 | tbl_type.ant_type; | 2306 | tbl_type.ant_type; |
2307 | } /* otherwise we don't modify the existing value */ | 2307 | } /* otherwise we don't modify the existing value */ |
2308 | 2308 | ||
2309 | index++; | 2309 | index++; |
2310 | repeat_rate--; | 2310 | repeat_rate--; |
2311 | 2311 | ||
2312 | if (priv) | 2312 | if (priv) |
2313 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2313 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2314 | 2314 | ||
2315 | /* Fill rest of rate table */ | 2315 | /* Fill rest of rate table */ |
2316 | while (index < LINK_QUAL_MAX_RETRY_NUM) { | 2316 | while (index < LINK_QUAL_MAX_RETRY_NUM) { |
2317 | /* Repeat initial/next rate. | 2317 | /* Repeat initial/next rate. |
2318 | * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. | 2318 | * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. |
2319 | * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ | 2319 | * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ |
2320 | while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { | 2320 | while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { |
2321 | if (is_legacy(tbl_type.lq_type)) { | 2321 | if (is_legacy(tbl_type.lq_type)) { |
2322 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) | 2322 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) |
2323 | ant_toggle_cnt++; | 2323 | ant_toggle_cnt++; |
2324 | else if (priv && | 2324 | else if (priv && |
2325 | rs_toggle_antenna(valid_tx_ant, | 2325 | rs_toggle_antenna(valid_tx_ant, |
2326 | &new_rate, &tbl_type)) | 2326 | &new_rate, &tbl_type)) |
2327 | ant_toggle_cnt = 1; | 2327 | ant_toggle_cnt = 1; |
2328 | } | 2328 | } |
2329 | 2329 | ||
2330 | /* Override next rate if needed for debug purposes */ | 2330 | /* Override next rate if needed for debug purposes */ |
2331 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2331 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
2332 | 2332 | ||
2333 | /* Fill next table entry */ | 2333 | /* Fill next table entry */ |
2334 | lq_cmd->rs_table[index].rate_n_flags = | 2334 | lq_cmd->rs_table[index].rate_n_flags = |
2335 | cpu_to_le32(new_rate); | 2335 | cpu_to_le32(new_rate); |
2336 | repeat_rate--; | 2336 | repeat_rate--; |
2337 | index++; | 2337 | index++; |
2338 | } | 2338 | } |
2339 | 2339 | ||
2340 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, | 2340 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, |
2341 | &rate_idx); | 2341 | &rate_idx); |
2342 | 2342 | ||
2343 | /* Indicate to uCode which entries might be MIMO. | 2343 | /* Indicate to uCode which entries might be MIMO. |
2344 | * If initial rate was MIMO, this will finally end up | 2344 | * If initial rate was MIMO, this will finally end up |
2345 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ | 2345 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ |
2346 | if (is_mimo(tbl_type.lq_type)) | 2346 | if (is_mimo(tbl_type.lq_type)) |
2347 | lq_cmd->general_params.mimo_delimiter = index; | 2347 | lq_cmd->general_params.mimo_delimiter = index; |
2348 | 2348 | ||
2349 | /* Get next rate */ | 2349 | /* Get next rate */ |
2350 | new_rate = rs_get_lower_rate(lq_sta, &tbl_type, rate_idx, | 2350 | new_rate = rs_get_lower_rate(lq_sta, &tbl_type, rate_idx, |
2351 | use_ht_possible); | 2351 | use_ht_possible); |
2352 | 2352 | ||
2353 | /* How many times should we repeat the next rate? */ | 2353 | /* How many times should we repeat the next rate? */ |
2354 | if (is_legacy(tbl_type.lq_type)) { | 2354 | if (is_legacy(tbl_type.lq_type)) { |
2355 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) | 2355 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) |
2356 | ant_toggle_cnt++; | 2356 | ant_toggle_cnt++; |
2357 | else if (priv && | 2357 | else if (priv && |
2358 | rs_toggle_antenna(valid_tx_ant, | 2358 | rs_toggle_antenna(valid_tx_ant, |
2359 | &new_rate, &tbl_type)) | 2359 | &new_rate, &tbl_type)) |
2360 | ant_toggle_cnt = 1; | 2360 | ant_toggle_cnt = 1; |
2361 | 2361 | ||
2362 | repeat_rate = IWL_NUMBER_TRY; | 2362 | repeat_rate = IWL_NUMBER_TRY; |
2363 | } else { | 2363 | } else { |
2364 | repeat_rate = IWL_HT_NUMBER_TRY; | 2364 | repeat_rate = IWL_HT_NUMBER_TRY; |
2365 | } | 2365 | } |
2366 | 2366 | ||
2367 | /* Don't allow HT rates after next pass. | 2367 | /* Don't allow HT rates after next pass. |
2368 | * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ | 2368 | * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ |
2369 | use_ht_possible = 0; | 2369 | use_ht_possible = 0; |
2370 | 2370 | ||
2371 | /* Override next rate if needed for debug purposes */ | 2371 | /* Override next rate if needed for debug purposes */ |
2372 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2372 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
2373 | 2373 | ||
2374 | /* Fill next table entry */ | 2374 | /* Fill next table entry */ |
2375 | lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); | 2375 | lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); |
2376 | 2376 | ||
2377 | index++; | 2377 | index++; |
2378 | repeat_rate--; | 2378 | repeat_rate--; |
2379 | } | 2379 | } |
2380 | 2380 | ||
2381 | lq_cmd->agg_params.agg_frame_cnt_limit = 64; | 2381 | lq_cmd->agg_params.agg_frame_cnt_limit = 64; |
2382 | lq_cmd->agg_params.agg_dis_start_th = 3; | 2382 | lq_cmd->agg_params.agg_dis_start_th = 3; |
2383 | lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); | 2383 | lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); |
2384 | } | 2384 | } |
2385 | 2385 | ||
2386 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2386 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
2387 | { | 2387 | { |
2388 | return hw->priv; | 2388 | return hw->priv; |
2389 | } | 2389 | } |
2390 | /* rate scale requires free function to be implemented */ | 2390 | /* rate scale requires free function to be implemented */ |
2391 | static void rs_free(void *priv_rate) | 2391 | static void rs_free(void *priv_rate) |
2392 | { | 2392 | { |
2393 | return; | 2393 | return; |
2394 | } | 2394 | } |
2395 | 2395 | ||
2396 | static void rs_clear(void *priv_rate) | ||
2397 | { | ||
2398 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2399 | struct iwl_priv *priv = (struct iwl_priv *) priv_rate; | ||
2400 | |||
2401 | IWL_DEBUG_RATE("enter\n"); | ||
2402 | |||
2403 | /* TODO - add rate scale state reset */ | ||
2404 | |||
2405 | IWL_DEBUG_RATE("leave\n"); | ||
2406 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
2407 | } | ||
2408 | |||
2409 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, | 2396 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, |
2410 | void *priv_sta) | 2397 | void *priv_sta) |
2411 | { | 2398 | { |
2412 | struct iwl_lq_sta *lq_sta = priv_sta; | 2399 | struct iwl_lq_sta *lq_sta = priv_sta; |
2413 | struct iwl_priv *priv __maybe_unused = priv_r; | 2400 | struct iwl_priv *priv __maybe_unused = priv_r; |
2414 | 2401 | ||
2415 | IWL_DEBUG_RATE("enter\n"); | 2402 | IWL_DEBUG_RATE("enter\n"); |
2416 | kfree(lq_sta); | 2403 | kfree(lq_sta); |
2417 | IWL_DEBUG_RATE("leave\n"); | 2404 | IWL_DEBUG_RATE("leave\n"); |
2418 | } | 2405 | } |
2419 | 2406 | ||
2420 | 2407 | ||
2421 | #ifdef CONFIG_MAC80211_DEBUGFS | 2408 | #ifdef CONFIG_MAC80211_DEBUGFS |
2422 | static int open_file_generic(struct inode *inode, struct file *file) | 2409 | static int open_file_generic(struct inode *inode, struct file *file) |
2423 | { | 2410 | { |
2424 | file->private_data = inode->i_private; | 2411 | file->private_data = inode->i_private; |
2425 | return 0; | 2412 | return 0; |
2426 | } | 2413 | } |
2427 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | 2414 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, |
2428 | u32 *rate_n_flags, int index) | 2415 | u32 *rate_n_flags, int index) |
2429 | { | 2416 | { |
2430 | struct iwl_priv *priv; | 2417 | struct iwl_priv *priv; |
2431 | 2418 | ||
2432 | priv = lq_sta->drv; | 2419 | priv = lq_sta->drv; |
2433 | if (lq_sta->dbg_fixed_rate) { | 2420 | if (lq_sta->dbg_fixed_rate) { |
2434 | if (index < 12) { | 2421 | if (index < 12) { |
2435 | *rate_n_flags = lq_sta->dbg_fixed_rate; | 2422 | *rate_n_flags = lq_sta->dbg_fixed_rate; |
2436 | } else { | 2423 | } else { |
2437 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 2424 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
2438 | *rate_n_flags = 0x800D; | 2425 | *rate_n_flags = 0x800D; |
2439 | else | 2426 | else |
2440 | *rate_n_flags = 0x820A; | 2427 | *rate_n_flags = 0x820A; |
2441 | } | 2428 | } |
2442 | IWL_DEBUG_RATE("Fixed rate ON\n"); | 2429 | IWL_DEBUG_RATE("Fixed rate ON\n"); |
2443 | } else { | 2430 | } else { |
2444 | IWL_DEBUG_RATE("Fixed rate OFF\n"); | 2431 | IWL_DEBUG_RATE("Fixed rate OFF\n"); |
2445 | } | 2432 | } |
2446 | } | 2433 | } |
2447 | 2434 | ||
2448 | static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | 2435 | static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, |
2449 | const char __user *user_buf, size_t count, loff_t *ppos) | 2436 | const char __user *user_buf, size_t count, loff_t *ppos) |
2450 | { | 2437 | { |
2451 | struct iwl_lq_sta *lq_sta = file->private_data; | 2438 | struct iwl_lq_sta *lq_sta = file->private_data; |
2452 | struct iwl_priv *priv; | 2439 | struct iwl_priv *priv; |
2453 | char buf[64]; | 2440 | char buf[64]; |
2454 | int buf_size; | 2441 | int buf_size; |
2455 | u32 parsed_rate; | 2442 | u32 parsed_rate; |
2456 | 2443 | ||
2457 | priv = lq_sta->drv; | 2444 | priv = lq_sta->drv; |
2458 | memset(buf, 0, sizeof(buf)); | 2445 | memset(buf, 0, sizeof(buf)); |
2459 | buf_size = min(count, sizeof(buf) - 1); | 2446 | buf_size = min(count, sizeof(buf) - 1); |
2460 | if (copy_from_user(buf, user_buf, buf_size)) | 2447 | if (copy_from_user(buf, user_buf, buf_size)) |
2461 | return -EFAULT; | 2448 | return -EFAULT; |
2462 | 2449 | ||
2463 | if (sscanf(buf, "%x", &parsed_rate) == 1) | 2450 | if (sscanf(buf, "%x", &parsed_rate) == 1) |
2464 | lq_sta->dbg_fixed_rate = parsed_rate; | 2451 | lq_sta->dbg_fixed_rate = parsed_rate; |
2465 | else | 2452 | else |
2466 | lq_sta->dbg_fixed_rate = 0; | 2453 | lq_sta->dbg_fixed_rate = 0; |
2467 | 2454 | ||
2468 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ | 2455 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ |
2469 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 2456 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
2470 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 2457 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
2471 | lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 2458 | lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
2472 | 2459 | ||
2473 | IWL_DEBUG_RATE("sta_id %d rate 0x%X\n", | 2460 | IWL_DEBUG_RATE("sta_id %d rate 0x%X\n", |
2474 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | 2461 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); |
2475 | 2462 | ||
2476 | if (lq_sta->dbg_fixed_rate) { | 2463 | if (lq_sta->dbg_fixed_rate) { |
2477 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 2464 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2478 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); | 2465 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); |
2479 | } | 2466 | } |
2480 | 2467 | ||
2481 | return count; | 2468 | return count; |
2482 | } | 2469 | } |
2483 | 2470 | ||
2484 | static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | 2471 | static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, |
2485 | char __user *user_buf, size_t count, loff_t *ppos) | 2472 | char __user *user_buf, size_t count, loff_t *ppos) |
2486 | { | 2473 | { |
2487 | char buff[1024]; | 2474 | char buff[1024]; |
2488 | int desc = 0; | 2475 | int desc = 0; |
2489 | int i = 0; | 2476 | int i = 0; |
2490 | 2477 | ||
2491 | struct iwl_lq_sta *lq_sta = file->private_data; | 2478 | struct iwl_lq_sta *lq_sta = file->private_data; |
2492 | 2479 | ||
2493 | desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); | 2480 | desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); |
2494 | desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", | 2481 | desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", |
2495 | lq_sta->total_failed, lq_sta->total_success, | 2482 | lq_sta->total_failed, lq_sta->total_success, |
2496 | lq_sta->active_legacy_rate); | 2483 | lq_sta->active_legacy_rate); |
2497 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 2484 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
2498 | lq_sta->dbg_fixed_rate); | 2485 | lq_sta->dbg_fixed_rate); |
2499 | desc += sprintf(buff+desc, "general:" | 2486 | desc += sprintf(buff+desc, "general:" |
2500 | "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", | 2487 | "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", |
2501 | lq_sta->lq.general_params.flags, | 2488 | lq_sta->lq.general_params.flags, |
2502 | lq_sta->lq.general_params.mimo_delimiter, | 2489 | lq_sta->lq.general_params.mimo_delimiter, |
2503 | lq_sta->lq.general_params.single_stream_ant_msk, | 2490 | lq_sta->lq.general_params.single_stream_ant_msk, |
2504 | lq_sta->lq.general_params.dual_stream_ant_msk); | 2491 | lq_sta->lq.general_params.dual_stream_ant_msk); |
2505 | 2492 | ||
2506 | desc += sprintf(buff+desc, "agg:" | 2493 | desc += sprintf(buff+desc, "agg:" |
2507 | "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n", | 2494 | "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n", |
2508 | le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit), | 2495 | le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit), |
2509 | lq_sta->lq.agg_params.agg_dis_start_th, | 2496 | lq_sta->lq.agg_params.agg_dis_start_th, |
2510 | lq_sta->lq.agg_params.agg_frame_cnt_limit); | 2497 | lq_sta->lq.agg_params.agg_frame_cnt_limit); |
2511 | 2498 | ||
2512 | desc += sprintf(buff+desc, | 2499 | desc += sprintf(buff+desc, |
2513 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", | 2500 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", |
2514 | lq_sta->lq.general_params.start_rate_index[0], | 2501 | lq_sta->lq.general_params.start_rate_index[0], |
2515 | lq_sta->lq.general_params.start_rate_index[1], | 2502 | lq_sta->lq.general_params.start_rate_index[1], |
2516 | lq_sta->lq.general_params.start_rate_index[2], | 2503 | lq_sta->lq.general_params.start_rate_index[2], |
2517 | lq_sta->lq.general_params.start_rate_index[3]); | 2504 | lq_sta->lq.general_params.start_rate_index[3]); |
2518 | 2505 | ||
2519 | 2506 | ||
2520 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | 2507 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) |
2521 | desc += sprintf(buff+desc, " rate[%d] 0x%X\n", | 2508 | desc += sprintf(buff+desc, " rate[%d] 0x%X\n", |
2522 | i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); | 2509 | i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); |
2523 | 2510 | ||
2524 | return simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2511 | return simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
2525 | } | 2512 | } |
2526 | 2513 | ||
2527 | static const struct file_operations rs_sta_dbgfs_scale_table_ops = { | 2514 | static const struct file_operations rs_sta_dbgfs_scale_table_ops = { |
2528 | .write = rs_sta_dbgfs_scale_table_write, | 2515 | .write = rs_sta_dbgfs_scale_table_write, |
2529 | .read = rs_sta_dbgfs_scale_table_read, | 2516 | .read = rs_sta_dbgfs_scale_table_read, |
2530 | .open = open_file_generic, | 2517 | .open = open_file_generic, |
2531 | }; | 2518 | }; |
2532 | static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | 2519 | static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, |
2533 | char __user *user_buf, size_t count, loff_t *ppos) | 2520 | char __user *user_buf, size_t count, loff_t *ppos) |
2534 | { | 2521 | { |
2535 | char buff[1024]; | 2522 | char buff[1024]; |
2536 | int desc = 0; | 2523 | int desc = 0; |
2537 | int i, j; | 2524 | int i, j; |
2538 | 2525 | ||
2539 | struct iwl_lq_sta *lq_sta = file->private_data; | 2526 | struct iwl_lq_sta *lq_sta = file->private_data; |
2540 | for (i = 0; i < LQ_SIZE; i++) { | 2527 | for (i = 0; i < LQ_SIZE; i++) { |
2541 | desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" | 2528 | desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" |
2542 | "rate=0x%X\n", | 2529 | "rate=0x%X\n", |
2543 | lq_sta->active_tbl == i?"*":"x", | 2530 | lq_sta->active_tbl == i?"*":"x", |
2544 | lq_sta->lq_info[i].lq_type, | 2531 | lq_sta->lq_info[i].lq_type, |
2545 | lq_sta->lq_info[i].is_SGI, | 2532 | lq_sta->lq_info[i].is_SGI, |
2546 | lq_sta->lq_info[i].is_fat, | 2533 | lq_sta->lq_info[i].is_fat, |
2547 | lq_sta->lq_info[i].is_dup, | 2534 | lq_sta->lq_info[i].is_dup, |
2548 | lq_sta->lq_info[i].current_rate); | 2535 | lq_sta->lq_info[i].current_rate); |
2549 | for (j = 0; j < IWL_RATE_COUNT; j++) { | 2536 | for (j = 0; j < IWL_RATE_COUNT; j++) { |
2550 | desc += sprintf(buff+desc, | 2537 | desc += sprintf(buff+desc, |
2551 | "counter=%d success=%d %%=%d\n", | 2538 | "counter=%d success=%d %%=%d\n", |
2552 | lq_sta->lq_info[i].win[j].counter, | 2539 | lq_sta->lq_info[i].win[j].counter, |
2553 | lq_sta->lq_info[i].win[j].success_counter, | 2540 | lq_sta->lq_info[i].win[j].success_counter, |
2554 | lq_sta->lq_info[i].win[j].success_ratio); | 2541 | lq_sta->lq_info[i].win[j].success_ratio); |
2555 | } | 2542 | } |
2556 | } | 2543 | } |
2557 | return simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2544 | return simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
2558 | } | 2545 | } |
2559 | 2546 | ||
2560 | static const struct file_operations rs_sta_dbgfs_stats_table_ops = { | 2547 | static const struct file_operations rs_sta_dbgfs_stats_table_ops = { |
2561 | .read = rs_sta_dbgfs_stats_table_read, | 2548 | .read = rs_sta_dbgfs_stats_table_read, |
2562 | .open = open_file_generic, | 2549 | .open = open_file_generic, |
2563 | }; | 2550 | }; |
2564 | 2551 | ||
2565 | static void rs_add_debugfs(void *priv, void *priv_sta, | 2552 | static void rs_add_debugfs(void *priv, void *priv_sta, |
2566 | struct dentry *dir) | 2553 | struct dentry *dir) |
2567 | { | 2554 | { |
2568 | struct iwl_lq_sta *lq_sta = priv_sta; | 2555 | struct iwl_lq_sta *lq_sta = priv_sta; |
2569 | lq_sta->rs_sta_dbgfs_scale_table_file = | 2556 | lq_sta->rs_sta_dbgfs_scale_table_file = |
2570 | debugfs_create_file("rate_scale_table", 0600, dir, | 2557 | debugfs_create_file("rate_scale_table", 0600, dir, |
2571 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 2558 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
2572 | lq_sta->rs_sta_dbgfs_stats_table_file = | 2559 | lq_sta->rs_sta_dbgfs_stats_table_file = |
2573 | debugfs_create_file("rate_stats_table", 0600, dir, | 2560 | debugfs_create_file("rate_stats_table", 0600, dir, |
2574 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 2561 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
2575 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 2562 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
2576 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, | 2563 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, |
2577 | &lq_sta->tx_agg_tid_en); | 2564 | &lq_sta->tx_agg_tid_en); |
2578 | 2565 | ||
2579 | } | 2566 | } |
2580 | 2567 | ||
2581 | static void rs_remove_debugfs(void *priv, void *priv_sta) | 2568 | static void rs_remove_debugfs(void *priv, void *priv_sta) |
2582 | { | 2569 | { |
2583 | struct iwl_lq_sta *lq_sta = priv_sta; | 2570 | struct iwl_lq_sta *lq_sta = priv_sta; |
2584 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); | 2571 | debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); |
2585 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); | 2572 | debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); |
2586 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); | 2573 | debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); |
2587 | } | 2574 | } |
2588 | #endif | 2575 | #endif |
2589 | 2576 | ||
2590 | static struct rate_control_ops rs_ops = { | 2577 | static struct rate_control_ops rs_ops = { |
2591 | .module = NULL, | 2578 | .module = NULL, |
2592 | .name = RS_NAME, | 2579 | .name = RS_NAME, |
2593 | .tx_status = rs_tx_status, | 2580 | .tx_status = rs_tx_status, |
2594 | .get_rate = rs_get_rate, | 2581 | .get_rate = rs_get_rate, |
2595 | .rate_init = rs_rate_init, | 2582 | .rate_init = rs_rate_init, |
2596 | .clear = rs_clear, | ||
2597 | .alloc = rs_alloc, | 2583 | .alloc = rs_alloc, |
2598 | .free = rs_free, | 2584 | .free = rs_free, |
2599 | .alloc_sta = rs_alloc_sta, | 2585 | .alloc_sta = rs_alloc_sta, |
2600 | .free_sta = rs_free_sta, | 2586 | .free_sta = rs_free_sta, |
2601 | #ifdef CONFIG_MAC80211_DEBUGFS | 2587 | #ifdef CONFIG_MAC80211_DEBUGFS |
2602 | .add_sta_debugfs = rs_add_debugfs, | 2588 | .add_sta_debugfs = rs_add_debugfs, |
2603 | .remove_sta_debugfs = rs_remove_debugfs, | 2589 | .remove_sta_debugfs = rs_remove_debugfs, |
2604 | #endif | 2590 | #endif |
2605 | }; | 2591 | }; |
2606 | 2592 | ||
2607 | int iwlagn_rate_control_register(void) | 2593 | int iwlagn_rate_control_register(void) |
2608 | { | 2594 | { |
2609 | return ieee80211_rate_control_register(&rs_ops); | 2595 | return ieee80211_rate_control_register(&rs_ops); |
2610 | } | 2596 | } |
2611 | 2597 | ||
2612 | void iwlagn_rate_control_unregister(void) | 2598 | void iwlagn_rate_control_unregister(void) |
2613 | { | 2599 | { |
2614 | ieee80211_rate_control_unregister(&rs_ops); | 2600 | ieee80211_rate_control_unregister(&rs_ops); |
2615 | } | 2601 | } |
2616 | 2602 | ||
2617 | 2603 |
include/net/mac80211.h
1 | /* | 1 | /* |
2 | * mac80211 <-> driver interface | 2 | * mac80211 <-> driver interface |
3 | * | 3 | * |
4 | * Copyright 2002-2005, Devicescape Software, Inc. | 4 | * Copyright 2002-2005, Devicescape Software, Inc. |
5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
6 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef MAC80211_H | 13 | #ifndef MAC80211_H |
14 | #define MAC80211_H | 14 | #define MAC80211_H |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/if_ether.h> | 17 | #include <linux/if_ether.h> |
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
19 | #include <linux/wireless.h> | 19 | #include <linux/wireless.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/ieee80211.h> | 21 | #include <linux/ieee80211.h> |
22 | #include <net/wireless.h> | 22 | #include <net/wireless.h> |
23 | #include <net/cfg80211.h> | 23 | #include <net/cfg80211.h> |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * DOC: Introduction | 26 | * DOC: Introduction |
27 | * | 27 | * |
28 | * mac80211 is the Linux stack for 802.11 hardware that implements | 28 | * mac80211 is the Linux stack for 802.11 hardware that implements |
29 | * only partial functionality in hard- or firmware. This document | 29 | * only partial functionality in hard- or firmware. This document |
30 | * defines the interface between mac80211 and low-level hardware | 30 | * defines the interface between mac80211 and low-level hardware |
31 | * drivers. | 31 | * drivers. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * DOC: Calling mac80211 from interrupts | 35 | * DOC: Calling mac80211 from interrupts |
36 | * | 36 | * |
37 | * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be | 37 | * Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be |
38 | * called in hardware interrupt context. The low-level driver must not call any | 38 | * called in hardware interrupt context. The low-level driver must not call any |
39 | * other functions in hardware interrupt context. If there is a need for such | 39 | * other functions in hardware interrupt context. If there is a need for such |
40 | * call, the low-level driver should first ACK the interrupt and perform the | 40 | * call, the low-level driver should first ACK the interrupt and perform the |
41 | * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even | 41 | * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even |
42 | * tasklet function. | 42 | * tasklet function. |
43 | * | 43 | * |
44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also | 44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also |
45 | * use the non-IRQ-safe functions! | 45 | * use the non-IRQ-safe functions! |
46 | */ | 46 | */ |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * DOC: Warning | 49 | * DOC: Warning |
50 | * | 50 | * |
51 | * If you're reading this document and not the header file itself, it will | 51 | * If you're reading this document and not the header file itself, it will |
52 | * be incomplete because not all documentation has been converted yet. | 52 | * be incomplete because not all documentation has been converted yet. |
53 | */ | 53 | */ |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * DOC: Frame format | 56 | * DOC: Frame format |
57 | * | 57 | * |
58 | * As a general rule, when frames are passed between mac80211 and the driver, | 58 | * As a general rule, when frames are passed between mac80211 and the driver, |
59 | * they start with the IEEE 802.11 header and include the same octets that are | 59 | * they start with the IEEE 802.11 header and include the same octets that are |
60 | * sent over the air except for the FCS which should be calculated by the | 60 | * sent over the air except for the FCS which should be calculated by the |
61 | * hardware. | 61 | * hardware. |
62 | * | 62 | * |
63 | * There are, however, various exceptions to this rule for advanced features: | 63 | * There are, however, various exceptions to this rule for advanced features: |
64 | * | 64 | * |
65 | * The first exception is for hardware encryption and decryption offload | 65 | * The first exception is for hardware encryption and decryption offload |
66 | * where the IV/ICV may or may not be generated in hardware. | 66 | * where the IV/ICV may or may not be generated in hardware. |
67 | * | 67 | * |
68 | * Secondly, when the hardware handles fragmentation, the frame handed to | 68 | * Secondly, when the hardware handles fragmentation, the frame handed to |
69 | * the driver from mac80211 is the MSDU, not the MPDU. | 69 | * the driver from mac80211 is the MSDU, not the MPDU. |
70 | * | 70 | * |
71 | * Finally, for received frames, the driver is able to indicate that it has | 71 | * Finally, for received frames, the driver is able to indicate that it has |
72 | * filled a radiotap header and put that in front of the frame; if it does | 72 | * filled a radiotap header and put that in front of the frame; if it does |
73 | * not do so then mac80211 may add this under certain circumstances. | 73 | * not do so then mac80211 may add this under certain circumstances. |
74 | */ | 74 | */ |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * enum ieee80211_notification_type - Low level driver notification | 77 | * enum ieee80211_notification_type - Low level driver notification |
78 | * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence | 78 | * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence |
79 | */ | 79 | */ |
80 | enum ieee80211_notification_types { | 80 | enum ieee80211_notification_types { |
81 | IEEE80211_NOTIFY_RE_ASSOC, | 81 | IEEE80211_NOTIFY_RE_ASSOC, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * enum ieee80211_max_queues - maximum number of queues | 85 | * enum ieee80211_max_queues - maximum number of queues |
86 | * | 86 | * |
87 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 87 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
88 | * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable | 88 | * @IEEE80211_MAX_AMPDU_QUEUES: Maximum number of queues usable |
89 | * for A-MPDU operation. | 89 | * for A-MPDU operation. |
90 | */ | 90 | */ |
91 | enum ieee80211_max_queues { | 91 | enum ieee80211_max_queues { |
92 | IEEE80211_MAX_QUEUES = 16, | 92 | IEEE80211_MAX_QUEUES = 16, |
93 | IEEE80211_MAX_AMPDU_QUEUES = 16, | 93 | IEEE80211_MAX_AMPDU_QUEUES = 16, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /** | 96 | /** |
97 | * struct ieee80211_tx_queue_params - transmit queue configuration | 97 | * struct ieee80211_tx_queue_params - transmit queue configuration |
98 | * | 98 | * |
99 | * The information provided in this structure is required for QoS | 99 | * The information provided in this structure is required for QoS |
100 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. | 100 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. |
101 | * | 101 | * |
102 | * @aifs: arbitration interface space [0..255] | 102 | * @aifs: arbitration interface space [0..255] |
103 | * @cw_min: minimum contention window [a value of the form | 103 | * @cw_min: minimum contention window [a value of the form |
104 | * 2^n-1 in the range 1..32767] | 104 | * 2^n-1 in the range 1..32767] |
105 | * @cw_max: maximum contention window [like @cw_min] | 105 | * @cw_max: maximum contention window [like @cw_min] |
106 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled | 106 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled |
107 | */ | 107 | */ |
108 | struct ieee80211_tx_queue_params { | 108 | struct ieee80211_tx_queue_params { |
109 | u16 txop; | 109 | u16 txop; |
110 | u16 cw_min; | 110 | u16 cw_min; |
111 | u16 cw_max; | 111 | u16 cw_max; |
112 | u8 aifs; | 112 | u8 aifs; |
113 | }; | 113 | }; |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * struct ieee80211_tx_queue_stats - transmit queue statistics | 116 | * struct ieee80211_tx_queue_stats - transmit queue statistics |
117 | * | 117 | * |
118 | * @len: number of packets in queue | 118 | * @len: number of packets in queue |
119 | * @limit: queue length limit | 119 | * @limit: queue length limit |
120 | * @count: number of frames sent | 120 | * @count: number of frames sent |
121 | */ | 121 | */ |
122 | struct ieee80211_tx_queue_stats { | 122 | struct ieee80211_tx_queue_stats { |
123 | unsigned int len; | 123 | unsigned int len; |
124 | unsigned int limit; | 124 | unsigned int limit; |
125 | unsigned int count; | 125 | unsigned int count; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct ieee80211_low_level_stats { | 128 | struct ieee80211_low_level_stats { |
129 | unsigned int dot11ACKFailureCount; | 129 | unsigned int dot11ACKFailureCount; |
130 | unsigned int dot11RTSFailureCount; | 130 | unsigned int dot11RTSFailureCount; |
131 | unsigned int dot11FCSErrorCount; | 131 | unsigned int dot11FCSErrorCount; |
132 | unsigned int dot11RTSSuccessCount; | 132 | unsigned int dot11RTSSuccessCount; |
133 | }; | 133 | }; |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * enum ieee80211_bss_change - BSS change notification flags | 136 | * enum ieee80211_bss_change - BSS change notification flags |
137 | * | 137 | * |
138 | * These flags are used with the bss_info_changed() callback | 138 | * These flags are used with the bss_info_changed() callback |
139 | * to indicate which BSS parameter changed. | 139 | * to indicate which BSS parameter changed. |
140 | * | 140 | * |
141 | * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated), | 141 | * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated), |
142 | * also implies a change in the AID. | 142 | * also implies a change in the AID. |
143 | * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed | 143 | * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed |
144 | * @BSS_CHANGED_ERP_PREAMBLE: preamble changed | 144 | * @BSS_CHANGED_ERP_PREAMBLE: preamble changed |
145 | * @BSS_CHANGED_ERP_SLOT: slot timing changed | 145 | * @BSS_CHANGED_ERP_SLOT: slot timing changed |
146 | * @BSS_CHANGED_HT: 802.11n parameters changed | 146 | * @BSS_CHANGED_HT: 802.11n parameters changed |
147 | * @BSS_CHANGED_BASIC_RATES: Basic rateset changed | 147 | * @BSS_CHANGED_BASIC_RATES: Basic rateset changed |
148 | */ | 148 | */ |
149 | enum ieee80211_bss_change { | 149 | enum ieee80211_bss_change { |
150 | BSS_CHANGED_ASSOC = 1<<0, | 150 | BSS_CHANGED_ASSOC = 1<<0, |
151 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, | 151 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, |
152 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, | 152 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, |
153 | BSS_CHANGED_ERP_SLOT = 1<<3, | 153 | BSS_CHANGED_ERP_SLOT = 1<<3, |
154 | BSS_CHANGED_HT = 1<<4, | 154 | BSS_CHANGED_HT = 1<<4, |
155 | BSS_CHANGED_BASIC_RATES = 1<<5, | 155 | BSS_CHANGED_BASIC_RATES = 1<<5, |
156 | }; | 156 | }; |
157 | 157 | ||
158 | /** | 158 | /** |
159 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration | 159 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration |
160 | * @secondary_channel_offset: secondary channel offset, uses | 160 | * @secondary_channel_offset: secondary channel offset, uses |
161 | * %IEEE80211_HT_PARAM_CHA_SEC_ values | 161 | * %IEEE80211_HT_PARAM_CHA_SEC_ values |
162 | * @width_40_ok: indicates that 40 MHz bandwidth may be used for TX | 162 | * @width_40_ok: indicates that 40 MHz bandwidth may be used for TX |
163 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) | 163 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) |
164 | */ | 164 | */ |
165 | struct ieee80211_bss_ht_conf { | 165 | struct ieee80211_bss_ht_conf { |
166 | u8 secondary_channel_offset; | 166 | u8 secondary_channel_offset; |
167 | bool width_40_ok; | 167 | bool width_40_ok; |
168 | u16 operation_mode; | 168 | u16 operation_mode; |
169 | }; | 169 | }; |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * struct ieee80211_bss_conf - holds the BSS's changing parameters | 172 | * struct ieee80211_bss_conf - holds the BSS's changing parameters |
173 | * | 173 | * |
174 | * This structure keeps information about a BSS (and an association | 174 | * This structure keeps information about a BSS (and an association |
175 | * to that BSS) that can change during the lifetime of the BSS. | 175 | * to that BSS) that can change during the lifetime of the BSS. |
176 | * | 176 | * |
177 | * @assoc: association status | 177 | * @assoc: association status |
178 | * @aid: association ID number, valid only when @assoc is true | 178 | * @aid: association ID number, valid only when @assoc is true |
179 | * @use_cts_prot: use CTS protection | 179 | * @use_cts_prot: use CTS protection |
180 | * @use_short_preamble: use 802.11b short preamble; | 180 | * @use_short_preamble: use 802.11b short preamble; |
181 | * if the hardware cannot handle this it must set the | 181 | * if the hardware cannot handle this it must set the |
182 | * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag | 182 | * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag |
183 | * @use_short_slot: use short slot time (only relevant for ERP); | 183 | * @use_short_slot: use short slot time (only relevant for ERP); |
184 | * if the hardware cannot handle this it must set the | 184 | * if the hardware cannot handle this it must set the |
185 | * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag | 185 | * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag |
186 | * @dtim_period: num of beacons before the next DTIM, for PSM | 186 | * @dtim_period: num of beacons before the next DTIM, for PSM |
187 | * @timestamp: beacon timestamp | 187 | * @timestamp: beacon timestamp |
188 | * @beacon_int: beacon interval | 188 | * @beacon_int: beacon interval |
189 | * @assoc_capability: capabilities taken from assoc resp | 189 | * @assoc_capability: capabilities taken from assoc resp |
190 | * @ht: BSS's HT configuration | 190 | * @ht: BSS's HT configuration |
191 | * @basic_rates: bitmap of basic rates, each bit stands for an | 191 | * @basic_rates: bitmap of basic rates, each bit stands for an |
192 | * index into the rate table configured by the driver in | 192 | * index into the rate table configured by the driver in |
193 | * the current band. | 193 | * the current band. |
194 | */ | 194 | */ |
195 | struct ieee80211_bss_conf { | 195 | struct ieee80211_bss_conf { |
196 | /* association related data */ | 196 | /* association related data */ |
197 | bool assoc; | 197 | bool assoc; |
198 | u16 aid; | 198 | u16 aid; |
199 | /* erp related data */ | 199 | /* erp related data */ |
200 | bool use_cts_prot; | 200 | bool use_cts_prot; |
201 | bool use_short_preamble; | 201 | bool use_short_preamble; |
202 | bool use_short_slot; | 202 | bool use_short_slot; |
203 | u8 dtim_period; | 203 | u8 dtim_period; |
204 | u16 beacon_int; | 204 | u16 beacon_int; |
205 | u16 assoc_capability; | 205 | u16 assoc_capability; |
206 | u64 timestamp; | 206 | u64 timestamp; |
207 | u64 basic_rates; | 207 | u64 basic_rates; |
208 | struct ieee80211_bss_ht_conf ht; | 208 | struct ieee80211_bss_ht_conf ht; |
209 | }; | 209 | }; |
210 | 210 | ||
211 | /** | 211 | /** |
212 | * enum mac80211_tx_control_flags - flags to describe transmission information/status | 212 | * enum mac80211_tx_control_flags - flags to describe transmission information/status |
213 | * | 213 | * |
214 | * These flags are used with the @flags member of &ieee80211_tx_info. | 214 | * These flags are used with the @flags member of &ieee80211_tx_info. |
215 | * | 215 | * |
216 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. | 216 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. |
217 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence | 217 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence |
218 | * number to this frame, taking care of not overwriting the fragment | 218 | * number to this frame, taking care of not overwriting the fragment |
219 | * number and increasing the sequence number only when the | 219 | * number and increasing the sequence number only when the |
220 | * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly | 220 | * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly |
221 | * assign sequence numbers to QoS-data frames but cannot do so correctly | 221 | * assign sequence numbers to QoS-data frames but cannot do so correctly |
222 | * for non-QoS-data and management frames because beacons need them from | 222 | * for non-QoS-data and management frames because beacons need them from |
223 | * that counter as well and mac80211 cannot guarantee proper sequencing. | 223 | * that counter as well and mac80211 cannot guarantee proper sequencing. |
224 | * If this flag is set, the driver should instruct the hardware to | 224 | * If this flag is set, the driver should instruct the hardware to |
225 | * assign a sequence number to the frame or assign one itself. Cf. IEEE | 225 | * assign a sequence number to the frame or assign one itself. Cf. IEEE |
226 | * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for | 226 | * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for |
227 | * beacons and always be clear for frames without a sequence number field. | 227 | * beacons and always be clear for frames without a sequence number field. |
228 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack | 228 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack |
229 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination | 229 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination |
230 | * station | 230 | * station |
231 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame | 231 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame |
232 | * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon | 232 | * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon |
233 | * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU | 233 | * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU |
234 | * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. | 234 | * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. |
235 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted | 235 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted |
236 | * because the destination STA was in powersave mode. | 236 | * because the destination STA was in powersave mode. |
237 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged | 237 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged |
238 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status | 238 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status |
239 | * is for the whole aggregation. | 239 | * is for the whole aggregation. |
240 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, | 240 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, |
241 | * so consider using block ack request (BAR). | 241 | * so consider using block ack request (BAR). |
242 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be | 242 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be |
243 | * set by rate control algorithms to indicate probe rate, will | 243 | * set by rate control algorithms to indicate probe rate, will |
244 | * be cleared for fragmented frames (except on the last fragment) | 244 | * be cleared for fragmented frames (except on the last fragment) |
245 | * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS | 245 | * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS |
246 | */ | 246 | */ |
247 | enum mac80211_tx_control_flags { | 247 | enum mac80211_tx_control_flags { |
248 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 248 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
249 | IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), | 249 | IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), |
250 | IEEE80211_TX_CTL_NO_ACK = BIT(2), | 250 | IEEE80211_TX_CTL_NO_ACK = BIT(2), |
251 | IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), | 251 | IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), |
252 | IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), | 252 | IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), |
253 | IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), | 253 | IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), |
254 | IEEE80211_TX_CTL_AMPDU = BIT(6), | 254 | IEEE80211_TX_CTL_AMPDU = BIT(6), |
255 | IEEE80211_TX_CTL_INJECTED = BIT(7), | 255 | IEEE80211_TX_CTL_INJECTED = BIT(7), |
256 | IEEE80211_TX_STAT_TX_FILTERED = BIT(8), | 256 | IEEE80211_TX_STAT_TX_FILTERED = BIT(8), |
257 | IEEE80211_TX_STAT_ACK = BIT(9), | 257 | IEEE80211_TX_STAT_ACK = BIT(9), |
258 | IEEE80211_TX_STAT_AMPDU = BIT(10), | 258 | IEEE80211_TX_STAT_AMPDU = BIT(10), |
259 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), | 259 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), |
260 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 260 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
261 | 261 | ||
262 | /* XXX: remove this */ | 262 | /* XXX: remove this */ |
263 | IEEE80211_TX_CTL_REQUEUE = BIT(13), | 263 | IEEE80211_TX_CTL_REQUEUE = BIT(13), |
264 | }; | 264 | }; |
265 | 265 | ||
266 | enum mac80211_rate_control_flags { | 266 | enum mac80211_rate_control_flags { |
267 | IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), | 267 | IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), |
268 | IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), | 268 | IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), |
269 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), | 269 | IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), |
270 | 270 | ||
271 | /* rate index is an MCS rate number instead of an index */ | 271 | /* rate index is an MCS rate number instead of an index */ |
272 | IEEE80211_TX_RC_MCS = BIT(3), | 272 | IEEE80211_TX_RC_MCS = BIT(3), |
273 | IEEE80211_TX_RC_GREEN_FIELD = BIT(4), | 273 | IEEE80211_TX_RC_GREEN_FIELD = BIT(4), |
274 | IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), | 274 | IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), |
275 | IEEE80211_TX_RC_DUP_DATA = BIT(6), | 275 | IEEE80211_TX_RC_DUP_DATA = BIT(6), |
276 | IEEE80211_TX_RC_SHORT_GI = BIT(7), | 276 | IEEE80211_TX_RC_SHORT_GI = BIT(7), |
277 | }; | 277 | }; |
278 | 278 | ||
279 | 279 | ||
280 | /* there are 40 bytes if you don't need the rateset to be kept */ | 280 | /* there are 40 bytes if you don't need the rateset to be kept */ |
281 | #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 | 281 | #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 |
282 | 282 | ||
283 | /* if you do need the rateset, then you have less space */ | 283 | /* if you do need the rateset, then you have less space */ |
284 | #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 | 284 | #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 |
285 | 285 | ||
286 | /* maximum number of rate stages */ | 286 | /* maximum number of rate stages */ |
287 | #define IEEE80211_TX_MAX_RATES 5 | 287 | #define IEEE80211_TX_MAX_RATES 5 |
288 | 288 | ||
289 | /** | 289 | /** |
290 | * struct ieee80211_tx_rate - rate selection/status | 290 | * struct ieee80211_tx_rate - rate selection/status |
291 | * | 291 | * |
292 | * @idx: rate index to attempt to send with | 292 | * @idx: rate index to attempt to send with |
293 | * @flags: rate control flags (&enum mac80211_rate_control_flags) | 293 | * @flags: rate control flags (&enum mac80211_rate_control_flags) |
294 | * @limit: number of retries before fallback | 294 | * @limit: number of retries before fallback |
295 | * | 295 | * |
296 | * A value of -1 for @idx indicates an invalid rate and, if used | 296 | * A value of -1 for @idx indicates an invalid rate and, if used |
297 | * in an array of retry rates, that no more rates should be tried. | 297 | * in an array of retry rates, that no more rates should be tried. |
298 | * | 298 | * |
299 | * When used for transmit status reporting, the driver should | 299 | * When used for transmit status reporting, the driver should |
300 | * always report the rate along with the flags it used. | 300 | * always report the rate along with the flags it used. |
301 | */ | 301 | */ |
302 | struct ieee80211_tx_rate { | 302 | struct ieee80211_tx_rate { |
303 | s8 idx; | 303 | s8 idx; |
304 | u8 count; | 304 | u8 count; |
305 | u8 flags; | 305 | u8 flags; |
306 | }; | 306 | }; |
307 | 307 | ||
308 | /** | 308 | /** |
309 | * struct ieee80211_tx_info - skb transmit information | 309 | * struct ieee80211_tx_info - skb transmit information |
310 | * | 310 | * |
311 | * This structure is placed in skb->cb for three uses: | 311 | * This structure is placed in skb->cb for three uses: |
312 | * (1) mac80211 TX control - mac80211 tells the driver what to do | 312 | * (1) mac80211 TX control - mac80211 tells the driver what to do |
313 | * (2) driver internal use (if applicable) | 313 | * (2) driver internal use (if applicable) |
314 | * (3) TX status information - driver tells mac80211 what happened | 314 | * (3) TX status information - driver tells mac80211 what happened |
315 | * | 315 | * |
316 | * The TX control's sta pointer is only valid during the ->tx call, | 316 | * The TX control's sta pointer is only valid during the ->tx call, |
317 | * it may be NULL. | 317 | * it may be NULL. |
318 | * | 318 | * |
319 | * @flags: transmit info flags, defined above | 319 | * @flags: transmit info flags, defined above |
320 | * @band: the band to transmit on (use for checking for races) | 320 | * @band: the band to transmit on (use for checking for races) |
321 | * @antenna_sel_tx: antenna to use, 0 for automatic diversity | 321 | * @antenna_sel_tx: antenna to use, 0 for automatic diversity |
322 | * @control: union for control data | 322 | * @control: union for control data |
323 | * @status: union for status data | 323 | * @status: union for status data |
324 | * @driver_data: array of driver_data pointers | 324 | * @driver_data: array of driver_data pointers |
325 | * @retry_count: number of retries | 325 | * @retry_count: number of retries |
326 | * @ampdu_ack_len: number of aggregated frames. | 326 | * @ampdu_ack_len: number of aggregated frames. |
327 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 327 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
328 | * @ampdu_ack_map: block ack bit map for the aggregation. | 328 | * @ampdu_ack_map: block ack bit map for the aggregation. |
329 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 329 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
330 | * @ack_signal: signal strength of the ACK frame | 330 | * @ack_signal: signal strength of the ACK frame |
331 | */ | 331 | */ |
332 | struct ieee80211_tx_info { | 332 | struct ieee80211_tx_info { |
333 | /* common information */ | 333 | /* common information */ |
334 | u32 flags; | 334 | u32 flags; |
335 | u8 band; | 335 | u8 band; |
336 | 336 | ||
337 | u8 antenna_sel_tx; | 337 | u8 antenna_sel_tx; |
338 | 338 | ||
339 | /* 2 byte hole */ | 339 | /* 2 byte hole */ |
340 | 340 | ||
341 | union { | 341 | union { |
342 | struct { | 342 | struct { |
343 | union { | 343 | union { |
344 | /* rate control */ | 344 | /* rate control */ |
345 | struct { | 345 | struct { |
346 | struct ieee80211_tx_rate rates[ | 346 | struct ieee80211_tx_rate rates[ |
347 | IEEE80211_TX_MAX_RATES]; | 347 | IEEE80211_TX_MAX_RATES]; |
348 | s8 rts_cts_rate_idx; | 348 | s8 rts_cts_rate_idx; |
349 | }; | 349 | }; |
350 | /* only needed before rate control */ | 350 | /* only needed before rate control */ |
351 | unsigned long jiffies; | 351 | unsigned long jiffies; |
352 | }; | 352 | }; |
353 | /* NB: vif can be NULL for injected frames */ | 353 | /* NB: vif can be NULL for injected frames */ |
354 | struct ieee80211_vif *vif; | 354 | struct ieee80211_vif *vif; |
355 | struct ieee80211_key_conf *hw_key; | 355 | struct ieee80211_key_conf *hw_key; |
356 | struct ieee80211_sta *sta; | 356 | struct ieee80211_sta *sta; |
357 | } control; | 357 | } control; |
358 | struct { | 358 | struct { |
359 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; | 359 | struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; |
360 | u8 ampdu_ack_len; | 360 | u8 ampdu_ack_len; |
361 | u64 ampdu_ack_map; | 361 | u64 ampdu_ack_map; |
362 | int ack_signal; | 362 | int ack_signal; |
363 | /* 8 bytes free */ | 363 | /* 8 bytes free */ |
364 | } status; | 364 | } status; |
365 | struct { | 365 | struct { |
366 | struct ieee80211_tx_rate driver_rates[ | 366 | struct ieee80211_tx_rate driver_rates[ |
367 | IEEE80211_TX_MAX_RATES]; | 367 | IEEE80211_TX_MAX_RATES]; |
368 | void *rate_driver_data[ | 368 | void *rate_driver_data[ |
369 | IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)]; | 369 | IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)]; |
370 | }; | 370 | }; |
371 | void *driver_data[ | 371 | void *driver_data[ |
372 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; | 372 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; |
373 | }; | 373 | }; |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) | 376 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) |
377 | { | 377 | { |
378 | return (struct ieee80211_tx_info *)skb->cb; | 378 | return (struct ieee80211_tx_info *)skb->cb; |
379 | } | 379 | } |
380 | 380 | ||
381 | /** | 381 | /** |
382 | * ieee80211_tx_info_clear_status - clear TX status | 382 | * ieee80211_tx_info_clear_status - clear TX status |
383 | * | 383 | * |
384 | * @info: The &struct ieee80211_tx_info to be cleared. | 384 | * @info: The &struct ieee80211_tx_info to be cleared. |
385 | * | 385 | * |
386 | * When the driver passes an skb back to mac80211, it must report | 386 | * When the driver passes an skb back to mac80211, it must report |
387 | * a number of things in TX status. This function clears everything | 387 | * a number of things in TX status. This function clears everything |
388 | * in the TX status but the rate control information (it does clear | 388 | * in the TX status but the rate control information (it does clear |
389 | * the count since you need to fill that in anyway). | 389 | * the count since you need to fill that in anyway). |
390 | * | 390 | * |
391 | * NOTE: You can only use this function if you do NOT use | 391 | * NOTE: You can only use this function if you do NOT use |
392 | * info->driver_data! Use info->rate_driver_data | 392 | * info->driver_data! Use info->rate_driver_data |
393 | * instead if you need only the less space that allows. | 393 | * instead if you need only the less space that allows. |
394 | */ | 394 | */ |
395 | static inline void | 395 | static inline void |
396 | ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | 396 | ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) |
397 | { | 397 | { |
398 | int i; | 398 | int i; |
399 | 399 | ||
400 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != | 400 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != |
401 | offsetof(struct ieee80211_tx_info, control.rates)); | 401 | offsetof(struct ieee80211_tx_info, control.rates)); |
402 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != | 402 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != |
403 | offsetof(struct ieee80211_tx_info, driver_rates)); | 403 | offsetof(struct ieee80211_tx_info, driver_rates)); |
404 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8); | 404 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8); |
405 | /* clear the rate counts */ | 405 | /* clear the rate counts */ |
406 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) | 406 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) |
407 | info->status.rates[i].count = 0; | 407 | info->status.rates[i].count = 0; |
408 | 408 | ||
409 | BUILD_BUG_ON( | 409 | BUILD_BUG_ON( |
410 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); | 410 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); |
411 | memset(&info->status.ampdu_ack_len, 0, | 411 | memset(&info->status.ampdu_ack_len, 0, |
412 | sizeof(struct ieee80211_tx_info) - | 412 | sizeof(struct ieee80211_tx_info) - |
413 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); | 413 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); |
414 | } | 414 | } |
415 | 415 | ||
416 | 416 | ||
417 | /** | 417 | /** |
418 | * enum mac80211_rx_flags - receive flags | 418 | * enum mac80211_rx_flags - receive flags |
419 | * | 419 | * |
420 | * These flags are used with the @flag member of &struct ieee80211_rx_status. | 420 | * These flags are used with the @flag member of &struct ieee80211_rx_status. |
421 | * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame. | 421 | * @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame. |
422 | * Use together with %RX_FLAG_MMIC_STRIPPED. | 422 | * Use together with %RX_FLAG_MMIC_STRIPPED. |
423 | * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. | 423 | * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. |
424 | * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header. | 424 | * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header. |
425 | * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, | 425 | * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, |
426 | * verification has been done by the hardware. | 426 | * verification has been done by the hardware. |
427 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. | 427 | * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. |
428 | * If this flag is set, the stack cannot do any replay detection | 428 | * If this flag is set, the stack cannot do any replay detection |
429 | * hence the driver or hardware will have to do that. | 429 | * hence the driver or hardware will have to do that. |
430 | * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on | 430 | * @RX_FLAG_FAILED_FCS_CRC: Set this flag if the FCS check failed on |
431 | * the frame. | 431 | * the frame. |
432 | * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on | 432 | * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on |
433 | * the frame. | 433 | * the frame. |
434 | * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) | 434 | * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) |
435 | * is valid. This is useful in monitor mode and necessary for beacon frames | 435 | * is valid. This is useful in monitor mode and necessary for beacon frames |
436 | * to enable IBSS merging. | 436 | * to enable IBSS merging. |
437 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame | 437 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame |
438 | */ | 438 | */ |
439 | enum mac80211_rx_flags { | 439 | enum mac80211_rx_flags { |
440 | RX_FLAG_MMIC_ERROR = 1<<0, | 440 | RX_FLAG_MMIC_ERROR = 1<<0, |
441 | RX_FLAG_DECRYPTED = 1<<1, | 441 | RX_FLAG_DECRYPTED = 1<<1, |
442 | RX_FLAG_RADIOTAP = 1<<2, | 442 | RX_FLAG_RADIOTAP = 1<<2, |
443 | RX_FLAG_MMIC_STRIPPED = 1<<3, | 443 | RX_FLAG_MMIC_STRIPPED = 1<<3, |
444 | RX_FLAG_IV_STRIPPED = 1<<4, | 444 | RX_FLAG_IV_STRIPPED = 1<<4, |
445 | RX_FLAG_FAILED_FCS_CRC = 1<<5, | 445 | RX_FLAG_FAILED_FCS_CRC = 1<<5, |
446 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, | 446 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, |
447 | RX_FLAG_TSFT = 1<<7, | 447 | RX_FLAG_TSFT = 1<<7, |
448 | RX_FLAG_SHORTPRE = 1<<8 | 448 | RX_FLAG_SHORTPRE = 1<<8 |
449 | }; | 449 | }; |
450 | 450 | ||
451 | /** | 451 | /** |
452 | * struct ieee80211_rx_status - receive status | 452 | * struct ieee80211_rx_status - receive status |
453 | * | 453 | * |
454 | * The low-level driver should provide this information (the subset | 454 | * The low-level driver should provide this information (the subset |
455 | * supported by hardware) to the 802.11 code with each received | 455 | * supported by hardware) to the 802.11 code with each received |
456 | * frame. | 456 | * frame. |
457 | * | 457 | * |
458 | * @mactime: value in microseconds of the 64-bit Time Synchronization Function | 458 | * @mactime: value in microseconds of the 64-bit Time Synchronization Function |
459 | * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. | 459 | * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. |
460 | * @band: the active band when this frame was received | 460 | * @band: the active band when this frame was received |
461 | * @freq: frequency the radio was tuned to when receiving this frame, in MHz | 461 | * @freq: frequency the radio was tuned to when receiving this frame, in MHz |
462 | * @signal: signal strength when receiving this frame, either in dBm, in dB or | 462 | * @signal: signal strength when receiving this frame, either in dBm, in dB or |
463 | * unspecified depending on the hardware capabilities flags | 463 | * unspecified depending on the hardware capabilities flags |
464 | * @IEEE80211_HW_SIGNAL_* | 464 | * @IEEE80211_HW_SIGNAL_* |
465 | * @noise: noise when receiving this frame, in dBm. | 465 | * @noise: noise when receiving this frame, in dBm. |
466 | * @qual: overall signal quality indication, in percent (0-100). | 466 | * @qual: overall signal quality indication, in percent (0-100). |
467 | * @antenna: antenna used | 467 | * @antenna: antenna used |
468 | * @rate_idx: index of data rate into band's supported rates | 468 | * @rate_idx: index of data rate into band's supported rates |
469 | * @flag: %RX_FLAG_* | 469 | * @flag: %RX_FLAG_* |
470 | */ | 470 | */ |
471 | struct ieee80211_rx_status { | 471 | struct ieee80211_rx_status { |
472 | u64 mactime; | 472 | u64 mactime; |
473 | enum ieee80211_band band; | 473 | enum ieee80211_band band; |
474 | int freq; | 474 | int freq; |
475 | int signal; | 475 | int signal; |
476 | int noise; | 476 | int noise; |
477 | int qual; | 477 | int qual; |
478 | int antenna; | 478 | int antenna; |
479 | int rate_idx; | 479 | int rate_idx; |
480 | int flag; | 480 | int flag; |
481 | }; | 481 | }; |
482 | 482 | ||
483 | /** | 483 | /** |
484 | * enum ieee80211_conf_flags - configuration flags | 484 | * enum ieee80211_conf_flags - configuration flags |
485 | * | 485 | * |
486 | * Flags to define PHY configuration options | 486 | * Flags to define PHY configuration options |
487 | * | 487 | * |
488 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) | 488 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) |
489 | * @IEEE80211_CONF_PS: Enable 802.11 power save mode | 489 | * @IEEE80211_CONF_PS: Enable 802.11 power save mode |
490 | */ | 490 | */ |
491 | enum ieee80211_conf_flags { | 491 | enum ieee80211_conf_flags { |
492 | IEEE80211_CONF_RADIOTAP = (1<<0), | 492 | IEEE80211_CONF_RADIOTAP = (1<<0), |
493 | IEEE80211_CONF_PS = (1<<1), | 493 | IEEE80211_CONF_PS = (1<<1), |
494 | }; | 494 | }; |
495 | 495 | ||
496 | /* XXX: remove all this once drivers stop trying to use it */ | 496 | /* XXX: remove all this once drivers stop trying to use it */ |
497 | static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) | 497 | static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) |
498 | { | 498 | { |
499 | return 0; | 499 | return 0; |
500 | } | 500 | } |
501 | #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) | 501 | #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) |
502 | 502 | ||
503 | struct ieee80211_ht_conf { | 503 | struct ieee80211_ht_conf { |
504 | bool enabled; | 504 | bool enabled; |
505 | }; | 505 | }; |
506 | 506 | ||
507 | /** | 507 | /** |
508 | * enum ieee80211_conf_changed - denotes which configuration changed | 508 | * enum ieee80211_conf_changed - denotes which configuration changed |
509 | * | 509 | * |
510 | * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed | 510 | * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed |
511 | * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed | 511 | * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed |
512 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed | 512 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed |
513 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed | 513 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed |
514 | * @IEEE80211_CONF_CHANGE_PS: the PS flag changed | 514 | * @IEEE80211_CONF_CHANGE_PS: the PS flag changed |
515 | * @IEEE80211_CONF_CHANGE_POWER: the TX power changed | 515 | * @IEEE80211_CONF_CHANGE_POWER: the TX power changed |
516 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed | 516 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed |
517 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed | 517 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed |
518 | * @IEEE80211_CONF_CHANGE_HT: HT configuration changed | 518 | * @IEEE80211_CONF_CHANGE_HT: HT configuration changed |
519 | */ | 519 | */ |
520 | enum ieee80211_conf_changed { | 520 | enum ieee80211_conf_changed { |
521 | IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), | 521 | IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), |
522 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), | 522 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), |
523 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), | 523 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), |
524 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), | 524 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), |
525 | IEEE80211_CONF_CHANGE_PS = BIT(4), | 525 | IEEE80211_CONF_CHANGE_PS = BIT(4), |
526 | IEEE80211_CONF_CHANGE_POWER = BIT(5), | 526 | IEEE80211_CONF_CHANGE_POWER = BIT(5), |
527 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), | 527 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), |
528 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), | 528 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), |
529 | IEEE80211_CONF_CHANGE_HT = BIT(8), | 529 | IEEE80211_CONF_CHANGE_HT = BIT(8), |
530 | }; | 530 | }; |
531 | 531 | ||
532 | /** | 532 | /** |
533 | * struct ieee80211_conf - configuration of the device | 533 | * struct ieee80211_conf - configuration of the device |
534 | * | 534 | * |
535 | * This struct indicates how the driver shall configure the hardware. | 535 | * This struct indicates how the driver shall configure the hardware. |
536 | * | 536 | * |
537 | * @radio_enabled: when zero, driver is required to switch off the radio. | 537 | * @radio_enabled: when zero, driver is required to switch off the radio. |
538 | * @beacon_int: beacon interval (TODO make interface config) | 538 | * @beacon_int: beacon interval (TODO make interface config) |
539 | * @listen_interval: listen interval in units of beacon interval | 539 | * @listen_interval: listen interval in units of beacon interval |
540 | * @flags: configuration flags defined above | 540 | * @flags: configuration flags defined above |
541 | * @power_level: requested transmit power (in dBm) | 541 | * @power_level: requested transmit power (in dBm) |
542 | * @channel: the channel to tune to | 542 | * @channel: the channel to tune to |
543 | * @ht: the HT configuration for the device | 543 | * @ht: the HT configuration for the device |
544 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame | 544 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame |
545 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, | 545 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, |
546 | * but actually means the number of transmissions not the number of retries | 546 | * but actually means the number of transmissions not the number of retries |
547 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" | 547 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" |
548 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the | 548 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the |
549 | * number of transmissions not the number of retries | 549 | * number of transmissions not the number of retries |
550 | */ | 550 | */ |
551 | struct ieee80211_conf { | 551 | struct ieee80211_conf { |
552 | int beacon_int; | 552 | int beacon_int; |
553 | u32 flags; | 553 | u32 flags; |
554 | int power_level; | 554 | int power_level; |
555 | 555 | ||
556 | u16 listen_interval; | 556 | u16 listen_interval; |
557 | bool radio_enabled; | 557 | bool radio_enabled; |
558 | 558 | ||
559 | u8 long_frame_max_tx_count, short_frame_max_tx_count; | 559 | u8 long_frame_max_tx_count, short_frame_max_tx_count; |
560 | 560 | ||
561 | struct ieee80211_channel *channel; | 561 | struct ieee80211_channel *channel; |
562 | struct ieee80211_ht_conf ht; | 562 | struct ieee80211_ht_conf ht; |
563 | }; | 563 | }; |
564 | 564 | ||
565 | /** | 565 | /** |
566 | * struct ieee80211_vif - per-interface data | 566 | * struct ieee80211_vif - per-interface data |
567 | * | 567 | * |
568 | * Data in this structure is continually present for driver | 568 | * Data in this structure is continually present for driver |
569 | * use during the life of a virtual interface. | 569 | * use during the life of a virtual interface. |
570 | * | 570 | * |
571 | * @type: type of this virtual interface | 571 | * @type: type of this virtual interface |
572 | * @bss_conf: BSS configuration for this interface, either our own | 572 | * @bss_conf: BSS configuration for this interface, either our own |
573 | * or the BSS we're associated to | 573 | * or the BSS we're associated to |
574 | * @drv_priv: data area for driver use, will always be aligned to | 574 | * @drv_priv: data area for driver use, will always be aligned to |
575 | * sizeof(void *). | 575 | * sizeof(void *). |
576 | */ | 576 | */ |
577 | struct ieee80211_vif { | 577 | struct ieee80211_vif { |
578 | enum nl80211_iftype type; | 578 | enum nl80211_iftype type; |
579 | struct ieee80211_bss_conf bss_conf; | 579 | struct ieee80211_bss_conf bss_conf; |
580 | /* must be last */ | 580 | /* must be last */ |
581 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 581 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
582 | }; | 582 | }; |
583 | 583 | ||
584 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | 584 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) |
585 | { | 585 | { |
586 | #ifdef CONFIG_MAC80211_MESH | 586 | #ifdef CONFIG_MAC80211_MESH |
587 | return vif->type == NL80211_IFTYPE_MESH_POINT; | 587 | return vif->type == NL80211_IFTYPE_MESH_POINT; |
588 | #endif | 588 | #endif |
589 | return false; | 589 | return false; |
590 | } | 590 | } |
591 | 591 | ||
592 | /** | 592 | /** |
593 | * struct ieee80211_if_init_conf - initial configuration of an interface | 593 | * struct ieee80211_if_init_conf - initial configuration of an interface |
594 | * | 594 | * |
595 | * @vif: pointer to a driver-use per-interface structure. The pointer | 595 | * @vif: pointer to a driver-use per-interface structure. The pointer |
596 | * itself is also used for various functions including | 596 | * itself is also used for various functions including |
597 | * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). | 597 | * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). |
598 | * @type: one of &enum nl80211_iftype constants. Determines the type of | 598 | * @type: one of &enum nl80211_iftype constants. Determines the type of |
599 | * added/removed interface. | 599 | * added/removed interface. |
600 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | 600 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid |
601 | * until the interface is removed (i.e. it cannot be used after | 601 | * until the interface is removed (i.e. it cannot be used after |
602 | * remove_interface() callback was called for this interface). | 602 | * remove_interface() callback was called for this interface). |
603 | * | 603 | * |
604 | * This structure is used in add_interface() and remove_interface() | 604 | * This structure is used in add_interface() and remove_interface() |
605 | * callbacks of &struct ieee80211_hw. | 605 | * callbacks of &struct ieee80211_hw. |
606 | * | 606 | * |
607 | * When you allow multiple interfaces to be added to your PHY, take care | 607 | * When you allow multiple interfaces to be added to your PHY, take care |
608 | * that the hardware can actually handle multiple MAC addresses. However, | 608 | * that the hardware can actually handle multiple MAC addresses. However, |
609 | * also take care that when there's no interface left with mac_addr != %NULL | 609 | * also take care that when there's no interface left with mac_addr != %NULL |
610 | * you remove the MAC address from the device to avoid acknowledging packets | 610 | * you remove the MAC address from the device to avoid acknowledging packets |
611 | * in pure monitor mode. | 611 | * in pure monitor mode. |
612 | */ | 612 | */ |
613 | struct ieee80211_if_init_conf { | 613 | struct ieee80211_if_init_conf { |
614 | enum nl80211_iftype type; | 614 | enum nl80211_iftype type; |
615 | struct ieee80211_vif *vif; | 615 | struct ieee80211_vif *vif; |
616 | void *mac_addr; | 616 | void *mac_addr; |
617 | }; | 617 | }; |
618 | 618 | ||
619 | /** | 619 | /** |
620 | * enum ieee80211_if_conf_change - interface config change flags | 620 | * enum ieee80211_if_conf_change - interface config change flags |
621 | * | 621 | * |
622 | * @IEEE80211_IFCC_BSSID: The BSSID changed. | 622 | * @IEEE80211_IFCC_BSSID: The BSSID changed. |
623 | * @IEEE80211_IFCC_SSID: The SSID changed. | 623 | * @IEEE80211_IFCC_SSID: The SSID changed. |
624 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed | 624 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed |
625 | * (currently AP and MESH only), use ieee80211_beacon_get(). | 625 | * (currently AP and MESH only), use ieee80211_beacon_get(). |
626 | */ | 626 | */ |
627 | enum ieee80211_if_conf_change { | 627 | enum ieee80211_if_conf_change { |
628 | IEEE80211_IFCC_BSSID = BIT(0), | 628 | IEEE80211_IFCC_BSSID = BIT(0), |
629 | IEEE80211_IFCC_SSID = BIT(1), | 629 | IEEE80211_IFCC_SSID = BIT(1), |
630 | IEEE80211_IFCC_BEACON = BIT(2), | 630 | IEEE80211_IFCC_BEACON = BIT(2), |
631 | }; | 631 | }; |
632 | 632 | ||
633 | /** | 633 | /** |
634 | * struct ieee80211_if_conf - configuration of an interface | 634 | * struct ieee80211_if_conf - configuration of an interface |
635 | * | 635 | * |
636 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. | 636 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. |
637 | * @bssid: BSSID of the network we are associated to/creating. | 637 | * @bssid: BSSID of the network we are associated to/creating. |
638 | * @ssid: used (together with @ssid_len) by drivers for hardware that | 638 | * @ssid: used (together with @ssid_len) by drivers for hardware that |
639 | * generate beacons independently. The pointer is valid only during the | 639 | * generate beacons independently. The pointer is valid only during the |
640 | * config_interface() call, so copy the value somewhere if you need | 640 | * config_interface() call, so copy the value somewhere if you need |
641 | * it. | 641 | * it. |
642 | * @ssid_len: length of the @ssid field. | 642 | * @ssid_len: length of the @ssid field. |
643 | * | 643 | * |
644 | * This structure is passed to the config_interface() callback of | 644 | * This structure is passed to the config_interface() callback of |
645 | * &struct ieee80211_hw. | 645 | * &struct ieee80211_hw. |
646 | */ | 646 | */ |
647 | struct ieee80211_if_conf { | 647 | struct ieee80211_if_conf { |
648 | u32 changed; | 648 | u32 changed; |
649 | u8 *bssid; | 649 | u8 *bssid; |
650 | u8 *ssid; | 650 | u8 *ssid; |
651 | size_t ssid_len; | 651 | size_t ssid_len; |
652 | }; | 652 | }; |
653 | 653 | ||
654 | /** | 654 | /** |
655 | * enum ieee80211_key_alg - key algorithm | 655 | * enum ieee80211_key_alg - key algorithm |
656 | * @ALG_WEP: WEP40 or WEP104 | 656 | * @ALG_WEP: WEP40 or WEP104 |
657 | * @ALG_TKIP: TKIP | 657 | * @ALG_TKIP: TKIP |
658 | * @ALG_CCMP: CCMP (AES) | 658 | * @ALG_CCMP: CCMP (AES) |
659 | */ | 659 | */ |
660 | enum ieee80211_key_alg { | 660 | enum ieee80211_key_alg { |
661 | ALG_WEP, | 661 | ALG_WEP, |
662 | ALG_TKIP, | 662 | ALG_TKIP, |
663 | ALG_CCMP, | 663 | ALG_CCMP, |
664 | }; | 664 | }; |
665 | 665 | ||
666 | /** | 666 | /** |
667 | * enum ieee80211_key_len - key length | 667 | * enum ieee80211_key_len - key length |
668 | * @LEN_WEP40: WEP 5-byte long key | 668 | * @LEN_WEP40: WEP 5-byte long key |
669 | * @LEN_WEP104: WEP 13-byte long key | 669 | * @LEN_WEP104: WEP 13-byte long key |
670 | */ | 670 | */ |
671 | enum ieee80211_key_len { | 671 | enum ieee80211_key_len { |
672 | LEN_WEP40 = 5, | 672 | LEN_WEP40 = 5, |
673 | LEN_WEP104 = 13, | 673 | LEN_WEP104 = 13, |
674 | }; | 674 | }; |
675 | 675 | ||
676 | /** | 676 | /** |
677 | * enum ieee80211_key_flags - key flags | 677 | * enum ieee80211_key_flags - key flags |
678 | * | 678 | * |
679 | * These flags are used for communication about keys between the driver | 679 | * These flags are used for communication about keys between the driver |
680 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. | 680 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. |
681 | * | 681 | * |
682 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates | 682 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates |
683 | * that the STA this key will be used with could be using QoS. | 683 | * that the STA this key will be used with could be using QoS. |
684 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the | 684 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the |
685 | * driver to indicate that it requires IV generation for this | 685 | * driver to indicate that it requires IV generation for this |
686 | * particular key. | 686 | * particular key. |
687 | * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by | 687 | * @IEEE80211_KEY_FLAG_GENERATE_MMIC: This flag should be set by |
688 | * the driver for a TKIP key if it requires Michael MIC | 688 | * the driver for a TKIP key if it requires Michael MIC |
689 | * generation in software. | 689 | * generation in software. |
690 | * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates | 690 | * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates |
691 | * that the key is pairwise rather then a shared key. | 691 | * that the key is pairwise rather then a shared key. |
692 | */ | 692 | */ |
693 | enum ieee80211_key_flags { | 693 | enum ieee80211_key_flags { |
694 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, | 694 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, |
695 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, | 695 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, |
696 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, | 696 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, |
697 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, | 697 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, |
698 | }; | 698 | }; |
699 | 699 | ||
700 | /** | 700 | /** |
701 | * struct ieee80211_key_conf - key information | 701 | * struct ieee80211_key_conf - key information |
702 | * | 702 | * |
703 | * This key information is given by mac80211 to the driver by | 703 | * This key information is given by mac80211 to the driver by |
704 | * the set_key() callback in &struct ieee80211_ops. | 704 | * the set_key() callback in &struct ieee80211_ops. |
705 | * | 705 | * |
706 | * @hw_key_idx: To be set by the driver, this is the key index the driver | 706 | * @hw_key_idx: To be set by the driver, this is the key index the driver |
707 | * wants to be given when a frame is transmitted and needs to be | 707 | * wants to be given when a frame is transmitted and needs to be |
708 | * encrypted in hardware. | 708 | * encrypted in hardware. |
709 | * @alg: The key algorithm. | 709 | * @alg: The key algorithm. |
710 | * @flags: key flags, see &enum ieee80211_key_flags. | 710 | * @flags: key flags, see &enum ieee80211_key_flags. |
711 | * @keyidx: the key index (0-3) | 711 | * @keyidx: the key index (0-3) |
712 | * @keylen: key material length | 712 | * @keylen: key material length |
713 | * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) | 713 | * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) |
714 | * data block: | 714 | * data block: |
715 | * - Temporal Encryption Key (128 bits) | 715 | * - Temporal Encryption Key (128 bits) |
716 | * - Temporal Authenticator Tx MIC Key (64 bits) | 716 | * - Temporal Authenticator Tx MIC Key (64 bits) |
717 | * - Temporal Authenticator Rx MIC Key (64 bits) | 717 | * - Temporal Authenticator Rx MIC Key (64 bits) |
718 | * @icv_len: FIXME | 718 | * @icv_len: FIXME |
719 | * @iv_len: FIXME | 719 | * @iv_len: FIXME |
720 | */ | 720 | */ |
721 | struct ieee80211_key_conf { | 721 | struct ieee80211_key_conf { |
722 | enum ieee80211_key_alg alg; | 722 | enum ieee80211_key_alg alg; |
723 | u8 icv_len; | 723 | u8 icv_len; |
724 | u8 iv_len; | 724 | u8 iv_len; |
725 | u8 hw_key_idx; | 725 | u8 hw_key_idx; |
726 | u8 flags; | 726 | u8 flags; |
727 | s8 keyidx; | 727 | s8 keyidx; |
728 | u8 keylen; | 728 | u8 keylen; |
729 | u8 key[0]; | 729 | u8 key[0]; |
730 | }; | 730 | }; |
731 | 731 | ||
732 | /** | 732 | /** |
733 | * enum set_key_cmd - key command | 733 | * enum set_key_cmd - key command |
734 | * | 734 | * |
735 | * Used with the set_key() callback in &struct ieee80211_ops, this | 735 | * Used with the set_key() callback in &struct ieee80211_ops, this |
736 | * indicates whether a key is being removed or added. | 736 | * indicates whether a key is being removed or added. |
737 | * | 737 | * |
738 | * @SET_KEY: a key is set | 738 | * @SET_KEY: a key is set |
739 | * @DISABLE_KEY: a key must be disabled | 739 | * @DISABLE_KEY: a key must be disabled |
740 | */ | 740 | */ |
741 | enum set_key_cmd { | 741 | enum set_key_cmd { |
742 | SET_KEY, DISABLE_KEY, | 742 | SET_KEY, DISABLE_KEY, |
743 | }; | 743 | }; |
744 | 744 | ||
745 | /** | 745 | /** |
746 | * struct ieee80211_sta - station table entry | 746 | * struct ieee80211_sta - station table entry |
747 | * | 747 | * |
748 | * A station table entry represents a station we are possibly | 748 | * A station table entry represents a station we are possibly |
749 | * communicating with. Since stations are RCU-managed in | 749 | * communicating with. Since stations are RCU-managed in |
750 | * mac80211, any ieee80211_sta pointer you get access to must | 750 | * mac80211, any ieee80211_sta pointer you get access to must |
751 | * either be protected by rcu_read_lock() explicitly or implicitly, | 751 | * either be protected by rcu_read_lock() explicitly or implicitly, |
752 | * or you must take good care to not use such a pointer after a | 752 | * or you must take good care to not use such a pointer after a |
753 | * call to your sta_notify callback that removed it. | 753 | * call to your sta_notify callback that removed it. |
754 | * | 754 | * |
755 | * @addr: MAC address | 755 | * @addr: MAC address |
756 | * @aid: AID we assigned to the station if we're an AP | 756 | * @aid: AID we assigned to the station if we're an AP |
757 | * @supp_rates: Bitmap of supported rates (per band) | 757 | * @supp_rates: Bitmap of supported rates (per band) |
758 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities | 758 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities |
759 | * @drv_priv: data area for driver use, will always be aligned to | 759 | * @drv_priv: data area for driver use, will always be aligned to |
760 | * sizeof(void *), size is determined in hw information. | 760 | * sizeof(void *), size is determined in hw information. |
761 | */ | 761 | */ |
762 | struct ieee80211_sta { | 762 | struct ieee80211_sta { |
763 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 763 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
764 | u8 addr[ETH_ALEN]; | 764 | u8 addr[ETH_ALEN]; |
765 | u16 aid; | 765 | u16 aid; |
766 | struct ieee80211_sta_ht_cap ht_cap; | 766 | struct ieee80211_sta_ht_cap ht_cap; |
767 | 767 | ||
768 | /* must be last */ | 768 | /* must be last */ |
769 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 769 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
770 | }; | 770 | }; |
771 | 771 | ||
772 | /** | 772 | /** |
773 | * enum sta_notify_cmd - sta notify command | 773 | * enum sta_notify_cmd - sta notify command |
774 | * | 774 | * |
775 | * Used with the sta_notify() callback in &struct ieee80211_ops, this | 775 | * Used with the sta_notify() callback in &struct ieee80211_ops, this |
776 | * indicates addition and removal of a station to station table. | 776 | * indicates addition and removal of a station to station table. |
777 | * | 777 | * |
778 | * @STA_NOTIFY_ADD: a station was added to the station table | 778 | * @STA_NOTIFY_ADD: a station was added to the station table |
779 | * @STA_NOTIFY_REMOVE: a station being removed from the station table | 779 | * @STA_NOTIFY_REMOVE: a station being removed from the station table |
780 | */ | 780 | */ |
781 | enum sta_notify_cmd { | 781 | enum sta_notify_cmd { |
782 | STA_NOTIFY_ADD, STA_NOTIFY_REMOVE | 782 | STA_NOTIFY_ADD, STA_NOTIFY_REMOVE |
783 | }; | 783 | }; |
784 | 784 | ||
785 | /** | 785 | /** |
786 | * enum ieee80211_tkip_key_type - get tkip key | 786 | * enum ieee80211_tkip_key_type - get tkip key |
787 | * | 787 | * |
788 | * Used by drivers which need to get a tkip key for skb. Some drivers need a | 788 | * Used by drivers which need to get a tkip key for skb. Some drivers need a |
789 | * phase 1 key, others need a phase 2 key. A single function allows the driver | 789 | * phase 1 key, others need a phase 2 key. A single function allows the driver |
790 | * to get the key, this enum indicates what type of key is required. | 790 | * to get the key, this enum indicates what type of key is required. |
791 | * | 791 | * |
792 | * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key | 792 | * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key |
793 | * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key | 793 | * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key |
794 | */ | 794 | */ |
795 | enum ieee80211_tkip_key_type { | 795 | enum ieee80211_tkip_key_type { |
796 | IEEE80211_TKIP_P1_KEY, | 796 | IEEE80211_TKIP_P1_KEY, |
797 | IEEE80211_TKIP_P2_KEY, | 797 | IEEE80211_TKIP_P2_KEY, |
798 | }; | 798 | }; |
799 | 799 | ||
800 | /** | 800 | /** |
801 | * enum ieee80211_hw_flags - hardware flags | 801 | * enum ieee80211_hw_flags - hardware flags |
802 | * | 802 | * |
803 | * These flags are used to indicate hardware capabilities to | 803 | * These flags are used to indicate hardware capabilities to |
804 | * the stack. Generally, flags here should have their meaning | 804 | * the stack. Generally, flags here should have their meaning |
805 | * done in a way that the simplest hardware doesn't need setting | 805 | * done in a way that the simplest hardware doesn't need setting |
806 | * any particular flags. There are some exceptions to this rule, | 806 | * any particular flags. There are some exceptions to this rule, |
807 | * however, so you are advised to review these flags carefully. | 807 | * however, so you are advised to review these flags carefully. |
808 | * | 808 | * |
809 | * @IEEE80211_HW_RX_INCLUDES_FCS: | 809 | * @IEEE80211_HW_RX_INCLUDES_FCS: |
810 | * Indicates that received frames passed to the stack include | 810 | * Indicates that received frames passed to the stack include |
811 | * the FCS at the end. | 811 | * the FCS at the end. |
812 | * | 812 | * |
813 | * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING: | 813 | * @IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING: |
814 | * Some wireless LAN chipsets buffer broadcast/multicast frames | 814 | * Some wireless LAN chipsets buffer broadcast/multicast frames |
815 | * for power saving stations in the hardware/firmware and others | 815 | * for power saving stations in the hardware/firmware and others |
816 | * rely on the host system for such buffering. This option is used | 816 | * rely on the host system for such buffering. This option is used |
817 | * to configure the IEEE 802.11 upper layer to buffer broadcast and | 817 | * to configure the IEEE 802.11 upper layer to buffer broadcast and |
818 | * multicast frames when there are power saving stations so that | 818 | * multicast frames when there are power saving stations so that |
819 | * the driver can fetch them with ieee80211_get_buffered_bc(). | 819 | * the driver can fetch them with ieee80211_get_buffered_bc(). |
820 | * | 820 | * |
821 | * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: | 821 | * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: |
822 | * Hardware is not capable of short slot operation on the 2.4 GHz band. | 822 | * Hardware is not capable of short slot operation on the 2.4 GHz band. |
823 | * | 823 | * |
824 | * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE: | 824 | * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE: |
825 | * Hardware is not capable of receiving frames with short preamble on | 825 | * Hardware is not capable of receiving frames with short preamble on |
826 | * the 2.4 GHz band. | 826 | * the 2.4 GHz band. |
827 | * | 827 | * |
828 | * @IEEE80211_HW_SIGNAL_UNSPEC: | 828 | * @IEEE80211_HW_SIGNAL_UNSPEC: |
829 | * Hardware can provide signal values but we don't know its units. We | 829 | * Hardware can provide signal values but we don't know its units. We |
830 | * expect values between 0 and @max_signal. | 830 | * expect values between 0 and @max_signal. |
831 | * If possible please provide dB or dBm instead. | 831 | * If possible please provide dB or dBm instead. |
832 | * | 832 | * |
833 | * @IEEE80211_HW_SIGNAL_DB: | 833 | * @IEEE80211_HW_SIGNAL_DB: |
834 | * Hardware gives signal values in dB, decibel difference from an | 834 | * Hardware gives signal values in dB, decibel difference from an |
835 | * arbitrary, fixed reference. We expect values between 0 and @max_signal. | 835 | * arbitrary, fixed reference. We expect values between 0 and @max_signal. |
836 | * If possible please provide dBm instead. | 836 | * If possible please provide dBm instead. |
837 | * | 837 | * |
838 | * @IEEE80211_HW_SIGNAL_DBM: | 838 | * @IEEE80211_HW_SIGNAL_DBM: |
839 | * Hardware gives signal values in dBm, decibel difference from | 839 | * Hardware gives signal values in dBm, decibel difference from |
840 | * one milliwatt. This is the preferred method since it is standardized | 840 | * one milliwatt. This is the preferred method since it is standardized |
841 | * between different devices. @max_signal does not need to be set. | 841 | * between different devices. @max_signal does not need to be set. |
842 | * | 842 | * |
843 | * @IEEE80211_HW_NOISE_DBM: | 843 | * @IEEE80211_HW_NOISE_DBM: |
844 | * Hardware can provide noise (radio interference) values in units dBm, | 844 | * Hardware can provide noise (radio interference) values in units dBm, |
845 | * decibel difference from one milliwatt. | 845 | * decibel difference from one milliwatt. |
846 | * | 846 | * |
847 | * @IEEE80211_HW_SPECTRUM_MGMT: | 847 | * @IEEE80211_HW_SPECTRUM_MGMT: |
848 | * Hardware supports spectrum management defined in 802.11h | 848 | * Hardware supports spectrum management defined in 802.11h |
849 | * Measurement, Channel Switch, Quieting, TPC | 849 | * Measurement, Channel Switch, Quieting, TPC |
850 | */ | 850 | */ |
851 | enum ieee80211_hw_flags { | 851 | enum ieee80211_hw_flags { |
852 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, | 852 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, |
853 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, | 853 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, |
854 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, | 854 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, |
855 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, | 855 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, |
856 | IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, | 856 | IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, |
857 | IEEE80211_HW_SIGNAL_DB = 1<<6, | 857 | IEEE80211_HW_SIGNAL_DB = 1<<6, |
858 | IEEE80211_HW_SIGNAL_DBM = 1<<7, | 858 | IEEE80211_HW_SIGNAL_DBM = 1<<7, |
859 | IEEE80211_HW_NOISE_DBM = 1<<8, | 859 | IEEE80211_HW_NOISE_DBM = 1<<8, |
860 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, | 860 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, |
861 | }; | 861 | }; |
862 | 862 | ||
863 | /** | 863 | /** |
864 | * struct ieee80211_hw - hardware information and state | 864 | * struct ieee80211_hw - hardware information and state |
865 | * | 865 | * |
866 | * This structure contains the configuration and hardware | 866 | * This structure contains the configuration and hardware |
867 | * information for an 802.11 PHY. | 867 | * information for an 802.11 PHY. |
868 | * | 868 | * |
869 | * @wiphy: This points to the &struct wiphy allocated for this | 869 | * @wiphy: This points to the &struct wiphy allocated for this |
870 | * 802.11 PHY. You must fill in the @perm_addr and @dev | 870 | * 802.11 PHY. You must fill in the @perm_addr and @dev |
871 | * members of this structure using SET_IEEE80211_DEV() | 871 | * members of this structure using SET_IEEE80211_DEV() |
872 | * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported | 872 | * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported |
873 | * bands (with channels, bitrates) are registered here. | 873 | * bands (with channels, bitrates) are registered here. |
874 | * | 874 | * |
875 | * @conf: &struct ieee80211_conf, device configuration, don't use. | 875 | * @conf: &struct ieee80211_conf, device configuration, don't use. |
876 | * | 876 | * |
877 | * @workqueue: single threaded workqueue available for driver use, | 877 | * @workqueue: single threaded workqueue available for driver use, |
878 | * allocated by mac80211 on registration and flushed when an | 878 | * allocated by mac80211 on registration and flushed when an |
879 | * interface is removed. | 879 | * interface is removed. |
880 | * NOTICE: All work performed on this workqueue should NEVER | 880 | * NOTICE: All work performed on this workqueue should NEVER |
881 | * acquire the RTNL lock (i.e. Don't use the function | 881 | * acquire the RTNL lock (i.e. Don't use the function |
882 | * ieee80211_iterate_active_interfaces()) | 882 | * ieee80211_iterate_active_interfaces()) |
883 | * | 883 | * |
884 | * @priv: pointer to private area that was allocated for driver use | 884 | * @priv: pointer to private area that was allocated for driver use |
885 | * along with this structure. | 885 | * along with this structure. |
886 | * | 886 | * |
887 | * @flags: hardware flags, see &enum ieee80211_hw_flags. | 887 | * @flags: hardware flags, see &enum ieee80211_hw_flags. |
888 | * | 888 | * |
889 | * @extra_tx_headroom: headroom to reserve in each transmit skb | 889 | * @extra_tx_headroom: headroom to reserve in each transmit skb |
890 | * for use by the driver (e.g. for transmit headers.) | 890 | * for use by the driver (e.g. for transmit headers.) |
891 | * | 891 | * |
892 | * @channel_change_time: time (in microseconds) it takes to change channels. | 892 | * @channel_change_time: time (in microseconds) it takes to change channels. |
893 | * | 893 | * |
894 | * @max_signal: Maximum value for signal (rssi) in RX information, used | 894 | * @max_signal: Maximum value for signal (rssi) in RX information, used |
895 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB | 895 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB |
896 | * | 896 | * |
897 | * @max_listen_interval: max listen interval in units of beacon interval | 897 | * @max_listen_interval: max listen interval in units of beacon interval |
898 | * that HW supports | 898 | * that HW supports |
899 | * | 899 | * |
900 | * @queues: number of available hardware transmit queues for | 900 | * @queues: number of available hardware transmit queues for |
901 | * data packets. WMM/QoS requires at least four, these | 901 | * data packets. WMM/QoS requires at least four, these |
902 | * queues need to have configurable access parameters. | 902 | * queues need to have configurable access parameters. |
903 | * | 903 | * |
904 | * @ampdu_queues: number of available hardware transmit queues | 904 | * @ampdu_queues: number of available hardware transmit queues |
905 | * for A-MPDU packets, these have no access parameters | 905 | * for A-MPDU packets, these have no access parameters |
906 | * because they're used only for A-MPDU frames. Note that | 906 | * because they're used only for A-MPDU frames. Note that |
907 | * mac80211 will not currently use any of the regular queues | 907 | * mac80211 will not currently use any of the regular queues |
908 | * for aggregation. | 908 | * for aggregation. |
909 | * | 909 | * |
910 | * @rate_control_algorithm: rate control algorithm for this hardware. | 910 | * @rate_control_algorithm: rate control algorithm for this hardware. |
911 | * If unset (NULL), the default algorithm will be used. Must be | 911 | * If unset (NULL), the default algorithm will be used. Must be |
912 | * set before calling ieee80211_register_hw(). | 912 | * set before calling ieee80211_register_hw(). |
913 | * | 913 | * |
914 | * @vif_data_size: size (in bytes) of the drv_priv data area | 914 | * @vif_data_size: size (in bytes) of the drv_priv data area |
915 | * within &struct ieee80211_vif. | 915 | * within &struct ieee80211_vif. |
916 | * @sta_data_size: size (in bytes) of the drv_priv data area | 916 | * @sta_data_size: size (in bytes) of the drv_priv data area |
917 | * within &struct ieee80211_sta. | 917 | * within &struct ieee80211_sta. |
918 | * | 918 | * |
919 | * @max_rates: maximum number of alternate rate retry stages | 919 | * @max_rates: maximum number of alternate rate retry stages |
920 | * @max_rate_tries: maximum number of tries for each stage | 920 | * @max_rate_tries: maximum number of tries for each stage |
921 | */ | 921 | */ |
922 | struct ieee80211_hw { | 922 | struct ieee80211_hw { |
923 | struct ieee80211_conf conf; | 923 | struct ieee80211_conf conf; |
924 | struct wiphy *wiphy; | 924 | struct wiphy *wiphy; |
925 | struct workqueue_struct *workqueue; | 925 | struct workqueue_struct *workqueue; |
926 | const char *rate_control_algorithm; | 926 | const char *rate_control_algorithm; |
927 | void *priv; | 927 | void *priv; |
928 | u32 flags; | 928 | u32 flags; |
929 | unsigned int extra_tx_headroom; | 929 | unsigned int extra_tx_headroom; |
930 | int channel_change_time; | 930 | int channel_change_time; |
931 | int vif_data_size; | 931 | int vif_data_size; |
932 | int sta_data_size; | 932 | int sta_data_size; |
933 | u16 queues; | 933 | u16 queues; |
934 | u16 ampdu_queues; | 934 | u16 ampdu_queues; |
935 | u16 max_listen_interval; | 935 | u16 max_listen_interval; |
936 | s8 max_signal; | 936 | s8 max_signal; |
937 | u8 max_rates; | 937 | u8 max_rates; |
938 | u8 max_rate_tries; | 938 | u8 max_rate_tries; |
939 | }; | 939 | }; |
940 | 940 | ||
941 | /** | 941 | /** |
942 | * SET_IEEE80211_DEV - set device for 802.11 hardware | 942 | * SET_IEEE80211_DEV - set device for 802.11 hardware |
943 | * | 943 | * |
944 | * @hw: the &struct ieee80211_hw to set the device for | 944 | * @hw: the &struct ieee80211_hw to set the device for |
945 | * @dev: the &struct device of this 802.11 device | 945 | * @dev: the &struct device of this 802.11 device |
946 | */ | 946 | */ |
947 | static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) | 947 | static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) |
948 | { | 948 | { |
949 | set_wiphy_dev(hw->wiphy, dev); | 949 | set_wiphy_dev(hw->wiphy, dev); |
950 | } | 950 | } |
951 | 951 | ||
952 | /** | 952 | /** |
953 | * SET_IEEE80211_PERM_ADDR - set the permanenet MAC address for 802.11 hardware | 953 | * SET_IEEE80211_PERM_ADDR - set the permanenet MAC address for 802.11 hardware |
954 | * | 954 | * |
955 | * @hw: the &struct ieee80211_hw to set the MAC address for | 955 | * @hw: the &struct ieee80211_hw to set the MAC address for |
956 | * @addr: the address to set | 956 | * @addr: the address to set |
957 | */ | 957 | */ |
958 | static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) | 958 | static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr) |
959 | { | 959 | { |
960 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); | 960 | memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN); |
961 | } | 961 | } |
962 | 962 | ||
963 | static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) | 963 | static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw) |
964 | { | 964 | { |
965 | return hw->queues; | 965 | return hw->queues; |
966 | } | 966 | } |
967 | 967 | ||
968 | static inline int ieee80211_num_queues(struct ieee80211_hw *hw) | 968 | static inline int ieee80211_num_queues(struct ieee80211_hw *hw) |
969 | { | 969 | { |
970 | return hw->queues + hw->ampdu_queues; | 970 | return hw->queues + hw->ampdu_queues; |
971 | } | 971 | } |
972 | 972 | ||
973 | static inline struct ieee80211_rate * | 973 | static inline struct ieee80211_rate * |
974 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, | 974 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, |
975 | const struct ieee80211_tx_info *c) | 975 | const struct ieee80211_tx_info *c) |
976 | { | 976 | { |
977 | if (WARN_ON(c->control.rates[0].idx < 0)) | 977 | if (WARN_ON(c->control.rates[0].idx < 0)) |
978 | return NULL; | 978 | return NULL; |
979 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; | 979 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; |
980 | } | 980 | } |
981 | 981 | ||
982 | static inline struct ieee80211_rate * | 982 | static inline struct ieee80211_rate * |
983 | ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, | 983 | ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, |
984 | const struct ieee80211_tx_info *c) | 984 | const struct ieee80211_tx_info *c) |
985 | { | 985 | { |
986 | if (c->control.rts_cts_rate_idx < 0) | 986 | if (c->control.rts_cts_rate_idx < 0) |
987 | return NULL; | 987 | return NULL; |
988 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx]; | 988 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx]; |
989 | } | 989 | } |
990 | 990 | ||
991 | static inline struct ieee80211_rate * | 991 | static inline struct ieee80211_rate * |
992 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | 992 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, |
993 | const struct ieee80211_tx_info *c, int idx) | 993 | const struct ieee80211_tx_info *c, int idx) |
994 | { | 994 | { |
995 | if (c->control.rates[idx + 1].idx < 0) | 995 | if (c->control.rates[idx + 1].idx < 0) |
996 | return NULL; | 996 | return NULL; |
997 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; | 997 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; |
998 | } | 998 | } |
999 | 999 | ||
1000 | /** | 1000 | /** |
1001 | * DOC: Hardware crypto acceleration | 1001 | * DOC: Hardware crypto acceleration |
1002 | * | 1002 | * |
1003 | * mac80211 is capable of taking advantage of many hardware | 1003 | * mac80211 is capable of taking advantage of many hardware |
1004 | * acceleration designs for encryption and decryption operations. | 1004 | * acceleration designs for encryption and decryption operations. |
1005 | * | 1005 | * |
1006 | * The set_key() callback in the &struct ieee80211_ops for a given | 1006 | * The set_key() callback in the &struct ieee80211_ops for a given |
1007 | * device is called to enable hardware acceleration of encryption and | 1007 | * device is called to enable hardware acceleration of encryption and |
1008 | * decryption. The callback takes an @address parameter that will be | 1008 | * decryption. The callback takes an @address parameter that will be |
1009 | * the broadcast address for default keys, the other station's hardware | 1009 | * the broadcast address for default keys, the other station's hardware |
1010 | * address for individual keys or the zero address for keys that will | 1010 | * address for individual keys or the zero address for keys that will |
1011 | * be used only for transmission. | 1011 | * be used only for transmission. |
1012 | * Multiple transmission keys with the same key index may be used when | 1012 | * Multiple transmission keys with the same key index may be used when |
1013 | * VLANs are configured for an access point. | 1013 | * VLANs are configured for an access point. |
1014 | * | 1014 | * |
1015 | * The @local_address parameter will always be set to our own address, | 1015 | * The @local_address parameter will always be set to our own address, |
1016 | * this is only relevant if you support multiple local addresses. | 1016 | * this is only relevant if you support multiple local addresses. |
1017 | * | 1017 | * |
1018 | * When transmitting, the TX control data will use the @hw_key_idx | 1018 | * When transmitting, the TX control data will use the @hw_key_idx |
1019 | * selected by the driver by modifying the &struct ieee80211_key_conf | 1019 | * selected by the driver by modifying the &struct ieee80211_key_conf |
1020 | * pointed to by the @key parameter to the set_key() function. | 1020 | * pointed to by the @key parameter to the set_key() function. |
1021 | * | 1021 | * |
1022 | * The set_key() call for the %SET_KEY command should return 0 if | 1022 | * The set_key() call for the %SET_KEY command should return 0 if |
1023 | * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be | 1023 | * the key is now in use, -%EOPNOTSUPP or -%ENOSPC if it couldn't be |
1024 | * added; if you return 0 then hw_key_idx must be assigned to the | 1024 | * added; if you return 0 then hw_key_idx must be assigned to the |
1025 | * hardware key index, you are free to use the full u8 range. | 1025 | * hardware key index, you are free to use the full u8 range. |
1026 | * | 1026 | * |
1027 | * When the cmd is %DISABLE_KEY then it must succeed. | 1027 | * When the cmd is %DISABLE_KEY then it must succeed. |
1028 | * | 1028 | * |
1029 | * Note that it is permissible to not decrypt a frame even if a key | 1029 | * Note that it is permissible to not decrypt a frame even if a key |
1030 | * for it has been uploaded to hardware, the stack will not make any | 1030 | * for it has been uploaded to hardware, the stack will not make any |
1031 | * decision based on whether a key has been uploaded or not but rather | 1031 | * decision based on whether a key has been uploaded or not but rather |
1032 | * based on the receive flags. | 1032 | * based on the receive flags. |
1033 | * | 1033 | * |
1034 | * The &struct ieee80211_key_conf structure pointed to by the @key | 1034 | * The &struct ieee80211_key_conf structure pointed to by the @key |
1035 | * parameter is guaranteed to be valid until another call to set_key() | 1035 | * parameter is guaranteed to be valid until another call to set_key() |
1036 | * removes it, but it can only be used as a cookie to differentiate | 1036 | * removes it, but it can only be used as a cookie to differentiate |
1037 | * keys. | 1037 | * keys. |
1038 | * | 1038 | * |
1039 | * In TKIP some HW need to be provided a phase 1 key, for RX decryption | 1039 | * In TKIP some HW need to be provided a phase 1 key, for RX decryption |
1040 | * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key | 1040 | * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key |
1041 | * handler. | 1041 | * handler. |
1042 | * The update_tkip_key() call updates the driver with the new phase 1 key. | 1042 | * The update_tkip_key() call updates the driver with the new phase 1 key. |
1043 | * This happens everytime the iv16 wraps around (every 65536 packets). The | 1043 | * This happens everytime the iv16 wraps around (every 65536 packets). The |
1044 | * set_key() call will happen only once for each key (unless the AP did | 1044 | * set_key() call will happen only once for each key (unless the AP did |
1045 | * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is | 1045 | * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is |
1046 | * provided by udpate_tkip_key only. The trigger that makes mac80211 call this | 1046 | * provided by udpate_tkip_key only. The trigger that makes mac80211 call this |
1047 | * handler is software decryption with wrap around of iv16. | 1047 | * handler is software decryption with wrap around of iv16. |
1048 | */ | 1048 | */ |
1049 | 1049 | ||
1050 | /** | 1050 | /** |
1051 | * DOC: Frame filtering | 1051 | * DOC: Frame filtering |
1052 | * | 1052 | * |
1053 | * mac80211 requires to see many management frames for proper | 1053 | * mac80211 requires to see many management frames for proper |
1054 | * operation, and users may want to see many more frames when | 1054 | * operation, and users may want to see many more frames when |
1055 | * in monitor mode. However, for best CPU usage and power consumption, | 1055 | * in monitor mode. However, for best CPU usage and power consumption, |
1056 | * having as few frames as possible percolate through the stack is | 1056 | * having as few frames as possible percolate through the stack is |
1057 | * desirable. Hence, the hardware should filter as much as possible. | 1057 | * desirable. Hence, the hardware should filter as much as possible. |
1058 | * | 1058 | * |
1059 | * To achieve this, mac80211 uses filter flags (see below) to tell | 1059 | * To achieve this, mac80211 uses filter flags (see below) to tell |
1060 | * the driver's configure_filter() function which frames should be | 1060 | * the driver's configure_filter() function which frames should be |
1061 | * passed to mac80211 and which should be filtered out. | 1061 | * passed to mac80211 and which should be filtered out. |
1062 | * | 1062 | * |
1063 | * The configure_filter() callback is invoked with the parameters | 1063 | * The configure_filter() callback is invoked with the parameters |
1064 | * @mc_count and @mc_list for the combined multicast address list | 1064 | * @mc_count and @mc_list for the combined multicast address list |
1065 | * of all virtual interfaces, @changed_flags telling which flags | 1065 | * of all virtual interfaces, @changed_flags telling which flags |
1066 | * were changed and @total_flags with the new flag states. | 1066 | * were changed and @total_flags with the new flag states. |
1067 | * | 1067 | * |
1068 | * If your device has no multicast address filters your driver will | 1068 | * If your device has no multicast address filters your driver will |
1069 | * need to check both the %FIF_ALLMULTI flag and the @mc_count | 1069 | * need to check both the %FIF_ALLMULTI flag and the @mc_count |
1070 | * parameter to see whether multicast frames should be accepted | 1070 | * parameter to see whether multicast frames should be accepted |
1071 | * or dropped. | 1071 | * or dropped. |
1072 | * | 1072 | * |
1073 | * All unsupported flags in @total_flags must be cleared. | 1073 | * All unsupported flags in @total_flags must be cleared. |
1074 | * Hardware does not support a flag if it is incapable of _passing_ | 1074 | * Hardware does not support a flag if it is incapable of _passing_ |
1075 | * the frame to the stack. Otherwise the driver must ignore | 1075 | * the frame to the stack. Otherwise the driver must ignore |
1076 | * the flag, but not clear it. | 1076 | * the flag, but not clear it. |
1077 | * You must _only_ clear the flag (announce no support for the | 1077 | * You must _only_ clear the flag (announce no support for the |
1078 | * flag to mac80211) if you are not able to pass the packet type | 1078 | * flag to mac80211) if you are not able to pass the packet type |
1079 | * to the stack (so the hardware always filters it). | 1079 | * to the stack (so the hardware always filters it). |
1080 | * So for example, you should clear @FIF_CONTROL, if your hardware | 1080 | * So for example, you should clear @FIF_CONTROL, if your hardware |
1081 | * always filters control frames. If your hardware always passes | 1081 | * always filters control frames. If your hardware always passes |
1082 | * control frames to the kernel and is incapable of filtering them, | 1082 | * control frames to the kernel and is incapable of filtering them, |
1083 | * you do _not_ clear the @FIF_CONTROL flag. | 1083 | * you do _not_ clear the @FIF_CONTROL flag. |
1084 | * This rule applies to all other FIF flags as well. | 1084 | * This rule applies to all other FIF flags as well. |
1085 | */ | 1085 | */ |
1086 | 1086 | ||
1087 | /** | 1087 | /** |
1088 | * enum ieee80211_filter_flags - hardware filter flags | 1088 | * enum ieee80211_filter_flags - hardware filter flags |
1089 | * | 1089 | * |
1090 | * These flags determine what the filter in hardware should be | 1090 | * These flags determine what the filter in hardware should be |
1091 | * programmed to let through and what should not be passed to the | 1091 | * programmed to let through and what should not be passed to the |
1092 | * stack. It is always safe to pass more frames than requested, | 1092 | * stack. It is always safe to pass more frames than requested, |
1093 | * but this has negative impact on power consumption. | 1093 | * but this has negative impact on power consumption. |
1094 | * | 1094 | * |
1095 | * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS, | 1095 | * @FIF_PROMISC_IN_BSS: promiscuous mode within your BSS, |
1096 | * think of the BSS as your network segment and then this corresponds | 1096 | * think of the BSS as your network segment and then this corresponds |
1097 | * to the regular ethernet device promiscuous mode. | 1097 | * to the regular ethernet device promiscuous mode. |
1098 | * | 1098 | * |
1099 | * @FIF_ALLMULTI: pass all multicast frames, this is used if requested | 1099 | * @FIF_ALLMULTI: pass all multicast frames, this is used if requested |
1100 | * by the user or if the hardware is not capable of filtering by | 1100 | * by the user or if the hardware is not capable of filtering by |
1101 | * multicast address. | 1101 | * multicast address. |
1102 | * | 1102 | * |
1103 | * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the | 1103 | * @FIF_FCSFAIL: pass frames with failed FCS (but you need to set the |
1104 | * %RX_FLAG_FAILED_FCS_CRC for them) | 1104 | * %RX_FLAG_FAILED_FCS_CRC for them) |
1105 | * | 1105 | * |
1106 | * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set | 1106 | * @FIF_PLCPFAIL: pass frames with failed PLCP CRC (but you need to set |
1107 | * the %RX_FLAG_FAILED_PLCP_CRC for them | 1107 | * the %RX_FLAG_FAILED_PLCP_CRC for them |
1108 | * | 1108 | * |
1109 | * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate | 1109 | * @FIF_BCN_PRBRESP_PROMISC: This flag is set during scanning to indicate |
1110 | * to the hardware that it should not filter beacons or probe responses | 1110 | * to the hardware that it should not filter beacons or probe responses |
1111 | * by BSSID. Filtering them can greatly reduce the amount of processing | 1111 | * by BSSID. Filtering them can greatly reduce the amount of processing |
1112 | * mac80211 needs to do and the amount of CPU wakeups, so you should | 1112 | * mac80211 needs to do and the amount of CPU wakeups, so you should |
1113 | * honour this flag if possible. | 1113 | * honour this flag if possible. |
1114 | * | 1114 | * |
1115 | * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then | 1115 | * @FIF_CONTROL: pass control frames, if PROMISC_IN_BSS is not set then |
1116 | * only those addressed to this station | 1116 | * only those addressed to this station |
1117 | * | 1117 | * |
1118 | * @FIF_OTHER_BSS: pass frames destined to other BSSes | 1118 | * @FIF_OTHER_BSS: pass frames destined to other BSSes |
1119 | */ | 1119 | */ |
1120 | enum ieee80211_filter_flags { | 1120 | enum ieee80211_filter_flags { |
1121 | FIF_PROMISC_IN_BSS = 1<<0, | 1121 | FIF_PROMISC_IN_BSS = 1<<0, |
1122 | FIF_ALLMULTI = 1<<1, | 1122 | FIF_ALLMULTI = 1<<1, |
1123 | FIF_FCSFAIL = 1<<2, | 1123 | FIF_FCSFAIL = 1<<2, |
1124 | FIF_PLCPFAIL = 1<<3, | 1124 | FIF_PLCPFAIL = 1<<3, |
1125 | FIF_BCN_PRBRESP_PROMISC = 1<<4, | 1125 | FIF_BCN_PRBRESP_PROMISC = 1<<4, |
1126 | FIF_CONTROL = 1<<5, | 1126 | FIF_CONTROL = 1<<5, |
1127 | FIF_OTHER_BSS = 1<<6, | 1127 | FIF_OTHER_BSS = 1<<6, |
1128 | }; | 1128 | }; |
1129 | 1129 | ||
1130 | /** | 1130 | /** |
1131 | * enum ieee80211_ampdu_mlme_action - A-MPDU actions | 1131 | * enum ieee80211_ampdu_mlme_action - A-MPDU actions |
1132 | * | 1132 | * |
1133 | * These flags are used with the ampdu_action() callback in | 1133 | * These flags are used with the ampdu_action() callback in |
1134 | * &struct ieee80211_ops to indicate which action is needed. | 1134 | * &struct ieee80211_ops to indicate which action is needed. |
1135 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation | 1135 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation |
1136 | * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation | 1136 | * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation |
1137 | * @IEEE80211_AMPDU_TX_START: start Tx aggregation | 1137 | * @IEEE80211_AMPDU_TX_START: start Tx aggregation |
1138 | * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation | 1138 | * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation |
1139 | */ | 1139 | */ |
1140 | enum ieee80211_ampdu_mlme_action { | 1140 | enum ieee80211_ampdu_mlme_action { |
1141 | IEEE80211_AMPDU_RX_START, | 1141 | IEEE80211_AMPDU_RX_START, |
1142 | IEEE80211_AMPDU_RX_STOP, | 1142 | IEEE80211_AMPDU_RX_STOP, |
1143 | IEEE80211_AMPDU_TX_START, | 1143 | IEEE80211_AMPDU_TX_START, |
1144 | IEEE80211_AMPDU_TX_STOP, | 1144 | IEEE80211_AMPDU_TX_STOP, |
1145 | }; | 1145 | }; |
1146 | 1146 | ||
1147 | /** | 1147 | /** |
1148 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 1148 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
1149 | * | 1149 | * |
1150 | * This structure contains various callbacks that the driver may | 1150 | * This structure contains various callbacks that the driver may |
1151 | * handle or, in some cases, must handle, for example to configure | 1151 | * handle or, in some cases, must handle, for example to configure |
1152 | * the hardware to a new channel or to transmit a frame. | 1152 | * the hardware to a new channel or to transmit a frame. |
1153 | * | 1153 | * |
1154 | * @tx: Handler that 802.11 module calls for each transmitted frame. | 1154 | * @tx: Handler that 802.11 module calls for each transmitted frame. |
1155 | * skb contains the buffer starting from the IEEE 802.11 header. | 1155 | * skb contains the buffer starting from the IEEE 802.11 header. |
1156 | * The low-level driver should send the frame out based on | 1156 | * The low-level driver should send the frame out based on |
1157 | * configuration in the TX control data. This handler should, | 1157 | * configuration in the TX control data. This handler should, |
1158 | * preferably, never fail and stop queues appropriately, more | 1158 | * preferably, never fail and stop queues appropriately, more |
1159 | * importantly, however, it must never fail for A-MPDU-queues. | 1159 | * importantly, however, it must never fail for A-MPDU-queues. |
1160 | * Must be implemented and atomic. | 1160 | * Must be implemented and atomic. |
1161 | * | 1161 | * |
1162 | * @start: Called before the first netdevice attached to the hardware | 1162 | * @start: Called before the first netdevice attached to the hardware |
1163 | * is enabled. This should turn on the hardware and must turn on | 1163 | * is enabled. This should turn on the hardware and must turn on |
1164 | * frame reception (for possibly enabled monitor interfaces.) | 1164 | * frame reception (for possibly enabled monitor interfaces.) |
1165 | * Returns negative error codes, these may be seen in userspace, | 1165 | * Returns negative error codes, these may be seen in userspace, |
1166 | * or zero. | 1166 | * or zero. |
1167 | * When the device is started it should not have a MAC address | 1167 | * When the device is started it should not have a MAC address |
1168 | * to avoid acknowledging frames before a non-monitor device | 1168 | * to avoid acknowledging frames before a non-monitor device |
1169 | * is added. | 1169 | * is added. |
1170 | * Must be implemented. | 1170 | * Must be implemented. |
1171 | * | 1171 | * |
1172 | * @stop: Called after last netdevice attached to the hardware | 1172 | * @stop: Called after last netdevice attached to the hardware |
1173 | * is disabled. This should turn off the hardware (at least | 1173 | * is disabled. This should turn off the hardware (at least |
1174 | * it must turn off frame reception.) | 1174 | * it must turn off frame reception.) |
1175 | * May be called right after add_interface if that rejects | 1175 | * May be called right after add_interface if that rejects |
1176 | * an interface. | 1176 | * an interface. |
1177 | * Must be implemented. | 1177 | * Must be implemented. |
1178 | * | 1178 | * |
1179 | * @add_interface: Called when a netdevice attached to the hardware is | 1179 | * @add_interface: Called when a netdevice attached to the hardware is |
1180 | * enabled. Because it is not called for monitor mode devices, @open | 1180 | * enabled. Because it is not called for monitor mode devices, @open |
1181 | * and @stop must be implemented. | 1181 | * and @stop must be implemented. |
1182 | * The driver should perform any initialization it needs before | 1182 | * The driver should perform any initialization it needs before |
1183 | * the device can be enabled. The initial configuration for the | 1183 | * the device can be enabled. The initial configuration for the |
1184 | * interface is given in the conf parameter. | 1184 | * interface is given in the conf parameter. |
1185 | * The callback may refuse to add an interface by returning a | 1185 | * The callback may refuse to add an interface by returning a |
1186 | * negative error code (which will be seen in userspace.) | 1186 | * negative error code (which will be seen in userspace.) |
1187 | * Must be implemented. | 1187 | * Must be implemented. |
1188 | * | 1188 | * |
1189 | * @remove_interface: Notifies a driver that an interface is going down. | 1189 | * @remove_interface: Notifies a driver that an interface is going down. |
1190 | * The @stop callback is called after this if it is the last interface | 1190 | * The @stop callback is called after this if it is the last interface |
1191 | * and no monitor interfaces are present. | 1191 | * and no monitor interfaces are present. |
1192 | * When all interfaces are removed, the MAC address in the hardware | 1192 | * When all interfaces are removed, the MAC address in the hardware |
1193 | * must be cleared so the device no longer acknowledges packets, | 1193 | * must be cleared so the device no longer acknowledges packets, |
1194 | * the mac_addr member of the conf structure is, however, set to the | 1194 | * the mac_addr member of the conf structure is, however, set to the |
1195 | * MAC address of the device going away. | 1195 | * MAC address of the device going away. |
1196 | * Hence, this callback must be implemented. | 1196 | * Hence, this callback must be implemented. |
1197 | * | 1197 | * |
1198 | * @config: Handler for configuration requests. IEEE 802.11 code calls this | 1198 | * @config: Handler for configuration requests. IEEE 802.11 code calls this |
1199 | * function to change hardware configuration, e.g., channel. | 1199 | * function to change hardware configuration, e.g., channel. |
1200 | * | 1200 | * |
1201 | * @config_interface: Handler for configuration requests related to interfaces | 1201 | * @config_interface: Handler for configuration requests related to interfaces |
1202 | * (e.g. BSSID changes.) | 1202 | * (e.g. BSSID changes.) |
1203 | * | 1203 | * |
1204 | * @bss_info_changed: Handler for configuration requests related to BSS | 1204 | * @bss_info_changed: Handler for configuration requests related to BSS |
1205 | * parameters that may vary during BSS's lifespan, and may affect low | 1205 | * parameters that may vary during BSS's lifespan, and may affect low |
1206 | * level driver (e.g. assoc/disassoc status, erp parameters). | 1206 | * level driver (e.g. assoc/disassoc status, erp parameters). |
1207 | * This function should not be used if no BSS has been set, unless | 1207 | * This function should not be used if no BSS has been set, unless |
1208 | * for association indication. The @changed parameter indicates which | 1208 | * for association indication. The @changed parameter indicates which |
1209 | * of the bss parameters has changed when a call is made. | 1209 | * of the bss parameters has changed when a call is made. |
1210 | * | 1210 | * |
1211 | * @configure_filter: Configure the device's RX filter. | 1211 | * @configure_filter: Configure the device's RX filter. |
1212 | * See the section "Frame filtering" for more information. | 1212 | * See the section "Frame filtering" for more information. |
1213 | * This callback must be implemented and atomic. | 1213 | * This callback must be implemented and atomic. |
1214 | * | 1214 | * |
1215 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 1215 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
1216 | * must be set or cleared for a given STA. Must be atomic. | 1216 | * must be set or cleared for a given STA. Must be atomic. |
1217 | * | 1217 | * |
1218 | * @set_key: See the section "Hardware crypto acceleration" | 1218 | * @set_key: See the section "Hardware crypto acceleration" |
1219 | * This callback can sleep, and is only called between add_interface | 1219 | * This callback can sleep, and is only called between add_interface |
1220 | * and remove_interface calls, i.e. while the interface with the | 1220 | * and remove_interface calls, i.e. while the interface with the |
1221 | * given local_address is enabled. | 1221 | * given local_address is enabled. |
1222 | * | 1222 | * |
1223 | * @update_tkip_key: See the section "Hardware crypto acceleration" | 1223 | * @update_tkip_key: See the section "Hardware crypto acceleration" |
1224 | * This callback will be called in the context of Rx. Called for drivers | 1224 | * This callback will be called in the context of Rx. Called for drivers |
1225 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. | 1225 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. |
1226 | * | 1226 | * |
1227 | * @hw_scan: Ask the hardware to service the scan request, no need to start | 1227 | * @hw_scan: Ask the hardware to service the scan request, no need to start |
1228 | * the scan state machine in stack. The scan must honour the channel | 1228 | * the scan state machine in stack. The scan must honour the channel |
1229 | * configuration done by the regulatory agent in the wiphy's registered | 1229 | * configuration done by the regulatory agent in the wiphy's registered |
1230 | * bands. When the scan finishes, ieee80211_scan_completed() must be | 1230 | * bands. When the scan finishes, ieee80211_scan_completed() must be |
1231 | * called; note that it also must be called when the scan cannot finish | 1231 | * called; note that it also must be called when the scan cannot finish |
1232 | * because the hardware is turned off! Anything else is a bug! | 1232 | * because the hardware is turned off! Anything else is a bug! |
1233 | * | 1233 | * |
1234 | * @get_stats: return low-level statistics | 1234 | * @get_stats: return low-level statistics |
1235 | * | 1235 | * |
1236 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this | 1236 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this |
1237 | * callback should be provided to read the TKIP transmit IVs (both IV32 | 1237 | * callback should be provided to read the TKIP transmit IVs (both IV32 |
1238 | * and IV16) for the given key from hardware. | 1238 | * and IV16) for the given key from hardware. |
1239 | * | 1239 | * |
1240 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) | 1240 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) |
1241 | * | 1241 | * |
1242 | * @set_frag_threshold: Configuration of fragmentation threshold. Assign this if | 1242 | * @set_frag_threshold: Configuration of fragmentation threshold. Assign this if |
1243 | * the device does fragmentation by itself; if this method is assigned then | 1243 | * the device does fragmentation by itself; if this method is assigned then |
1244 | * the stack will not do fragmentation. | 1244 | * the stack will not do fragmentation. |
1245 | * | 1245 | * |
1246 | * @sta_notify: Notifies low level driver about addition or removal | 1246 | * @sta_notify: Notifies low level driver about addition or removal |
1247 | * of assocaited station or AP. | 1247 | * of assocaited station or AP. |
1248 | * | 1248 | * |
1249 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 1249 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1250 | * bursting) for a hardware TX queue. | 1250 | * bursting) for a hardware TX queue. |
1251 | * | 1251 | * |
1252 | * @get_tx_stats: Get statistics of the current TX queue status. This is used | 1252 | * @get_tx_stats: Get statistics of the current TX queue status. This is used |
1253 | * to get number of currently queued packets (queue length), maximum queue | 1253 | * to get number of currently queued packets (queue length), maximum queue |
1254 | * size (limit), and total number of packets sent using each TX queue | 1254 | * size (limit), and total number of packets sent using each TX queue |
1255 | * (count). The 'stats' pointer points to an array that has hw->queues + | 1255 | * (count). The 'stats' pointer points to an array that has hw->queues + |
1256 | * hw->ampdu_queues items. | 1256 | * hw->ampdu_queues items. |
1257 | * | 1257 | * |
1258 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, | 1258 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, |
1259 | * this is only used for IBSS mode debugging and, as such, is not a | 1259 | * this is only used for IBSS mode debugging and, as such, is not a |
1260 | * required function. Must be atomic. | 1260 | * required function. Must be atomic. |
1261 | * | 1261 | * |
1262 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize | 1262 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize |
1263 | * with other STAs in the IBSS. This is only used in IBSS mode. This | 1263 | * with other STAs in the IBSS. This is only used in IBSS mode. This |
1264 | * function is optional if the firmware/hardware takes full care of | 1264 | * function is optional if the firmware/hardware takes full care of |
1265 | * TSF synchronization. | 1265 | * TSF synchronization. |
1266 | * | 1266 | * |
1267 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. | 1267 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. |
1268 | * This is needed only for IBSS mode and the result of this function is | 1268 | * This is needed only for IBSS mode and the result of this function is |
1269 | * used to determine whether to reply to Probe Requests. | 1269 | * used to determine whether to reply to Probe Requests. |
1270 | * | 1270 | * |
1271 | * @conf_ht: Configures low level driver with 802.11n HT data. Must be atomic. | 1271 | * @conf_ht: Configures low level driver with 802.11n HT data. Must be atomic. |
1272 | * | 1272 | * |
1273 | * @ampdu_action: Perform a certain A-MPDU action | 1273 | * @ampdu_action: Perform a certain A-MPDU action |
1274 | * The RA/TID combination determines the destination and TID we want | 1274 | * The RA/TID combination determines the destination and TID we want |
1275 | * the ampdu action to be performed for. The action is defined through | 1275 | * the ampdu action to be performed for. The action is defined through |
1276 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) | 1276 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) |
1277 | * is the first frame we expect to perform the action on. notice | 1277 | * is the first frame we expect to perform the action on. notice |
1278 | * that TX/RX_STOP can pass NULL for this parameter. | 1278 | * that TX/RX_STOP can pass NULL for this parameter. |
1279 | */ | 1279 | */ |
1280 | struct ieee80211_ops { | 1280 | struct ieee80211_ops { |
1281 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1281 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
1282 | int (*start)(struct ieee80211_hw *hw); | 1282 | int (*start)(struct ieee80211_hw *hw); |
1283 | void (*stop)(struct ieee80211_hw *hw); | 1283 | void (*stop)(struct ieee80211_hw *hw); |
1284 | int (*add_interface)(struct ieee80211_hw *hw, | 1284 | int (*add_interface)(struct ieee80211_hw *hw, |
1285 | struct ieee80211_if_init_conf *conf); | 1285 | struct ieee80211_if_init_conf *conf); |
1286 | void (*remove_interface)(struct ieee80211_hw *hw, | 1286 | void (*remove_interface)(struct ieee80211_hw *hw, |
1287 | struct ieee80211_if_init_conf *conf); | 1287 | struct ieee80211_if_init_conf *conf); |
1288 | int (*config)(struct ieee80211_hw *hw, u32 changed); | 1288 | int (*config)(struct ieee80211_hw *hw, u32 changed); |
1289 | int (*config_interface)(struct ieee80211_hw *hw, | 1289 | int (*config_interface)(struct ieee80211_hw *hw, |
1290 | struct ieee80211_vif *vif, | 1290 | struct ieee80211_vif *vif, |
1291 | struct ieee80211_if_conf *conf); | 1291 | struct ieee80211_if_conf *conf); |
1292 | void (*bss_info_changed)(struct ieee80211_hw *hw, | 1292 | void (*bss_info_changed)(struct ieee80211_hw *hw, |
1293 | struct ieee80211_vif *vif, | 1293 | struct ieee80211_vif *vif, |
1294 | struct ieee80211_bss_conf *info, | 1294 | struct ieee80211_bss_conf *info, |
1295 | u32 changed); | 1295 | u32 changed); |
1296 | void (*configure_filter)(struct ieee80211_hw *hw, | 1296 | void (*configure_filter)(struct ieee80211_hw *hw, |
1297 | unsigned int changed_flags, | 1297 | unsigned int changed_flags, |
1298 | unsigned int *total_flags, | 1298 | unsigned int *total_flags, |
1299 | int mc_count, struct dev_addr_list *mc_list); | 1299 | int mc_count, struct dev_addr_list *mc_list); |
1300 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 1300 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
1301 | bool set); | 1301 | bool set); |
1302 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1302 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
1303 | const u8 *local_address, const u8 *address, | 1303 | const u8 *local_address, const u8 *address, |
1304 | struct ieee80211_key_conf *key); | 1304 | struct ieee80211_key_conf *key); |
1305 | void (*update_tkip_key)(struct ieee80211_hw *hw, | 1305 | void (*update_tkip_key)(struct ieee80211_hw *hw, |
1306 | struct ieee80211_key_conf *conf, const u8 *address, | 1306 | struct ieee80211_key_conf *conf, const u8 *address, |
1307 | u32 iv32, u16 *phase1key); | 1307 | u32 iv32, u16 *phase1key); |
1308 | int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); | 1308 | int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); |
1309 | int (*get_stats)(struct ieee80211_hw *hw, | 1309 | int (*get_stats)(struct ieee80211_hw *hw, |
1310 | struct ieee80211_low_level_stats *stats); | 1310 | struct ieee80211_low_level_stats *stats); |
1311 | void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, | 1311 | void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, |
1312 | u32 *iv32, u16 *iv16); | 1312 | u32 *iv32, u16 *iv16); |
1313 | int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); | 1313 | int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); |
1314 | int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); | 1314 | int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); |
1315 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1315 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1316 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 1316 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
1317 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, | 1317 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, |
1318 | const struct ieee80211_tx_queue_params *params); | 1318 | const struct ieee80211_tx_queue_params *params); |
1319 | int (*get_tx_stats)(struct ieee80211_hw *hw, | 1319 | int (*get_tx_stats)(struct ieee80211_hw *hw, |
1320 | struct ieee80211_tx_queue_stats *stats); | 1320 | struct ieee80211_tx_queue_stats *stats); |
1321 | u64 (*get_tsf)(struct ieee80211_hw *hw); | 1321 | u64 (*get_tsf)(struct ieee80211_hw *hw); |
1322 | void (*reset_tsf)(struct ieee80211_hw *hw); | 1322 | void (*reset_tsf)(struct ieee80211_hw *hw); |
1323 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 1323 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
1324 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1324 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1325 | enum ieee80211_ampdu_mlme_action action, | 1325 | enum ieee80211_ampdu_mlme_action action, |
1326 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 1326 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
1327 | }; | 1327 | }; |
1328 | 1328 | ||
1329 | /** | 1329 | /** |
1330 | * ieee80211_alloc_hw - Allocate a new hardware device | 1330 | * ieee80211_alloc_hw - Allocate a new hardware device |
1331 | * | 1331 | * |
1332 | * This must be called once for each hardware device. The returned pointer | 1332 | * This must be called once for each hardware device. The returned pointer |
1333 | * must be used to refer to this device when calling other functions. | 1333 | * must be used to refer to this device when calling other functions. |
1334 | * mac80211 allocates a private data area for the driver pointed to by | 1334 | * mac80211 allocates a private data area for the driver pointed to by |
1335 | * @priv in &struct ieee80211_hw, the size of this area is given as | 1335 | * @priv in &struct ieee80211_hw, the size of this area is given as |
1336 | * @priv_data_len. | 1336 | * @priv_data_len. |
1337 | * | 1337 | * |
1338 | * @priv_data_len: length of private data | 1338 | * @priv_data_len: length of private data |
1339 | * @ops: callbacks for this device | 1339 | * @ops: callbacks for this device |
1340 | */ | 1340 | */ |
1341 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 1341 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
1342 | const struct ieee80211_ops *ops); | 1342 | const struct ieee80211_ops *ops); |
1343 | 1343 | ||
1344 | /** | 1344 | /** |
1345 | * ieee80211_register_hw - Register hardware device | 1345 | * ieee80211_register_hw - Register hardware device |
1346 | * | 1346 | * |
1347 | * You must call this function before any other functions in | 1347 | * You must call this function before any other functions in |
1348 | * mac80211. Note that before a hardware can be registered, you | 1348 | * mac80211. Note that before a hardware can be registered, you |
1349 | * need to fill the contained wiphy's information. | 1349 | * need to fill the contained wiphy's information. |
1350 | * | 1350 | * |
1351 | * @hw: the device to register as returned by ieee80211_alloc_hw() | 1351 | * @hw: the device to register as returned by ieee80211_alloc_hw() |
1352 | */ | 1352 | */ |
1353 | int ieee80211_register_hw(struct ieee80211_hw *hw); | 1353 | int ieee80211_register_hw(struct ieee80211_hw *hw); |
1354 | 1354 | ||
1355 | #ifdef CONFIG_MAC80211_LEDS | 1355 | #ifdef CONFIG_MAC80211_LEDS |
1356 | extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw); | 1356 | extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw); |
1357 | extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw); | 1357 | extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw); |
1358 | extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw); | 1358 | extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw); |
1359 | extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw); | 1359 | extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw); |
1360 | #endif | 1360 | #endif |
1361 | /** | 1361 | /** |
1362 | * ieee80211_get_tx_led_name - get name of TX LED | 1362 | * ieee80211_get_tx_led_name - get name of TX LED |
1363 | * | 1363 | * |
1364 | * mac80211 creates a transmit LED trigger for each wireless hardware | 1364 | * mac80211 creates a transmit LED trigger for each wireless hardware |
1365 | * that can be used to drive LEDs if your driver registers a LED device. | 1365 | * that can be used to drive LEDs if your driver registers a LED device. |
1366 | * This function returns the name (or %NULL if not configured for LEDs) | 1366 | * This function returns the name (or %NULL if not configured for LEDs) |
1367 | * of the trigger so you can automatically link the LED device. | 1367 | * of the trigger so you can automatically link the LED device. |
1368 | * | 1368 | * |
1369 | * @hw: the hardware to get the LED trigger name for | 1369 | * @hw: the hardware to get the LED trigger name for |
1370 | */ | 1370 | */ |
1371 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | 1371 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) |
1372 | { | 1372 | { |
1373 | #ifdef CONFIG_MAC80211_LEDS | 1373 | #ifdef CONFIG_MAC80211_LEDS |
1374 | return __ieee80211_get_tx_led_name(hw); | 1374 | return __ieee80211_get_tx_led_name(hw); |
1375 | #else | 1375 | #else |
1376 | return NULL; | 1376 | return NULL; |
1377 | #endif | 1377 | #endif |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | /** | 1380 | /** |
1381 | * ieee80211_get_rx_led_name - get name of RX LED | 1381 | * ieee80211_get_rx_led_name - get name of RX LED |
1382 | * | 1382 | * |
1383 | * mac80211 creates a receive LED trigger for each wireless hardware | 1383 | * mac80211 creates a receive LED trigger for each wireless hardware |
1384 | * that can be used to drive LEDs if your driver registers a LED device. | 1384 | * that can be used to drive LEDs if your driver registers a LED device. |
1385 | * This function returns the name (or %NULL if not configured for LEDs) | 1385 | * This function returns the name (or %NULL if not configured for LEDs) |
1386 | * of the trigger so you can automatically link the LED device. | 1386 | * of the trigger so you can automatically link the LED device. |
1387 | * | 1387 | * |
1388 | * @hw: the hardware to get the LED trigger name for | 1388 | * @hw: the hardware to get the LED trigger name for |
1389 | */ | 1389 | */ |
1390 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | 1390 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) |
1391 | { | 1391 | { |
1392 | #ifdef CONFIG_MAC80211_LEDS | 1392 | #ifdef CONFIG_MAC80211_LEDS |
1393 | return __ieee80211_get_rx_led_name(hw); | 1393 | return __ieee80211_get_rx_led_name(hw); |
1394 | #else | 1394 | #else |
1395 | return NULL; | 1395 | return NULL; |
1396 | #endif | 1396 | #endif |
1397 | } | 1397 | } |
1398 | 1398 | ||
1399 | /** | 1399 | /** |
1400 | * ieee80211_get_assoc_led_name - get name of association LED | 1400 | * ieee80211_get_assoc_led_name - get name of association LED |
1401 | * | 1401 | * |
1402 | * mac80211 creates a association LED trigger for each wireless hardware | 1402 | * mac80211 creates a association LED trigger for each wireless hardware |
1403 | * that can be used to drive LEDs if your driver registers a LED device. | 1403 | * that can be used to drive LEDs if your driver registers a LED device. |
1404 | * This function returns the name (or %NULL if not configured for LEDs) | 1404 | * This function returns the name (or %NULL if not configured for LEDs) |
1405 | * of the trigger so you can automatically link the LED device. | 1405 | * of the trigger so you can automatically link the LED device. |
1406 | * | 1406 | * |
1407 | * @hw: the hardware to get the LED trigger name for | 1407 | * @hw: the hardware to get the LED trigger name for |
1408 | */ | 1408 | */ |
1409 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | 1409 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) |
1410 | { | 1410 | { |
1411 | #ifdef CONFIG_MAC80211_LEDS | 1411 | #ifdef CONFIG_MAC80211_LEDS |
1412 | return __ieee80211_get_assoc_led_name(hw); | 1412 | return __ieee80211_get_assoc_led_name(hw); |
1413 | #else | 1413 | #else |
1414 | return NULL; | 1414 | return NULL; |
1415 | #endif | 1415 | #endif |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | /** | 1418 | /** |
1419 | * ieee80211_get_radio_led_name - get name of radio LED | 1419 | * ieee80211_get_radio_led_name - get name of radio LED |
1420 | * | 1420 | * |
1421 | * mac80211 creates a radio change LED trigger for each wireless hardware | 1421 | * mac80211 creates a radio change LED trigger for each wireless hardware |
1422 | * that can be used to drive LEDs if your driver registers a LED device. | 1422 | * that can be used to drive LEDs if your driver registers a LED device. |
1423 | * This function returns the name (or %NULL if not configured for LEDs) | 1423 | * This function returns the name (or %NULL if not configured for LEDs) |
1424 | * of the trigger so you can automatically link the LED device. | 1424 | * of the trigger so you can automatically link the LED device. |
1425 | * | 1425 | * |
1426 | * @hw: the hardware to get the LED trigger name for | 1426 | * @hw: the hardware to get the LED trigger name for |
1427 | */ | 1427 | */ |
1428 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 1428 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
1429 | { | 1429 | { |
1430 | #ifdef CONFIG_MAC80211_LEDS | 1430 | #ifdef CONFIG_MAC80211_LEDS |
1431 | return __ieee80211_get_radio_led_name(hw); | 1431 | return __ieee80211_get_radio_led_name(hw); |
1432 | #else | 1432 | #else |
1433 | return NULL; | 1433 | return NULL; |
1434 | #endif | 1434 | #endif |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | /** | 1437 | /** |
1438 | * ieee80211_unregister_hw - Unregister a hardware device | 1438 | * ieee80211_unregister_hw - Unregister a hardware device |
1439 | * | 1439 | * |
1440 | * This function instructs mac80211 to free allocated resources | 1440 | * This function instructs mac80211 to free allocated resources |
1441 | * and unregister netdevices from the networking subsystem. | 1441 | * and unregister netdevices from the networking subsystem. |
1442 | * | 1442 | * |
1443 | * @hw: the hardware to unregister | 1443 | * @hw: the hardware to unregister |
1444 | */ | 1444 | */ |
1445 | void ieee80211_unregister_hw(struct ieee80211_hw *hw); | 1445 | void ieee80211_unregister_hw(struct ieee80211_hw *hw); |
1446 | 1446 | ||
1447 | /** | 1447 | /** |
1448 | * ieee80211_free_hw - free hardware descriptor | 1448 | * ieee80211_free_hw - free hardware descriptor |
1449 | * | 1449 | * |
1450 | * This function frees everything that was allocated, including the | 1450 | * This function frees everything that was allocated, including the |
1451 | * private data for the driver. You must call ieee80211_unregister_hw() | 1451 | * private data for the driver. You must call ieee80211_unregister_hw() |
1452 | * before calling this function. | 1452 | * before calling this function. |
1453 | * | 1453 | * |
1454 | * @hw: the hardware to free | 1454 | * @hw: the hardware to free |
1455 | */ | 1455 | */ |
1456 | void ieee80211_free_hw(struct ieee80211_hw *hw); | 1456 | void ieee80211_free_hw(struct ieee80211_hw *hw); |
1457 | 1457 | ||
1458 | /* trick to avoid symbol clashes with the ieee80211 subsystem */ | 1458 | /* trick to avoid symbol clashes with the ieee80211 subsystem */ |
1459 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 1459 | void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, |
1460 | struct ieee80211_rx_status *status); | 1460 | struct ieee80211_rx_status *status); |
1461 | 1461 | ||
1462 | /** | 1462 | /** |
1463 | * ieee80211_rx - receive frame | 1463 | * ieee80211_rx - receive frame |
1464 | * | 1464 | * |
1465 | * Use this function to hand received frames to mac80211. The receive | 1465 | * Use this function to hand received frames to mac80211. The receive |
1466 | * buffer in @skb must start with an IEEE 802.11 header or a radiotap | 1466 | * buffer in @skb must start with an IEEE 802.11 header or a radiotap |
1467 | * header if %RX_FLAG_RADIOTAP is set in the @status flags. | 1467 | * header if %RX_FLAG_RADIOTAP is set in the @status flags. |
1468 | * | 1468 | * |
1469 | * This function may not be called in IRQ context. Calls to this function | 1469 | * This function may not be called in IRQ context. Calls to this function |
1470 | * for a single hardware must be synchronized against each other. Calls | 1470 | * for a single hardware must be synchronized against each other. Calls |
1471 | * to this function and ieee80211_rx_irqsafe() may not be mixed for a | 1471 | * to this function and ieee80211_rx_irqsafe() may not be mixed for a |
1472 | * single hardware. | 1472 | * single hardware. |
1473 | * | 1473 | * |
1474 | * @hw: the hardware this frame came in on | 1474 | * @hw: the hardware this frame came in on |
1475 | * @skb: the buffer to receive, owned by mac80211 after this call | 1475 | * @skb: the buffer to receive, owned by mac80211 after this call |
1476 | * @status: status of this frame; the status pointer need not be valid | 1476 | * @status: status of this frame; the status pointer need not be valid |
1477 | * after this function returns | 1477 | * after this function returns |
1478 | */ | 1478 | */ |
1479 | static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | 1479 | static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, |
1480 | struct ieee80211_rx_status *status) | 1480 | struct ieee80211_rx_status *status) |
1481 | { | 1481 | { |
1482 | __ieee80211_rx(hw, skb, status); | 1482 | __ieee80211_rx(hw, skb, status); |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | /** | 1485 | /** |
1486 | * ieee80211_rx_irqsafe - receive frame | 1486 | * ieee80211_rx_irqsafe - receive frame |
1487 | * | 1487 | * |
1488 | * Like ieee80211_rx() but can be called in IRQ context | 1488 | * Like ieee80211_rx() but can be called in IRQ context |
1489 | * (internally defers to a tasklet.) | 1489 | * (internally defers to a tasklet.) |
1490 | * | 1490 | * |
1491 | * Calls to this function and ieee80211_rx() may not be mixed for a | 1491 | * Calls to this function and ieee80211_rx() may not be mixed for a |
1492 | * single hardware. | 1492 | * single hardware. |
1493 | * | 1493 | * |
1494 | * @hw: the hardware this frame came in on | 1494 | * @hw: the hardware this frame came in on |
1495 | * @skb: the buffer to receive, owned by mac80211 after this call | 1495 | * @skb: the buffer to receive, owned by mac80211 after this call |
1496 | * @status: status of this frame; the status pointer need not be valid | 1496 | * @status: status of this frame; the status pointer need not be valid |
1497 | * after this function returns and is not freed by mac80211, | 1497 | * after this function returns and is not freed by mac80211, |
1498 | * it is recommended that it points to a stack area | 1498 | * it is recommended that it points to a stack area |
1499 | */ | 1499 | */ |
1500 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, | 1500 | void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, |
1501 | struct sk_buff *skb, | 1501 | struct sk_buff *skb, |
1502 | struct ieee80211_rx_status *status); | 1502 | struct ieee80211_rx_status *status); |
1503 | 1503 | ||
1504 | /** | 1504 | /** |
1505 | * ieee80211_tx_status - transmit status callback | 1505 | * ieee80211_tx_status - transmit status callback |
1506 | * | 1506 | * |
1507 | * Call this function for all transmitted frames after they have been | 1507 | * Call this function for all transmitted frames after they have been |
1508 | * transmitted. It is permissible to not call this function for | 1508 | * transmitted. It is permissible to not call this function for |
1509 | * multicast frames but this can affect statistics. | 1509 | * multicast frames but this can affect statistics. |
1510 | * | 1510 | * |
1511 | * This function may not be called in IRQ context. Calls to this function | 1511 | * This function may not be called in IRQ context. Calls to this function |
1512 | * for a single hardware must be synchronized against each other. Calls | 1512 | * for a single hardware must be synchronized against each other. Calls |
1513 | * to this function and ieee80211_tx_status_irqsafe() may not be mixed | 1513 | * to this function and ieee80211_tx_status_irqsafe() may not be mixed |
1514 | * for a single hardware. | 1514 | * for a single hardware. |
1515 | * | 1515 | * |
1516 | * @hw: the hardware the frame was transmitted by | 1516 | * @hw: the hardware the frame was transmitted by |
1517 | * @skb: the frame that was transmitted, owned by mac80211 after this call | 1517 | * @skb: the frame that was transmitted, owned by mac80211 after this call |
1518 | */ | 1518 | */ |
1519 | void ieee80211_tx_status(struct ieee80211_hw *hw, | 1519 | void ieee80211_tx_status(struct ieee80211_hw *hw, |
1520 | struct sk_buff *skb); | 1520 | struct sk_buff *skb); |
1521 | 1521 | ||
1522 | /** | 1522 | /** |
1523 | * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback | 1523 | * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback |
1524 | * | 1524 | * |
1525 | * Like ieee80211_tx_status() but can be called in IRQ context | 1525 | * Like ieee80211_tx_status() but can be called in IRQ context |
1526 | * (internally defers to a tasklet.) | 1526 | * (internally defers to a tasklet.) |
1527 | * | 1527 | * |
1528 | * Calls to this function and ieee80211_tx_status() may not be mixed for a | 1528 | * Calls to this function and ieee80211_tx_status() may not be mixed for a |
1529 | * single hardware. | 1529 | * single hardware. |
1530 | * | 1530 | * |
1531 | * @hw: the hardware the frame was transmitted by | 1531 | * @hw: the hardware the frame was transmitted by |
1532 | * @skb: the frame that was transmitted, owned by mac80211 after this call | 1532 | * @skb: the frame that was transmitted, owned by mac80211 after this call |
1533 | */ | 1533 | */ |
1534 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 1534 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
1535 | struct sk_buff *skb); | 1535 | struct sk_buff *skb); |
1536 | 1536 | ||
1537 | /** | 1537 | /** |
1538 | * ieee80211_beacon_get - beacon generation function | 1538 | * ieee80211_beacon_get - beacon generation function |
1539 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1539 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1540 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1540 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1541 | * | 1541 | * |
1542 | * If the beacon frames are generated by the host system (i.e., not in | 1542 | * If the beacon frames are generated by the host system (i.e., not in |
1543 | * hardware/firmware), the low-level driver uses this function to receive | 1543 | * hardware/firmware), the low-level driver uses this function to receive |
1544 | * the next beacon frame from the 802.11 code. The low-level is responsible | 1544 | * the next beacon frame from the 802.11 code. The low-level is responsible |
1545 | * for calling this function before beacon data is needed (e.g., based on | 1545 | * for calling this function before beacon data is needed (e.g., based on |
1546 | * hardware interrupt). Returned skb is used only once and low-level driver | 1546 | * hardware interrupt). Returned skb is used only once and low-level driver |
1547 | * is responsible of freeing it. | 1547 | * is responsible of freeing it. |
1548 | */ | 1548 | */ |
1549 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 1549 | struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
1550 | struct ieee80211_vif *vif); | 1550 | struct ieee80211_vif *vif); |
1551 | 1551 | ||
1552 | /** | 1552 | /** |
1553 | * ieee80211_rts_get - RTS frame generation function | 1553 | * ieee80211_rts_get - RTS frame generation function |
1554 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1554 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1555 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1555 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1556 | * @frame: pointer to the frame that is going to be protected by the RTS. | 1556 | * @frame: pointer to the frame that is going to be protected by the RTS. |
1557 | * @frame_len: the frame length (in octets). | 1557 | * @frame_len: the frame length (in octets). |
1558 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1558 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1559 | * @rts: The buffer where to store the RTS frame. | 1559 | * @rts: The buffer where to store the RTS frame. |
1560 | * | 1560 | * |
1561 | * If the RTS frames are generated by the host system (i.e., not in | 1561 | * If the RTS frames are generated by the host system (i.e., not in |
1562 | * hardware/firmware), the low-level driver uses this function to receive | 1562 | * hardware/firmware), the low-level driver uses this function to receive |
1563 | * the next RTS frame from the 802.11 code. The low-level is responsible | 1563 | * the next RTS frame from the 802.11 code. The low-level is responsible |
1564 | * for calling this function before and RTS frame is needed. | 1564 | * for calling this function before and RTS frame is needed. |
1565 | */ | 1565 | */ |
1566 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1566 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1567 | const void *frame, size_t frame_len, | 1567 | const void *frame, size_t frame_len, |
1568 | const struct ieee80211_tx_info *frame_txctl, | 1568 | const struct ieee80211_tx_info *frame_txctl, |
1569 | struct ieee80211_rts *rts); | 1569 | struct ieee80211_rts *rts); |
1570 | 1570 | ||
1571 | /** | 1571 | /** |
1572 | * ieee80211_rts_duration - Get the duration field for an RTS frame | 1572 | * ieee80211_rts_duration - Get the duration field for an RTS frame |
1573 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1573 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1574 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1574 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1575 | * @frame_len: the length of the frame that is going to be protected by the RTS. | 1575 | * @frame_len: the length of the frame that is going to be protected by the RTS. |
1576 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1576 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1577 | * | 1577 | * |
1578 | * If the RTS is generated in firmware, but the host system must provide | 1578 | * If the RTS is generated in firmware, but the host system must provide |
1579 | * the duration field, the low-level driver uses this function to receive | 1579 | * the duration field, the low-level driver uses this function to receive |
1580 | * the duration field value in little-endian byteorder. | 1580 | * the duration field value in little-endian byteorder. |
1581 | */ | 1581 | */ |
1582 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | 1582 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, |
1583 | struct ieee80211_vif *vif, size_t frame_len, | 1583 | struct ieee80211_vif *vif, size_t frame_len, |
1584 | const struct ieee80211_tx_info *frame_txctl); | 1584 | const struct ieee80211_tx_info *frame_txctl); |
1585 | 1585 | ||
1586 | /** | 1586 | /** |
1587 | * ieee80211_ctstoself_get - CTS-to-self frame generation function | 1587 | * ieee80211_ctstoself_get - CTS-to-self frame generation function |
1588 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1588 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1589 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1589 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1590 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. | 1590 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. |
1591 | * @frame_len: the frame length (in octets). | 1591 | * @frame_len: the frame length (in octets). |
1592 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1592 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1593 | * @cts: The buffer where to store the CTS-to-self frame. | 1593 | * @cts: The buffer where to store the CTS-to-self frame. |
1594 | * | 1594 | * |
1595 | * If the CTS-to-self frames are generated by the host system (i.e., not in | 1595 | * If the CTS-to-self frames are generated by the host system (i.e., not in |
1596 | * hardware/firmware), the low-level driver uses this function to receive | 1596 | * hardware/firmware), the low-level driver uses this function to receive |
1597 | * the next CTS-to-self frame from the 802.11 code. The low-level is responsible | 1597 | * the next CTS-to-self frame from the 802.11 code. The low-level is responsible |
1598 | * for calling this function before and CTS-to-self frame is needed. | 1598 | * for calling this function before and CTS-to-self frame is needed. |
1599 | */ | 1599 | */ |
1600 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, | 1600 | void ieee80211_ctstoself_get(struct ieee80211_hw *hw, |
1601 | struct ieee80211_vif *vif, | 1601 | struct ieee80211_vif *vif, |
1602 | const void *frame, size_t frame_len, | 1602 | const void *frame, size_t frame_len, |
1603 | const struct ieee80211_tx_info *frame_txctl, | 1603 | const struct ieee80211_tx_info *frame_txctl, |
1604 | struct ieee80211_cts *cts); | 1604 | struct ieee80211_cts *cts); |
1605 | 1605 | ||
1606 | /** | 1606 | /** |
1607 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame | 1607 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame |
1608 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1608 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1609 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1609 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1610 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. | 1610 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. |
1611 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1611 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1612 | * | 1612 | * |
1613 | * If the CTS-to-self is generated in firmware, but the host system must provide | 1613 | * If the CTS-to-self is generated in firmware, but the host system must provide |
1614 | * the duration field, the low-level driver uses this function to receive | 1614 | * the duration field, the low-level driver uses this function to receive |
1615 | * the duration field value in little-endian byteorder. | 1615 | * the duration field value in little-endian byteorder. |
1616 | */ | 1616 | */ |
1617 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | 1617 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, |
1618 | struct ieee80211_vif *vif, | 1618 | struct ieee80211_vif *vif, |
1619 | size_t frame_len, | 1619 | size_t frame_len, |
1620 | const struct ieee80211_tx_info *frame_txctl); | 1620 | const struct ieee80211_tx_info *frame_txctl); |
1621 | 1621 | ||
1622 | /** | 1622 | /** |
1623 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame | 1623 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame |
1624 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1624 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1625 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1625 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1626 | * @frame_len: the length of the frame. | 1626 | * @frame_len: the length of the frame. |
1627 | * @rate: the rate at which the frame is going to be transmitted. | 1627 | * @rate: the rate at which the frame is going to be transmitted. |
1628 | * | 1628 | * |
1629 | * Calculate the duration field of some generic frame, given its | 1629 | * Calculate the duration field of some generic frame, given its |
1630 | * length and transmission rate (in 100kbps). | 1630 | * length and transmission rate (in 100kbps). |
1631 | */ | 1631 | */ |
1632 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | 1632 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, |
1633 | struct ieee80211_vif *vif, | 1633 | struct ieee80211_vif *vif, |
1634 | size_t frame_len, | 1634 | size_t frame_len, |
1635 | struct ieee80211_rate *rate); | 1635 | struct ieee80211_rate *rate); |
1636 | 1636 | ||
1637 | /** | 1637 | /** |
1638 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames | 1638 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames |
1639 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1639 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1640 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1640 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. |
1641 | * | 1641 | * |
1642 | * Function for accessing buffered broadcast and multicast frames. If | 1642 | * Function for accessing buffered broadcast and multicast frames. If |
1643 | * hardware/firmware does not implement buffering of broadcast/multicast | 1643 | * hardware/firmware does not implement buffering of broadcast/multicast |
1644 | * frames when power saving is used, 802.11 code buffers them in the host | 1644 | * frames when power saving is used, 802.11 code buffers them in the host |
1645 | * memory. The low-level driver uses this function to fetch next buffered | 1645 | * memory. The low-level driver uses this function to fetch next buffered |
1646 | * frame. In most cases, this is used when generating beacon frame. This | 1646 | * frame. In most cases, this is used when generating beacon frame. This |
1647 | * function returns a pointer to the next buffered skb or NULL if no more | 1647 | * function returns a pointer to the next buffered skb or NULL if no more |
1648 | * buffered frames are available. | 1648 | * buffered frames are available. |
1649 | * | 1649 | * |
1650 | * Note: buffered frames are returned only after DTIM beacon frame was | 1650 | * Note: buffered frames are returned only after DTIM beacon frame was |
1651 | * generated with ieee80211_beacon_get() and the low-level driver must thus | 1651 | * generated with ieee80211_beacon_get() and the low-level driver must thus |
1652 | * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns | 1652 | * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns |
1653 | * NULL if the previous generated beacon was not DTIM, so the low-level driver | 1653 | * NULL if the previous generated beacon was not DTIM, so the low-level driver |
1654 | * does not need to check for DTIM beacons separately and should be able to | 1654 | * does not need to check for DTIM beacons separately and should be able to |
1655 | * use common code for all beacons. | 1655 | * use common code for all beacons. |
1656 | */ | 1656 | */ |
1657 | struct sk_buff * | 1657 | struct sk_buff * |
1658 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 1658 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
1659 | 1659 | ||
1660 | /** | 1660 | /** |
1661 | * ieee80211_get_hdrlen_from_skb - get header length from data | 1661 | * ieee80211_get_hdrlen_from_skb - get header length from data |
1662 | * | 1662 | * |
1663 | * Given an skb with a raw 802.11 header at the data pointer this function | 1663 | * Given an skb with a raw 802.11 header at the data pointer this function |
1664 | * returns the 802.11 header length in bytes (not including encryption | 1664 | * returns the 802.11 header length in bytes (not including encryption |
1665 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 | 1665 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 |
1666 | * header the function returns 0. | 1666 | * header the function returns 0. |
1667 | * | 1667 | * |
1668 | * @skb: the frame | 1668 | * @skb: the frame |
1669 | */ | 1669 | */ |
1670 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); | 1670 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); |
1671 | 1671 | ||
1672 | /** | 1672 | /** |
1673 | * ieee80211_hdrlen - get header length in bytes from frame control | 1673 | * ieee80211_hdrlen - get header length in bytes from frame control |
1674 | * @fc: frame control field in little-endian format | 1674 | * @fc: frame control field in little-endian format |
1675 | */ | 1675 | */ |
1676 | unsigned int ieee80211_hdrlen(__le16 fc); | 1676 | unsigned int ieee80211_hdrlen(__le16 fc); |
1677 | 1677 | ||
1678 | /** | 1678 | /** |
1679 | * ieee80211_get_tkip_key - get a TKIP rc4 for skb | 1679 | * ieee80211_get_tkip_key - get a TKIP rc4 for skb |
1680 | * | 1680 | * |
1681 | * This function computes a TKIP rc4 key for an skb. It computes | 1681 | * This function computes a TKIP rc4 key for an skb. It computes |
1682 | * a phase 1 key if needed (iv16 wraps around). This function is to | 1682 | * a phase 1 key if needed (iv16 wraps around). This function is to |
1683 | * be used by drivers which can do HW encryption but need to compute | 1683 | * be used by drivers which can do HW encryption but need to compute |
1684 | * to phase 1/2 key in SW. | 1684 | * to phase 1/2 key in SW. |
1685 | * | 1685 | * |
1686 | * @keyconf: the parameter passed with the set key | 1686 | * @keyconf: the parameter passed with the set key |
1687 | * @skb: the skb for which the key is needed | 1687 | * @skb: the skb for which the key is needed |
1688 | * @type: TBD | 1688 | * @type: TBD |
1689 | * @key: a buffer to which the key will be written | 1689 | * @key: a buffer to which the key will be written |
1690 | */ | 1690 | */ |
1691 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 1691 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, |
1692 | struct sk_buff *skb, | 1692 | struct sk_buff *skb, |
1693 | enum ieee80211_tkip_key_type type, u8 *key); | 1693 | enum ieee80211_tkip_key_type type, u8 *key); |
1694 | /** | 1694 | /** |
1695 | * ieee80211_wake_queue - wake specific queue | 1695 | * ieee80211_wake_queue - wake specific queue |
1696 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1696 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1697 | * @queue: queue number (counted from zero). | 1697 | * @queue: queue number (counted from zero). |
1698 | * | 1698 | * |
1699 | * Drivers should use this function instead of netif_wake_queue. | 1699 | * Drivers should use this function instead of netif_wake_queue. |
1700 | */ | 1700 | */ |
1701 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); | 1701 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); |
1702 | 1702 | ||
1703 | /** | 1703 | /** |
1704 | * ieee80211_stop_queue - stop specific queue | 1704 | * ieee80211_stop_queue - stop specific queue |
1705 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1705 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1706 | * @queue: queue number (counted from zero). | 1706 | * @queue: queue number (counted from zero). |
1707 | * | 1707 | * |
1708 | * Drivers should use this function instead of netif_stop_queue. | 1708 | * Drivers should use this function instead of netif_stop_queue. |
1709 | */ | 1709 | */ |
1710 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); | 1710 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); |
1711 | 1711 | ||
1712 | /** | 1712 | /** |
1713 | * ieee80211_queue_stopped - test status of the queue | 1713 | * ieee80211_queue_stopped - test status of the queue |
1714 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1714 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1715 | * @queue: queue number (counted from zero). | 1715 | * @queue: queue number (counted from zero). |
1716 | * | 1716 | * |
1717 | * Drivers should use this function instead of netif_stop_queue. | 1717 | * Drivers should use this function instead of netif_stop_queue. |
1718 | */ | 1718 | */ |
1719 | 1719 | ||
1720 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); | 1720 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); |
1721 | 1721 | ||
1722 | /** | 1722 | /** |
1723 | * ieee80211_stop_queues - stop all queues | 1723 | * ieee80211_stop_queues - stop all queues |
1724 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1724 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1725 | * | 1725 | * |
1726 | * Drivers should use this function instead of netif_stop_queue. | 1726 | * Drivers should use this function instead of netif_stop_queue. |
1727 | */ | 1727 | */ |
1728 | void ieee80211_stop_queues(struct ieee80211_hw *hw); | 1728 | void ieee80211_stop_queues(struct ieee80211_hw *hw); |
1729 | 1729 | ||
1730 | /** | 1730 | /** |
1731 | * ieee80211_wake_queues - wake all queues | 1731 | * ieee80211_wake_queues - wake all queues |
1732 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1732 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1733 | * | 1733 | * |
1734 | * Drivers should use this function instead of netif_wake_queue. | 1734 | * Drivers should use this function instead of netif_wake_queue. |
1735 | */ | 1735 | */ |
1736 | void ieee80211_wake_queues(struct ieee80211_hw *hw); | 1736 | void ieee80211_wake_queues(struct ieee80211_hw *hw); |
1737 | 1737 | ||
1738 | /** | 1738 | /** |
1739 | * ieee80211_scan_completed - completed hardware scan | 1739 | * ieee80211_scan_completed - completed hardware scan |
1740 | * | 1740 | * |
1741 | * When hardware scan offload is used (i.e. the hw_scan() callback is | 1741 | * When hardware scan offload is used (i.e. the hw_scan() callback is |
1742 | * assigned) this function needs to be called by the driver to notify | 1742 | * assigned) this function needs to be called by the driver to notify |
1743 | * mac80211 that the scan finished. | 1743 | * mac80211 that the scan finished. |
1744 | * | 1744 | * |
1745 | * @hw: the hardware that finished the scan | 1745 | * @hw: the hardware that finished the scan |
1746 | */ | 1746 | */ |
1747 | void ieee80211_scan_completed(struct ieee80211_hw *hw); | 1747 | void ieee80211_scan_completed(struct ieee80211_hw *hw); |
1748 | 1748 | ||
1749 | /** | 1749 | /** |
1750 | * ieee80211_iterate_active_interfaces - iterate active interfaces | 1750 | * ieee80211_iterate_active_interfaces - iterate active interfaces |
1751 | * | 1751 | * |
1752 | * This function iterates over the interfaces associated with a given | 1752 | * This function iterates over the interfaces associated with a given |
1753 | * hardware that are currently active and calls the callback for them. | 1753 | * hardware that are currently active and calls the callback for them. |
1754 | * This function allows the iterator function to sleep, when the iterator | 1754 | * This function allows the iterator function to sleep, when the iterator |
1755 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can | 1755 | * function is atomic @ieee80211_iterate_active_interfaces_atomic can |
1756 | * be used. | 1756 | * be used. |
1757 | * | 1757 | * |
1758 | * @hw: the hardware struct of which the interfaces should be iterated over | 1758 | * @hw: the hardware struct of which the interfaces should be iterated over |
1759 | * @iterator: the iterator function to call | 1759 | * @iterator: the iterator function to call |
1760 | * @data: first argument of the iterator function | 1760 | * @data: first argument of the iterator function |
1761 | */ | 1761 | */ |
1762 | void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, | 1762 | void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, |
1763 | void (*iterator)(void *data, u8 *mac, | 1763 | void (*iterator)(void *data, u8 *mac, |
1764 | struct ieee80211_vif *vif), | 1764 | struct ieee80211_vif *vif), |
1765 | void *data); | 1765 | void *data); |
1766 | 1766 | ||
1767 | /** | 1767 | /** |
1768 | * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces | 1768 | * ieee80211_iterate_active_interfaces_atomic - iterate active interfaces |
1769 | * | 1769 | * |
1770 | * This function iterates over the interfaces associated with a given | 1770 | * This function iterates over the interfaces associated with a given |
1771 | * hardware that are currently active and calls the callback for them. | 1771 | * hardware that are currently active and calls the callback for them. |
1772 | * This function requires the iterator callback function to be atomic, | 1772 | * This function requires the iterator callback function to be atomic, |
1773 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. | 1773 | * if that is not desired, use @ieee80211_iterate_active_interfaces instead. |
1774 | * | 1774 | * |
1775 | * @hw: the hardware struct of which the interfaces should be iterated over | 1775 | * @hw: the hardware struct of which the interfaces should be iterated over |
1776 | * @iterator: the iterator function to call, cannot sleep | 1776 | * @iterator: the iterator function to call, cannot sleep |
1777 | * @data: first argument of the iterator function | 1777 | * @data: first argument of the iterator function |
1778 | */ | 1778 | */ |
1779 | void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, | 1779 | void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, |
1780 | void (*iterator)(void *data, | 1780 | void (*iterator)(void *data, |
1781 | u8 *mac, | 1781 | u8 *mac, |
1782 | struct ieee80211_vif *vif), | 1782 | struct ieee80211_vif *vif), |
1783 | void *data); | 1783 | void *data); |
1784 | 1784 | ||
1785 | /** | 1785 | /** |
1786 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. | 1786 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. |
1787 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1787 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1788 | * @ra: receiver address of the BA session recipient | 1788 | * @ra: receiver address of the BA session recipient |
1789 | * @tid: the TID to BA on. | 1789 | * @tid: the TID to BA on. |
1790 | * | 1790 | * |
1791 | * Return: success if addBA request was sent, failure otherwise | 1791 | * Return: success if addBA request was sent, failure otherwise |
1792 | * | 1792 | * |
1793 | * Although mac80211/low level driver/user space application can estimate | 1793 | * Although mac80211/low level driver/user space application can estimate |
1794 | * the need to start aggregation on a certain RA/TID, the session level | 1794 | * the need to start aggregation on a certain RA/TID, the session level |
1795 | * will be managed by the mac80211. | 1795 | * will be managed by the mac80211. |
1796 | */ | 1796 | */ |
1797 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 1797 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); |
1798 | 1798 | ||
1799 | /** | 1799 | /** |
1800 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. | 1800 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. |
1801 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1801 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1802 | * @ra: receiver address of the BA session recipient. | 1802 | * @ra: receiver address of the BA session recipient. |
1803 | * @tid: the TID to BA on. | 1803 | * @tid: the TID to BA on. |
1804 | * | 1804 | * |
1805 | * This function must be called by low level driver once it has | 1805 | * This function must be called by low level driver once it has |
1806 | * finished with preparations for the BA session. | 1806 | * finished with preparations for the BA session. |
1807 | */ | 1807 | */ |
1808 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 1808 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); |
1809 | 1809 | ||
1810 | /** | 1810 | /** |
1811 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. | 1811 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. |
1812 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1812 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1813 | * @ra: receiver address of the BA session recipient. | 1813 | * @ra: receiver address of the BA session recipient. |
1814 | * @tid: the TID to BA on. | 1814 | * @tid: the TID to BA on. |
1815 | * | 1815 | * |
1816 | * This function must be called by low level driver once it has | 1816 | * This function must be called by low level driver once it has |
1817 | * finished with preparations for the BA session. | 1817 | * finished with preparations for the BA session. |
1818 | * This version of the function is IRQ-safe. | 1818 | * This version of the function is IRQ-safe. |
1819 | */ | 1819 | */ |
1820 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1820 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1821 | u16 tid); | 1821 | u16 tid); |
1822 | 1822 | ||
1823 | /** | 1823 | /** |
1824 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. | 1824 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. |
1825 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1825 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1826 | * @ra: receiver address of the BA session recipient | 1826 | * @ra: receiver address of the BA session recipient |
1827 | * @tid: the TID to stop BA. | 1827 | * @tid: the TID to stop BA. |
1828 | * @initiator: if indicates initiator DELBA frame will be sent. | 1828 | * @initiator: if indicates initiator DELBA frame will be sent. |
1829 | * | 1829 | * |
1830 | * Return: error if no sta with matching da found, success otherwise | 1830 | * Return: error if no sta with matching da found, success otherwise |
1831 | * | 1831 | * |
1832 | * Although mac80211/low level driver/user space application can estimate | 1832 | * Although mac80211/low level driver/user space application can estimate |
1833 | * the need to stop aggregation on a certain RA/TID, the session level | 1833 | * the need to stop aggregation on a certain RA/TID, the session level |
1834 | * will be managed by the mac80211. | 1834 | * will be managed by the mac80211. |
1835 | */ | 1835 | */ |
1836 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | 1836 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, |
1837 | u8 *ra, u16 tid, | 1837 | u8 *ra, u16 tid, |
1838 | enum ieee80211_back_parties initiator); | 1838 | enum ieee80211_back_parties initiator); |
1839 | 1839 | ||
1840 | /** | 1840 | /** |
1841 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. | 1841 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. |
1842 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1842 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1843 | * @ra: receiver address of the BA session recipient. | 1843 | * @ra: receiver address of the BA session recipient. |
1844 | * @tid: the desired TID to BA on. | 1844 | * @tid: the desired TID to BA on. |
1845 | * | 1845 | * |
1846 | * This function must be called by low level driver once it has | 1846 | * This function must be called by low level driver once it has |
1847 | * finished with preparations for the BA session tear down. | 1847 | * finished with preparations for the BA session tear down. |
1848 | */ | 1848 | */ |
1849 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); | 1849 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); |
1850 | 1850 | ||
1851 | /** | 1851 | /** |
1852 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. | 1852 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. |
1853 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1853 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1854 | * @ra: receiver address of the BA session recipient. | 1854 | * @ra: receiver address of the BA session recipient. |
1855 | * @tid: the desired TID to BA on. | 1855 | * @tid: the desired TID to BA on. |
1856 | * | 1856 | * |
1857 | * This function must be called by low level driver once it has | 1857 | * This function must be called by low level driver once it has |
1858 | * finished with preparations for the BA session tear down. | 1858 | * finished with preparations for the BA session tear down. |
1859 | * This version of the function is IRQ-safe. | 1859 | * This version of the function is IRQ-safe. |
1860 | */ | 1860 | */ |
1861 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1861 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1862 | u16 tid); | 1862 | u16 tid); |
1863 | 1863 | ||
1864 | /** | 1864 | /** |
1865 | * ieee80211_notify_mac - low level driver notification | 1865 | * ieee80211_notify_mac - low level driver notification |
1866 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1866 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1867 | * @notif_type: enum ieee80211_notification_types | 1867 | * @notif_type: enum ieee80211_notification_types |
1868 | * | 1868 | * |
1869 | * This function must be called by low level driver to inform mac80211 of | 1869 | * This function must be called by low level driver to inform mac80211 of |
1870 | * low level driver status change or force mac80211 to re-assoc for low | 1870 | * low level driver status change or force mac80211 to re-assoc for low |
1871 | * level driver internal error that require re-assoc. | 1871 | * level driver internal error that require re-assoc. |
1872 | */ | 1872 | */ |
1873 | void ieee80211_notify_mac(struct ieee80211_hw *hw, | 1873 | void ieee80211_notify_mac(struct ieee80211_hw *hw, |
1874 | enum ieee80211_notification_types notif_type); | 1874 | enum ieee80211_notification_types notif_type); |
1875 | 1875 | ||
1876 | /** | 1876 | /** |
1877 | * ieee80211_find_sta - find a station | 1877 | * ieee80211_find_sta - find a station |
1878 | * | 1878 | * |
1879 | * @hw: pointer as obtained from ieee80211_alloc_hw() | 1879 | * @hw: pointer as obtained from ieee80211_alloc_hw() |
1880 | * @addr: station's address | 1880 | * @addr: station's address |
1881 | * | 1881 | * |
1882 | * This function must be called under RCU lock and the | 1882 | * This function must be called under RCU lock and the |
1883 | * resulting pointer is only valid under RCU lock as well. | 1883 | * resulting pointer is only valid under RCU lock as well. |
1884 | */ | 1884 | */ |
1885 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 1885 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
1886 | const u8 *addr); | 1886 | const u8 *addr); |
1887 | 1887 | ||
1888 | 1888 | ||
1889 | /* Rate control API */ | 1889 | /* Rate control API */ |
1890 | 1890 | ||
1891 | /** | 1891 | /** |
1892 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo | 1892 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo |
1893 | * | 1893 | * |
1894 | * @hw: The hardware the algorithm is invoked for. | 1894 | * @hw: The hardware the algorithm is invoked for. |
1895 | * @sband: The band this frame is being transmitted on. | 1895 | * @sband: The band this frame is being transmitted on. |
1896 | * @bss_conf: the current BSS configuration | 1896 | * @bss_conf: the current BSS configuration |
1897 | * @reported_rate: The rate control algorithm can fill this in to indicate | 1897 | * @reported_rate: The rate control algorithm can fill this in to indicate |
1898 | * which rate should be reported to userspace as the current rate and | 1898 | * which rate should be reported to userspace as the current rate and |
1899 | * used for rate calculations in the mesh network. | 1899 | * used for rate calculations in the mesh network. |
1900 | * @rts: whether RTS will be used for this frame because it is longer than the | 1900 | * @rts: whether RTS will be used for this frame because it is longer than the |
1901 | * RTS threshold | 1901 | * RTS threshold |
1902 | * @short_preamble: whether mac80211 will request short-preamble transmission | 1902 | * @short_preamble: whether mac80211 will request short-preamble transmission |
1903 | * if the selected rate supports it | 1903 | * if the selected rate supports it |
1904 | * @max_rate_idx: user-requested maximum rate (not MCS for now) | 1904 | * @max_rate_idx: user-requested maximum rate (not MCS for now) |
1905 | */ | 1905 | */ |
1906 | struct ieee80211_tx_rate_control { | 1906 | struct ieee80211_tx_rate_control { |
1907 | struct ieee80211_hw *hw; | 1907 | struct ieee80211_hw *hw; |
1908 | struct ieee80211_supported_band *sband; | 1908 | struct ieee80211_supported_band *sband; |
1909 | struct ieee80211_bss_conf *bss_conf; | 1909 | struct ieee80211_bss_conf *bss_conf; |
1910 | struct sk_buff *skb; | 1910 | struct sk_buff *skb; |
1911 | struct ieee80211_tx_rate reported_rate; | 1911 | struct ieee80211_tx_rate reported_rate; |
1912 | bool rts, short_preamble; | 1912 | bool rts, short_preamble; |
1913 | u8 max_rate_idx; | 1913 | u8 max_rate_idx; |
1914 | }; | 1914 | }; |
1915 | 1915 | ||
1916 | struct rate_control_ops { | 1916 | struct rate_control_ops { |
1917 | struct module *module; | 1917 | struct module *module; |
1918 | const char *name; | 1918 | const char *name; |
1919 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); | 1919 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); |
1920 | void (*clear)(void *priv); | ||
1921 | void (*free)(void *priv); | 1920 | void (*free)(void *priv); |
1922 | 1921 | ||
1923 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); | 1922 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); |
1924 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | 1923 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, |
1925 | struct ieee80211_sta *sta, void *priv_sta); | 1924 | struct ieee80211_sta *sta, void *priv_sta); |
1926 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | 1925 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, |
1927 | void *priv_sta); | 1926 | void *priv_sta); |
1928 | 1927 | ||
1929 | void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, | 1928 | void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, |
1930 | struct ieee80211_sta *sta, void *priv_sta, | 1929 | struct ieee80211_sta *sta, void *priv_sta, |
1931 | struct sk_buff *skb); | 1930 | struct sk_buff *skb); |
1932 | void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, | 1931 | void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, |
1933 | struct ieee80211_tx_rate_control *txrc); | 1932 | struct ieee80211_tx_rate_control *txrc); |
1934 | 1933 | ||
1935 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | 1934 | void (*add_sta_debugfs)(void *priv, void *priv_sta, |
1936 | struct dentry *dir); | 1935 | struct dentry *dir); |
1937 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | 1936 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); |
1938 | }; | 1937 | }; |
1939 | 1938 | ||
1940 | static inline int rate_supported(struct ieee80211_sta *sta, | 1939 | static inline int rate_supported(struct ieee80211_sta *sta, |
1941 | enum ieee80211_band band, | 1940 | enum ieee80211_band band, |
1942 | int index) | 1941 | int index) |
1943 | { | 1942 | { |
1944 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | 1943 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); |
1945 | } | 1944 | } |
1946 | 1945 | ||
1947 | static inline s8 | 1946 | static inline s8 |
1948 | rate_lowest_index(struct ieee80211_supported_band *sband, | 1947 | rate_lowest_index(struct ieee80211_supported_band *sband, |
1949 | struct ieee80211_sta *sta) | 1948 | struct ieee80211_sta *sta) |
1950 | { | 1949 | { |
1951 | int i; | 1950 | int i; |
1952 | 1951 | ||
1953 | for (i = 0; i < sband->n_bitrates; i++) | 1952 | for (i = 0; i < sband->n_bitrates; i++) |
1954 | if (rate_supported(sta, sband->band, i)) | 1953 | if (rate_supported(sta, sband->band, i)) |
1955 | return i; | 1954 | return i; |
1956 | 1955 | ||
1957 | /* warn when we cannot find a rate. */ | 1956 | /* warn when we cannot find a rate. */ |
1958 | WARN_ON(1); | 1957 | WARN_ON(1); |
1959 | 1958 | ||
1960 | return 0; | 1959 | return 0; |
1961 | } | 1960 | } |
1962 | 1961 | ||
1963 | 1962 | ||
1964 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | 1963 | int ieee80211_rate_control_register(struct rate_control_ops *ops); |
1965 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | 1964 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); |
1966 | 1965 | ||
1967 | #endif /* MAC80211_H */ | 1966 | #endif /* MAC80211_H */ |
1968 | 1967 |
net/mac80211/rate.h
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #ifndef IEEE80211_RATE_H | 11 | #ifndef IEEE80211_RATE_H |
12 | #define IEEE80211_RATE_H | 12 | #define IEEE80211_RATE_H |
13 | 13 | ||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/kref.h> | 17 | #include <linux/kref.h> |
18 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | 23 | struct ieee80211_local *local; |
24 | struct rate_control_ops *ops; | 24 | struct rate_control_ops *ops; |
25 | void *priv; | 25 | void *priv; |
26 | struct kref kref; | 26 | struct kref kref; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
30 | * first available algorithm. */ | 30 | * first available algorithm. */ |
31 | struct rate_control_ref *rate_control_alloc(const char *name, | 31 | struct rate_control_ref *rate_control_alloc(const char *name, |
32 | struct ieee80211_local *local); | 32 | struct ieee80211_local *local); |
33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
34 | struct sta_info *sta, | 34 | struct sta_info *sta, |
35 | struct ieee80211_tx_rate_control *txrc); | 35 | struct ieee80211_tx_rate_control *txrc); |
36 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 36 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
37 | void rate_control_put(struct rate_control_ref *ref); | 37 | void rate_control_put(struct rate_control_ref *ref); |
38 | 38 | ||
39 | static inline void rate_control_tx_status(struct ieee80211_local *local, | 39 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
40 | struct ieee80211_supported_band *sband, | 40 | struct ieee80211_supported_band *sband, |
41 | struct sta_info *sta, | 41 | struct sta_info *sta, |
42 | struct sk_buff *skb) | 42 | struct sk_buff *skb) |
43 | { | 43 | { |
44 | struct rate_control_ref *ref = local->rate_ctrl; | 44 | struct rate_control_ref *ref = local->rate_ctrl; |
45 | struct ieee80211_sta *ista = &sta->sta; | 45 | struct ieee80211_sta *ista = &sta->sta; |
46 | void *priv_sta = sta->rate_ctrl_priv; | 46 | void *priv_sta = sta->rate_ctrl_priv; |
47 | 47 | ||
48 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | 48 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | static inline void rate_control_rate_init(struct sta_info *sta) | 52 | static inline void rate_control_rate_init(struct sta_info *sta) |
53 | { | 53 | { |
54 | struct ieee80211_local *local = sta->sdata->local; | 54 | struct ieee80211_local *local = sta->sdata->local; |
55 | struct rate_control_ref *ref = sta->rate_ctrl; | 55 | struct rate_control_ref *ref = sta->rate_ctrl; |
56 | struct ieee80211_sta *ista = &sta->sta; | 56 | struct ieee80211_sta *ista = &sta->sta; |
57 | void *priv_sta = sta->rate_ctrl_priv; | 57 | void *priv_sta = sta->rate_ctrl_priv; |
58 | struct ieee80211_supported_band *sband; | 58 | struct ieee80211_supported_band *sband; |
59 | 59 | ||
60 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 60 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
61 | 61 | ||
62 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 62 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | static inline void rate_control_clear(struct ieee80211_local *local) | ||
67 | { | ||
68 | struct rate_control_ref *ref = local->rate_ctrl; | ||
69 | ref->ops->clear(ref->priv); | ||
70 | } | ||
71 | |||
72 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 66 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
73 | struct ieee80211_sta *sta, | 67 | struct ieee80211_sta *sta, |
74 | gfp_t gfp) | 68 | gfp_t gfp) |
75 | { | 69 | { |
76 | return ref->ops->alloc_sta(ref->priv, sta, gfp); | 70 | return ref->ops->alloc_sta(ref->priv, sta, gfp); |
77 | } | 71 | } |
78 | 72 | ||
79 | static inline void rate_control_free_sta(struct sta_info *sta) | 73 | static inline void rate_control_free_sta(struct sta_info *sta) |
80 | { | 74 | { |
81 | struct rate_control_ref *ref = sta->rate_ctrl; | 75 | struct rate_control_ref *ref = sta->rate_ctrl; |
82 | struct ieee80211_sta *ista = &sta->sta; | 76 | struct ieee80211_sta *ista = &sta->sta; |
83 | void *priv_sta = sta->rate_ctrl_priv; | 77 | void *priv_sta = sta->rate_ctrl_priv; |
84 | 78 | ||
85 | ref->ops->free_sta(ref->priv, ista, priv_sta); | 79 | ref->ops->free_sta(ref->priv, ista, priv_sta); |
86 | } | 80 | } |
87 | 81 | ||
88 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | 82 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) |
89 | { | 83 | { |
90 | #ifdef CONFIG_MAC80211_DEBUGFS | 84 | #ifdef CONFIG_MAC80211_DEBUGFS |
91 | struct rate_control_ref *ref = sta->rate_ctrl; | 85 | struct rate_control_ref *ref = sta->rate_ctrl; |
92 | if (sta->debugfs.dir && ref->ops->add_sta_debugfs) | 86 | if (sta->debugfs.dir && ref->ops->add_sta_debugfs) |
93 | ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, | 87 | ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, |
94 | sta->debugfs.dir); | 88 | sta->debugfs.dir); |
95 | #endif | 89 | #endif |
96 | } | 90 | } |
97 | 91 | ||
98 | static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | 92 | static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) |
99 | { | 93 | { |
100 | #ifdef CONFIG_MAC80211_DEBUGFS | 94 | #ifdef CONFIG_MAC80211_DEBUGFS |
101 | struct rate_control_ref *ref = sta->rate_ctrl; | 95 | struct rate_control_ref *ref = sta->rate_ctrl; |
102 | if (ref->ops->remove_sta_debugfs) | 96 | if (ref->ops->remove_sta_debugfs) |
103 | ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); | 97 | ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); |
104 | #endif | 98 | #endif |
105 | } | 99 | } |
106 | 100 | ||
107 | /* functions for rate control related to a device */ | 101 | /* functions for rate control related to a device */ |
108 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 102 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
109 | const char *name); | 103 | const char *name); |
110 | void rate_control_deinitialize(struct ieee80211_local *local); | 104 | void rate_control_deinitialize(struct ieee80211_local *local); |
111 | 105 | ||
112 | 106 | ||
113 | /* Rate control algorithms */ | 107 | /* Rate control algorithms */ |
114 | #ifdef CONFIG_MAC80211_RC_PID | 108 | #ifdef CONFIG_MAC80211_RC_PID |
115 | extern int rc80211_pid_init(void); | 109 | extern int rc80211_pid_init(void); |
116 | extern void rc80211_pid_exit(void); | 110 | extern void rc80211_pid_exit(void); |
117 | #else | 111 | #else |
118 | static inline int rc80211_pid_init(void) | 112 | static inline int rc80211_pid_init(void) |
119 | { | 113 | { |
120 | return 0; | 114 | return 0; |
121 | } | 115 | } |
122 | static inline void rc80211_pid_exit(void) | 116 | static inline void rc80211_pid_exit(void) |
123 | { | 117 | { |
124 | } | 118 | } |
125 | #endif | 119 | #endif |
126 | 120 | ||
127 | #ifdef CONFIG_MAC80211_RC_MINSTREL | 121 | #ifdef CONFIG_MAC80211_RC_MINSTREL |
128 | extern int rc80211_minstrel_init(void); | 122 | extern int rc80211_minstrel_init(void); |
129 | extern void rc80211_minstrel_exit(void); | 123 | extern void rc80211_minstrel_exit(void); |
130 | #else | 124 | #else |
131 | static inline int rc80211_minstrel_init(void) | 125 | static inline int rc80211_minstrel_init(void) |
132 | { | 126 | { |
133 | return 0; | 127 | return 0; |
134 | } | 128 | } |
135 | static inline void rc80211_minstrel_exit(void) | 129 | static inline void rc80211_minstrel_exit(void) |
136 | { | 130 | { |
137 | } | 131 | } |
138 | #endif | 132 | #endif |
139 | 133 | ||
140 | 134 | ||
141 | #endif /* IEEE80211_RATE_H */ | 135 | #endif /* IEEE80211_RATE_H */ |
142 | 136 |
net/mac80211/rc80211_minstrel.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | 2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | * | 7 | * |
8 | * Based on minstrel.c: | 8 | * Based on minstrel.c: |
9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> | 9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> |
10 | * Sponsored by Indranet Technologies Ltd | 10 | * Sponsored by Indranet Technologies Ltd |
11 | * | 11 | * |
12 | * Based on sample.c: | 12 | * Based on sample.c: |
13 | * Copyright (c) 2005 John Bicket | 13 | * Copyright (c) 2005 John Bicket |
14 | * All rights reserved. | 14 | * All rights reserved. |
15 | * | 15 | * |
16 | * Redistribution and use in source and binary forms, with or without | 16 | * Redistribution and use in source and binary forms, with or without |
17 | * modification, are permitted provided that the following conditions | 17 | * modification, are permitted provided that the following conditions |
18 | * are met: | 18 | * are met: |
19 | * 1. Redistributions of source code must retain the above copyright | 19 | * 1. Redistributions of source code must retain the above copyright |
20 | * notice, this list of conditions and the following disclaimer, | 20 | * notice, this list of conditions and the following disclaimer, |
21 | * without modification. | 21 | * without modification. |
22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | 22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | 23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any |
24 | * redistribution must be conditioned upon including a substantially | 24 | * redistribution must be conditioned upon including a substantially |
25 | * similar Disclaimer requirement for further binary redistribution. | 25 | * similar Disclaimer requirement for further binary redistribution. |
26 | * 3. Neither the names of the above-listed copyright holders nor the names | 26 | * 3. Neither the names of the above-listed copyright holders nor the names |
27 | * of any contributors may be used to endorse or promote products derived | 27 | * of any contributors may be used to endorse or promote products derived |
28 | * from this software without specific prior written permission. | 28 | * from this software without specific prior written permission. |
29 | * | 29 | * |
30 | * Alternatively, this software may be distributed under the terms of the | 30 | * Alternatively, this software may be distributed under the terms of the |
31 | * GNU General Public License ("GPL") version 2 as published by the Free | 31 | * GNU General Public License ("GPL") version 2 as published by the Free |
32 | * Software Foundation. | 32 | * Software Foundation. |
33 | * | 33 | * |
34 | * NO WARRANTY | 34 | * NO WARRANTY |
35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | 37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY |
38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | 38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | 39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, |
40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | 42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
45 | * THE POSSIBILITY OF SUCH DAMAGES. | 45 | * THE POSSIBILITY OF SUCH DAMAGES. |
46 | */ | 46 | */ |
47 | #include <linux/netdevice.h> | 47 | #include <linux/netdevice.h> |
48 | #include <linux/types.h> | 48 | #include <linux/types.h> |
49 | #include <linux/skbuff.h> | 49 | #include <linux/skbuff.h> |
50 | #include <linux/debugfs.h> | 50 | #include <linux/debugfs.h> |
51 | #include <linux/random.h> | 51 | #include <linux/random.h> |
52 | #include <linux/ieee80211.h> | 52 | #include <linux/ieee80211.h> |
53 | #include <net/mac80211.h> | 53 | #include <net/mac80211.h> |
54 | #include "rate.h" | 54 | #include "rate.h" |
55 | #include "rc80211_minstrel.h" | 55 | #include "rc80211_minstrel.h" |
56 | 56 | ||
57 | #define SAMPLE_COLUMNS 10 | 57 | #define SAMPLE_COLUMNS 10 |
58 | #define SAMPLE_TBL(_mi, _idx, _col) \ | 58 | #define SAMPLE_TBL(_mi, _idx, _col) \ |
59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] | 59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] |
60 | 60 | ||
61 | /* convert mac80211 rate index to local array index */ | 61 | /* convert mac80211 rate index to local array index */ |
62 | static inline int | 62 | static inline int |
63 | rix_to_ndx(struct minstrel_sta_info *mi, int rix) | 63 | rix_to_ndx(struct minstrel_sta_info *mi, int rix) |
64 | { | 64 | { |
65 | int i = rix; | 65 | int i = rix; |
66 | for (i = rix; i >= 0; i--) | 66 | for (i = rix; i >= 0; i--) |
67 | if (mi->r[i].rix == rix) | 67 | if (mi->r[i].rix == rix) |
68 | break; | 68 | break; |
69 | WARN_ON(mi->r[i].rix != rix); | 69 | WARN_ON(mi->r[i].rix != rix); |
70 | return i; | 70 | return i; |
71 | } | 71 | } |
72 | 72 | ||
73 | static inline bool | 73 | static inline bool |
74 | use_low_rate(struct sk_buff *skb) | 74 | use_low_rate(struct sk_buff *skb) |
75 | { | 75 | { |
76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
78 | u16 fc; | 78 | u16 fc; |
79 | 79 | ||
80 | fc = le16_to_cpu(hdr->frame_control); | 80 | fc = le16_to_cpu(hdr->frame_control); |
81 | 81 | ||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | 82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || |
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
84 | is_multicast_ether_addr(hdr->addr1)); | 84 | is_multicast_ether_addr(hdr->addr1)); |
85 | } | 85 | } |
86 | 86 | ||
87 | 87 | ||
88 | static void | 88 | static void |
89 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 89 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
90 | { | 90 | { |
91 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | 91 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; |
92 | u32 max_prob = 0, index_max_prob = 0; | 92 | u32 max_prob = 0, index_max_prob = 0; |
93 | u32 usecs; | 93 | u32 usecs; |
94 | u32 p; | 94 | u32 p; |
95 | int i; | 95 | int i; |
96 | 96 | ||
97 | mi->stats_update = jiffies; | 97 | mi->stats_update = jiffies; |
98 | for (i = 0; i < mi->n_rates; i++) { | 98 | for (i = 0; i < mi->n_rates; i++) { |
99 | struct minstrel_rate *mr = &mi->r[i]; | 99 | struct minstrel_rate *mr = &mi->r[i]; |
100 | 100 | ||
101 | usecs = mr->perfect_tx_time; | 101 | usecs = mr->perfect_tx_time; |
102 | if (!usecs) | 102 | if (!usecs) |
103 | usecs = 1000000; | 103 | usecs = 1000000; |
104 | 104 | ||
105 | /* To avoid rounding issues, probabilities scale from 0 (0%) | 105 | /* To avoid rounding issues, probabilities scale from 0 (0%) |
106 | * to 18000 (100%) */ | 106 | * to 18000 (100%) */ |
107 | if (mr->attempts) { | 107 | if (mr->attempts) { |
108 | p = (mr->success * 18000) / mr->attempts; | 108 | p = (mr->success * 18000) / mr->attempts; |
109 | mr->succ_hist += mr->success; | 109 | mr->succ_hist += mr->success; |
110 | mr->att_hist += mr->attempts; | 110 | mr->att_hist += mr->attempts; |
111 | mr->cur_prob = p; | 111 | mr->cur_prob = p; |
112 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * | 112 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * |
113 | mp->ewma_level)) / 100; | 113 | mp->ewma_level)) / 100; |
114 | mr->probability = p; | 114 | mr->probability = p; |
115 | mr->cur_tp = p * (1000000 / usecs); | 115 | mr->cur_tp = p * (1000000 / usecs); |
116 | } | 116 | } |
117 | 117 | ||
118 | mr->last_success = mr->success; | 118 | mr->last_success = mr->success; |
119 | mr->last_attempts = mr->attempts; | 119 | mr->last_attempts = mr->attempts; |
120 | mr->success = 0; | 120 | mr->success = 0; |
121 | mr->attempts = 0; | 121 | mr->attempts = 0; |
122 | 122 | ||
123 | /* Sample less often below the 10% chance of success. | 123 | /* Sample less often below the 10% chance of success. |
124 | * Sample less often above the 95% chance of success. */ | 124 | * Sample less often above the 95% chance of success. */ |
125 | if ((mr->probability > 17100) || (mr->probability < 1800)) { | 125 | if ((mr->probability > 17100) || (mr->probability < 1800)) { |
126 | mr->adjusted_retry_count = mr->retry_count >> 1; | 126 | mr->adjusted_retry_count = mr->retry_count >> 1; |
127 | if (mr->adjusted_retry_count > 2) | 127 | if (mr->adjusted_retry_count > 2) |
128 | mr->adjusted_retry_count = 2; | 128 | mr->adjusted_retry_count = 2; |
129 | mr->sample_limit = 4; | 129 | mr->sample_limit = 4; |
130 | } else { | 130 | } else { |
131 | mr->sample_limit = -1; | 131 | mr->sample_limit = -1; |
132 | mr->adjusted_retry_count = mr->retry_count; | 132 | mr->adjusted_retry_count = mr->retry_count; |
133 | } | 133 | } |
134 | if (!mr->adjusted_retry_count) | 134 | if (!mr->adjusted_retry_count) |
135 | mr->adjusted_retry_count = 2; | 135 | mr->adjusted_retry_count = 2; |
136 | } | 136 | } |
137 | 137 | ||
138 | for (i = 0; i < mi->n_rates; i++) { | 138 | for (i = 0; i < mi->n_rates; i++) { |
139 | struct minstrel_rate *mr = &mi->r[i]; | 139 | struct minstrel_rate *mr = &mi->r[i]; |
140 | if (max_tp < mr->cur_tp) { | 140 | if (max_tp < mr->cur_tp) { |
141 | index_max_tp = i; | 141 | index_max_tp = i; |
142 | max_tp = mr->cur_tp; | 142 | max_tp = mr->cur_tp; |
143 | } | 143 | } |
144 | if (max_prob < mr->probability) { | 144 | if (max_prob < mr->probability) { |
145 | index_max_prob = i; | 145 | index_max_prob = i; |
146 | max_prob = mr->probability; | 146 | max_prob = mr->probability; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | max_tp = 0; | 150 | max_tp = 0; |
151 | for (i = 0; i < mi->n_rates; i++) { | 151 | for (i = 0; i < mi->n_rates; i++) { |
152 | struct minstrel_rate *mr = &mi->r[i]; | 152 | struct minstrel_rate *mr = &mi->r[i]; |
153 | 153 | ||
154 | if (i == index_max_tp) | 154 | if (i == index_max_tp) |
155 | continue; | 155 | continue; |
156 | 156 | ||
157 | if (max_tp < mr->cur_tp) { | 157 | if (max_tp < mr->cur_tp) { |
158 | index_max_tp2 = i; | 158 | index_max_tp2 = i; |
159 | max_tp = mr->cur_tp; | 159 | max_tp = mr->cur_tp; |
160 | } | 160 | } |
161 | } | 161 | } |
162 | mi->max_tp_rate = index_max_tp; | 162 | mi->max_tp_rate = index_max_tp; |
163 | mi->max_tp_rate2 = index_max_tp2; | 163 | mi->max_tp_rate2 = index_max_tp2; |
164 | mi->max_prob_rate = index_max_prob; | 164 | mi->max_prob_rate = index_max_prob; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void | 167 | static void |
168 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | 168 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, |
169 | struct ieee80211_sta *sta, void *priv_sta, | 169 | struct ieee80211_sta *sta, void *priv_sta, |
170 | struct sk_buff *skb) | 170 | struct sk_buff *skb) |
171 | { | 171 | { |
172 | struct minstrel_sta_info *mi = priv_sta; | 172 | struct minstrel_sta_info *mi = priv_sta; |
173 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 173 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
174 | struct ieee80211_tx_rate *ar = info->status.rates; | 174 | struct ieee80211_tx_rate *ar = info->status.rates; |
175 | int i, ndx; | 175 | int i, ndx; |
176 | int success; | 176 | int success; |
177 | 177 | ||
178 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); | 178 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
179 | 179 | ||
180 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 180 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
181 | if (ar[i].idx < 0) | 181 | if (ar[i].idx < 0) |
182 | break; | 182 | break; |
183 | 183 | ||
184 | ndx = rix_to_ndx(mi, ar[i].idx); | 184 | ndx = rix_to_ndx(mi, ar[i].idx); |
185 | mi->r[ndx].attempts += ar[i].count; | 185 | mi->r[ndx].attempts += ar[i].count; |
186 | 186 | ||
187 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) | 187 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) |
188 | mi->r[ndx].success += success; | 188 | mi->r[ndx].success += success; |
189 | } | 189 | } |
190 | 190 | ||
191 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) | 191 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) |
192 | mi->sample_count++; | 192 | mi->sample_count++; |
193 | 193 | ||
194 | if (mi->sample_deferred > 0) | 194 | if (mi->sample_deferred > 0) |
195 | mi->sample_deferred--; | 195 | mi->sample_deferred--; |
196 | } | 196 | } |
197 | 197 | ||
198 | 198 | ||
199 | static inline unsigned int | 199 | static inline unsigned int |
200 | minstrel_get_retry_count(struct minstrel_rate *mr, | 200 | minstrel_get_retry_count(struct minstrel_rate *mr, |
201 | struct ieee80211_tx_info *info) | 201 | struct ieee80211_tx_info *info) |
202 | { | 202 | { |
203 | unsigned int retry = mr->adjusted_retry_count; | 203 | unsigned int retry = mr->adjusted_retry_count; |
204 | 204 | ||
205 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | 205 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) |
206 | retry = max(2U, min(mr->retry_count_rtscts, retry)); | 206 | retry = max(2U, min(mr->retry_count_rtscts, retry)); |
207 | else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) | 207 | else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) |
208 | retry = max(2U, min(mr->retry_count_cts, retry)); | 208 | retry = max(2U, min(mr->retry_count_cts, retry)); |
209 | return retry; | 209 | return retry; |
210 | } | 210 | } |
211 | 211 | ||
212 | 212 | ||
213 | static int | 213 | static int |
214 | minstrel_get_next_sample(struct minstrel_sta_info *mi) | 214 | minstrel_get_next_sample(struct minstrel_sta_info *mi) |
215 | { | 215 | { |
216 | unsigned int sample_ndx; | 216 | unsigned int sample_ndx; |
217 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); | 217 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); |
218 | mi->sample_idx++; | 218 | mi->sample_idx++; |
219 | if (mi->sample_idx > (mi->n_rates - 2)) { | 219 | if (mi->sample_idx > (mi->n_rates - 2)) { |
220 | mi->sample_idx = 0; | 220 | mi->sample_idx = 0; |
221 | mi->sample_column++; | 221 | mi->sample_column++; |
222 | if (mi->sample_column >= SAMPLE_COLUMNS) | 222 | if (mi->sample_column >= SAMPLE_COLUMNS) |
223 | mi->sample_column = 0; | 223 | mi->sample_column = 0; |
224 | } | 224 | } |
225 | return sample_ndx; | 225 | return sample_ndx; |
226 | } | 226 | } |
227 | 227 | ||
228 | void | 228 | void |
229 | minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | 229 | minstrel_get_rate(void *priv, struct ieee80211_sta *sta, |
230 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) | 230 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) |
231 | { | 231 | { |
232 | struct sk_buff *skb = txrc->skb; | 232 | struct sk_buff *skb = txrc->skb; |
233 | struct ieee80211_supported_band *sband = txrc->sband; | 233 | struct ieee80211_supported_band *sband = txrc->sband; |
234 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 234 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
235 | struct minstrel_sta_info *mi = priv_sta; | 235 | struct minstrel_sta_info *mi = priv_sta; |
236 | struct minstrel_priv *mp = priv; | 236 | struct minstrel_priv *mp = priv; |
237 | struct ieee80211_tx_rate *ar = info->control.rates; | 237 | struct ieee80211_tx_rate *ar = info->control.rates; |
238 | unsigned int ndx, sample_ndx = 0; | 238 | unsigned int ndx, sample_ndx = 0; |
239 | bool mrr; | 239 | bool mrr; |
240 | bool sample_slower = false; | 240 | bool sample_slower = false; |
241 | bool sample = false; | 241 | bool sample = false; |
242 | int i, delta; | 242 | int i, delta; |
243 | int mrr_ndx[3]; | 243 | int mrr_ndx[3]; |
244 | int sample_rate; | 244 | int sample_rate; |
245 | 245 | ||
246 | if (!sta || !mi || use_low_rate(skb)) { | 246 | if (!sta || !mi || use_low_rate(skb)) { |
247 | ar[0].idx = rate_lowest_index(sband, sta); | 247 | ar[0].idx = rate_lowest_index(sband, sta); |
248 | ar[0].count = mp->max_retry; | 248 | ar[0].count = mp->max_retry; |
249 | return; | 249 | return; |
250 | } | 250 | } |
251 | 251 | ||
252 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; | 252 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; |
253 | 253 | ||
254 | if (time_after(jiffies, mi->stats_update + (mp->update_interval * | 254 | if (time_after(jiffies, mi->stats_update + (mp->update_interval * |
255 | HZ) / 1000)) | 255 | HZ) / 1000)) |
256 | minstrel_update_stats(mp, mi); | 256 | minstrel_update_stats(mp, mi); |
257 | 257 | ||
258 | ndx = mi->max_tp_rate; | 258 | ndx = mi->max_tp_rate; |
259 | 259 | ||
260 | if (mrr) | 260 | if (mrr) |
261 | sample_rate = mp->lookaround_rate_mrr; | 261 | sample_rate = mp->lookaround_rate_mrr; |
262 | else | 262 | else |
263 | sample_rate = mp->lookaround_rate; | 263 | sample_rate = mp->lookaround_rate; |
264 | 264 | ||
265 | mi->packet_count++; | 265 | mi->packet_count++; |
266 | delta = (mi->packet_count * sample_rate / 100) - | 266 | delta = (mi->packet_count * sample_rate / 100) - |
267 | (mi->sample_count + mi->sample_deferred / 2); | 267 | (mi->sample_count + mi->sample_deferred / 2); |
268 | 268 | ||
269 | /* delta > 0: sampling required */ | 269 | /* delta > 0: sampling required */ |
270 | if ((delta > 0) && (mrr || !mi->prev_sample)) { | 270 | if ((delta > 0) && (mrr || !mi->prev_sample)) { |
271 | struct minstrel_rate *msr; | 271 | struct minstrel_rate *msr; |
272 | if (mi->packet_count >= 10000) { | 272 | if (mi->packet_count >= 10000) { |
273 | mi->sample_deferred = 0; | 273 | mi->sample_deferred = 0; |
274 | mi->sample_count = 0; | 274 | mi->sample_count = 0; |
275 | mi->packet_count = 0; | 275 | mi->packet_count = 0; |
276 | } else if (delta > mi->n_rates * 2) { | 276 | } else if (delta > mi->n_rates * 2) { |
277 | /* With multi-rate retry, not every planned sample | 277 | /* With multi-rate retry, not every planned sample |
278 | * attempt actually gets used, due to the way the retry | 278 | * attempt actually gets used, due to the way the retry |
279 | * chain is set up - [max_tp,sample,prob,lowest] for | 279 | * chain is set up - [max_tp,sample,prob,lowest] for |
280 | * sample_rate < max_tp. | 280 | * sample_rate < max_tp. |
281 | * | 281 | * |
282 | * If there's too much sampling backlog and the link | 282 | * If there's too much sampling backlog and the link |
283 | * starts getting worse, minstrel would start bursting | 283 | * starts getting worse, minstrel would start bursting |
284 | * out lots of sampling frames, which would result | 284 | * out lots of sampling frames, which would result |
285 | * in a large throughput loss. */ | 285 | * in a large throughput loss. */ |
286 | mi->sample_count += (delta - mi->n_rates * 2); | 286 | mi->sample_count += (delta - mi->n_rates * 2); |
287 | } | 287 | } |
288 | 288 | ||
289 | sample_ndx = minstrel_get_next_sample(mi); | 289 | sample_ndx = minstrel_get_next_sample(mi); |
290 | msr = &mi->r[sample_ndx]; | 290 | msr = &mi->r[sample_ndx]; |
291 | sample = true; | 291 | sample = true; |
292 | sample_slower = mrr && (msr->perfect_tx_time > | 292 | sample_slower = mrr && (msr->perfect_tx_time > |
293 | mi->r[ndx].perfect_tx_time); | 293 | mi->r[ndx].perfect_tx_time); |
294 | 294 | ||
295 | if (!sample_slower) { | 295 | if (!sample_slower) { |
296 | if (msr->sample_limit != 0) { | 296 | if (msr->sample_limit != 0) { |
297 | ndx = sample_ndx; | 297 | ndx = sample_ndx; |
298 | mi->sample_count++; | 298 | mi->sample_count++; |
299 | if (msr->sample_limit > 0) | 299 | if (msr->sample_limit > 0) |
300 | msr->sample_limit--; | 300 | msr->sample_limit--; |
301 | } else { | 301 | } else { |
302 | sample = false; | 302 | sample = false; |
303 | } | 303 | } |
304 | } else { | 304 | } else { |
305 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark | 305 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark |
306 | * packets that have the sampling rate deferred to the | 306 | * packets that have the sampling rate deferred to the |
307 | * second MRR stage. Increase the sample counter only | 307 | * second MRR stage. Increase the sample counter only |
308 | * if the deferred sample rate was actually used. | 308 | * if the deferred sample rate was actually used. |
309 | * Use the sample_deferred counter to make sure that | 309 | * Use the sample_deferred counter to make sure that |
310 | * the sampling is not done in large bursts */ | 310 | * the sampling is not done in large bursts */ |
311 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 311 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
312 | mi->sample_deferred++; | 312 | mi->sample_deferred++; |
313 | } | 313 | } |
314 | } | 314 | } |
315 | mi->prev_sample = sample; | 315 | mi->prev_sample = sample; |
316 | 316 | ||
317 | /* If we're not using MRR and the sampling rate already | 317 | /* If we're not using MRR and the sampling rate already |
318 | * has a probability of >95%, we shouldn't be attempting | 318 | * has a probability of >95%, we shouldn't be attempting |
319 | * to use it, as this only wastes precious airtime */ | 319 | * to use it, as this only wastes precious airtime */ |
320 | if (!mrr && sample && (mi->r[ndx].probability > 17100)) | 320 | if (!mrr && sample && (mi->r[ndx].probability > 17100)) |
321 | ndx = mi->max_tp_rate; | 321 | ndx = mi->max_tp_rate; |
322 | 322 | ||
323 | ar[0].idx = mi->r[ndx].rix; | 323 | ar[0].idx = mi->r[ndx].rix; |
324 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); | 324 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); |
325 | 325 | ||
326 | if (!mrr) { | 326 | if (!mrr) { |
327 | if (!sample) | 327 | if (!sample) |
328 | ar[0].count = mp->max_retry; | 328 | ar[0].count = mp->max_retry; |
329 | ar[1].idx = mi->lowest_rix; | 329 | ar[1].idx = mi->lowest_rix; |
330 | ar[1].count = mp->max_retry; | 330 | ar[1].count = mp->max_retry; |
331 | return; | 331 | return; |
332 | } | 332 | } |
333 | 333 | ||
334 | /* MRR setup */ | 334 | /* MRR setup */ |
335 | if (sample) { | 335 | if (sample) { |
336 | if (sample_slower) | 336 | if (sample_slower) |
337 | mrr_ndx[0] = sample_ndx; | 337 | mrr_ndx[0] = sample_ndx; |
338 | else | 338 | else |
339 | mrr_ndx[0] = mi->max_tp_rate; | 339 | mrr_ndx[0] = mi->max_tp_rate; |
340 | } else { | 340 | } else { |
341 | mrr_ndx[0] = mi->max_tp_rate2; | 341 | mrr_ndx[0] = mi->max_tp_rate2; |
342 | } | 342 | } |
343 | mrr_ndx[1] = mi->max_prob_rate; | 343 | mrr_ndx[1] = mi->max_prob_rate; |
344 | mrr_ndx[2] = 0; | 344 | mrr_ndx[2] = 0; |
345 | for (i = 1; i < 4; i++) { | 345 | for (i = 1; i < 4; i++) { |
346 | ar[i].idx = mi->r[mrr_ndx[i - 1]].rix; | 346 | ar[i].idx = mi->r[mrr_ndx[i - 1]].rix; |
347 | ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count; | 347 | ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count; |
348 | } | 348 | } |
349 | } | 349 | } |
350 | 350 | ||
351 | 351 | ||
352 | static void | 352 | static void |
353 | calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, | 353 | calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, |
354 | struct minstrel_rate *d, struct ieee80211_rate *rate) | 354 | struct minstrel_rate *d, struct ieee80211_rate *rate) |
355 | { | 355 | { |
356 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); | 356 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); |
357 | 357 | ||
358 | d->perfect_tx_time = ieee80211_frame_duration(local, 1200, | 358 | d->perfect_tx_time = ieee80211_frame_duration(local, 1200, |
359 | rate->bitrate, erp, 1); | 359 | rate->bitrate, erp, 1); |
360 | d->ack_time = ieee80211_frame_duration(local, 10, | 360 | d->ack_time = ieee80211_frame_duration(local, 10, |
361 | rate->bitrate, erp, 1); | 361 | rate->bitrate, erp, 1); |
362 | } | 362 | } |
363 | 363 | ||
364 | static void | 364 | static void |
365 | init_sample_table(struct minstrel_sta_info *mi) | 365 | init_sample_table(struct minstrel_sta_info *mi) |
366 | { | 366 | { |
367 | unsigned int i, col, new_idx; | 367 | unsigned int i, col, new_idx; |
368 | unsigned int n_srates = mi->n_rates - 1; | 368 | unsigned int n_srates = mi->n_rates - 1; |
369 | u8 rnd[8]; | 369 | u8 rnd[8]; |
370 | 370 | ||
371 | mi->sample_column = 0; | 371 | mi->sample_column = 0; |
372 | mi->sample_idx = 0; | 372 | mi->sample_idx = 0; |
373 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); | 373 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); |
374 | 374 | ||
375 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | 375 | for (col = 0; col < SAMPLE_COLUMNS; col++) { |
376 | for (i = 0; i < n_srates; i++) { | 376 | for (i = 0; i < n_srates; i++) { |
377 | get_random_bytes(rnd, sizeof(rnd)); | 377 | get_random_bytes(rnd, sizeof(rnd)); |
378 | new_idx = (i + rnd[i & 7]) % n_srates; | 378 | new_idx = (i + rnd[i & 7]) % n_srates; |
379 | 379 | ||
380 | while (SAMPLE_TBL(mi, new_idx, col) != 0) | 380 | while (SAMPLE_TBL(mi, new_idx, col) != 0) |
381 | new_idx = (new_idx + 1) % n_srates; | 381 | new_idx = (new_idx + 1) % n_srates; |
382 | 382 | ||
383 | /* Don't sample the slowest rate (i.e. slowest base | 383 | /* Don't sample the slowest rate (i.e. slowest base |
384 | * rate). We must presume that the slowest rate works | 384 | * rate). We must presume that the slowest rate works |
385 | * fine, or else other management frames will also be | 385 | * fine, or else other management frames will also be |
386 | * failing and the link will break */ | 386 | * failing and the link will break */ |
387 | SAMPLE_TBL(mi, new_idx, col) = i + 1; | 387 | SAMPLE_TBL(mi, new_idx, col) = i + 1; |
388 | } | 388 | } |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | static void | 392 | static void |
393 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | 393 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, |
394 | struct ieee80211_sta *sta, void *priv_sta) | 394 | struct ieee80211_sta *sta, void *priv_sta) |
395 | { | 395 | { |
396 | struct minstrel_sta_info *mi = priv_sta; | 396 | struct minstrel_sta_info *mi = priv_sta; |
397 | struct minstrel_priv *mp = priv; | 397 | struct minstrel_priv *mp = priv; |
398 | struct minstrel_rate *mr_ctl; | 398 | struct minstrel_rate *mr_ctl; |
399 | unsigned int i, n = 0; | 399 | unsigned int i, n = 0; |
400 | unsigned int t_slot = 9; /* FIXME: get real slot time */ | 400 | unsigned int t_slot = 9; /* FIXME: get real slot time */ |
401 | 401 | ||
402 | mi->lowest_rix = rate_lowest_index(sband, sta); | 402 | mi->lowest_rix = rate_lowest_index(sband, sta); |
403 | mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)]; | 403 | mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)]; |
404 | mi->sp_ack_dur = mr_ctl->ack_time; | 404 | mi->sp_ack_dur = mr_ctl->ack_time; |
405 | 405 | ||
406 | for (i = 0; i < sband->n_bitrates; i++) { | 406 | for (i = 0; i < sband->n_bitrates; i++) { |
407 | struct minstrel_rate *mr = &mi->r[n]; | 407 | struct minstrel_rate *mr = &mi->r[n]; |
408 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; | 408 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; |
409 | unsigned int tx_time_single; | 409 | unsigned int tx_time_single; |
410 | unsigned int cw = mp->cw_min; | 410 | unsigned int cw = mp->cw_min; |
411 | 411 | ||
412 | if (!rate_supported(sta, sband->band, i)) | 412 | if (!rate_supported(sta, sband->band, i)) |
413 | continue; | 413 | continue; |
414 | n++; | 414 | n++; |
415 | memset(mr, 0, sizeof(*mr)); | 415 | memset(mr, 0, sizeof(*mr)); |
416 | 416 | ||
417 | mr->rix = i; | 417 | mr->rix = i; |
418 | mr->bitrate = sband->bitrates[i].bitrate / 5; | 418 | mr->bitrate = sband->bitrates[i].bitrate / 5; |
419 | calc_rate_durations(mi, hw_to_local(mp->hw), mr, | 419 | calc_rate_durations(mi, hw_to_local(mp->hw), mr, |
420 | &sband->bitrates[i]); | 420 | &sband->bitrates[i]); |
421 | 421 | ||
422 | /* calculate maximum number of retransmissions before | 422 | /* calculate maximum number of retransmissions before |
423 | * fallback (based on maximum segment size) */ | 423 | * fallback (based on maximum segment size) */ |
424 | mr->sample_limit = -1; | 424 | mr->sample_limit = -1; |
425 | mr->retry_count = 1; | 425 | mr->retry_count = 1; |
426 | mr->retry_count_cts = 1; | 426 | mr->retry_count_cts = 1; |
427 | mr->retry_count_rtscts = 1; | 427 | mr->retry_count_rtscts = 1; |
428 | tx_time = mr->perfect_tx_time + mi->sp_ack_dur; | 428 | tx_time = mr->perfect_tx_time + mi->sp_ack_dur; |
429 | do { | 429 | do { |
430 | /* add one retransmission */ | 430 | /* add one retransmission */ |
431 | tx_time_single = mr->ack_time + mr->perfect_tx_time; | 431 | tx_time_single = mr->ack_time + mr->perfect_tx_time; |
432 | 432 | ||
433 | /* contention window */ | 433 | /* contention window */ |
434 | tx_time_single += t_slot + min(cw, mp->cw_max); | 434 | tx_time_single += t_slot + min(cw, mp->cw_max); |
435 | cw = (cw + 1) << 1; | 435 | cw = (cw + 1) << 1; |
436 | 436 | ||
437 | tx_time += tx_time_single; | 437 | tx_time += tx_time_single; |
438 | tx_time_cts += tx_time_single + mi->sp_ack_dur; | 438 | tx_time_cts += tx_time_single + mi->sp_ack_dur; |
439 | tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; | 439 | tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; |
440 | if ((tx_time_cts < mp->segment_size) && | 440 | if ((tx_time_cts < mp->segment_size) && |
441 | (mr->retry_count_cts < mp->max_retry)) | 441 | (mr->retry_count_cts < mp->max_retry)) |
442 | mr->retry_count_cts++; | 442 | mr->retry_count_cts++; |
443 | if ((tx_time_rtscts < mp->segment_size) && | 443 | if ((tx_time_rtscts < mp->segment_size) && |
444 | (mr->retry_count_rtscts < mp->max_retry)) | 444 | (mr->retry_count_rtscts < mp->max_retry)) |
445 | mr->retry_count_rtscts++; | 445 | mr->retry_count_rtscts++; |
446 | } while ((tx_time < mp->segment_size) && | 446 | } while ((tx_time < mp->segment_size) && |
447 | (++mr->retry_count < mp->max_retry)); | 447 | (++mr->retry_count < mp->max_retry)); |
448 | mr->adjusted_retry_count = mr->retry_count; | 448 | mr->adjusted_retry_count = mr->retry_count; |
449 | } | 449 | } |
450 | 450 | ||
451 | for (i = n; i < sband->n_bitrates; i++) { | 451 | for (i = n; i < sband->n_bitrates; i++) { |
452 | struct minstrel_rate *mr = &mi->r[i]; | 452 | struct minstrel_rate *mr = &mi->r[i]; |
453 | mr->rix = -1; | 453 | mr->rix = -1; |
454 | } | 454 | } |
455 | 455 | ||
456 | mi->n_rates = n; | 456 | mi->n_rates = n; |
457 | mi->stats_update = jiffies; | 457 | mi->stats_update = jiffies; |
458 | 458 | ||
459 | init_sample_table(mi); | 459 | init_sample_table(mi); |
460 | } | 460 | } |
461 | 461 | ||
462 | static void * | 462 | static void * |
463 | minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | 463 | minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
464 | { | 464 | { |
465 | struct ieee80211_supported_band *sband; | 465 | struct ieee80211_supported_band *sband; |
466 | struct minstrel_sta_info *mi; | 466 | struct minstrel_sta_info *mi; |
467 | struct minstrel_priv *mp = priv; | 467 | struct minstrel_priv *mp = priv; |
468 | struct ieee80211_hw *hw = mp->hw; | 468 | struct ieee80211_hw *hw = mp->hw; |
469 | int max_rates = 0; | 469 | int max_rates = 0; |
470 | int i; | 470 | int i; |
471 | 471 | ||
472 | mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); | 472 | mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); |
473 | if (!mi) | 473 | if (!mi) |
474 | return NULL; | 474 | return NULL; |
475 | 475 | ||
476 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 476 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
477 | sband = hw->wiphy->bands[hw->conf.channel->band]; | 477 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
478 | if (sband->n_bitrates > max_rates) | 478 | if (sband->n_bitrates > max_rates) |
479 | max_rates = sband->n_bitrates; | 479 | max_rates = sband->n_bitrates; |
480 | } | 480 | } |
481 | 481 | ||
482 | mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); | 482 | mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); |
483 | if (!mi->r) | 483 | if (!mi->r) |
484 | goto error; | 484 | goto error; |
485 | 485 | ||
486 | mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); | 486 | mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); |
487 | if (!mi->sample_table) | 487 | if (!mi->sample_table) |
488 | goto error1; | 488 | goto error1; |
489 | 489 | ||
490 | mi->stats_update = jiffies; | 490 | mi->stats_update = jiffies; |
491 | return mi; | 491 | return mi; |
492 | 492 | ||
493 | error1: | 493 | error1: |
494 | kfree(mi->r); | 494 | kfree(mi->r); |
495 | error: | 495 | error: |
496 | kfree(mi); | 496 | kfree(mi); |
497 | return NULL; | 497 | return NULL; |
498 | } | 498 | } |
499 | 499 | ||
500 | static void | 500 | static void |
501 | minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) | 501 | minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) |
502 | { | 502 | { |
503 | struct minstrel_sta_info *mi = priv_sta; | 503 | struct minstrel_sta_info *mi = priv_sta; |
504 | 504 | ||
505 | kfree(mi->sample_table); | 505 | kfree(mi->sample_table); |
506 | kfree(mi->r); | 506 | kfree(mi->r); |
507 | kfree(mi); | 507 | kfree(mi); |
508 | } | 508 | } |
509 | 509 | ||
510 | static void | ||
511 | minstrel_clear(void *priv) | ||
512 | { | ||
513 | } | ||
514 | |||
515 | static void * | 510 | static void * |
516 | minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 511 | minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
517 | { | 512 | { |
518 | struct minstrel_priv *mp; | 513 | struct minstrel_priv *mp; |
519 | 514 | ||
520 | mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); | 515 | mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); |
521 | if (!mp) | 516 | if (!mp) |
522 | return NULL; | 517 | return NULL; |
523 | 518 | ||
524 | /* contention window settings | 519 | /* contention window settings |
525 | * Just an approximation. Using the per-queue values would complicate | 520 | * Just an approximation. Using the per-queue values would complicate |
526 | * the calculations and is probably unnecessary */ | 521 | * the calculations and is probably unnecessary */ |
527 | mp->cw_min = 15; | 522 | mp->cw_min = 15; |
528 | mp->cw_max = 1023; | 523 | mp->cw_max = 1023; |
529 | 524 | ||
530 | /* number of packets (in %) to use for sampling other rates | 525 | /* number of packets (in %) to use for sampling other rates |
531 | * sample less often for non-mrr packets, because the overhead | 526 | * sample less often for non-mrr packets, because the overhead |
532 | * is much higher than with mrr */ | 527 | * is much higher than with mrr */ |
533 | mp->lookaround_rate = 5; | 528 | mp->lookaround_rate = 5; |
534 | mp->lookaround_rate_mrr = 10; | 529 | mp->lookaround_rate_mrr = 10; |
535 | 530 | ||
536 | /* moving average weight for EWMA */ | 531 | /* moving average weight for EWMA */ |
537 | mp->ewma_level = 75; | 532 | mp->ewma_level = 75; |
538 | 533 | ||
539 | /* maximum time that the hw is allowed to stay in one MRR segment */ | 534 | /* maximum time that the hw is allowed to stay in one MRR segment */ |
540 | mp->segment_size = 6000; | 535 | mp->segment_size = 6000; |
541 | 536 | ||
542 | if (hw->max_rate_tries > 0) | 537 | if (hw->max_rate_tries > 0) |
543 | mp->max_retry = hw->max_rate_tries; | 538 | mp->max_retry = hw->max_rate_tries; |
544 | else | 539 | else |
545 | /* safe default, does not necessarily have to match hw properties */ | 540 | /* safe default, does not necessarily have to match hw properties */ |
546 | mp->max_retry = 7; | 541 | mp->max_retry = 7; |
547 | 542 | ||
548 | if (hw->max_rates >= 4) | 543 | if (hw->max_rates >= 4) |
549 | mp->has_mrr = true; | 544 | mp->has_mrr = true; |
550 | 545 | ||
551 | mp->hw = hw; | 546 | mp->hw = hw; |
552 | mp->update_interval = 100; | 547 | mp->update_interval = 100; |
553 | 548 | ||
554 | return mp; | 549 | return mp; |
555 | } | 550 | } |
556 | 551 | ||
557 | static void | 552 | static void |
558 | minstrel_free(void *priv) | 553 | minstrel_free(void *priv) |
559 | { | 554 | { |
560 | kfree(priv); | 555 | kfree(priv); |
561 | } | 556 | } |
562 | 557 | ||
563 | static struct rate_control_ops mac80211_minstrel = { | 558 | static struct rate_control_ops mac80211_minstrel = { |
564 | .name = "minstrel", | 559 | .name = "minstrel", |
565 | .tx_status = minstrel_tx_status, | 560 | .tx_status = minstrel_tx_status, |
566 | .get_rate = minstrel_get_rate, | 561 | .get_rate = minstrel_get_rate, |
567 | .rate_init = minstrel_rate_init, | 562 | .rate_init = minstrel_rate_init, |
568 | .clear = minstrel_clear, | ||
569 | .alloc = minstrel_alloc, | 563 | .alloc = minstrel_alloc, |
570 | .free = minstrel_free, | 564 | .free = minstrel_free, |
571 | .alloc_sta = minstrel_alloc_sta, | 565 | .alloc_sta = minstrel_alloc_sta, |
572 | .free_sta = minstrel_free_sta, | 566 | .free_sta = minstrel_free_sta, |
573 | #ifdef CONFIG_MAC80211_DEBUGFS | 567 | #ifdef CONFIG_MAC80211_DEBUGFS |
574 | .add_sta_debugfs = minstrel_add_sta_debugfs, | 568 | .add_sta_debugfs = minstrel_add_sta_debugfs, |
575 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, | 569 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, |
576 | #endif | 570 | #endif |
577 | }; | 571 | }; |
578 | 572 | ||
579 | int __init | 573 | int __init |
580 | rc80211_minstrel_init(void) | 574 | rc80211_minstrel_init(void) |
581 | { | 575 | { |
582 | return ieee80211_rate_control_register(&mac80211_minstrel); | 576 | return ieee80211_rate_control_register(&mac80211_minstrel); |
583 | } | 577 | } |
584 | 578 | ||
585 | void | 579 | void |
586 | rc80211_minstrel_exit(void) | 580 | rc80211_minstrel_exit(void) |
587 | { | 581 | { |
588 | ieee80211_rate_control_unregister(&mac80211_minstrel); | 582 | ieee80211_rate_control_unregister(&mac80211_minstrel); |
589 | } | 583 | } |
590 | 584 | ||
591 | 585 |
net/mac80211/rc80211_pid_algo.c
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | 4 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> |
5 | * Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it> | 5 | * Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/debugfs.h> | 15 | #include <linux/debugfs.h> |
16 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
17 | #include "rate.h" | 17 | #include "rate.h" |
18 | #include "mesh.h" | 18 | #include "mesh.h" |
19 | #include "rc80211_pid.h" | 19 | #include "rc80211_pid.h" |
20 | 20 | ||
21 | 21 | ||
22 | /* This is an implementation of a TX rate control algorithm that uses a PID | 22 | /* This is an implementation of a TX rate control algorithm that uses a PID |
23 | * controller. Given a target failed frames rate, the controller decides about | 23 | * controller. Given a target failed frames rate, the controller decides about |
24 | * TX rate changes to meet the target failed frames rate. | 24 | * TX rate changes to meet the target failed frames rate. |
25 | * | 25 | * |
26 | * The controller basically computes the following: | 26 | * The controller basically computes the following: |
27 | * | 27 | * |
28 | * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening) | 28 | * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening) |
29 | * | 29 | * |
30 | * where | 30 | * where |
31 | * adj adjustment value that is used to switch TX rate (see below) | 31 | * adj adjustment value that is used to switch TX rate (see below) |
32 | * err current error: target vs. current failed frames percentage | 32 | * err current error: target vs. current failed frames percentage |
33 | * last_err last error | 33 | * last_err last error |
34 | * err_avg average (i.e. poor man's integral) of recent errors | 34 | * err_avg average (i.e. poor man's integral) of recent errors |
35 | * sharpening non-zero when fast response is needed (i.e. right after | 35 | * sharpening non-zero when fast response is needed (i.e. right after |
36 | * association or no frames sent for a long time), heading | 36 | * association or no frames sent for a long time), heading |
37 | * to zero over time | 37 | * to zero over time |
38 | * CP Proportional coefficient | 38 | * CP Proportional coefficient |
39 | * CI Integral coefficient | 39 | * CI Integral coefficient |
40 | * CD Derivative coefficient | 40 | * CD Derivative coefficient |
41 | * | 41 | * |
42 | * CP, CI, CD are subject to careful tuning. | 42 | * CP, CI, CD are subject to careful tuning. |
43 | * | 43 | * |
44 | * The integral component uses a exponential moving average approach instead of | 44 | * The integral component uses a exponential moving average approach instead of |
45 | * an actual sliding window. The advantage is that we don't need to keep an | 45 | * an actual sliding window. The advantage is that we don't need to keep an |
46 | * array of the last N error values and computation is easier. | 46 | * array of the last N error values and computation is easier. |
47 | * | 47 | * |
48 | * Once we have the adj value, we map it to a rate by means of a learning | 48 | * Once we have the adj value, we map it to a rate by means of a learning |
49 | * algorithm. This algorithm keeps the state of the percentual failed frames | 49 | * algorithm. This algorithm keeps the state of the percentual failed frames |
50 | * difference between rates. The behaviour of the lowest available rate is kept | 50 | * difference between rates. The behaviour of the lowest available rate is kept |
51 | * as a reference value, and every time we switch between two rates, we compute | 51 | * as a reference value, and every time we switch between two rates, we compute |
52 | * the difference between the failed frames each rate exhibited. By doing so, | 52 | * the difference between the failed frames each rate exhibited. By doing so, |
53 | * we compare behaviours which different rates exhibited in adjacent timeslices, | 53 | * we compare behaviours which different rates exhibited in adjacent timeslices, |
54 | * thus the comparison is minimally affected by external conditions. This | 54 | * thus the comparison is minimally affected by external conditions. This |
55 | * difference gets propagated to the whole set of measurements, so that the | 55 | * difference gets propagated to the whole set of measurements, so that the |
56 | * reference is always the same. Periodically, we normalize this set so that | 56 | * reference is always the same. Periodically, we normalize this set so that |
57 | * recent events weigh the most. By comparing the adj value with this set, we | 57 | * recent events weigh the most. By comparing the adj value with this set, we |
58 | * avoid pejorative switches to lower rates and allow for switches to higher | 58 | * avoid pejorative switches to lower rates and allow for switches to higher |
59 | * rates if they behaved well. | 59 | * rates if they behaved well. |
60 | * | 60 | * |
61 | * Note that for the computations we use a fixed-point representation to avoid | 61 | * Note that for the computations we use a fixed-point representation to avoid |
62 | * floating point arithmetic. Hence, all values are shifted left by | 62 | * floating point arithmetic. Hence, all values are shifted left by |
63 | * RC_PID_ARITH_SHIFT. | 63 | * RC_PID_ARITH_SHIFT. |
64 | */ | 64 | */ |
65 | 65 | ||
66 | 66 | ||
67 | /* Adjust the rate while ensuring that we won't switch to a lower rate if it | 67 | /* Adjust the rate while ensuring that we won't switch to a lower rate if it |
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct ieee80211_sta *sta, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | 73 | struct rc_pid_sta_info *spinfo, int adj, |
74 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
75 | { | 75 | { |
76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
77 | int cur = spinfo->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
78 | 78 | ||
79 | band = sband->band; | 79 | band = sband->band; |
80 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
81 | 81 | ||
82 | /* Map passed arguments to sorted values. */ | 82 | /* Map passed arguments to sorted values. */ |
83 | cur_sorted = rinfo[cur].rev_index; | 83 | cur_sorted = rinfo[cur].rev_index; |
84 | new_sorted = cur_sorted + adj; | 84 | new_sorted = cur_sorted + adj; |
85 | 85 | ||
86 | /* Check limits. */ | 86 | /* Check limits. */ |
87 | if (new_sorted < 0) | 87 | if (new_sorted < 0) |
88 | new_sorted = rinfo[0].rev_index; | 88 | new_sorted = rinfo[0].rev_index; |
89 | else if (new_sorted >= n_bitrates) | 89 | else if (new_sorted >= n_bitrates) |
90 | new_sorted = rinfo[n_bitrates - 1].rev_index; | 90 | new_sorted = rinfo[n_bitrates - 1].rev_index; |
91 | 91 | ||
92 | tmp = new_sorted; | 92 | tmp = new_sorted; |
93 | 93 | ||
94 | if (adj < 0) { | 94 | if (adj < 0) { |
95 | /* Ensure that the rate decrease isn't disadvantageous. */ | 95 | /* Ensure that the rate decrease isn't disadvantageous. */ |
96 | for (probe = cur_sorted; probe >= new_sorted; probe--) | 96 | for (probe = cur_sorted; probe >= new_sorted; probe--) |
97 | if (rinfo[probe].diff <= rinfo[cur_sorted].diff && | 97 | if (rinfo[probe].diff <= rinfo[cur_sorted].diff && |
98 | rate_supported(sta, band, rinfo[probe].index)) | 98 | rate_supported(sta, band, rinfo[probe].index)) |
99 | tmp = probe; | 99 | tmp = probe; |
100 | } else { | 100 | } else { |
101 | /* Look for rate increase with zero (or below) cost. */ | 101 | /* Look for rate increase with zero (or below) cost. */ |
102 | for (probe = new_sorted + 1; probe < n_bitrates; probe++) | 102 | for (probe = new_sorted + 1; probe < n_bitrates; probe++) |
103 | if (rinfo[probe].diff <= rinfo[new_sorted].diff && | 103 | if (rinfo[probe].diff <= rinfo[new_sorted].diff && |
104 | rate_supported(sta, band, rinfo[probe].index)) | 104 | rate_supported(sta, band, rinfo[probe].index)) |
105 | tmp = probe; | 105 | tmp = probe; |
106 | } | 106 | } |
107 | 107 | ||
108 | /* Fit the rate found to the nearest supported rate. */ | 108 | /* Fit the rate found to the nearest supported rate. */ |
109 | do { | 109 | do { |
110 | if (rate_supported(sta, band, rinfo[tmp].index)) { | 110 | if (rate_supported(sta, band, rinfo[tmp].index)) { |
111 | spinfo->txrate_idx = rinfo[tmp].index; | 111 | spinfo->txrate_idx = rinfo[tmp].index; |
112 | break; | 112 | break; |
113 | } | 113 | } |
114 | if (adj < 0) | 114 | if (adj < 0) |
115 | tmp--; | 115 | tmp--; |
116 | else | 116 | else |
117 | tmp++; | 117 | tmp++; |
118 | } while (tmp < n_bitrates && tmp >= 0); | 118 | } while (tmp < n_bitrates && tmp >= 0); |
119 | 119 | ||
120 | #ifdef CONFIG_MAC80211_DEBUGFS | 120 | #ifdef CONFIG_MAC80211_DEBUGFS |
121 | rate_control_pid_event_rate_change(&spinfo->events, | 121 | rate_control_pid_event_rate_change(&spinfo->events, |
122 | spinfo->txrate_idx, | 122 | spinfo->txrate_idx, |
123 | sband->bitrates[spinfo->txrate_idx].bitrate); | 123 | sband->bitrates[spinfo->txrate_idx].bitrate); |
124 | #endif | 124 | #endif |
125 | } | 125 | } |
126 | 126 | ||
127 | /* Normalize the failed frames per-rate differences. */ | 127 | /* Normalize the failed frames per-rate differences. */ |
128 | static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | 128 | static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) |
129 | { | 129 | { |
130 | int i, norm_offset = pinfo->norm_offset; | 130 | int i, norm_offset = pinfo->norm_offset; |
131 | struct rc_pid_rateinfo *r = pinfo->rinfo; | 131 | struct rc_pid_rateinfo *r = pinfo->rinfo; |
132 | 132 | ||
133 | if (r[0].diff > norm_offset) | 133 | if (r[0].diff > norm_offset) |
134 | r[0].diff -= norm_offset; | 134 | r[0].diff -= norm_offset; |
135 | else if (r[0].diff < -norm_offset) | 135 | else if (r[0].diff < -norm_offset) |
136 | r[0].diff += norm_offset; | 136 | r[0].diff += norm_offset; |
137 | for (i = 0; i < l - 1; i++) | 137 | for (i = 0; i < l - 1; i++) |
138 | if (r[i + 1].diff > r[i].diff + norm_offset) | 138 | if (r[i + 1].diff > r[i].diff + norm_offset) |
139 | r[i + 1].diff -= norm_offset; | 139 | r[i + 1].diff -= norm_offset; |
140 | else if (r[i + 1].diff <= r[i].diff) | 140 | else if (r[i + 1].diff <= r[i].diff) |
141 | r[i + 1].diff += norm_offset; | 141 | r[i + 1].diff += norm_offset; |
142 | } | 142 | } |
143 | 143 | ||
144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
145 | struct ieee80211_supported_band *sband, | 145 | struct ieee80211_supported_band *sband, |
146 | struct ieee80211_sta *sta, | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | 147 | struct rc_pid_sta_info *spinfo) |
148 | { | 148 | { |
149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
150 | u32 pf; | 150 | u32 pf; |
151 | s32 err_avg; | 151 | s32 err_avg; |
152 | u32 err_prop; | 152 | u32 err_prop; |
153 | u32 err_int; | 153 | u32 err_int; |
154 | u32 err_der; | 154 | u32 err_der; |
155 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
156 | unsigned long period; | 156 | unsigned long period; |
157 | 157 | ||
158 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
159 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
160 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
161 | if (!period) | 161 | if (!period) |
162 | period = 1; | 162 | period = 1; |
163 | if (jiffies - spinfo->last_sample > 2 * period) | 163 | if (jiffies - spinfo->last_sample > 2 * period) |
164 | spinfo->sharp_cnt = pinfo->sharpen_duration; | 164 | spinfo->sharp_cnt = pinfo->sharpen_duration; |
165 | 165 | ||
166 | spinfo->last_sample = jiffies; | 166 | spinfo->last_sample = jiffies; |
167 | 167 | ||
168 | /* This should never happen, but in case, we assume the old sample is | 168 | /* This should never happen, but in case, we assume the old sample is |
169 | * still a good measurement and copy it. */ | 169 | * still a good measurement and copy it. */ |
170 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
171 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
172 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | 173 | /* XXX: BAD HACK!!! */ |
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | 174 | struct sta_info *si = container_of(sta, struct sta_info, sta); |
175 | 175 | ||
176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
177 | 177 | ||
178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
179 | mesh_plink_broken(si); | 179 | mesh_plink_broken(si); |
180 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
182 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
183 | } | 183 | } |
184 | 184 | ||
185 | spinfo->tx_num_xmit = 0; | 185 | spinfo->tx_num_xmit = 0; |
186 | spinfo->tx_num_failed = 0; | 186 | spinfo->tx_num_failed = 0; |
187 | 187 | ||
188 | /* If we just switched rate, update the rate behaviour info. */ | 188 | /* If we just switched rate, update the rate behaviour info. */ |
189 | if (pinfo->oldrate != spinfo->txrate_idx) { | 189 | if (pinfo->oldrate != spinfo->txrate_idx) { |
190 | 190 | ||
191 | i = rinfo[pinfo->oldrate].rev_index; | 191 | i = rinfo[pinfo->oldrate].rev_index; |
192 | j = rinfo[spinfo->txrate_idx].rev_index; | 192 | j = rinfo[spinfo->txrate_idx].rev_index; |
193 | 193 | ||
194 | tmp = (pf - spinfo->last_pf); | 194 | tmp = (pf - spinfo->last_pf); |
195 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); | 195 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); |
196 | 196 | ||
197 | rinfo[j].diff = rinfo[i].diff + tmp; | 197 | rinfo[j].diff = rinfo[i].diff + tmp; |
198 | pinfo->oldrate = spinfo->txrate_idx; | 198 | pinfo->oldrate = spinfo->txrate_idx; |
199 | } | 199 | } |
200 | rate_control_pid_normalize(pinfo, sband->n_bitrates); | 200 | rate_control_pid_normalize(pinfo, sband->n_bitrates); |
201 | 201 | ||
202 | /* Compute the proportional, integral and derivative errors. */ | 202 | /* Compute the proportional, integral and derivative errors. */ |
203 | err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; | 203 | err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; |
204 | 204 | ||
205 | err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; | 205 | err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; |
206 | spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; | 206 | spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; |
207 | err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift; | 207 | err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift; |
208 | 208 | ||
209 | err_der = (pf - spinfo->last_pf) * | 209 | err_der = (pf - spinfo->last_pf) * |
210 | (1 + pinfo->sharpen_factor * spinfo->sharp_cnt); | 210 | (1 + pinfo->sharpen_factor * spinfo->sharp_cnt); |
211 | spinfo->last_pf = pf; | 211 | spinfo->last_pf = pf; |
212 | if (spinfo->sharp_cnt) | 212 | if (spinfo->sharp_cnt) |
213 | spinfo->sharp_cnt--; | 213 | spinfo->sharp_cnt--; |
214 | 214 | ||
215 | #ifdef CONFIG_MAC80211_DEBUGFS | 215 | #ifdef CONFIG_MAC80211_DEBUGFS |
216 | rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int, | 216 | rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int, |
217 | err_der); | 217 | err_der); |
218 | #endif | 218 | #endif |
219 | 219 | ||
220 | /* Compute the controller output. */ | 220 | /* Compute the controller output. */ |
221 | adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i | 221 | adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i |
222 | + err_der * pinfo->coeff_d); | 222 | + err_der * pinfo->coeff_d); |
223 | adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT); | 223 | adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT); |
224 | 224 | ||
225 | /* Change rate. */ | 225 | /* Change rate. */ |
226 | if (adj) | 226 | if (adj) |
227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
228 | } | 228 | } |
229 | 229 | ||
230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | 231 | struct ieee80211_sta *sta, void *priv_sta, |
232 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
233 | { | 233 | { |
234 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
235 | struct rc_pid_sta_info *spinfo = priv_sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
236 | unsigned long period; | 236 | unsigned long period; |
237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
238 | 238 | ||
239 | if (!spinfo) | 239 | if (!spinfo) |
240 | return; | 240 | return; |
241 | 241 | ||
242 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
243 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
244 | if (info->status.rates[0].idx != spinfo->txrate_idx) | 244 | if (info->status.rates[0].idx != spinfo->txrate_idx) |
245 | return; | 245 | return; |
246 | 246 | ||
247 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
248 | 248 | ||
249 | #ifdef CONFIG_MAC80211_DEBUGFS | 249 | #ifdef CONFIG_MAC80211_DEBUGFS |
250 | rate_control_pid_event_tx_status(&spinfo->events, info); | 250 | rate_control_pid_event_tx_status(&spinfo->events, info); |
251 | #endif | 251 | #endif |
252 | 252 | ||
253 | /* We count frames that totally failed to be transmitted as two bad | 253 | /* We count frames that totally failed to be transmitted as two bad |
254 | * frames, those that made it out but had some retries as one good and | 254 | * frames, those that made it out but had some retries as one good and |
255 | * one bad frame. */ | 255 | * one bad frame. */ |
256 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { | 256 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { |
257 | spinfo->tx_num_failed += 2; | 257 | spinfo->tx_num_failed += 2; |
258 | spinfo->tx_num_xmit++; | 258 | spinfo->tx_num_xmit++; |
259 | } else if (info->status.rates[0].count) { | 259 | } else if (info->status.rates[0].count) { |
260 | spinfo->tx_num_failed++; | 260 | spinfo->tx_num_failed++; |
261 | spinfo->tx_num_xmit++; | 261 | spinfo->tx_num_xmit++; |
262 | } | 262 | } |
263 | 263 | ||
264 | /* Update PID controller state. */ | 264 | /* Update PID controller state. */ |
265 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 265 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
266 | if (!period) | 266 | if (!period) |
267 | period = 1; | 267 | period = 1; |
268 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
270 | } | 270 | } |
271 | 271 | ||
272 | static void | 272 | static void |
273 | rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, |
274 | void *priv_sta, | 274 | void *priv_sta, |
275 | struct ieee80211_tx_rate_control *txrc) | 275 | struct ieee80211_tx_rate_control *txrc) |
276 | { | 276 | { |
277 | struct sk_buff *skb = txrc->skb; | 277 | struct sk_buff *skb = txrc->skb; |
278 | struct ieee80211_supported_band *sband = txrc->sband; | 278 | struct ieee80211_supported_band *sband = txrc->sband; |
279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
280 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 280 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
281 | struct rc_pid_sta_info *spinfo = priv_sta; | 281 | struct rc_pid_sta_info *spinfo = priv_sta; |
282 | int rateidx; | 282 | int rateidx; |
283 | u16 fc; | 283 | u16 fc; |
284 | 284 | ||
285 | if (txrc->rts) | 285 | if (txrc->rts) |
286 | info->control.rates[0].count = | 286 | info->control.rates[0].count = |
287 | txrc->hw->conf.long_frame_max_tx_count; | 287 | txrc->hw->conf.long_frame_max_tx_count; |
288 | else | 288 | else |
289 | info->control.rates[0].count = | 289 | info->control.rates[0].count = |
290 | txrc->hw->conf.short_frame_max_tx_count; | 290 | txrc->hw->conf.short_frame_max_tx_count; |
291 | 291 | ||
292 | /* Send management frames and broadcast/multicast data using lowest | 292 | /* Send management frames and broadcast/multicast data using lowest |
293 | * rate. */ | 293 | * rate. */ |
294 | fc = le16_to_cpu(hdr->frame_control); | 294 | fc = le16_to_cpu(hdr->frame_control); |
295 | if (!sta || !spinfo || | 295 | if (!sta || !spinfo || |
296 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 296 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
297 | is_multicast_ether_addr(hdr->addr1)) { | 297 | is_multicast_ether_addr(hdr->addr1)) { |
298 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 298 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
299 | return; | 299 | return; |
300 | } | 300 | } |
301 | 301 | ||
302 | rateidx = spinfo->txrate_idx; | 302 | rateidx = spinfo->txrate_idx; |
303 | 303 | ||
304 | if (rateidx >= sband->n_bitrates) | 304 | if (rateidx >= sband->n_bitrates) |
305 | rateidx = sband->n_bitrates - 1; | 305 | rateidx = sband->n_bitrates - 1; |
306 | 306 | ||
307 | info->control.rates[0].idx = rateidx; | 307 | info->control.rates[0].idx = rateidx; |
308 | 308 | ||
309 | #ifdef CONFIG_MAC80211_DEBUGFS | 309 | #ifdef CONFIG_MAC80211_DEBUGFS |
310 | rate_control_pid_event_tx_rate(&spinfo->events, | 310 | rate_control_pid_event_tx_rate(&spinfo->events, |
311 | rateidx, sband->bitrates[rateidx].bitrate); | 311 | rateidx, sband->bitrates[rateidx].bitrate); |
312 | #endif | 312 | #endif |
313 | } | 313 | } |
314 | 314 | ||
315 | static void | 315 | static void |
316 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | 316 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
317 | struct ieee80211_sta *sta, void *priv_sta) | 317 | struct ieee80211_sta *sta, void *priv_sta) |
318 | { | 318 | { |
319 | struct rc_pid_sta_info *spinfo = priv_sta; | 319 | struct rc_pid_sta_info *spinfo = priv_sta; |
320 | struct sta_info *si; | 320 | struct sta_info *si; |
321 | 321 | ||
322 | /* TODO: This routine should consider using RSSI from previous packets | 322 | /* TODO: This routine should consider using RSSI from previous packets |
323 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 323 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
324 | * Until that method is implemented, we will use the lowest supported | 324 | * Until that method is implemented, we will use the lowest supported |
325 | * rate as a workaround. */ | 325 | * rate as a workaround. */ |
326 | 326 | ||
327 | spinfo->txrate_idx = rate_lowest_index(sband, sta); | 327 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
328 | /* HACK */ | 328 | /* HACK */ |
329 | si = container_of(sta, struct sta_info, sta); | 329 | si = container_of(sta, struct sta_info, sta); |
330 | si->fail_avg = 0; | 330 | si->fail_avg = 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, | 333 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
334 | struct dentry *debugfsdir) | 334 | struct dentry *debugfsdir) |
335 | { | 335 | { |
336 | struct rc_pid_info *pinfo; | 336 | struct rc_pid_info *pinfo; |
337 | struct rc_pid_rateinfo *rinfo; | 337 | struct rc_pid_rateinfo *rinfo; |
338 | struct ieee80211_supported_band *sband; | 338 | struct ieee80211_supported_band *sband; |
339 | int i, j, tmp; | 339 | int i, j, tmp; |
340 | bool s; | 340 | bool s; |
341 | #ifdef CONFIG_MAC80211_DEBUGFS | 341 | #ifdef CONFIG_MAC80211_DEBUGFS |
342 | struct rc_pid_debugfs_entries *de; | 342 | struct rc_pid_debugfs_entries *de; |
343 | #endif | 343 | #endif |
344 | 344 | ||
345 | sband = hw->wiphy->bands[hw->conf.channel->band]; | 345 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
346 | 346 | ||
347 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 347 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
348 | if (!pinfo) | 348 | if (!pinfo) |
349 | return NULL; | 349 | return NULL; |
350 | 350 | ||
351 | /* We can safely assume that sband won't change unless we get | 351 | /* We can safely assume that sband won't change unless we get |
352 | * reinitialized. */ | 352 | * reinitialized. */ |
353 | rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC); | 353 | rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC); |
354 | if (!rinfo) { | 354 | if (!rinfo) { |
355 | kfree(pinfo); | 355 | kfree(pinfo); |
356 | return NULL; | 356 | return NULL; |
357 | } | 357 | } |
358 | 358 | ||
359 | pinfo->target = RC_PID_TARGET_PF; | 359 | pinfo->target = RC_PID_TARGET_PF; |
360 | pinfo->sampling_period = RC_PID_INTERVAL; | 360 | pinfo->sampling_period = RC_PID_INTERVAL; |
361 | pinfo->coeff_p = RC_PID_COEFF_P; | 361 | pinfo->coeff_p = RC_PID_COEFF_P; |
362 | pinfo->coeff_i = RC_PID_COEFF_I; | 362 | pinfo->coeff_i = RC_PID_COEFF_I; |
363 | pinfo->coeff_d = RC_PID_COEFF_D; | 363 | pinfo->coeff_d = RC_PID_COEFF_D; |
364 | pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT; | 364 | pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT; |
365 | pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR; | 365 | pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR; |
366 | pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION; | 366 | pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION; |
367 | pinfo->norm_offset = RC_PID_NORM_OFFSET; | 367 | pinfo->norm_offset = RC_PID_NORM_OFFSET; |
368 | pinfo->rinfo = rinfo; | 368 | pinfo->rinfo = rinfo; |
369 | pinfo->oldrate = 0; | 369 | pinfo->oldrate = 0; |
370 | 370 | ||
371 | /* Sort the rates. This is optimized for the most common case (i.e. | 371 | /* Sort the rates. This is optimized for the most common case (i.e. |
372 | * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed | 372 | * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed |
373 | * mapping too. */ | 373 | * mapping too. */ |
374 | for (i = 0; i < sband->n_bitrates; i++) { | 374 | for (i = 0; i < sband->n_bitrates; i++) { |
375 | rinfo[i].index = i; | 375 | rinfo[i].index = i; |
376 | rinfo[i].rev_index = i; | 376 | rinfo[i].rev_index = i; |
377 | if (RC_PID_FAST_START) | 377 | if (RC_PID_FAST_START) |
378 | rinfo[i].diff = 0; | 378 | rinfo[i].diff = 0; |
379 | else | 379 | else |
380 | rinfo[i].diff = i * pinfo->norm_offset; | 380 | rinfo[i].diff = i * pinfo->norm_offset; |
381 | } | 381 | } |
382 | for (i = 1; i < sband->n_bitrates; i++) { | 382 | for (i = 1; i < sband->n_bitrates; i++) { |
383 | s = 0; | 383 | s = 0; |
384 | for (j = 0; j < sband->n_bitrates - i; j++) | 384 | for (j = 0; j < sband->n_bitrates - i; j++) |
385 | if (unlikely(sband->bitrates[rinfo[j].index].bitrate > | 385 | if (unlikely(sband->bitrates[rinfo[j].index].bitrate > |
386 | sband->bitrates[rinfo[j + 1].index].bitrate)) { | 386 | sband->bitrates[rinfo[j + 1].index].bitrate)) { |
387 | tmp = rinfo[j].index; | 387 | tmp = rinfo[j].index; |
388 | rinfo[j].index = rinfo[j + 1].index; | 388 | rinfo[j].index = rinfo[j + 1].index; |
389 | rinfo[j + 1].index = tmp; | 389 | rinfo[j + 1].index = tmp; |
390 | rinfo[rinfo[j].index].rev_index = j; | 390 | rinfo[rinfo[j].index].rev_index = j; |
391 | rinfo[rinfo[j + 1].index].rev_index = j + 1; | 391 | rinfo[rinfo[j + 1].index].rev_index = j + 1; |
392 | s = 1; | 392 | s = 1; |
393 | } | 393 | } |
394 | if (!s) | 394 | if (!s) |
395 | break; | 395 | break; |
396 | } | 396 | } |
397 | 397 | ||
398 | #ifdef CONFIG_MAC80211_DEBUGFS | 398 | #ifdef CONFIG_MAC80211_DEBUGFS |
399 | de = &pinfo->dentries; | 399 | de = &pinfo->dentries; |
400 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 400 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
401 | debugfsdir, &pinfo->target); | 401 | debugfsdir, &pinfo->target); |
402 | de->sampling_period = debugfs_create_u32("sampling_period", | 402 | de->sampling_period = debugfs_create_u32("sampling_period", |
403 | S_IRUSR | S_IWUSR, debugfsdir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
404 | &pinfo->sampling_period); | 404 | &pinfo->sampling_period); |
405 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 405 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
406 | debugfsdir, &pinfo->coeff_p); | 406 | debugfsdir, &pinfo->coeff_p); |
407 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 407 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
408 | debugfsdir, &pinfo->coeff_i); | 408 | debugfsdir, &pinfo->coeff_i); |
409 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 409 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
410 | debugfsdir, &pinfo->coeff_d); | 410 | debugfsdir, &pinfo->coeff_d); |
411 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 411 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
412 | S_IRUSR | S_IWUSR, debugfsdir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
413 | &pinfo->smoothing_shift); | 413 | &pinfo->smoothing_shift); |
414 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 414 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
415 | S_IRUSR | S_IWUSR, debugfsdir, | 415 | S_IRUSR | S_IWUSR, debugfsdir, |
416 | &pinfo->sharpen_factor); | 416 | &pinfo->sharpen_factor); |
417 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 417 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
418 | S_IRUSR | S_IWUSR, debugfsdir, | 418 | S_IRUSR | S_IWUSR, debugfsdir, |
419 | &pinfo->sharpen_duration); | 419 | &pinfo->sharpen_duration); |
420 | de->norm_offset = debugfs_create_u32("norm_offset", | 420 | de->norm_offset = debugfs_create_u32("norm_offset", |
421 | S_IRUSR | S_IWUSR, debugfsdir, | 421 | S_IRUSR | S_IWUSR, debugfsdir, |
422 | &pinfo->norm_offset); | 422 | &pinfo->norm_offset); |
423 | #endif | 423 | #endif |
424 | 424 | ||
425 | return pinfo; | 425 | return pinfo; |
426 | } | 426 | } |
427 | 427 | ||
428 | static void rate_control_pid_free(void *priv) | 428 | static void rate_control_pid_free(void *priv) |
429 | { | 429 | { |
430 | struct rc_pid_info *pinfo = priv; | 430 | struct rc_pid_info *pinfo = priv; |
431 | #ifdef CONFIG_MAC80211_DEBUGFS | 431 | #ifdef CONFIG_MAC80211_DEBUGFS |
432 | struct rc_pid_debugfs_entries *de = &pinfo->dentries; | 432 | struct rc_pid_debugfs_entries *de = &pinfo->dentries; |
433 | 433 | ||
434 | debugfs_remove(de->norm_offset); | 434 | debugfs_remove(de->norm_offset); |
435 | debugfs_remove(de->sharpen_duration); | 435 | debugfs_remove(de->sharpen_duration); |
436 | debugfs_remove(de->sharpen_factor); | 436 | debugfs_remove(de->sharpen_factor); |
437 | debugfs_remove(de->smoothing_shift); | 437 | debugfs_remove(de->smoothing_shift); |
438 | debugfs_remove(de->coeff_d); | 438 | debugfs_remove(de->coeff_d); |
439 | debugfs_remove(de->coeff_i); | 439 | debugfs_remove(de->coeff_i); |
440 | debugfs_remove(de->coeff_p); | 440 | debugfs_remove(de->coeff_p); |
441 | debugfs_remove(de->sampling_period); | 441 | debugfs_remove(de->sampling_period); |
442 | debugfs_remove(de->target); | 442 | debugfs_remove(de->target); |
443 | #endif | 443 | #endif |
444 | 444 | ||
445 | kfree(pinfo->rinfo); | 445 | kfree(pinfo->rinfo); |
446 | kfree(pinfo); | 446 | kfree(pinfo); |
447 | } | 447 | } |
448 | 448 | ||
449 | static void rate_control_pid_clear(void *priv) | ||
450 | { | ||
451 | } | ||
452 | |||
453 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, | 449 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
454 | gfp_t gfp) | 450 | gfp_t gfp) |
455 | { | 451 | { |
456 | struct rc_pid_sta_info *spinfo; | 452 | struct rc_pid_sta_info *spinfo; |
457 | 453 | ||
458 | spinfo = kzalloc(sizeof(*spinfo), gfp); | 454 | spinfo = kzalloc(sizeof(*spinfo), gfp); |
459 | if (spinfo == NULL) | 455 | if (spinfo == NULL) |
460 | return NULL; | 456 | return NULL; |
461 | 457 | ||
462 | spinfo->last_sample = jiffies; | 458 | spinfo->last_sample = jiffies; |
463 | 459 | ||
464 | #ifdef CONFIG_MAC80211_DEBUGFS | 460 | #ifdef CONFIG_MAC80211_DEBUGFS |
465 | spin_lock_init(&spinfo->events.lock); | 461 | spin_lock_init(&spinfo->events.lock); |
466 | init_waitqueue_head(&spinfo->events.waitqueue); | 462 | init_waitqueue_head(&spinfo->events.waitqueue); |
467 | #endif | 463 | #endif |
468 | 464 | ||
469 | return spinfo; | 465 | return spinfo; |
470 | } | 466 | } |
471 | 467 | ||
472 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, | 468 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
473 | void *priv_sta) | 469 | void *priv_sta) |
474 | { | 470 | { |
475 | kfree(priv_sta); | 471 | kfree(priv_sta); |
476 | } | 472 | } |
477 | 473 | ||
478 | static struct rate_control_ops mac80211_rcpid = { | 474 | static struct rate_control_ops mac80211_rcpid = { |
479 | .name = "pid", | 475 | .name = "pid", |
480 | .tx_status = rate_control_pid_tx_status, | 476 | .tx_status = rate_control_pid_tx_status, |
481 | .get_rate = rate_control_pid_get_rate, | 477 | .get_rate = rate_control_pid_get_rate, |
482 | .rate_init = rate_control_pid_rate_init, | 478 | .rate_init = rate_control_pid_rate_init, |
483 | .clear = rate_control_pid_clear, | ||
484 | .alloc = rate_control_pid_alloc, | 479 | .alloc = rate_control_pid_alloc, |
485 | .free = rate_control_pid_free, | 480 | .free = rate_control_pid_free, |
486 | .alloc_sta = rate_control_pid_alloc_sta, | 481 | .alloc_sta = rate_control_pid_alloc_sta, |
487 | .free_sta = rate_control_pid_free_sta, | 482 | .free_sta = rate_control_pid_free_sta, |
488 | #ifdef CONFIG_MAC80211_DEBUGFS | 483 | #ifdef CONFIG_MAC80211_DEBUGFS |
489 | .add_sta_debugfs = rate_control_pid_add_sta_debugfs, | 484 | .add_sta_debugfs = rate_control_pid_add_sta_debugfs, |
490 | .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs, | 485 | .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs, |
491 | #endif | 486 | #endif |
492 | }; | 487 | }; |
493 | 488 | ||
494 | int __init rc80211_pid_init(void) | 489 | int __init rc80211_pid_init(void) |
495 | { | 490 | { |
496 | return ieee80211_rate_control_register(&mac80211_rcpid); | 491 | return ieee80211_rate_control_register(&mac80211_rcpid); |
497 | } | 492 | } |
498 | 493 | ||
499 | void rc80211_pid_exit(void) | 494 | void rc80211_pid_exit(void) |
500 | { | 495 | { |
501 | ieee80211_rate_control_unregister(&mac80211_rcpid); | 496 | ieee80211_rate_control_unregister(&mac80211_rcpid); |
502 | } | 497 | } |
503 | 498 |
net/mac80211/util.c
1 | /* | 1 | /* |
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | * utilities for mac80211 | 11 | * utilities for mac80211 |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <net/mac80211.h> | 14 | #include <net/mac80211.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
19 | #include <linux/etherdevice.h> | 19 | #include <linux/etherdevice.h> |
20 | #include <linux/if_arp.h> | 20 | #include <linux/if_arp.h> |
21 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
22 | #include <linux/bitmap.h> | 22 | #include <linux/bitmap.h> |
23 | #include <net/net_namespace.h> | 23 | #include <net/net_namespace.h> |
24 | #include <net/cfg80211.h> | 24 | #include <net/cfg80211.h> |
25 | #include <net/rtnetlink.h> | 25 | #include <net/rtnetlink.h> |
26 | 26 | ||
27 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
28 | #include "rate.h" | 28 | #include "rate.h" |
29 | #include "mesh.h" | 29 | #include "mesh.h" |
30 | #include "wme.h" | 30 | #include "wme.h" |
31 | 31 | ||
32 | /* privid for wiphys to determine whether they belong to us or not */ | 32 | /* privid for wiphys to determine whether they belong to us or not */ |
33 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 33 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; |
34 | 34 | ||
35 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ | 35 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ |
36 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ | 36 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ |
37 | const unsigned char rfc1042_header[] __aligned(2) = | 37 | const unsigned char rfc1042_header[] __aligned(2) = |
38 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; | 38 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; |
39 | 39 | ||
40 | /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ | 40 | /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ |
41 | const unsigned char bridge_tunnel_header[] __aligned(2) = | 41 | const unsigned char bridge_tunnel_header[] __aligned(2) = |
42 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | 42 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; |
43 | 43 | ||
44 | 44 | ||
45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
46 | enum nl80211_iftype type) | 46 | enum nl80211_iftype type) |
47 | { | 47 | { |
48 | __le16 fc = hdr->frame_control; | 48 | __le16 fc = hdr->frame_control; |
49 | 49 | ||
50 | /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ | 50 | /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ |
51 | if (len < 16) | 51 | if (len < 16) |
52 | return NULL; | 52 | return NULL; |
53 | 53 | ||
54 | if (ieee80211_is_data(fc)) { | 54 | if (ieee80211_is_data(fc)) { |
55 | if (len < 24) /* drop incorrect hdr len (data) */ | 55 | if (len < 24) /* drop incorrect hdr len (data) */ |
56 | return NULL; | 56 | return NULL; |
57 | 57 | ||
58 | if (ieee80211_has_a4(fc)) | 58 | if (ieee80211_has_a4(fc)) |
59 | return NULL; | 59 | return NULL; |
60 | if (ieee80211_has_tods(fc)) | 60 | if (ieee80211_has_tods(fc)) |
61 | return hdr->addr1; | 61 | return hdr->addr1; |
62 | if (ieee80211_has_fromds(fc)) | 62 | if (ieee80211_has_fromds(fc)) |
63 | return hdr->addr2; | 63 | return hdr->addr2; |
64 | 64 | ||
65 | return hdr->addr3; | 65 | return hdr->addr3; |
66 | } | 66 | } |
67 | 67 | ||
68 | if (ieee80211_is_mgmt(fc)) { | 68 | if (ieee80211_is_mgmt(fc)) { |
69 | if (len < 24) /* drop incorrect hdr len (mgmt) */ | 69 | if (len < 24) /* drop incorrect hdr len (mgmt) */ |
70 | return NULL; | 70 | return NULL; |
71 | return hdr->addr3; | 71 | return hdr->addr3; |
72 | } | 72 | } |
73 | 73 | ||
74 | if (ieee80211_is_ctl(fc)) { | 74 | if (ieee80211_is_ctl(fc)) { |
75 | if(ieee80211_is_pspoll(fc)) | 75 | if(ieee80211_is_pspoll(fc)) |
76 | return hdr->addr1; | 76 | return hdr->addr1; |
77 | 77 | ||
78 | if (ieee80211_is_back_req(fc)) { | 78 | if (ieee80211_is_back_req(fc)) { |
79 | switch (type) { | 79 | switch (type) { |
80 | case NL80211_IFTYPE_STATION: | 80 | case NL80211_IFTYPE_STATION: |
81 | return hdr->addr2; | 81 | return hdr->addr2; |
82 | case NL80211_IFTYPE_AP: | 82 | case NL80211_IFTYPE_AP: |
83 | case NL80211_IFTYPE_AP_VLAN: | 83 | case NL80211_IFTYPE_AP_VLAN: |
84 | return hdr->addr1; | 84 | return hdr->addr1; |
85 | default: | 85 | default: |
86 | break; /* fall through to the return */ | 86 | break; /* fall through to the return */ |
87 | } | 87 | } |
88 | } | 88 | } |
89 | } | 89 | } |
90 | 90 | ||
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
93 | 93 | ||
94 | unsigned int ieee80211_hdrlen(__le16 fc) | 94 | unsigned int ieee80211_hdrlen(__le16 fc) |
95 | { | 95 | { |
96 | unsigned int hdrlen = 24; | 96 | unsigned int hdrlen = 24; |
97 | 97 | ||
98 | if (ieee80211_is_data(fc)) { | 98 | if (ieee80211_is_data(fc)) { |
99 | if (ieee80211_has_a4(fc)) | 99 | if (ieee80211_has_a4(fc)) |
100 | hdrlen = 30; | 100 | hdrlen = 30; |
101 | if (ieee80211_is_data_qos(fc)) | 101 | if (ieee80211_is_data_qos(fc)) |
102 | hdrlen += IEEE80211_QOS_CTL_LEN; | 102 | hdrlen += IEEE80211_QOS_CTL_LEN; |
103 | goto out; | 103 | goto out; |
104 | } | 104 | } |
105 | 105 | ||
106 | if (ieee80211_is_ctl(fc)) { | 106 | if (ieee80211_is_ctl(fc)) { |
107 | /* | 107 | /* |
108 | * ACK and CTS are 10 bytes, all others 16. To see how | 108 | * ACK and CTS are 10 bytes, all others 16. To see how |
109 | * to get this condition consider | 109 | * to get this condition consider |
110 | * subtype mask: 0b0000000011110000 (0x00F0) | 110 | * subtype mask: 0b0000000011110000 (0x00F0) |
111 | * ACK subtype: 0b0000000011010000 (0x00D0) | 111 | * ACK subtype: 0b0000000011010000 (0x00D0) |
112 | * CTS subtype: 0b0000000011000000 (0x00C0) | 112 | * CTS subtype: 0b0000000011000000 (0x00C0) |
113 | * bits that matter: ^^^ (0x00E0) | 113 | * bits that matter: ^^^ (0x00E0) |
114 | * value of those: 0b0000000011000000 (0x00C0) | 114 | * value of those: 0b0000000011000000 (0x00C0) |
115 | */ | 115 | */ |
116 | if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) | 116 | if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0)) |
117 | hdrlen = 10; | 117 | hdrlen = 10; |
118 | else | 118 | else |
119 | hdrlen = 16; | 119 | hdrlen = 16; |
120 | } | 120 | } |
121 | out: | 121 | out: |
122 | return hdrlen; | 122 | return hdrlen; |
123 | } | 123 | } |
124 | EXPORT_SYMBOL(ieee80211_hdrlen); | 124 | EXPORT_SYMBOL(ieee80211_hdrlen); |
125 | 125 | ||
126 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | 126 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) |
127 | { | 127 | { |
128 | const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data; | 128 | const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data; |
129 | unsigned int hdrlen; | 129 | unsigned int hdrlen; |
130 | 130 | ||
131 | if (unlikely(skb->len < 10)) | 131 | if (unlikely(skb->len < 10)) |
132 | return 0; | 132 | return 0; |
133 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 133 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
134 | if (unlikely(hdrlen > skb->len)) | 134 | if (unlikely(hdrlen > skb->len)) |
135 | return 0; | 135 | return 0; |
136 | return hdrlen; | 136 | return hdrlen; |
137 | } | 137 | } |
138 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 138 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
139 | 139 | ||
140 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | 140 | int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
141 | { | 141 | { |
142 | int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; | 142 | int ae = meshhdr->flags & IEEE80211S_FLAGS_AE; |
143 | /* 7.1.3.5a.2 */ | 143 | /* 7.1.3.5a.2 */ |
144 | switch (ae) { | 144 | switch (ae) { |
145 | case 0: | 145 | case 0: |
146 | return 6; | 146 | return 6; |
147 | case 1: | 147 | case 1: |
148 | return 12; | 148 | return 12; |
149 | case 2: | 149 | case 2: |
150 | return 18; | 150 | return 18; |
151 | case 3: | 151 | case 3: |
152 | return 24; | 152 | return 24; |
153 | default: | 153 | default: |
154 | return 6; | 154 | return 6; |
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | 158 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) |
159 | { | 159 | { |
160 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 160 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; |
161 | 161 | ||
162 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 162 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
163 | if (tx->extra_frag) { | 163 | if (tx->extra_frag) { |
164 | struct ieee80211_hdr *fhdr; | 164 | struct ieee80211_hdr *fhdr; |
165 | int i; | 165 | int i; |
166 | for (i = 0; i < tx->num_extra_frag; i++) { | 166 | for (i = 0; i < tx->num_extra_frag; i++) { |
167 | fhdr = (struct ieee80211_hdr *) | 167 | fhdr = (struct ieee80211_hdr *) |
168 | tx->extra_frag[i]->data; | 168 | tx->extra_frag[i]->data; |
169 | fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 169 | fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
170 | } | 170 | } |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
174 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 174 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
175 | int rate, int erp, int short_preamble) | 175 | int rate, int erp, int short_preamble) |
176 | { | 176 | { |
177 | int dur; | 177 | int dur; |
178 | 178 | ||
179 | /* calculate duration (in microseconds, rounded up to next higher | 179 | /* calculate duration (in microseconds, rounded up to next higher |
180 | * integer if it includes a fractional microsecond) to send frame of | 180 | * integer if it includes a fractional microsecond) to send frame of |
181 | * len bytes (does not include FCS) at the given rate. Duration will | 181 | * len bytes (does not include FCS) at the given rate. Duration will |
182 | * also include SIFS. | 182 | * also include SIFS. |
183 | * | 183 | * |
184 | * rate is in 100 kbps, so divident is multiplied by 10 in the | 184 | * rate is in 100 kbps, so divident is multiplied by 10 in the |
185 | * DIV_ROUND_UP() operations. | 185 | * DIV_ROUND_UP() operations. |
186 | */ | 186 | */ |
187 | 187 | ||
188 | if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { | 188 | if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { |
189 | /* | 189 | /* |
190 | * OFDM: | 190 | * OFDM: |
191 | * | 191 | * |
192 | * N_DBPS = DATARATE x 4 | 192 | * N_DBPS = DATARATE x 4 |
193 | * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) | 193 | * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS) |
194 | * (16 = SIGNAL time, 6 = tail bits) | 194 | * (16 = SIGNAL time, 6 = tail bits) |
195 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext | 195 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext |
196 | * | 196 | * |
197 | * T_SYM = 4 usec | 197 | * T_SYM = 4 usec |
198 | * 802.11a - 17.5.2: aSIFSTime = 16 usec | 198 | * 802.11a - 17.5.2: aSIFSTime = 16 usec |
199 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + | 199 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + |
200 | * signal ext = 6 usec | 200 | * signal ext = 6 usec |
201 | */ | 201 | */ |
202 | dur = 16; /* SIFS + signal ext */ | 202 | dur = 16; /* SIFS + signal ext */ |
203 | dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ | 203 | dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ |
204 | dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ | 204 | dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ |
205 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, | 205 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, |
206 | 4 * rate); /* T_SYM x N_SYM */ | 206 | 4 * rate); /* T_SYM x N_SYM */ |
207 | } else { | 207 | } else { |
208 | /* | 208 | /* |
209 | * 802.11b or 802.11g with 802.11b compatibility: | 209 | * 802.11b or 802.11g with 802.11b compatibility: |
210 | * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + | 210 | * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime + |
211 | * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. | 211 | * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0. |
212 | * | 212 | * |
213 | * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 | 213 | * 802.11 (DS): 15.3.3, 802.11b: 18.3.4 |
214 | * aSIFSTime = 10 usec | 214 | * aSIFSTime = 10 usec |
215 | * aPreambleLength = 144 usec or 72 usec with short preamble | 215 | * aPreambleLength = 144 usec or 72 usec with short preamble |
216 | * aPLCPHeaderLength = 48 usec or 24 usec with short preamble | 216 | * aPLCPHeaderLength = 48 usec or 24 usec with short preamble |
217 | */ | 217 | */ |
218 | dur = 10; /* aSIFSTime = 10 usec */ | 218 | dur = 10; /* aSIFSTime = 10 usec */ |
219 | dur += short_preamble ? (72 + 24) : (144 + 48); | 219 | dur += short_preamble ? (72 + 24) : (144 + 48); |
220 | 220 | ||
221 | dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate); | 221 | dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate); |
222 | } | 222 | } |
223 | 223 | ||
224 | return dur; | 224 | return dur; |
225 | } | 225 | } |
226 | 226 | ||
227 | /* Exported duration function for driver use */ | 227 | /* Exported duration function for driver use */ |
228 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | 228 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, |
229 | struct ieee80211_vif *vif, | 229 | struct ieee80211_vif *vif, |
230 | size_t frame_len, | 230 | size_t frame_len, |
231 | struct ieee80211_rate *rate) | 231 | struct ieee80211_rate *rate) |
232 | { | 232 | { |
233 | struct ieee80211_local *local = hw_to_local(hw); | 233 | struct ieee80211_local *local = hw_to_local(hw); |
234 | struct ieee80211_sub_if_data *sdata; | 234 | struct ieee80211_sub_if_data *sdata; |
235 | u16 dur; | 235 | u16 dur; |
236 | int erp; | 236 | int erp; |
237 | bool short_preamble = false; | 237 | bool short_preamble = false; |
238 | 238 | ||
239 | erp = 0; | 239 | erp = 0; |
240 | if (vif) { | 240 | if (vif) { |
241 | sdata = vif_to_sdata(vif); | 241 | sdata = vif_to_sdata(vif); |
242 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 242 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
243 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 243 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
244 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 244 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
245 | } | 245 | } |
246 | 246 | ||
247 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, | 247 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, |
248 | short_preamble); | 248 | short_preamble); |
249 | 249 | ||
250 | return cpu_to_le16(dur); | 250 | return cpu_to_le16(dur); |
251 | } | 251 | } |
252 | EXPORT_SYMBOL(ieee80211_generic_frame_duration); | 252 | EXPORT_SYMBOL(ieee80211_generic_frame_duration); |
253 | 253 | ||
254 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | 254 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, |
255 | struct ieee80211_vif *vif, size_t frame_len, | 255 | struct ieee80211_vif *vif, size_t frame_len, |
256 | const struct ieee80211_tx_info *frame_txctl) | 256 | const struct ieee80211_tx_info *frame_txctl) |
257 | { | 257 | { |
258 | struct ieee80211_local *local = hw_to_local(hw); | 258 | struct ieee80211_local *local = hw_to_local(hw); |
259 | struct ieee80211_rate *rate; | 259 | struct ieee80211_rate *rate; |
260 | struct ieee80211_sub_if_data *sdata; | 260 | struct ieee80211_sub_if_data *sdata; |
261 | bool short_preamble; | 261 | bool short_preamble; |
262 | int erp; | 262 | int erp; |
263 | u16 dur; | 263 | u16 dur; |
264 | struct ieee80211_supported_band *sband; | 264 | struct ieee80211_supported_band *sband; |
265 | 265 | ||
266 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 266 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
267 | 267 | ||
268 | short_preamble = false; | 268 | short_preamble = false; |
269 | 269 | ||
270 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 270 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
271 | 271 | ||
272 | erp = 0; | 272 | erp = 0; |
273 | if (vif) { | 273 | if (vif) { |
274 | sdata = vif_to_sdata(vif); | 274 | sdata = vif_to_sdata(vif); |
275 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 275 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
276 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 276 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
277 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 277 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
278 | } | 278 | } |
279 | 279 | ||
280 | /* CTS duration */ | 280 | /* CTS duration */ |
281 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, | 281 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, |
282 | erp, short_preamble); | 282 | erp, short_preamble); |
283 | /* Data frame duration */ | 283 | /* Data frame duration */ |
284 | dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, | 284 | dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, |
285 | erp, short_preamble); | 285 | erp, short_preamble); |
286 | /* ACK duration */ | 286 | /* ACK duration */ |
287 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, | 287 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, |
288 | erp, short_preamble); | 288 | erp, short_preamble); |
289 | 289 | ||
290 | return cpu_to_le16(dur); | 290 | return cpu_to_le16(dur); |
291 | } | 291 | } |
292 | EXPORT_SYMBOL(ieee80211_rts_duration); | 292 | EXPORT_SYMBOL(ieee80211_rts_duration); |
293 | 293 | ||
294 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | 294 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, |
295 | struct ieee80211_vif *vif, | 295 | struct ieee80211_vif *vif, |
296 | size_t frame_len, | 296 | size_t frame_len, |
297 | const struct ieee80211_tx_info *frame_txctl) | 297 | const struct ieee80211_tx_info *frame_txctl) |
298 | { | 298 | { |
299 | struct ieee80211_local *local = hw_to_local(hw); | 299 | struct ieee80211_local *local = hw_to_local(hw); |
300 | struct ieee80211_rate *rate; | 300 | struct ieee80211_rate *rate; |
301 | struct ieee80211_sub_if_data *sdata; | 301 | struct ieee80211_sub_if_data *sdata; |
302 | bool short_preamble; | 302 | bool short_preamble; |
303 | int erp; | 303 | int erp; |
304 | u16 dur; | 304 | u16 dur; |
305 | struct ieee80211_supported_band *sband; | 305 | struct ieee80211_supported_band *sband; |
306 | 306 | ||
307 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 307 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
308 | 308 | ||
309 | short_preamble = false; | 309 | short_preamble = false; |
310 | 310 | ||
311 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 311 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
312 | erp = 0; | 312 | erp = 0; |
313 | if (vif) { | 313 | if (vif) { |
314 | sdata = vif_to_sdata(vif); | 314 | sdata = vif_to_sdata(vif); |
315 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 315 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
316 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 316 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
317 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 317 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
318 | } | 318 | } |
319 | 319 | ||
320 | /* Data frame duration */ | 320 | /* Data frame duration */ |
321 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, | 321 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
322 | erp, short_preamble); | 322 | erp, short_preamble); |
323 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { | 323 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { |
324 | /* ACK duration */ | 324 | /* ACK duration */ |
325 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, | 325 | dur += ieee80211_frame_duration(local, 10, rate->bitrate, |
326 | erp, short_preamble); | 326 | erp, short_preamble); |
327 | } | 327 | } |
328 | 328 | ||
329 | return cpu_to_le16(dur); | 329 | return cpu_to_le16(dur); |
330 | } | 330 | } |
331 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); | 331 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); |
332 | 332 | ||
333 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | 333 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) |
334 | { | 334 | { |
335 | struct ieee80211_local *local = hw_to_local(hw); | 335 | struct ieee80211_local *local = hw_to_local(hw); |
336 | 336 | ||
337 | if (test_bit(queue, local->queues_pending)) { | 337 | if (test_bit(queue, local->queues_pending)) { |
338 | set_bit(queue, local->queues_pending_run); | 338 | set_bit(queue, local->queues_pending_run); |
339 | tasklet_schedule(&local->tx_pending_tasklet); | 339 | tasklet_schedule(&local->tx_pending_tasklet); |
340 | } else { | 340 | } else { |
341 | netif_wake_subqueue(local->mdev, queue); | 341 | netif_wake_subqueue(local->mdev, queue); |
342 | } | 342 | } |
343 | } | 343 | } |
344 | EXPORT_SYMBOL(ieee80211_wake_queue); | 344 | EXPORT_SYMBOL(ieee80211_wake_queue); |
345 | 345 | ||
346 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | 346 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) |
347 | { | 347 | { |
348 | struct ieee80211_local *local = hw_to_local(hw); | 348 | struct ieee80211_local *local = hw_to_local(hw); |
349 | 349 | ||
350 | netif_stop_subqueue(local->mdev, queue); | 350 | netif_stop_subqueue(local->mdev, queue); |
351 | } | 351 | } |
352 | EXPORT_SYMBOL(ieee80211_stop_queue); | 352 | EXPORT_SYMBOL(ieee80211_stop_queue); |
353 | 353 | ||
354 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 354 | void ieee80211_stop_queues(struct ieee80211_hw *hw) |
355 | { | 355 | { |
356 | int i; | 356 | int i; |
357 | 357 | ||
358 | for (i = 0; i < ieee80211_num_queues(hw); i++) | 358 | for (i = 0; i < ieee80211_num_queues(hw); i++) |
359 | ieee80211_stop_queue(hw, i); | 359 | ieee80211_stop_queue(hw, i); |
360 | } | 360 | } |
361 | EXPORT_SYMBOL(ieee80211_stop_queues); | 361 | EXPORT_SYMBOL(ieee80211_stop_queues); |
362 | 362 | ||
363 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | 363 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) |
364 | { | 364 | { |
365 | struct ieee80211_local *local = hw_to_local(hw); | 365 | struct ieee80211_local *local = hw_to_local(hw); |
366 | return __netif_subqueue_stopped(local->mdev, queue); | 366 | return __netif_subqueue_stopped(local->mdev, queue); |
367 | } | 367 | } |
368 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 368 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
369 | 369 | ||
370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
371 | { | 371 | { |
372 | int i; | 372 | int i; |
373 | 373 | ||
374 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) | 374 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) |
375 | ieee80211_wake_queue(hw, i); | 375 | ieee80211_wake_queue(hw, i); |
376 | } | 376 | } |
377 | EXPORT_SYMBOL(ieee80211_wake_queues); | 377 | EXPORT_SYMBOL(ieee80211_wake_queues); |
378 | 378 | ||
379 | void ieee80211_iterate_active_interfaces( | 379 | void ieee80211_iterate_active_interfaces( |
380 | struct ieee80211_hw *hw, | 380 | struct ieee80211_hw *hw, |
381 | void (*iterator)(void *data, u8 *mac, | 381 | void (*iterator)(void *data, u8 *mac, |
382 | struct ieee80211_vif *vif), | 382 | struct ieee80211_vif *vif), |
383 | void *data) | 383 | void *data) |
384 | { | 384 | { |
385 | struct ieee80211_local *local = hw_to_local(hw); | 385 | struct ieee80211_local *local = hw_to_local(hw); |
386 | struct ieee80211_sub_if_data *sdata; | 386 | struct ieee80211_sub_if_data *sdata; |
387 | 387 | ||
388 | rtnl_lock(); | 388 | rtnl_lock(); |
389 | 389 | ||
390 | list_for_each_entry(sdata, &local->interfaces, list) { | 390 | list_for_each_entry(sdata, &local->interfaces, list) { |
391 | switch (sdata->vif.type) { | 391 | switch (sdata->vif.type) { |
392 | case __NL80211_IFTYPE_AFTER_LAST: | 392 | case __NL80211_IFTYPE_AFTER_LAST: |
393 | case NL80211_IFTYPE_UNSPECIFIED: | 393 | case NL80211_IFTYPE_UNSPECIFIED: |
394 | case NL80211_IFTYPE_MONITOR: | 394 | case NL80211_IFTYPE_MONITOR: |
395 | case NL80211_IFTYPE_AP_VLAN: | 395 | case NL80211_IFTYPE_AP_VLAN: |
396 | continue; | 396 | continue; |
397 | case NL80211_IFTYPE_AP: | 397 | case NL80211_IFTYPE_AP: |
398 | case NL80211_IFTYPE_STATION: | 398 | case NL80211_IFTYPE_STATION: |
399 | case NL80211_IFTYPE_ADHOC: | 399 | case NL80211_IFTYPE_ADHOC: |
400 | case NL80211_IFTYPE_WDS: | 400 | case NL80211_IFTYPE_WDS: |
401 | case NL80211_IFTYPE_MESH_POINT: | 401 | case NL80211_IFTYPE_MESH_POINT: |
402 | break; | 402 | break; |
403 | } | 403 | } |
404 | if (netif_running(sdata->dev)) | 404 | if (netif_running(sdata->dev)) |
405 | iterator(data, sdata->dev->dev_addr, | 405 | iterator(data, sdata->dev->dev_addr, |
406 | &sdata->vif); | 406 | &sdata->vif); |
407 | } | 407 | } |
408 | 408 | ||
409 | rtnl_unlock(); | 409 | rtnl_unlock(); |
410 | } | 410 | } |
411 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 411 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
412 | 412 | ||
413 | void ieee80211_iterate_active_interfaces_atomic( | 413 | void ieee80211_iterate_active_interfaces_atomic( |
414 | struct ieee80211_hw *hw, | 414 | struct ieee80211_hw *hw, |
415 | void (*iterator)(void *data, u8 *mac, | 415 | void (*iterator)(void *data, u8 *mac, |
416 | struct ieee80211_vif *vif), | 416 | struct ieee80211_vif *vif), |
417 | void *data) | 417 | void *data) |
418 | { | 418 | { |
419 | struct ieee80211_local *local = hw_to_local(hw); | 419 | struct ieee80211_local *local = hw_to_local(hw); |
420 | struct ieee80211_sub_if_data *sdata; | 420 | struct ieee80211_sub_if_data *sdata; |
421 | 421 | ||
422 | rcu_read_lock(); | 422 | rcu_read_lock(); |
423 | 423 | ||
424 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 424 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
425 | switch (sdata->vif.type) { | 425 | switch (sdata->vif.type) { |
426 | case __NL80211_IFTYPE_AFTER_LAST: | 426 | case __NL80211_IFTYPE_AFTER_LAST: |
427 | case NL80211_IFTYPE_UNSPECIFIED: | 427 | case NL80211_IFTYPE_UNSPECIFIED: |
428 | case NL80211_IFTYPE_MONITOR: | 428 | case NL80211_IFTYPE_MONITOR: |
429 | case NL80211_IFTYPE_AP_VLAN: | 429 | case NL80211_IFTYPE_AP_VLAN: |
430 | continue; | 430 | continue; |
431 | case NL80211_IFTYPE_AP: | 431 | case NL80211_IFTYPE_AP: |
432 | case NL80211_IFTYPE_STATION: | 432 | case NL80211_IFTYPE_STATION: |
433 | case NL80211_IFTYPE_ADHOC: | 433 | case NL80211_IFTYPE_ADHOC: |
434 | case NL80211_IFTYPE_WDS: | 434 | case NL80211_IFTYPE_WDS: |
435 | case NL80211_IFTYPE_MESH_POINT: | 435 | case NL80211_IFTYPE_MESH_POINT: |
436 | break; | 436 | break; |
437 | } | 437 | } |
438 | if (netif_running(sdata->dev)) | 438 | if (netif_running(sdata->dev)) |
439 | iterator(data, sdata->dev->dev_addr, | 439 | iterator(data, sdata->dev->dev_addr, |
440 | &sdata->vif); | 440 | &sdata->vif); |
441 | } | 441 | } |
442 | 442 | ||
443 | rcu_read_unlock(); | 443 | rcu_read_unlock(); |
444 | } | 444 | } |
445 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 445 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
446 | 446 | ||
447 | void ieee802_11_parse_elems(u8 *start, size_t len, | 447 | void ieee802_11_parse_elems(u8 *start, size_t len, |
448 | struct ieee802_11_elems *elems) | 448 | struct ieee802_11_elems *elems) |
449 | { | 449 | { |
450 | size_t left = len; | 450 | size_t left = len; |
451 | u8 *pos = start; | 451 | u8 *pos = start; |
452 | 452 | ||
453 | memset(elems, 0, sizeof(*elems)); | 453 | memset(elems, 0, sizeof(*elems)); |
454 | elems->ie_start = start; | 454 | elems->ie_start = start; |
455 | elems->total_len = len; | 455 | elems->total_len = len; |
456 | 456 | ||
457 | while (left >= 2) { | 457 | while (left >= 2) { |
458 | u8 id, elen; | 458 | u8 id, elen; |
459 | 459 | ||
460 | id = *pos++; | 460 | id = *pos++; |
461 | elen = *pos++; | 461 | elen = *pos++; |
462 | left -= 2; | 462 | left -= 2; |
463 | 463 | ||
464 | if (elen > left) | 464 | if (elen > left) |
465 | return; | 465 | return; |
466 | 466 | ||
467 | switch (id) { | 467 | switch (id) { |
468 | case WLAN_EID_SSID: | 468 | case WLAN_EID_SSID: |
469 | elems->ssid = pos; | 469 | elems->ssid = pos; |
470 | elems->ssid_len = elen; | 470 | elems->ssid_len = elen; |
471 | break; | 471 | break; |
472 | case WLAN_EID_SUPP_RATES: | 472 | case WLAN_EID_SUPP_RATES: |
473 | elems->supp_rates = pos; | 473 | elems->supp_rates = pos; |
474 | elems->supp_rates_len = elen; | 474 | elems->supp_rates_len = elen; |
475 | break; | 475 | break; |
476 | case WLAN_EID_FH_PARAMS: | 476 | case WLAN_EID_FH_PARAMS: |
477 | elems->fh_params = pos; | 477 | elems->fh_params = pos; |
478 | elems->fh_params_len = elen; | 478 | elems->fh_params_len = elen; |
479 | break; | 479 | break; |
480 | case WLAN_EID_DS_PARAMS: | 480 | case WLAN_EID_DS_PARAMS: |
481 | elems->ds_params = pos; | 481 | elems->ds_params = pos; |
482 | elems->ds_params_len = elen; | 482 | elems->ds_params_len = elen; |
483 | break; | 483 | break; |
484 | case WLAN_EID_CF_PARAMS: | 484 | case WLAN_EID_CF_PARAMS: |
485 | elems->cf_params = pos; | 485 | elems->cf_params = pos; |
486 | elems->cf_params_len = elen; | 486 | elems->cf_params_len = elen; |
487 | break; | 487 | break; |
488 | case WLAN_EID_TIM: | 488 | case WLAN_EID_TIM: |
489 | elems->tim = pos; | 489 | elems->tim = pos; |
490 | elems->tim_len = elen; | 490 | elems->tim_len = elen; |
491 | break; | 491 | break; |
492 | case WLAN_EID_IBSS_PARAMS: | 492 | case WLAN_EID_IBSS_PARAMS: |
493 | elems->ibss_params = pos; | 493 | elems->ibss_params = pos; |
494 | elems->ibss_params_len = elen; | 494 | elems->ibss_params_len = elen; |
495 | break; | 495 | break; |
496 | case WLAN_EID_CHALLENGE: | 496 | case WLAN_EID_CHALLENGE: |
497 | elems->challenge = pos; | 497 | elems->challenge = pos; |
498 | elems->challenge_len = elen; | 498 | elems->challenge_len = elen; |
499 | break; | 499 | break; |
500 | case WLAN_EID_WPA: | 500 | case WLAN_EID_WPA: |
501 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | 501 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && |
502 | pos[2] == 0xf2) { | 502 | pos[2] == 0xf2) { |
503 | /* Microsoft OUI (00:50:F2) */ | 503 | /* Microsoft OUI (00:50:F2) */ |
504 | if (pos[3] == 1) { | 504 | if (pos[3] == 1) { |
505 | /* OUI Type 1 - WPA IE */ | 505 | /* OUI Type 1 - WPA IE */ |
506 | elems->wpa = pos; | 506 | elems->wpa = pos; |
507 | elems->wpa_len = elen; | 507 | elems->wpa_len = elen; |
508 | } else if (elen >= 5 && pos[3] == 2) { | 508 | } else if (elen >= 5 && pos[3] == 2) { |
509 | if (pos[4] == 0) { | 509 | if (pos[4] == 0) { |
510 | elems->wmm_info = pos; | 510 | elems->wmm_info = pos; |
511 | elems->wmm_info_len = elen; | 511 | elems->wmm_info_len = elen; |
512 | } else if (pos[4] == 1) { | 512 | } else if (pos[4] == 1) { |
513 | elems->wmm_param = pos; | 513 | elems->wmm_param = pos; |
514 | elems->wmm_param_len = elen; | 514 | elems->wmm_param_len = elen; |
515 | } | 515 | } |
516 | } | 516 | } |
517 | } | 517 | } |
518 | break; | 518 | break; |
519 | case WLAN_EID_RSN: | 519 | case WLAN_EID_RSN: |
520 | elems->rsn = pos; | 520 | elems->rsn = pos; |
521 | elems->rsn_len = elen; | 521 | elems->rsn_len = elen; |
522 | break; | 522 | break; |
523 | case WLAN_EID_ERP_INFO: | 523 | case WLAN_EID_ERP_INFO: |
524 | elems->erp_info = pos; | 524 | elems->erp_info = pos; |
525 | elems->erp_info_len = elen; | 525 | elems->erp_info_len = elen; |
526 | break; | 526 | break; |
527 | case WLAN_EID_EXT_SUPP_RATES: | 527 | case WLAN_EID_EXT_SUPP_RATES: |
528 | elems->ext_supp_rates = pos; | 528 | elems->ext_supp_rates = pos; |
529 | elems->ext_supp_rates_len = elen; | 529 | elems->ext_supp_rates_len = elen; |
530 | break; | 530 | break; |
531 | case WLAN_EID_HT_CAPABILITY: | 531 | case WLAN_EID_HT_CAPABILITY: |
532 | if (elen >= sizeof(struct ieee80211_ht_cap)) | 532 | if (elen >= sizeof(struct ieee80211_ht_cap)) |
533 | elems->ht_cap_elem = (void *)pos; | 533 | elems->ht_cap_elem = (void *)pos; |
534 | break; | 534 | break; |
535 | case WLAN_EID_HT_INFORMATION: | 535 | case WLAN_EID_HT_INFORMATION: |
536 | if (elen >= sizeof(struct ieee80211_ht_info)) | 536 | if (elen >= sizeof(struct ieee80211_ht_info)) |
537 | elems->ht_info_elem = (void *)pos; | 537 | elems->ht_info_elem = (void *)pos; |
538 | break; | 538 | break; |
539 | case WLAN_EID_MESH_ID: | 539 | case WLAN_EID_MESH_ID: |
540 | elems->mesh_id = pos; | 540 | elems->mesh_id = pos; |
541 | elems->mesh_id_len = elen; | 541 | elems->mesh_id_len = elen; |
542 | break; | 542 | break; |
543 | case WLAN_EID_MESH_CONFIG: | 543 | case WLAN_EID_MESH_CONFIG: |
544 | elems->mesh_config = pos; | 544 | elems->mesh_config = pos; |
545 | elems->mesh_config_len = elen; | 545 | elems->mesh_config_len = elen; |
546 | break; | 546 | break; |
547 | case WLAN_EID_PEER_LINK: | 547 | case WLAN_EID_PEER_LINK: |
548 | elems->peer_link = pos; | 548 | elems->peer_link = pos; |
549 | elems->peer_link_len = elen; | 549 | elems->peer_link_len = elen; |
550 | break; | 550 | break; |
551 | case WLAN_EID_PREQ: | 551 | case WLAN_EID_PREQ: |
552 | elems->preq = pos; | 552 | elems->preq = pos; |
553 | elems->preq_len = elen; | 553 | elems->preq_len = elen; |
554 | break; | 554 | break; |
555 | case WLAN_EID_PREP: | 555 | case WLAN_EID_PREP: |
556 | elems->prep = pos; | 556 | elems->prep = pos; |
557 | elems->prep_len = elen; | 557 | elems->prep_len = elen; |
558 | break; | 558 | break; |
559 | case WLAN_EID_PERR: | 559 | case WLAN_EID_PERR: |
560 | elems->perr = pos; | 560 | elems->perr = pos; |
561 | elems->perr_len = elen; | 561 | elems->perr_len = elen; |
562 | break; | 562 | break; |
563 | case WLAN_EID_CHANNEL_SWITCH: | 563 | case WLAN_EID_CHANNEL_SWITCH: |
564 | elems->ch_switch_elem = pos; | 564 | elems->ch_switch_elem = pos; |
565 | elems->ch_switch_elem_len = elen; | 565 | elems->ch_switch_elem_len = elen; |
566 | break; | 566 | break; |
567 | case WLAN_EID_QUIET: | 567 | case WLAN_EID_QUIET: |
568 | if (!elems->quiet_elem) { | 568 | if (!elems->quiet_elem) { |
569 | elems->quiet_elem = pos; | 569 | elems->quiet_elem = pos; |
570 | elems->quiet_elem_len = elen; | 570 | elems->quiet_elem_len = elen; |
571 | } | 571 | } |
572 | elems->num_of_quiet_elem++; | 572 | elems->num_of_quiet_elem++; |
573 | break; | 573 | break; |
574 | case WLAN_EID_COUNTRY: | 574 | case WLAN_EID_COUNTRY: |
575 | elems->country_elem = pos; | 575 | elems->country_elem = pos; |
576 | elems->country_elem_len = elen; | 576 | elems->country_elem_len = elen; |
577 | break; | 577 | break; |
578 | case WLAN_EID_PWR_CONSTRAINT: | 578 | case WLAN_EID_PWR_CONSTRAINT: |
579 | elems->pwr_constr_elem = pos; | 579 | elems->pwr_constr_elem = pos; |
580 | elems->pwr_constr_elem_len = elen; | 580 | elems->pwr_constr_elem_len = elen; |
581 | break; | 581 | break; |
582 | default: | 582 | default: |
583 | break; | 583 | break; |
584 | } | 584 | } |
585 | 585 | ||
586 | left -= elen; | 586 | left -= elen; |
587 | pos += elen; | 587 | pos += elen; |
588 | } | 588 | } |
589 | } | 589 | } |
590 | 590 | ||
591 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | 591 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) |
592 | { | 592 | { |
593 | struct ieee80211_local *local = sdata->local; | 593 | struct ieee80211_local *local = sdata->local; |
594 | struct ieee80211_tx_queue_params qparam; | 594 | struct ieee80211_tx_queue_params qparam; |
595 | int i; | 595 | int i; |
596 | 596 | ||
597 | if (!local->ops->conf_tx) | 597 | if (!local->ops->conf_tx) |
598 | return; | 598 | return; |
599 | 599 | ||
600 | memset(&qparam, 0, sizeof(qparam)); | 600 | memset(&qparam, 0, sizeof(qparam)); |
601 | 601 | ||
602 | qparam.aifs = 2; | 602 | qparam.aifs = 2; |
603 | 603 | ||
604 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 604 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
605 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | 605 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) |
606 | qparam.cw_min = 31; | 606 | qparam.cw_min = 31; |
607 | else | 607 | else |
608 | qparam.cw_min = 15; | 608 | qparam.cw_min = 15; |
609 | 609 | ||
610 | qparam.cw_max = 1023; | 610 | qparam.cw_max = 1023; |
611 | qparam.txop = 0; | 611 | qparam.txop = 0; |
612 | 612 | ||
613 | for (i = 0; i < local_to_hw(local)->queues; i++) | 613 | for (i = 0; i < local_to_hw(local)->queues; i++) |
614 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | 614 | local->ops->conf_tx(local_to_hw(local), i, &qparam); |
615 | } | 615 | } |
616 | 616 | ||
617 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 617 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
618 | int encrypt) | 618 | int encrypt) |
619 | { | 619 | { |
620 | skb->dev = sdata->local->mdev; | 620 | skb->dev = sdata->local->mdev; |
621 | skb_set_mac_header(skb, 0); | 621 | skb_set_mac_header(skb, 0); |
622 | skb_set_network_header(skb, 0); | 622 | skb_set_network_header(skb, 0); |
623 | skb_set_transport_header(skb, 0); | 623 | skb_set_transport_header(skb, 0); |
624 | 624 | ||
625 | skb->iif = sdata->dev->ifindex; | 625 | skb->iif = sdata->dev->ifindex; |
626 | skb->do_not_encrypt = !encrypt; | 626 | skb->do_not_encrypt = !encrypt; |
627 | 627 | ||
628 | dev_queue_xmit(skb); | 628 | dev_queue_xmit(skb); |
629 | } | 629 | } |
630 | 630 | ||
631 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | 631 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) |
632 | { | 632 | { |
633 | int ret = -EINVAL; | 633 | int ret = -EINVAL; |
634 | struct ieee80211_channel *chan; | 634 | struct ieee80211_channel *chan; |
635 | struct ieee80211_local *local = sdata->local; | 635 | struct ieee80211_local *local = sdata->local; |
636 | 636 | ||
637 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | 637 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); |
638 | 638 | ||
639 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | 639 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
640 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 640 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) | 641 | chan->flags & IEEE80211_CHAN_NO_IBSS) |
642 | return ret; | 642 | return ret; |
643 | local->oper_channel = chan; | 643 | local->oper_channel = chan; |
644 | 644 | ||
645 | if (local->sw_scanning || local->hw_scanning) | 645 | if (local->sw_scanning || local->hw_scanning) |
646 | ret = 0; | 646 | ret = 0; |
647 | else | 647 | else |
648 | ret = ieee80211_hw_config( | 648 | ret = ieee80211_hw_config( |
649 | local, IEEE80211_CONF_CHANGE_CHANNEL); | 649 | local, IEEE80211_CONF_CHANGE_CHANNEL); |
650 | |||
651 | rate_control_clear(local); | ||
652 | } | 650 | } |
653 | 651 | ||
654 | return ret; | 652 | return ret; |
655 | } | 653 | } |
656 | 654 | ||
657 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | 655 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, |
658 | enum ieee80211_band band) | 656 | enum ieee80211_band band) |
659 | { | 657 | { |
660 | struct ieee80211_supported_band *sband; | 658 | struct ieee80211_supported_band *sband; |
661 | struct ieee80211_rate *bitrates; | 659 | struct ieee80211_rate *bitrates; |
662 | u64 mandatory_rates; | 660 | u64 mandatory_rates; |
663 | enum ieee80211_rate_flags mandatory_flag; | 661 | enum ieee80211_rate_flags mandatory_flag; |
664 | int i; | 662 | int i; |
665 | 663 | ||
666 | sband = local->hw.wiphy->bands[band]; | 664 | sband = local->hw.wiphy->bands[band]; |
667 | if (!sband) { | 665 | if (!sband) { |
668 | WARN_ON(1); | 666 | WARN_ON(1); |
669 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 667 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
670 | } | 668 | } |
671 | 669 | ||
672 | if (band == IEEE80211_BAND_2GHZ) | 670 | if (band == IEEE80211_BAND_2GHZ) |
673 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | 671 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; |
674 | else | 672 | else |
675 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | 673 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; |
676 | 674 | ||
677 | bitrates = sband->bitrates; | 675 | bitrates = sband->bitrates; |
678 | mandatory_rates = 0; | 676 | mandatory_rates = 0; |
679 | for (i = 0; i < sband->n_bitrates; i++) | 677 | for (i = 0; i < sband->n_bitrates; i++) |
680 | if (bitrates[i].flags & mandatory_flag) | 678 | if (bitrates[i].flags & mandatory_flag) |
681 | mandatory_rates |= BIT(i); | 679 | mandatory_rates |= BIT(i); |
682 | return mandatory_rates; | 680 | return mandatory_rates; |
683 | } | 681 | } |
684 | 682 |