diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
commit | 5c01d5669356e13f0fb468944c1dd4c6a7e978ad (patch) | |
tree | fa43345288d7b25fac92b3b35360a177c4947313 /drivers/net/wireless/wl12xx | |
parent | fea069152614cdeefba4b2bf80afcddb9c217fc8 (diff) | |
parent | a5e944f1d955f3819503348426763e21e0413ba6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/wl12xx/wl1271_main.c
Diffstat (limited to 'drivers/net/wireless/wl12xx')
21 files changed, 912 insertions, 401 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 56b78e4b0198..4d479708158d 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -202,8 +202,8 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
202 | goto out; | 202 | goto out; |
203 | } | 203 | } |
204 | 204 | ||
205 | /* No NVS from netlink, try to get it from the filesystem */ | 205 | if (wl->nvs == NULL && !wl->use_eeprom) { |
206 | if (wl->nvs == NULL) { | 206 | /* No NVS from netlink, try to get it from the filesystem */ |
207 | ret = wl1251_fetch_nvs(wl); | 207 | ret = wl1251_fetch_nvs(wl); |
208 | if (ret < 0) | 208 | if (ret < 0) |
209 | goto out; | 209 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 3bfb59bd4635..e81474203a23 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -310,7 +310,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) | |||
310 | 310 | ||
311 | static struct spi_driver wl1251_spi_driver = { | 311 | static struct spi_driver wl1251_spi_driver = { |
312 | .driver = { | 312 | .driver = { |
313 | .name = "wl1251", | 313 | .name = DRIVER_NAME, |
314 | .bus = &spi_bus_type, | 314 | .bus = &spi_bus_type, |
315 | .owner = THIS_MODULE, | 315 | .owner = THIS_MODULE, |
316 | }, | 316 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 8f11506f8310..75887e74205b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -55,6 +55,7 @@ enum { | |||
55 | DEBUG_ACX = BIT(13), | 55 | DEBUG_ACX = BIT(13), |
56 | DEBUG_SDIO = BIT(14), | 56 | DEBUG_SDIO = BIT(14), |
57 | DEBUG_FILTERS = BIT(15), | 57 | DEBUG_FILTERS = BIT(15), |
58 | DEBUG_ADHOC = BIT(16), | ||
58 | DEBUG_ALL = ~0, | 59 | DEBUG_ALL = ~0, |
59 | }; | 60 | }; |
60 | 61 | ||
@@ -147,14 +148,7 @@ struct wl1271_nvs_file { | |||
147 | */ | 148 | */ |
148 | #undef WL1271_80211A_ENABLED | 149 | #undef WL1271_80211A_ENABLED |
149 | 150 | ||
150 | /* | 151 | #define WL1271_BUSY_WORD_CNT 1 |
151 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
152 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
153 | * with this mode occasionally on boot, so lets have three for now. A value of | ||
154 | * three should make sure, that the chipset will always be ready, though this | ||
155 | * will impact throughput and latencies slightly. | ||
156 | */ | ||
157 | #define WL1271_BUSY_WORD_CNT 3 | ||
158 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 152 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
159 | 153 | ||
160 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 154 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
@@ -380,6 +374,7 @@ struct wl1271 { | |||
380 | #define WL1271_FLAG_PSM_REQUESTED (8) | 374 | #define WL1271_FLAG_PSM_REQUESTED (8) |
381 | #define WL1271_FLAG_IRQ_PENDING (9) | 375 | #define WL1271_FLAG_IRQ_PENDING (9) |
382 | #define WL1271_FLAG_IRQ_RUNNING (10) | 376 | #define WL1271_FLAG_IRQ_RUNNING (10) |
377 | #define WL1271_FLAG_IDLE (11) | ||
383 | unsigned long flags; | 378 | unsigned long flags; |
384 | 379 | ||
385 | struct wl1271_partition_set part; | 380 | struct wl1271_partition_set part; |
@@ -396,6 +391,7 @@ struct wl1271 { | |||
396 | u8 bssid[ETH_ALEN]; | 391 | u8 bssid[ETH_ALEN]; |
397 | u8 mac_addr[ETH_ALEN]; | 392 | u8 mac_addr[ETH_ALEN]; |
398 | u8 bss_type; | 393 | u8 bss_type; |
394 | u8 set_bss_type; | ||
399 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | 395 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; |
400 | u8 ssid_len; | 396 | u8 ssid_len; |
401 | int channel; | 397 | int channel; |
@@ -452,11 +448,15 @@ struct wl1271 { | |||
452 | /* currently configured rate set */ | 448 | /* currently configured rate set */ |
453 | u32 sta_rate_set; | 449 | u32 sta_rate_set; |
454 | u32 basic_rate_set; | 450 | u32 basic_rate_set; |
451 | u32 basic_rate; | ||
455 | u32 rate_set; | 452 | u32 rate_set; |
456 | 453 | ||
457 | /* The current band */ | 454 | /* The current band */ |
458 | enum ieee80211_band band; | 455 | enum ieee80211_band band; |
459 | 456 | ||
457 | /* Beaconing interval (needed for ad-hoc) */ | ||
458 | u32 beacon_int; | ||
459 | |||
460 | /* Default key (for WEP) */ | 460 | /* Default key (for WEP) */ |
461 | u32 default_key; | 461 | u32 default_key; |
462 | 462 | ||
@@ -473,6 +473,9 @@ struct wl1271 { | |||
473 | /* in dBm */ | 473 | /* in dBm */ |
474 | int power_level; | 474 | int power_level; |
475 | 475 | ||
476 | int rssi_thold; | ||
477 | int last_rssi_event; | ||
478 | |||
476 | struct wl1271_stats stats; | 479 | struct wl1271_stats stats; |
477 | struct wl1271_debugfs debugfs; | 480 | struct wl1271_debugfs debugfs; |
478 | 481 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index adaa3f2485c3..2ad086efe06e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -505,12 +505,17 @@ out: | |||
505 | return ret; | 505 | return ret; |
506 | } | 506 | } |
507 | 507 | ||
508 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | 508 | #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff |
509 | |||
510 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) | ||
509 | { | 511 | { |
510 | struct acx_conn_monit_params *acx; | 512 | struct acx_conn_monit_params *acx; |
513 | u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; | ||
514 | u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE; | ||
511 | int ret; | 515 | int ret; |
512 | 516 | ||
513 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | 517 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s", |
518 | enable ? "enabled" : "disabled"); | ||
514 | 519 | ||
515 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 520 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
516 | if (!acx) { | 521 | if (!acx) { |
@@ -518,8 +523,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl) | |||
518 | goto out; | 523 | goto out; |
519 | } | 524 | } |
520 | 525 | ||
521 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | 526 | if (enable) { |
522 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | 527 | threshold = wl->conf.conn.synch_fail_thold; |
528 | timeout = wl->conf.conn.bss_lose_timeout; | ||
529 | } | ||
530 | |||
531 | acx->synch_fail_thold = cpu_to_le32(threshold); | ||
532 | acx->bss_lose_timeout = cpu_to_le32(timeout); | ||
523 | 533 | ||
524 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | 534 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, |
525 | acx, sizeof(*acx)); | 535 | acx, sizeof(*acx)); |
@@ -793,7 +803,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
793 | 803 | ||
794 | /* configure one basic rate class */ | 804 | /* configure one basic rate class */ |
795 | idx = ACX_TX_BASIC_RATE; | 805 | idx = ACX_TX_BASIC_RATE; |
796 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); | 806 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); |
797 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | 807 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
798 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | 808 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
799 | acx->rate_class[idx].aflags = c->aflags; | 809 | acx->rate_class[idx].aflags = c->aflags; |
@@ -1130,3 +1140,129 @@ out: | |||
1130 | kfree(acx); | 1140 | kfree(acx); |
1131 | return ret; | 1141 | return ret; |
1132 | } | 1142 | } |
1143 | |||
1144 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) | ||
1145 | { | ||
1146 | struct wl1271_acx_keep_alive_mode *acx = NULL; | ||
1147 | int ret = 0; | ||
1148 | |||
1149 | wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); | ||
1150 | |||
1151 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1152 | if (!acx) { | ||
1153 | ret = -ENOMEM; | ||
1154 | goto out; | ||
1155 | } | ||
1156 | |||
1157 | acx->enabled = enable; | ||
1158 | |||
1159 | ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); | ||
1160 | if (ret < 0) { | ||
1161 | wl1271_warning("acx keep alive mode failed: %d", ret); | ||
1162 | goto out; | ||
1163 | } | ||
1164 | |||
1165 | out: | ||
1166 | kfree(acx); | ||
1167 | return ret; | ||
1168 | } | ||
1169 | |||
1170 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) | ||
1171 | { | ||
1172 | struct wl1271_acx_keep_alive_config *acx = NULL; | ||
1173 | int ret = 0; | ||
1174 | |||
1175 | wl1271_debug(DEBUG_ACX, "acx keep alive config"); | ||
1176 | |||
1177 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1178 | if (!acx) { | ||
1179 | ret = -ENOMEM; | ||
1180 | goto out; | ||
1181 | } | ||
1182 | |||
1183 | acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); | ||
1184 | acx->index = index; | ||
1185 | acx->tpl_validation = tpl_valid; | ||
1186 | acx->trigger = ACX_KEEP_ALIVE_NO_TX; | ||
1187 | |||
1188 | ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, | ||
1189 | acx, sizeof(*acx)); | ||
1190 | if (ret < 0) { | ||
1191 | wl1271_warning("acx keep alive config failed: %d", ret); | ||
1192 | goto out; | ||
1193 | } | ||
1194 | |||
1195 | out: | ||
1196 | kfree(acx); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1201 | s16 thold, u8 hyst) | ||
1202 | { | ||
1203 | struct wl1271_acx_rssi_snr_trigger *acx = NULL; | ||
1204 | int ret = 0; | ||
1205 | |||
1206 | wl1271_debug(DEBUG_ACX, "acx rssi snr trigger"); | ||
1207 | |||
1208 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1209 | if (!acx) { | ||
1210 | ret = -ENOMEM; | ||
1211 | goto out; | ||
1212 | } | ||
1213 | |||
1214 | wl->last_rssi_event = -1; | ||
1215 | |||
1216 | acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); | ||
1217 | acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; | ||
1218 | acx->type = WL1271_ACX_TRIG_TYPE_EDGE; | ||
1219 | if (enable) | ||
1220 | acx->enable = WL1271_ACX_TRIG_ENABLE; | ||
1221 | else | ||
1222 | acx->enable = WL1271_ACX_TRIG_DISABLE; | ||
1223 | |||
1224 | acx->index = WL1271_ACX_TRIG_IDX_RSSI; | ||
1225 | acx->dir = WL1271_ACX_TRIG_DIR_BIDIR; | ||
1226 | acx->threshold = cpu_to_le16(thold); | ||
1227 | acx->hysteresis = hyst; | ||
1228 | |||
1229 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx)); | ||
1230 | if (ret < 0) { | ||
1231 | wl1271_warning("acx rssi snr trigger setting failed: %d", ret); | ||
1232 | goto out; | ||
1233 | } | ||
1234 | |||
1235 | out: | ||
1236 | kfree(acx); | ||
1237 | return ret; | ||
1238 | } | ||
1239 | |||
1240 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) | ||
1241 | { | ||
1242 | struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; | ||
1243 | struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; | ||
1244 | int ret = 0; | ||
1245 | |||
1246 | wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights"); | ||
1247 | |||
1248 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1249 | if (!acx) { | ||
1250 | ret = -ENOMEM; | ||
1251 | goto out; | ||
1252 | } | ||
1253 | |||
1254 | acx->rssi_beacon = c->avg_weight_rssi_beacon; | ||
1255 | acx->rssi_data = c->avg_weight_rssi_data; | ||
1256 | acx->snr_beacon = c->avg_weight_snr_beacon; | ||
1257 | acx->snr_data = c->avg_weight_snr_data; | ||
1258 | |||
1259 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx)); | ||
1260 | if (ret < 0) { | ||
1261 | wl1271_warning("acx rssi snr trigger weights failed: %d", ret); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | |||
1265 | out: | ||
1266 | kfree(acx); | ||
1267 | return ret; | ||
1268 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 8e5870fa9609..420e7e2fc021 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -915,6 +915,84 @@ struct wl1271_acx_pm_config { | |||
915 | u8 padding[3]; | 915 | u8 padding[3]; |
916 | } __attribute__ ((packed)); | 916 | } __attribute__ ((packed)); |
917 | 917 | ||
918 | struct wl1271_acx_keep_alive_mode { | ||
919 | struct acx_header header; | ||
920 | |||
921 | u8 enabled; | ||
922 | u8 padding[3]; | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | enum { | ||
926 | ACX_KEEP_ALIVE_NO_TX = 0, | ||
927 | ACX_KEEP_ALIVE_PERIOD_ONLY | ||
928 | }; | ||
929 | |||
930 | enum { | ||
931 | ACX_KEEP_ALIVE_TPL_INVALID = 0, | ||
932 | ACX_KEEP_ALIVE_TPL_VALID | ||
933 | }; | ||
934 | |||
935 | struct wl1271_acx_keep_alive_config { | ||
936 | struct acx_header header; | ||
937 | |||
938 | __le32 period; | ||
939 | u8 index; | ||
940 | u8 tpl_validation; | ||
941 | u8 trigger; | ||
942 | u8 padding; | ||
943 | } __attribute__ ((packed)); | ||
944 | |||
945 | enum { | ||
946 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, | ||
947 | WL1271_ACX_TRIG_TYPE_EDGE, | ||
948 | }; | ||
949 | |||
950 | enum { | ||
951 | WL1271_ACX_TRIG_DIR_LOW = 0, | ||
952 | WL1271_ACX_TRIG_DIR_HIGH, | ||
953 | WL1271_ACX_TRIG_DIR_BIDIR, | ||
954 | }; | ||
955 | |||
956 | enum { | ||
957 | WL1271_ACX_TRIG_ENABLE = 1, | ||
958 | WL1271_ACX_TRIG_DISABLE, | ||
959 | }; | ||
960 | |||
961 | enum { | ||
962 | WL1271_ACX_TRIG_METRIC_RSSI_BEACON = 0, | ||
963 | WL1271_ACX_TRIG_METRIC_RSSI_DATA, | ||
964 | WL1271_ACX_TRIG_METRIC_SNR_BEACON, | ||
965 | WL1271_ACX_TRIG_METRIC_SNR_DATA, | ||
966 | }; | ||
967 | |||
968 | enum { | ||
969 | WL1271_ACX_TRIG_IDX_RSSI = 0, | ||
970 | WL1271_ACX_TRIG_COUNT = 8, | ||
971 | }; | ||
972 | |||
973 | struct wl1271_acx_rssi_snr_trigger { | ||
974 | struct acx_header header; | ||
975 | |||
976 | __le16 threshold; | ||
977 | __le16 pacing; /* 0 - 60000 ms */ | ||
978 | u8 metric; | ||
979 | u8 type; | ||
980 | u8 dir; | ||
981 | u8 hysteresis; | ||
982 | u8 index; | ||
983 | u8 enable; | ||
984 | u8 padding[2]; | ||
985 | }; | ||
986 | |||
987 | struct wl1271_acx_rssi_snr_avg_weights { | ||
988 | struct acx_header header; | ||
989 | |||
990 | u8 rssi_beacon; | ||
991 | u8 rssi_data; | ||
992 | u8 snr_beacon; | ||
993 | u8 snr_data; | ||
994 | }; | ||
995 | |||
918 | enum { | 996 | enum { |
919 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 997 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
920 | ACX_MEM_CFG = 0x0003, | 998 | ACX_MEM_CFG = 0x0003, |
@@ -963,8 +1041,8 @@ enum { | |||
963 | ACX_FRAG_CFG = 0x004F, | 1041 | ACX_FRAG_CFG = 0x004F, |
964 | ACX_BET_ENABLE = 0x0050, | 1042 | ACX_BET_ENABLE = 0x0050, |
965 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 1043 | ACX_RSSI_SNR_TRIGGER = 0x0051, |
966 | ACX_RSSI_SNR_WEIGHTS = 0x0051, | 1044 | ACX_RSSI_SNR_WEIGHTS = 0x0052, |
967 | ACX_KEEP_ALIVE_MODE = 0x0052, | 1045 | ACX_KEEP_ALIVE_MODE = 0x0053, |
968 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1046 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
969 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 1047 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, |
970 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 1048 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, |
@@ -1004,7 +1082,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | |||
1004 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1082 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1005 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1083 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1006 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1084 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1007 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1085 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1008 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); | 1086 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1009 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1087 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1010 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1088 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
@@ -1031,5 +1109,10 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | |||
1031 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1109 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1032 | u8 version); | 1110 | u8 version); |
1033 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1111 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1112 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | ||
1113 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | ||
1114 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1115 | s16 thold, u8 hyst); | ||
1116 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); | ||
1034 | 1117 | ||
1035 | #endif /* __WL1271_ACX_H__ */ | 1118 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 1937859d74eb..8087dc17f29d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -411,7 +411,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
411 | /* unmask required mbox events */ | 411 | /* unmask required mbox events */ |
412 | wl->event_mask = BSS_LOSE_EVENT_ID | | 412 | wl->event_mask = BSS_LOSE_EVENT_ID | |
413 | SCAN_COMPLETE_EVENT_ID | | 413 | SCAN_COMPLETE_EVENT_ID | |
414 | PS_REPORT_EVENT_ID; | 414 | PS_REPORT_EVENT_ID | |
415 | JOIN_EVENT_COMPLETE_ID | | ||
416 | DISCONNECT_EVENT_COMPLETE_ID | | ||
417 | RSSI_SNR_TRIGGER_0_EVENT_ID; | ||
415 | 418 | ||
416 | ret = wl1271_event_unmask(wl); | 419 | ret = wl1271_event_unmask(wl); |
417 | if (ret < 0) { | 420 | if (ret < 0) { |
@@ -452,11 +455,15 @@ int wl1271_boot(struct wl1271 *wl) | |||
452 | 455 | ||
453 | if (REF_CLOCK != 0) { | 456 | if (REF_CLOCK != 0) { |
454 | u16 val; | 457 | u16 val; |
455 | /* Set clock type */ | 458 | /* Set clock type (open drain) */ |
456 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 459 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
457 | val &= FREF_CLK_TYPE_BITS; | 460 | val &= FREF_CLK_TYPE_BITS; |
458 | val |= CLK_REQ_PRCM; | ||
459 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 461 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
462 | |||
463 | /* Set clock pull mode (no pull) */ | ||
464 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
465 | val |= NO_PULL; | ||
466 | wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
460 | } else { | 467 | } else { |
461 | u16 val; | 468 | u16 val; |
462 | /* Set clock polarity */ | 469 | /* Set clock polarity */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 412443ee655a..95ecc5241959 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -53,10 +53,13 @@ struct wl1271_static_data { | |||
53 | #define OCP_REG_POLARITY 0x0064 | 53 | #define OCP_REG_POLARITY 0x0064 |
54 | #define OCP_REG_CLK_TYPE 0x0448 | 54 | #define OCP_REG_CLK_TYPE 0x0448 |
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
56 | 57 | ||
57 | #define CMD_MBOX_ADDRESS 0x407B4 | ||
58 | 58 | ||
59 | #define POLARITY_LOW BIT(1) | 59 | #define CMD_MBOX_ADDRESS 0x407B4 |
60 | |||
61 | #define POLARITY_LOW BIT(1) | ||
62 | #define NO_PULL (BIT(14) | BIT(15)) | ||
60 | 63 | ||
61 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | 64 | #define FREF_CLK_TYPE_BITS 0xfffffe7f |
62 | #define CLK_REQ_PRCM 0x100 | 65 | #define CLK_REQ_PRCM 0x100 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 92254d0d6c4c..6b5ba8ec94c9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -35,6 +35,9 @@ | |||
35 | #include "wl1271_acx.h" | 35 | #include "wl1271_acx.h" |
36 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
37 | #include "wl1271_cmd.h" | 37 | #include "wl1271_cmd.h" |
38 | #include "wl1271_event.h" | ||
39 | |||
40 | #define WL1271_CMD_POLL_COUNT 5 | ||
38 | 41 | ||
39 | /* | 42 | /* |
40 | * send command to firmware | 43 | * send command to firmware |
@@ -52,6 +55,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
52 | u32 intr; | 55 | u32 intr; |
53 | int ret = 0; | 56 | int ret = 0; |
54 | u16 status; | 57 | u16 status; |
58 | u16 poll_count = 0; | ||
55 | 59 | ||
56 | cmd = buf; | 60 | cmd = buf; |
57 | cmd->id = cpu_to_le16(id); | 61 | cmd->id = cpu_to_le16(id); |
@@ -73,7 +77,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
73 | goto out; | 77 | goto out; |
74 | } | 78 | } |
75 | 79 | ||
76 | msleep(1); | 80 | udelay(10); |
81 | poll_count++; | ||
82 | if (poll_count == WL1271_CMD_POLL_COUNT) | ||
83 | wl1271_info("cmd polling took over %d cycles", | ||
84 | poll_count); | ||
77 | 85 | ||
78 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 86 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
79 | } | 87 | } |
@@ -249,6 +257,35 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
249 | return ret; | 257 | return ret; |
250 | } | 258 | } |
251 | 259 | ||
260 | /* | ||
261 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
262 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | ||
263 | */ | ||
264 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
265 | { | ||
266 | u32 events_vector, event; | ||
267 | unsigned long timeout; | ||
268 | |||
269 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | ||
270 | |||
271 | do { | ||
272 | if (time_after(jiffies, timeout)) | ||
273 | return -ETIMEDOUT; | ||
274 | |||
275 | msleep(1); | ||
276 | |||
277 | /* read from both event fields */ | ||
278 | wl1271_read(wl, wl->mbox_ptr[0], &events_vector, | ||
279 | sizeof(events_vector), false); | ||
280 | event = events_vector & mask; | ||
281 | wl1271_read(wl, wl->mbox_ptr[1], &events_vector, | ||
282 | sizeof(events_vector), false); | ||
283 | event |= events_vector & mask; | ||
284 | } while (!event); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
252 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | 289 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) |
253 | { | 290 | { |
254 | static bool do_cal = true; | 291 | static bool do_cal = true; |
@@ -281,20 +318,12 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
281 | join->rx_config_options = cpu_to_le32(wl->rx_config); | 318 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
282 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); | 319 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
283 | join->bss_type = bss_type; | 320 | join->bss_type = bss_type; |
321 | join->basic_rate_set = wl->basic_rate_set; | ||
284 | 322 | ||
285 | if (wl->band == IEEE80211_BAND_2GHZ) | 323 | if (wl->band == IEEE80211_BAND_5GHZ) |
286 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | ||
287 | CONF_HW_BIT_RATE_2MBPS | | ||
288 | CONF_HW_BIT_RATE_5_5MBPS | | ||
289 | CONF_HW_BIT_RATE_11MBPS); | ||
290 | else { | ||
291 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | 324 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; |
292 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | | ||
293 | CONF_HW_BIT_RATE_12MBPS | | ||
294 | CONF_HW_BIT_RATE_24MBPS); | ||
295 | } | ||
296 | 325 | ||
297 | join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); | 326 | join->beacon_interval = cpu_to_le16(wl->beacon_int); |
298 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | 327 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; |
299 | 328 | ||
300 | join->channel = wl->channel; | 329 | join->channel = wl->channel; |
@@ -319,11 +348,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
319 | goto out_free; | 348 | goto out_free; |
320 | } | 349 | } |
321 | 350 | ||
322 | /* | 351 | ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); |
323 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 352 | if (ret < 0) |
324 | * simplify locking we just sleep instead, for now | 353 | wl1271_error("cmd join event completion error"); |
325 | */ | ||
326 | msleep(10); | ||
327 | 354 | ||
328 | out_free: | 355 | out_free: |
329 | kfree(join); | 356 | kfree(join); |
@@ -455,7 +482,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) | |||
455 | if (ret < 0) { | 482 | if (ret < 0) { |
456 | wl1271_error("tx %s cmd for channel %d failed", | 483 | wl1271_error("tx %s cmd for channel %d failed", |
457 | enable ? "start" : "stop", cmd->channel); | 484 | enable ? "start" : "stop", cmd->channel); |
458 | return ret; | 485 | goto out; |
459 | } | 486 | } |
460 | 487 | ||
461 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 488 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
@@ -547,17 +574,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
547 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 574 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
548 | struct wl1271_cmd_scan *params = NULL; | 575 | struct wl1271_cmd_scan *params = NULL; |
549 | struct ieee80211_channel *channels; | 576 | struct ieee80211_channel *channels; |
577 | u32 rate; | ||
550 | int i, j, n_ch, ret; | 578 | int i, j, n_ch, ret; |
551 | u16 scan_options = 0; | 579 | u16 scan_options = 0; |
552 | u8 ieee_band; | 580 | u8 ieee_band; |
553 | 581 | ||
554 | if (band == WL1271_SCAN_BAND_2_4_GHZ) | 582 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { |
555 | ieee_band = IEEE80211_BAND_2GHZ; | 583 | ieee_band = IEEE80211_BAND_2GHZ; |
556 | else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) | 584 | rate = wl->conf.tx.basic_rate; |
585 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
557 | ieee_band = IEEE80211_BAND_2GHZ; | 586 | ieee_band = IEEE80211_BAND_2GHZ; |
558 | else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) | 587 | rate = wl->conf.tx.basic_rate; |
588 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
559 | ieee_band = IEEE80211_BAND_5GHZ; | 589 | ieee_band = IEEE80211_BAND_5GHZ; |
560 | else | 590 | rate = wl->conf.tx.basic_rate_5; |
591 | } else | ||
561 | return -EINVAL; | 592 | return -EINVAL; |
562 | 593 | ||
563 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | 594 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) |
@@ -584,8 +615,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
584 | params->params.scan_options = cpu_to_le16(scan_options); | 615 | params->params.scan_options = cpu_to_le16(scan_options); |
585 | 616 | ||
586 | params->params.num_probe_requests = probe_requests; | 617 | params->params.num_probe_requests = probe_requests; |
587 | /* Let the fw autodetect suitable tx_rate for probes */ | 618 | params->params.tx_rate = rate; |
588 | params->params.tx_rate = 0; | ||
589 | params->params.tid_trigger = 0; | 619 | params->params.tid_trigger = 0; |
590 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 620 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
591 | 621 | ||
@@ -666,11 +696,12 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
666 | 696 | ||
667 | out: | 697 | out: |
668 | kfree(params); | 698 | kfree(params); |
699 | kfree(trigger); | ||
669 | return ret; | 700 | return ret; |
670 | } | 701 | } |
671 | 702 | ||
672 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 703 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
673 | void *buf, size_t buf_len) | 704 | void *buf, size_t buf_len, int index, u32 rates) |
674 | { | 705 | { |
675 | struct wl1271_cmd_template_set *cmd; | 706 | struct wl1271_cmd_template_set *cmd; |
676 | int ret = 0; | 707 | int ret = 0; |
@@ -688,9 +719,10 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
688 | 719 | ||
689 | cmd->len = cpu_to_le16(buf_len); | 720 | cmd->len = cpu_to_le16(buf_len); |
690 | cmd->template_type = template_id; | 721 | cmd->template_type = template_id; |
691 | cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); | 722 | cmd->enabled_rates = cpu_to_le32(rates); |
692 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; | 723 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; |
693 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; | 724 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; |
725 | cmd->index = index; | ||
694 | 726 | ||
695 | if (buf) | 727 | if (buf) |
696 | memcpy(cmd->template_data, buf, buf_len); | 728 | memcpy(cmd->template_data, buf, buf_len); |
@@ -727,7 +759,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) | |||
727 | ptr = skb->data; | 759 | ptr = skb->data; |
728 | } | 760 | } |
729 | 761 | ||
730 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size); | 762 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
763 | WL1271_RATE_AUTOMATIC); | ||
731 | 764 | ||
732 | out: | 765 | out: |
733 | dev_kfree_skb(skb); | 766 | dev_kfree_skb(skb); |
@@ -738,6 +771,29 @@ out: | |||
738 | 771 | ||
739 | } | 772 | } |
740 | 773 | ||
774 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) | ||
775 | { | ||
776 | struct sk_buff *skb = NULL; | ||
777 | int ret = -ENOMEM; | ||
778 | |||
779 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | ||
780 | if (!skb) | ||
781 | goto out; | ||
782 | |||
783 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, | ||
784 | skb->data, skb->len, | ||
785 | CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
786 | WL1271_RATE_AUTOMATIC); | ||
787 | |||
788 | out: | ||
789 | dev_kfree_skb(skb); | ||
790 | if (ret) | ||
791 | wl1271_warning("cmd build klv null data failed %d", ret); | ||
792 | |||
793 | return ret; | ||
794 | |||
795 | } | ||
796 | |||
741 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 797 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) |
742 | { | 798 | { |
743 | struct sk_buff *skb; | 799 | struct sk_buff *skb; |
@@ -748,7 +804,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | |||
748 | goto out; | 804 | goto out; |
749 | 805 | ||
750 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, | 806 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
751 | skb->len); | 807 | skb->len, 0, wl->basic_rate); |
752 | 808 | ||
753 | out: | 809 | out: |
754 | dev_kfree_skb(skb); | 810 | dev_kfree_skb(skb); |
@@ -773,10 +829,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, | |||
773 | 829 | ||
774 | if (band == IEEE80211_BAND_2GHZ) | 830 | if (band == IEEE80211_BAND_2GHZ) |
775 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 831 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
776 | skb->data, skb->len); | 832 | skb->data, skb->len, 0, |
833 | wl->conf.tx.basic_rate); | ||
777 | else | 834 | else |
778 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 835 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
779 | skb->data, skb->len); | 836 | skb->data, skb->len, 0, |
837 | wl->conf.tx.basic_rate_5); | ||
780 | 838 | ||
781 | out: | 839 | out: |
782 | dev_kfree_skb(skb); | 840 | dev_kfree_skb(skb); |
@@ -801,7 +859,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
801 | template.qos_ctrl = cpu_to_le16(0); | 859 | template.qos_ctrl = cpu_to_le16(0); |
802 | 860 | ||
803 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | 861 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, |
804 | sizeof(template)); | 862 | sizeof(template), 0, |
863 | WL1271_RATE_AUTOMATIC); | ||
805 | } | 864 | } |
806 | 865 | ||
807 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 866 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
@@ -914,6 +973,10 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) | |||
914 | goto out_free; | 973 | goto out_free; |
915 | } | 974 | } |
916 | 975 | ||
976 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | ||
977 | if (ret < 0) | ||
978 | wl1271_error("cmd disconnect event completion error"); | ||
979 | |||
917 | out_free: | 980 | out_free: |
918 | kfree(cmd); | 981 | kfree(cmd); |
919 | 982 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 6324bbf36843..00f78b7aa384 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -45,13 +45,14 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
45 | const u8 *ie, size_t ie_len, u8 active_scan, | 45 | const u8 *ie, size_t ie_len, u8 active_scan, |
46 | u8 high_prio, u8 band, u8 probe_requests); | 46 | u8 high_prio, u8 band, u8 probe_requests); |
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len); | 48 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | 50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); |
51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, | 51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
52 | const u8 *ssid, size_t ssid_len, | 52 | const u8 *ssid, size_t ssid_len, |
53 | const u8 *ie, size_t ie_len, u8 band); | 53 | const u8 *ie, size_t ie_len, u8 band); |
54 | int wl1271_build_qos_null_data(struct wl1271 *wl); | 54 | int wl1271_build_qos_null_data(struct wl1271 *wl); |
55 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | ||
55 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 56 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
56 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 57 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
57 | u8 key_size, const u8 *key, const u8 *addr, | 58 | u8 key_size, const u8 *key, const u8 *addr, |
@@ -101,6 +102,11 @@ enum wl1271_commands { | |||
101 | 102 | ||
102 | #define MAX_CMD_PARAMS 572 | 103 | #define MAX_CMD_PARAMS 572 |
103 | 104 | ||
105 | enum { | ||
106 | CMD_TEMPL_KLV_IDX_NULL_DATA = 0, | ||
107 | CMD_TEMPL_KLV_IDX_MAX = 4 | ||
108 | }; | ||
109 | |||
104 | enum cmd_templ { | 110 | enum cmd_templ { |
105 | CMD_TEMPL_NULL_DATA = 0, | 111 | CMD_TEMPL_NULL_DATA = 0, |
106 | CMD_TEMPL_BEACON, | 112 | CMD_TEMPL_BEACON, |
@@ -123,6 +129,7 @@ enum cmd_templ { | |||
123 | /* unit ms */ | 129 | /* unit ms */ |
124 | #define WL1271_COMMAND_TIMEOUT 2000 | 130 | #define WL1271_COMMAND_TIMEOUT 2000 |
125 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 | 131 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 |
132 | #define WL1271_EVENT_TIMEOUT 100 | ||
126 | 133 | ||
127 | struct wl1271_cmd_header { | 134 | struct wl1271_cmd_header { |
128 | __le16 id; | 135 | __le16 id; |
@@ -245,6 +252,8 @@ struct cmd_enabledisable_path { | |||
245 | u8 padding[3]; | 252 | u8 padding[3]; |
246 | } __attribute__ ((packed)); | 253 | } __attribute__ ((packed)); |
247 | 254 | ||
255 | #define WL1271_RATE_AUTOMATIC 0 | ||
256 | |||
248 | struct wl1271_cmd_template_set { | 257 | struct wl1271_cmd_template_set { |
249 | struct wl1271_cmd_header header; | 258 | struct wl1271_cmd_header header; |
250 | 259 | ||
@@ -511,6 +520,8 @@ enum wl1271_disconnect_type { | |||
511 | }; | 520 | }; |
512 | 521 | ||
513 | struct wl1271_cmd_disconnect { | 522 | struct wl1271_cmd_disconnect { |
523 | struct wl1271_cmd_header header; | ||
524 | |||
514 | __le32 rx_config_options; | 525 | __le32 rx_config_options; |
515 | __le32 rx_filter_options; | 526 | __le32 rx_filter_options; |
516 | 527 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 7fcfe06b1412..c44307c4bcf8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -66,6 +66,32 @@ enum { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | enum { | 68 | enum { |
69 | CONF_HW_RXTX_RATE_MCS7 = 0, | ||
70 | CONF_HW_RXTX_RATE_MCS6, | ||
71 | CONF_HW_RXTX_RATE_MCS5, | ||
72 | CONF_HW_RXTX_RATE_MCS4, | ||
73 | CONF_HW_RXTX_RATE_MCS3, | ||
74 | CONF_HW_RXTX_RATE_MCS2, | ||
75 | CONF_HW_RXTX_RATE_MCS1, | ||
76 | CONF_HW_RXTX_RATE_MCS0, | ||
77 | CONF_HW_RXTX_RATE_54, | ||
78 | CONF_HW_RXTX_RATE_48, | ||
79 | CONF_HW_RXTX_RATE_36, | ||
80 | CONF_HW_RXTX_RATE_24, | ||
81 | CONF_HW_RXTX_RATE_22, | ||
82 | CONF_HW_RXTX_RATE_18, | ||
83 | CONF_HW_RXTX_RATE_12, | ||
84 | CONF_HW_RXTX_RATE_11, | ||
85 | CONF_HW_RXTX_RATE_9, | ||
86 | CONF_HW_RXTX_RATE_6, | ||
87 | CONF_HW_RXTX_RATE_5_5, | ||
88 | CONF_HW_RXTX_RATE_2, | ||
89 | CONF_HW_RXTX_RATE_1, | ||
90 | CONF_HW_RXTX_RATE_MAX, | ||
91 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | ||
92 | }; | ||
93 | |||
94 | enum { | ||
69 | CONF_SG_DISABLE = 0, | 95 | CONF_SG_DISABLE = 0, |
70 | CONF_SG_PROTECTIVE, | 96 | CONF_SG_PROTECTIVE, |
71 | CONF_SG_OPPORTUNISTIC | 97 | CONF_SG_OPPORTUNISTIC |
@@ -648,6 +674,19 @@ struct conf_tx_settings { | |||
648 | */ | 674 | */ |
649 | u16 tx_compl_threshold; | 675 | u16 tx_compl_threshold; |
650 | 676 | ||
677 | /* | ||
678 | * The rate used for control messages and scanning on the 2.4GHz band | ||
679 | * | ||
680 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
681 | */ | ||
682 | u32 basic_rate; | ||
683 | |||
684 | /* | ||
685 | * The rate used for control messages and scanning on the 5GHz band | ||
686 | * | ||
687 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
688 | */ | ||
689 | u32 basic_rate_5; | ||
651 | }; | 690 | }; |
652 | 691 | ||
653 | enum { | 692 | enum { |
@@ -717,65 +756,6 @@ enum { | |||
717 | CONF_TRIG_EVENT_DIR_BIDIR | 756 | CONF_TRIG_EVENT_DIR_BIDIR |
718 | }; | 757 | }; |
719 | 758 | ||
720 | |||
721 | struct conf_sig_trigger { | ||
722 | /* | ||
723 | * The RSSI / SNR threshold value. | ||
724 | * | ||
725 | * FIXME: what is the range? | ||
726 | */ | ||
727 | s16 threshold; | ||
728 | |||
729 | /* | ||
730 | * Minimum delay between two trigger events for this trigger in ms. | ||
731 | * | ||
732 | * Range: 0 - 60000 | ||
733 | */ | ||
734 | u16 pacing; | ||
735 | |||
736 | /* | ||
737 | * The measurement data source for this trigger. | ||
738 | * | ||
739 | * Range: CONF_TRIG_METRIC_* | ||
740 | */ | ||
741 | u8 metric; | ||
742 | |||
743 | /* | ||
744 | * The trigger type of this trigger. | ||
745 | * | ||
746 | * Range: CONF_TRIG_EVENT_TYPE_* | ||
747 | */ | ||
748 | u8 type; | ||
749 | |||
750 | /* | ||
751 | * The direction of the trigger. | ||
752 | * | ||
753 | * Range: CONF_TRIG_EVENT_DIR_* | ||
754 | */ | ||
755 | u8 direction; | ||
756 | |||
757 | /* | ||
758 | * Hysteresis range of the trigger around the threshold (in dB) | ||
759 | * | ||
760 | * Range: u8 | ||
761 | */ | ||
762 | u8 hysteresis; | ||
763 | |||
764 | /* | ||
765 | * Index of the trigger rule. | ||
766 | * | ||
767 | * Range: 0 - CONF_MAX_RSSI_SNR_TRIGGERS-1 | ||
768 | */ | ||
769 | u8 index; | ||
770 | |||
771 | /* | ||
772 | * Enable / disable this rule (to use for clearing rules.) | ||
773 | * | ||
774 | * Range: 1 - Enabled, 2 - Not enabled | ||
775 | */ | ||
776 | u8 enable; | ||
777 | }; | ||
778 | |||
779 | struct conf_sig_weights { | 759 | struct conf_sig_weights { |
780 | 760 | ||
781 | /* | 761 | /* |
@@ -894,12 +874,6 @@ struct conf_conn_settings { | |||
894 | u8 ps_poll_threshold; | 874 | u8 ps_poll_threshold; |
895 | 875 | ||
896 | /* | 876 | /* |
897 | * Configuration of signal (rssi/snr) triggers. | ||
898 | */ | ||
899 | u8 sig_trigger_count; | ||
900 | struct conf_sig_trigger sig_trigger[CONF_MAX_RSSI_SNR_TRIGGERS]; | ||
901 | |||
902 | /* | ||
903 | * Configuration of signal average weights. | 877 | * Configuration of signal average weights. |
904 | */ | 878 | */ |
905 | struct conf_sig_weights sig_weights; | 879 | struct conf_sig_weights sig_weights; |
@@ -929,6 +903,22 @@ struct conf_conn_settings { | |||
929 | * Range 0 - 255 | 903 | * Range 0 - 255 |
930 | */ | 904 | */ |
931 | u8 psm_entry_retries; | 905 | u8 psm_entry_retries; |
906 | |||
907 | /* | ||
908 | * | ||
909 | * Specifies the interval of the connection keep-alive null-func | ||
910 | * frame in ms. | ||
911 | * | ||
912 | * Range: 1000 - 3600000 | ||
913 | */ | ||
914 | u32 keep_alive_interval; | ||
915 | |||
916 | /* | ||
917 | * Maximum listen interval supported by the driver in units of beacons. | ||
918 | * | ||
919 | * Range: u16 | ||
920 | */ | ||
921 | u8 max_listen_interval; | ||
932 | }; | 922 | }; |
933 | 923 | ||
934 | enum { | 924 | enum { |
@@ -990,6 +980,43 @@ struct conf_pm_config_settings { | |||
990 | bool host_fast_wakeup_support; | 980 | bool host_fast_wakeup_support; |
991 | }; | 981 | }; |
992 | 982 | ||
983 | struct conf_roam_trigger_settings { | ||
984 | /* | ||
985 | * The minimum interval between two trigger events. | ||
986 | * | ||
987 | * Range: 0 - 60000 ms | ||
988 | */ | ||
989 | u16 trigger_pacing; | ||
990 | |||
991 | /* | ||
992 | * The weight for rssi/beacon average calculation | ||
993 | * | ||
994 | * Range: 0 - 255 | ||
995 | */ | ||
996 | u8 avg_weight_rssi_beacon; | ||
997 | |||
998 | /* | ||
999 | * The weight for rssi/data frame average calculation | ||
1000 | * | ||
1001 | * Range: 0 - 255 | ||
1002 | */ | ||
1003 | u8 avg_weight_rssi_data; | ||
1004 | |||
1005 | /* | ||
1006 | * The weight for snr/beacon average calculation | ||
1007 | * | ||
1008 | * Range: 0 - 255 | ||
1009 | */ | ||
1010 | u8 avg_weight_snr_beacon; | ||
1011 | |||
1012 | /* | ||
1013 | * The weight for snr/data frame average calculation | ||
1014 | * | ||
1015 | * Range: 0 - 255 | ||
1016 | */ | ||
1017 | u8 avg_weight_snr_data; | ||
1018 | }; | ||
1019 | |||
993 | struct conf_drv_settings { | 1020 | struct conf_drv_settings { |
994 | struct conf_sg_settings sg; | 1021 | struct conf_sg_settings sg; |
995 | struct conf_rx_settings rx; | 1022 | struct conf_rx_settings rx; |
@@ -998,6 +1025,7 @@ struct conf_drv_settings { | |||
998 | struct conf_init_settings init; | 1025 | struct conf_init_settings init; |
999 | struct conf_itrim_settings itrim; | 1026 | struct conf_itrim_settings itrim; |
1000 | struct conf_pm_config_settings pm_config; | 1027 | struct conf_pm_config_settings pm_config; |
1028 | struct conf_roam_trigger_settings roam_trigger; | ||
1001 | }; | 1029 | }; |
1002 | 1030 | ||
1003 | #endif | 1031 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 4d35af96c597..cf37aa6eb137 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -31,14 +31,11 @@ | |||
31 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 31 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
32 | struct event_mailbox *mbox) | 32 | struct event_mailbox *mbox) |
33 | { | 33 | { |
34 | int size = sizeof(struct wl12xx_probe_req_template); | ||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 34 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 35 | mbox->scheduled_scan_status); |
37 | 36 | ||
38 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 37 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 38 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
41 | NULL, size); | ||
42 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | 39 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend |
43 | * to the wl1271_cmd_scan function that we are not | 40 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 41 | * scanning as it checks that. |
@@ -52,15 +49,6 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
52 | WL1271_SCAN_BAND_5_GHZ, | 49 | WL1271_SCAN_BAND_5_GHZ, |
53 | wl->scan.probe_requests); | 50 | wl->scan.probe_requests); |
54 | } else { | 51 | } else { |
55 | if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) | ||
56 | wl1271_cmd_template_set(wl, | ||
57 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
58 | NULL, size); | ||
59 | else | ||
60 | wl1271_cmd_template_set(wl, | ||
61 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
62 | NULL, size); | ||
63 | |||
64 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
65 | ieee80211_scan_completed(wl->hw, false); | 53 | ieee80211_scan_completed(wl->hw, false); |
66 | mutex_lock(&wl->mutex); | 54 | mutex_lock(&wl->mutex); |
@@ -93,16 +81,9 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
93 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 81 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
94 | true); | 82 | true); |
95 | } else { | 83 | } else { |
96 | wl1271_error("PSM entry failed, giving up.\n"); | 84 | wl1271_info("No ack to nullfunc from AP."); |
97 | /* FIXME: this may need to be reconsidered. for now it | ||
98 | is not possible to indicate to the mac80211 | ||
99 | afterwards that PSM entry failed. To maximize | ||
100 | functionality (receiving data and remaining | ||
101 | associated) make sure that we are in sync with the | ||
102 | AP in regard of PSM mode. */ | ||
103 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
104 | false); | ||
105 | wl->psm_entry_retry = 0; | 85 | wl->psm_entry_retry = 0; |
86 | *beacon_loss = true; | ||
106 | } | 87 | } |
107 | break; | 88 | break; |
108 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 89 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -144,6 +125,24 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
144 | return ret; | 125 | return ret; |
145 | } | 126 | } |
146 | 127 | ||
128 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | ||
129 | struct event_mailbox *mbox) | ||
130 | { | ||
131 | enum nl80211_cqm_rssi_threshold_event event; | ||
132 | s8 metric = mbox->rssi_snr_trigger_metric[0]; | ||
133 | |||
134 | wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); | ||
135 | |||
136 | if (metric <= wl->rssi_thold) | ||
137 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; | ||
138 | else | ||
139 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; | ||
140 | |||
141 | if (event != wl->last_rssi_event) | ||
142 | ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); | ||
143 | wl->last_rssi_event = event; | ||
144 | } | ||
145 | |||
147 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) | 146 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) |
148 | { | 147 | { |
149 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); | 148 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); |
@@ -173,10 +172,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
173 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 172 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon |
174 | * filtering) is enabled. Without PSM, the stack will receive all | 173 | * filtering) is enabled. Without PSM, the stack will receive all |
175 | * beacons and can detect beacon loss by itself. | 174 | * beacons and can detect beacon loss by itself. |
175 | * | ||
176 | * As there's possibility that the driver disables PSM before receiving | ||
177 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
178 | * | ||
176 | */ | 179 | */ |
177 | if (vector & BSS_LOSE_EVENT_ID && | 180 | if (vector & BSS_LOSE_EVENT_ID) { |
178 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 181 | wl1271_info("Beacon loss detected."); |
179 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | ||
180 | 182 | ||
181 | /* indicate to the stack, that beacons have been lost */ | 183 | /* indicate to the stack, that beacons have been lost */ |
182 | beacon_loss = true; | 184 | beacon_loss = true; |
@@ -189,17 +191,15 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
189 | return ret; | 191 | return ret; |
190 | } | 192 | } |
191 | 193 | ||
192 | if (wl->vif && beacon_loss) { | 194 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
193 | /* Obviously, it's dangerous to release the mutex while | 195 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
194 | we are holding many of the variables in the wl struct. | 196 | if (wl->vif) |
195 | That's why it's done last in the function, and care must | 197 | wl1271_event_rssi_trigger(wl, mbox); |
196 | be taken that nothing more is done after this function | ||
197 | returns. */ | ||
198 | mutex_unlock(&wl->mutex); | ||
199 | ieee80211_beacon_loss(wl->vif); | ||
200 | mutex_lock(&wl->mutex); | ||
201 | } | 198 | } |
202 | 199 | ||
200 | if (wl->vif && beacon_loss) | ||
201 | ieee80211_connection_loss(wl->vif); | ||
202 | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 278f9206aa56..58371008f270 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -38,6 +38,14 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | RSSI_SNR_TRIGGER_0_EVENT_ID = BIT(0), | ||
42 | RSSI_SNR_TRIGGER_1_EVENT_ID = BIT(1), | ||
43 | RSSI_SNR_TRIGGER_2_EVENT_ID = BIT(2), | ||
44 | RSSI_SNR_TRIGGER_3_EVENT_ID = BIT(3), | ||
45 | RSSI_SNR_TRIGGER_4_EVENT_ID = BIT(4), | ||
46 | RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), | ||
47 | RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), | ||
48 | RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), | ||
41 | MEASUREMENT_START_EVENT_ID = BIT(8), | 49 | MEASUREMENT_START_EVENT_ID = BIT(8), |
42 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), | 50 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), |
43 | SCAN_COMPLETE_EVENT_ID = BIT(10), | 51 | SCAN_COMPLETE_EVENT_ID = BIT(10), |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index e3806b035d0c..4447af1557f5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -52,50 +52,65 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
52 | 52 | ||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret; | 55 | int ret, i; |
56 | 56 | ||
57 | /* send empty templates for fw memory reservation */ | 57 | /* send empty templates for fw memory reservation */ |
58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
59 | sizeof(struct wl12xx_probe_req_template)); | 59 | sizeof(struct wl12xx_probe_req_template), |
60 | 0, WL1271_RATE_AUTOMATIC); | ||
60 | if (ret < 0) | 61 | if (ret < 0) |
61 | return ret; | 62 | return ret; |
62 | 63 | ||
63 | if (wl1271_11a_enabled()) { | 64 | if (wl1271_11a_enabled()) { |
65 | size_t size = sizeof(struct wl12xx_probe_req_template); | ||
64 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
65 | NULL, | 67 | NULL, size, 0, |
66 | sizeof(struct wl12xx_probe_req_template)); | 68 | WL1271_RATE_AUTOMATIC); |
67 | if (ret < 0) | 69 | if (ret < 0) |
68 | return ret; | 70 | return ret; |
69 | } | 71 | } |
70 | 72 | ||
71 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
72 | sizeof(struct wl12xx_null_data_template)); | 74 | sizeof(struct wl12xx_null_data_template), |
75 | 0, WL1271_RATE_AUTOMATIC); | ||
73 | if (ret < 0) | 76 | if (ret < 0) |
74 | return ret; | 77 | return ret; |
75 | 78 | ||
76 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, | 79 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, |
77 | sizeof(struct wl12xx_ps_poll_template)); | 80 | sizeof(struct wl12xx_ps_poll_template), |
81 | 0, WL1271_RATE_AUTOMATIC); | ||
78 | if (ret < 0) | 82 | if (ret < 0) |
79 | return ret; | 83 | return ret; |
80 | 84 | ||
81 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | 85 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, |
82 | sizeof | 86 | sizeof |
83 | (struct wl12xx_qos_null_data_template)); | 87 | (struct wl12xx_qos_null_data_template), |
88 | 0, WL1271_RATE_AUTOMATIC); | ||
84 | if (ret < 0) | 89 | if (ret < 0) |
85 | return ret; | 90 | return ret; |
86 | 91 | ||
87 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, | 92 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, |
88 | sizeof | 93 | sizeof |
89 | (struct wl12xx_probe_resp_template)); | 94 | (struct wl12xx_probe_resp_template), |
95 | 0, WL1271_RATE_AUTOMATIC); | ||
90 | if (ret < 0) | 96 | if (ret < 0) |
91 | return ret; | 97 | return ret; |
92 | 98 | ||
93 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, | 99 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, |
94 | sizeof | 100 | sizeof |
95 | (struct wl12xx_beacon_template)); | 101 | (struct wl12xx_beacon_template), |
102 | 0, WL1271_RATE_AUTOMATIC); | ||
96 | if (ret < 0) | 103 | if (ret < 0) |
97 | return ret; | 104 | return ret; |
98 | 105 | ||
106 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
107 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | ||
108 | WL1271_CMD_TEMPL_MAX_SIZE, i, | ||
109 | WL1271_RATE_AUTOMATIC); | ||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | } | ||
113 | |||
99 | return 0; | 114 | return 0; |
100 | } | 115 | } |
101 | 116 | ||
@@ -237,7 +252,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
237 | goto out_free_memmap; | 252 | goto out_free_memmap; |
238 | 253 | ||
239 | /* Initialize connection monitoring thresholds */ | 254 | /* Initialize connection monitoring thresholds */ |
240 | ret = wl1271_acx_conn_monit_params(wl); | 255 | ret = wl1271_acx_conn_monit_params(wl, false); |
241 | if (ret < 0) | 256 | if (ret < 0) |
242 | goto out_free_memmap; | 257 | goto out_free_memmap; |
243 | 258 | ||
@@ -325,6 +340,24 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
325 | if (ret < 0) | 340 | if (ret < 0) |
326 | goto out_free_memmap; | 341 | goto out_free_memmap; |
327 | 342 | ||
343 | /* disable all keep-alive templates */ | ||
344 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
345 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
346 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
347 | if (ret < 0) | ||
348 | goto out_free_memmap; | ||
349 | } | ||
350 | |||
351 | /* disable the keep-alive feature */ | ||
352 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
353 | if (ret < 0) | ||
354 | goto out_free_memmap; | ||
355 | |||
356 | /* Configure rssi/snr averaging weights */ | ||
357 | ret = wl1271_acx_rssi_snr_avg_weights(wl); | ||
358 | if (ret < 0) | ||
359 | goto out_free_memmap; | ||
360 | |||
328 | return 0; | 361 | return 0; |
329 | 362 | ||
330 | out_free_memmap: | 363 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index aa970b759dd5..814f300c3f17 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -117,8 +117,7 @@ static struct conf_drv_settings default_conf = { | |||
117 | .tx = { | 117 | .tx = { |
118 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
119 | .rc_conf = { | 119 | .rc_conf = { |
120 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 120 | .enabled_rates = 0, |
121 | CONF_HW_BIT_RATE_2MBPS, | ||
122 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
123 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
124 | .aflags = 0 | 123 | .aflags = 0 |
@@ -215,11 +214,13 @@ static struct conf_drv_settings default_conf = { | |||
215 | }, | 214 | }, |
216 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
217 | .tx_compl_timeout = 700, | 216 | .tx_compl_timeout = 700, |
218 | .tx_compl_threshold = 4 | 217 | .tx_compl_threshold = 4, |
218 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
219 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
219 | }, | 220 | }, |
220 | .conn = { | 221 | .conn = { |
221 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
222 | .listen_interval = 0, | 223 | .listen_interval = 1, |
223 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 224 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
224 | .bcn_filt_ie_count = 1, | 225 | .bcn_filt_ie_count = 1, |
225 | .bcn_filt_ie = { | 226 | .bcn_filt_ie = { |
@@ -234,38 +235,11 @@ static struct conf_drv_settings default_conf = { | |||
234 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
235 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
236 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 20, |
237 | .sig_trigger_count = 2, | ||
238 | .sig_trigger = { | ||
239 | [0] = { | ||
240 | .threshold = -75, | ||
241 | .pacing = 500, | ||
242 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
243 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
244 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
245 | .hysteresis = 2, | ||
246 | .index = 0, | ||
247 | .enable = 1 | ||
248 | }, | ||
249 | [1] = { | ||
250 | .threshold = -75, | ||
251 | .pacing = 500, | ||
252 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
253 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
254 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
255 | .hysteresis = 2, | ||
256 | .index = 1, | ||
257 | .enable = 1 | ||
258 | } | ||
259 | }, | ||
260 | .sig_weights = { | ||
261 | .rssi_bcn_avg_weight = 10, | ||
262 | .rssi_pkt_avg_weight = 10, | ||
263 | .snr_bcn_avg_weight = 10, | ||
264 | .snr_pkt_avg_weight = 10 | ||
265 | }, | ||
266 | .bet_enable = CONF_BET_MODE_ENABLE, | 238 | .bet_enable = CONF_BET_MODE_ENABLE, |
267 | .bet_max_consecutive = 10, | 239 | .bet_max_consecutive = 10, |
268 | .psm_entry_retries = 3 | 240 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | ||
242 | .max_listen_interval = 20, | ||
269 | }, | 243 | }, |
270 | .init = { | 244 | .init = { |
271 | .radioparam = { | 245 | .radioparam = { |
@@ -279,6 +253,14 @@ static struct conf_drv_settings default_conf = { | |||
279 | .pm_config = { | 253 | .pm_config = { |
280 | .host_clk_settling_time = 5000, | 254 | .host_clk_settling_time = 5000, |
281 | .host_fast_wakeup_support = false | 255 | .host_fast_wakeup_support = false |
256 | }, | ||
257 | .roam_trigger = { | ||
258 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
259 | .trigger_pacing = 1, | ||
260 | .avg_weight_rssi_beacon = 20, | ||
261 | .avg_weight_rssi_data = 10, | ||
262 | .avg_weight_snr_beacon = 20, | ||
263 | .avg_weight_snr_data = 10 | ||
282 | } | 264 | } |
283 | }; | 265 | }; |
284 | 266 | ||
@@ -349,7 +331,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
349 | goto out_free_memmap; | 331 | goto out_free_memmap; |
350 | 332 | ||
351 | /* Initialize connection monitoring thresholds */ | 333 | /* Initialize connection monitoring thresholds */ |
352 | ret = wl1271_acx_conn_monit_params(wl); | 334 | ret = wl1271_acx_conn_monit_params(wl, false); |
353 | if (ret < 0) | 335 | if (ret < 0) |
354 | goto out_free_memmap; | 336 | goto out_free_memmap; |
355 | 337 | ||
@@ -959,9 +941,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
959 | switch (vif->type) { | 941 | switch (vif->type) { |
960 | case NL80211_IFTYPE_STATION: | 942 | case NL80211_IFTYPE_STATION: |
961 | wl->bss_type = BSS_TYPE_STA_BSS; | 943 | wl->bss_type = BSS_TYPE_STA_BSS; |
944 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
962 | break; | 945 | break; |
963 | case NL80211_IFTYPE_ADHOC: | 946 | case NL80211_IFTYPE_ADHOC: |
964 | wl->bss_type = BSS_TYPE_IBSS; | 947 | wl->bss_type = BSS_TYPE_IBSS; |
948 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
965 | break; | 949 | break; |
966 | default: | 950 | default: |
967 | ret = -EOPNOTSUPP; | 951 | ret = -EOPNOTSUPP; |
@@ -1066,6 +1050,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1066 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1050 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1067 | wl->ssid_len = 0; | 1051 | wl->ssid_len = 0; |
1068 | wl->bss_type = MAX_BSS_TYPE; | 1052 | wl->bss_type = MAX_BSS_TYPE; |
1053 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1069 | wl->band = IEEE80211_BAND_2GHZ; | 1054 | wl->band = IEEE80211_BAND_2GHZ; |
1070 | 1055 | ||
1071 | wl->rx_counter = 0; | 1056 | wl->rx_counter = 0; |
@@ -1088,6 +1073,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1088 | wl->tx_blocks_freed[i] = 0; | 1073 | wl->tx_blocks_freed[i] = 0; |
1089 | 1074 | ||
1090 | wl1271_debugfs_reset(wl); | 1075 | wl1271_debugfs_reset(wl); |
1076 | |||
1077 | kfree(wl->fw_status); | ||
1078 | wl->fw_status = NULL; | ||
1079 | kfree(wl->tx_res_if); | ||
1080 | wl->tx_res_if = NULL; | ||
1081 | kfree(wl->target_mem_map); | ||
1082 | wl->target_mem_map = NULL; | ||
1083 | |||
1091 | mutex_unlock(&wl->mutex); | 1084 | mutex_unlock(&wl->mutex); |
1092 | } | 1085 | } |
1093 | 1086 | ||
@@ -1138,10 +1131,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1138 | /* pass through frames from all BSS */ | 1131 | /* pass through frames from all BSS */ |
1139 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 1132 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1140 | 1133 | ||
1141 | /* the dummy join is performed always with STATION BSS type to allow | 1134 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1142 | also ad-hoc mode to listen to the surroundings without sending any | ||
1143 | beacons yet. */ | ||
1144 | ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); | ||
1145 | if (ret < 0) | 1135 | if (ret < 0) |
1146 | goto out; | 1136 | goto out; |
1147 | 1137 | ||
@@ -1171,6 +1161,32 @@ out: | |||
1171 | return ret; | 1161 | return ret; |
1172 | } | 1162 | } |
1173 | 1163 | ||
1164 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1165 | { | ||
1166 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1167 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1168 | else | ||
1169 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1170 | } | ||
1171 | |||
1172 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1173 | { | ||
1174 | int i; | ||
1175 | u32 rate = 0; | ||
1176 | |||
1177 | if (!wl->basic_rate_set) { | ||
1178 | WARN_ON(1); | ||
1179 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1180 | } | ||
1181 | |||
1182 | for (i = 0; !rate; i++) { | ||
1183 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1184 | rate = 1 << i; | ||
1185 | } | ||
1186 | |||
1187 | return rate; | ||
1188 | } | ||
1189 | |||
1174 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1190 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1175 | { | 1191 | { |
1176 | struct wl1271 *wl = hw->priv; | 1192 | struct wl1271 *wl = hw->priv; |
@@ -1187,12 +1203,41 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1187 | 1203 | ||
1188 | mutex_lock(&wl->mutex); | 1204 | mutex_lock(&wl->mutex); |
1189 | 1205 | ||
1190 | wl->band = conf->channel->band; | 1206 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
1207 | goto out; | ||
1191 | 1208 | ||
1192 | ret = wl1271_ps_elp_wakeup(wl, false); | 1209 | ret = wl1271_ps_elp_wakeup(wl, false); |
1193 | if (ret < 0) | 1210 | if (ret < 0) |
1194 | goto out; | 1211 | goto out; |
1195 | 1212 | ||
1213 | /* if the channel changes while joined, join again */ | ||
1214 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1215 | wl->band = conf->channel->band; | ||
1216 | wl->channel = channel; | ||
1217 | |||
1218 | /* | ||
1219 | * FIXME: the mac80211 should really provide a fixed rate | ||
1220 | * to use here. for now, just use the smallest possible rate | ||
1221 | * for the band as a fixed rate for association frames and | ||
1222 | * other control messages. | ||
1223 | */ | ||
1224 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1225 | wl1271_set_band_rate(wl); | ||
1226 | |||
1227 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1228 | ret = wl1271_acx_rate_policies(wl); | ||
1229 | if (ret < 0) | ||
1230 | wl1271_warning("rate policy for update channel " | ||
1231 | "failed %d", ret); | ||
1232 | |||
1233 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1234 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1235 | if (ret < 0) | ||
1236 | wl1271_warning("cmd join to update channel " | ||
1237 | "failed %d", ret); | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1196 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1241 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1197 | if (conf->flags & IEEE80211_CONF_IDLE && | 1242 | if (conf->flags & IEEE80211_CONF_IDLE && |
1198 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1243 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
@@ -1201,24 +1246,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1201 | wl1271_join_channel(wl, channel); | 1246 | wl1271_join_channel(wl, channel); |
1202 | 1247 | ||
1203 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1248 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1204 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1249 | wl->rate_set = wl1271_min_rate_get(wl); |
1205 | wl->sta_rate_set = 0; | 1250 | wl->sta_rate_set = 0; |
1206 | wl1271_acx_rate_policies(wl); | 1251 | wl1271_acx_rate_policies(wl); |
1207 | } | 1252 | wl1271_acx_keep_alive_config( |
1253 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1254 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1255 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1256 | } else | ||
1257 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1208 | } | 1258 | } |
1209 | 1259 | ||
1210 | /* if the channel changes while joined, join again */ | ||
1211 | if (channel != wl->channel && | ||
1212 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1213 | wl->channel = channel; | ||
1214 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1215 | ret = wl1271_cmd_join(wl, wl->bss_type); | ||
1216 | if (ret < 0) | ||
1217 | wl1271_warning("cmd join to update channel failed %d", | ||
1218 | ret); | ||
1219 | } else | ||
1220 | wl->channel = channel; | ||
1221 | |||
1222 | if (conf->flags & IEEE80211_CONF_PS && | 1260 | if (conf->flags & IEEE80211_CONF_PS && |
1223 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1261 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1224 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1262 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1272,6 +1310,11 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, | |||
1272 | { | 1310 | { |
1273 | struct wl1271_filter_params *fp; | 1311 | struct wl1271_filter_params *fp; |
1274 | struct netdev_hw_addr *ha; | 1312 | struct netdev_hw_addr *ha; |
1313 | struct wl1271 *wl = hw->priv; | ||
1314 | int i; | ||
1315 | |||
1316 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1317 | return 0; | ||
1275 | 1318 | ||
1276 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1319 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1277 | if (!fp) { | 1320 | if (!fp) { |
@@ -1314,15 +1357,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1314 | 1357 | ||
1315 | mutex_lock(&wl->mutex); | 1358 | mutex_lock(&wl->mutex); |
1316 | 1359 | ||
1317 | if (wl->state == WL1271_STATE_OFF) | 1360 | *total &= WL1271_SUPPORTED_FILTERS; |
1361 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1362 | |||
1363 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1318 | goto out; | 1364 | goto out; |
1319 | 1365 | ||
1320 | ret = wl1271_ps_elp_wakeup(wl, false); | 1366 | ret = wl1271_ps_elp_wakeup(wl, false); |
1321 | if (ret < 0) | 1367 | if (ret < 0) |
1322 | goto out; | 1368 | goto out; |
1323 | 1369 | ||
1324 | *total &= WL1271_SUPPORTED_FILTERS; | ||
1325 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1326 | 1370 | ||
1327 | if (*total & FIF_ALLMULTI) | 1371 | if (*total & FIF_ALLMULTI) |
1328 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1372 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
@@ -1516,10 +1560,13 @@ out: | |||
1516 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1560 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1517 | { | 1561 | { |
1518 | struct wl1271 *wl = hw->priv; | 1562 | struct wl1271 *wl = hw->priv; |
1519 | int ret; | 1563 | int ret = 0; |
1520 | 1564 | ||
1521 | mutex_lock(&wl->mutex); | 1565 | mutex_lock(&wl->mutex); |
1522 | 1566 | ||
1567 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1568 | goto out; | ||
1569 | |||
1523 | ret = wl1271_ps_elp_wakeup(wl, false); | 1570 | ret = wl1271_ps_elp_wakeup(wl, false); |
1524 | if (ret < 0) | 1571 | if (ret < 0) |
1525 | goto out; | 1572 | goto out; |
@@ -1561,6 +1608,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1561 | enum wl1271_cmd_ps_mode mode; | 1608 | enum wl1271_cmd_ps_mode mode; |
1562 | struct wl1271 *wl = hw->priv; | 1609 | struct wl1271 *wl = hw->priv; |
1563 | bool do_join = false; | 1610 | bool do_join = false; |
1611 | bool do_keepalive = false; | ||
1564 | int ret; | 1612 | int ret; |
1565 | 1613 | ||
1566 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1614 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1571,20 +1619,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1571 | if (ret < 0) | 1619 | if (ret < 0) |
1572 | goto out; | 1620 | goto out; |
1573 | 1621 | ||
1574 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1622 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1575 | /* FIXME: This implements rudimentary ad-hoc support - | 1623 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1576 | proper templates are on the wish list and notification | 1624 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1577 | on when they change. This patch will update the templates | 1625 | bss_conf->beacon_int); |
1578 | on every call to this function. */ | 1626 | |
1627 | wl->beacon_int = bss_conf->beacon_int; | ||
1628 | do_join = true; | ||
1629 | } | ||
1630 | |||
1631 | if ((changed && BSS_CHANGED_BEACON) && | ||
1632 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1579 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1633 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1580 | 1634 | ||
1635 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1636 | |||
1581 | if (beacon) { | 1637 | if (beacon) { |
1582 | struct ieee80211_hdr *hdr; | 1638 | struct ieee80211_hdr *hdr; |
1583 | 1639 | ||
1584 | wl1271_ssid_set(wl, beacon); | 1640 | wl1271_ssid_set(wl, beacon); |
1585 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1641 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1586 | beacon->data, | 1642 | beacon->data, |
1587 | beacon->len); | 1643 | beacon->len, 0, |
1644 | wl1271_min_rate_get(wl)); | ||
1588 | 1645 | ||
1589 | if (ret < 0) { | 1646 | if (ret < 0) { |
1590 | dev_kfree_skb(beacon); | 1647 | dev_kfree_skb(beacon); |
@@ -1599,7 +1656,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1599 | ret = wl1271_cmd_template_set(wl, | 1656 | ret = wl1271_cmd_template_set(wl, |
1600 | CMD_TEMPL_PROBE_RESPONSE, | 1657 | CMD_TEMPL_PROBE_RESPONSE, |
1601 | beacon->data, | 1658 | beacon->data, |
1602 | beacon->len); | 1659 | beacon->len, 0, |
1660 | wl1271_min_rate_get(wl)); | ||
1603 | dev_kfree_skb(beacon); | 1661 | dev_kfree_skb(beacon); |
1604 | if (ret < 0) | 1662 | if (ret < 0) |
1605 | goto out_sleep; | 1663 | goto out_sleep; |
@@ -1609,6 +1667,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1609 | } | 1667 | } |
1610 | } | 1668 | } |
1611 | 1669 | ||
1670 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1671 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1672 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1673 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1674 | |||
1675 | if (bss_conf->enable_beacon) | ||
1676 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1677 | else | ||
1678 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1679 | do_join = true; | ||
1680 | } | ||
1681 | |||
1682 | if (changed & BSS_CHANGED_CQM) { | ||
1683 | bool enable = false; | ||
1684 | if (bss_conf->cqm_rssi_thold) | ||
1685 | enable = true; | ||
1686 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | ||
1687 | bss_conf->cqm_rssi_thold, | ||
1688 | bss_conf->cqm_rssi_hyst); | ||
1689 | if (ret < 0) | ||
1690 | goto out; | ||
1691 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
1692 | } | ||
1693 | |||
1612 | if ((changed & BSS_CHANGED_BSSID) && | 1694 | if ((changed & BSS_CHANGED_BSSID) && |
1613 | /* | 1695 | /* |
1614 | * Now we know the correct bssid, so we send a new join command | 1696 | * Now we know the correct bssid, so we send a new join command |
@@ -1630,10 +1712,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1630 | 1712 | ||
1631 | if (changed & BSS_CHANGED_ASSOC) { | 1713 | if (changed & BSS_CHANGED_ASSOC) { |
1632 | if (bss_conf->assoc) { | 1714 | if (bss_conf->assoc) { |
1715 | u32 rates; | ||
1633 | wl->aid = bss_conf->aid; | 1716 | wl->aid = bss_conf->aid; |
1634 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1717 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1635 | 1718 | ||
1636 | /* | 1719 | /* |
1720 | * use basic rates from AP, and determine lowest rate | ||
1721 | * to use with control frames. | ||
1722 | */ | ||
1723 | rates = bss_conf->basic_rates; | ||
1724 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1725 | rates); | ||
1726 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1727 | ret = wl1271_acx_rate_policies(wl); | ||
1728 | if (ret < 0) | ||
1729 | goto out_sleep; | ||
1730 | |||
1731 | /* | ||
1637 | * with wl1271, we don't need to update the | 1732 | * with wl1271, we don't need to update the |
1638 | * beacon_int and dtim_period, because the firmware | 1733 | * beacon_int and dtim_period, because the firmware |
1639 | * updates it by itself when the first beacon is | 1734 | * updates it by itself when the first beacon is |
@@ -1643,7 +1738,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1643 | if (ret < 0) | 1738 | if (ret < 0) |
1644 | goto out_sleep; | 1739 | goto out_sleep; |
1645 | 1740 | ||
1646 | ret = wl1271_acx_aid(wl, wl->aid); | 1741 | /* |
1742 | * The SSID is intentionally set to NULL here - the | ||
1743 | * firmware will set the probe request with a | ||
1744 | * broadcast SSID regardless of what we set in the | ||
1745 | * template. | ||
1746 | */ | ||
1747 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1748 | NULL, 0, wl->band); | ||
1749 | |||
1750 | /* Enable the keep-alive feature */ | ||
1751 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1752 | if (ret < 0) | ||
1753 | goto out_sleep; | ||
1754 | |||
1755 | /* | ||
1756 | * This is awkward. The keep-alive configs must be done | ||
1757 | * *after* the join command, because otherwise it will | ||
1758 | * not work, but it must only be done *once* because | ||
1759 | * otherwise the firmware will start complaining. | ||
1760 | */ | ||
1761 | do_keepalive = true; | ||
1762 | |||
1763 | /* enable the connection monitoring feature */ | ||
1764 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1647 | if (ret < 0) | 1765 | if (ret < 0) |
1648 | goto out_sleep; | 1766 | goto out_sleep; |
1649 | 1767 | ||
@@ -1659,6 +1777,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1659 | /* use defaults when not associated */ | 1777 | /* use defaults when not associated */ |
1660 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1778 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1661 | wl->aid = 0; | 1779 | wl->aid = 0; |
1780 | |||
1781 | /* revert back to minimum rates for the current band */ | ||
1782 | wl1271_set_band_rate(wl); | ||
1783 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1784 | ret = wl1271_acx_rate_policies(wl); | ||
1785 | if (ret < 0) | ||
1786 | goto out_sleep; | ||
1787 | |||
1788 | /* disable connection monitor features */ | ||
1789 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1790 | |||
1791 | /* Disable the keep-alive feature */ | ||
1792 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1793 | |||
1794 | if (ret < 0) | ||
1795 | goto out_sleep; | ||
1662 | } | 1796 | } |
1663 | 1797 | ||
1664 | } | 1798 | } |
@@ -1693,7 +1827,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1693 | } | 1827 | } |
1694 | 1828 | ||
1695 | if (do_join) { | 1829 | if (do_join) { |
1696 | ret = wl1271_cmd_join(wl, wl->bss_type); | 1830 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1697 | if (ret < 0) { | 1831 | if (ret < 0) { |
1698 | wl1271_warning("cmd join failed %d", ret); | 1832 | wl1271_warning("cmd join failed %d", ret); |
1699 | goto out_sleep; | 1833 | goto out_sleep; |
@@ -1701,6 +1835,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1701 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1835 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1702 | } | 1836 | } |
1703 | 1837 | ||
1838 | /* | ||
1839 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1840 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1841 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1842 | * JOIN operation, and the template config after the ACX_AID. | ||
1843 | */ | ||
1844 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1845 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1846 | if (ret < 0) | ||
1847 | goto out_sleep; | ||
1848 | } | ||
1849 | |||
1850 | if (do_keepalive) { | ||
1851 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1852 | if (ret < 0) | ||
1853 | goto out_sleep; | ||
1854 | ret = wl1271_acx_keep_alive_config( | ||
1855 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1856 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1857 | if (ret < 0) | ||
1858 | goto out_sleep; | ||
1859 | } | ||
1860 | |||
1704 | out_sleep: | 1861 | out_sleep: |
1705 | wl1271_ps_elp_sleep(wl); | 1862 | wl1271_ps_elp_sleep(wl); |
1706 | 1863 | ||
@@ -1812,6 +1969,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1812 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1969 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1813 | }; | 1970 | }; |
1814 | 1971 | ||
1972 | /* mapping to indexes for wl1271_rates */ | ||
1973 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1974 | /* MCS rates are used only with 11n */ | ||
1975 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1976 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1977 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1978 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
1979 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
1980 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
1981 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
1982 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
1983 | |||
1984 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
1985 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
1986 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
1987 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
1988 | |||
1989 | /* TI-specific rate */ | ||
1990 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
1991 | |||
1992 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
1993 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
1994 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
1995 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
1996 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
1997 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
1998 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
1999 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
2000 | }; | ||
2001 | |||
1815 | /* can't be const, mac80211 writes to this */ | 2002 | /* can't be const, mac80211 writes to this */ |
1816 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2003 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1817 | .channels = wl1271_channels, | 2004 | .channels = wl1271_channels, |
@@ -1894,6 +2081,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1894 | { .hw_value = 165, .center_freq = 5825}, | 2081 | { .hw_value = 165, .center_freq = 5825}, |
1895 | }; | 2082 | }; |
1896 | 2083 | ||
2084 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2085 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2086 | /* MCS rates are used only with 11n */ | ||
2087 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2088 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2089 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2090 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2091 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2092 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2093 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2094 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2095 | |||
2096 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2097 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2098 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2099 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2100 | |||
2101 | /* TI-specific rate */ | ||
2102 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2103 | |||
2104 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2105 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2106 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2107 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2108 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2112 | }; | ||
1897 | 2113 | ||
1898 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2114 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1899 | .channels = wl1271_channels_5ghz, | 2115 | .channels = wl1271_channels_5ghz, |
@@ -1902,6 +2118,11 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1902 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2118 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1903 | }; | 2119 | }; |
1904 | 2120 | ||
2121 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2122 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2123 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2124 | }; | ||
2125 | |||
1905 | static const struct ieee80211_ops wl1271_ops = { | 2126 | static const struct ieee80211_ops wl1271_ops = { |
1906 | .start = wl1271_op_start, | 2127 | .start = wl1271_op_start, |
1907 | .stop = wl1271_op_stop, | 2128 | .stop = wl1271_op_stop, |
@@ -1919,6 +2140,27 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1919 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2140 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1920 | }; | 2141 | }; |
1921 | 2142 | ||
2143 | |||
2144 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2145 | { | ||
2146 | u8 idx; | ||
2147 | |||
2148 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2149 | |||
2150 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2151 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2156 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2157 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | return idx; | ||
2162 | } | ||
2163 | |||
1922 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | 2164 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, |
1923 | struct device_attribute *attr, | 2165 | struct device_attribute *attr, |
1924 | char *buf) | 2166 | char *buf) |
@@ -2021,13 +2263,16 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2021 | /* unit us */ | 2263 | /* unit us */ |
2022 | /* FIXME: find a proper value */ | 2264 | /* FIXME: find a proper value */ |
2023 | wl->hw->channel_change_time = 10000; | 2265 | wl->hw->channel_change_time = 10000; |
2266 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
2024 | 2267 | ||
2025 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2268 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
2026 | IEEE80211_HW_NOISE_DBM | | 2269 | IEEE80211_HW_NOISE_DBM | |
2027 | IEEE80211_HW_BEACON_FILTER | | 2270 | IEEE80211_HW_BEACON_FILTER | |
2028 | IEEE80211_HW_SUPPORTS_PS | | 2271 | IEEE80211_HW_SUPPORTS_PS | |
2029 | IEEE80211_HW_SUPPORTS_UAPSD | | 2272 | IEEE80211_HW_SUPPORTS_UAPSD | |
2030 | IEEE80211_HW_HAS_RATE_CONTROL; | 2273 | IEEE80211_HW_HAS_RATE_CONTROL | |
2274 | IEEE80211_HW_CONNECTION_MONITOR | | ||
2275 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
2031 | 2276 | ||
2032 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2277 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2033 | BIT(NL80211_IFTYPE_ADHOC); | 2278 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2038,6 +2283,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2038 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2283 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2039 | 2284 | ||
2040 | wl->hw->queues = 4; | 2285 | wl->hw->queues = 4; |
2286 | wl->hw->max_rates = 1; | ||
2041 | 2287 | ||
2042 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 2288 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2043 | 2289 | ||
@@ -2053,7 +2299,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2053 | struct platform_device *plat_dev = NULL; | 2299 | struct platform_device *plat_dev = NULL; |
2054 | struct wl1271 *wl; | 2300 | struct wl1271 *wl; |
2055 | int i, ret; | 2301 | int i, ret; |
2056 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
2057 | 2302 | ||
2058 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2303 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2059 | if (!hw) { | 2304 | if (!hw) { |
@@ -2083,6 +2328,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2083 | 2328 | ||
2084 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2329 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2085 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2330 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2331 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2086 | wl->default_key = 0; | 2332 | wl->default_key = 0; |
2087 | wl->rx_counter = 0; | 2333 | wl->rx_counter = 0; |
2088 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2334 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2090,6 +2336,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2090 | wl->psm_entry_retry = 0; | 2336 | wl->psm_entry_retry = 0; |
2091 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2337 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2092 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2338 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2339 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2093 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2340 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2094 | wl->sta_rate_set = 0; | 2341 | wl->sta_rate_set = 0; |
2095 | wl->band = IEEE80211_BAND_2GHZ; | 2342 | wl->band = IEEE80211_BAND_2GHZ; |
@@ -2105,13 +2352,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2105 | wl->state = WL1271_STATE_OFF; | 2352 | wl->state = WL1271_STATE_OFF; |
2106 | mutex_init(&wl->mutex); | 2353 | mutex_init(&wl->mutex); |
2107 | 2354 | ||
2108 | /* | ||
2109 | * FIXME: we should use a zero MAC address here, but for now we | ||
2110 | * generate a random Nokia address. | ||
2111 | */ | ||
2112 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
2113 | get_random_bytes(wl->mac_addr + 3, 3); | ||
2114 | |||
2115 | /* Apply default driver configuration. */ | 2355 | /* Apply default driver configuration. */ |
2116 | wl1271_conf_init(wl); | 2356 | wl1271_conf_init(wl); |
2117 | 2357 | ||
@@ -2157,7 +2397,6 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2157 | 2397 | ||
2158 | wl1271_debugfs_exit(wl); | 2398 | wl1271_debugfs_exit(wl); |
2159 | 2399 | ||
2160 | kfree(wl->target_mem_map); | ||
2161 | vfree(wl->fw); | 2400 | vfree(wl->fw); |
2162 | wl->fw = NULL; | 2401 | wl->fw = NULL; |
2163 | kfree(wl->nvs); | 2402 | kfree(wl->nvs); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 5a04482b9353..a5e60e0403e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -40,7 +40,8 @@ void wl1271_elp_work(struct work_struct *work) | |||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | 43 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
44 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | ||
44 | goto out; | 45 | goto out; |
45 | 46 | ||
46 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
@@ -56,7 +57,8 @@ out: | |||
56 | /* Routines to toggle sleep mode while in ELP */ | 57 | /* Routines to toggle sleep mode while in ELP */ |
57 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 58 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
58 | { | 59 | { |
59 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 60 | if (test_bit(WL1271_FLAG_PSM, &wl->flags) || |
61 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | ||
60 | cancel_delayed_work(&wl->elp_work); | 62 | cancel_delayed_work(&wl->elp_work); |
61 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 63 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
62 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 64 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 6f1b732ae43b..57f4bfd959c8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -43,66 +43,6 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | |||
43 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | 43 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* The values of this table must match the wl1271_rates[] array */ | ||
47 | static u8 wl1271_rx_rate_to_idx[] = { | ||
48 | /* MCS rates are used only with 11n */ | ||
49 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
50 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
51 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
52 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
53 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
54 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
55 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
56 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
57 | |||
58 | 11, /* WL1271_RATE_54 */ | ||
59 | 10, /* WL1271_RATE_48 */ | ||
60 | 9, /* WL1271_RATE_36 */ | ||
61 | 8, /* WL1271_RATE_24 */ | ||
62 | |||
63 | /* TI-specific rate */ | ||
64 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
65 | |||
66 | 7, /* WL1271_RATE_18 */ | ||
67 | 6, /* WL1271_RATE_12 */ | ||
68 | 3, /* WL1271_RATE_11 */ | ||
69 | 5, /* WL1271_RATE_9 */ | ||
70 | 4, /* WL1271_RATE_6 */ | ||
71 | 2, /* WL1271_RATE_5_5 */ | ||
72 | 1, /* WL1271_RATE_2 */ | ||
73 | 0 /* WL1271_RATE_1 */ | ||
74 | }; | ||
75 | |||
76 | /* The values of this table must match the wl1271_rates[] array */ | ||
77 | static u8 wl1271_5_ghz_rx_rate_to_idx[] = { | ||
78 | /* MCS rates are used only with 11n */ | ||
79 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
80 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
81 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
82 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
83 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
84 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
85 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
86 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
87 | |||
88 | 7, /* WL1271_RATE_54 */ | ||
89 | 6, /* WL1271_RATE_48 */ | ||
90 | 5, /* WL1271_RATE_36 */ | ||
91 | 4, /* WL1271_RATE_24 */ | ||
92 | |||
93 | /* TI-specific rate */ | ||
94 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
95 | |||
96 | 3, /* WL1271_RATE_18 */ | ||
97 | 2, /* WL1271_RATE_12 */ | ||
98 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ | ||
99 | 1, /* WL1271_RATE_9 */ | ||
100 | 0, /* WL1271_RATE_6 */ | ||
101 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ | ||
102 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ | ||
103 | WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ | ||
104 | }; | ||
105 | |||
106 | static void wl1271_rx_status(struct wl1271 *wl, | 46 | static void wl1271_rx_status(struct wl1271 *wl, |
107 | struct wl1271_rx_descriptor *desc, | 47 | struct wl1271_rx_descriptor *desc, |
108 | struct ieee80211_rx_status *status, | 48 | struct ieee80211_rx_status *status, |
@@ -110,20 +50,8 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
110 | { | 50 | { |
111 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 51 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
112 | 52 | ||
113 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | 53 | status->band = wl->band; |
114 | WL1271_RX_DESC_BAND_BG) { | 54 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); |
115 | status->band = IEEE80211_BAND_2GHZ; | ||
116 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; | ||
117 | } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | ||
118 | WL1271_RX_DESC_BAND_A) { | ||
119 | status->band = IEEE80211_BAND_5GHZ; | ||
120 | status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; | ||
121 | } else | ||
122 | wl1271_warning("unsupported band 0x%x", | ||
123 | desc->flags & WL1271_RX_DESC_BAND_MASK); | ||
124 | |||
125 | if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) | ||
126 | wl1271_warning("unsupported rate"); | ||
127 | 55 | ||
128 | /* | 56 | /* |
129 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | 57 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the |
@@ -133,13 +61,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
133 | */ | 61 | */ |
134 | status->signal = desc->rssi; | 62 | status->signal = desc->rssi; |
135 | 63 | ||
136 | /* | ||
137 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we | ||
138 | * need to divide by two for now, but TI has been discussing about | ||
139 | * changing it. This needs to be rechecked. | ||
140 | */ | ||
141 | status->noise = desc->rssi - (desc->snr >> 1); | ||
142 | |||
143 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 64 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
144 | 65 | ||
145 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 66 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index 1ae6d1783ed4..b89be4758e78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RX_MAX_PACKET_ID 3 | 43 | #define RX_MAX_PACKET_ID 3 |
44 | 44 | ||
45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 | 45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 |
46 | #define WL1271_RX_RATE_UNSUPPORTED 0xFF | ||
47 | 46 | ||
48 | #define RX_DESC_VALID_FCS 0x0001 | 47 | #define RX_DESC_VALID_FCS 0x0001 |
49 | #define RX_DESC_MATCH_RXADDR1 0x0002 | 48 | #define RX_DESC_MATCH_RXADDR1 0x0002 |
@@ -117,5 +116,6 @@ struct wl1271_rx_descriptor { | |||
117 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
118 | 117 | ||
119 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); | 118 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); |
119 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
120 | 120 | ||
121 | #endif | 121 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 3c03de74dbfc..d3d6f302f705 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -117,7 +117,7 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
117 | else | 117 | else |
118 | ret = sdio_memcpy_fromio(func, buf, addr, len); | 118 | ret = sdio_memcpy_fromio(func, buf, addr, len); |
119 | 119 | ||
120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %d bytes", | 120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", |
121 | addr, len); | 121 | addr, len); |
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
123 | } | 123 | } |
@@ -138,7 +138,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | 138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", |
139 | addr, ((u8 *)buf)[0]); | 139 | addr, ((u8 *)buf)[0]); |
140 | } else { | 140 | } else { |
141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %d bytes", | 141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", |
142 | addr, len); | 142 | addr, len); |
143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
144 | 144 | ||
@@ -255,7 +255,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | static struct sdio_driver wl1271_sdio_driver = { | 257 | static struct sdio_driver wl1271_sdio_driver = { |
258 | .name = "wl1271", | 258 | .name = "wl1271_sdio", |
259 | .id_table = wl1271_devices, | 259 | .id_table = wl1271_devices, |
260 | .probe = wl1271_probe, | 260 | .probe = wl1271_probe, |
261 | .remove = __devexit_p(wl1271_remove), | 261 | .remove = __devexit_p(wl1271_remove), |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 256e84ad0baf..5189b812f939 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -105,6 +105,7 @@ static void wl1271_spi_reset(struct wl1271 *wl) | |||
105 | spi_message_add_tail(&t, &m); | 105 | spi_message_add_tail(&t, &m); |
106 | 106 | ||
107 | spi_sync(wl_to_spi(wl), &m); | 107 | spi_sync(wl_to_spi(wl), &m); |
108 | kfree(cmd); | ||
108 | 109 | ||
109 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 110 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
110 | } | 111 | } |
@@ -159,47 +160,24 @@ static void wl1271_spi_init(struct wl1271 *wl) | |||
159 | spi_message_add_tail(&t, &m); | 160 | spi_message_add_tail(&t, &m); |
160 | 161 | ||
161 | spi_sync(wl_to_spi(wl), &m); | 162 | spi_sync(wl_to_spi(wl), &m); |
163 | kfree(cmd); | ||
162 | 164 | ||
163 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 165 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
164 | } | 166 | } |
165 | 167 | ||
166 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 168 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
167 | 169 | ||
168 | /* FIXME: Check busy words, removed due to SPI bug */ | 170 | static int wl1271_spi_read_busy(struct wl1271 *wl) |
169 | #if 0 | ||
170 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
171 | { | 171 | { |
172 | struct spi_transfer t[1]; | 172 | struct spi_transfer t[1]; |
173 | struct spi_message m; | 173 | struct spi_message m; |
174 | u32 *busy_buf; | 174 | u32 *busy_buf; |
175 | int num_busy_bytes = 0; | 175 | int num_busy_bytes = 0; |
176 | 176 | ||
177 | wl1271_info("spi read BUSY!"); | ||
178 | |||
179 | /* | ||
180 | * Look for the non-busy word in the read buffer, and if found, | ||
181 | * read in the remaining data into the buffer. | ||
182 | */ | ||
183 | busy_buf = (u32 *)buf; | ||
184 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
185 | num_busy_bytes += sizeof(u32); | ||
186 | if (*busy_buf & 0x1) { | ||
187 | spi_message_init(&m); | ||
188 | memset(t, 0, sizeof(t)); | ||
189 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
190 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
191 | t[0].len = num_busy_bytes; | ||
192 | spi_message_add_tail(&t[0], &m); | ||
193 | spi_sync(wl_to_spi(wl), &m); | ||
194 | return; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /* | 177 | /* |
199 | * Read further busy words from SPI until a non-busy word is | 178 | * Read further busy words from SPI until a non-busy word is |
200 | * encountered, then read the data itself into the buffer. | 179 | * encountered, then read the data itself into the buffer. |
201 | */ | 180 | */ |
202 | wl1271_info("spi read BUSY-polling needed!"); | ||
203 | 181 | ||
204 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; | 182 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
205 | busy_buf = wl->buffer_busyword; | 183 | busy_buf = wl->buffer_busyword; |
@@ -209,28 +187,21 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
209 | memset(t, 0, sizeof(t)); | 187 | memset(t, 0, sizeof(t)); |
210 | t[0].rx_buf = busy_buf; | 188 | t[0].rx_buf = busy_buf; |
211 | t[0].len = sizeof(u32); | 189 | t[0].len = sizeof(u32); |
190 | t[0].cs_change = true; | ||
212 | spi_message_add_tail(&t[0], &m); | 191 | spi_message_add_tail(&t[0], &m); |
213 | spi_sync(wl_to_spi(wl), &m); | 192 | spi_sync(wl_to_spi(wl), &m); |
214 | 193 | ||
215 | if (*busy_buf & 0x1) { | 194 | if (*busy_buf & 0x1) |
216 | spi_message_init(&m); | 195 | return 0; |
217 | memset(t, 0, sizeof(t)); | ||
218 | t[0].rx_buf = buf; | ||
219 | t[0].len = len; | ||
220 | spi_message_add_tail(&t[0], &m); | ||
221 | spi_sync(wl_to_spi(wl), &m); | ||
222 | return; | ||
223 | } | ||
224 | } | 196 | } |
225 | 197 | ||
226 | /* The SPI bus is unresponsive, the read failed. */ | 198 | /* The SPI bus is unresponsive, the read failed. */ |
227 | memset(buf, 0, len); | ||
228 | wl1271_error("SPI read busy-word timeout!\n"); | 199 | wl1271_error("SPI read busy-word timeout!\n"); |
200 | return -ETIMEDOUT; | ||
229 | } | 201 | } |
230 | #endif | ||
231 | 202 | ||
232 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 203 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
233 | size_t len, bool fixed) | 204 | size_t len, bool fixed) |
234 | { | 205 | { |
235 | struct spi_transfer t[3]; | 206 | struct spi_transfer t[3]; |
236 | struct spi_message m; | 207 | struct spi_message m; |
@@ -253,22 +224,32 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
253 | 224 | ||
254 | t[0].tx_buf = cmd; | 225 | t[0].tx_buf = cmd; |
255 | t[0].len = 4; | 226 | t[0].len = 4; |
227 | t[0].cs_change = true; | ||
256 | spi_message_add_tail(&t[0], &m); | 228 | spi_message_add_tail(&t[0], &m); |
257 | 229 | ||
258 | /* Busy and non busy words read */ | 230 | /* Busy and non busy words read */ |
259 | t[1].rx_buf = busy_buf; | 231 | t[1].rx_buf = busy_buf; |
260 | t[1].len = WL1271_BUSY_WORD_LEN; | 232 | t[1].len = WL1271_BUSY_WORD_LEN; |
233 | t[1].cs_change = true; | ||
261 | spi_message_add_tail(&t[1], &m); | 234 | spi_message_add_tail(&t[1], &m); |
262 | 235 | ||
263 | t[2].rx_buf = buf; | ||
264 | t[2].len = len; | ||
265 | spi_message_add_tail(&t[2], &m); | ||
266 | |||
267 | spi_sync(wl_to_spi(wl), &m); | 236 | spi_sync(wl_to_spi(wl), &m); |
268 | 237 | ||
269 | /* FIXME: Check busy words, removed due to SPI bug */ | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
270 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | 239 | wl1271_spi_read_busy(wl)) { |
271 | wl1271_spi_read_busy(wl, buf, len); */ | 240 | memset(buf, 0, len); |
241 | return; | ||
242 | } | ||
243 | |||
244 | spi_message_init(&m); | ||
245 | memset(t, 0, sizeof(t)); | ||
246 | |||
247 | t[0].rx_buf = buf; | ||
248 | t[0].len = len; | ||
249 | t[0].cs_change = true; | ||
250 | spi_message_add_tail(&t[0], &m); | ||
251 | |||
252 | spi_sync(wl_to_spi(wl), &m); | ||
272 | 253 | ||
273 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 254 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
274 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 255 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
@@ -443,7 +424,7 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
443 | 424 | ||
444 | static struct spi_driver wl1271_spi_driver = { | 425 | static struct spi_driver wl1271_spi_driver = { |
445 | .driver = { | 426 | .driver = { |
446 | .name = "wl1271", | 427 | .name = "wl1271_spi", |
447 | .bus = &spi_bus_type, | 428 | .bus = &spi_bus_type, |
448 | .owner = THIS_MODULE, | 429 | .owner = THIS_MODULE, |
449 | }, | 430 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 6d109df9a0a0..62db79508ddf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 223 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
224 | { | 224 | { |
225 | struct ieee80211_supported_band *band; | 225 | struct ieee80211_supported_band *band; |
226 | u32 enabled_rates = 0; | 226 | u32 enabled_rates = 0; |
@@ -304,6 +304,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
304 | struct ieee80211_tx_info *info; | 304 | struct ieee80211_tx_info *info; |
305 | struct sk_buff *skb; | 305 | struct sk_buff *skb; |
306 | int id = result->id; | 306 | int id = result->id; |
307 | int rate = -1; | ||
308 | u8 retries = 0; | ||
307 | 309 | ||
308 | /* check for id legality */ | 310 | /* check for id legality */ |
309 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { | 311 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
@@ -314,19 +316,22 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
314 | skb = wl->tx_frames[id]; | 316 | skb = wl->tx_frames[id]; |
315 | info = IEEE80211_SKB_CB(skb); | 317 | info = IEEE80211_SKB_CB(skb); |
316 | 318 | ||
317 | /* update packet status */ | 319 | /* update the TX status info */ |
318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 320 | if (result->status == TX_SUCCESS) { |
319 | if (result->status == TX_SUCCESS) | 321 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
320 | info->flags |= IEEE80211_TX_STAT_ACK; | 322 | info->flags |= IEEE80211_TX_STAT_ACK; |
321 | if (result->status & TX_RETRY_EXCEEDED) { | 323 | rate = wl1271_rate_to_idx(wl, result->rate_class_index); |
322 | /* FIXME */ | 324 | retries = result->ack_failures; |
323 | /* info->status.excessive_retries = 1; */ | 325 | } else if (result->status == TX_RETRY_EXCEEDED) { |
324 | wl->stats.excessive_retries++; | 326 | wl->stats.excessive_retries++; |
325 | } | 327 | retries = result->ack_failures; |
326 | } | 328 | } |
327 | 329 | ||
328 | /* FIXME */ | 330 | info->status.rates[0].idx = rate; |
329 | /* info->status.retry_count = result->ack_failures; */ | 331 | info->status.rates[0].count = retries; |
332 | info->status.rates[0].flags = 0; | ||
333 | info->status.ack_signal = -1; | ||
334 | |||
330 | wl->stats.retry_count += result->ack_failures; | 335 | wl->stats.retry_count += result->ack_failures; |
331 | 336 | ||
332 | /* update security sequence number */ | 337 | /* update security sequence number */ |
@@ -350,8 +355,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
350 | result->id, skb, result->ack_failures, | 355 | result->id, skb, result->ack_failures, |
351 | result->rate_class_index, result->status); | 356 | result->rate_class_index, result->status); |
352 | 357 | ||
353 | /* FIXME: do we need to tell the stack about the used rate? */ | ||
354 | |||
355 | /* return the packet to the stack */ | 358 | /* return the packet to the stack */ |
356 | ieee80211_tx_status(wl->hw, skb); | 359 | ieee80211_tx_status(wl->hw, skb); |
357 | wl->tx_frames[result->id] = NULL; | 360 | wl->tx_frames[result->id] = NULL; |
@@ -413,31 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
413 | { | 416 | { |
414 | int i; | 417 | int i; |
415 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
416 | struct ieee80211_tx_info *info; | ||
417 | 419 | ||
418 | /* TX failure */ | 420 | /* TX failure */ |
419 | /* control->flags = 0; FIXME */ | 421 | /* control->flags = 0; FIXME */ |
420 | 422 | ||
421 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 423 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
422 | info = IEEE80211_SKB_CB(skb); | ||
423 | |||
424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); | 424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); |
425 | |||
426 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
427 | continue; | ||
428 | |||
429 | ieee80211_tx_status(wl->hw, skb); | 425 | ieee80211_tx_status(wl->hw, skb); |
430 | } | 426 | } |
431 | 427 | ||
432 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
433 | if (wl->tx_frames[i] != NULL) { | 429 | if (wl->tx_frames[i] != NULL) { |
434 | skb = wl->tx_frames[i]; | 430 | skb = wl->tx_frames[i]; |
435 | info = IEEE80211_SKB_CB(skb); | ||
436 | |||
437 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
438 | continue; | ||
439 | |||
440 | ieee80211_tx_status(wl->hw, skb); | ||
441 | wl->tx_frames[i] = NULL; | 431 | wl->tx_frames[i] = NULL; |
432 | ieee80211_tx_status(wl->hw, skb); | ||
442 | } | 433 | } |
443 | } | 434 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 5e6c27a57415..3b8b7ac253fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -159,5 +159,7 @@ static inline int wl1271_tx_ac_to_tid(int ac) | |||
159 | void wl1271_tx_work(struct work_struct *work); | 159 | void wl1271_tx_work(struct work_struct *work); |
160 | void wl1271_tx_complete(struct wl1271 *wl); | 160 | void wl1271_tx_complete(struct wl1271 *wl); |
161 | void wl1271_tx_flush(struct wl1271 *wl); | 161 | void wl1271_tx_flush(struct wl1271 *wl); |
162 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
163 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | ||
162 | 164 | ||
163 | #endif | 165 | #endif |