diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx')
29 files changed, 1177 insertions, 710 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 054533f7a12..6301578d156 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -247,6 +247,7 @@ struct wl1251_debugfs { | |||
247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; | 247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; |
248 | 248 | ||
249 | struct dentry *tx_queue_len; | 249 | struct dentry *tx_queue_len; |
250 | struct dentry *tx_queue_status; | ||
250 | 251 | ||
251 | struct dentry *retry_count; | 252 | struct dentry *retry_count; |
252 | struct dentry *excessive_retries; | 253 | struct dentry *excessive_retries; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index acfa086dbfc..beff084040b 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -976,3 +976,72 @@ out: | |||
976 | kfree(acx); | 976 | kfree(acx); |
977 | return ret; | 977 | return ret; |
978 | } | 978 | } |
979 | |||
980 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
981 | u8 aifs, u16 txop) | ||
982 | { | ||
983 | struct wl1251_acx_ac_cfg *acx; | ||
984 | int ret = 0; | ||
985 | |||
986 | wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " | ||
987 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); | ||
988 | |||
989 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
990 | |||
991 | if (!acx) { | ||
992 | ret = -ENOMEM; | ||
993 | goto out; | ||
994 | } | ||
995 | |||
996 | acx->ac = ac; | ||
997 | acx->cw_min = cw_min; | ||
998 | acx->cw_max = cw_max; | ||
999 | acx->aifsn = aifs; | ||
1000 | acx->txop_limit = txop; | ||
1001 | |||
1002 | ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | ||
1003 | if (ret < 0) { | ||
1004 | wl1251_warning("acx ac cfg failed: %d", ret); | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | out: | ||
1009 | kfree(acx); | ||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1014 | enum wl1251_acx_channel_type type, | ||
1015 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1016 | enum wl1251_acx_ack_policy ack_policy) | ||
1017 | { | ||
1018 | struct wl1251_acx_tid_cfg *acx; | ||
1019 | int ret = 0; | ||
1020 | |||
1021 | wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d " | ||
1022 | "ps_scheme %d ack_policy %d", queue, type, tsid, | ||
1023 | ps_scheme, ack_policy); | ||
1024 | |||
1025 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1026 | |||
1027 | if (!acx) { | ||
1028 | ret = -ENOMEM; | ||
1029 | goto out; | ||
1030 | } | ||
1031 | |||
1032 | acx->queue = queue; | ||
1033 | acx->type = type; | ||
1034 | acx->tsid = tsid; | ||
1035 | acx->ps_scheme = ps_scheme; | ||
1036 | acx->ack_policy = ack_policy; | ||
1037 | |||
1038 | ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | ||
1039 | if (ret < 0) { | ||
1040 | wl1251_warning("acx tid cfg failed: %d", ret); | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | out: | ||
1045 | kfree(acx); | ||
1046 | return ret; | ||
1047 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 652371432cd..26160c45784 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -1166,6 +1166,87 @@ struct wl1251_acx_wr_tbtt_and_dtim { | |||
1166 | u8 padding; | 1166 | u8 padding; |
1167 | } __attribute__ ((packed)); | 1167 | } __attribute__ ((packed)); |
1168 | 1168 | ||
1169 | struct wl1251_acx_ac_cfg { | ||
1170 | struct acx_header header; | ||
1171 | |||
1172 | /* | ||
1173 | * Access Category - The TX queue's access category | ||
1174 | * (refer to AccessCategory_enum) | ||
1175 | */ | ||
1176 | u8 ac; | ||
1177 | |||
1178 | /* | ||
1179 | * The contention window minimum size (in slots) for | ||
1180 | * the access class. | ||
1181 | */ | ||
1182 | u8 cw_min; | ||
1183 | |||
1184 | /* | ||
1185 | * The contention window maximum size (in slots) for | ||
1186 | * the access class. | ||
1187 | */ | ||
1188 | u16 cw_max; | ||
1189 | |||
1190 | /* The AIF value (in slots) for the access class. */ | ||
1191 | u8 aifsn; | ||
1192 | |||
1193 | u8 reserved; | ||
1194 | |||
1195 | /* The TX Op Limit (in microseconds) for the access class. */ | ||
1196 | u16 txop_limit; | ||
1197 | } __attribute__ ((packed)); | ||
1198 | |||
1199 | |||
1200 | enum wl1251_acx_channel_type { | ||
1201 | CHANNEL_TYPE_DCF = 0, | ||
1202 | CHANNEL_TYPE_EDCF = 1, | ||
1203 | CHANNEL_TYPE_HCCA = 2, | ||
1204 | }; | ||
1205 | |||
1206 | enum wl1251_acx_ps_scheme { | ||
1207 | /* regular ps: simple sending of packets */ | ||
1208 | WL1251_ACX_PS_SCHEME_LEGACY = 0, | ||
1209 | |||
1210 | /* sending a packet triggers a unscheduled apsd downstream */ | ||
1211 | WL1251_ACX_PS_SCHEME_UPSD_TRIGGER = 1, | ||
1212 | |||
1213 | /* a pspoll packet will be sent before every data packet */ | ||
1214 | WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, | ||
1215 | |||
1216 | /* scheduled apsd mode */ | ||
1217 | WL1251_ACX_PS_SCHEME_SAPSD = 3, | ||
1218 | }; | ||
1219 | |||
1220 | enum wl1251_acx_ack_policy { | ||
1221 | WL1251_ACX_ACK_POLICY_LEGACY = 0, | ||
1222 | WL1251_ACX_ACK_POLICY_NO_ACK = 1, | ||
1223 | WL1251_ACX_ACK_POLICY_BLOCK = 2, | ||
1224 | }; | ||
1225 | |||
1226 | struct wl1251_acx_tid_cfg { | ||
1227 | struct acx_header header; | ||
1228 | |||
1229 | /* tx queue id number (0-7) */ | ||
1230 | u8 queue; | ||
1231 | |||
1232 | /* channel access type for the queue, enum wl1251_acx_channel_type */ | ||
1233 | u8 type; | ||
1234 | |||
1235 | /* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */ | ||
1236 | u8 tsid; | ||
1237 | |||
1238 | /* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */ | ||
1239 | u8 ps_scheme; | ||
1240 | |||
1241 | /* the tx queue ack policy, enum wl1251_acx_ack_policy */ | ||
1242 | u8 ack_policy; | ||
1243 | |||
1244 | u8 padding[3]; | ||
1245 | |||
1246 | /* not supported */ | ||
1247 | u32 apsdconf[2]; | ||
1248 | } __attribute__ ((packed)); | ||
1249 | |||
1169 | /************************************************************************* | 1250 | /************************************************************************* |
1170 | 1251 | ||
1171 | Host Interrupt Register (WiLink -> Host) | 1252 | Host Interrupt Register (WiLink -> Host) |
@@ -1322,5 +1403,11 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | |||
1322 | int wl1251_acx_rate_policies(struct wl1251 *wl); | 1403 | int wl1251_acx_rate_policies(struct wl1251 *wl); |
1323 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | 1404 | int wl1251_acx_mem_cfg(struct wl1251 *wl); |
1324 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | 1405 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); |
1406 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
1407 | u8 aifs, u16 txop); | ||
1408 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1409 | enum wl1251_acx_channel_type type, | ||
1410 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1411 | enum wl1251_acx_ack_policy ack_policy); | ||
1325 | 1412 | ||
1326 | #endif /* __WL1251_ACX_H__ */ | 1413 | #endif /* __WL1251_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index 770f260726b..0320b478bb3 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c | |||
@@ -410,3 +410,86 @@ out: | |||
410 | kfree(cmd); | 410 | kfree(cmd); |
411 | return ret; | 411 | return ret; |
412 | } | 412 | } |
413 | |||
414 | int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | ||
415 | struct ieee80211_channel *channels[], | ||
416 | unsigned int n_channels, unsigned int n_probes) | ||
417 | { | ||
418 | struct wl1251_cmd_scan *cmd; | ||
419 | int i, ret = 0; | ||
420 | |||
421 | wl1251_debug(DEBUG_CMD, "cmd scan"); | ||
422 | |||
423 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
424 | if (!cmd) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
428 | cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | | ||
429 | CFG_RX_MGMT_EN | | ||
430 | CFG_RX_BCN_EN); | ||
431 | cmd->params.scan_options = 0; | ||
432 | cmd->params.num_channels = n_channels; | ||
433 | cmd->params.num_probe_requests = n_probes; | ||
434 | cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | ||
435 | cmd->params.tid_trigger = 0; | ||
436 | |||
437 | for (i = 0; i < n_channels; i++) { | ||
438 | cmd->channels[i].min_duration = | ||
439 | cpu_to_le32(WL1251_SCAN_MIN_DURATION); | ||
440 | cmd->channels[i].max_duration = | ||
441 | cpu_to_le32(WL1251_SCAN_MAX_DURATION); | ||
442 | memset(&cmd->channels[i].bssid_lsb, 0xff, 4); | ||
443 | memset(&cmd->channels[i].bssid_msb, 0xff, 2); | ||
444 | cmd->channels[i].early_termination = 0; | ||
445 | cmd->channels[i].tx_power_att = 0; | ||
446 | cmd->channels[i].channel = channels[i]->hw_value; | ||
447 | } | ||
448 | |||
449 | cmd->params.ssid_len = ssid_len; | ||
450 | if (ssid) | ||
451 | memcpy(cmd->params.ssid, ssid, ssid_len); | ||
452 | |||
453 | ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); | ||
454 | if (ret < 0) { | ||
455 | wl1251_error("cmd scan failed: %d", ret); | ||
456 | goto out; | ||
457 | } | ||
458 | |||
459 | wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); | ||
460 | |||
461 | if (cmd->header.status != CMD_STATUS_SUCCESS) { | ||
462 | wl1251_error("cmd scan status wasn't success: %d", | ||
463 | cmd->header.status); | ||
464 | ret = -EIO; | ||
465 | goto out; | ||
466 | } | ||
467 | |||
468 | out: | ||
469 | kfree(cmd); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) | ||
474 | { | ||
475 | struct wl1251_cmd_trigger_scan_to *cmd; | ||
476 | int ret; | ||
477 | |||
478 | wl1251_debug(DEBUG_CMD, "cmd trigger scan to"); | ||
479 | |||
480 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
481 | if (!cmd) | ||
482 | return -ENOMEM; | ||
483 | |||
484 | cmd->timeout = timeout; | ||
485 | |||
486 | ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); | ||
487 | if (ret < 0) { | ||
488 | wl1251_error("cmd trigger scan to failed: %d", ret); | ||
489 | goto out; | ||
490 | } | ||
491 | |||
492 | out: | ||
493 | kfree(cmd); | ||
494 | return ret; | ||
495 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index dff798ad0ef..4ad67cae94d 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #include "wl1251.h" | 28 | #include "wl1251.h" |
29 | 29 | ||
30 | #include <net/cfg80211.h> | ||
31 | |||
30 | struct acx_header; | 32 | struct acx_header; |
31 | 33 | ||
32 | int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); | 34 | int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); |
@@ -43,6 +45,10 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, | |||
43 | size_t len); | 45 | size_t len); |
44 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, | 46 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, |
45 | void *buf, size_t buf_len); | 47 | void *buf, size_t buf_len); |
48 | int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | ||
49 | struct ieee80211_channel *channels[], | ||
50 | unsigned int n_channels, unsigned int n_probes); | ||
51 | int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout); | ||
46 | 52 | ||
47 | /* unit ms */ | 53 | /* unit ms */ |
48 | #define WL1251_COMMAND_TIMEOUT 2000 | 54 | #define WL1251_COMMAND_TIMEOUT 2000 |
@@ -163,8 +169,12 @@ struct cmd_read_write_memory { | |||
163 | #define CMDMBOX_HEADER_LEN 4 | 169 | #define CMDMBOX_HEADER_LEN 4 |
164 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
165 | 171 | ||
172 | #define WL1251_SCAN_MIN_DURATION 30000 | ||
173 | #define WL1251_SCAN_MAX_DURATION 60000 | ||
174 | |||
175 | #define WL1251_SCAN_NUM_PROBES 3 | ||
166 | 176 | ||
167 | struct basic_scan_parameters { | 177 | struct wl1251_scan_parameters { |
168 | u32 rx_config_options; | 178 | u32 rx_config_options; |
169 | u32 rx_filter_options; | 179 | u32 rx_filter_options; |
170 | 180 | ||
@@ -189,11 +199,11 @@ struct basic_scan_parameters { | |||
189 | 199 | ||
190 | u8 tid_trigger; | 200 | u8 tid_trigger; |
191 | u8 ssid_len; | 201 | u8 ssid_len; |
192 | u32 ssid[8]; | 202 | u8 ssid[32]; |
193 | 203 | ||
194 | } __attribute__ ((packed)); | 204 | } __attribute__ ((packed)); |
195 | 205 | ||
196 | struct basic_scan_channel_parameters { | 206 | struct wl1251_scan_ch_parameters { |
197 | u32 min_duration; /* in TU */ | 207 | u32 min_duration; /* in TU */ |
198 | u32 max_duration; /* in TU */ | 208 | u32 max_duration; /* in TU */ |
199 | u32 bssid_lsb; | 209 | u32 bssid_lsb; |
@@ -213,11 +223,11 @@ struct basic_scan_channel_parameters { | |||
213 | /* SCAN parameters */ | 223 | /* SCAN parameters */ |
214 | #define SCAN_MAX_NUM_OF_CHANNELS 16 | 224 | #define SCAN_MAX_NUM_OF_CHANNELS 16 |
215 | 225 | ||
216 | struct cmd_scan { | 226 | struct wl1251_cmd_scan { |
217 | struct wl1251_cmd_header header; | 227 | struct wl1251_cmd_header header; |
218 | 228 | ||
219 | struct basic_scan_parameters params; | 229 | struct wl1251_scan_parameters params; |
220 | struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; | 230 | struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; |
221 | } __attribute__ ((packed)); | 231 | } __attribute__ ((packed)); |
222 | 232 | ||
223 | enum { | 233 | enum { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c index a00723059f8..0ccba57fb9f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c | |||
@@ -237,6 +237,27 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1251_open_file_generic, | 237 | .open = wl1251_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1251 *wl = file->private_data; | ||
244 | char buf[3], status; | ||
245 | int len; | ||
246 | |||
247 | if (wl->tx_queue_stopped) | ||
248 | status = 's'; | ||
249 | else | ||
250 | status = 'r'; | ||
251 | |||
252 | len = scnprintf(buf, sizeof(buf), "%c\n", status); | ||
253 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
254 | } | ||
255 | |||
256 | static const struct file_operations tx_queue_status_ops = { | ||
257 | .read = tx_queue_status_read, | ||
258 | .open = wl1251_open_file_generic, | ||
259 | }; | ||
260 | |||
240 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) | 261 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) |
241 | { | 262 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 263 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -331,6 +352,7 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl) | |||
331 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); | 352 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); |
332 | 353 | ||
333 | DEBUGFS_DEL(tx_queue_len); | 354 | DEBUGFS_DEL(tx_queue_len); |
355 | DEBUGFS_DEL(tx_queue_status); | ||
334 | DEBUGFS_DEL(retry_count); | 356 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 357 | DEBUGFS_DEL(excessive_retries); |
336 | } | 358 | } |
@@ -431,6 +453,7 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl) | |||
431 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | 453 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); |
432 | 454 | ||
433 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); | 455 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); |
456 | DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); | ||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 457 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 458 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 459 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index 5cb573383ee..5aad56ea715 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c | |||
@@ -294,6 +294,11 @@ static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) | |||
294 | goto out; | 294 | goto out; |
295 | } | 295 | } |
296 | 296 | ||
297 | wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); | ||
298 | wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); | ||
299 | wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); | ||
300 | wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); | ||
301 | |||
297 | out: | 302 | out: |
298 | kfree(config); | 303 | kfree(config); |
299 | return ret; | 304 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h index b3b25ec885e..269cefb3e7d 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ b/drivers/net/wireless/wl12xx/wl1251_init.h | |||
@@ -26,6 +26,53 @@ | |||
26 | 26 | ||
27 | #include "wl1251.h" | 27 | #include "wl1251.h" |
28 | 28 | ||
29 | enum { | ||
30 | /* best effort/legacy */ | ||
31 | AC_BE = 0, | ||
32 | |||
33 | /* background */ | ||
34 | AC_BK = 1, | ||
35 | |||
36 | /* video */ | ||
37 | AC_VI = 2, | ||
38 | |||
39 | /* voice */ | ||
40 | AC_VO = 3, | ||
41 | |||
42 | /* broadcast dummy access category */ | ||
43 | AC_BCAST = 4, | ||
44 | |||
45 | NUM_ACCESS_CATEGORIES = 4 | ||
46 | }; | ||
47 | |||
48 | /* following are defult values for the IE fields*/ | ||
49 | #define CWMIN_BK 15 | ||
50 | #define CWMIN_BE 15 | ||
51 | #define CWMIN_VI 7 | ||
52 | #define CWMIN_VO 3 | ||
53 | #define CWMAX_BK 1023 | ||
54 | #define CWMAX_BE 63 | ||
55 | #define CWMAX_VI 15 | ||
56 | #define CWMAX_VO 7 | ||
57 | |||
58 | /* slot number setting to start transmission at PIFS interval */ | ||
59 | #define AIFS_PIFS 1 | ||
60 | |||
61 | /* | ||
62 | * slot number setting to start transmission at DIFS interval - normal DCF | ||
63 | * access | ||
64 | */ | ||
65 | #define AIFS_DIFS 2 | ||
66 | |||
67 | #define AIFSN_BK 7 | ||
68 | #define AIFSN_BE 3 | ||
69 | #define AIFSN_VI AIFS_PIFS | ||
70 | #define AIFSN_VO AIFS_PIFS | ||
71 | #define TXOP_BK 0 | ||
72 | #define TXOP_BE 0 | ||
73 | #define TXOP_VI 3008 | ||
74 | #define TXOP_VO 1504 | ||
75 | |||
29 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); | 76 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); |
30 | int wl1251_hw_init_templates_config(struct wl1251 *wl); | 77 | int wl1251_hw_init_templates_config(struct wl1251 *wl); |
31 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); | 78 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 2f50a256efa..595f0f94d16 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -395,6 +395,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
395 | * the queue here, otherwise the queue will get too long. | 395 | * the queue here, otherwise the queue will get too long. |
396 | */ | 396 | */ |
397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { | 397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { |
398 | wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); | ||
398 | ieee80211_stop_queues(wl->hw); | 399 | ieee80211_stop_queues(wl->hw); |
399 | 400 | ||
400 | /* | 401 | /* |
@@ -510,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
510 | } | 511 | } |
511 | 512 | ||
512 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, | 513 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, |
513 | struct ieee80211_if_init_conf *conf) | 514 | struct ieee80211_vif *vif) |
514 | { | 515 | { |
515 | struct wl1251 *wl = hw->priv; | 516 | struct wl1251 *wl = hw->priv; |
516 | int ret = 0; | 517 | int ret = 0; |
517 | 518 | ||
518 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 519 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
519 | conf->type, conf->mac_addr); | 520 | vif->type, vif->addr); |
520 | 521 | ||
521 | mutex_lock(&wl->mutex); | 522 | mutex_lock(&wl->mutex); |
522 | if (wl->vif) { | 523 | if (wl->vif) { |
@@ -524,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
524 | goto out; | 525 | goto out; |
525 | } | 526 | } |
526 | 527 | ||
527 | wl->vif = conf->vif; | 528 | wl->vif = vif; |
528 | 529 | ||
529 | switch (conf->type) { | 530 | switch (vif->type) { |
530 | case NL80211_IFTYPE_STATION: | 531 | case NL80211_IFTYPE_STATION: |
531 | wl->bss_type = BSS_TYPE_STA_BSS; | 532 | wl->bss_type = BSS_TYPE_STA_BSS; |
532 | break; | 533 | break; |
@@ -538,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
538 | goto out; | 539 | goto out; |
539 | } | 540 | } |
540 | 541 | ||
541 | if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { | 542 | if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { |
542 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 543 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
543 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 544 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
544 | ret = wl1251_acx_station_id(wl); | 545 | ret = wl1251_acx_station_id(wl); |
545 | if (ret < 0) | 546 | if (ret < 0) |
@@ -552,7 +553,7 @@ out: | |||
552 | } | 553 | } |
553 | 554 | ||
554 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | 555 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, |
555 | struct ieee80211_if_init_conf *conf) | 556 | struct ieee80211_vif *vif) |
556 | { | 557 | { |
557 | struct wl1251 *wl = hw->priv; | 558 | struct wl1251 *wl = hw->priv; |
558 | 559 | ||
@@ -562,43 +563,25 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | |||
562 | mutex_unlock(&wl->mutex); | 563 | mutex_unlock(&wl->mutex); |
563 | } | 564 | } |
564 | 565 | ||
565 | static int wl1251_build_null_data(struct wl1251 *wl) | 566 | static int wl1251_build_qos_null_data(struct wl1251 *wl) |
566 | { | 567 | { |
567 | struct wl12xx_null_data_template template; | 568 | struct ieee80211_qos_hdr template; |
568 | 569 | ||
569 | if (!is_zero_ether_addr(wl->bssid)) { | 570 | memset(&template, 0, sizeof(template)); |
570 | memcpy(template.header.da, wl->bssid, ETH_ALEN); | ||
571 | memcpy(template.header.bssid, wl->bssid, ETH_ALEN); | ||
572 | } else { | ||
573 | memset(template.header.da, 0xff, ETH_ALEN); | ||
574 | memset(template.header.bssid, 0xff, ETH_ALEN); | ||
575 | } | ||
576 | |||
577 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | ||
578 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
579 | IEEE80211_STYPE_NULLFUNC | | ||
580 | IEEE80211_FCTL_TODS); | ||
581 | |||
582 | return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, | ||
583 | sizeof(template)); | ||
584 | |||
585 | } | ||
586 | |||
587 | static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid) | ||
588 | { | ||
589 | struct wl12xx_ps_poll_template template; | ||
590 | 571 | ||
591 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | 572 | memcpy(template.addr1, wl->bssid, ETH_ALEN); |
592 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | 573 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); |
574 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
593 | 575 | ||
594 | /* aid in PS-Poll has its two MSBs each set to 1 */ | 576 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | |
595 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | 577 | IEEE80211_STYPE_QOS_NULLFUNC | |
578 | IEEE80211_FCTL_TODS); | ||
596 | 579 | ||
597 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 580 | /* FIXME: not sure what priority to use here */ |
581 | template.qos_ctrl = cpu_to_le16(0); | ||
598 | 582 | ||
599 | return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, | 583 | return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template, |
600 | sizeof(template)); | 584 | sizeof(template)); |
601 | |||
602 | } | 585 | } |
603 | 586 | ||
604 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | 587 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) |
@@ -640,20 +623,25 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
640 | * through the bss_info_changed() hook. | 623 | * through the bss_info_changed() hook. |
641 | */ | 624 | */ |
642 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 625 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); |
626 | if (ret < 0) | ||
627 | goto out_sleep; | ||
643 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 628 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
644 | wl->psm_requested) { | 629 | wl->psm_requested) { |
645 | wl1251_debug(DEBUG_PSM, "psm disabled"); | 630 | wl1251_debug(DEBUG_PSM, "psm disabled"); |
646 | 631 | ||
647 | wl->psm_requested = false; | 632 | wl->psm_requested = false; |
648 | 633 | ||
649 | if (wl->psm) | 634 | if (wl->psm) { |
650 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | 635 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); |
636 | if (ret < 0) | ||
637 | goto out_sleep; | ||
638 | } | ||
651 | } | 639 | } |
652 | 640 | ||
653 | if (conf->power_level != wl->power_level) { | 641 | if (conf->power_level != wl->power_level) { |
654 | ret = wl1251_acx_tx_power(wl, conf->power_level); | 642 | ret = wl1251_acx_tx_power(wl, conf->power_level); |
655 | if (ret < 0) | 643 | if (ret < 0) |
656 | goto out; | 644 | goto out_sleep; |
657 | 645 | ||
658 | wl->power_level = conf->power_level; | 646 | wl->power_level = conf->power_level; |
659 | } | 647 | } |
@@ -864,199 +852,61 @@ out: | |||
864 | return ret; | 852 | return ret; |
865 | } | 853 | } |
866 | 854 | ||
867 | static int wl1251_build_basic_rates(char *rates) | 855 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, |
868 | { | 856 | struct cfg80211_scan_request *req) |
869 | u8 index = 0; | ||
870 | |||
871 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | ||
872 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
873 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
874 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
875 | |||
876 | return index; | ||
877 | } | ||
878 | |||
879 | static int wl1251_build_extended_rates(char *rates) | ||
880 | { | 857 | { |
881 | u8 index = 0; | 858 | struct wl1251 *wl = hw->priv; |
882 | 859 | struct sk_buff *skb; | |
883 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | 860 | size_t ssid_len = 0; |
884 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | 861 | u8 *ssid = NULL; |
885 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | 862 | int ret; |
886 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | ||
887 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | ||
888 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | ||
889 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | ||
890 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
891 | |||
892 | return index; | ||
893 | } | ||
894 | |||
895 | 863 | ||
896 | static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len) | 864 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); |
897 | { | ||
898 | struct wl12xx_probe_req_template template; | ||
899 | struct wl12xx_ie_rates *rates; | ||
900 | char *ptr; | ||
901 | u16 size; | ||
902 | |||
903 | ptr = (char *)&template; | ||
904 | size = sizeof(struct ieee80211_header); | ||
905 | |||
906 | memset(template.header.da, 0xff, ETH_ALEN); | ||
907 | memset(template.header.bssid, 0xff, ETH_ALEN); | ||
908 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | ||
909 | template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | ||
910 | |||
911 | /* IEs */ | ||
912 | /* SSID */ | ||
913 | template.ssid.header.id = WLAN_EID_SSID; | ||
914 | template.ssid.header.len = ssid_len; | ||
915 | if (ssid_len && ssid) | ||
916 | memcpy(template.ssid.ssid, ssid, ssid_len); | ||
917 | size += sizeof(struct wl12xx_ie_header) + ssid_len; | ||
918 | ptr += size; | ||
919 | |||
920 | /* Basic Rates */ | ||
921 | rates = (struct wl12xx_ie_rates *)ptr; | ||
922 | rates->header.id = WLAN_EID_SUPP_RATES; | ||
923 | rates->header.len = wl1251_build_basic_rates(rates->rates); | ||
924 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
925 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
926 | |||
927 | /* Extended rates */ | ||
928 | rates = (struct wl12xx_ie_rates *)ptr; | ||
929 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | ||
930 | rates->header.len = wl1251_build_extended_rates(rates->rates); | ||
931 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | ||
932 | |||
933 | wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | ||
934 | |||
935 | return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template, | ||
936 | size); | ||
937 | } | ||
938 | 865 | ||
939 | static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len, | 866 | if (req->n_ssids) { |
940 | u8 active_scan, u8 high_prio, u8 num_channels, | 867 | ssid = req->ssids[0].ssid; |
941 | u8 probe_requests) | 868 | ssid_len = req->ssids[0].ssid_len; |
942 | { | ||
943 | struct wl1251_cmd_trigger_scan_to *trigger = NULL; | ||
944 | struct cmd_scan *params = NULL; | ||
945 | int i, ret; | ||
946 | u16 scan_options = 0; | ||
947 | |||
948 | if (wl->scanning) | ||
949 | return -EINVAL; | ||
950 | |||
951 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
952 | if (!params) | ||
953 | return -ENOMEM; | ||
954 | |||
955 | params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
956 | params->params.rx_filter_options = | ||
957 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
958 | |||
959 | /* High priority scan */ | ||
960 | if (!active_scan) | ||
961 | scan_options |= SCAN_PASSIVE; | ||
962 | if (high_prio) | ||
963 | scan_options |= SCAN_PRIORITY_HIGH; | ||
964 | params->params.scan_options = scan_options; | ||
965 | |||
966 | params->params.num_channels = num_channels; | ||
967 | params->params.num_probe_requests = probe_requests; | ||
968 | params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | ||
969 | params->params.tid_trigger = 0; | ||
970 | |||
971 | for (i = 0; i < num_channels; i++) { | ||
972 | params->channels[i].min_duration = cpu_to_le32(30000); | ||
973 | params->channels[i].max_duration = cpu_to_le32(60000); | ||
974 | memset(¶ms->channels[i].bssid_lsb, 0xff, 4); | ||
975 | memset(¶ms->channels[i].bssid_msb, 0xff, 2); | ||
976 | params->channels[i].early_termination = 0; | ||
977 | params->channels[i].tx_power_att = 0; | ||
978 | params->channels[i].channel = i + 1; | ||
979 | memset(params->channels[i].pad, 0, 3); | ||
980 | } | 869 | } |
981 | 870 | ||
982 | for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) | 871 | mutex_lock(&wl->mutex); |
983 | memset(¶ms->channels[i], 0, | ||
984 | sizeof(struct basic_scan_channel_parameters)); | ||
985 | |||
986 | if (len && ssid) { | ||
987 | params->params.ssid_len = len; | ||
988 | memcpy(params->params.ssid, ssid, len); | ||
989 | } else { | ||
990 | params->params.ssid_len = 0; | ||
991 | memset(params->params.ssid, 0, 32); | ||
992 | } | ||
993 | 872 | ||
994 | ret = wl1251_build_probe_req(wl, ssid, len); | 873 | if (wl->scanning) { |
995 | if (ret < 0) { | 874 | wl1251_debug(DEBUG_SCAN, "scan already in progress"); |
996 | wl1251_error("PROBE request template failed"); | 875 | ret = -EINVAL; |
997 | goto out; | 876 | goto out; |
998 | } | 877 | } |
999 | 878 | ||
1000 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | 879 | ret = wl1251_ps_elp_wakeup(wl); |
1001 | if (!trigger) | 880 | if (ret < 0) |
1002 | goto out; | 881 | goto out; |
1003 | 882 | ||
1004 | trigger->timeout = 0; | 883 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
1005 | 884 | req->ie, req->ie_len); | |
1006 | ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | 885 | if (!skb) { |
1007 | sizeof(*trigger)); | 886 | ret = -ENOMEM; |
1008 | if (ret < 0) { | ||
1009 | wl1251_error("trigger scan to failed for hw scan"); | ||
1010 | goto out; | 887 | goto out; |
1011 | } | 888 | } |
1012 | 889 | ||
1013 | wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 890 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, |
1014 | 891 | skb->len); | |
1015 | wl->scanning = true; | 892 | dev_kfree_skb(skb); |
893 | if (ret < 0) | ||
894 | goto out_sleep; | ||
1016 | 895 | ||
1017 | ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); | 896 | ret = wl1251_cmd_trigger_scan_to(wl, 0); |
1018 | if (ret < 0) | 897 | if (ret < 0) |
1019 | wl1251_error("SCAN failed"); | 898 | goto out_sleep; |
1020 | 899 | ||
1021 | wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); | 900 | wl->scanning = true; |
1022 | 901 | ||
1023 | if (params->header.status != CMD_STATUS_SUCCESS) { | 902 | ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, |
1024 | wl1251_error("TEST command answer error: %d", | 903 | req->n_channels, WL1251_SCAN_NUM_PROBES); |
1025 | params->header.status); | 904 | if (ret < 0) { |
1026 | wl->scanning = false; | 905 | wl->scanning = false; |
1027 | ret = -EIO; | 906 | goto out_sleep; |
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | out: | ||
1032 | kfree(params); | ||
1033 | return ret; | ||
1034 | |||
1035 | } | ||
1036 | |||
1037 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | ||
1038 | struct cfg80211_scan_request *req) | ||
1039 | { | ||
1040 | struct wl1251 *wl = hw->priv; | ||
1041 | int ret; | ||
1042 | u8 *ssid = NULL; | ||
1043 | size_t ssid_len = 0; | ||
1044 | |||
1045 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); | ||
1046 | |||
1047 | if (req->n_ssids) { | ||
1048 | ssid = req->ssids[0].ssid; | ||
1049 | ssid_len = req->ssids[0].ssid_len; | ||
1050 | } | 907 | } |
1051 | 908 | ||
1052 | mutex_lock(&wl->mutex); | 909 | out_sleep: |
1053 | |||
1054 | ret = wl1251_ps_elp_wakeup(wl); | ||
1055 | if (ret < 0) | ||
1056 | goto out; | ||
1057 | |||
1058 | ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); | ||
1059 | |||
1060 | wl1251_ps_elp_sleep(wl); | 910 | wl1251_ps_elp_sleep(wl); |
1061 | 911 | ||
1062 | out: | 912 | out: |
@@ -1095,7 +945,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1095 | { | 945 | { |
1096 | enum wl1251_cmd_ps_mode mode; | 946 | enum wl1251_cmd_ps_mode mode; |
1097 | struct wl1251 *wl = hw->priv; | 947 | struct wl1251 *wl = hw->priv; |
1098 | struct sk_buff *beacon; | 948 | struct sk_buff *beacon, *skb; |
1099 | int ret; | 949 | int ret; |
1100 | 950 | ||
1101 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 951 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1109,7 +959,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1109 | if (changed & BSS_CHANGED_BSSID) { | 959 | if (changed & BSS_CHANGED_BSSID) { |
1110 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 960 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1111 | 961 | ||
1112 | ret = wl1251_build_null_data(wl); | 962 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); |
963 | if (!skb) | ||
964 | goto out_sleep; | ||
965 | |||
966 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, | ||
967 | skb->data, skb->len); | ||
968 | dev_kfree_skb(skb); | ||
969 | if (ret < 0) | ||
970 | goto out_sleep; | ||
971 | |||
972 | ret = wl1251_build_qos_null_data(wl); | ||
1113 | if (ret < 0) | 973 | if (ret < 0) |
1114 | goto out; | 974 | goto out; |
1115 | 975 | ||
@@ -1130,7 +990,14 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1130 | wl->dtim_period); | 990 | wl->dtim_period); |
1131 | wl->aid = bss_conf->aid; | 991 | wl->aid = bss_conf->aid; |
1132 | 992 | ||
1133 | ret = wl1251_build_ps_poll(wl, wl->aid); | 993 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); |
994 | if (!skb) | ||
995 | goto out_sleep; | ||
996 | |||
997 | ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, | ||
998 | skb->data, | ||
999 | skb->len); | ||
1000 | dev_kfree_skb(skb); | ||
1134 | if (ret < 0) | 1001 | if (ret < 0) |
1135 | goto out_sleep; | 1002 | goto out_sleep; |
1136 | 1003 | ||
@@ -1176,7 +1043,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1176 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); | 1043 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); |
1177 | if (ret < 0) { | 1044 | if (ret < 0) { |
1178 | wl1251_warning("Set ctsprotect failed %d", ret); | 1045 | wl1251_warning("Set ctsprotect failed %d", ret); |
1179 | goto out; | 1046 | goto out_sleep; |
1180 | } | 1047 | } |
1181 | } | 1048 | } |
1182 | 1049 | ||
@@ -1187,7 +1054,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1187 | 1054 | ||
1188 | if (ret < 0) { | 1055 | if (ret < 0) { |
1189 | dev_kfree_skb(beacon); | 1056 | dev_kfree_skb(beacon); |
1190 | goto out; | 1057 | goto out_sleep; |
1191 | } | 1058 | } |
1192 | 1059 | ||
1193 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, | 1060 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, |
@@ -1196,13 +1063,13 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1196 | dev_kfree_skb(beacon); | 1063 | dev_kfree_skb(beacon); |
1197 | 1064 | ||
1198 | if (ret < 0) | 1065 | if (ret < 0) |
1199 | goto out; | 1066 | goto out_sleep; |
1200 | 1067 | ||
1201 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, | 1068 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, |
1202 | wl->channel, wl->dtim_period); | 1069 | wl->channel, wl->dtim_period); |
1203 | 1070 | ||
1204 | if (ret < 0) | 1071 | if (ret < 0) |
1205 | goto out; | 1072 | goto out_sleep; |
1206 | } | 1073 | } |
1207 | 1074 | ||
1208 | out_sleep: | 1075 | out_sleep: |
@@ -1273,6 +1140,48 @@ static struct ieee80211_channel wl1251_channels[] = { | |||
1273 | { .hw_value = 13, .center_freq = 2472}, | 1140 | { .hw_value = 13, .center_freq = 2472}, |
1274 | }; | 1141 | }; |
1275 | 1142 | ||
1143 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1144 | const struct ieee80211_tx_queue_params *params) | ||
1145 | { | ||
1146 | enum wl1251_acx_ps_scheme ps_scheme; | ||
1147 | struct wl1251 *wl = hw->priv; | ||
1148 | int ret; | ||
1149 | |||
1150 | mutex_lock(&wl->mutex); | ||
1151 | |||
1152 | wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1153 | |||
1154 | ret = wl1251_ps_elp_wakeup(wl); | ||
1155 | if (ret < 0) | ||
1156 | goto out; | ||
1157 | |||
1158 | ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), | ||
1159 | params->cw_min, params->cw_max, | ||
1160 | params->aifs, params->txop); | ||
1161 | if (ret < 0) | ||
1162 | goto out_sleep; | ||
1163 | |||
1164 | if (params->uapsd) | ||
1165 | ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER; | ||
1166 | else | ||
1167 | ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY; | ||
1168 | |||
1169 | ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), | ||
1170 | CHANNEL_TYPE_EDCF, | ||
1171 | wl1251_tx_get_queue(queue), ps_scheme, | ||
1172 | WL1251_ACX_ACK_POLICY_LEGACY); | ||
1173 | if (ret < 0) | ||
1174 | goto out_sleep; | ||
1175 | |||
1176 | out_sleep: | ||
1177 | wl1251_ps_elp_sleep(wl); | ||
1178 | |||
1179 | out: | ||
1180 | mutex_unlock(&wl->mutex); | ||
1181 | |||
1182 | return ret; | ||
1183 | } | ||
1184 | |||
1276 | /* can't be const, mac80211 writes to this */ | 1185 | /* can't be const, mac80211 writes to this */ |
1277 | static struct ieee80211_supported_band wl1251_band_2ghz = { | 1186 | static struct ieee80211_supported_band wl1251_band_2ghz = { |
1278 | .channels = wl1251_channels, | 1187 | .channels = wl1251_channels, |
@@ -1293,6 +1202,7 @@ static const struct ieee80211_ops wl1251_ops = { | |||
1293 | .hw_scan = wl1251_op_hw_scan, | 1202 | .hw_scan = wl1251_op_hw_scan, |
1294 | .bss_info_changed = wl1251_op_bss_info_changed, | 1203 | .bss_info_changed = wl1251_op_bss_info_changed, |
1295 | .set_rts_threshold = wl1251_op_set_rts_threshold, | 1204 | .set_rts_threshold = wl1251_op_set_rts_threshold, |
1205 | .conf_tx = wl1251_op_conf_tx, | ||
1296 | }; | 1206 | }; |
1297 | 1207 | ||
1298 | static int wl1251_register_hw(struct wl1251 *wl) | 1208 | static int wl1251_register_hw(struct wl1251 *wl) |
@@ -1332,12 +1242,15 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1332 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1242 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1333 | IEEE80211_HW_NOISE_DBM | | 1243 | IEEE80211_HW_NOISE_DBM | |
1334 | IEEE80211_HW_SUPPORTS_PS | | 1244 | IEEE80211_HW_SUPPORTS_PS | |
1335 | IEEE80211_HW_BEACON_FILTER; | 1245 | IEEE80211_HW_BEACON_FILTER | |
1246 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
1336 | 1247 | ||
1337 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1248 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
1338 | wl->hw->wiphy->max_scan_ssids = 1; | 1249 | wl->hw->wiphy->max_scan_ssids = 1; |
1339 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; | 1250 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; |
1340 | 1251 | ||
1252 | wl->hw->queues = 4; | ||
1253 | |||
1341 | ret = wl1251_register_hw(wl); | 1254 | ret = wl1251_register_hw(wl); |
1342 | if (ret) | 1255 | if (ret) |
1343 | goto out; | 1256 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 9931b197ff7..851dfb65e47 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include "wl1251_cmd.h" | 26 | #include "wl1251_cmd.h" |
27 | #include "wl1251_io.h" | 27 | #include "wl1251_io.h" |
28 | 28 | ||
29 | #define WL1251_WAKEUP_TIMEOUT 2000 | 29 | /* in ms */ |
30 | #define WL1251_WAKEUP_TIMEOUT 100 | ||
30 | 31 | ||
31 | void wl1251_elp_work(struct work_struct *work) | 32 | void wl1251_elp_work(struct work_struct *work) |
32 | { | 33 | { |
@@ -67,7 +68,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) | |||
67 | 68 | ||
68 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | 69 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) |
69 | { | 70 | { |
70 | unsigned long timeout; | 71 | unsigned long timeout, start; |
71 | u32 elp_reg; | 72 | u32 elp_reg; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!wl->elp) |
@@ -75,6 +76,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
75 | 76 | ||
76 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); |
77 | 78 | ||
79 | start = jiffies; | ||
78 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); |
79 | 81 | ||
80 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 82 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
@@ -95,8 +97,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
95 | } | 97 | } |
96 | 98 | ||
97 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | 99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", |
98 | jiffies_to_msecs(jiffies) - | 100 | jiffies_to_msecs(jiffies - start)); |
99 | (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); | ||
100 | 101 | ||
101 | wl->elp = false; | 102 | wl->elp = false; |
102 | 103 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index f84cc89cbff..b56732226cc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -126,7 +126,7 @@ static void wl1251_rx_body(struct wl1251 *wl, | |||
126 | if (wl->rx_current_buffer) | 126 | if (wl->rx_current_buffer) |
127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; | 127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; |
128 | 128 | ||
129 | skb = dev_alloc_skb(length); | 129 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
130 | if (!skb) { | 130 | if (!skb) { |
131 | wl1251_error("Couldn't allocate RX frame"); | 131 | wl1251_error("Couldn't allocate RX frame"); |
132 | return; | 132 | return; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index f8597061584..c8223185efd 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c | |||
@@ -167,8 +167,7 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, | |||
167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); | 167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); |
168 | tx_hdr->id = id; | 168 | tx_hdr->id = id; |
169 | 169 | ||
170 | /* FIXME: how to get the correct queue id? */ | 170 | tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb)); |
171 | tx_hdr->xmit_queue = 0; | ||
172 | 171 | ||
173 | wl1251_tx_control(tx_hdr, control, fc); | 172 | wl1251_tx_control(tx_hdr, control, fc); |
174 | wl1251_tx_frag_block_num(tx_hdr); | 173 | wl1251_tx_frag_block_num(tx_hdr); |
@@ -220,6 +219,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
220 | /* align the buffer on a 4-byte boundary */ | 219 | /* align the buffer on a 4-byte boundary */ |
221 | skb_reserve(skb, offset); | 220 | skb_reserve(skb, offset); |
222 | memmove(skb->data, src, skb->len); | 221 | memmove(skb->data, src, skb->len); |
222 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | ||
223 | } else { | 223 | } else { |
224 | wl1251_info("No handler, fixme!"); | 224 | wl1251_info("No handler, fixme!"); |
225 | return -EINVAL; | 225 | return -EINVAL; |
@@ -237,8 +237,9 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
237 | 237 | ||
238 | wl1251_mem_write(wl, addr, skb->data, len); | 238 | wl1251_mem_write(wl, addr, skb->data, len); |
239 | 239 | ||
240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", | 240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x " |
241 | tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); | 241 | "queue %d", tx_hdr->id, skb, tx_hdr->length, |
242 | tx_hdr->rate, tx_hdr->xmit_queue); | ||
242 | 243 | ||
243 | return 0; | 244 | return 0; |
244 | } | 245 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 7c1c1665c81..55856c6bb97 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define __WL1251_TX_H__ | 26 | #define __WL1251_TX_H__ |
27 | 27 | ||
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include "wl1251_acx.h" | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * | 32 | * |
@@ -209,6 +210,22 @@ struct tx_result { | |||
209 | u8 done_2; | 210 | u8 done_2; |
210 | } __attribute__ ((packed)); | 211 | } __attribute__ ((packed)); |
211 | 212 | ||
213 | static inline int wl1251_tx_get_queue(int queue) | ||
214 | { | ||
215 | switch (queue) { | ||
216 | case 0: | ||
217 | return QOS_AC_VO; | ||
218 | case 1: | ||
219 | return QOS_AC_VI; | ||
220 | case 2: | ||
221 | return QOS_AC_BE; | ||
222 | case 3: | ||
223 | return QOS_AC_BK; | ||
224 | default: | ||
225 | return QOS_AC_BE; | ||
226 | } | ||
227 | } | ||
228 | |||
212 | void wl1251_tx_work(struct work_struct *work); | 229 | void wl1251_tx_work(struct work_struct *work); |
213 | void wl1251_tx_complete(struct wl1251 *wl); | 230 | void wl1251_tx_complete(struct wl1251 *wl); |
214 | void wl1251_tx_flush(struct wl1251 *wl); | 231 | void wl1251_tx_flush(struct wl1251 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861..d0938db043b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -107,10 +107,9 @@ enum { | |||
107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
109 | 109 | ||
110 | #define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) | ||
111 | |||
112 | #define WL1271_FW_NAME "wl1271-fw.bin" | 110 | #define WL1271_FW_NAME "wl1271-fw.bin" |
113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | #define WL1271_NVS_LEN 468 | ||
114 | 113 | ||
115 | /* | 114 | /* |
116 | * Enable/disable 802.11a support for WL1273 | 115 | * Enable/disable 802.11a support for WL1273 |
@@ -276,6 +275,7 @@ struct wl1271_debugfs { | |||
276 | 275 | ||
277 | struct dentry *retry_count; | 276 | struct dentry *retry_count; |
278 | struct dentry *excessive_retries; | 277 | struct dentry *excessive_retries; |
278 | struct dentry *gpio_power; | ||
279 | }; | 279 | }; |
280 | 280 | ||
281 | #define NUM_TX_QUEUES 4 | 281 | #define NUM_TX_QUEUES 4 |
@@ -322,6 +322,17 @@ struct wl1271 { | |||
322 | enum wl1271_state state; | 322 | enum wl1271_state state; |
323 | struct mutex mutex; | 323 | struct mutex mutex; |
324 | 324 | ||
325 | #define WL1271_FLAG_STA_RATES_CHANGED (0) | ||
326 | #define WL1271_FLAG_STA_ASSOCIATED (1) | ||
327 | #define WL1271_FLAG_JOINED (2) | ||
328 | #define WL1271_FLAG_GPIO_POWER (3) | ||
329 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) | ||
330 | #define WL1271_FLAG_SCANNING (5) | ||
331 | #define WL1271_FLAG_IN_ELP (6) | ||
332 | #define WL1271_FLAG_PSM (7) | ||
333 | #define WL1271_FLAG_PSM_REQUESTED (8) | ||
334 | unsigned long flags; | ||
335 | |||
325 | struct wl1271_partition_set part; | 336 | struct wl1271_partition_set part; |
326 | 337 | ||
327 | struct wl1271_chip chip; | 338 | struct wl1271_chip chip; |
@@ -359,7 +370,6 @@ struct wl1271 { | |||
359 | 370 | ||
360 | /* Frames scheduled for transmission, not handled yet */ | 371 | /* Frames scheduled for transmission, not handled yet */ |
361 | struct sk_buff_head tx_queue; | 372 | struct sk_buff_head tx_queue; |
362 | bool tx_queue_stopped; | ||
363 | 373 | ||
364 | struct work_struct tx_work; | 374 | struct work_struct tx_work; |
365 | 375 | ||
@@ -387,14 +397,15 @@ struct wl1271 { | |||
387 | u32 mbox_ptr[2]; | 397 | u32 mbox_ptr[2]; |
388 | 398 | ||
389 | /* Are we currently scanning */ | 399 | /* Are we currently scanning */ |
390 | bool scanning; | ||
391 | struct wl1271_scan scan; | 400 | struct wl1271_scan scan; |
392 | 401 | ||
393 | /* Our association ID */ | 402 | /* Our association ID */ |
394 | u16 aid; | 403 | u16 aid; |
395 | 404 | ||
396 | /* currently configured rate set */ | 405 | /* currently configured rate set */ |
406 | u32 sta_rate_set; | ||
397 | u32 basic_rate_set; | 407 | u32 basic_rate_set; |
408 | u32 rate_set; | ||
398 | 409 | ||
399 | /* The current band */ | 410 | /* The current band */ |
400 | enum ieee80211_band band; | 411 | enum ieee80211_band band; |
@@ -405,18 +416,9 @@ struct wl1271 { | |||
405 | unsigned int rx_config; | 416 | unsigned int rx_config; |
406 | unsigned int rx_filter; | 417 | unsigned int rx_filter; |
407 | 418 | ||
408 | /* is firmware in elp mode */ | ||
409 | bool elp; | ||
410 | |||
411 | struct completion *elp_compl; | 419 | struct completion *elp_compl; |
412 | struct delayed_work elp_work; | 420 | struct delayed_work elp_work; |
413 | 421 | ||
414 | /* we can be in psm, but not in elp, we have to differentiate */ | ||
415 | bool psm; | ||
416 | |||
417 | /* PSM mode requested */ | ||
418 | bool psm_requested; | ||
419 | |||
420 | /* retry counter for PSM entries */ | 422 | /* retry counter for PSM entries */ |
421 | u8 psm_entry_retry; | 423 | u8 psm_entry_retry; |
422 | 424 | ||
@@ -435,9 +437,6 @@ struct wl1271 { | |||
435 | 437 | ||
436 | struct ieee80211_vif *vif; | 438 | struct ieee80211_vif *vif; |
437 | 439 | ||
438 | /* Used for a workaround to send disconnect before rejoining */ | ||
439 | bool joined; | ||
440 | |||
441 | /* Current chipset configuration */ | 440 | /* Current chipset configuration */ |
442 | struct conf_drv_settings conf; | 441 | struct conf_drv_settings conf; |
443 | 442 | ||
@@ -455,7 +454,9 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
455 | 454 | ||
456 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 455 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 |
457 | 456 | ||
458 | /* WL1271 needs a 200ms sleep after power on */ | 457 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
458 | on in case is has been shut down shortly before */ | ||
459 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | ||
459 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 460 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
460 | 461 | ||
461 | static inline bool wl1271_11a_enabled(void) | 462 | static inline bool wl1271_11a_enabled(void) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7..0b343484347 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -390,6 +390,35 @@ out: | |||
390 | return ret; | 390 | return ret; |
391 | } | 391 | } |
392 | 392 | ||
393 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl) | ||
394 | { | ||
395 | struct acx_dco_itrim_params *dco; | ||
396 | struct conf_itrim_settings *c = &wl->conf.itrim; | ||
397 | int ret; | ||
398 | |||
399 | wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); | ||
400 | |||
401 | dco = kzalloc(sizeof(*dco), GFP_KERNEL); | ||
402 | if (!dco) { | ||
403 | ret = -ENOMEM; | ||
404 | goto out; | ||
405 | } | ||
406 | |||
407 | dco->enable = c->enable; | ||
408 | dco->timeout = cpu_to_le32(c->timeout); | ||
409 | |||
410 | ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, | ||
411 | dco, sizeof(*dco)); | ||
412 | if (ret < 0) { | ||
413 | wl1271_warning("failed to set dco itrim parameters: %d", ret); | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | out: | ||
418 | kfree(dco); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
393 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) | 422 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) |
394 | { | 423 | { |
395 | struct acx_beacon_filter_option *beacon_filter = NULL; | 424 | struct acx_beacon_filter_option *beacon_filter = NULL; |
@@ -758,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
758 | return 0; | 787 | return 0; |
759 | } | 788 | } |
760 | 789 | ||
761 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | 790 | int wl1271_acx_rate_policies(struct wl1271 *wl) |
762 | { | 791 | { |
763 | struct acx_rate_policy *acx; | 792 | struct acx_rate_policy *acx; |
764 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | 793 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; |
794 | int idx = 0; | ||
765 | int ret = 0; | 795 | int ret = 0; |
766 | 796 | ||
767 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 797 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | |||
773 | goto out; | 803 | goto out; |
774 | } | 804 | } |
775 | 805 | ||
776 | /* configure one default (one-size-fits-all) rate class */ | 806 | /* configure one basic rate class */ |
777 | acx->rate_class_cnt = cpu_to_le32(1); | 807 | idx = ACX_TX_BASIC_RATE; |
778 | acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); | 808 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); |
779 | acx->rate_class[0].short_retry_limit = c->short_retry_limit; | 809 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
780 | acx->rate_class[0].long_retry_limit = c->long_retry_limit; | 810 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
781 | acx->rate_class[0].aflags = c->aflags; | 811 | acx->rate_class[idx].aflags = c->aflags; |
812 | |||
813 | /* configure one AP supported rate class */ | ||
814 | idx = ACX_TX_AP_FULL_RATE; | ||
815 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); | ||
816 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | ||
817 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | ||
818 | acx->rate_class[idx].aflags = c->aflags; | ||
819 | |||
820 | acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); | ||
782 | 821 | ||
783 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 822 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
784 | if (ret < 0) { | 823 | if (ret < 0) { |
@@ -1012,59 +1051,6 @@ out: | |||
1012 | return ret; | 1051 | return ret; |
1013 | } | 1052 | } |
1014 | 1053 | ||
1015 | int wl1271_acx_smart_reflex(struct wl1271 *wl) | ||
1016 | { | ||
1017 | struct acx_smart_reflex_state *sr_state = NULL; | ||
1018 | struct acx_smart_reflex_config_params *sr_param = NULL; | ||
1019 | int i, ret; | ||
1020 | |||
1021 | wl1271_debug(DEBUG_ACX, "acx smart reflex"); | ||
1022 | |||
1023 | sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); | ||
1024 | if (!sr_param) { | ||
1025 | ret = -ENOMEM; | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { | ||
1030 | struct conf_mart_reflex_err_table *e = | ||
1031 | &(wl->conf.init.sr_err_tbl[i]); | ||
1032 | |||
1033 | sr_param->error_table[i].len = e->len; | ||
1034 | sr_param->error_table[i].upper_limit = e->upper_limit; | ||
1035 | memcpy(sr_param->error_table[i].values, e->values, e->len); | ||
1036 | } | ||
1037 | |||
1038 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, | ||
1039 | sr_param, sizeof(*sr_param)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); | ||
1046 | if (!sr_state) { | ||
1047 | ret = -ENOMEM; | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | /* enable smart reflex */ | ||
1052 | sr_state->enable = wl->conf.init.sr_enable; | ||
1053 | |||
1054 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, | ||
1055 | sr_state, sizeof(*sr_state)); | ||
1056 | if (ret < 0) { | ||
1057 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | |||
1061 | out: | ||
1062 | kfree(sr_state); | ||
1063 | kfree(sr_param); | ||
1064 | return ret; | ||
1065 | |||
1066 | } | ||
1067 | |||
1068 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | 1054 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) |
1069 | { | 1055 | { |
1070 | struct wl1271_acx_bet_enable *acx = NULL; | 1056 | struct wl1271_acx_bet_enable *acx = NULL; |
@@ -1132,3 +1118,31 @@ out: | |||
1132 | kfree(acx); | 1118 | kfree(acx); |
1133 | return ret; | 1119 | return ret; |
1134 | } | 1120 | } |
1121 | |||
1122 | int wl1271_acx_pm_config(struct wl1271 *wl) | ||
1123 | { | ||
1124 | struct wl1271_acx_pm_config *acx = NULL; | ||
1125 | struct conf_pm_config_settings *c = &wl->conf.pm_config; | ||
1126 | int ret = 0; | ||
1127 | |||
1128 | wl1271_debug(DEBUG_ACX, "acx pm config"); | ||
1129 | |||
1130 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1131 | if (!acx) { | ||
1132 | ret = -ENOMEM; | ||
1133 | goto out; | ||
1134 | } | ||
1135 | |||
1136 | acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); | ||
1137 | acx->host_fast_wakeup_support = c->host_fast_wakeup_support; | ||
1138 | |||
1139 | ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); | ||
1140 | if (ret < 0) { | ||
1141 | wl1271_warning("acx pm config failed: %d", ret); | ||
1142 | goto out; | ||
1143 | } | ||
1144 | |||
1145 | out: | ||
1146 | kfree(acx); | ||
1147 | return ret; | ||
1148 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 2ce0a812854..1bb63af64f0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -415,23 +415,12 @@ struct acx_bt_wlan_coex { | |||
415 | u8 pad[3]; | 415 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
417 | 417 | ||
418 | struct acx_smart_reflex_state { | 418 | struct acx_dco_itrim_params { |
419 | struct acx_header header; | 419 | struct acx_header header; |
420 | 420 | ||
421 | u8 enable; | 421 | u8 enable; |
422 | u8 padding[3]; | 422 | u8 padding[3]; |
423 | } __attribute__ ((packed)); | 423 | __le32 timeout; |
424 | |||
425 | struct smart_reflex_err_table { | ||
426 | u8 len; | ||
427 | s8 upper_limit; | ||
428 | s8 values[14]; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct acx_smart_reflex_config_params { | ||
432 | struct acx_header header; | ||
433 | |||
434 | struct smart_reflex_err_table error_table[3]; | ||
435 | } __attribute__ ((packed)); | 424 | } __attribute__ ((packed)); |
436 | 425 | ||
437 | #define PTA_ANTENNA_TYPE_DEF (0) | 426 | #define PTA_ANTENNA_TYPE_DEF (0) |
@@ -837,6 +826,9 @@ struct acx_rate_class { | |||
837 | u8 reserved; | 826 | u8 reserved; |
838 | }; | 827 | }; |
839 | 828 | ||
829 | #define ACX_TX_BASIC_RATE 0 | ||
830 | #define ACX_TX_AP_FULL_RATE 1 | ||
831 | #define ACX_TX_RATE_POLICY_CNT 2 | ||
840 | struct acx_rate_policy { | 832 | struct acx_rate_policy { |
841 | struct acx_header header; | 833 | struct acx_header header; |
842 | 834 | ||
@@ -877,8 +869,8 @@ struct acx_tx_config_options { | |||
877 | __le16 tx_compl_threshold; /* number of packets */ | 869 | __le16 tx_compl_threshold; /* number of packets */ |
878 | } __attribute__ ((packed)); | 870 | } __attribute__ ((packed)); |
879 | 871 | ||
880 | #define ACX_RX_MEM_BLOCKS 64 | 872 | #define ACX_RX_MEM_BLOCKS 70 |
881 | #define ACX_TX_MIN_MEM_BLOCKS 64 | 873 | #define ACX_TX_MIN_MEM_BLOCKS 40 |
882 | #define ACX_TX_DESCRIPTORS 32 | 874 | #define ACX_TX_DESCRIPTORS 32 |
883 | #define ACX_NUM_SSID_PROFILES 1 | 875 | #define ACX_NUM_SSID_PROFILES 1 |
884 | 876 | ||
@@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter { | |||
969 | used. */ | 961 | used. */ |
970 | } __attribute__((packed)); | 962 | } __attribute__((packed)); |
971 | 963 | ||
964 | struct wl1271_acx_pm_config { | ||
965 | struct acx_header header; | ||
966 | |||
967 | __le32 host_clk_settling_time; | ||
968 | u8 host_fast_wakeup_support; | ||
969 | u8 padding[3]; | ||
970 | } __attribute__ ((packed)); | ||
972 | 971 | ||
973 | enum { | 972 | enum { |
974 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 973 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
@@ -1027,13 +1026,13 @@ enum { | |||
1027 | ACX_HT_BSS_OPERATION = 0x0058, | 1026 | ACX_HT_BSS_OPERATION = 0x0058, |
1028 | ACX_COEX_ACTIVITY = 0x0059, | 1027 | ACX_COEX_ACTIVITY = 0x0059, |
1029 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | 1028 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, |
1030 | ACX_SET_SMART_REFLEX_STATE = 0x005B, | 1029 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1031 | ACX_SET_SMART_REFLEX_PARAMS = 0x005F, | ||
1032 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1030 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1033 | DOT11_CUR_TX_PWR = 0x100D, | 1031 | DOT11_CUR_TX_PWR = 0x100D, |
1034 | DOT11_RX_DOT11_MODE = 0x1012, | 1032 | DOT11_RX_DOT11_MODE = 0x1012, |
1035 | DOT11_RTS_THRESHOLD = 0x1013, | 1033 | DOT11_RTS_THRESHOLD = 0x1013, |
1036 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | 1034 | DOT11_GROUP_ADDRESS_TBL = 0x1014, |
1035 | ACX_PM_CONFIG = 0x1016, | ||
1037 | 1036 | ||
1038 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, | 1037 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, |
1039 | 1038 | ||
@@ -1056,6 +1055,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | |||
1056 | void *mc_list, u32 mc_list_len); | 1055 | void *mc_list, u32 mc_list_len); |
1057 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1056 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1058 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1057 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); |
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | ||
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); |
@@ -1069,7 +1069,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | |||
1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1070 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1072 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); |
1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); |
1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); |
1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
@@ -1081,5 +1081,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl); | |||
1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1083 | u8 version); | 1083 | u8 version); |
1084 | int wl1271_acx_pm_config(struct wl1271 *wl); | ||
1084 | 1085 | ||
1085 | #endif /* __WL1271_ACX_H__ */ | 1086 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca..e803b876f3f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
225 | if (nvs == NULL) | 225 | if (nvs == NULL) |
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | if (wl->nvs_len < WL1271_NVS_LEN) | ||
229 | return -EINVAL; | ||
230 | |||
228 | nvs_ptr = nvs; | 231 | nvs_ptr = nvs; |
229 | 232 | ||
230 | nvs_len = wl->nvs_len; | 233 | /* only the first part of the NVS needs to be uploaded */ |
234 | nvs_len = WL1271_NVS_LEN; | ||
235 | |||
236 | /* FIXME: read init settings from the remaining part of the NVS */ | ||
231 | 237 | ||
232 | /* Update the device MAC address into the nvs */ | 238 | /* Update the device MAC address into the nvs */ |
233 | nvs[11] = wl->mac_addr[0]; | 239 | nvs[11] = wl->mac_addr[0]; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index c3385b3d246..a74259bb596 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -209,6 +209,26 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; | 209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; |
210 | gen_parms->settings = g->settings; | 210 | gen_parms->settings = g->settings; |
211 | 211 | ||
212 | gen_parms->sr_state = g->sr_state; | ||
213 | |||
214 | memcpy(gen_parms->srf1, | ||
215 | g->srf1, | ||
216 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
217 | memcpy(gen_parms->srf2, | ||
218 | g->srf2, | ||
219 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
220 | memcpy(gen_parms->srf3, | ||
221 | g->srf3, | ||
222 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
223 | memcpy(gen_parms->sr_debug_table, | ||
224 | g->sr_debug_table, | ||
225 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
226 | |||
227 | gen_parms->sr_sen_n_p = g->sr_sen_n_p; | ||
228 | gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; | ||
229 | gen_parms->sr_sen_nrn = g->sr_sen_nrn; | ||
230 | gen_parms->sr_sen_prn = g->sr_sen_prn; | ||
231 | |||
212 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 232 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
213 | if (ret < 0) | 233 | if (ret < 0) |
214 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 234 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -253,6 +273,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
253 | CONF_NUMBER_OF_RATE_GROUPS); | 273 | CONF_NUMBER_OF_RATE_GROUPS); |
254 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, | 274 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, |
255 | CONF_NUMBER_OF_RATE_GROUPS); | 275 | CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, | ||
277 | CONF_NUMBER_OF_RATE_GROUPS); | ||
256 | 278 | ||
257 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, | 279 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, |
258 | CONF_NUMBER_OF_CHANNELS_2_4); | 280 | CONF_NUMBER_OF_CHANNELS_2_4); |
@@ -263,6 +285,11 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
263 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); | 285 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); |
264 | 286 | ||
265 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | 287 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; |
288 | radio_parms->degraded_low_to_normal_threshold = | ||
289 | r->degraded_low_to_normal_threshold; | ||
290 | radio_parms->degraded_normal_to_high_threshold = | ||
291 | r->degraded_normal_to_high_threshold; | ||
292 | |||
266 | 293 | ||
267 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | 294 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) |
268 | radio_parms->tx_ref_pd_voltage_5[i] = | 295 | radio_parms->tx_ref_pd_voltage_5[i] = |
@@ -275,6 +302,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
275 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | 302 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_degraded_5, | 303 | memcpy(radio_parms->tx_rate_limits_degraded_5, |
277 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | 304 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); |
305 | memcpy(radio_parms->tx_rate_limits_extreme_5, | ||
306 | r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
278 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | 307 | memcpy(radio_parms->tx_channel_limits_ofdm_5, |
279 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | 308 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); |
280 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | 309 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, |
@@ -283,6 +312,10 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
283 | CONF_NUMBER_OF_RATE_GROUPS); | 312 | CONF_NUMBER_OF_RATE_GROUPS); |
284 | memcpy(radio_parms->rx_fem_insertion_loss_5, | 313 | memcpy(radio_parms->rx_fem_insertion_loss_5, |
285 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | 314 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); |
315 | radio_parms->degraded_low_to_normal_threshold_5 = | ||
316 | r->degraded_low_to_normal_threshold_5; | ||
317 | radio_parms->degraded_normal_to_high_threshold_5 = | ||
318 | r->degraded_normal_to_high_threshold_5; | ||
286 | 319 | ||
287 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 320 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
288 | radio_parms, sizeof(*radio_parms)); | 321 | radio_parms, sizeof(*radio_parms)); |
@@ -311,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
311 | do_cal = false; | 344 | do_cal = false; |
312 | } | 345 | } |
313 | 346 | ||
314 | /* FIXME: This is a workaround, because with the current stack, we | ||
315 | * cannot know when we have disassociated. So, if we have already | ||
316 | * joined, we disconnect before joining again. */ | ||
317 | if (wl->joined) { | ||
318 | ret = wl1271_cmd_disconnect(wl); | ||
319 | if (ret < 0) { | ||
320 | wl1271_error("failed to disconnect before rejoining"); | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | wl->joined = false; | ||
325 | } | ||
326 | |||
327 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 347 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
328 | if (!join) { | 348 | if (!join) { |
329 | ret = -ENOMEM; | 349 | ret = -ENOMEM; |
@@ -388,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
388 | goto out_free; | 408 | goto out_free; |
389 | } | 409 | } |
390 | 410 | ||
391 | wl->joined = true; | ||
392 | |||
393 | /* | 411 | /* |
394 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 412 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to |
395 | * simplify locking we just sleep instead, for now | 413 | * simplify locking we just sleep instead, for now |
@@ -487,7 +505,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
487 | return 0; | 505 | return 0; |
488 | } | 506 | } |
489 | 507 | ||
490 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | 508 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) |
491 | { | 509 | { |
492 | struct cmd_enabledisable_path *cmd; | 510 | struct cmd_enabledisable_path *cmd; |
493 | int ret; | 511 | int ret; |
@@ -501,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
501 | goto out; | 519 | goto out; |
502 | } | 520 | } |
503 | 521 | ||
504 | cmd->channel = channel; | 522 | /* the channel here is only used for calibration, so hardcoded to 1 */ |
523 | cmd->channel = 1; | ||
505 | 524 | ||
506 | if (enable) { | 525 | if (enable) { |
507 | cmd_rx = CMD_ENABLE_RX; | 526 | cmd_rx = CMD_ENABLE_RX; |
@@ -514,22 +533,22 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
514 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); | 533 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); |
515 | if (ret < 0) { | 534 | if (ret < 0) { |
516 | wl1271_error("rx %s cmd for channel %d failed", | 535 | wl1271_error("rx %s cmd for channel %d failed", |
517 | enable ? "start" : "stop", channel); | 536 | enable ? "start" : "stop", cmd->channel); |
518 | goto out; | 537 | goto out; |
519 | } | 538 | } |
520 | 539 | ||
521 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 540 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
522 | enable ? "start" : "stop", channel); | 541 | enable ? "start" : "stop", cmd->channel); |
523 | 542 | ||
524 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); | 543 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); |
525 | if (ret < 0) { | 544 | if (ret < 0) { |
526 | wl1271_error("tx %s cmd for channel %d failed", | 545 | wl1271_error("tx %s cmd for channel %d failed", |
527 | enable ? "start" : "stop", channel); | 546 | enable ? "start" : "stop", cmd->channel); |
528 | return ret; | 547 | return ret; |
529 | } | 548 | } |
530 | 549 | ||
531 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 550 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
532 | enable ? "start" : "stop", channel); | 551 | enable ? "start" : "stop", cmd->channel); |
533 | 552 | ||
534 | out: | 553 | out: |
535 | kfree(cmd); | 554 | kfree(cmd); |
@@ -636,7 +655,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
636 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | 655 | channels = wl->hw->wiphy->bands[ieee_band]->channels; |
637 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | 656 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; |
638 | 657 | ||
639 | if (wl->scanning) | 658 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) |
640 | return -EINVAL; | 659 | return -EINVAL; |
641 | 660 | ||
642 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 661 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
@@ -711,7 +730,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
711 | 730 | ||
712 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 731 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); |
713 | 732 | ||
714 | wl->scanning = true; | 733 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); |
715 | if (wl1271_11a_enabled()) { | 734 | if (wl1271_11a_enabled()) { |
716 | wl->scan.state = band; | 735 | wl->scan.state = band; |
717 | if (band == WL1271_SCAN_BAND_DUAL) { | 736 | if (band == WL1271_SCAN_BAND_DUAL) { |
@@ -729,7 +748,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
729 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | 748 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); |
730 | if (ret < 0) { | 749 | if (ret < 0) { |
731 | wl1271_error("SCAN failed"); | 750 | wl1271_error("SCAN failed"); |
732 | wl->scanning = false; | 751 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
733 | goto out; | 752 | goto out; |
734 | } | 753 | } |
735 | 754 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index b4fa4acb922..09fe91297ac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -37,7 +37,7 @@ int wl1271_cmd_join(struct wl1271 *wl); | |||
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); | 40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
@@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd { | |||
437 | u8 tx_bip_fem_autodetect; | 437 | u8 tx_bip_fem_autodetect; |
438 | u8 tx_bip_fem_manufacturer; | 438 | u8 tx_bip_fem_manufacturer; |
439 | u8 settings; | 439 | u8 settings; |
440 | |||
441 | u8 sr_state; | ||
442 | |||
443 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
444 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
445 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
446 | |||
447 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
448 | |||
449 | u8 sr_sen_n_p; | ||
450 | u8 sr_sen_n_p_gain; | ||
451 | u8 sr_sen_nrn; | ||
452 | u8 sr_sen_prn; | ||
453 | |||
454 | u8 padding[3]; | ||
440 | } __attribute__ ((packed)); | 455 | } __attribute__ ((packed)); |
441 | 456 | ||
442 | struct wl1271_radio_parms_cmd { | 457 | struct wl1271_radio_parms_cmd { |
@@ -458,11 +473,12 @@ struct wl1271_radio_parms_cmd { | |||
458 | /* Dynamic radio parameters */ | 473 | /* Dynamic radio parameters */ |
459 | /* 2.4GHz */ | 474 | /* 2.4GHz */ |
460 | __le16 tx_ref_pd_voltage; | 475 | __le16 tx_ref_pd_voltage; |
461 | s8 tx_ref_power; | 476 | u8 tx_ref_power; |
462 | s8 tx_offset_db; | 477 | s8 tx_offset_db; |
463 | 478 | ||
464 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 479 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
465 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 480 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
481 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
466 | 482 | ||
467 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 483 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
468 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 484 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -471,15 +487,19 @@ struct wl1271_radio_parms_cmd { | |||
471 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 487 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
472 | u8 rx_fem_insertion_loss; | 488 | u8 rx_fem_insertion_loss; |
473 | 489 | ||
474 | u8 padding2; | 490 | u8 degraded_low_to_normal_threshold; |
491 | u8 degraded_normal_to_high_threshold; | ||
492 | |||
493 | u8 padding1; /* our own padding, not in ref driver */ | ||
475 | 494 | ||
476 | /* 5GHz */ | 495 | /* 5GHz */ |
477 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 496 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
478 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 497 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
479 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 498 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
480 | 499 | ||
481 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 500 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
482 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 501 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
502 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
483 | 503 | ||
484 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 504 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
485 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 505 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -488,7 +508,10 @@ struct wl1271_radio_parms_cmd { | |||
488 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 508 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
489 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 509 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
490 | 510 | ||
491 | u8 padding3[2]; | 511 | u8 degraded_low_to_normal_threshold_5; |
512 | u8 degraded_normal_to_high_threshold_5; | ||
513 | |||
514 | u8 padding2[2]; | ||
492 | } __attribute__ ((packed)); | 515 | } __attribute__ ((packed)); |
493 | 516 | ||
494 | struct wl1271_cmd_cal_channel_tune { | 517 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede26..1993d63c214 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -258,7 +258,8 @@ struct conf_rx_settings { | |||
258 | #define CONF_TX_MAX_RATE_CLASSES 8 | 258 | #define CONF_TX_MAX_RATE_CLASSES 8 |
259 | 259 | ||
260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 | 260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 |
261 | #define CONF_TX_RATE_MASK_ALL 0x1eff | 261 | #define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ |
262 | CONF_HW_BIT_RATE_2MBPS) | ||
262 | #define CONF_TX_RATE_RETRY_LIMIT 10 | 263 | #define CONF_TX_RATE_RETRY_LIMIT 10 |
263 | 264 | ||
264 | struct conf_tx_rate_class { | 265 | struct conf_tx_rate_class { |
@@ -722,31 +723,6 @@ struct conf_conn_settings { | |||
722 | u8 psm_entry_retries; | 723 | u8 psm_entry_retries; |
723 | }; | 724 | }; |
724 | 725 | ||
725 | #define CONF_SR_ERR_TBL_MAX_VALUES 14 | ||
726 | |||
727 | struct conf_mart_reflex_err_table { | ||
728 | /* | ||
729 | * Length of the error table values table. | ||
730 | * | ||
731 | * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES | ||
732 | */ | ||
733 | u8 len; | ||
734 | |||
735 | /* | ||
736 | * Smart Reflex error table upper limit. | ||
737 | * | ||
738 | * Range: s8 | ||
739 | */ | ||
740 | s8 upper_limit; | ||
741 | |||
742 | /* | ||
743 | * Smart Reflex error table values. | ||
744 | * | ||
745 | * Range: s8 | ||
746 | */ | ||
747 | s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; | ||
748 | }; | ||
749 | |||
750 | enum { | 726 | enum { |
751 | CONF_REF_CLK_19_2_E, | 727 | CONF_REF_CLK_19_2_E, |
752 | CONF_REF_CLK_26_E, | 728 | CONF_REF_CLK_26_E, |
@@ -759,6 +735,9 @@ enum single_dual_band_enum { | |||
759 | CONF_DUAL_BAND | 735 | CONF_DUAL_BAND |
760 | }; | 736 | }; |
761 | 737 | ||
738 | |||
739 | #define CONF_MAX_SMART_REFLEX_PARAMS 16 | ||
740 | |||
762 | struct conf_general_parms { | 741 | struct conf_general_parms { |
763 | /* | 742 | /* |
764 | * RF Reference Clock type / speed | 743 | * RF Reference Clock type / speed |
@@ -815,6 +794,20 @@ struct conf_general_parms { | |||
815 | * Range: Unknown | 794 | * Range: Unknown |
816 | */ | 795 | */ |
817 | u8 settings; | 796 | u8 settings; |
797 | |||
798 | /* Smart reflex settings */ | ||
799 | u8 sr_state; | ||
800 | |||
801 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
802 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
803 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
804 | |||
805 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
806 | |||
807 | u8 sr_sen_n_p; | ||
808 | u8 sr_sen_n_p_gain; | ||
809 | u8 sr_sen_nrn; | ||
810 | u8 sr_sen_prn; | ||
818 | }; | 811 | }; |
819 | 812 | ||
820 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | 813 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 |
@@ -847,12 +840,13 @@ struct conf_radio_parms { | |||
847 | * | 840 | * |
848 | * Range: unknown | 841 | * Range: unknown |
849 | */ | 842 | */ |
850 | s16 tx_ref_pd_voltage; | 843 | u16 tx_ref_pd_voltage; |
851 | s8 tx_ref_power; | 844 | u8 tx_ref_power; |
852 | s8 tx_offset_db; | 845 | s8 tx_offset_db; |
853 | 846 | ||
854 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 847 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
855 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 848 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
849 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
856 | 850 | ||
857 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 851 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
858 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 852 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -861,17 +855,22 @@ struct conf_radio_parms { | |||
861 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 855 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
862 | u8 rx_fem_insertion_loss; | 856 | u8 rx_fem_insertion_loss; |
863 | 857 | ||
858 | u8 degraded_low_to_normal_threshold; | ||
859 | u8 degraded_normal_to_high_threshold; | ||
860 | |||
861 | |||
864 | /* | 862 | /* |
865 | * Dynamic radio parameters for 5GHz | 863 | * Dynamic radio parameters for 5GHz |
866 | * | 864 | * |
867 | * Range: unknown | 865 | * Range: unknown |
868 | */ | 866 | */ |
869 | s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 867 | u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
870 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 868 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
871 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 869 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
872 | 870 | ||
873 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 871 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
874 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 872 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
873 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
875 | 874 | ||
876 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 875 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
877 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 876 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -879,33 +878,46 @@ struct conf_radio_parms { | |||
879 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | 878 | /* FIXME: this is inconsistent with the types for 2.4GHz */ |
880 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 879 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
881 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 880 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
882 | }; | ||
883 | 881 | ||
884 | #define CONF_SR_ERR_TBL_COUNT 3 | 882 | u8 degraded_low_to_normal_threshold_5; |
883 | u8 degraded_normal_to_high_threshold_5; | ||
884 | }; | ||
885 | 885 | ||
886 | struct conf_init_settings { | 886 | struct conf_init_settings { |
887 | /* | 887 | /* |
888 | * Configure Smart Reflex error table values. | 888 | * Configure general parameters. |
889 | */ | 889 | */ |
890 | struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; | 890 | struct conf_general_parms genparam; |
891 | 891 | ||
892 | /* | 892 | /* |
893 | * Smart Reflex enable flag. | 893 | * Configure radio parameters. |
894 | * | ||
895 | * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled | ||
896 | */ | 894 | */ |
897 | u8 sr_enable; | 895 | struct conf_radio_parms radioparam; |
898 | 896 | ||
897 | }; | ||
898 | |||
899 | struct conf_itrim_settings { | ||
900 | /* enable dco itrim */ | ||
901 | u8 enable; | ||
902 | |||
903 | /* moderation timeout in microsecs from the last TX */ | ||
904 | u32 timeout; | ||
905 | }; | ||
906 | |||
907 | struct conf_pm_config_settings { | ||
899 | /* | 908 | /* |
900 | * Configure general parameters. | 909 | * Host clock settling time |
910 | * | ||
911 | * Range: 0 - 30000 us | ||
901 | */ | 912 | */ |
902 | struct conf_general_parms genparam; | 913 | u32 host_clk_settling_time; |
903 | 914 | ||
904 | /* | 915 | /* |
905 | * Configure radio parameters. | 916 | * Host fast wakeup support |
917 | * | ||
918 | * Range: true, false | ||
906 | */ | 919 | */ |
907 | struct conf_radio_parms radioparam; | 920 | bool host_fast_wakeup_support; |
908 | |||
909 | }; | 921 | }; |
910 | 922 | ||
911 | struct conf_drv_settings { | 923 | struct conf_drv_settings { |
@@ -914,6 +926,8 @@ struct conf_drv_settings { | |||
914 | struct conf_tx_settings tx; | 926 | struct conf_tx_settings tx; |
915 | struct conf_conn_settings conn; | 927 | struct conf_conn_settings conn; |
916 | struct conf_init_settings init; | 928 | struct conf_init_settings init; |
929 | struct conf_itrim_settings itrim; | ||
930 | struct conf_pm_config_settings pm_config; | ||
917 | }; | 931 | }; |
918 | 932 | ||
919 | #endif | 933 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index c1805e5f896..8d7588ca68f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1271_open_file_generic, | 237 | .open = wl1271_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1271 *wl = file->private_data; | ||
244 | bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
245 | |||
246 | int res; | ||
247 | char buf[10]; | ||
248 | |||
249 | res = scnprintf(buf, sizeof(buf), "%d\n", state); | ||
250 | |||
251 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
252 | } | ||
253 | |||
254 | static ssize_t gpio_power_write(struct file *file, | ||
255 | const char __user *user_buf, | ||
256 | size_t count, loff_t *ppos) | ||
257 | { | ||
258 | struct wl1271 *wl = file->private_data; | ||
259 | char buf[10]; | ||
260 | size_t len; | ||
261 | unsigned long value; | ||
262 | int ret; | ||
263 | |||
264 | mutex_lock(&wl->mutex); | ||
265 | |||
266 | len = min(count, sizeof(buf) - 1); | ||
267 | if (copy_from_user(buf, user_buf, len)) { | ||
268 | ret = -EFAULT; | ||
269 | goto out; | ||
270 | } | ||
271 | buf[len] = '\0'; | ||
272 | |||
273 | ret = strict_strtoul(buf, 0, &value); | ||
274 | if (ret < 0) { | ||
275 | wl1271_warning("illegal value in gpio_power"); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | if (value) { | ||
280 | wl->set_power(true); | ||
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
282 | } else { | ||
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | |||
287 | out: | ||
288 | mutex_unlock(&wl->mutex); | ||
289 | return count; | ||
290 | } | ||
291 | |||
292 | static const struct file_operations gpio_power_ops = { | ||
293 | .read = gpio_power_read, | ||
294 | .write = gpio_power_write, | ||
295 | .open = wl1271_open_file_generic | ||
296 | }; | ||
297 | |||
240 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) | 298 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) |
241 | { | 299 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 300 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -333,6 +391,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl) | |||
333 | DEBUGFS_DEL(tx_queue_len); | 391 | DEBUGFS_DEL(tx_queue_len); |
334 | DEBUGFS_DEL(retry_count); | 392 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 393 | DEBUGFS_DEL(excessive_retries); |
394 | |||
395 | DEBUGFS_DEL(gpio_power); | ||
336 | } | 396 | } |
337 | 397 | ||
338 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 398 | static int wl1271_debugfs_add_files(struct wl1271 *wl) |
@@ -434,6 +494,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 494 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 495 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 496 | ||
497 | DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); | ||
498 | |||
437 | out: | 499 | out: |
438 | if (ret < 0) | 500 | if (ret < 0) |
439 | wl1271_debugfs_delete_files(wl); | 501 | wl1271_debugfs_delete_files(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index d13fdd99c85..0a145afc990 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -35,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 36 | mbox->scheduled_scan_status); |
37 | 37 | ||
38 | if (wl->scanning) { | 38 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
41 | NULL, size); | 41 | NULL, size); |
@@ -43,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
43 | * to the wl1271_cmd_scan function that we are not | 43 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 44 | * scanning as it checks that. |
45 | */ | 45 | */ |
46 | wl->scanning = false; | 46 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
48 | wl->scan.active, | 48 | wl->scan.active, |
49 | wl->scan.high_prio, | 49 | wl->scan.high_prio, |
@@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
62 | mutex_unlock(&wl->mutex); | 62 | mutex_unlock(&wl->mutex); |
63 | ieee80211_scan_completed(wl->hw, false); | 63 | ieee80211_scan_completed(wl->hw, false); |
64 | mutex_lock(&wl->mutex); | 64 | mutex_lock(&wl->mutex); |
65 | wl->scanning = false; | 65 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | return 0; | 68 | return 0; |
@@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
78 | 78 | ||
79 | switch (mbox->ps_status) { | 79 | switch (mbox->ps_status) { |
80 | case EVENT_ENTER_POWER_SAVE_FAIL: | 80 | case EVENT_ENTER_POWER_SAVE_FAIL: |
81 | if (!wl->psm) { | 81 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
82 | wl->psm_entry_retry = 0; | 82 | wl->psm_entry_retry = 0; |
83 | break; | 83 | break; |
84 | } | 84 | } |
@@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
89 | } else { | 89 | } else { |
90 | wl1271_error("PSM entry failed, giving up.\n"); | 90 | wl1271_error("PSM entry failed, giving up.\n"); |
91 | wl->psm_entry_retry = 0; | 91 | wl->psm_entry_retry = 0; |
92 | *beacon_loss = true; | ||
93 | } | 92 | } |
94 | break; | 93 | break; |
95 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 94 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -136,7 +135,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
136 | * filtering) is enabled. Without PSM, the stack will receive all | 135 | * filtering) is enabled. Without PSM, the stack will receive all |
137 | * beacons and can detect beacon loss by itself. | 136 | * beacons and can detect beacon loss by itself. |
138 | */ | 137 | */ |
139 | if (vector & BSS_LOSE_EVENT_ID && wl->psm) { | 138 | if (vector & BSS_LOSE_EVENT_ID && |
139 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | 140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
141 | 141 | ||
142 | /* indicate to the stack, that beacons have been lost */ | 142 | /* indicate to the stack, that beacons have been lost */ |
@@ -150,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
152 | 152 | ||
153 | if (beacon_loss) { | 153 | if (wl->vif && beacon_loss) { |
154 | /* Obviously, it's dangerous to release the mutex while | 154 | /* Obviously, it's dangerous to release the mutex while |
155 | we are holding many of the variables in the wl struct. | 155 | we are holding many of the variables in the wl struct. |
156 | That's why it's done last in the function, and care must | 156 | That's why it's done last in the function, and care must |
@@ -184,7 +184,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl) | |||
184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
185 | } | 185 | } |
186 | 186 | ||
187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | 187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) |
188 | { | 188 | { |
189 | struct event_mailbox mbox; | 189 | struct event_mailbox mbox; |
190 | int ret; | 190 | int ret; |
@@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | |||
204 | return ret; | 204 | return ret; |
205 | 205 | ||
206 | /* then we let the firmware know it can go on...*/ | 206 | /* then we let the firmware know it can go on...*/ |
207 | if (do_ack) | 207 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
208 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, | ||
209 | INTR_TRIG_EVENT_ACK); | ||
210 | 208 | ||
211 | return 0; | 209 | return 0; |
212 | } | 210 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a..278f9206aa5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -112,6 +112,6 @@ struct event_mailbox { | |||
112 | 112 | ||
113 | int wl1271_event_unmask(struct wl1271 *wl); | 113 | int wl1271_event_unmask(struct wl1271 *wl); |
114 | void wl1271_event_mbox_config(struct wl1271 *wl); | 114 | void wl1271_event_mbox_config(struct wl1271 *wl); |
115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); | 115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
116 | 116 | ||
117 | #endif | 117 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 11249b436cf..c9848eecb76 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
229 | if (ret < 0) | 229 | if (ret < 0) |
230 | goto out_free_memmap; | 230 | goto out_free_memmap; |
231 | 231 | ||
232 | ret = wl1271_acx_dco_itrim_params(wl); | ||
233 | if (ret < 0) | ||
234 | goto out_free_memmap; | ||
235 | |||
232 | /* Initialize connection monitoring thresholds */ | 236 | /* Initialize connection monitoring thresholds */ |
233 | ret = wl1271_acx_conn_monit_params(wl); | 237 | ret = wl1271_acx_conn_monit_params(wl); |
234 | if (ret < 0) | 238 | if (ret < 0) |
@@ -280,12 +284,12 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
280 | goto out_free_memmap; | 284 | goto out_free_memmap; |
281 | 285 | ||
282 | /* Configure TX rate classes */ | 286 | /* Configure TX rate classes */ |
283 | ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); | 287 | ret = wl1271_acx_rate_policies(wl); |
284 | if (ret < 0) | 288 | if (ret < 0) |
285 | goto out_free_memmap; | 289 | goto out_free_memmap; |
286 | 290 | ||
287 | /* Enable data path */ | 291 | /* Enable data path */ |
288 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 292 | ret = wl1271_cmd_data_path(wl, 1); |
289 | if (ret < 0) | 293 | if (ret < 0) |
290 | goto out_free_memmap; | 294 | goto out_free_memmap; |
291 | 295 | ||
@@ -299,8 +303,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
299 | if (ret < 0) | 303 | if (ret < 0) |
300 | goto out_free_memmap; | 304 | goto out_free_memmap; |
301 | 305 | ||
302 | /* Configure smart reflex */ | 306 | /* configure PM */ |
303 | ret = wl1271_acx_smart_reflex(wl); | 307 | ret = wl1271_acx_pm_config(wl); |
304 | if (ret < 0) | 308 | if (ret < 0) |
305 | goto out_free_memmap; | 309 | goto out_free_memmap; |
306 | 310 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42f..e4867b895c4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include "wl1271_cmd.h" | 47 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 48 | #include "wl1271_boot.h" |
49 | 49 | ||
50 | #define WL1271_BOOT_RETRIES 3 | ||
51 | |||
50 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
51 | .sg = { | 53 | .sg = { |
52 | .per_threshold = 7500, | 54 | .per_threshold = 7500, |
@@ -67,16 +69,17 @@ static struct conf_drv_settings default_conf = { | |||
67 | .ps_poll_timeout = 15, | 69 | .ps_poll_timeout = 15, |
68 | .upsd_timeout = 15, | 70 | .upsd_timeout = 15, |
69 | .rts_threshold = 2347, | 71 | .rts_threshold = 2347, |
70 | .rx_cca_threshold = 0xFFEF, | 72 | .rx_cca_threshold = 0, |
71 | .irq_blk_threshold = 0, | 73 | .irq_blk_threshold = 0xFFFF, |
72 | .irq_pkt_threshold = USHORT_MAX, | 74 | .irq_pkt_threshold = 0, |
73 | .irq_timeout = 5, | 75 | .irq_timeout = 600, |
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | 76 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
75 | }, | 77 | }, |
76 | .tx = { | 78 | .tx = { |
77 | .tx_energy_detection = 0, | 79 | .tx_energy_detection = 0, |
78 | .rc_conf = { | 80 | .rc_conf = { |
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | 81 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | |
82 | CONF_HW_BIT_RATE_2MBPS, | ||
80 | .short_retry_limit = 10, | 83 | .short_retry_limit = 10, |
81 | .long_retry_limit = 10, | 84 | .long_retry_limit = 10, |
82 | .aflags = 0 | 85 | .aflags = 0 |
@@ -172,8 +175,8 @@ static struct conf_drv_settings default_conf = { | |||
172 | } | 175 | } |
173 | }, | 176 | }, |
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 177 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
175 | .tx_compl_timeout = 5, | 178 | .tx_compl_timeout = 700, |
176 | .tx_compl_threshold = 5 | 179 | .tx_compl_threshold = 4 |
177 | }, | 180 | }, |
178 | .conn = { | 181 | .conn = { |
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 182 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -186,12 +189,12 @@ static struct conf_drv_settings default_conf = { | |||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 189 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
187 | } | 190 | } |
188 | }, | 191 | }, |
189 | .synch_fail_thold = 5, | 192 | .synch_fail_thold = 10, |
190 | .bss_lose_timeout = 100, | 193 | .bss_lose_timeout = 100, |
191 | .beacon_rx_timeout = 10000, | 194 | .beacon_rx_timeout = 10000, |
192 | .broadcast_timeout = 20000, | 195 | .broadcast_timeout = 20000, |
193 | .rx_broadcast_in_ps = 1, | 196 | .rx_broadcast_in_ps = 1, |
194 | .ps_poll_threshold = 4, | 197 | .ps_poll_threshold = 20, |
195 | .sig_trigger_count = 2, | 198 | .sig_trigger_count = 2, |
196 | .sig_trigger = { | 199 | .sig_trigger = { |
197 | [0] = { | 200 | [0] = { |
@@ -226,46 +229,35 @@ static struct conf_drv_settings default_conf = { | |||
226 | .psm_entry_retries = 3 | 229 | .psm_entry_retries = 3 |
227 | }, | 230 | }, |
228 | .init = { | 231 | .init = { |
229 | .sr_err_tbl = { | ||
230 | [0] = { | ||
231 | .len = 7, | ||
232 | .upper_limit = 0x03, | ||
233 | .values = { | ||
234 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
235 | 0x00 } | ||
236 | }, | ||
237 | [1] = { | ||
238 | .len = 7, | ||
239 | .upper_limit = 0x03, | ||
240 | .values = { | ||
241 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
242 | 0x00 } | ||
243 | }, | ||
244 | [2] = { | ||
245 | .len = 7, | ||
246 | .upper_limit = 0x03, | ||
247 | .values = { | ||
248 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
249 | 0x00 } | ||
250 | } | ||
251 | }, | ||
252 | .sr_enable = 1, | ||
253 | .genparam = { | 232 | .genparam = { |
254 | .ref_clk = CONF_REF_CLK_38_4_E, | 233 | .ref_clk = CONF_REF_CLK_38_4_E, |
255 | .settling_time = 5, | 234 | .settling_time = 5, |
256 | .clk_valid_on_wakeup = 0, | 235 | .clk_valid_on_wakeup = 0, |
257 | .dc2dcmode = 0, | 236 | .dc2dcmode = 0, |
258 | .single_dual_band = CONF_SINGLE_BAND, | 237 | .single_dual_band = CONF_SINGLE_BAND, |
259 | .tx_bip_fem_autodetect = 0, | 238 | .tx_bip_fem_autodetect = 1, |
260 | .tx_bip_fem_manufacturer = 1, | 239 | .tx_bip_fem_manufacturer = 1, |
261 | .settings = 1, | 240 | .settings = 1, |
241 | .sr_state = 1, | ||
242 | .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
243 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
244 | .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
245 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
246 | .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
247 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
248 | .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, | ||
249 | 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
250 | .sr_sen_n_p = 0, | ||
251 | .sr_sen_n_p_gain = 0, | ||
252 | .sr_sen_nrn = 0, | ||
253 | .sr_sen_prn = 0, | ||
262 | }, | 254 | }, |
263 | .radioparam = { | 255 | .radioparam = { |
264 | .rx_trace_loss = 10, | 256 | .rx_trace_loss = 0x24, |
265 | .tx_trace_loss = 10, | 257 | .tx_trace_loss = 0x0, |
266 | .rx_rssi_and_proc_compens = { | 258 | .rx_rssi_and_proc_compens = { |
267 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | 259 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, |
268 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | 260 | 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, |
269 | 0x00, 0x0a, 0x14 }, | 261 | 0x00, 0x0a, 0x14 }, |
270 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 262 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
271 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 263 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
@@ -273,13 +265,15 @@ static struct conf_drv_settings default_conf = { | |||
273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
275 | 0x00, 0x00, 0x00 }, | 267 | 0x00, 0x00, 0x00 }, |
276 | .tx_ref_pd_voltage = 0x24e, | 268 | .tx_ref_pd_voltage = 0x1a9, |
277 | .tx_ref_power = 0x78, | 269 | .tx_ref_power = 0x80, |
278 | .tx_offset_db = 0x0, | 270 | .tx_offset_db = 0x0, |
279 | .tx_rate_limits_normal = { | 271 | .tx_rate_limits_normal = { |
280 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | 272 | 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, |
281 | .tx_rate_limits_degraded = { | 273 | .tx_rate_limits_degraded = { |
282 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | 274 | 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, |
275 | .tx_rate_limits_extreme = { | ||
276 | 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
283 | .tx_channel_limits_11b = { | 277 | .tx_channel_limits_11b = { |
284 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | 278 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, |
285 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | 279 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, |
@@ -289,10 +283,12 @@ static struct conf_drv_settings default_conf = { | |||
289 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | 283 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, |
290 | 0x20, 0x50 }, | 284 | 0x20, 0x50 }, |
291 | .tx_pdv_rate_offsets = { | 285 | .tx_pdv_rate_offsets = { |
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | 286 | 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, |
293 | .tx_ibias = { | 287 | .tx_ibias = { |
294 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | 288 | 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, |
295 | .rx_fem_insertion_loss = 0x14, | 289 | .rx_fem_insertion_loss = 0x0e, |
290 | .degraded_low_to_normal_threshold = 0x1e, | ||
291 | .degraded_normal_to_high_threshold = 0x2d, | ||
296 | .tx_ref_pd_voltage_5 = { | 292 | .tx_ref_pd_voltage_5 = { |
297 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | 293 | 0x0190, 0x01a4, 0x01c3, 0x01d8, |
298 | 0x020a, 0x021c }, | 294 | 0x020a, 0x021c }, |
@@ -304,6 +300,8 @@ static struct conf_drv_settings default_conf = { | |||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 300 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
305 | .tx_rate_limits_degraded_5 = { | 301 | .tx_rate_limits_degraded_5 = { |
306 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 302 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
303 | .tx_rate_limits_extreme_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
307 | .tx_channel_limits_ofdm_5 = { | 305 | .tx_channel_limits_ofdm_5 = { |
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 306 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 307 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
@@ -315,8 +313,18 @@ static struct conf_drv_settings default_conf = { | |||
315 | .tx_ibias_5 = { | 313 | .tx_ibias_5 = { |
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | 314 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .rx_fem_insertion_loss_5 = { | 315 | .rx_fem_insertion_loss_5 = { |
318 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | 316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .degraded_low_to_normal_threshold_5 = 0x00, | ||
318 | .degraded_normal_to_high_threshold_5 = 0x00 | ||
319 | } | 319 | } |
320 | }, | ||
321 | .itrim = { | ||
322 | .enable = false, | ||
323 | .timeout = 50000, | ||
324 | }, | ||
325 | .pm_config = { | ||
326 | .host_clk_settling_time = 5000, | ||
327 | .host_fast_wakeup_support = false | ||
320 | } | 328 | } |
321 | }; | 329 | }; |
322 | 330 | ||
@@ -359,7 +367,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
359 | if (ret < 0) | 367 | if (ret < 0) |
360 | return ret; | 368 | return ret; |
361 | 369 | ||
362 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 370 | ret = wl1271_cmd_data_path(wl, 1); |
363 | if (ret < 0) | 371 | if (ret < 0) |
364 | return ret; | 372 | return ret; |
365 | 373 | ||
@@ -374,11 +382,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) | |||
374 | static void wl1271_power_off(struct wl1271 *wl) | 382 | static void wl1271_power_off(struct wl1271 *wl) |
375 | { | 383 | { |
376 | wl->set_power(false); | 384 | wl->set_power(false); |
385 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | 386 | } |
378 | 387 | ||
379 | static void wl1271_power_on(struct wl1271 *wl) | 388 | static void wl1271_power_on(struct wl1271 *wl) |
380 | { | 389 | { |
381 | wl->set_power(true); | 390 | wl->set_power(true); |
391 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | 392 | } |
383 | 393 | ||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 394 | static void wl1271_fw_status(struct wl1271 *wl, |
@@ -447,14 +457,13 @@ static void wl1271_irq_work(struct work_struct *work) | |||
447 | intr &= WL1271_INTR_MASK; | 457 | intr &= WL1271_INTR_MASK; |
448 | 458 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 459 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
450 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; | ||
451 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 460 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
452 | wl1271_event_handle(wl, 0, do_ack); | 461 | wl1271_event_handle(wl, 0); |
453 | } | 462 | } |
454 | 463 | ||
455 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 464 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
456 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 465 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
457 | wl1271_event_handle(wl, 1, true); | 466 | wl1271_event_handle(wl, 1); |
458 | } | 467 | } |
459 | 468 | ||
460 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 469 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -614,6 +623,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
614 | struct wl1271_partition_set partition; | 623 | struct wl1271_partition_set partition; |
615 | int ret = 0; | 624 | int ret = 0; |
616 | 625 | ||
626 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
617 | wl1271_power_on(wl); | 627 | wl1271_power_on(wl); |
618 | msleep(WL1271_POWER_ON_SLEEP); | 628 | msleep(WL1271_POWER_ON_SLEEP); |
619 | wl1271_spi_reset(wl); | 629 | wl1271_spi_reset(wl); |
@@ -643,7 +653,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
643 | 653 | ||
644 | ret = wl1271_setup(wl); | 654 | ret = wl1271_setup(wl); |
645 | if (ret < 0) | 655 | if (ret < 0) |
646 | goto out_power_off; | 656 | goto out; |
647 | break; | 657 | break; |
648 | case CHIP_ID_1271_PG20: | 658 | case CHIP_ID_1271_PG20: |
649 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 659 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -651,38 +661,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
651 | 661 | ||
652 | ret = wl1271_setup(wl); | 662 | ret = wl1271_setup(wl); |
653 | if (ret < 0) | 663 | if (ret < 0) |
654 | goto out_power_off; | 664 | goto out; |
655 | break; | 665 | break; |
656 | default: | 666 | default: |
657 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 667 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
658 | ret = -ENODEV; | 668 | ret = -ENODEV; |
659 | goto out_power_off; | 669 | goto out; |
660 | } | 670 | } |
661 | 671 | ||
662 | if (wl->fw == NULL) { | 672 | if (wl->fw == NULL) { |
663 | ret = wl1271_fetch_firmware(wl); | 673 | ret = wl1271_fetch_firmware(wl); |
664 | if (ret < 0) | 674 | if (ret < 0) |
665 | goto out_power_off; | 675 | goto out; |
666 | } | 676 | } |
667 | 677 | ||
668 | /* No NVS from netlink, try to get it from the filesystem */ | 678 | /* No NVS from netlink, try to get it from the filesystem */ |
669 | if (wl->nvs == NULL) { | 679 | if (wl->nvs == NULL) { |
670 | ret = wl1271_fetch_nvs(wl); | 680 | ret = wl1271_fetch_nvs(wl); |
671 | if (ret < 0) | 681 | if (ret < 0) |
672 | goto out_power_off; | 682 | goto out; |
673 | } | 683 | } |
674 | 684 | ||
675 | goto out; | ||
676 | |||
677 | out_power_off: | ||
678 | wl1271_power_off(wl); | ||
679 | |||
680 | out: | 685 | out: |
681 | return ret; | 686 | return ret; |
682 | } | 687 | } |
683 | 688 | ||
684 | int wl1271_plt_start(struct wl1271 *wl) | 689 | int wl1271_plt_start(struct wl1271 *wl) |
685 | { | 690 | { |
691 | int retries = WL1271_BOOT_RETRIES; | ||
686 | int ret; | 692 | int ret; |
687 | 693 | ||
688 | mutex_lock(&wl->mutex); | 694 | mutex_lock(&wl->mutex); |
@@ -696,35 +702,48 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
696 | goto out; | 702 | goto out; |
697 | } | 703 | } |
698 | 704 | ||
699 | wl->state = WL1271_STATE_PLT; | 705 | while (retries) { |
700 | 706 | retries--; | |
701 | ret = wl1271_chip_wakeup(wl); | 707 | ret = wl1271_chip_wakeup(wl); |
702 | if (ret < 0) | 708 | if (ret < 0) |
703 | goto out; | 709 | goto power_off; |
704 | |||
705 | ret = wl1271_boot(wl); | ||
706 | if (ret < 0) | ||
707 | goto out_power_off; | ||
708 | |||
709 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
710 | 710 | ||
711 | ret = wl1271_plt_init(wl); | 711 | ret = wl1271_boot(wl); |
712 | if (ret < 0) | 712 | if (ret < 0) |
713 | goto out_irq_disable; | 713 | goto power_off; |
714 | 714 | ||
715 | /* Make sure power saving is disabled */ | 715 | ret = wl1271_plt_init(wl); |
716 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 716 | if (ret < 0) |
717 | if (ret < 0) | 717 | goto irq_disable; |
718 | goto out_irq_disable; | ||
719 | 718 | ||
720 | goto out; | 719 | /* Make sure power saving is disabled */ |
720 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
721 | if (ret < 0) | ||
722 | goto irq_disable; | ||
721 | 723 | ||
722 | out_irq_disable: | 724 | wl->state = WL1271_STATE_PLT; |
723 | wl1271_disable_interrupts(wl); | 725 | wl1271_notice("firmware booted in PLT mode (%s)", |
726 | wl->chip.fw_ver); | ||
727 | goto out; | ||
724 | 728 | ||
725 | out_power_off: | 729 | irq_disable: |
726 | wl1271_power_off(wl); | 730 | wl1271_disable_interrupts(wl); |
731 | mutex_unlock(&wl->mutex); | ||
732 | /* Unlocking the mutex in the middle of handling is | ||
733 | inherently unsafe. In this case we deem it safe to do, | ||
734 | because we need to let any possibly pending IRQ out of | ||
735 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
736 | work function will not do anything.) Also, any other | ||
737 | possible concurrent operations will fail due to the | ||
738 | current state, hence the wl1271 struct should be safe. */ | ||
739 | cancel_work_sync(&wl->irq_work); | ||
740 | mutex_lock(&wl->mutex); | ||
741 | power_off: | ||
742 | wl1271_power_off(wl); | ||
743 | } | ||
727 | 744 | ||
745 | wl1271_error("firmware boot in PLT mode failed despite %d retries", | ||
746 | WL1271_BOOT_RETRIES); | ||
728 | out: | 747 | out: |
729 | mutex_unlock(&wl->mutex); | 748 | mutex_unlock(&wl->mutex); |
730 | 749 | ||
@@ -762,7 +781,20 @@ out: | |||
762 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 781 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
763 | { | 782 | { |
764 | struct wl1271 *wl = hw->priv; | 783 | struct wl1271 *wl = hw->priv; |
784 | struct ieee80211_conf *conf = &hw->conf; | ||
785 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
786 | struct ieee80211_sta *sta = txinfo->control.sta; | ||
787 | unsigned long flags; | ||
765 | 788 | ||
789 | /* peek into the rates configured in the STA entry */ | ||
790 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
791 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | ||
792 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | ||
793 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
794 | } | ||
795 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
796 | |||
797 | /* queue the packet */ | ||
766 | skb_queue_tail(&wl->tx_queue, skb); | 798 | skb_queue_tail(&wl->tx_queue, skb); |
767 | 799 | ||
768 | /* | 800 | /* |
@@ -784,7 +816,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | * protected. Maybe fix this by removing the stupid | 816 | * protected. Maybe fix this by removing the stupid |
785 | * variable altogether and checking the real queue state? | 817 | * variable altogether and checking the real queue state? |
786 | */ | 818 | */ |
787 | wl->tx_queue_stopped = true; | 819 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
788 | } | 820 | } |
789 | 821 | ||
790 | return NETDEV_TX_OK; | 822 | return NETDEV_TX_OK; |
@@ -880,6 +912,7 @@ static struct notifier_block wl1271_dev_notifier = { | |||
880 | static int wl1271_op_start(struct ieee80211_hw *hw) | 912 | static int wl1271_op_start(struct ieee80211_hw *hw) |
881 | { | 913 | { |
882 | struct wl1271 *wl = hw->priv; | 914 | struct wl1271 *wl = hw->priv; |
915 | int retries = WL1271_BOOT_RETRIES; | ||
883 | int ret = 0; | 916 | int ret = 0; |
884 | 917 | ||
885 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 918 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -893,30 +926,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
893 | goto out; | 926 | goto out; |
894 | } | 927 | } |
895 | 928 | ||
896 | ret = wl1271_chip_wakeup(wl); | 929 | while (retries) { |
897 | if (ret < 0) | 930 | retries--; |
898 | goto out; | 931 | ret = wl1271_chip_wakeup(wl); |
899 | 932 | if (ret < 0) | |
900 | ret = wl1271_boot(wl); | 933 | goto power_off; |
901 | if (ret < 0) | ||
902 | goto out_power_off; | ||
903 | |||
904 | ret = wl1271_hw_init(wl); | ||
905 | if (ret < 0) | ||
906 | goto out_irq_disable; | ||
907 | |||
908 | wl->state = WL1271_STATE_ON; | ||
909 | 934 | ||
910 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 935 | ret = wl1271_boot(wl); |
936 | if (ret < 0) | ||
937 | goto power_off; | ||
911 | 938 | ||
912 | goto out; | 939 | ret = wl1271_hw_init(wl); |
940 | if (ret < 0) | ||
941 | goto irq_disable; | ||
913 | 942 | ||
914 | out_irq_disable: | 943 | wl->state = WL1271_STATE_ON; |
915 | wl1271_disable_interrupts(wl); | 944 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
945 | goto out; | ||
916 | 946 | ||
917 | out_power_off: | 947 | irq_disable: |
918 | wl1271_power_off(wl); | 948 | wl1271_disable_interrupts(wl); |
949 | mutex_unlock(&wl->mutex); | ||
950 | /* Unlocking the mutex in the middle of handling is | ||
951 | inherently unsafe. In this case we deem it safe to do, | ||
952 | because we need to let any possibly pending IRQ out of | ||
953 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
954 | work function will not do anything.) Also, any other | ||
955 | possible concurrent operations will fail due to the | ||
956 | current state, hence the wl1271 struct should be safe. */ | ||
957 | cancel_work_sync(&wl->irq_work); | ||
958 | mutex_lock(&wl->mutex); | ||
959 | power_off: | ||
960 | wl1271_power_off(wl); | ||
961 | } | ||
919 | 962 | ||
963 | wl1271_error("firmware boot failed despite %d retries", | ||
964 | WL1271_BOOT_RETRIES); | ||
920 | out: | 965 | out: |
921 | mutex_unlock(&wl->mutex); | 966 | mutex_unlock(&wl->mutex); |
922 | 967 | ||
@@ -944,11 +989,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
944 | 989 | ||
945 | WARN_ON(wl->state != WL1271_STATE_ON); | 990 | WARN_ON(wl->state != WL1271_STATE_ON); |
946 | 991 | ||
947 | if (wl->scanning) { | 992 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
948 | mutex_unlock(&wl->mutex); | 993 | mutex_unlock(&wl->mutex); |
949 | ieee80211_scan_completed(wl->hw, true); | 994 | ieee80211_scan_completed(wl->hw, true); |
950 | mutex_lock(&wl->mutex); | 995 | mutex_lock(&wl->mutex); |
951 | wl->scanning = false; | ||
952 | } | 996 | } |
953 | 997 | ||
954 | wl->state = WL1271_STATE_OFF; | 998 | wl->state = WL1271_STATE_OFF; |
@@ -973,10 +1017,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
973 | wl->band = IEEE80211_BAND_2GHZ; | 1017 | wl->band = IEEE80211_BAND_2GHZ; |
974 | 1018 | ||
975 | wl->rx_counter = 0; | 1019 | wl->rx_counter = 0; |
976 | wl->elp = false; | ||
977 | wl->psm = 0; | ||
978 | wl->psm_entry_retry = 0; | 1020 | wl->psm_entry_retry = 0; |
979 | wl->tx_queue_stopped = false; | ||
980 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1021 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
981 | wl->tx_blocks_available = 0; | 1022 | wl->tx_blocks_available = 0; |
982 | wl->tx_results_count = 0; | 1023 | wl->tx_results_count = 0; |
@@ -986,7 +1027,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
986 | wl->tx_security_seq_32 = 0; | 1027 | wl->tx_security_seq_32 = 0; |
987 | wl->time_offset = 0; | 1028 | wl->time_offset = 0; |
988 | wl->session_counter = 0; | 1029 | wl->session_counter = 0; |
989 | wl->joined = false; | 1030 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1031 | wl->sta_rate_set = 0; | ||
1032 | wl->flags = 0; | ||
990 | 1033 | ||
991 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1034 | for (i = 0; i < NUM_TX_QUEUES; i++) |
992 | wl->tx_blocks_freed[i] = 0; | 1035 | wl->tx_blocks_freed[i] = 0; |
@@ -996,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
996 | } | 1039 | } |
997 | 1040 | ||
998 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1041 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
999 | struct ieee80211_if_init_conf *conf) | 1042 | struct ieee80211_vif *vif) |
1000 | { | 1043 | { |
1001 | struct wl1271 *wl = hw->priv; | 1044 | struct wl1271 *wl = hw->priv; |
1002 | int ret = 0; | 1045 | int ret = 0; |
1003 | 1046 | ||
1004 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1047 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1005 | conf->type, conf->mac_addr); | 1048 | vif->type, vif->addr); |
1006 | 1049 | ||
1007 | mutex_lock(&wl->mutex); | 1050 | mutex_lock(&wl->mutex); |
1008 | if (wl->vif) { | 1051 | if (wl->vif) { |
@@ -1010,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1010 | goto out; | 1053 | goto out; |
1011 | } | 1054 | } |
1012 | 1055 | ||
1013 | wl->vif = conf->vif; | 1056 | wl->vif = vif; |
1014 | 1057 | ||
1015 | switch (conf->type) { | 1058 | switch (vif->type) { |
1016 | case NL80211_IFTYPE_STATION: | 1059 | case NL80211_IFTYPE_STATION: |
1017 | wl->bss_type = BSS_TYPE_STA_BSS; | 1060 | wl->bss_type = BSS_TYPE_STA_BSS; |
1018 | break; | 1061 | break; |
@@ -1032,7 +1075,7 @@ out: | |||
1032 | } | 1075 | } |
1033 | 1076 | ||
1034 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1077 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_if_init_conf *conf) | 1078 | struct ieee80211_vif *vif) |
1036 | { | 1079 | { |
1037 | struct wl1271 *wl = hw->priv; | 1080 | struct wl1271 *wl = hw->priv; |
1038 | 1081 | ||
@@ -1109,6 +1152,51 @@ out: | |||
1109 | } | 1152 | } |
1110 | #endif | 1153 | #endif |
1111 | 1154 | ||
1155 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1156 | { | ||
1157 | int ret = 0; | ||
1158 | /* we need to use a dummy BSSID for now */ | ||
1159 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1160 | 0xad, 0xbe, 0xef }; | ||
1161 | |||
1162 | /* the dummy join is not required for ad-hoc */ | ||
1163 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1164 | goto out; | ||
1165 | |||
1166 | /* disable mac filter, so we hear everything */ | ||
1167 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1168 | |||
1169 | wl->channel = channel; | ||
1170 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1171 | |||
1172 | ret = wl1271_cmd_join(wl); | ||
1173 | if (ret < 0) | ||
1174 | goto out; | ||
1175 | |||
1176 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1177 | |||
1178 | out: | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1183 | { | ||
1184 | int ret; | ||
1185 | |||
1186 | /* to stop listening to a channel, we disconnect */ | ||
1187 | ret = wl1271_cmd_disconnect(wl); | ||
1188 | if (ret < 0) | ||
1189 | goto out; | ||
1190 | |||
1191 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1192 | wl->channel = 0; | ||
1193 | memset(wl->bssid, 0, ETH_ALEN); | ||
1194 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1195 | |||
1196 | out: | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1112 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1200 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1113 | { | 1201 | { |
1114 | struct wl1271 *wl = hw->priv; | 1202 | struct wl1271 *wl = hw->priv; |
@@ -1117,10 +1205,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1117 | 1205 | ||
1118 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1206 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1119 | 1207 | ||
1120 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1208 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1121 | channel, | 1209 | channel, |
1122 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1210 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1123 | conf->power_level); | 1211 | conf->power_level, |
1212 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1124 | 1213 | ||
1125 | mutex_lock(&wl->mutex); | 1214 | mutex_lock(&wl->mutex); |
1126 | 1215 | ||
@@ -1130,34 +1219,44 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1130 | if (ret < 0) | 1219 | if (ret < 0) |
1131 | goto out; | 1220 | goto out; |
1132 | 1221 | ||
1133 | if (channel != wl->channel) { | 1222 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1134 | /* | 1223 | if (conf->flags & IEEE80211_CONF_IDLE && |
1135 | * We assume that the stack will configure the right channel | 1224 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1136 | * before associating, so we don't need to send a join | 1225 | wl1271_unjoin_channel(wl); |
1137 | * command here. We will join the right channel when the | 1226 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1138 | * BSSID changes | 1227 | wl1271_join_channel(wl, channel); |
1139 | */ | 1228 | |
1140 | wl->channel = channel; | 1229 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1230 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1231 | wl->sta_rate_set = 0; | ||
1232 | wl1271_acx_rate_policies(wl); | ||
1233 | } | ||
1141 | } | 1234 | } |
1142 | 1235 | ||
1143 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1236 | /* if the channel changes while joined, join again */ |
1144 | wl1271_info("psm enabled"); | 1237 | if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1238 | wl1271_join_channel(wl, channel); | ||
1145 | 1239 | ||
1146 | wl->psm_requested = true; | 1240 | if (conf->flags & IEEE80211_CONF_PS && |
1241 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | ||
1242 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | ||
1147 | 1243 | ||
1148 | /* | 1244 | /* |
1149 | * We enter PSM only if we're already associated. | 1245 | * We enter PSM only if we're already associated. |
1150 | * If we're not, we'll enter it when joining an SSID, | 1246 | * If we're not, we'll enter it when joining an SSID, |
1151 | * through the bss_info_changed() hook. | 1247 | * through the bss_info_changed() hook. |
1152 | */ | 1248 | */ |
1153 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1249 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1250 | wl1271_info("psm enabled"); | ||
1251 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
1252 | } | ||
1154 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1253 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1155 | wl->psm_requested) { | 1254 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1156 | wl1271_info("psm disabled"); | 1255 | wl1271_info("psm disabled"); |
1157 | 1256 | ||
1158 | wl->psm_requested = false; | 1257 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1159 | 1258 | ||
1160 | if (wl->psm) | 1259 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1161 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1260 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); |
1162 | } | 1261 | } |
1163 | 1262 | ||
@@ -1440,22 +1539,6 @@ out: | |||
1440 | return ret; | 1539 | return ret; |
1441 | } | 1540 | } |
1442 | 1541 | ||
1443 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | ||
1444 | { | ||
1445 | struct ieee80211_supported_band *band; | ||
1446 | u32 enabled_rates = 0; | ||
1447 | int bit; | ||
1448 | |||
1449 | band = wl->hw->wiphy->bands[wl->band]; | ||
1450 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1451 | if (basic_rate_set & 0x1) | ||
1452 | enabled_rates |= band->bitrates[bit].hw_value; | ||
1453 | basic_rate_set >>= 1; | ||
1454 | } | ||
1455 | |||
1456 | return enabled_rates; | ||
1457 | } | ||
1458 | |||
1459 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1542 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
1460 | struct ieee80211_vif *vif, | 1543 | struct ieee80211_vif *vif, |
1461 | struct ieee80211_bss_conf *bss_conf, | 1544 | struct ieee80211_bss_conf *bss_conf, |
@@ -1473,9 +1556,68 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1473 | if (ret < 0) | 1556 | if (ret < 0) |
1474 | goto out; | 1557 | goto out; |
1475 | 1558 | ||
1559 | if ((changed & BSS_CHANGED_BSSID) && | ||
1560 | /* | ||
1561 | * Now we know the correct bssid, so we send a new join command | ||
1562 | * and enable the BSSID filter | ||
1563 | */ | ||
1564 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1565 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1566 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1567 | ret = wl1271_cmd_build_null_data(wl); | ||
1568 | if (ret < 0) { | ||
1569 | wl1271_warning("cmd buld null data failed %d", | ||
1570 | ret); | ||
1571 | goto out_sleep; | ||
1572 | } | ||
1573 | ret = wl1271_cmd_join(wl); | ||
1574 | if (ret < 0) { | ||
1575 | wl1271_warning("cmd join failed %d", ret); | ||
1576 | goto out_sleep; | ||
1577 | } | ||
1578 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1579 | } | ||
1580 | |||
1581 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
1582 | /* FIXME: This implements rudimentary ad-hoc support - | ||
1583 | proper templates are on the wish list and notification | ||
1584 | on when they change. This patch will update the templates | ||
1585 | on every call to this function. Also, the firmware will not | ||
1586 | answer to probe-requests as it does not have the proper | ||
1587 | SSID set in the JOIN command. The probe-response template | ||
1588 | is set nevertheless, as the FW will ASSERT without it */ | ||
1589 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
1590 | |||
1591 | if (beacon) { | ||
1592 | struct ieee80211_hdr *hdr; | ||
1593 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1594 | beacon->data, | ||
1595 | beacon->len); | ||
1596 | |||
1597 | if (ret < 0) { | ||
1598 | dev_kfree_skb(beacon); | ||
1599 | goto out_sleep; | ||
1600 | } | ||
1601 | |||
1602 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
1603 | hdr->frame_control = cpu_to_le16( | ||
1604 | IEEE80211_FTYPE_MGMT | | ||
1605 | IEEE80211_STYPE_PROBE_RESP); | ||
1606 | |||
1607 | ret = wl1271_cmd_template_set(wl, | ||
1608 | CMD_TEMPL_PROBE_RESPONSE, | ||
1609 | beacon->data, | ||
1610 | beacon->len); | ||
1611 | dev_kfree_skb(beacon); | ||
1612 | if (ret < 0) | ||
1613 | goto out_sleep; | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1476 | if (changed & BSS_CHANGED_ASSOC) { | 1617 | if (changed & BSS_CHANGED_ASSOC) { |
1477 | if (bss_conf->assoc) { | 1618 | if (bss_conf->assoc) { |
1478 | wl->aid = bss_conf->aid; | 1619 | wl->aid = bss_conf->aid; |
1620 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1479 | 1621 | ||
1480 | /* | 1622 | /* |
1481 | * with wl1271, we don't need to update the | 1623 | * with wl1271, we don't need to update the |
@@ -1492,7 +1634,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1492 | goto out_sleep; | 1634 | goto out_sleep; |
1493 | 1635 | ||
1494 | /* If we want to go in PSM but we're not there yet */ | 1636 | /* If we want to go in PSM but we're not there yet */ |
1495 | if (wl->psm_requested && !wl->psm) { | 1637 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1638 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1496 | mode = STATION_POWER_SAVE_MODE; | 1639 | mode = STATION_POWER_SAVE_MODE; |
1497 | ret = wl1271_ps_set_mode(wl, mode); | 1640 | ret = wl1271_ps_set_mode(wl, mode); |
1498 | if (ret < 0) | 1641 | if (ret < 0) |
@@ -1500,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1500 | } | 1643 | } |
1501 | } else { | 1644 | } else { |
1502 | /* use defaults when not associated */ | 1645 | /* use defaults when not associated */ |
1503 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1646 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1504 | wl->aid = 0; | 1647 | wl->aid = 0; |
1505 | } | 1648 | } |
1506 | 1649 | ||
@@ -1535,17 +1678,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1535 | } | 1678 | } |
1536 | } | 1679 | } |
1537 | 1680 | ||
1538 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1539 | wl->basic_rate_set = wl1271_enabled_rates_get( | ||
1540 | wl, bss_conf->basic_rates); | ||
1541 | |||
1542 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1543 | if (ret < 0) { | ||
1544 | wl1271_warning("Set rate policies failed %d", ret); | ||
1545 | goto out_sleep; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | out_sleep: | 1681 | out_sleep: |
1550 | wl1271_ps_elp_sleep(wl); | 1682 | wl1271_ps_elp_sleep(wl); |
1551 | 1683 | ||
@@ -1599,19 +1731,19 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1599 | 1731 | ||
1600 | /* can't be const, mac80211 writes to this */ | 1732 | /* can't be const, mac80211 writes to this */ |
1601 | static struct ieee80211_channel wl1271_channels[] = { | 1733 | static struct ieee80211_channel wl1271_channels[] = { |
1602 | { .hw_value = 1, .center_freq = 2412}, | 1734 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1603 | { .hw_value = 2, .center_freq = 2417}, | 1735 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, |
1604 | { .hw_value = 3, .center_freq = 2422}, | 1736 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, |
1605 | { .hw_value = 4, .center_freq = 2427}, | 1737 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, |
1606 | { .hw_value = 5, .center_freq = 2432}, | 1738 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
1607 | { .hw_value = 6, .center_freq = 2437}, | 1739 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, |
1608 | { .hw_value = 7, .center_freq = 2442}, | 1740 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, |
1609 | { .hw_value = 8, .center_freq = 2447}, | 1741 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, |
1610 | { .hw_value = 9, .center_freq = 2452}, | 1742 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
1611 | { .hw_value = 10, .center_freq = 2457}, | 1743 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, |
1612 | { .hw_value = 11, .center_freq = 2462}, | 1744 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
1613 | { .hw_value = 12, .center_freq = 2467}, | 1745 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
1614 | { .hw_value = 13, .center_freq = 2472}, | 1746 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1615 | }; | 1747 | }; |
1616 | 1748 | ||
1617 | /* can't be const, mac80211 writes to this */ | 1749 | /* can't be const, mac80211 writes to this */ |
@@ -1757,7 +1889,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1757 | IEEE80211_HW_BEACON_FILTER | | 1889 | IEEE80211_HW_BEACON_FILTER | |
1758 | IEEE80211_HW_SUPPORTS_PS; | 1890 | IEEE80211_HW_SUPPORTS_PS; |
1759 | 1891 | ||
1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1892 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1893 | BIT(NL80211_IFTYPE_ADHOC); | ||
1761 | wl->hw->wiphy->max_scan_ssids = 1; | 1894 | wl->hw->wiphy->max_scan_ssids = 1; |
1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 1895 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1763 | 1896 | ||
@@ -1818,21 +1951,18 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1818 | 1951 | ||
1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 1952 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1820 | wl->channel = WL1271_DEFAULT_CHANNEL; | 1953 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1821 | wl->scanning = false; | ||
1822 | wl->default_key = 0; | 1954 | wl->default_key = 0; |
1823 | wl->rx_counter = 0; | 1955 | wl->rx_counter = 0; |
1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1956 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 1957 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1826 | wl->elp = false; | ||
1827 | wl->psm = 0; | ||
1828 | wl->psm_requested = false; | ||
1829 | wl->psm_entry_retry = 0; | 1958 | wl->psm_entry_retry = 0; |
1830 | wl->tx_queue_stopped = false; | ||
1831 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1959 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1832 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1960 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
1961 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1962 | wl->sta_rate_set = 0; | ||
1833 | wl->band = IEEE80211_BAND_2GHZ; | 1963 | wl->band = IEEE80211_BAND_2GHZ; |
1834 | wl->vif = NULL; | 1964 | wl->vif = NULL; |
1835 | wl->joined = false; | 1965 | wl->flags = 0; |
1836 | 1966 | ||
1837 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 1967 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1838 | wl->tx_frames[i] = NULL; | 1968 | wl->tx_frames[i] = NULL; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 507cd91d7ee..e407790f677 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 39 | ||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (wl->elp || !wl->psm) | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | ||
43 | goto out; | 44 | goto out; |
44 | 45 | ||
45 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 46 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
46 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 47 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
47 | wl->elp = true; | 48 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
48 | 49 | ||
49 | out: | 50 | out: |
50 | mutex_unlock(&wl->mutex); | 51 | mutex_unlock(&wl->mutex); |
@@ -55,7 +56,7 @@ out: | |||
55 | /* Routines to toggle sleep mode while in ELP */ | 56 | /* Routines to toggle sleep mode while in ELP */ |
56 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 57 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
57 | { | 58 | { |
58 | if (wl->psm) { | 59 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
59 | cancel_delayed_work(&wl->elp_work); | 60 | cancel_delayed_work(&wl->elp_work); |
60 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 61 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
61 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 62 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
@@ -70,7 +71,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
70 | u32 start_time = jiffies; | 71 | u32 start_time = jiffies; |
71 | bool pending = false; | 72 | bool pending = false; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
74 | return 0; | 75 | return 0; |
75 | 76 | ||
76 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); |
@@ -101,7 +102,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
101 | } | 102 | } |
102 | } | 103 | } |
103 | 104 | ||
104 | wl->elp = false; | 105 | clear_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
105 | 106 | ||
106 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", | 107 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", |
107 | jiffies_to_msecs(jiffies - start_time)); | 108 | jiffies_to_msecs(jiffies - start_time)); |
@@ -143,7 +144,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
143 | if (ret < 0) | 144 | if (ret < 0) |
144 | return ret; | 145 | return ret; |
145 | 146 | ||
146 | wl->psm = 1; | 147 | set_bit(WL1271_FLAG_PSM, &wl->flags); |
147 | break; | 148 | break; |
148 | case STATION_ACTIVE_MODE: | 149 | case STATION_ACTIVE_MODE: |
149 | default: | 150 | default: |
@@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
166 | if (ret < 0) | 167 | if (ret < 0) |
167 | return ret; | 168 | return ret; |
168 | 169 | ||
169 | wl->psm = 0; | 170 | clear_bit(WL1271_FLAG_PSM, &wl->flags); |
170 | break; | 171 | break; |
171 | } | 172 | } |
172 | 173 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h index 1f237389d1c..99096077152 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/wl1271_reg.h | |||
@@ -62,73 +62,10 @@ | |||
62 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) | 62 | #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) |
63 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) | 63 | #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) |
64 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) | 64 | #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) |
65 | /* | ||
66 | * Interrupt registers. | ||
67 | * 64 bit interrupt sources registers ws ced. | ||
68 | * sme interupts were removed and new ones were added. | ||
69 | * Order was changed. | ||
70 | */ | ||
71 | #define FIQ_MASK (REGISTERS_BASE + 0x0400) | ||
72 | #define FIQ_MASK_L (REGISTERS_BASE + 0x0400) | ||
73 | #define FIQ_MASK_H (REGISTERS_BASE + 0x0404) | ||
74 | #define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) | ||
75 | #define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) | ||
76 | #define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) | ||
77 | #define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) | ||
78 | #define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) | ||
79 | #define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) | ||
80 | #define IRQ_MASK (REGISTERS_BASE + 0x0418) | ||
81 | #define IRQ_MASK_L (REGISTERS_BASE + 0x0418) | ||
82 | #define IRQ_MASK_H (REGISTERS_BASE + 0x041C) | ||
83 | #define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) | ||
84 | #define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) | ||
85 | #define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) | ||
86 | #define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) | ||
87 | #define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) | ||
88 | #define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) | ||
89 | #define ECPU_MASK (REGISTERS_BASE + 0x0448) | ||
90 | #define FIQ_STS_L (REGISTERS_BASE + 0x044C) | ||
91 | #define FIQ_STS_H (REGISTERS_BASE + 0x0450) | ||
92 | #define IRQ_STS_L (REGISTERS_BASE + 0x0454) | ||
93 | #define IRQ_STS_H (REGISTERS_BASE + 0x0458) | ||
94 | #define INT_STS_ND (REGISTERS_BASE + 0x0464) | ||
95 | #define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) | ||
96 | #define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) | ||
97 | #define INT_STS_CLR (REGISTERS_BASE + 0x04B4) | ||
98 | #define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) | ||
99 | #define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) | ||
100 | #define INT_ACK (REGISTERS_BASE + 0x046C) | ||
101 | #define INT_ACK_L (REGISTERS_BASE + 0x046C) | ||
102 | #define INT_ACK_H (REGISTERS_BASE + 0x0470) | ||
103 | #define INT_TRIG (REGISTERS_BASE + 0x0474) | ||
104 | #define INT_TRIG_L (REGISTERS_BASE + 0x0474) | ||
105 | #define INT_TRIG_H (REGISTERS_BASE + 0x0478) | ||
106 | #define HOST_STS_L (REGISTERS_BASE + 0x045C) | ||
107 | #define HOST_STS_H (REGISTERS_BASE + 0x0460) | ||
108 | #define HOST_MASK (REGISTERS_BASE + 0x0430) | ||
109 | #define HOST_MASK_L (REGISTERS_BASE + 0x0430) | ||
110 | #define HOST_MASK_H (REGISTERS_BASE + 0x0434) | ||
111 | #define HOST_MASK_SET (REGISTERS_BASE + 0x0438) | ||
112 | #define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) | ||
113 | #define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) | ||
114 | #define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) | ||
115 | #define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) | ||
116 | #define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) | ||
117 | 65 | ||
118 | #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) | 66 | #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) |
119 | #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) | 67 | #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) |
120 | 68 | ||
121 | /* Host Interrupts*/ | ||
122 | #define HINT_MASK (REGISTERS_BASE + 0x0494) | ||
123 | #define HINT_MASK_SET (REGISTERS_BASE + 0x0498) | ||
124 | #define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) | ||
125 | #define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) | ||
126 | /*1150 spec calls this HINT_STS_RAW*/ | ||
127 | #define HINT_STS_ND (REGISTERS_BASE + 0x04B0) | ||
128 | #define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) | ||
129 | #define HINT_ACK (REGISTERS_BASE + 0x04A8) | ||
130 | #define HINT_TRIG (REGISTERS_BASE + 0x04AC) | ||
131 | |||
132 | /*============================================= | 69 | /*============================================= |
133 | Host Interrupt Mask Register - 32bit (RW) | 70 | Host Interrupt Mask Register - 32bit (RW) |
134 | ------------------------------------------ | 71 | ------------------------------------------ |
@@ -433,16 +370,6 @@ | |||
433 | 370 | ||
434 | 371 | ||
435 | /*=============================================== | 372 | /*=============================================== |
436 | Phy regs | ||
437 | ===============================================*/ | ||
438 | #define ACX_PHY_ADDR_REG SBB_ADDR | ||
439 | #define ACX_PHY_DATA_REG SBB_DATA | ||
440 | #define ACX_PHY_CTRL_REG SBB_CTL | ||
441 | #define ACX_PHY_REG_WR_MASK 0x00000001ul | ||
442 | #define ACX_PHY_REG_RD_MASK 0x00000002ul | ||
443 | |||
444 | |||
445 | /*=============================================== | ||
446 | EEPROM Read/Write Request 32bit RW | 373 | EEPROM Read/Write Request 32bit RW |
447 | ------------------------------------------ | 374 | ------------------------------------------ |
448 | 1 EE_READ - EEPROM Read Request 1 - Setting this bit | 375 | 1 EE_READ - EEPROM Read Request 1 - Setting this bit |
@@ -511,28 +438,6 @@ | |||
511 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f | 438 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f |
512 | #define ACX_CONT_WIND_MAX 0x03ff0000 | 439 | #define ACX_CONT_WIND_MAX 0x03ff0000 |
513 | 440 | ||
514 | /* | ||
515 | * Indirect slave register/memory registers | ||
516 | * ---------------------------------------- | ||
517 | */ | ||
518 | #define HW_SLAVE_REG_ADDR_REG 0x00000004 | ||
519 | #define HW_SLAVE_REG_DATA_REG 0x00000008 | ||
520 | #define HW_SLAVE_REG_CTRL_REG 0x0000000c | ||
521 | |||
522 | #define SLAVE_AUTO_INC 0x00010000 | ||
523 | #define SLAVE_NO_AUTO_INC 0x00000000 | ||
524 | #define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 | ||
525 | |||
526 | #define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR | ||
527 | #define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA | ||
528 | #define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL | ||
529 | #define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL | ||
530 | |||
531 | #define HW_FUNC_EVENT_INT_EN 0x8000 | ||
532 | #define HW_FUNC_EVENT_MASK_REG 0x00000034 | ||
533 | |||
534 | #define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) | ||
535 | |||
536 | /*=============================================== | 441 | /*=============================================== |
537 | HI_CFG Interface Configuration Register Values | 442 | HI_CFG Interface Configuration Register Values |
538 | ------------------------------------------ | 443 | ------------------------------------------ |
@@ -647,10 +552,6 @@ b12-b0 - Supported Rate indicator bits as defined below. | |||
647 | ******************************************************************************/ | 552 | ******************************************************************************/ |
648 | 553 | ||
649 | 554 | ||
650 | #define TNETW1251_CHIP_ID_PG1_0 0x07010101 | ||
651 | #define TNETW1251_CHIP_ID_PG1_1 0x07020101 | ||
652 | #define TNETW1251_CHIP_ID_PG1_2 0x07030101 | ||
653 | |||
654 | /************************************************************************* | 555 | /************************************************************************* |
655 | 556 | ||
656 | Interrupt Trigger Register (Host -> WiLink) | 557 | Interrupt Trigger Register (Host -> WiLink) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 02978a16e73..ee9564aa6ec 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -397,8 +397,7 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | |||
397 | /* poll for data ready */ | 397 | /* poll for data ready */ |
398 | do { | 398 | do { |
399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | 399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); |
400 | timeout--; | 400 | } while (!(val & OCP_READY_MASK) && --timeout); |
401 | } while (!(val & OCP_READY_MASK) && timeout); | ||
402 | 401 | ||
403 | if (!timeout) { | 402 | if (!timeout) { |
404 | wl1271_warning("Top register access timed out."); | 403 | wl1271_warning("Top register access timed out."); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 00af065c77c..a288cc317d7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
121 | pad = pad - skb->len; | 121 | pad = pad - skb->len; |
122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
123 | 123 | ||
124 | /* if the packets are destined for AP (have a STA entry) send them | ||
125 | with AP rate policies, otherwise use default basic rates */ | ||
126 | if (control->control.sta) | ||
127 | tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; | ||
128 | |||
124 | desc->tx_attr = cpu_to_le16(tx_attr); | 129 | desc->tx_attr = cpu_to_le16(tx_attr); |
125 | 130 | ||
126 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 131 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
@@ -214,18 +219,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
214 | return ret; | 219 | return ret; |
215 | } | 220 | } |
216 | 221 | ||
222 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | ||
223 | { | ||
224 | struct ieee80211_supported_band *band; | ||
225 | u32 enabled_rates = 0; | ||
226 | int bit; | ||
227 | |||
228 | band = wl->hw->wiphy->bands[wl->band]; | ||
229 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
230 | if (rate_set & 0x1) | ||
231 | enabled_rates |= band->bitrates[bit].hw_value; | ||
232 | rate_set >>= 1; | ||
233 | } | ||
234 | |||
235 | return enabled_rates; | ||
236 | } | ||
237 | |||
217 | void wl1271_tx_work(struct work_struct *work) | 238 | void wl1271_tx_work(struct work_struct *work) |
218 | { | 239 | { |
219 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); | 240 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); |
220 | struct sk_buff *skb; | 241 | struct sk_buff *skb; |
221 | bool woken_up = false; | 242 | bool woken_up = false; |
243 | u32 sta_rates = 0; | ||
222 | int ret; | 244 | int ret; |
223 | 245 | ||
246 | /* check if the rates supported by the AP have changed */ | ||
247 | if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, | ||
248 | &wl->flags))) { | ||
249 | unsigned long flags; | ||
250 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
251 | sta_rates = wl->sta_rate_set; | ||
252 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
253 | } | ||
254 | |||
224 | mutex_lock(&wl->mutex); | 255 | mutex_lock(&wl->mutex); |
225 | 256 | ||
226 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 257 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
227 | goto out; | 258 | goto out; |
228 | 259 | ||
260 | /* if rates have changed, re-configure the rate policy */ | ||
261 | if (unlikely(sta_rates)) { | ||
262 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | ||
263 | wl1271_acx_rate_policies(wl); | ||
264 | } | ||
265 | |||
229 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 266 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
230 | if (!woken_up) { | 267 | if (!woken_up) { |
231 | ret = wl1271_ps_elp_wakeup(wl, false); | 268 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -240,18 +277,18 @@ void wl1271_tx_work(struct work_struct *work) | |||
240 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | 277 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " |
241 | "stop queues"); | 278 | "stop queues"); |
242 | ieee80211_stop_queues(wl->hw); | 279 | ieee80211_stop_queues(wl->hw); |
243 | wl->tx_queue_stopped = true; | 280 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
244 | skb_queue_head(&wl->tx_queue, skb); | 281 | skb_queue_head(&wl->tx_queue, skb); |
245 | goto out; | 282 | goto out; |
246 | } else if (ret < 0) { | 283 | } else if (ret < 0) { |
247 | dev_kfree_skb(skb); | 284 | dev_kfree_skb(skb); |
248 | goto out; | 285 | goto out; |
249 | } else if (wl->tx_queue_stopped) { | 286 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, |
287 | &wl->flags)) { | ||
250 | /* firmware buffer has space, restart queues */ | 288 | /* firmware buffer has space, restart queues */ |
251 | wl1271_debug(DEBUG_TX, | 289 | wl1271_debug(DEBUG_TX, |
252 | "complete_packet: waking queues"); | 290 | "complete_packet: waking queues"); |
253 | ieee80211_wake_queues(wl->hw); | 291 | ieee80211_wake_queues(wl->hw); |
254 | wl->tx_queue_stopped = false; | ||
255 | } | 292 | } |
256 | } | 293 | } |
257 | 294 | ||