~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/wl12xx/init.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include "acx.h"
31
31
#include "cmd.h"
32
32
#include "reg.h"
33
 
 
34
 
static int wl1271_init_hwenc_config(struct wl1271 *wl)
35
 
{
36
 
        int ret;
37
 
 
38
 
        ret = wl1271_acx_feature_cfg(wl);
39
 
        if (ret < 0) {
40
 
                wl1271_warning("couldn't set feature config");
41
 
                return ret;
42
 
        }
43
 
 
44
 
        ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
45
 
        if (ret < 0) {
46
 
                wl1271_warning("couldn't set default key");
47
 
                return ret;
48
 
        }
49
 
 
50
 
        return 0;
51
 
}
52
 
 
53
 
int wl1271_init_templates_config(struct wl1271 *wl)
 
33
#include "tx.h"
 
34
#include "io.h"
 
35
 
 
36
int wl1271_sta_init_templates_config(struct wl1271 *wl)
54
37
{
55
38
        int ret, i;
56
39
 
118
101
        return 0;
119
102
}
120
103
 
 
104
static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
 
105
{
 
106
        struct wl12xx_disconn_template *tmpl;
 
107
        int ret;
 
108
 
 
109
        tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
 
110
        if (!tmpl) {
 
111
                ret = -ENOMEM;
 
112
                goto out;
 
113
        }
 
114
 
 
115
        tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 
116
                                             IEEE80211_STYPE_DEAUTH);
 
117
 
 
118
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
 
119
                                      tmpl, sizeof(*tmpl), 0,
 
120
                                      wl1271_tx_min_rate_get(wl));
 
121
 
 
122
out:
 
123
        kfree(tmpl);
 
124
        return ret;
 
125
}
 
126
 
 
127
static int wl1271_ap_init_null_template(struct wl1271 *wl)
 
128
{
 
129
        struct ieee80211_hdr_3addr *nullfunc;
 
130
        int ret;
 
131
 
 
132
        nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
 
133
        if (!nullfunc) {
 
134
                ret = -ENOMEM;
 
135
                goto out;
 
136
        }
 
137
 
 
138
        nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 
139
                                              IEEE80211_STYPE_NULLFUNC |
 
140
                                              IEEE80211_FCTL_FROMDS);
 
141
 
 
142
        /* nullfunc->addr1 is filled by FW */
 
143
 
 
144
        memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
 
145
        memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
 
146
 
 
147
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
 
148
                                      sizeof(*nullfunc), 0,
 
149
                                      wl1271_tx_min_rate_get(wl));
 
150
 
 
151
out:
 
152
        kfree(nullfunc);
 
153
        return ret;
 
154
}
 
155
 
 
156
static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
 
157
{
 
158
        struct ieee80211_qos_hdr *qosnull;
 
159
        int ret;
 
160
 
 
161
        qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
 
162
        if (!qosnull) {
 
163
                ret = -ENOMEM;
 
164
                goto out;
 
165
        }
 
166
 
 
167
        qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 
168
                                             IEEE80211_STYPE_QOS_NULLFUNC |
 
169
                                             IEEE80211_FCTL_FROMDS);
 
170
 
 
171
        /* qosnull->addr1 is filled by FW */
 
172
 
 
173
        memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
 
174
        memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
 
175
 
 
176
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
 
177
                                      sizeof(*qosnull), 0,
 
178
                                      wl1271_tx_min_rate_get(wl));
 
179
 
 
180
out:
 
181
        kfree(qosnull);
 
182
        return ret;
 
183
}
 
184
 
 
185
static int wl1271_ap_init_templates_config(struct wl1271 *wl)
 
186
{
 
187
        int ret;
 
188
 
 
189
        /*
 
190
         * Put very large empty placeholders for all templates. These
 
191
         * reserve memory for later.
 
192
         */
 
193
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
 
194
                                      sizeof
 
195
                                      (struct wl12xx_probe_resp_template),
 
196
                                      0, WL1271_RATE_AUTOMATIC);
 
197
        if (ret < 0)
 
198
                return ret;
 
199
 
 
200
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
 
201
                                      sizeof
 
202
                                      (struct wl12xx_beacon_template),
 
203
                                      0, WL1271_RATE_AUTOMATIC);
 
204
        if (ret < 0)
 
205
                return ret;
 
206
 
 
207
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
 
208
                                      sizeof
 
209
                                      (struct wl12xx_disconn_template),
 
210
                                      0, WL1271_RATE_AUTOMATIC);
 
211
        if (ret < 0)
 
212
                return ret;
 
213
 
 
214
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
 
215
                                      sizeof(struct wl12xx_null_data_template),
 
216
                                      0, WL1271_RATE_AUTOMATIC);
 
217
        if (ret < 0)
 
218
                return ret;
 
219
 
 
220
        ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
 
221
                                      sizeof
 
222
                                      (struct wl12xx_qos_null_data_template),
 
223
                                      0, WL1271_RATE_AUTOMATIC);
 
224
        if (ret < 0)
 
225
                return ret;
 
226
 
 
227
        return 0;
 
228
}
 
229
 
121
230
static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
122
231
{
123
232
        int ret;
145
254
        if (ret < 0)
146
255
                return ret;
147
256
 
148
 
        ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
149
 
        if (ret < 0)
150
 
                return ret;
151
 
 
152
257
        ret = wl1271_acx_service_period_timeout(wl);
153
258
        if (ret < 0)
154
259
                return ret;
155
260
 
156
 
        ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
 
261
        ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold);
157
262
        if (ret < 0)
158
263
                return ret;
159
264
 
180
285
{
181
286
        int ret;
182
287
 
183
 
        ret = wl1271_acx_sg_cfg(wl);
 
288
        if (wl->bss_type == BSS_TYPE_AP_BSS)
 
289
                ret = wl1271_acx_ap_sg_cfg(wl);
 
290
        else
 
291
                ret = wl1271_acx_sta_sg_cfg(wl);
184
292
        if (ret < 0)
185
293
                return ret;
186
294
 
213
321
        return 0;
214
322
}
215
323
 
 
324
static int wl1271_sta_hw_init(struct wl1271 *wl)
 
325
{
 
326
        int ret;
 
327
 
 
328
        if (wl->chip.id != CHIP_ID_1283_PG20) {
 
329
                ret = wl1271_cmd_ext_radio_parms(wl);
 
330
                if (ret < 0)
 
331
                        return ret;
 
332
        }
 
333
 
 
334
        /* PS config */
 
335
        ret = wl1271_acx_config_ps(wl);
 
336
        if (ret < 0)
 
337
                return ret;
 
338
 
 
339
        ret = wl1271_sta_init_templates_config(wl);
 
340
        if (ret < 0)
 
341
                return ret;
 
342
 
 
343
        ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
 
344
        if (ret < 0)
 
345
                return ret;
 
346
 
 
347
        /* Initialize connection monitoring thresholds */
 
348
        ret = wl1271_acx_conn_monit_params(wl, false);
 
349
        if (ret < 0)
 
350
                return ret;
 
351
 
 
352
        /* Beacon filtering */
 
353
        ret = wl1271_init_beacon_filter(wl);
 
354
        if (ret < 0)
 
355
                return ret;
 
356
 
 
357
        /* FM WLAN coexistence */
 
358
        ret = wl1271_acx_fm_coex(wl);
 
359
        if (ret < 0)
 
360
                return ret;
 
361
 
 
362
        /* Beacons and broadcast settings */
 
363
        ret = wl1271_init_beacon_broadcast(wl);
 
364
        if (ret < 0)
 
365
                return ret;
 
366
 
 
367
        /* Configure for ELP power saving */
 
368
        ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
 
369
        if (ret < 0)
 
370
                return ret;
 
371
 
 
372
        /* Configure rssi/snr averaging weights */
 
373
        ret = wl1271_acx_rssi_snr_avg_weights(wl);
 
374
        if (ret < 0)
 
375
                return ret;
 
376
 
 
377
        ret = wl1271_acx_sta_rate_policies(wl);
 
378
        if (ret < 0)
 
379
                return ret;
 
380
 
 
381
        ret = wl1271_acx_sta_mem_cfg(wl);
 
382
        if (ret < 0)
 
383
                return ret;
 
384
 
 
385
        return 0;
 
386
}
 
387
 
 
388
static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
 
389
{
 
390
        int ret, i;
 
391
 
 
392
        ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
 
393
        if (ret < 0) {
 
394
                wl1271_warning("couldn't set default key");
 
395
                return ret;
 
396
        }
 
397
 
 
398
        /* disable all keep-alive templates */
 
399
        for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
 
400
                ret = wl1271_acx_keep_alive_config(wl, i,
 
401
                                                   ACX_KEEP_ALIVE_TPL_INVALID);
 
402
                if (ret < 0)
 
403
                        return ret;
 
404
        }
 
405
 
 
406
        /* disable the keep-alive feature */
 
407
        ret = wl1271_acx_keep_alive_mode(wl, false);
 
408
        if (ret < 0)
 
409
                return ret;
 
410
 
 
411
        return 0;
 
412
}
 
413
 
 
414
static int wl1271_ap_hw_init(struct wl1271 *wl)
 
415
{
 
416
        int ret;
 
417
 
 
418
        ret = wl1271_ap_init_templates_config(wl);
 
419
        if (ret < 0)
 
420
                return ret;
 
421
 
 
422
        /* Configure for power always on */
 
423
        ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
 
424
        if (ret < 0)
 
425
                return ret;
 
426
 
 
427
        ret = wl1271_init_ap_rates(wl);
 
428
        if (ret < 0)
 
429
                return ret;
 
430
 
 
431
        ret = wl1271_acx_max_tx_retry(wl);
 
432
        if (ret < 0)
 
433
                return ret;
 
434
 
 
435
        ret = wl1271_acx_ap_mem_cfg(wl);
 
436
        if (ret < 0)
 
437
                return ret;
 
438
 
 
439
        return 0;
 
440
}
 
441
 
 
442
int wl1271_ap_init_templates(struct wl1271 *wl)
 
443
{
 
444
        int ret;
 
445
 
 
446
        ret = wl1271_ap_init_deauth_template(wl);
 
447
        if (ret < 0)
 
448
                return ret;
 
449
 
 
450
        ret = wl1271_ap_init_null_template(wl);
 
451
        if (ret < 0)
 
452
                return ret;
 
453
 
 
454
        ret = wl1271_ap_init_qos_null_template(wl);
 
455
        if (ret < 0)
 
456
                return ret;
 
457
 
 
458
        /*
 
459
         * when operating as AP we want to receive external beacons for
 
460
         * configuring ERP protection.
 
461
         */
 
462
        ret = wl1271_acx_set_ap_beacon_filter(wl, false);
 
463
        if (ret < 0)
 
464
                return ret;
 
465
 
 
466
        return 0;
 
467
}
 
468
 
 
469
static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
 
470
{
 
471
        return wl1271_ap_init_templates(wl);
 
472
}
 
473
 
 
474
int wl1271_init_ap_rates(struct wl1271 *wl)
 
475
{
 
476
        int i, ret;
 
477
        struct conf_tx_rate_class rc;
 
478
        u32 supported_rates;
 
479
 
 
480
        wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set);
 
481
 
 
482
        if (wl->basic_rate_set == 0)
 
483
                return -EINVAL;
 
484
 
 
485
        rc.enabled_rates = wl->basic_rate_set;
 
486
        rc.long_retry_limit = 10;
 
487
        rc.short_retry_limit = 10;
 
488
        rc.aflags = 0;
 
489
        ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE);
 
490
        if (ret < 0)
 
491
                return ret;
 
492
 
 
493
        /* use the min basic rate for AP broadcast/multicast */
 
494
        rc.enabled_rates = wl1271_tx_min_rate_get(wl);
 
495
        rc.short_retry_limit = 10;
 
496
        rc.long_retry_limit = 10;
 
497
        rc.aflags = 0;
 
498
        ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE);
 
499
        if (ret < 0)
 
500
                return ret;
 
501
 
 
502
        /*
 
503
         * If the basic rates contain OFDM rates, use OFDM only
 
504
         * rates for unicast TX as well. Else use all supported rates.
 
505
         */
 
506
        if ((wl->basic_rate_set & CONF_TX_OFDM_RATES))
 
507
                supported_rates = CONF_TX_OFDM_RATES;
 
508
        else
 
509
                supported_rates = CONF_TX_AP_ENABLED_RATES;
 
510
 
 
511
        /* configure unicast TX rate classes */
 
512
        for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
 
513
                rc.enabled_rates = supported_rates;
 
514
                rc.short_retry_limit = 10;
 
515
                rc.long_retry_limit = 10;
 
516
                rc.aflags = 0;
 
517
                ret = wl1271_acx_ap_rate_policy(wl, &rc, i);
 
518
                if (ret < 0)
 
519
                        return ret;
 
520
        }
 
521
 
 
522
        return 0;
 
523
}
 
524
 
 
525
static void wl1271_check_ba_support(struct wl1271 *wl)
 
526
{
 
527
        /* validate FW cose ver x.x.x.50-60.x */
 
528
        if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
 
529
            (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
 
530
                wl->ba_support = true;
 
531
                return;
 
532
        }
 
533
 
 
534
        wl->ba_support = false;
 
535
}
 
536
 
 
537
static int wl1271_set_ba_policies(struct wl1271 *wl)
 
538
{
 
539
        u8 tid_index;
 
540
        int ret = 0;
 
541
 
 
542
        /* Reset the BA RX indicators */
 
543
        wl->ba_rx_bitmap = 0;
 
544
 
 
545
        /* validate that FW support BA */
 
546
        wl1271_check_ba_support(wl);
 
547
 
 
548
        if (wl->ba_support)
 
549
                /* 802.11n initiator BA session setting */
 
550
                for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
 
551
                     ++tid_index) {
 
552
                        ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
 
553
                                                        tid_index, true);
 
554
                        if (ret < 0)
 
555
                                break;
 
556
                }
 
557
 
 
558
        return ret;
 
559
}
 
560
 
 
561
int wl1271_chip_specific_init(struct wl1271 *wl)
 
562
{
 
563
        int ret = 0;
 
564
 
 
565
        if (wl->chip.id == CHIP_ID_1283_PG20) {
 
566
                u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
 
567
 
 
568
                if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT)
 
569
                        /* Enable SDIO padding */
 
570
                        host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
 
571
 
 
572
                /* Must be before wl1271_acx_init_mem_config() */
 
573
                ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
 
574
                if (ret < 0)
 
575
                        goto out;
 
576
        }
 
577
out:
 
578
        return ret;
 
579
}
 
580
 
 
581
 
216
582
int wl1271_hw_init(struct wl1271 *wl)
217
583
{
218
584
        struct conf_tx_ac_category *conf_ac;
219
585
        struct conf_tx_tid *conf_tid;
220
586
        int ret, i;
221
 
 
222
 
        ret = wl1271_cmd_general_parms(wl);
223
 
        if (ret < 0)
224
 
                return ret;
225
 
 
226
 
        ret = wl1271_cmd_radio_parms(wl);
227
 
        if (ret < 0)
228
 
                return ret;
229
 
 
230
 
        ret = wl1271_cmd_ext_radio_parms(wl);
231
 
        if (ret < 0)
232
 
                return ret;
233
 
 
234
 
        /* Template settings */
235
 
        ret = wl1271_init_templates_config(wl);
 
587
        bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
588
 
 
589
        if (wl->chip.id == CHIP_ID_1283_PG20)
 
590
                ret = wl128x_cmd_general_parms(wl);
 
591
        else
 
592
                ret = wl1271_cmd_general_parms(wl);
 
593
        if (ret < 0)
 
594
                return ret;
 
595
 
 
596
        if (wl->chip.id == CHIP_ID_1283_PG20)
 
597
                ret = wl128x_cmd_radio_parms(wl);
 
598
        else
 
599
                ret = wl1271_cmd_radio_parms(wl);
 
600
        if (ret < 0)
 
601
                return ret;
 
602
 
 
603
        /* Chip-specific init */
 
604
        ret = wl1271_chip_specific_init(wl);
 
605
        if (ret < 0)
 
606
                return ret;
 
607
 
 
608
        /* Mode specific init */
 
609
        if (is_ap)
 
610
                ret = wl1271_ap_hw_init(wl);
 
611
        else
 
612
                ret = wl1271_sta_hw_init(wl);
 
613
 
 
614
        if (ret < 0)
 
615
                return ret;
 
616
 
 
617
        /* Bluetooth WLAN coexistence */
 
618
        ret = wl1271_init_pta(wl);
236
619
        if (ret < 0)
237
620
                return ret;
238
621
 
259
642
        if (ret < 0)
260
643
                goto out_free_memmap;
261
644
 
262
 
        /* Initialize connection monitoring thresholds */
263
 
        ret = wl1271_acx_conn_monit_params(wl, false);
264
 
        if (ret < 0)
265
 
                goto out_free_memmap;
266
 
 
267
 
        /* Beacon filtering */
268
 
        ret = wl1271_init_beacon_filter(wl);
269
 
        if (ret < 0)
270
 
                goto out_free_memmap;
271
 
 
272
645
        /* Configure TX patch complete interrupt behavior */
273
646
        ret = wl1271_acx_tx_config_options(wl);
274
647
        if (ret < 0)
279
652
        if (ret < 0)
280
653
                goto out_free_memmap;
281
654
 
282
 
        /* Bluetooth WLAN coexistence */
283
 
        ret = wl1271_init_pta(wl);
284
 
        if (ret < 0)
285
 
                goto out_free_memmap;
286
 
 
287
655
        /* Energy detection */
288
656
        ret = wl1271_init_energy_detection(wl);
289
657
        if (ret < 0)
290
658
                goto out_free_memmap;
291
659
 
292
 
        /* Beacons and boradcast settings */
293
 
        ret = wl1271_init_beacon_broadcast(wl);
294
 
        if (ret < 0)
295
 
                goto out_free_memmap;
296
 
 
297
660
        /* Default fragmentation threshold */
298
 
        ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 
661
        ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold);
299
662
        if (ret < 0)
300
663
                goto out_free_memmap;
301
664
 
321
684
                        goto out_free_memmap;
322
685
        }
323
686
 
324
 
        /* Configure TX rate classes */
325
 
        ret = wl1271_acx_rate_policies(wl);
326
 
        if (ret < 0)
327
 
                goto out_free_memmap;
328
 
 
329
687
        /* Enable data path */
330
688
        ret = wl1271_cmd_data_path(wl, 1);
331
689
        if (ret < 0)
332
690
                goto out_free_memmap;
333
691
 
334
 
        /* Configure for ELP power saving */
335
 
        ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
336
 
        if (ret < 0)
337
 
                goto out_free_memmap;
338
 
 
339
692
        /* Configure HW encryption */
340
 
        ret = wl1271_init_hwenc_config(wl);
 
693
        ret = wl1271_acx_feature_cfg(wl);
341
694
        if (ret < 0)
342
695
                goto out_free_memmap;
343
696
 
346
699
        if (ret < 0)
347
700
                goto out_free_memmap;
348
701
 
349
 
        /* disable all keep-alive templates */
350
 
        for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
351
 
                ret = wl1271_acx_keep_alive_config(wl, i,
352
 
                                                   ACX_KEEP_ALIVE_TPL_INVALID);
353
 
                if (ret < 0)
354
 
                        goto out_free_memmap;
355
 
        }
 
702
        /* Mode specific init - post mem init */
 
703
        if (is_ap)
 
704
                ret = wl1271_ap_hw_init_post_mem(wl);
 
705
        else
 
706
                ret = wl1271_sta_hw_init_post_mem(wl);
356
707
 
357
 
        /* disable the keep-alive feature */
358
 
        ret = wl1271_acx_keep_alive_mode(wl, false);
359
708
        if (ret < 0)
360
709
                goto out_free_memmap;
361
710
 
362
 
        /* Configure rssi/snr averaging weights */
363
 
        ret = wl1271_acx_rssi_snr_avg_weights(wl);
 
711
        /* Configure initiator BA sessions policies */
 
712
        ret = wl1271_set_ba_policies(wl);
364
713
        if (ret < 0)
365
714
                goto out_free_memmap;
366
715