~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/wlc_rate.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <linux/kernel.h>
 
17
#include <linux/module.h>
 
18
 
 
19
#include <proto/802.11.h>
 
20
#include <bcmdefs.h>
 
21
#include <bcmutils.h>
 
22
#include <siutils.h>
 
23
#include <wlioctl.h>
 
24
#include <sbhnddma.h>
 
25
 
 
26
#include "wlc_types.h"
 
27
#include "d11.h"
 
28
#include "wl_dbg.h"
 
29
#include "wlc_cfg.h"
 
30
#include "wlc_scb.h"
 
31
#include "wlc_pub.h"
 
32
#include "wlc_rate.h"
 
33
 
 
34
/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
 
35
const u8 rate_info[WLC_MAXRATE + 1] = {
 
36
        /*  0     1     2     3     4     5     6     7     8     9 */
 
37
/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
 
38
/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
 
39
/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
 
40
/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
 
41
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
 
42
/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
43
/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
44
/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
45
/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
46
/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
 
47
/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
 
48
};
 
49
 
 
50
/* rates are in units of Kbps */
 
51
const mcs_info_t mcs_table[MCS_TABLE_SIZE] = {
 
52
        /* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
 
53
        {6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
 
54
         WLC_RATE_6M},
 
55
        /* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
 
56
        {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
 
57
         WLC_RATE_12M},
 
58
        /* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
 
59
        {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
 
60
         WLC_RATE_18M},
 
61
        /* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
 
62
        {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
 
63
         WLC_RATE_24M},
 
64
        /* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
 
65
        {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
 
66
         WLC_RATE_36M},
 
67
        /* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
 
68
        {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
 
69
         WLC_RATE_48M},
 
70
        /* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
 
71
        {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
 
72
         WLC_RATE_54M},
 
73
        /* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
 
74
        {65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
 
75
         WLC_RATE_54M},
 
76
        /* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
 
77
        {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
 
78
         WLC_RATE_6M},
 
79
        /* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
 
80
        {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
 
81
         WLC_RATE_12M},
 
82
        /* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
 
83
        {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
 
84
         WLC_RATE_18M},
 
85
        /* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
 
86
        {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
 
87
         WLC_RATE_24M},
 
88
        /* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
 
89
        {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
 
90
         WLC_RATE_36M},
 
91
        /* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
 
92
        {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
 
93
         WLC_RATE_48M},
 
94
        /* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
 
95
        {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
 
96
         WLC_RATE_54M},
 
97
        /* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
 
98
        {130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
 
99
         WLC_RATE_54M},
 
100
        /* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
 
101
        {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
 
102
         WLC_RATE_6M},
 
103
        /* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
 
104
        {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
 
105
         WLC_RATE_12M},
 
106
        /* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
 
107
        {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
 
108
         WLC_RATE_18M},
 
109
        /* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
 
110
        {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
 
111
         WLC_RATE_24M},
 
112
        /* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
 
113
        {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
 
114
         WLC_RATE_36M},
 
115
        /* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
 
116
        {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
 
117
         WLC_RATE_48M},
 
118
        /* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
 
119
        {175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
 
120
         WLC_RATE_54M},
 
121
        /* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
 
122
        {195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
 
123
         WLC_RATE_54M},
 
124
        /* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
 
125
        {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
 
126
         WLC_RATE_6M},
 
127
        /* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
 
128
        {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
 
129
         WLC_RATE_12M},
 
130
        /* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
 
131
        {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
 
132
         WLC_RATE_18M},
 
133
        /* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
 
134
        {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
 
135
         WLC_RATE_24M},
 
136
        /* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
 
137
        {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
 
138
         WLC_RATE_36M},
 
139
        /* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
 
140
        {208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
 
141
         WLC_RATE_48M},
 
142
        /* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
 
143
        {234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
 
144
         WLC_RATE_54M},
 
145
        /* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
 
146
        {260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
 
147
         WLC_RATE_54M},
 
148
        /* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
 
149
        {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, WLC_RATE_6M},
 
150
};
 
151
 
 
152
/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
 
153
 *   Number of spatial streams: always 1
 
154
 *   other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
 
155
 */
 
156
typedef struct legacy_phycfg {
 
157
        u32 rate_ofdm;  /* ofdm mac rate */
 
158
        u8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */
 
159
} legacy_phycfg_t;
 
160
 
 
161
#define LEGACY_PHYCFG_TABLE_SIZE        12      /* Number of legacy_rate_cfg entries in the table */
 
162
 
 
163
/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
 
164
/* Eventually MIMOPHY would also be converted to this format */
 
165
/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
 
166
static const legacy_phycfg_t legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
 
167
        {WLC_RATE_1M, 0x00},    /* CCK  1Mbps,  data rate  0 */
 
168
        {WLC_RATE_2M, 0x08},    /* CCK  2Mbps,  data rate  1 */
 
169
        {WLC_RATE_5M5, 0x10},   /* CCK  5.5Mbps,  data rate  2 */
 
170
        {WLC_RATE_11M, 0x18},   /* CCK  11Mbps,  data rate   3 */
 
171
        {WLC_RATE_6M, 0x00},    /* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
 
172
        {WLC_RATE_9M, 0x02},    /* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
 
173
        {WLC_RATE_12M, 0x08},   /* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
 
174
        {WLC_RATE_18M, 0x0A},   /* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
 
175
        {WLC_RATE_24M, 0x10},   /* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
 
176
        {WLC_RATE_36M, 0x12},   /* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
 
177
        {WLC_RATE_48M, 0x19},   /* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
 
178
        {WLC_RATE_54M, 0x1A},   /* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
 
179
};
 
180
 
 
181
/* Hardware rates (also encodes default basic rates) */
 
182
 
 
183
const wlc_rateset_t cck_ofdm_mimo_rates = {
 
184
        12,
 
185
        {                       /*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
 
186
         0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
 
187
         0x6c},
 
188
        0x00,
 
189
        {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
190
         0x00, 0x00, 0x00, 0x00}
 
191
};
 
192
 
 
193
const wlc_rateset_t ofdm_mimo_rates = {
 
194
        8,
 
195
        {                       /*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
 
196
         0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
 
197
        0x00,
 
198
        {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
199
         0x00, 0x00, 0x00, 0x00}
 
200
};
 
201
 
 
202
/* Default ratesets that include MCS32 for 40BW channels */
 
203
const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
 
204
        12,
 
205
        {                       /*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
 
206
         0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
 
207
         0x6c},
 
208
        0x00,
 
209
        {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
210
         0x00, 0x00, 0x00, 0x00}
 
211
};
 
212
 
 
213
const wlc_rateset_t ofdm_40bw_mimo_rates = {
 
214
        8,
 
215
        {                       /*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
 
216
         0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
 
217
        0x00,
 
218
        {0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
219
         0x00, 0x00, 0x00, 0x00}
 
220
};
 
221
 
 
222
const wlc_rateset_t cck_ofdm_rates = {
 
223
        12,
 
224
        {                       /*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
 
225
         0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
 
226
         0x6c},
 
227
        0x00,
 
228
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
229
         0x00, 0x00, 0x00, 0x00}
 
230
};
 
231
 
 
232
const wlc_rateset_t gphy_legacy_rates = {
 
233
        4,
 
234
        {                       /*    1b,   2b,   5.5b,  11b Mbps */
 
235
         0x82, 0x84, 0x8b, 0x96},
 
236
        0x00,
 
237
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
238
         0x00, 0x00, 0x00, 0x00}
 
239
};
 
240
 
 
241
const wlc_rateset_t ofdm_rates = {
 
242
        8,
 
243
        {                       /*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
 
244
         0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
 
245
        0x00,
 
246
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
247
         0x00, 0x00, 0x00, 0x00}
 
248
};
 
249
 
 
250
const wlc_rateset_t cck_rates = {
 
251
        4,
 
252
        {                       /*    1b,   2b,   5.5,  11 Mbps */
 
253
         0x82, 0x84, 0x0b, 0x16},
 
254
        0x00,
 
255
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
256
         0x00, 0x00, 0x00, 0x00}
 
257
};
 
258
 
 
259
static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate);
 
260
 
 
261
/* check if rateset is valid.
 
262
 * if check_brate is true, rateset without a basic rate is considered NOT valid.
 
263
 */
 
264
static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate)
 
265
{
 
266
        uint idx;
 
267
 
 
268
        if (!rs->count)
 
269
                return false;
 
270
 
 
271
        if (!check_brate)
 
272
                return true;
 
273
 
 
274
        /* error if no basic rates */
 
275
        for (idx = 0; idx < rs->count; idx++) {
 
276
                if (rs->rates[idx] & WLC_RATE_FLAG)
 
277
                        return true;
 
278
        }
 
279
        return false;
 
280
}
 
281
 
 
282
void wlc_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
 
283
{
 
284
        int i;
 
285
        for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
 
286
                rs->mcs[i] = 0;
 
287
}
 
288
 
 
289
/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
 
290
 * and check if resulting rateset is valid.
 
291
*/
 
292
bool
 
293
wlc_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
 
294
                                   const wlc_rateset_t *hw_rs,
 
295
                                   bool check_brate, u8 txstreams)
 
296
{
 
297
        u8 rateset[WLC_MAXRATE + 1];
 
298
        u8 r;
 
299
        uint count;
 
300
        uint i;
 
301
 
 
302
        memset(rateset, 0, sizeof(rateset));
 
303
        count = rs->count;
 
304
 
 
305
        for (i = 0; i < count; i++) {
 
306
                /* mask off "basic rate" bit, WLC_RATE_FLAG */
 
307
                r = (int)rs->rates[i] & RATE_MASK;
 
308
                if ((r > WLC_MAXRATE) || (rate_info[r] == 0)) {
 
309
                        continue;
 
310
                }
 
311
                rateset[r] = rs->rates[i];      /* preserve basic bit! */
 
312
        }
 
313
 
 
314
        /* fill out the rates in order, looking at only supported rates */
 
315
        count = 0;
 
316
        for (i = 0; i < hw_rs->count; i++) {
 
317
                r = hw_rs->rates[i] & RATE_MASK;
 
318
                ASSERT(r <= WLC_MAXRATE);
 
319
                if (rateset[r])
 
320
                        rs->rates[count++] = rateset[r];
 
321
        }
 
322
 
 
323
        rs->count = count;
 
324
 
 
325
        /* only set the mcs rate bit if the equivalent hw mcs bit is set */
 
326
        for (i = 0; i < MCSSET_LEN; i++)
 
327
                rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
 
328
 
 
329
        if (wlc_rateset_valid(rs, check_brate))
 
330
                return true;
 
331
        else
 
332
                return false;
 
333
}
 
334
 
 
335
/* calculate the rate of a rx'd frame and return it as a ratespec */
 
336
ratespec_t BCMFASTPATH wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp)
 
337
{
 
338
        int phy_type;
 
339
        ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
 
340
 
 
341
        phy_type =
 
342
            ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
 
343
 
 
344
        if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
 
345
            (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
 
346
                switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
 
347
                case PRXS0_CCK:
 
348
                        rspec =
 
349
                            CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
 
350
                        break;
 
351
                case PRXS0_OFDM:
 
352
                        rspec =
 
353
                            OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->
 
354
                                              rlpt[0]);
 
355
                        break;
 
356
                case PRXS0_PREN:
 
357
                        rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
 
358
                        if (plcp[0] & MIMO_PLCP_40MHZ) {
 
359
                                /* indicate rspec is for 40 MHz mode */
 
360
                                rspec &= ~RSPEC_BW_MASK;
 
361
                                rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
 
362
                        }
 
363
                        break;
 
364
                case PRXS0_STDN:
 
365
                        /* fallthru */
 
366
                default:
 
367
                        /* not supported */
 
368
                        ASSERT(0);
 
369
                        break;
 
370
                }
 
371
                if (PLCP3_ISSGI(plcp[3]))
 
372
                        rspec |= RSPEC_SHORT_GI;
 
373
        } else
 
374
            if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
 
375
                rspec = OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->rlpt[0]);
 
376
        else
 
377
                rspec = CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
 
378
 
 
379
        return rspec;
 
380
}
 
381
 
 
382
/* copy rateset src to dst as-is (no masking or sorting) */
 
383
void wlc_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
 
384
{
 
385
        memcpy(dst, src, sizeof(wlc_rateset_t));
 
386
}
 
387
 
 
388
/*
 
389
 * Copy and selectively filter one rateset to another.
 
390
 * 'basic_only' means only copy basic rates.
 
391
 * 'rates' indicates cck (11b) and ofdm rates combinations.
 
392
 *    - 0: cck and ofdm
 
393
 *    - 1: cck only
 
394
 *    - 2: ofdm only
 
395
 * 'xmask' is the copy mask (typically 0x7f or 0xff).
 
396
 */
 
397
void
 
398
wlc_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
 
399
                   u8 rates, uint xmask, bool mcsallow)
 
400
{
 
401
        uint i;
 
402
        uint r;
 
403
        uint count;
 
404
 
 
405
        count = 0;
 
406
        for (i = 0; i < src->count; i++) {
 
407
                r = src->rates[i];
 
408
                if (basic_only && !(r & WLC_RATE_FLAG))
 
409
                        continue;
 
410
                if ((rates == WLC_RATES_CCK) && IS_OFDM((r & RATE_MASK)))
 
411
                        continue;
 
412
                if ((rates == WLC_RATES_OFDM) && IS_CCK((r & RATE_MASK)))
 
413
                        continue;
 
414
                dst->rates[count++] = r & xmask;
 
415
        }
 
416
        dst->count = count;
 
417
        dst->htphy_membership = src->htphy_membership;
 
418
 
 
419
        if (mcsallow && rates != WLC_RATES_CCK)
 
420
                memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
 
421
        else
 
422
                wlc_rateset_mcs_clear(dst);
 
423
}
 
424
 
 
425
/* select rateset for a given phy_type and bandtype and filter it, sort it
 
426
 * and fill rs_tgt with result
 
427
 */
 
428
void
 
429
wlc_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
 
430
                    uint phy_type, int bandtype, bool cck_only, uint rate_mask,
 
431
                    bool mcsallow, u8 bw, u8 txstreams)
 
432
{
 
433
        const wlc_rateset_t *rs_dflt;
 
434
        wlc_rateset_t rs_sel;
 
435
        if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
 
436
            (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
 
437
            (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
 
438
            (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
 
439
                if (BAND_5G(bandtype)) {
 
440
                        rs_dflt = (bw == WLC_20_MHZ ?
 
441
                                   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
 
442
                } else {
 
443
                        rs_dflt = (bw == WLC_20_MHZ ?
 
444
                                   &cck_ofdm_mimo_rates :
 
445
                                   &cck_ofdm_40bw_mimo_rates);
 
446
                }
 
447
        } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
 
448
                rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
 
449
        } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
 
450
                rs_dflt = &ofdm_rates;
 
451
        } else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
 
452
                rs_dflt = &cck_ofdm_rates;
 
453
        } else {
 
454
                ASSERT(0);      /* should not happen */
 
455
                rs_dflt = &cck_rates;   /* force cck */
 
456
        }
 
457
 
 
458
        /* if hw rateset is not supplied, assign selected rateset to it */
 
459
        if (!rs_hw)
 
460
                rs_hw = rs_dflt;
 
461
 
 
462
        wlc_rateset_copy(rs_dflt, &rs_sel);
 
463
        wlc_rateset_mcs_upd(&rs_sel, txstreams);
 
464
        wlc_rateset_filter(&rs_sel, rs_tgt, false,
 
465
                           cck_only ? WLC_RATES_CCK : WLC_RATES_CCK_OFDM,
 
466
                           rate_mask, mcsallow);
 
467
        wlc_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
 
468
                                           mcsallow ? txstreams : 1);
 
469
}
 
470
 
 
471
s16 BCMFASTPATH wlc_rate_legacy_phyctl(uint rate)
 
472
{
 
473
        uint i;
 
474
        for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
 
475
                if (rate == legacy_phycfg_table[i].rate_ofdm)
 
476
                        return legacy_phycfg_table[i].tx_phy_ctl3;
 
477
 
 
478
        return -1;
 
479
}
 
480
 
 
481
void wlc_rateset_mcs_clear(wlc_rateset_t *rateset)
 
482
{
 
483
        uint i;
 
484
        for (i = 0; i < MCSSET_LEN; i++)
 
485
                rateset->mcs[i] = 0;
 
486
}
 
487
 
 
488
void wlc_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
 
489
{
 
490
        memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
 
491
        wlc_rateset_mcs_upd(rateset, txstreams);
 
492
}
 
493
 
 
494
/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
 
495
void wlc_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
 
496
{
 
497
        if (bw == WLC_40_MHZ)
 
498
                setbit(rateset->mcs, 32);
 
499
        else
 
500
                clrbit(rateset->mcs, 32);
 
501
}