aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-07-20 12:30:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-20 12:30:48 -0400
commit90b90f60c4f8e3a8525dfeb4aec46a9c7a29c857 (patch)
tree9b1d8ca6084012a02b302520bc26e5be65ba7b2a /drivers/net/wireless/ti
parent769162e38b91e1d300752e666260fa6c7b203fbc (diff)
parent36eb22e97a2b621fb707eead58ef915ab0f46e9e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wl12xx/cmd.c34
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c23
-rw-r--r--drivers/net/wireless/ti/wl18xx/conf.h21
-rw-r--r--drivers/net/wireless/ti/wl18xx/io.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c117
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c12
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c44
-rw-r--r--drivers/net/wireless/ti/wlcore/testmode.c85
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c14
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h8
12 files changed, 290 insertions, 74 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
index 30be784a40d8..622206241e83 100644
--- a/drivers/net/wireless/ti/wl12xx/cmd.c
+++ b/drivers/net/wireless/ti/wl12xx/cmd.c
@@ -85,7 +85,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
85 85
86 memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 86 memcpy(&gen_parms->general_params, gp, sizeof(*gp));
87 87
88 if (gp->tx_bip_fem_auto_detect) 88 /* If we started in PLT FEM_DETECT mode, force auto detect */
89 if (wl->plt_mode == PLT_FEM_DETECT)
90 gen_parms->general_params.tx_bip_fem_auto_detect = true;
91
92 if (gen_parms->general_params.tx_bip_fem_auto_detect)
89 answer = true; 93 answer = true;
90 94
91 /* Override the REF CLK from the NVS with the one from platform data */ 95 /* Override the REF CLK from the NVS with the one from platform data */
@@ -106,8 +110,17 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
106 goto out; 110 goto out;
107 } 111 }
108 112
113 /* If we are in calibrator based fem auto detect - save fem nr */
114 if (wl->plt_mode == PLT_FEM_DETECT)
115 wl->fem_manuf = gp->tx_bip_fem_manufacturer;
116
109 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 117 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
110 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 118 answer == false ?
119 "manual" :
120 wl->plt_mode == PLT_FEM_DETECT ?
121 "calibrator_fem_detect" :
122 "auto",
123 gp->tx_bip_fem_manufacturer);
111 124
112out: 125out:
113 kfree(gen_parms); 126 kfree(gen_parms);
@@ -139,7 +152,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
139 152
140 memcpy(&gen_parms->general_params, gp, sizeof(*gp)); 153 memcpy(&gen_parms->general_params, gp, sizeof(*gp));
141 154
142 if (gp->tx_bip_fem_auto_detect) 155 /* If we started in PLT FEM_DETECT mode, force auto detect */
156 if (wl->plt_mode == PLT_FEM_DETECT)
157 gen_parms->general_params.tx_bip_fem_auto_detect = true;
158
159 if (gen_parms->general_params.tx_bip_fem_auto_detect)
143 answer = true; 160 answer = true;
144 161
145 /* Replace REF and TCXO CLKs with the ones from platform data */ 162 /* Replace REF and TCXO CLKs with the ones from platform data */
@@ -161,8 +178,17 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
161 goto out; 178 goto out;
162 } 179 }
163 180
181 /* If we are in calibrator based fem auto detect - save fem nr */
182 if (wl->plt_mode == PLT_FEM_DETECT)
183 wl->fem_manuf = gp->tx_bip_fem_manufacturer;
184
164 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 185 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
165 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 186 answer == false ?
187 "manual" :
188 wl->plt_mode == PLT_FEM_DETECT ?
189 "calibrator_fem_detect" :
190 "auto",
191 gp->tx_bip_fem_manufacturer);
166 192
167out: 193out:
168 kfree(gen_parms); 194 kfree(gen_parms);
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 3d6c71b7a3c7..f429fc110cb0 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1339,6 +1339,14 @@ static int wl12xx_hw_init(struct wl1271 *wl)
1339 ret = wl128x_cmd_general_parms(wl); 1339 ret = wl128x_cmd_general_parms(wl);
1340 if (ret < 0) 1340 if (ret < 0)
1341 goto out; 1341 goto out;
1342
1343 /*
1344 * If we are in calibrator based auto detect then we got the FEM nr
1345 * in wl->fem_manuf. No need to continue further
1346 */
1347 if (wl->plt_mode == PLT_FEM_DETECT)
1348 goto out;
1349
1342 ret = wl128x_cmd_radio_parms(wl); 1350 ret = wl128x_cmd_radio_parms(wl);
1343 if (ret < 0) 1351 if (ret < 0)
1344 goto out; 1352 goto out;
@@ -1355,6 +1363,14 @@ static int wl12xx_hw_init(struct wl1271 *wl)
1355 ret = wl1271_cmd_general_parms(wl); 1363 ret = wl1271_cmd_general_parms(wl);
1356 if (ret < 0) 1364 if (ret < 0)
1357 goto out; 1365 goto out;
1366
1367 /*
1368 * If we are in calibrator based auto detect then we got the FEM nr
1369 * in wl->fem_manuf. No need to continue further
1370 */
1371 if (wl->plt_mode == PLT_FEM_DETECT)
1372 goto out;
1373
1358 ret = wl1271_cmd_radio_parms(wl); 1374 ret = wl1271_cmd_radio_parms(wl);
1359 if (ret < 0) 1375 if (ret < 0)
1360 goto out; 1376 goto out;
@@ -1500,6 +1516,13 @@ static int wl12xx_plt_init(struct wl1271 *wl)
1500 if (ret < 0) 1516 if (ret < 0)
1501 goto out_irq_disable; 1517 goto out_irq_disable;
1502 1518
1519 /*
1520 * If we are in calibrator based auto detect then we got the FEM nr
1521 * in wl->fem_manuf. No need to continue further
1522 */
1523 if (wl->plt_mode == PLT_FEM_DETECT)
1524 goto out;
1525
1503 ret = wl1271_acx_init_mem_config(wl); 1526 ret = wl1271_acx_init_mem_config(wl);
1504 if (ret < 0) 1527 if (ret < 0)
1505 goto out_irq_disable; 1528 goto out_irq_disable;
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index fac0b7e87e75..4d426cc20274 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -23,7 +23,7 @@
23#define __WL18XX_CONF_H__ 23#define __WL18XX_CONF_H__
24 24
25#define WL18XX_CONF_MAGIC 0x10e100ca 25#define WL18XX_CONF_MAGIC 0x10e100ca
26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0002) 26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0003)
27#define WL18XX_CONF_MASK 0x0000ffff 27#define WL18XX_CONF_MASK 0x0000ffff
28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ 28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
29 sizeof(struct wl18xx_priv_conf)) 29 sizeof(struct wl18xx_priv_conf))
@@ -84,7 +84,26 @@ struct wl18xx_mac_and_phy_params {
84 u8 padding[1]; 84 u8 padding[1];
85} __packed; 85} __packed;
86 86
87enum wl18xx_ht_mode {
88 /* Default - use MIMO, fallback to SISO20 */
89 HT_MODE_DEFAULT = 0,
90
91 /* Wide - use SISO40 */
92 HT_MODE_WIDE = 1,
93
94 /* Use SISO20 */
95 HT_MODE_SISO20 = 2,
96};
97
98struct wl18xx_ht_settings {
99 /* DEFAULT / WIDE / SISO20 */
100 u8 mode;
101} __packed;
102
87struct wl18xx_priv_conf { 103struct wl18xx_priv_conf {
104 /* Module params structures */
105 struct wl18xx_ht_settings ht;
106
88 /* this structure is copied wholesale to FW */ 107 /* this structure is copied wholesale to FW */
89 struct wl18xx_mac_and_phy_params phy; 108 struct wl18xx_mac_and_phy_params phy;
90} __packed; 109} __packed;
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c
index 0c06ccfd1b8c..f0abf3ef2c95 100644
--- a/drivers/net/wireless/ti/wl18xx/io.c
+++ b/drivers/net/wireless/ti/wl18xx/io.c
@@ -54,7 +54,7 @@ out:
54 54
55int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) 55int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
56{ 56{
57 u32 val; 57 u32 val = 0;
58 int ret; 58 int ret;
59 59
60 if (WARN_ON(addr % 2)) 60 if (WARN_ON(addr % 2))
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index b378b34c4a6a..69042bb9a097 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -43,8 +43,8 @@
43 43
44#define WL18XX_RX_CHECKSUM_MASK 0x40 44#define WL18XX_RX_CHECKSUM_MASK 0x40
45 45
46static char *ht_mode_param = "default"; 46static char *ht_mode_param = NULL;
47static char *board_type_param = "hdk"; 47static char *board_type_param = NULL;
48static bool checksum_param = false; 48static bool checksum_param = false;
49static bool enable_11a_param = true; 49static bool enable_11a_param = true;
50static int num_rx_desc_param = -1; 50static int num_rx_desc_param = -1;
@@ -494,16 +494,20 @@ static struct wlcore_conf wl18xx_conf = {
494}; 494};
495 495
496static struct wl18xx_priv_conf wl18xx_default_priv_conf = { 496static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
497 .ht = {
498 .mode = HT_MODE_DEFAULT,
499 },
497 .phy = { 500 .phy = {
498 .phy_standalone = 0x00, 501 .phy_standalone = 0x00,
499 .primary_clock_setting_time = 0x05, 502 .primary_clock_setting_time = 0x05,
500 .clock_valid_on_wake_up = 0x00, 503 .clock_valid_on_wake_up = 0x00,
501 .secondary_clock_setting_time = 0x05, 504 .secondary_clock_setting_time = 0x05,
505 .board_type = BOARD_TYPE_HDK_18XX,
502 .rdl = 0x01, 506 .rdl = 0x01,
503 .auto_detect = 0x00, 507 .auto_detect = 0x00,
504 .dedicated_fem = FEM_NONE, 508 .dedicated_fem = FEM_NONE,
505 .low_band_component = COMPONENT_2_WAY_SWITCH, 509 .low_band_component = COMPONENT_2_WAY_SWITCH,
506 .low_band_component_type = 0x05, 510 .low_band_component_type = 0x06,
507 .high_band_component = COMPONENT_2_WAY_SWITCH, 511 .high_band_component = COMPONENT_2_WAY_SWITCH,
508 .high_band_component_type = 0x09, 512 .high_band_component_type = 0x09,
509 .tcxo_ldo_voltage = 0x00, 513 .tcxo_ldo_voltage = 0x00,
@@ -772,16 +776,24 @@ out:
772static int wl18xx_set_mac_and_phy(struct wl1271 *wl) 776static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
773{ 777{
774 struct wl18xx_priv *priv = wl->priv; 778 struct wl18xx_priv *priv = wl->priv;
779 struct wl18xx_mac_and_phy_params *params;
775 int ret; 780 int ret;
776 781
782 params = kmemdup(&priv->conf.phy, sizeof(*params), GFP_KERNEL);
783 if (!params) {
784 ret = -ENOMEM;
785 goto out;
786 }
787
777 ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); 788 ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
778 if (ret < 0) 789 if (ret < 0)
779 goto out; 790 goto out;
780 791
781 ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, 792 ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, params,
782 sizeof(struct wl18xx_mac_and_phy_params), false); 793 sizeof(*params), false);
783 794
784out: 795out:
796 kfree(params);
785 return ret; 797 return ret;
786} 798}
787 799
@@ -1001,6 +1013,13 @@ static void wl18xx_set_rx_csum(struct wl1271 *wl,
1001 skb->ip_summed = CHECKSUM_UNNECESSARY; 1013 skb->ip_summed = CHECKSUM_UNNECESSARY;
1002} 1014}
1003 1015
1016static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
1017{
1018 struct wl18xx_priv *priv = wl->priv;
1019
1020 return priv->conf.phy.number_of_assembled_ant2_4 >= 2;
1021}
1022
1004/* 1023/*
1005 * TODO: instead of having these two functions to get the rate mask, 1024 * TODO: instead of having these two functions to get the rate mask,
1006 * we should modify the wlvif->rate_set instead 1025 * we should modify the wlvif->rate_set instead
@@ -1017,6 +1036,9 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1017 1036
1018 /* we don't support MIMO in wide-channel mode */ 1037 /* we don't support MIMO in wide-channel mode */
1019 hw_rate_set &= ~CONF_TX_MIMO_RATES; 1038 hw_rate_set &= ~CONF_TX_MIMO_RATES;
1039 } else if (wl18xx_is_mimo_supported(wl)) {
1040 wl1271_debug(DEBUG_ACX, "using MIMO channel rate mask");
1041 hw_rate_set |= CONF_TX_MIMO_RATES;
1020 } 1042 }
1021 1043
1022 return hw_rate_set; 1044 return hw_rate_set;
@@ -1025,8 +1047,6 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1025static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, 1047static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1026 struct wl12xx_vif *wlvif) 1048 struct wl12xx_vif *wlvif)
1027{ 1049{
1028 struct wl18xx_priv *priv = wl->priv;
1029
1030 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || 1050 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1031 wlvif->channel_type == NL80211_CHAN_HT40PLUS) { 1051 wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1032 wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); 1052 wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
@@ -1036,7 +1056,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1036 return 0; 1056 return 0;
1037 1057
1038 return CONF_TX_RATE_USE_WIDE_CHAN; 1058 return CONF_TX_RATE_USE_WIDE_CHAN;
1039 } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 && 1059 } else if (wl18xx_is_mimo_supported(wl) &&
1040 wlvif->band == IEEE80211_BAND_2GHZ) { 1060 wlvif->band == IEEE80211_BAND_2GHZ) {
1041 wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); 1061 wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
1042 /* 1062 /*
@@ -1136,6 +1156,12 @@ static int wl18xx_plt_init(struct wl1271 *wl)
1136{ 1156{
1137 int ret; 1157 int ret;
1138 1158
1159 /* calibrator based auto/fem detect not supported for 18xx */
1160 if (wl->plt_mode == PLT_FEM_DETECT) {
1161 wl1271_error("wl18xx_plt_init: PLT FEM_DETECT not supported");
1162 return -EINVAL;
1163 }
1164
1139 ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); 1165 ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
1140 if (ret < 0) 1166 if (ret < 0)
1141 return ret; 1167 return ret;
@@ -1383,27 +1409,44 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1383 if (ret < 0) 1409 if (ret < 0)
1384 goto out_free; 1410 goto out_free;
1385 1411
1386 if (!strcmp(board_type_param, "fpga")) { 1412 /* If the module param is set, update it in conf */
1387 priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX; 1413 if (board_type_param) {
1388 } else if (!strcmp(board_type_param, "hdk")) { 1414 if (!strcmp(board_type_param, "fpga")) {
1389 priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX; 1415 priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;
1390 /* HACK! Just for now we hardcode HDK to 0x06 */ 1416 } else if (!strcmp(board_type_param, "hdk")) {
1391 priv->conf.phy.low_band_component_type = 0x06; 1417 priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;
1392 } else if (!strcmp(board_type_param, "dvp")) { 1418 } else if (!strcmp(board_type_param, "dvp")) {
1393 priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX; 1419 priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;
1394 } else if (!strcmp(board_type_param, "evb")) { 1420 } else if (!strcmp(board_type_param, "evb")) {
1395 priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX; 1421 priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;
1396 } else if (!strcmp(board_type_param, "com8")) { 1422 } else if (!strcmp(board_type_param, "com8")) {
1397 priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX; 1423 priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;
1398 /* HACK! Just for now we hardcode COM8 to 0x06 */ 1424 } else {
1425 wl1271_error("invalid board type '%s'",
1426 board_type_param);
1427 ret = -EINVAL;
1428 goto out_free;
1429 }
1430 }
1431
1432 /* HACK! Just for now we hardcode COM8 and HDK to 0x06 */
1433 switch (priv->conf.phy.board_type) {
1434 case BOARD_TYPE_HDK_18XX:
1435 case BOARD_TYPE_COM8_18XX:
1399 priv->conf.phy.low_band_component_type = 0x06; 1436 priv->conf.phy.low_band_component_type = 0x06;
1400 } else { 1437 break;
1401 wl1271_error("invalid board type '%s'", board_type_param); 1438 case BOARD_TYPE_FPGA_18XX:
1439 case BOARD_TYPE_DVP_18XX:
1440 case BOARD_TYPE_EVB_18XX:
1441 priv->conf.phy.low_band_component_type = 0x05;
1442 break;
1443 default:
1444 wl1271_error("invalid board type '%d'",
1445 priv->conf.phy.board_type);
1402 ret = -EINVAL; 1446 ret = -EINVAL;
1403 goto out_free; 1447 goto out_free;
1404 } 1448 }
1405 1449
1406 /* If the module param is set, update it in conf */
1407 if (low_band_component_param != -1) 1450 if (low_band_component_param != -1)
1408 priv->conf.phy.low_band_component = low_band_component_param; 1451 priv->conf.phy.low_band_component = low_band_component_param;
1409 if (low_band_component_type_param != -1) 1452 if (low_band_component_type_param != -1)
@@ -1424,12 +1467,26 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1424 if (dc2dc_param != -1) 1467 if (dc2dc_param != -1)
1425 priv->conf.phy.external_pa_dc2dc = dc2dc_param; 1468 priv->conf.phy.external_pa_dc2dc = dc2dc_param;
1426 1469
1427 if (!strcmp(ht_mode_param, "default")) { 1470 if (ht_mode_param) {
1471 if (!strcmp(ht_mode_param, "default"))
1472 priv->conf.ht.mode = HT_MODE_DEFAULT;
1473 else if (!strcmp(ht_mode_param, "wide"))
1474 priv->conf.ht.mode = HT_MODE_WIDE;
1475 else if (!strcmp(ht_mode_param, "siso20"))
1476 priv->conf.ht.mode = HT_MODE_SISO20;
1477 else {
1478 wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1479 ret = -EINVAL;
1480 goto out_free;
1481 }
1482 }
1483
1484 if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
1428 /* 1485 /*
1429 * Only support mimo with multiple antennas. Fall back to 1486 * Only support mimo with multiple antennas. Fall back to
1430 * siso20. 1487 * siso20.
1431 */ 1488 */
1432 if (priv->conf.phy.number_of_assembled_ant2_4 >= 2) 1489 if (wl18xx_is_mimo_supported(wl))
1433 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1490 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1434 &wl18xx_mimo_ht_cap_2ghz); 1491 &wl18xx_mimo_ht_cap_2ghz);
1435 else 1492 else
@@ -1439,20 +1496,16 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1439 /* 5Ghz is always wide */ 1496 /* 5Ghz is always wide */
1440 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1497 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1441 &wl18xx_siso40_ht_cap_5ghz); 1498 &wl18xx_siso40_ht_cap_5ghz);
1442 } else if (!strcmp(ht_mode_param, "wide")) { 1499 } else if (priv->conf.ht.mode == HT_MODE_WIDE) {
1443 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1500 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1444 &wl18xx_siso40_ht_cap_2ghz); 1501 &wl18xx_siso40_ht_cap_2ghz);
1445 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1502 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1446 &wl18xx_siso40_ht_cap_5ghz); 1503 &wl18xx_siso40_ht_cap_5ghz);
1447 } else if (!strcmp(ht_mode_param, "siso20")) { 1504 } else if (priv->conf.ht.mode == HT_MODE_SISO20) {
1448 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1505 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1449 &wl18xx_siso20_ht_cap); 1506 &wl18xx_siso20_ht_cap);
1450 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1507 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1451 &wl18xx_siso20_ht_cap); 1508 &wl18xx_siso20_ht_cap);
1452 } else {
1453 wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1454 ret = -EINVAL;
1455 goto out_free;
1456 } 1509 }
1457 1510
1458 if (!checksum_param) { 1511 if (!checksum_param) {
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index a23949cdaebc..20e1bd923832 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -497,6 +497,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
497{ 497{
498 struct wl12xx_cmd_role_stop *cmd; 498 struct wl12xx_cmd_role_stop *cmd;
499 int ret; 499 int ret;
500 bool timeout = false;
500 501
501 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) 502 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID))
502 return -EINVAL; 503 return -EINVAL;
@@ -519,6 +520,17 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
519 goto out_free; 520 goto out_free;
520 } 521 }
521 522
523 /*
524 * Sometimes the firmware doesn't send this event, so we just
525 * time out without failing. Queue recovery for other
526 * failures.
527 */
528 ret = wl1271_cmd_wait_for_event_or_timeout(wl,
529 ROLE_STOP_COMPLETE_EVENT_ID,
530 &timeout);
531 if (ret)
532 wl12xx_queue_recovery_work(wl);
533
522 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); 534 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
523 535
524out_free: 536out_free:
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index d7d9f801e506..4ef0b095f0d6 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -192,7 +192,7 @@ enum cmd_templ {
192#define WL1271_COMMAND_TIMEOUT 2000 192#define WL1271_COMMAND_TIMEOUT 2000
193#define WL1271_CMD_TEMPL_DFLT_SIZE 252 193#define WL1271_CMD_TEMPL_DFLT_SIZE 252
194#define WL1271_CMD_TEMPL_MAX_SIZE 512 194#define WL1271_CMD_TEMPL_MAX_SIZE 512
195#define WL1271_EVENT_TIMEOUT 1000 195#define WL1271_EVENT_TIMEOUT 1500
196 196
197struct wl1271_cmd_header { 197struct wl1271_cmd_header {
198 __le16 id; 198 __le16 id;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 9f04b64dfa33..72548609f711 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1064,10 +1064,17 @@ out:
1064 return ret; 1064 return ret;
1065} 1065}
1066 1066
1067int wl1271_plt_start(struct wl1271 *wl) 1067int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)
1068{ 1068{
1069 int retries = WL1271_BOOT_RETRIES; 1069 int retries = WL1271_BOOT_RETRIES;
1070 struct wiphy *wiphy = wl->hw->wiphy; 1070 struct wiphy *wiphy = wl->hw->wiphy;
1071
1072 static const char* const PLT_MODE[] = {
1073 "PLT_OFF",
1074 "PLT_ON",
1075 "PLT_FEM_DETECT"
1076 };
1077
1071 int ret; 1078 int ret;
1072 1079
1073 mutex_lock(&wl->mutex); 1080 mutex_lock(&wl->mutex);
@@ -1081,6 +1088,10 @@ int wl1271_plt_start(struct wl1271 *wl)
1081 goto out; 1088 goto out;
1082 } 1089 }
1083 1090
1091 /* Indicate to lower levels that we are now in PLT mode */
1092 wl->plt = true;
1093 wl->plt_mode = plt_mode;
1094
1084 while (retries) { 1095 while (retries) {
1085 retries--; 1096 retries--;
1086 ret = wl12xx_chip_wakeup(wl, true); 1097 ret = wl12xx_chip_wakeup(wl, true);
@@ -1091,9 +1102,9 @@ int wl1271_plt_start(struct wl1271 *wl)
1091 if (ret < 0) 1102 if (ret < 0)
1092 goto power_off; 1103 goto power_off;
1093 1104
1094 wl->plt = true;
1095 wl->state = WL1271_STATE_ON; 1105 wl->state = WL1271_STATE_ON;
1096 wl1271_notice("firmware booted in PLT mode (%s)", 1106 wl1271_notice("firmware booted in PLT mode %s (%s)",
1107 PLT_MODE[plt_mode],
1097 wl->chip.fw_ver_str); 1108 wl->chip.fw_ver_str);
1098 1109
1099 /* update hw/fw version info in wiphy struct */ 1110 /* update hw/fw version info in wiphy struct */
@@ -1107,6 +1118,9 @@ power_off:
1107 wl1271_power_off(wl); 1118 wl1271_power_off(wl);
1108 } 1119 }
1109 1120
1121 wl->plt = false;
1122 wl->plt_mode = PLT_OFF;
1123
1110 wl1271_error("firmware boot in PLT mode failed despite %d retries", 1124 wl1271_error("firmware boot in PLT mode failed despite %d retries",
1111 WL1271_BOOT_RETRIES); 1125 WL1271_BOOT_RETRIES);
1112out: 1126out:
@@ -1159,6 +1173,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
1159 wl->sleep_auth = WL1271_PSM_ILLEGAL; 1173 wl->sleep_auth = WL1271_PSM_ILLEGAL;
1160 wl->state = WL1271_STATE_OFF; 1174 wl->state = WL1271_STATE_OFF;
1161 wl->plt = false; 1175 wl->plt = false;
1176 wl->plt_mode = PLT_OFF;
1162 wl->rx_counter = 0; 1177 wl->rx_counter = 0;
1163 mutex_unlock(&wl->mutex); 1178 mutex_unlock(&wl->mutex);
1164 1179
@@ -1585,6 +1600,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
1585 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) 1600 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
1586 goto out; 1601 goto out;
1587 1602
1603 if ((wl->conf.conn.suspend_wake_up_event ==
1604 wl->conf.conn.wake_up_event) &&
1605 (wl->conf.conn.suspend_listen_interval ==
1606 wl->conf.conn.listen_interval))
1607 goto out;
1608
1588 ret = wl1271_ps_elp_wakeup(wl); 1609 ret = wl1271_ps_elp_wakeup(wl);
1589 if (ret < 0) 1610 if (ret < 0)
1590 goto out; 1611 goto out;
@@ -1648,6 +1669,13 @@ static void wl1271_configure_resume(struct wl1271 *wl,
1648 if ((!is_ap) && (!is_sta)) 1669 if ((!is_ap) && (!is_sta))
1649 return; 1670 return;
1650 1671
1672 if (is_sta &&
1673 ((wl->conf.conn.suspend_wake_up_event ==
1674 wl->conf.conn.wake_up_event) &&
1675 (wl->conf.conn.suspend_listen_interval ==
1676 wl->conf.conn.listen_interval)))
1677 return;
1678
1651 ret = wl1271_ps_elp_wakeup(wl); 1679 ret = wl1271_ps_elp_wakeup(wl);
1652 if (ret < 0) 1680 if (ret < 0)
1653 return; 1681 return;
@@ -2364,7 +2392,14 @@ deinit:
2364 else 2392 else
2365 wl->sta_count--; 2393 wl->sta_count--;
2366 2394
2367 /* Last AP, have more stations. Configure according to STA. */ 2395 /*
2396 * Last AP, have more stations. Configure sleep auth according to STA.
2397 * Don't do thin on unintended recovery.
2398 */
2399 if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) &&
2400 !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags))
2401 goto unlock;
2402
2368 if (wl->ap_count == 0 && is_ap && wl->sta_count) { 2403 if (wl->ap_count == 0 && is_ap && wl->sta_count) {
2369 u8 sta_auth = wl->conf.conn.sta_sleep_auth; 2404 u8 sta_auth = wl->conf.conn.sta_sleep_auth;
2370 /* Configure for power according to debugfs */ 2405 /* Configure for power according to debugfs */
@@ -2378,6 +2413,7 @@ deinit:
2378 wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); 2413 wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
2379 } 2414 }
2380 2415
2416unlock:
2381 mutex_unlock(&wl->mutex); 2417 mutex_unlock(&wl->mutex);
2382 2418
2383 del_timer_sync(&wlvif->rx_streaming_timer); 2419 del_timer_sync(&wlvif->rx_streaming_timer);
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c
index d6f57e2c03cf..49e5ee1525c9 100644
--- a/drivers/net/wireless/ti/wlcore/testmode.c
+++ b/drivers/net/wireless/ti/wlcore/testmode.c
@@ -129,8 +129,12 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
129 goto out_sleep; 129 goto out_sleep;
130 } 130 }
131 131
132 if (nla_put(skb, WL1271_TM_ATTR_DATA, buf_len, buf)) 132 if (nla_put(skb, WL1271_TM_ATTR_DATA, buf_len, buf)) {
133 goto nla_put_failure; 133 kfree_skb(skb);
134 ret = -EMSGSIZE;
135 goto out_sleep;
136 }
137
134 ret = cfg80211_testmode_reply(skb); 138 ret = cfg80211_testmode_reply(skb);
135 if (ret < 0) 139 if (ret < 0)
136 goto out_sleep; 140 goto out_sleep;
@@ -142,11 +146,6 @@ out:
142 mutex_unlock(&wl->mutex); 146 mutex_unlock(&wl->mutex);
143 147
144 return ret; 148 return ret;
145
146nla_put_failure:
147 kfree_skb(skb);
148 ret = -EMSGSIZE;
149 goto out_sleep;
150} 149}
151 150
152static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) 151static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
@@ -192,8 +191,12 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
192 goto out_free; 191 goto out_free;
193 } 192 }
194 193
195 if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd)) 194 if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd)) {
196 goto nla_put_failure; 195 kfree_skb(skb);
196 ret = -EMSGSIZE;
197 goto out_free;
198 }
199
197 ret = cfg80211_testmode_reply(skb); 200 ret = cfg80211_testmode_reply(skb);
198 if (ret < 0) 201 if (ret < 0)
199 goto out_free; 202 goto out_free;
@@ -206,11 +209,6 @@ out:
206 mutex_unlock(&wl->mutex); 209 mutex_unlock(&wl->mutex);
207 210
208 return ret; 211 return ret;
209
210nla_put_failure:
211 kfree_skb(skb);
212 ret = -EMSGSIZE;
213 goto out_free;
214} 212}
215 213
216static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) 214static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
@@ -245,6 +243,43 @@ static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
245 return 0; 243 return 0;
246} 244}
247 245
246static int wl1271_tm_detect_fem(struct wl1271 *wl, struct nlattr *tb[])
247{
248 /* return FEM type */
249 int ret, len;
250 struct sk_buff *skb;
251
252 ret = wl1271_plt_start(wl, PLT_FEM_DETECT);
253 if (ret < 0)
254 goto out;
255
256 mutex_lock(&wl->mutex);
257
258 len = nla_total_size(sizeof(wl->fem_manuf));
259 skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
260 if (!skb) {
261 ret = -ENOMEM;
262 goto out_mutex;
263 }
264
265 if (nla_put(skb, WL1271_TM_ATTR_DATA, sizeof(wl->fem_manuf),
266 &wl->fem_manuf)) {
267 kfree_skb(skb);
268 ret = -EMSGSIZE;
269 goto out_mutex;
270 }
271
272 ret = cfg80211_testmode_reply(skb);
273
274out_mutex:
275 mutex_unlock(&wl->mutex);
276
277 /* We always stop plt after DETECT mode */
278 wl1271_plt_stop(wl);
279out:
280 return ret;
281}
282
248static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) 283static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
249{ 284{
250 u32 val; 285 u32 val;
@@ -258,11 +293,14 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
258 val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]); 293 val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
259 294
260 switch (val) { 295 switch (val) {
261 case 0: 296 case PLT_OFF:
262 ret = wl1271_plt_stop(wl); 297 ret = wl1271_plt_stop(wl);
263 break; 298 break;
264 case 1: 299 case PLT_ON:
265 ret = wl1271_plt_start(wl); 300 ret = wl1271_plt_start(wl, PLT_ON);
301 break;
302 case PLT_FEM_DETECT:
303 ret = wl1271_tm_detect_fem(wl, tb);
266 break; 304 break;
267 default: 305 default:
268 ret = -EINVAL; 306 ret = -EINVAL;
@@ -303,8 +341,12 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
303 goto out; 341 goto out;
304 } 342 }
305 343
306 if (nla_put(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr)) 344 if (nla_put(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr)) {
307 goto nla_put_failure; 345 kfree_skb(skb);
346 ret = -EMSGSIZE;
347 goto out;
348 }
349
308 ret = cfg80211_testmode_reply(skb); 350 ret = cfg80211_testmode_reply(skb);
309 if (ret < 0) 351 if (ret < 0)
310 goto out; 352 goto out;
@@ -312,11 +354,6 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
312out: 354out:
313 mutex_unlock(&wl->mutex); 355 mutex_unlock(&wl->mutex);
314 return ret; 356 return ret;
315
316nla_put_failure:
317 kfree_skb(skb);
318 ret = -EMSGSIZE;
319 goto out;
320} 357}
321 358
322int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) 359int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 8038a5026933..f0081f746482 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -306,22 +306,24 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
306 rate_idx = 0; 306 rate_idx = 0;
307 else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { 307 else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
308 /* 308 /*
309 * if the packets are destined for AP (have a STA entry) 309 * if the packets are data packets
310 * send them with AP rate policies (EAPOLs are an exception), 310 * send them with AP rate policies (EAPOLs are an exception),
311 * otherwise use default basic rates 311 * otherwise use default basic rates
312 */ 312 */
313 if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) 313 if (skb->protocol == cpu_to_be16(ETH_P_PAE))
314 rate_idx = wlvif->sta.p2p_rate_idx;
315 else if (skb->protocol == cpu_to_be16(ETH_P_PAE))
316 rate_idx = wlvif->sta.basic_rate_idx; 314 rate_idx = wlvif->sta.basic_rate_idx;
317 else if (control->control.sta) 315 else if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
316 rate_idx = wlvif->sta.p2p_rate_idx;
317 else if (ieee80211_is_data(frame_control))
318 rate_idx = wlvif->sta.ap_rate_idx; 318 rate_idx = wlvif->sta.ap_rate_idx;
319 else 319 else
320 rate_idx = wlvif->sta.basic_rate_idx; 320 rate_idx = wlvif->sta.basic_rate_idx;
321 } else { 321 } else {
322 if (hlid == wlvif->ap.global_hlid) 322 if (hlid == wlvif->ap.global_hlid)
323 rate_idx = wlvif->ap.mgmt_rate_idx; 323 rate_idx = wlvif->ap.mgmt_rate_idx;
324 else if (hlid == wlvif->ap.bcast_hlid) 324 else if (hlid == wlvif->ap.bcast_hlid ||
325 skb->protocol == cpu_to_be16(ETH_P_PAE))
326 /* send AP bcast and EAPOLs using the min basic rate */
325 rate_idx = wlvif->ap.bcast_rate_idx; 327 rate_idx = wlvif->ap.bcast_rate_idx;
326 else 328 else
327 rate_idx = wlvif->ap.ucast_rate_idx[ac]; 329 rate_idx = wlvif->ap.ucast_rate_idx[ac];
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 27ccc275a1c1..0ce7a8ebbd46 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -156,6 +156,8 @@ struct wl1271 {
156 enum wl1271_state state; 156 enum wl1271_state state;
157 enum wl12xx_fw_type fw_type; 157 enum wl12xx_fw_type fw_type;
158 bool plt; 158 bool plt;
159 enum plt_mode plt_mode;
160 u8 fem_manuf;
159 u8 last_vif_count; 161 u8 last_vif_count;
160 struct mutex mutex; 162 struct mutex mutex;
161 163
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 0187eef4fb07..c0505635bb00 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -293,6 +293,12 @@ enum rx_filter_action {
293 FILTER_FW_HANDLE = 2 293 FILTER_FW_HANDLE = 2
294}; 294};
295 295
296enum plt_mode {
297 PLT_OFF = 0,
298 PLT_ON = 1,
299 PLT_FEM_DETECT = 2,
300};
301
296struct wl12xx_rx_filter_field { 302struct wl12xx_rx_filter_field {
297 __le16 offset; 303 __le16 offset;
298 u8 len; 304 u8 len;
@@ -459,7 +465,7 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
459#define wl12xx_for_each_wlvif_ap(wl, wlvif) \ 465#define wl12xx_for_each_wlvif_ap(wl, wlvif) \
460 wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS) 466 wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS)
461 467
462int wl1271_plt_start(struct wl1271 *wl); 468int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode);
463int wl1271_plt_stop(struct wl1271 *wl); 469int wl1271_plt_stop(struct wl1271 *wl);
464int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); 470int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
465void wl12xx_queue_recovery_work(struct wl1271 *wl); 471void wl12xx_queue_recovery_work(struct wl1271 *wl);