diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-20 12:30:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-20 12:30:48 -0400 |
commit | 90b90f60c4f8e3a8525dfeb4aec46a9c7a29c857 (patch) | |
tree | 9b1d8ca6084012a02b302520bc26e5be65ba7b2a /drivers/net/wireless/ti | |
parent | 769162e38b91e1d300752e666260fa6c7b203fbc (diff) | |
parent | 36eb22e97a2b621fb707eead58ef915ab0f46e9e (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.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/main.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/conf.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/io.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 117 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/testmode.c | 85 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/tx.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 8 |
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 | ||
112 | out: | 125 | out: |
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 | ||
167 | out: | 193 | out: |
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 | ||
87 | enum 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 | |||
98 | struct wl18xx_ht_settings { | ||
99 | /* DEFAULT / WIDE / SISO20 */ | ||
100 | u8 mode; | ||
101 | } __packed; | ||
102 | |||
87 | struct wl18xx_priv_conf { | 103 | struct 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 | ||
55 | int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) | 55 | int 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 | ||
46 | static char *ht_mode_param = "default"; | 46 | static char *ht_mode_param = NULL; |
47 | static char *board_type_param = "hdk"; | 47 | static char *board_type_param = NULL; |
48 | static bool checksum_param = false; | 48 | static bool checksum_param = false; |
49 | static bool enable_11a_param = true; | 49 | static bool enable_11a_param = true; |
50 | static int num_rx_desc_param = -1; | 50 | static int num_rx_desc_param = -1; |
@@ -494,16 +494,20 @@ static struct wlcore_conf wl18xx_conf = { | |||
494 | }; | 494 | }; |
495 | 495 | ||
496 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 496 | static 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: | |||
772 | static int wl18xx_set_mac_and_phy(struct wl1271 *wl) | 776 | static 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 | ||
784 | out: | 795 | out: |
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 | ||
1016 | static 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, | |||
1025 | static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | 1047 | static 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 | ||
524 | out_free: | 536 | out_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 | ||
197 | struct wl1271_cmd_header { | 197 | struct 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 | ||
1067 | int wl1271_plt_start(struct wl1271 *wl) | 1067 | int 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); |
1112 | out: | 1126 | out: |
@@ -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 | ||
2416 | unlock: | ||
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 | |||
146 | nla_put_failure: | ||
147 | kfree_skb(skb); | ||
148 | ret = -EMSGSIZE; | ||
149 | goto out_sleep; | ||
150 | } | 149 | } |
151 | 150 | ||
152 | static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) | 151 | static 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 | |||
210 | nla_put_failure: | ||
211 | kfree_skb(skb); | ||
212 | ret = -EMSGSIZE; | ||
213 | goto out_free; | ||
214 | } | 212 | } |
215 | 213 | ||
216 | static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) | 214 | static 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 | ||
246 | static 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 | |||
274 | out_mutex: | ||
275 | mutex_unlock(&wl->mutex); | ||
276 | |||
277 | /* We always stop plt after DETECT mode */ | ||
278 | wl1271_plt_stop(wl); | ||
279 | out: | ||
280 | return ret; | ||
281 | } | ||
282 | |||
248 | static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) | 283 | static 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[]) | |||
312 | out: | 354 | out: |
313 | mutex_unlock(&wl->mutex); | 355 | mutex_unlock(&wl->mutex); |
314 | return ret; | 356 | return ret; |
315 | |||
316 | nla_put_failure: | ||
317 | kfree_skb(skb); | ||
318 | ret = -EMSGSIZE; | ||
319 | goto out; | ||
320 | } | 357 | } |
321 | 358 | ||
322 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) | 359 | int 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 | ||
296 | enum plt_mode { | ||
297 | PLT_OFF = 0, | ||
298 | PLT_ON = 1, | ||
299 | PLT_FEM_DETECT = 2, | ||
300 | }; | ||
301 | |||
296 | struct wl12xx_rx_filter_field { | 302 | struct 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 | ||
462 | int wl1271_plt_start(struct wl1271 *wl); | 468 | int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode); |
463 | int wl1271_plt_stop(struct wl1271 *wl); | 469 | int wl1271_plt_stop(struct wl1271 *wl); |
464 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 470 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
465 | void wl12xx_queue_recovery_work(struct wl1271 *wl); | 471 | void wl12xx_queue_recovery_work(struct wl1271 *wl); |