diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac/rate.h')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/rate.h | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/rate.h b/drivers/net/wireless/brcm80211/brcmsmac/rate.h new file mode 100644 index 000000000000..e7b9dc2f2731 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmsmac/rate.h | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _BRCM_RATE_H_ | ||
18 | #define _BRCM_RATE_H_ | ||
19 | |||
20 | #include "types.h" | ||
21 | #include "d11.h" | ||
22 | |||
23 | extern const u8 rate_info[]; | ||
24 | extern const struct brcms_c_rateset cck_ofdm_mimo_rates; | ||
25 | extern const struct brcms_c_rateset ofdm_mimo_rates; | ||
26 | extern const struct brcms_c_rateset cck_ofdm_rates; | ||
27 | extern const struct brcms_c_rateset ofdm_rates; | ||
28 | extern const struct brcms_c_rateset cck_rates; | ||
29 | extern const struct brcms_c_rateset gphy_legacy_rates; | ||
30 | extern const struct brcms_c_rateset rate_limit_1_2; | ||
31 | |||
32 | struct brcms_mcs_info { | ||
33 | /* phy rate in kbps [20Mhz] */ | ||
34 | u32 phy_rate_20; | ||
35 | /* phy rate in kbps [40Mhz] */ | ||
36 | u32 phy_rate_40; | ||
37 | /* phy rate in kbps [20Mhz] with SGI */ | ||
38 | u32 phy_rate_20_sgi; | ||
39 | /* phy rate in kbps [40Mhz] with SGI */ | ||
40 | u32 phy_rate_40_sgi; | ||
41 | /* phy ctl byte 3, code rate, modulation type, # of streams */ | ||
42 | u8 tx_phy_ctl3; | ||
43 | /* matching legacy ofdm rate in 500bkps */ | ||
44 | u8 leg_ofdm; | ||
45 | }; | ||
46 | |||
47 | #define BRCMS_MAXMCS 32 /* max valid mcs index */ | ||
48 | #define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ | ||
49 | extern const struct brcms_mcs_info mcs_table[]; | ||
50 | |||
51 | #define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ | ||
52 | #define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ | ||
53 | |||
54 | /* returns num tx streams - 1 */ | ||
55 | static inline u8 mcs_2_txstreams(u8 mcs) | ||
56 | { | ||
57 | return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; | ||
58 | } | ||
59 | |||
60 | static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) | ||
61 | { | ||
62 | if (sgi) { | ||
63 | if (is40) | ||
64 | return mcs_table[mcs].phy_rate_40_sgi; | ||
65 | return mcs_table[mcs].phy_rate_20_sgi; | ||
66 | } | ||
67 | if (is40) | ||
68 | return mcs_table[mcs].phy_rate_40; | ||
69 | |||
70 | return mcs_table[mcs].phy_rate_20; | ||
71 | } | ||
72 | |||
73 | /* Macro to use the rate_info table */ | ||
74 | #define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ | ||
75 | |||
76 | /* | ||
77 | * rate spec : holds rate and mode specific information required to generate a | ||
78 | * tx frame. Legacy CCK and OFDM information is held in the same manner as was | ||
79 | * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO | ||
80 | * specific information | ||
81 | */ | ||
82 | |||
83 | /* rate spec bit fields */ | ||
84 | |||
85 | /* Either 500Kbps units or MIMO MCS idx */ | ||
86 | #define RSPEC_RATE_MASK 0x0000007F | ||
87 | /* mimo MCS is stored in RSPEC_RATE_MASK */ | ||
88 | #define RSPEC_MIMORATE 0x08000000 | ||
89 | /* mimo bw mask */ | ||
90 | #define RSPEC_BW_MASK 0x00000700 | ||
91 | /* mimo bw shift */ | ||
92 | #define RSPEC_BW_SHIFT 8 | ||
93 | /* mimo Space/Time/Frequency mode mask */ | ||
94 | #define RSPEC_STF_MASK 0x00003800 | ||
95 | /* mimo Space/Time/Frequency mode shift */ | ||
96 | #define RSPEC_STF_SHIFT 11 | ||
97 | /* mimo coding type mask */ | ||
98 | #define RSPEC_CT_MASK 0x0000C000 | ||
99 | /* mimo coding type shift */ | ||
100 | #define RSPEC_CT_SHIFT 14 | ||
101 | /* mimo num STC streams per PLCP defn. */ | ||
102 | #define RSPEC_STC_MASK 0x00300000 | ||
103 | /* mimo num STC streams per PLCP defn. */ | ||
104 | #define RSPEC_STC_SHIFT 20 | ||
105 | /* mimo bit indicates adv coding in use */ | ||
106 | #define RSPEC_LDPC_CODING 0x00400000 | ||
107 | /* mimo bit indicates short GI in use */ | ||
108 | #define RSPEC_SHORT_GI 0x00800000 | ||
109 | /* bit indicates override both rate & mode */ | ||
110 | #define RSPEC_OVERRIDE 0x80000000 | ||
111 | /* bit indicates override rate only */ | ||
112 | #define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 | ||
113 | |||
114 | static inline bool rspec_active(u32 rspec) | ||
115 | { | ||
116 | return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); | ||
117 | } | ||
118 | |||
119 | static inline u8 rspec_phytxbyte2(u32 rspec) | ||
120 | { | ||
121 | return (rspec & 0xff00) >> 8; | ||
122 | } | ||
123 | |||
124 | static inline u32 rspec_get_bw(u32 rspec) | ||
125 | { | ||
126 | return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; | ||
127 | } | ||
128 | |||
129 | static inline bool rspec_issgi(u32 rspec) | ||
130 | { | ||
131 | return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; | ||
132 | } | ||
133 | |||
134 | static inline bool rspec_is40mhz(u32 rspec) | ||
135 | { | ||
136 | u32 bw = rspec_get_bw(rspec); | ||
137 | |||
138 | return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; | ||
139 | } | ||
140 | |||
141 | static inline uint rspec2rate(u32 rspec) | ||
142 | { | ||
143 | if (rspec & RSPEC_MIMORATE) | ||
144 | return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), | ||
145 | rspec_issgi(rspec)); | ||
146 | return rspec & RSPEC_RATE_MASK; | ||
147 | } | ||
148 | |||
149 | static inline u8 rspec_mimoplcp3(u32 rspec) | ||
150 | { | ||
151 | return (rspec & 0xf00000) >> 16; | ||
152 | } | ||
153 | |||
154 | static inline bool plcp3_issgi(u8 plcp) | ||
155 | { | ||
156 | return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; | ||
157 | } | ||
158 | |||
159 | static inline uint rspec_stc(u32 rspec) | ||
160 | { | ||
161 | return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; | ||
162 | } | ||
163 | |||
164 | static inline uint rspec_stf(u32 rspec) | ||
165 | { | ||
166 | return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; | ||
167 | } | ||
168 | |||
169 | static inline bool is_mcs_rate(u32 ratespec) | ||
170 | { | ||
171 | return (ratespec & RSPEC_MIMORATE) != 0; | ||
172 | } | ||
173 | |||
174 | static inline bool is_ofdm_rate(u32 ratespec) | ||
175 | { | ||
176 | return !is_mcs_rate(ratespec) && | ||
177 | (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); | ||
178 | } | ||
179 | |||
180 | static inline bool is_cck_rate(u32 ratespec) | ||
181 | { | ||
182 | u32 rate = (ratespec & BRCMS_RATE_MASK); | ||
183 | |||
184 | return !is_mcs_rate(ratespec) && ( | ||
185 | rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || | ||
186 | rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); | ||
187 | } | ||
188 | |||
189 | static inline bool is_single_stream(u8 mcs) | ||
190 | { | ||
191 | return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; | ||
192 | } | ||
193 | |||
194 | static inline u8 cck_rspec(u8 cck) | ||
195 | { | ||
196 | return cck & RSPEC_RATE_MASK; | ||
197 | } | ||
198 | |||
199 | /* Convert encoded rate value in plcp header to numerical rates in 500 KHz | ||
200 | * increments */ | ||
201 | extern const u8 ofdm_rate_lookup[]; | ||
202 | |||
203 | static inline u8 ofdm_phy2mac_rate(u8 rlpt) | ||
204 | { | ||
205 | return ofdm_rate_lookup[rlpt & 0x7]; | ||
206 | } | ||
207 | |||
208 | static inline u8 cck_phy2mac_rate(u8 signal) | ||
209 | { | ||
210 | return signal/5; | ||
211 | } | ||
212 | |||
213 | /* Rates specified in brcms_c_rateset_filter() */ | ||
214 | #define BRCMS_RATES_CCK_OFDM 0 | ||
215 | #define BRCMS_RATES_CCK 1 | ||
216 | #define BRCMS_RATES_OFDM 2 | ||
217 | |||
218 | /* sanitize, and sort a rateset with the basic bit(s) preserved, validate | ||
219 | * rateset */ | ||
220 | extern bool | ||
221 | brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, | ||
222 | const struct brcms_c_rateset *hw_rs, | ||
223 | bool check_brate, u8 txstreams); | ||
224 | /* copy rateset src to dst as-is (no masking or sorting) */ | ||
225 | extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, | ||
226 | struct brcms_c_rateset *dst); | ||
227 | |||
228 | /* would be nice to have these documented ... */ | ||
229 | extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); | ||
230 | |||
231 | extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, | ||
232 | struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, | ||
233 | bool mcsallow); | ||
234 | |||
235 | extern void | ||
236 | brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, | ||
237 | const struct brcms_c_rateset *rs_hw, uint phy_type, | ||
238 | int bandtype, bool cck_only, uint rate_mask, | ||
239 | bool mcsallow, u8 bw, u8 txstreams); | ||
240 | |||
241 | extern s16 brcms_c_rate_legacy_phyctl(uint rate); | ||
242 | |||
243 | extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); | ||
244 | extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); | ||
245 | extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, | ||
246 | u8 txstreams); | ||
247 | extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, | ||
248 | u8 bw); | ||
249 | |||
250 | #endif /* _BRCM_RATE_H_ */ | ||