aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.c82
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.h17
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c125
3 files changed, 117 insertions, 107 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
index 770f260726bd..fcbfbd7585f8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -410,3 +410,85 @@ out:
410 kfree(cmd); 410 kfree(cmd);
411 return ret; 411 return ret;
412} 412}
413
414int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
415 unsigned int n_channels, unsigned int n_probes)
416{
417 struct wl1251_cmd_scan *cmd;
418 int i, ret = 0;
419
420 wl1251_debug(DEBUG_CMD, "cmd scan");
421
422 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
423 if (!cmd)
424 return -ENOMEM;
425
426 cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
427 cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
428 CFG_RX_MGMT_EN |
429 CFG_RX_BCN_EN);
430 cmd->params.scan_options = 0;
431 cmd->params.num_channels = n_channels;
432 cmd->params.num_probe_requests = n_probes;
433 cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
434 cmd->params.tid_trigger = 0;
435
436 for (i = 0; i < n_channels; i++) {
437 cmd->channels[i].min_duration =
438 cpu_to_le32(WL1251_SCAN_MIN_DURATION);
439 cmd->channels[i].max_duration =
440 cpu_to_le32(WL1251_SCAN_MAX_DURATION);
441 memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
442 memset(&cmd->channels[i].bssid_msb, 0xff, 2);
443 cmd->channels[i].early_termination = 0;
444 cmd->channels[i].tx_power_att = 0;
445 cmd->channels[i].channel = i + 1;
446 }
447
448 cmd->params.ssid_len = ssid_len;
449 if (ssid)
450 memcpy(cmd->params.ssid, ssid, ssid_len);
451
452 ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
453 if (ret < 0) {
454 wl1251_error("cmd scan failed: %d", ret);
455 goto out;
456 }
457
458 wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
459
460 if (cmd->header.status != CMD_STATUS_SUCCESS) {
461 wl1251_error("cmd scan status wasn't success: %d",
462 cmd->header.status);
463 ret = -EIO;
464 goto out;
465 }
466
467out:
468 kfree(cmd);
469 return ret;
470}
471
472int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout)
473{
474 struct wl1251_cmd_trigger_scan_to *cmd;
475 int ret;
476
477 wl1251_debug(DEBUG_CMD, "cmd trigger scan to");
478
479 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
480 if (!cmd)
481 return -ENOMEM;
482
483 cmd->timeout = timeout;
484
485 ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
486 if (ret < 0) {
487 wl1251_error("cmd trigger scan to failed: %d", ret);
488 goto out;
489 }
490
491out:
492 kfree(cmd);
493 return ret;
494}
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
index dff798ad0ef5..63ae3193f7c6 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -43,6 +43,9 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
43 size_t len); 43 size_t len);
44int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, 44int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
45 void *buf, size_t buf_len); 45 void *buf, size_t buf_len);
46int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
47 unsigned int n_channels, unsigned int n_probes);
48int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout);
46 49
47/* unit ms */ 50/* unit ms */
48#define WL1251_COMMAND_TIMEOUT 2000 51#define WL1251_COMMAND_TIMEOUT 2000
@@ -163,8 +166,10 @@ struct cmd_read_write_memory {
163#define CMDMBOX_HEADER_LEN 4 166#define CMDMBOX_HEADER_LEN 4
164#define CMDMBOX_INFO_ELEM_HEADER_LEN 4 167#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
165 168
169#define WL1251_SCAN_MIN_DURATION 30000
170#define WL1251_SCAN_MAX_DURATION 60000
166 171
167struct basic_scan_parameters { 172struct wl1251_scan_parameters {
168 u32 rx_config_options; 173 u32 rx_config_options;
169 u32 rx_filter_options; 174 u32 rx_filter_options;
170 175
@@ -189,11 +194,11 @@ struct basic_scan_parameters {
189 194
190 u8 tid_trigger; 195 u8 tid_trigger;
191 u8 ssid_len; 196 u8 ssid_len;
192 u32 ssid[8]; 197 u8 ssid[32];
193 198
194} __attribute__ ((packed)); 199} __attribute__ ((packed));
195 200
196struct basic_scan_channel_parameters { 201struct wl1251_scan_ch_parameters {
197 u32 min_duration; /* in TU */ 202 u32 min_duration; /* in TU */
198 u32 max_duration; /* in TU */ 203 u32 max_duration; /* in TU */
199 u32 bssid_lsb; 204 u32 bssid_lsb;
@@ -213,11 +218,11 @@ struct basic_scan_channel_parameters {
213/* SCAN parameters */ 218/* SCAN parameters */
214#define SCAN_MAX_NUM_OF_CHANNELS 16 219#define SCAN_MAX_NUM_OF_CHANNELS 16
215 220
216struct cmd_scan { 221struct wl1251_cmd_scan {
217 struct wl1251_cmd_header header; 222 struct wl1251_cmd_header header;
218 223
219 struct basic_scan_parameters params; 224 struct wl1251_scan_parameters params;
220 struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; 225 struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
221} __attribute__ ((packed)); 226} __attribute__ ((packed));
222 227
223enum { 228enum {
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 6cce86462fac..e038707294a5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -903,111 +903,13 @@ static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len)
903 size); 903 size);
904} 904}
905 905
906static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
907 u8 active_scan, u8 high_prio, u8 num_channels,
908 u8 probe_requests)
909{
910 struct wl1251_cmd_trigger_scan_to *trigger = NULL;
911 struct cmd_scan *params = NULL;
912 int i, ret;
913 u16 scan_options = 0;
914
915 if (wl->scanning)
916 return -EINVAL;
917
918 params = kzalloc(sizeof(*params), GFP_KERNEL);
919 if (!params)
920 return -ENOMEM;
921
922 params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
923 params->params.rx_filter_options =
924 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
925
926 /* High priority scan */
927 if (!active_scan)
928 scan_options |= SCAN_PASSIVE;
929 if (high_prio)
930 scan_options |= SCAN_PRIORITY_HIGH;
931 params->params.scan_options = scan_options;
932
933 params->params.num_channels = num_channels;
934 params->params.num_probe_requests = probe_requests;
935 params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
936 params->params.tid_trigger = 0;
937
938 for (i = 0; i < num_channels; i++) {
939 params->channels[i].min_duration = cpu_to_le32(30000);
940 params->channels[i].max_duration = cpu_to_le32(60000);
941 memset(&params->channels[i].bssid_lsb, 0xff, 4);
942 memset(&params->channels[i].bssid_msb, 0xff, 2);
943 params->channels[i].early_termination = 0;
944 params->channels[i].tx_power_att = 0;
945 params->channels[i].channel = i + 1;
946 memset(params->channels[i].pad, 0, 3);
947 }
948
949 for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++)
950 memset(&params->channels[i], 0,
951 sizeof(struct basic_scan_channel_parameters));
952
953 if (len && ssid) {
954 params->params.ssid_len = len;
955 memcpy(params->params.ssid, ssid, len);
956 } else {
957 params->params.ssid_len = 0;
958 memset(params->params.ssid, 0, 32);
959 }
960
961 ret = wl1251_build_probe_req(wl, ssid, len);
962 if (ret < 0) {
963 wl1251_error("PROBE request template failed");
964 goto out;
965 }
966
967 trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
968 if (!trigger)
969 goto out;
970
971 trigger->timeout = 0;
972
973 ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
974 sizeof(*trigger));
975 if (ret < 0) {
976 wl1251_error("trigger scan to failed for hw scan");
977 goto out;
978 }
979
980 wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
981
982 wl->scanning = true;
983
984 ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
985 if (ret < 0)
986 wl1251_error("SCAN failed");
987
988 wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
989
990 if (params->header.status != CMD_STATUS_SUCCESS) {
991 wl1251_error("TEST command answer error: %d",
992 params->header.status);
993 wl->scanning = false;
994 ret = -EIO;
995 goto out;
996 }
997
998out:
999 kfree(params);
1000 return ret;
1001
1002}
1003
1004static int wl1251_op_hw_scan(struct ieee80211_hw *hw, 906static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
1005 struct cfg80211_scan_request *req) 907 struct cfg80211_scan_request *req)
1006{ 908{
1007 struct wl1251 *wl = hw->priv; 909 struct wl1251 *wl = hw->priv;
1008 int ret;
1009 u8 *ssid = NULL;
1010 size_t ssid_len = 0; 910 size_t ssid_len = 0;
911 u8 *ssid = NULL;
912 int ret;
1011 913
1012 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); 914 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
1013 915
@@ -1018,12 +920,33 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
1018 920
1019 mutex_lock(&wl->mutex); 921 mutex_lock(&wl->mutex);
1020 922
923 if (wl->scanning) {
924 wl1251_debug(DEBUG_SCAN, "scan already in progress");
925 ret = -EINVAL;
926 goto out;
927 }
928
1021 ret = wl1251_ps_elp_wakeup(wl); 929 ret = wl1251_ps_elp_wakeup(wl);
1022 if (ret < 0) 930 if (ret < 0)
1023 goto out; 931 goto out;
1024 932
1025 ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); 933 ret = wl1251_build_probe_req(wl, ssid, ssid_len);
934 if (ret < 0)
935 wl1251_error("probe request template build failed");
936
937 ret = wl1251_cmd_trigger_scan_to(wl, 0);
938 if (ret < 0)
939 goto out_sleep;
940
941 wl->scanning = true;
1026 942
943 ret = wl1251_cmd_scan(wl, ssid, ssid_len, 13, 3);
944 if (ret < 0) {
945 wl->scanning = false;
946 goto out_sleep;
947 }
948
949out_sleep:
1027 wl1251_ps_elp_sleep(wl); 950 wl1251_ps_elp_sleep(wl);
1028 951
1029out: 952out: