diff options
author | Luciano Coelho <coelho@ti.com> | 2013-01-18 02:40:07 -0500 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2013-01-18 02:59:08 -0500 |
commit | 5b37649bbcfc14c1ecfb76c5b018dd686924b946 (patch) | |
tree | 5d88b1619176b860041fdd20b64ce917b8613698 /drivers/net/wireless/ti/wl18xx/main.c | |
parent | 660b9caaad380758c756a7e60397e33dab44fe3f (diff) | |
parent | 2e07d02828759a506b5205b2cff40daa58df5bf7 (diff) |
Merge branch 'wl12xx-next' into for-linville
Conflicts:
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wlcore/wlcore.h
Diffstat (limited to 'drivers/net/wireless/ti/wl18xx/main.c')
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 267 |
1 files changed, 219 insertions, 48 deletions
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 8d8c1f8c63b7..0be1cfc17a86 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -34,10 +34,13 @@ | |||
34 | 34 | ||
35 | #include "reg.h" | 35 | #include "reg.h" |
36 | #include "conf.h" | 36 | #include "conf.h" |
37 | #include "cmd.h" | ||
37 | #include "acx.h" | 38 | #include "acx.h" |
38 | #include "tx.h" | 39 | #include "tx.h" |
39 | #include "wl18xx.h" | 40 | #include "wl18xx.h" |
40 | #include "io.h" | 41 | #include "io.h" |
42 | #include "scan.h" | ||
43 | #include "event.h" | ||
41 | #include "debugfs.h" | 44 | #include "debugfs.h" |
42 | 45 | ||
43 | #define WL18XX_RX_CHECKSUM_MASK 0x40 | 46 | #define WL18XX_RX_CHECKSUM_MASK 0x40 |
@@ -334,6 +337,8 @@ static struct wlcore_conf wl18xx_conf = { | |||
334 | .tmpl_short_retry_limit = 10, | 337 | .tmpl_short_retry_limit = 10, |
335 | .tmpl_long_retry_limit = 10, | 338 | .tmpl_long_retry_limit = 10, |
336 | .tx_watchdog_timeout = 5000, | 339 | .tx_watchdog_timeout = 5000, |
340 | .slow_link_thold = 3, | ||
341 | .fast_link_thold = 30, | ||
337 | }, | 342 | }, |
338 | .conn = { | 343 | .conn = { |
339 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 344 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -391,8 +396,10 @@ static struct wlcore_conf wl18xx_conf = { | |||
391 | .scan = { | 396 | .scan = { |
392 | .min_dwell_time_active = 7500, | 397 | .min_dwell_time_active = 7500, |
393 | .max_dwell_time_active = 30000, | 398 | .max_dwell_time_active = 30000, |
394 | .min_dwell_time_passive = 100000, | 399 | .min_dwell_time_active_long = 25000, |
395 | .max_dwell_time_passive = 100000, | 400 | .max_dwell_time_active_long = 50000, |
401 | .dwell_time_passive = 100000, | ||
402 | .dwell_time_dfs = 150000, | ||
396 | .num_probe_reqs = 2, | 403 | .num_probe_reqs = 2, |
397 | .split_scan_timeout = 50000, | 404 | .split_scan_timeout = 50000, |
398 | }, | 405 | }, |
@@ -489,6 +496,10 @@ static struct wlcore_conf wl18xx_conf = { | |||
489 | .increase_time = 1, | 496 | .increase_time = 1, |
490 | .window_size = 16, | 497 | .window_size = 16, |
491 | }, | 498 | }, |
499 | .recovery = { | ||
500 | .bug_on_recovery = 0, | ||
501 | .no_recovery = 0, | ||
502 | }, | ||
492 | }; | 503 | }; |
493 | 504 | ||
494 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 505 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { |
@@ -501,7 +512,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
501 | .clock_valid_on_wake_up = 0x00, | 512 | .clock_valid_on_wake_up = 0x00, |
502 | .secondary_clock_setting_time = 0x05, | 513 | .secondary_clock_setting_time = 0x05, |
503 | .board_type = BOARD_TYPE_HDK_18XX, | 514 | .board_type = BOARD_TYPE_HDK_18XX, |
504 | .rdl = 0x01, | ||
505 | .auto_detect = 0x00, | 515 | .auto_detect = 0x00, |
506 | .dedicated_fem = FEM_NONE, | 516 | .dedicated_fem = FEM_NONE, |
507 | .low_band_component = COMPONENT_3_WAY_SWITCH, | 517 | .low_band_component = COMPONENT_3_WAY_SWITCH, |
@@ -517,14 +527,39 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
517 | .enable_clpc = 0x00, | 527 | .enable_clpc = 0x00, |
518 | .enable_tx_low_pwr_on_siso_rdl = 0x00, | 528 | .enable_tx_low_pwr_on_siso_rdl = 0x00, |
519 | .rx_profile = 0x00, | 529 | .rx_profile = 0x00, |
520 | .pwr_limit_reference_11_abg = 0xc8, | 530 | .pwr_limit_reference_11_abg = 0x64, |
531 | .per_chan_pwr_limit_arr_11abg = { | ||
532 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
533 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
534 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
535 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
536 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
537 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
538 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
539 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
540 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
541 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
542 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
543 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
544 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
545 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
546 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
547 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
548 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, | ||
549 | .pwr_limit_reference_11p = 0x64, | ||
550 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, | ||
551 | 0xff, 0xff, 0xff }, | ||
521 | .psat = 0, | 552 | .psat = 0, |
522 | .low_power_val = 0x00, | 553 | .low_power_val = 0x08, |
523 | .med_power_val = 0x0a, | 554 | .med_power_val = 0x12, |
524 | .high_power_val = 0x1e, | 555 | .high_power_val = 0x18, |
556 | .low_power_val_2nd = 0x05, | ||
557 | .med_power_val_2nd = 0x0a, | ||
558 | .high_power_val_2nd = 0x14, | ||
525 | .external_pa_dc2dc = 0, | 559 | .external_pa_dc2dc = 0, |
526 | .number_of_assembled_ant2_4 = 1, | 560 | .number_of_assembled_ant2_4 = 2, |
527 | .number_of_assembled_ant5 = 1, | 561 | .number_of_assembled_ant5 = 1, |
562 | .tx_rf_margin = 1, | ||
528 | }, | 563 | }, |
529 | }; | 564 | }; |
530 | 565 | ||
@@ -595,7 +630,7 @@ static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { | |||
595 | }; | 630 | }; |
596 | 631 | ||
597 | /* TODO: maybe move to a new header file? */ | 632 | /* TODO: maybe move to a new header file? */ |
598 | #define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin" | 633 | #define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw-2.bin" |
599 | 634 | ||
600 | static int wl18xx_identify_chip(struct wl1271 *wl) | 635 | static int wl18xx_identify_chip(struct wl1271 *wl) |
601 | { | 636 | { |
@@ -608,15 +643,18 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
608 | wl->sr_fw_name = WL18XX_FW_NAME; | 643 | wl->sr_fw_name = WL18XX_FW_NAME; |
609 | /* wl18xx uses the same firmware for PLT */ | 644 | /* wl18xx uses the same firmware for PLT */ |
610 | wl->plt_fw_name = WL18XX_FW_NAME; | 645 | wl->plt_fw_name = WL18XX_FW_NAME; |
611 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | 646 | wl->quirks |= WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | |
612 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
613 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | 647 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | |
614 | WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | | 648 | WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN | |
615 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | 649 | WLCORE_QUIRK_TX_PAD_LAST_FRAME | |
616 | 650 | WLCORE_QUIRK_REGDOMAIN_CONF | | |
617 | wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, WL18XX_IFTYPE_VER, | 651 | WLCORE_QUIRK_DUAL_PROBE_TMPL; |
618 | WL18XX_MAJOR_VER, WL18XX_SUBTYPE_VER, | 652 | |
619 | WL18XX_MINOR_VER); | 653 | wlcore_set_min_fw_ver(wl, WL18XX_CHIP_VER, |
654 | WL18XX_IFTYPE_VER, WL18XX_MAJOR_VER, | ||
655 | WL18XX_SUBTYPE_VER, WL18XX_MINOR_VER, | ||
656 | /* there's no separate multi-role FW */ | ||
657 | 0, 0, 0, 0); | ||
620 | break; | 658 | break; |
621 | case CHIP_ID_185x_PG10: | 659 | case CHIP_ID_185x_PG10: |
622 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", | 660 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", |
@@ -630,6 +668,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
630 | goto out; | 668 | goto out; |
631 | } | 669 | } |
632 | 670 | ||
671 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | ||
672 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | ||
673 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | ||
674 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; | ||
675 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; | ||
633 | out: | 676 | out: |
634 | return ret; | 677 | return ret; |
635 | } | 678 | } |
@@ -843,6 +886,20 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
843 | if (ret < 0) | 886 | if (ret < 0) |
844 | goto out; | 887 | goto out; |
845 | 888 | ||
889 | wl->event_mask = BSS_LOSS_EVENT_ID | | ||
890 | SCAN_COMPLETE_EVENT_ID | | ||
891 | RSSI_SNR_TRIGGER_0_EVENT_ID | | ||
892 | PERIODIC_SCAN_COMPLETE_EVENT_ID | | ||
893 | PERIODIC_SCAN_REPORT_EVENT_ID | | ||
894 | DUMMY_PACKET_EVENT_ID | | ||
895 | PEER_REMOVE_COMPLETE_EVENT_ID | | ||
896 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | ||
897 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | ||
898 | INACTIVE_STA_EVENT_ID | | ||
899 | MAX_TX_FAILURE_EVENT_ID | | ||
900 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | | ||
901 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | ||
902 | |||
846 | ret = wlcore_boot_run_firmware(wl); | 903 | ret = wlcore_boot_run_firmware(wl); |
847 | if (ret < 0) | 904 | if (ret < 0) |
848 | goto out; | 905 | goto out; |
@@ -964,7 +1021,7 @@ static int wl18xx_hw_init(struct wl1271 *wl) | |||
964 | 1021 | ||
965 | /* (re)init private structures. Relevant on recovery as well. */ | 1022 | /* (re)init private structures. Relevant on recovery as well. */ |
966 | priv->last_fw_rls_idx = 0; | 1023 | priv->last_fw_rls_idx = 0; |
967 | priv->extra_spare_vif_count = 0; | 1024 | priv->extra_spare_key_count = 0; |
968 | 1025 | ||
969 | /* set the default amount of spare blocks in the bitmap */ | 1026 | /* set the default amount of spare blocks in the bitmap */ |
970 | ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); | 1027 | ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); |
@@ -1022,7 +1079,12 @@ static bool wl18xx_is_mimo_supported(struct wl1271 *wl) | |||
1022 | { | 1079 | { |
1023 | struct wl18xx_priv *priv = wl->priv; | 1080 | struct wl18xx_priv *priv = wl->priv; |
1024 | 1081 | ||
1025 | return priv->conf.phy.number_of_assembled_ant2_4 >= 2; | 1082 | /* only support MIMO with multiple antennas, and when SISO |
1083 | * is not forced through config | ||
1084 | */ | ||
1085 | return (priv->conf.phy.number_of_assembled_ant2_4 >= 2) && | ||
1086 | (priv->conf.ht.mode != HT_MODE_WIDE) && | ||
1087 | (priv->conf.ht.mode != HT_MODE_SISO20); | ||
1026 | } | 1088 | } |
1027 | 1089 | ||
1028 | /* | 1090 | /* |
@@ -1223,8 +1285,8 @@ static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) | |||
1223 | { | 1285 | { |
1224 | struct wl18xx_priv *priv = wl->priv; | 1286 | struct wl18xx_priv *priv = wl->priv; |
1225 | 1287 | ||
1226 | /* If we have VIFs requiring extra spare, indulge them */ | 1288 | /* If we have keys requiring extra spare, indulge them */ |
1227 | if (priv->extra_spare_vif_count) | 1289 | if (priv->extra_spare_key_count) |
1228 | return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; | 1290 | return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; |
1229 | 1291 | ||
1230 | return WL18XX_TX_HW_BLOCK_SPARE; | 1292 | return WL18XX_TX_HW_BLOCK_SPARE; |
@@ -1236,42 +1298,48 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
1236 | struct ieee80211_key_conf *key_conf) | 1298 | struct ieee80211_key_conf *key_conf) |
1237 | { | 1299 | { |
1238 | struct wl18xx_priv *priv = wl->priv; | 1300 | struct wl18xx_priv *priv = wl->priv; |
1239 | bool change_spare = false; | 1301 | bool change_spare = false, special_enc; |
1240 | int ret; | 1302 | int ret; |
1241 | 1303 | ||
1304 | wl1271_debug(DEBUG_CRYPT, "extra spare keys before: %d", | ||
1305 | priv->extra_spare_key_count); | ||
1306 | |||
1307 | special_enc = key_conf->cipher == WL1271_CIPHER_SUITE_GEM || | ||
1308 | key_conf->cipher == WLAN_CIPHER_SUITE_TKIP; | ||
1309 | |||
1310 | ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1311 | if (ret < 0) | ||
1312 | goto out; | ||
1313 | |||
1242 | /* | 1314 | /* |
1243 | * when adding the first or removing the last GEM/TKIP interface, | 1315 | * when adding the first or removing the last GEM/TKIP key, |
1244 | * we have to adjust the number of spare blocks. | 1316 | * we have to adjust the number of spare blocks. |
1245 | */ | 1317 | */ |
1246 | change_spare = (key_conf->cipher == WL1271_CIPHER_SUITE_GEM || | 1318 | if (special_enc) { |
1247 | key_conf->cipher == WLAN_CIPHER_SUITE_TKIP) && | 1319 | if (cmd == SET_KEY) { |
1248 | ((priv->extra_spare_vif_count == 0 && cmd == SET_KEY) || | 1320 | /* first key */ |
1249 | (priv->extra_spare_vif_count == 1 && cmd == DISABLE_KEY)); | 1321 | change_spare = (priv->extra_spare_key_count == 0); |
1322 | priv->extra_spare_key_count++; | ||
1323 | } else if (cmd == DISABLE_KEY) { | ||
1324 | /* last key */ | ||
1325 | change_spare = (priv->extra_spare_key_count == 1); | ||
1326 | priv->extra_spare_key_count--; | ||
1327 | } | ||
1328 | } | ||
1250 | 1329 | ||
1251 | /* no need to change spare - just regular set_key */ | 1330 | wl1271_debug(DEBUG_CRYPT, "extra spare keys after: %d", |
1252 | if (!change_spare) | 1331 | priv->extra_spare_key_count); |
1253 | return wlcore_set_key(wl, cmd, vif, sta, key_conf); | ||
1254 | 1332 | ||
1255 | ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); | 1333 | if (!change_spare) |
1256 | if (ret < 0) | ||
1257 | goto out; | 1334 | goto out; |
1258 | 1335 | ||
1259 | /* key is now set, change the spare blocks */ | 1336 | /* key is now set, change the spare blocks */ |
1260 | if (cmd == SET_KEY) { | 1337 | if (priv->extra_spare_key_count) |
1261 | ret = wl18xx_set_host_cfg_bitmap(wl, | 1338 | ret = wl18xx_set_host_cfg_bitmap(wl, |
1262 | WL18XX_TX_HW_EXTRA_BLOCK_SPARE); | 1339 | WL18XX_TX_HW_EXTRA_BLOCK_SPARE); |
1263 | if (ret < 0) | 1340 | else |
1264 | goto out; | ||
1265 | |||
1266 | priv->extra_spare_vif_count++; | ||
1267 | } else { | ||
1268 | ret = wl18xx_set_host_cfg_bitmap(wl, | 1341 | ret = wl18xx_set_host_cfg_bitmap(wl, |
1269 | WL18XX_TX_HW_BLOCK_SPARE); | 1342 | WL18XX_TX_HW_BLOCK_SPARE); |
1270 | if (ret < 0) | ||
1271 | goto out; | ||
1272 | |||
1273 | priv->extra_spare_vif_count--; | ||
1274 | } | ||
1275 | 1343 | ||
1276 | out: | 1344 | out: |
1277 | return ret; | 1345 | return ret; |
@@ -1296,6 +1364,92 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, | |||
1296 | return buf_offset; | 1364 | return buf_offset; |
1297 | } | 1365 | } |
1298 | 1366 | ||
1367 | static void wl18xx_sta_rc_update(struct wl1271 *wl, | ||
1368 | struct wl12xx_vif *wlvif, | ||
1369 | struct ieee80211_sta *sta, | ||
1370 | u32 changed) | ||
1371 | { | ||
1372 | bool wide = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1373 | |||
1374 | wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide); | ||
1375 | |||
1376 | if (!(changed & IEEE80211_RC_BW_CHANGED)) | ||
1377 | return; | ||
1378 | |||
1379 | mutex_lock(&wl->mutex); | ||
1380 | |||
1381 | /* sanity */ | ||
1382 | if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) | ||
1383 | goto out; | ||
1384 | |||
1385 | /* ignore the change before association */ | ||
1386 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
1387 | goto out; | ||
1388 | |||
1389 | /* | ||
1390 | * If we started out as wide, we can change the operation mode. If we | ||
1391 | * thought this was a 20mhz AP, we have to reconnect | ||
1392 | */ | ||
1393 | if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS || | ||
1394 | wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS) | ||
1395 | wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide); | ||
1396 | else | ||
1397 | ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif)); | ||
1398 | |||
1399 | out: | ||
1400 | mutex_unlock(&wl->mutex); | ||
1401 | } | ||
1402 | |||
1403 | static int wl18xx_set_peer_cap(struct wl1271 *wl, | ||
1404 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1405 | bool allow_ht_operation, | ||
1406 | u32 rate_set, u8 hlid) | ||
1407 | { | ||
1408 | return wl18xx_acx_set_peer_cap(wl, ht_cap, allow_ht_operation, | ||
1409 | rate_set, hlid); | ||
1410 | } | ||
1411 | |||
1412 | static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid, | ||
1413 | struct wl1271_link *lnk) | ||
1414 | { | ||
1415 | u8 thold; | ||
1416 | struct wl18xx_fw_status_priv *status_priv = | ||
1417 | (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; | ||
1418 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | ||
1419 | |||
1420 | /* suspended links are never high priority */ | ||
1421 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | ||
1422 | return false; | ||
1423 | |||
1424 | /* the priority thresholds are taken from FW */ | ||
1425 | if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | ||
1426 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | ||
1427 | thold = status_priv->tx_fast_link_prio_threshold; | ||
1428 | else | ||
1429 | thold = status_priv->tx_slow_link_prio_threshold; | ||
1430 | |||
1431 | return lnk->allocated_pkts < thold; | ||
1432 | } | ||
1433 | |||
1434 | static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | ||
1435 | struct wl1271_link *lnk) | ||
1436 | { | ||
1437 | u8 thold; | ||
1438 | struct wl18xx_fw_status_priv *status_priv = | ||
1439 | (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; | ||
1440 | u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap); | ||
1441 | |||
1442 | if (test_bit(hlid, (unsigned long *)&suspend_bitmap)) | ||
1443 | thold = status_priv->tx_suspend_threshold; | ||
1444 | else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) && | ||
1445 | !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map)) | ||
1446 | thold = status_priv->tx_fast_stop_threshold; | ||
1447 | else | ||
1448 | thold = status_priv->tx_slow_stop_threshold; | ||
1449 | |||
1450 | return lnk->allocated_pkts < thold; | ||
1451 | } | ||
1452 | |||
1299 | static int wl18xx_setup(struct wl1271 *wl); | 1453 | static int wl18xx_setup(struct wl1271 *wl); |
1300 | 1454 | ||
1301 | static struct wlcore_ops wl18xx_ops = { | 1455 | static struct wlcore_ops wl18xx_ops = { |
@@ -1305,6 +1459,8 @@ static struct wlcore_ops wl18xx_ops = { | |||
1305 | .plt_init = wl18xx_plt_init, | 1459 | .plt_init = wl18xx_plt_init, |
1306 | .trigger_cmd = wl18xx_trigger_cmd, | 1460 | .trigger_cmd = wl18xx_trigger_cmd, |
1307 | .ack_event = wl18xx_ack_event, | 1461 | .ack_event = wl18xx_ack_event, |
1462 | .wait_for_event = wl18xx_wait_for_event, | ||
1463 | .process_mailbox_events = wl18xx_process_mailbox_events, | ||
1308 | .calc_tx_blocks = wl18xx_calc_tx_blocks, | 1464 | .calc_tx_blocks = wl18xx_calc_tx_blocks, |
1309 | .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, | 1465 | .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, |
1310 | .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, | 1466 | .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, |
@@ -1320,16 +1476,26 @@ static struct wlcore_ops wl18xx_ops = { | |||
1320 | .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, | 1476 | .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, |
1321 | .get_mac = wl18xx_get_mac, | 1477 | .get_mac = wl18xx_get_mac, |
1322 | .debugfs_init = wl18xx_debugfs_add_files, | 1478 | .debugfs_init = wl18xx_debugfs_add_files, |
1479 | .scan_start = wl18xx_scan_start, | ||
1480 | .scan_stop = wl18xx_scan_stop, | ||
1481 | .sched_scan_start = wl18xx_sched_scan_start, | ||
1482 | .sched_scan_stop = wl18xx_scan_sched_scan_stop, | ||
1323 | .handle_static_data = wl18xx_handle_static_data, | 1483 | .handle_static_data = wl18xx_handle_static_data, |
1324 | .get_spare_blocks = wl18xx_get_spare_blocks, | 1484 | .get_spare_blocks = wl18xx_get_spare_blocks, |
1325 | .set_key = wl18xx_set_key, | 1485 | .set_key = wl18xx_set_key, |
1486 | .channel_switch = wl18xx_cmd_channel_switch, | ||
1326 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1487 | .pre_pkt_send = wl18xx_pre_pkt_send, |
1488 | .sta_rc_update = wl18xx_sta_rc_update, | ||
1489 | .set_peer_cap = wl18xx_set_peer_cap, | ||
1490 | .lnk_high_prio = wl18xx_lnk_high_prio, | ||
1491 | .lnk_low_prio = wl18xx_lnk_low_prio, | ||
1327 | }; | 1492 | }; |
1328 | 1493 | ||
1329 | /* HT cap appropriate for wide channels in 2Ghz */ | 1494 | /* HT cap appropriate for wide channels in 2Ghz */ |
1330 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { | 1495 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { |
1331 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1496 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1332 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, | 1497 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40 | |
1498 | IEEE80211_HT_CAP_GRN_FLD, | ||
1333 | .ht_supported = true, | 1499 | .ht_supported = true, |
1334 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1500 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1335 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1501 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1343,7 +1509,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { | |||
1343 | /* HT cap appropriate for wide channels in 5Ghz */ | 1509 | /* HT cap appropriate for wide channels in 5Ghz */ |
1344 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { | 1510 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { |
1345 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1511 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1346 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | 1512 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
1513 | IEEE80211_HT_CAP_GRN_FLD, | ||
1347 | .ht_supported = true, | 1514 | .ht_supported = true, |
1348 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1515 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1349 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1516 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1356,7 +1523,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { | |||
1356 | 1523 | ||
1357 | /* HT cap appropriate for SISO 20 */ | 1524 | /* HT cap appropriate for SISO 20 */ |
1358 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | 1525 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { |
1359 | .cap = IEEE80211_HT_CAP_SGI_20, | 1526 | .cap = IEEE80211_HT_CAP_SGI_20 | |
1527 | IEEE80211_HT_CAP_GRN_FLD, | ||
1360 | .ht_supported = true, | 1528 | .ht_supported = true, |
1361 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1529 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1362 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1530 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1369,7 +1537,8 @@ static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | |||
1369 | 1537 | ||
1370 | /* HT cap appropriate for MIMO rates in 20mhz channel */ | 1538 | /* HT cap appropriate for MIMO rates in 20mhz channel */ |
1371 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | 1539 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { |
1372 | .cap = IEEE80211_HT_CAP_SGI_20, | 1540 | .cap = IEEE80211_HT_CAP_SGI_20 | |
1541 | IEEE80211_HT_CAP_GRN_FLD, | ||
1373 | .ht_supported = true, | 1542 | .ht_supported = true, |
1374 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1543 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1375 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1544 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
@@ -1387,7 +1556,8 @@ static int wl18xx_setup(struct wl1271 *wl) | |||
1387 | 1556 | ||
1388 | wl->rtable = wl18xx_rtable; | 1557 | wl->rtable = wl18xx_rtable; |
1389 | wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; | 1558 | wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; |
1390 | wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; | 1559 | wl->num_rx_desc = WL18XX_NUM_RX_DESCRIPTORS; |
1560 | wl->num_channels = 2; | ||
1391 | wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; | 1561 | wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES; |
1392 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; | 1562 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; |
1393 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; | 1563 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; |
@@ -1506,7 +1676,8 @@ static int wl18xx_probe(struct platform_device *pdev) | |||
1506 | int ret; | 1676 | int ret; |
1507 | 1677 | ||
1508 | hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), | 1678 | hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), |
1509 | WL18XX_AGGR_BUFFER_SIZE); | 1679 | WL18XX_AGGR_BUFFER_SIZE, |
1680 | sizeof(struct wl18xx_event_mailbox)); | ||
1510 | if (IS_ERR(hw)) { | 1681 | if (IS_ERR(hw)) { |
1511 | wl1271_error("can't allocate hw"); | 1682 | wl1271_error("can't allocate hw"); |
1512 | ret = PTR_ERR(hw); | 1683 | ret = PTR_ERR(hw); |