~ubuntu-branches/ubuntu/quantal/linux-lowlatency/quantal-proposed

« back to all changes in this revision

Viewing changes to drivers/net/wireless/ti/wlcore/init.c

  • Committer: Package Import Robot
  • Author(s): Andy Whitcroft, Andy Whitcroft
  • Date: 2012-06-21 09:16:38 UTC
  • Revision ID: package-import@ubuntu.com-20120621091638-gubhv4nox8xez1ct
Tags: 3.5.0-1.1
[ Andy Whitcroft]

* Rebuild lowlatency against Ubuntu-3.5.0-1.1
* All new configuration system to allow configuration deltas to be
  exposed via debian.lowlatency/config-delta

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of wl1271
 
3
 *
 
4
 * Copyright (C) 2009 Nokia Corporation
 
5
 *
 
6
 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License
 
10
 * version 2 as published by the Free Software Foundation.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 
20
 * 02110-1301 USA
 
21
 *
 
22
 */
 
23
 
 
24
#include <linux/kernel.h>
 
25
#include <linux/module.h>
 
26
#include <linux/slab.h>
 
27
 
 
28
#include "debug.h"
 
29
#include "init.h"
 
30
#include "wl12xx_80211.h"
 
31
#include "acx.h"
 
32
#include "cmd.h"
 
33
#include "tx.h"
 
34
#include "io.h"
 
35
#include "hw_ops.h"
 
36
 
 
37
int wl1271_init_templates_config(struct wl1271 *wl)
 
38
{
 
39
        int ret, i;
 
40
        size_t max_size;
 
41
 
 
42
        /* send empty templates for fw memory reservation */
 
43
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
44
                                      CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
 
45
                                      WL1271_CMD_TEMPL_MAX_SIZE,
 
46
                                      0, WL1271_RATE_AUTOMATIC);
 
47
        if (ret < 0)
 
48
                return ret;
 
49
 
 
50
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
51
                                      CMD_TEMPL_CFG_PROBE_REQ_5,
 
52
                                      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
 
53
                                      WL1271_RATE_AUTOMATIC);
 
54
        if (ret < 0)
 
55
                return ret;
 
56
 
 
57
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
58
                                      CMD_TEMPL_NULL_DATA, NULL,
 
59
                                      sizeof(struct wl12xx_null_data_template),
 
60
                                      0, WL1271_RATE_AUTOMATIC);
 
61
        if (ret < 0)
 
62
                return ret;
 
63
 
 
64
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
65
                                      CMD_TEMPL_PS_POLL, NULL,
 
66
                                      sizeof(struct wl12xx_ps_poll_template),
 
67
                                      0, WL1271_RATE_AUTOMATIC);
 
68
        if (ret < 0)
 
69
                return ret;
 
70
 
 
71
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
72
                                      CMD_TEMPL_QOS_NULL_DATA, NULL,
 
73
                                      sizeof
 
74
                                      (struct ieee80211_qos_hdr),
 
75
                                      0, WL1271_RATE_AUTOMATIC);
 
76
        if (ret < 0)
 
77
                return ret;
 
78
 
 
79
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
80
                                      CMD_TEMPL_PROBE_RESPONSE, NULL,
 
81
                                      WL1271_CMD_TEMPL_DFLT_SIZE,
 
82
                                      0, WL1271_RATE_AUTOMATIC);
 
83
        if (ret < 0)
 
84
                return ret;
 
85
 
 
86
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
87
                                      CMD_TEMPL_BEACON, NULL,
 
88
                                      WL1271_CMD_TEMPL_DFLT_SIZE,
 
89
                                      0, WL1271_RATE_AUTOMATIC);
 
90
        if (ret < 0)
 
91
                return ret;
 
92
 
 
93
        max_size = sizeof(struct wl12xx_arp_rsp_template) +
 
94
                   WL1271_EXTRA_SPACE_MAX;
 
95
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
96
                                      CMD_TEMPL_ARP_RSP, NULL,
 
97
                                      max_size,
 
98
                                      0, WL1271_RATE_AUTOMATIC);
 
99
        if (ret < 0)
 
100
                return ret;
 
101
 
 
102
        /*
 
103
         * Put very large empty placeholders for all templates. These
 
104
         * reserve memory for later.
 
105
         */
 
106
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
107
                                      CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
 
108
                                      WL1271_CMD_TEMPL_MAX_SIZE,
 
109
                                      0, WL1271_RATE_AUTOMATIC);
 
110
        if (ret < 0)
 
111
                return ret;
 
112
 
 
113
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
114
                                      CMD_TEMPL_AP_BEACON, NULL,
 
115
                                      WL1271_CMD_TEMPL_MAX_SIZE,
 
116
                                      0, WL1271_RATE_AUTOMATIC);
 
117
        if (ret < 0)
 
118
                return ret;
 
119
 
 
120
        ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
121
                                      CMD_TEMPL_DEAUTH_AP, NULL,
 
122
                                      sizeof
 
123
                                      (struct wl12xx_disconn_template),
 
124
                                      0, WL1271_RATE_AUTOMATIC);
 
125
        if (ret < 0)
 
126
                return ret;
 
127
 
 
128
        for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
 
129
                ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
 
130
                                              CMD_TEMPL_KLV, NULL,
 
131
                                              sizeof(struct ieee80211_qos_hdr),
 
132
                                              i, WL1271_RATE_AUTOMATIC);
 
133
                if (ret < 0)
 
134
                        return ret;
 
135
        }
 
136
 
 
137
        return 0;
 
138
}
 
139
 
 
140
static int wl1271_ap_init_deauth_template(struct wl1271 *wl,
 
141
                                          struct wl12xx_vif *wlvif)
 
142
{
 
143
        struct wl12xx_disconn_template *tmpl;
 
144
        int ret;
 
145
        u32 rate;
 
146
 
 
147
        tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
 
148
        if (!tmpl) {
 
149
                ret = -ENOMEM;
 
150
                goto out;
 
151
        }
 
152
 
 
153
        tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 
154
                                             IEEE80211_STYPE_DEAUTH);
 
155
 
 
156
        rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
 
157
        ret = wl1271_cmd_template_set(wl, wlvif->role_id,
 
158
                                      CMD_TEMPL_DEAUTH_AP,
 
159
                                      tmpl, sizeof(*tmpl), 0, rate);
 
160
 
 
161
out:
 
162
        kfree(tmpl);
 
163
        return ret;
 
164
}
 
165
 
 
166
static int wl1271_ap_init_null_template(struct wl1271 *wl,
 
167
                                        struct ieee80211_vif *vif)
 
168
{
 
169
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 
170
        struct ieee80211_hdr_3addr *nullfunc;
 
171
        int ret;
 
172
        u32 rate;
 
173
 
 
174
        nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
 
175
        if (!nullfunc) {
 
176
                ret = -ENOMEM;
 
177
                goto out;
 
178
        }
 
179
 
 
180
        nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 
181
                                              IEEE80211_STYPE_NULLFUNC |
 
182
                                              IEEE80211_FCTL_FROMDS);
 
183
 
 
184
        /* nullfunc->addr1 is filled by FW */
 
185
 
 
186
        memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
 
187
        memcpy(nullfunc->addr3, vif->addr, ETH_ALEN);
 
188
 
 
189
        rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
 
190
        ret = wl1271_cmd_template_set(wl, wlvif->role_id,
 
191
                                      CMD_TEMPL_NULL_DATA, nullfunc,
 
192
                                      sizeof(*nullfunc), 0, rate);
 
193
 
 
194
out:
 
195
        kfree(nullfunc);
 
196
        return ret;
 
197
}
 
198
 
 
199
static int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
 
200
                                            struct ieee80211_vif *vif)
 
201
{
 
202
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 
203
        struct ieee80211_qos_hdr *qosnull;
 
204
        int ret;
 
205
        u32 rate;
 
206
 
 
207
        qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
 
208
        if (!qosnull) {
 
209
                ret = -ENOMEM;
 
210
                goto out;
 
211
        }
 
212
 
 
213
        qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 
214
                                             IEEE80211_STYPE_QOS_NULLFUNC |
 
215
                                             IEEE80211_FCTL_FROMDS);
 
216
 
 
217
        /* qosnull->addr1 is filled by FW */
 
218
 
 
219
        memcpy(qosnull->addr2, vif->addr, ETH_ALEN);
 
220
        memcpy(qosnull->addr3, vif->addr, ETH_ALEN);
 
221
 
 
222
        rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
 
223
        ret = wl1271_cmd_template_set(wl, wlvif->role_id,
 
224
                                      CMD_TEMPL_QOS_NULL_DATA, qosnull,
 
225
                                      sizeof(*qosnull), 0, rate);
 
226
 
 
227
out:
 
228
        kfree(qosnull);
 
229
        return ret;
 
230
}
 
231
 
 
232
static int wl12xx_init_rx_config(struct wl1271 *wl)
 
233
{
 
234
        int ret;
 
235
 
 
236
        ret = wl1271_acx_rx_msdu_life_time(wl);
 
237
        if (ret < 0)
 
238
                return ret;
 
239
 
 
240
        return 0;
 
241
}
 
242
 
 
243
static int wl12xx_init_phy_vif_config(struct wl1271 *wl,
 
244
                                            struct wl12xx_vif *wlvif)
 
245
{
 
246
        int ret;
 
247
 
 
248
        ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME);
 
249
        if (ret < 0)
 
250
                return ret;
 
251
 
 
252
        ret = wl1271_acx_service_period_timeout(wl, wlvif);
 
253
        if (ret < 0)
 
254
                return ret;
 
255
 
 
256
        ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold);
 
257
        if (ret < 0)
 
258
                return ret;
 
259
 
 
260
        return 0;
 
261
}
 
262
 
 
263
static int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
 
264
                                         struct wl12xx_vif *wlvif)
 
265
{
 
266
        int ret;
 
267
 
 
268
        ret = wl1271_acx_beacon_filter_table(wl, wlvif);
 
269
        if (ret < 0)
 
270
                return ret;
 
271
 
 
272
        /* enable beacon filtering */
 
273
        ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
 
274
        if (ret < 0)
 
275
                return ret;
 
276
 
 
277
        return 0;
 
278
}
 
279
 
 
280
int wl1271_init_pta(struct wl1271 *wl)
 
281
{
 
282
        int ret;
 
283
 
 
284
        ret = wl12xx_acx_sg_cfg(wl);
 
285
        if (ret < 0)
 
286
                return ret;
 
287
 
 
288
        ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
 
289
        if (ret < 0)
 
290
                return ret;
 
291
 
 
292
        return 0;
 
293
}
 
294
 
 
295
int wl1271_init_energy_detection(struct wl1271 *wl)
 
296
{
 
297
        int ret;
 
298
 
 
299
        ret = wl1271_acx_cca_threshold(wl);
 
300
        if (ret < 0)
 
301
                return ret;
 
302
 
 
303
        return 0;
 
304
}
 
305
 
 
306
static int wl1271_init_beacon_broadcast(struct wl1271 *wl,
 
307
                                        struct wl12xx_vif *wlvif)
 
308
{
 
309
        int ret;
 
310
 
 
311
        ret = wl1271_acx_bcn_dtim_options(wl, wlvif);
 
312
        if (ret < 0)
 
313
                return ret;
 
314
 
 
315
        return 0;
 
316
}
 
317
 
 
318
static int wl12xx_init_fwlog(struct wl1271 *wl)
 
319
{
 
320
        int ret;
 
321
 
 
322
        if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED)
 
323
                return 0;
 
324
 
 
325
        ret = wl12xx_cmd_config_fwlog(wl);
 
326
        if (ret < 0)
 
327
                return ret;
 
328
 
 
329
        return 0;
 
330
}
 
331
 
 
332
/* generic sta initialization (non vif-specific) */
 
333
static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
334
{
 
335
        int ret;
 
336
 
 
337
        /* PS config */
 
338
        ret = wl12xx_acx_config_ps(wl, wlvif);
 
339
        if (ret < 0)
 
340
                return ret;
 
341
 
 
342
        /* FM WLAN coexistence */
 
343
        ret = wl1271_acx_fm_coex(wl);
 
344
        if (ret < 0)
 
345
                return ret;
 
346
 
 
347
        ret = wl1271_acx_sta_rate_policies(wl, wlvif);
 
348
        if (ret < 0)
 
349
                return ret;
 
350
 
 
351
        return 0;
 
352
}
 
353
 
 
354
static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl,
 
355
                                       struct ieee80211_vif *vif)
 
356
{
 
357
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 
358
        int ret, i;
 
359
 
 
360
        /* disable all keep-alive templates */
 
361
        for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
 
362
                ret = wl1271_acx_keep_alive_config(wl, wlvif, i,
 
363
                                                   ACX_KEEP_ALIVE_TPL_INVALID);
 
364
                if (ret < 0)
 
365
                        return ret;
 
366
        }
 
367
 
 
368
        /* disable the keep-alive feature */
 
369
        ret = wl1271_acx_keep_alive_mode(wl, wlvif, false);
 
370
        if (ret < 0)
 
371
                return ret;
 
372
 
 
373
        return 0;
 
374
}
 
375
 
 
376
/* generic ap initialization (non vif-specific) */
 
377
static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
378
{
 
379
        int ret;
 
380
 
 
381
        ret = wl1271_init_ap_rates(wl, wlvif);
 
382
        if (ret < 0)
 
383
                return ret;
 
384
 
 
385
        return 0;
 
386
}
 
387
 
 
388
int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif)
 
389
{
 
390
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 
391
        int ret;
 
392
 
 
393
        ret = wl1271_ap_init_deauth_template(wl, wlvif);
 
394
        if (ret < 0)
 
395
                return ret;
 
396
 
 
397
        ret = wl1271_ap_init_null_template(wl, vif);
 
398
        if (ret < 0)
 
399
                return ret;
 
400
 
 
401
        ret = wl1271_ap_init_qos_null_template(wl, vif);
 
402
        if (ret < 0)
 
403
                return ret;
 
404
 
 
405
        /*
 
406
         * when operating as AP we want to receive external beacons for
 
407
         * configuring ERP protection.
 
408
         */
 
409
        ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
 
410
        if (ret < 0)
 
411
                return ret;
 
412
 
 
413
        return 0;
 
414
}
 
415
 
 
416
static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl,
 
417
                                      struct ieee80211_vif *vif)
 
418
{
 
419
        return wl1271_ap_init_templates(wl, vif);
 
420
}
 
421
 
 
422
int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
423
{
 
424
        int i, ret;
 
425
        struct conf_tx_rate_class rc;
 
426
        u32 supported_rates;
 
427
 
 
428
        wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x",
 
429
                     wlvif->basic_rate_set);
 
430
 
 
431
        if (wlvif->basic_rate_set == 0)
 
432
                return -EINVAL;
 
433
 
 
434
        rc.enabled_rates = wlvif->basic_rate_set;
 
435
        rc.long_retry_limit = 10;
 
436
        rc.short_retry_limit = 10;
 
437
        rc.aflags = 0;
 
438
        ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx);
 
439
        if (ret < 0)
 
440
                return ret;
 
441
 
 
442
        /* use the min basic rate for AP broadcast/multicast */
 
443
        rc.enabled_rates = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
 
444
        rc.short_retry_limit = 10;
 
445
        rc.long_retry_limit = 10;
 
446
        rc.aflags = 0;
 
447
        ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx);
 
448
        if (ret < 0)
 
449
                return ret;
 
450
 
 
451
        /*
 
452
         * If the basic rates contain OFDM rates, use OFDM only
 
453
         * rates for unicast TX as well. Else use all supported rates.
 
454
         */
 
455
        if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES))
 
456
                supported_rates = CONF_TX_OFDM_RATES;
 
457
        else
 
458
                supported_rates = CONF_TX_AP_ENABLED_RATES;
 
459
 
 
460
        /* unconditionally enable HT rates */
 
461
        supported_rates |= CONF_TX_MCS_RATES;
 
462
 
 
463
        /* configure unicast TX rate classes */
 
464
        for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
 
465
                rc.enabled_rates = supported_rates;
 
466
                rc.short_retry_limit = 10;
 
467
                rc.long_retry_limit = 10;
 
468
                rc.aflags = 0;
 
469
                ret = wl1271_acx_ap_rate_policy(wl, &rc,
 
470
                                                wlvif->ap.ucast_rate_idx[i]);
 
471
                if (ret < 0)
 
472
                        return ret;
 
473
        }
 
474
 
 
475
        return 0;
 
476
}
 
477
 
 
478
static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
479
{
 
480
        /* Reset the BA RX indicators */
 
481
        wlvif->ba_allowed = true;
 
482
        wl->ba_rx_session_count = 0;
 
483
 
 
484
        /* BA is supported in STA/AP modes */
 
485
        if (wlvif->bss_type != BSS_TYPE_AP_BSS &&
 
486
            wlvif->bss_type != BSS_TYPE_STA_BSS) {
 
487
                wlvif->ba_support = false;
 
488
                return 0;
 
489
        }
 
490
 
 
491
        wlvif->ba_support = true;
 
492
 
 
493
        /* 802.11n initiator BA session setting */
 
494
        return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
 
495
}
 
496
 
 
497
/* vif-specifc initialization */
 
498
static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
499
{
 
500
        int ret;
 
501
 
 
502
        ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0);
 
503
        if (ret < 0)
 
504
                return ret;
 
505
 
 
506
        /* Initialize connection monitoring thresholds */
 
507
        ret = wl1271_acx_conn_monit_params(wl, wlvif, false);
 
508
        if (ret < 0)
 
509
                return ret;
 
510
 
 
511
        /* Beacon filtering */
 
512
        ret = wl1271_init_sta_beacon_filter(wl, wlvif);
 
513
        if (ret < 0)
 
514
                return ret;
 
515
 
 
516
        /* Beacons and broadcast settings */
 
517
        ret = wl1271_init_beacon_broadcast(wl, wlvif);
 
518
        if (ret < 0)
 
519
                return ret;
 
520
 
 
521
        /* Configure rssi/snr averaging weights */
 
522
        ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif);
 
523
        if (ret < 0)
 
524
                return ret;
 
525
 
 
526
        return 0;
 
527
}
 
528
 
 
529
/* vif-specific intialization */
 
530
static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
531
{
 
532
        int ret;
 
533
 
 
534
        ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
 
535
        if (ret < 0)
 
536
                return ret;
 
537
 
 
538
        /* initialize Tx power */
 
539
        ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level);
 
540
        if (ret < 0)
 
541
                return ret;
 
542
 
 
543
        return 0;
 
544
}
 
545
 
 
546
int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
 
547
{
 
548
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
 
549
        struct conf_tx_ac_category *conf_ac;
 
550
        struct conf_tx_tid *conf_tid;
 
551
        bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
 
552
        int ret, i;
 
553
 
 
554
        /*
 
555
         * consider all existing roles before configuring psm.
 
556
         * TODO: reconfigure on interface removal.
 
557
         */
 
558
        if (!wl->ap_count) {
 
559
                if (is_ap) {
 
560
                        /* Configure for power always on */
 
561
                        ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
 
562
                        if (ret < 0)
 
563
                                return ret;
 
564
                } else if (!wl->sta_count) {
 
565
                        if (wl->quirks & WLCORE_QUIRK_NO_ELP) {
 
566
                                /* Configure for power always on */
 
567
                                ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
 
568
                                if (ret < 0)
 
569
                                        return ret;
 
570
                        } else {
 
571
                                /* Configure for ELP power saving */
 
572
                                ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
 
573
                                if (ret < 0)
 
574
                                        return ret;
 
575
                        }
 
576
                }
 
577
        }
 
578
 
 
579
        /* Mode specific init */
 
580
        if (is_ap) {
 
581
                ret = wl1271_ap_hw_init(wl, wlvif);
 
582
                if (ret < 0)
 
583
                        return ret;
 
584
 
 
585
                ret = wl12xx_init_ap_role(wl, wlvif);
 
586
                if (ret < 0)
 
587
                        return ret;
 
588
        } else {
 
589
                ret = wl1271_sta_hw_init(wl, wlvif);
 
590
                if (ret < 0)
 
591
                        return ret;
 
592
 
 
593
                ret = wl12xx_init_sta_role(wl, wlvif);
 
594
                if (ret < 0)
 
595
                        return ret;
 
596
        }
 
597
 
 
598
        wl12xx_init_phy_vif_config(wl, wlvif);
 
599
 
 
600
        /* Default TID/AC configuration */
 
601
        BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
 
602
        for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
 
603
                conf_ac = &wl->conf.tx.ac_conf[i];
 
604
                ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac,
 
605
                                        conf_ac->cw_min, conf_ac->cw_max,
 
606
                                        conf_ac->aifsn, conf_ac->tx_op_limit);
 
607
                if (ret < 0)
 
608
                        return ret;
 
609
 
 
610
                conf_tid = &wl->conf.tx.tid_conf[i];
 
611
                ret = wl1271_acx_tid_cfg(wl, wlvif,
 
612
                                         conf_tid->queue_id,
 
613
                                         conf_tid->channel_type,
 
614
                                         conf_tid->tsid,
 
615
                                         conf_tid->ps_scheme,
 
616
                                         conf_tid->ack_policy,
 
617
                                         conf_tid->apsd_conf[0],
 
618
                                         conf_tid->apsd_conf[1]);
 
619
                if (ret < 0)
 
620
                        return ret;
 
621
        }
 
622
 
 
623
        /* Configure HW encryption */
 
624
        ret = wl1271_acx_feature_cfg(wl, wlvif);
 
625
        if (ret < 0)
 
626
                return ret;
 
627
 
 
628
        /* Mode specific init - post mem init */
 
629
        if (is_ap)
 
630
                ret = wl1271_ap_hw_init_post_mem(wl, vif);
 
631
        else
 
632
                ret = wl1271_sta_hw_init_post_mem(wl, vif);
 
633
 
 
634
        if (ret < 0)
 
635
                return ret;
 
636
 
 
637
        /* Configure initiator BA sessions policies */
 
638
        ret = wl1271_set_ba_policies(wl, wlvif);
 
639
        if (ret < 0)
 
640
                return ret;
 
641
 
 
642
        ret = wlcore_hw_init_vif(wl, wlvif);
 
643
        if (ret < 0)
 
644
                return ret;
 
645
 
 
646
        return 0;
 
647
}
 
648
 
 
649
int wl1271_hw_init(struct wl1271 *wl)
 
650
{
 
651
        int ret;
 
652
 
 
653
        /* Chip-specific hw init */
 
654
        ret = wl->ops->hw_init(wl);
 
655
        if (ret < 0)
 
656
                return ret;
 
657
 
 
658
        /* Init templates */
 
659
        ret = wl1271_init_templates_config(wl);
 
660
        if (ret < 0)
 
661
                return ret;
 
662
 
 
663
        ret = wl12xx_acx_mem_cfg(wl);
 
664
        if (ret < 0)
 
665
                return ret;
 
666
 
 
667
        /* Configure the FW logger */
 
668
        ret = wl12xx_init_fwlog(wl);
 
669
        if (ret < 0)
 
670
                return ret;
 
671
 
 
672
        /* Bluetooth WLAN coexistence */
 
673
        ret = wl1271_init_pta(wl);
 
674
        if (ret < 0)
 
675
                return ret;
 
676
 
 
677
        /* Default memory configuration */
 
678
        ret = wl1271_acx_init_mem_config(wl);
 
679
        if (ret < 0)
 
680
                return ret;
 
681
 
 
682
        /* RX config */
 
683
        ret = wl12xx_init_rx_config(wl);
 
684
        if (ret < 0)
 
685
                goto out_free_memmap;
 
686
 
 
687
        ret = wl1271_acx_dco_itrim_params(wl);
 
688
        if (ret < 0)
 
689
                goto out_free_memmap;
 
690
 
 
691
        /* Configure TX patch complete interrupt behavior */
 
692
        ret = wl1271_acx_tx_config_options(wl);
 
693
        if (ret < 0)
 
694
                goto out_free_memmap;
 
695
 
 
696
        /* RX complete interrupt pacing */
 
697
        ret = wl1271_acx_init_rx_interrupt(wl);
 
698
        if (ret < 0)
 
699
                goto out_free_memmap;
 
700
 
 
701
        /* Energy detection */
 
702
        ret = wl1271_init_energy_detection(wl);
 
703
        if (ret < 0)
 
704
                goto out_free_memmap;
 
705
 
 
706
        /* Default fragmentation threshold */
 
707
        ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
 
708
        if (ret < 0)
 
709
                goto out_free_memmap;
 
710
 
 
711
        /* Enable data path */
 
712
        ret = wl1271_cmd_data_path(wl, 1);
 
713
        if (ret < 0)
 
714
                goto out_free_memmap;
 
715
 
 
716
        /* configure PM */
 
717
        ret = wl1271_acx_pm_config(wl);
 
718
        if (ret < 0)
 
719
                goto out_free_memmap;
 
720
 
 
721
        ret = wl12xx_acx_set_rate_mgmt_params(wl);
 
722
        if (ret < 0)
 
723
                goto out_free_memmap;
 
724
 
 
725
        /* configure hangover */
 
726
        ret = wl12xx_acx_config_hangover(wl);
 
727
        if (ret < 0)
 
728
                goto out_free_memmap;
 
729
 
 
730
        return 0;
 
731
 
 
732
 out_free_memmap:
 
733
        kfree(wl->target_mem_map);
 
734
        wl->target_mem_map = NULL;
 
735
 
 
736
        return ret;
 
737
}