diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-13 15:57:29 -0400 |
commit | e300d955debdadf599c36e47eb0bc16f5976215c (patch) | |
tree | 8fafcc789dc06e90665e6eee6388af228bbd2fd7 /drivers/net/wireless/wl12xx | |
parent | 242647bcf8464860f173f3d4d4ab3490d3558518 (diff) | |
parent | 815868e7b5c207ba42d5b317ccc51f8112732268 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/wl12xx/wl1271_cmd.h
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r-- | drivers/net/wireless/wl12xx/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_spi.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_boot.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.c | 248 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_cmd.h | 68 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_conf.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_event.c | 99 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_event.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_rx.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_scan.c | 257 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_scan.h | 109 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_spi.c | 1 |
17 files changed, 579 insertions, 488 deletions
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 27ddd2be0a91..078b4398ac1f 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -10,7 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | |||
10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o | 13 | wl1271_init.o wl1271_debugfs.o wl1271_scan.o |
14 | 14 | ||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | 15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o |
16 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index c8f268951e10..38f72f417183 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -1417,5 +1417,4 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw); | |||
1417 | MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); | 1417 | MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); |
1418 | MODULE_LICENSE("GPL"); | 1418 | MODULE_LICENSE("GPL"); |
1419 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | 1419 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); |
1420 | MODULE_ALIAS("spi:wl1251"); | ||
1421 | MODULE_FIRMWARE(WL1251_FW_NAME); | 1420 | MODULE_FIRMWARE(WL1251_FW_NAME); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index e81474203a23..27fdfaaeb074 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -345,3 +345,4 @@ module_exit(wl1251_spi_exit); | |||
345 | 345 | ||
346 | MODULE_LICENSE("GPL"); | 346 | MODULE_LICENSE("GPL"); |
347 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | 347 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); |
348 | MODULE_ALIAS("spi:wl1251"); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index ec09f0d40ca2..53d47d7a2a1d 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -300,12 +300,10 @@ struct wl1271_rx_mem_pool_addr { | |||
300 | 300 | ||
301 | struct wl1271_scan { | 301 | struct wl1271_scan { |
302 | struct cfg80211_scan_request *req; | 302 | struct cfg80211_scan_request *req; |
303 | bool *scanned_ch; | ||
303 | u8 state; | 304 | u8 state; |
304 | u8 ssid[IW_ESSID_MAX_SIZE+1]; | 305 | u8 ssid[IW_ESSID_MAX_SIZE+1]; |
305 | size_t ssid_len; | 306 | size_t ssid_len; |
306 | u8 active; | ||
307 | u8 high_prio; | ||
308 | u8 probe_requests; | ||
309 | }; | 307 | }; |
310 | 308 | ||
311 | struct wl1271_if_operations { | 309 | struct wl1271_if_operations { |
@@ -343,14 +341,14 @@ struct wl1271 { | |||
343 | #define WL1271_FLAG_JOINED (2) | 341 | #define WL1271_FLAG_JOINED (2) |
344 | #define WL1271_FLAG_GPIO_POWER (3) | 342 | #define WL1271_FLAG_GPIO_POWER (3) |
345 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) | 343 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) |
346 | #define WL1271_FLAG_SCANNING (5) | 344 | #define WL1271_FLAG_IN_ELP (5) |
347 | #define WL1271_FLAG_IN_ELP (6) | 345 | #define WL1271_FLAG_PSM (6) |
348 | #define WL1271_FLAG_PSM (7) | 346 | #define WL1271_FLAG_PSM_REQUESTED (7) |
349 | #define WL1271_FLAG_PSM_REQUESTED (8) | 347 | #define WL1271_FLAG_IRQ_PENDING (8) |
350 | #define WL1271_FLAG_IRQ_PENDING (9) | 348 | #define WL1271_FLAG_IRQ_RUNNING (9) |
351 | #define WL1271_FLAG_IRQ_RUNNING (10) | 349 | #define WL1271_FLAG_IDLE (10) |
352 | #define WL1271_FLAG_IDLE (11) | 350 | #define WL1271_FLAG_IDLE_REQUESTED (11) |
353 | #define WL1271_FLAG_IDLE_REQUESTED (12) | 351 | #define WL1271_FLAG_PSPOLL_FAILURE (12) |
354 | unsigned long flags; | 352 | unsigned long flags; |
355 | 353 | ||
356 | struct wl1271_partition_set part; | 354 | struct wl1271_partition_set part; |
@@ -445,6 +443,10 @@ struct wl1271 { | |||
445 | 443 | ||
446 | struct completion *elp_compl; | 444 | struct completion *elp_compl; |
447 | struct delayed_work elp_work; | 445 | struct delayed_work elp_work; |
446 | struct delayed_work pspoll_work; | ||
447 | |||
448 | /* counter for ps-poll delivery failures */ | ||
449 | int ps_poll_failures; | ||
448 | 450 | ||
449 | /* retry counter for PSM entries */ | 451 | /* retry counter for PSM entries */ |
450 | u8 psm_entry_retry; | 452 | u8 psm_entry_retry; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index e19e2f8f1e52..bb245f05af49 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -1075,8 +1075,7 @@ out: | |||
1075 | return ret; | 1075 | return ret; |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1078 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) |
1079 | u8 version) | ||
1080 | { | 1079 | { |
1081 | struct wl1271_acx_arp_filter *acx; | 1080 | struct wl1271_acx_arp_filter *acx; |
1082 | int ret; | 1081 | int ret; |
@@ -1089,17 +1088,11 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | |||
1089 | goto out; | 1088 | goto out; |
1090 | } | 1089 | } |
1091 | 1090 | ||
1092 | acx->version = version; | 1091 | acx->version = ACX_IPV4_VERSION; |
1093 | acx->enable = enable; | 1092 | acx->enable = enable; |
1094 | 1093 | ||
1095 | if (enable == true) { | 1094 | if (enable == true) |
1096 | if (version == ACX_IPV4_VERSION) | 1095 | memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); |
1097 | memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE); | ||
1098 | else if (version == ACX_IPV6_VERSION) | ||
1099 | memcpy(acx->address, address, sizeof(acx->address)); | ||
1100 | else | ||
1101 | wl1271_error("Invalid IP version"); | ||
1102 | } | ||
1103 | 1096 | ||
1104 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, | 1097 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, |
1105 | acx, sizeof(*acx)); | 1098 | acx, sizeof(*acx)); |
@@ -1266,3 +1259,29 @@ out: | |||
1266 | kfree(acx); | 1259 | kfree(acx); |
1267 | return ret; | 1260 | return ret; |
1268 | } | 1261 | } |
1262 | |||
1263 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) | ||
1264 | { | ||
1265 | struct wl1271_acx_fw_tsf_information *tsf_info; | ||
1266 | int ret; | ||
1267 | |||
1268 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); | ||
1269 | if (!tsf_info) { | ||
1270 | ret = -ENOMEM; | ||
1271 | goto out; | ||
1272 | } | ||
1273 | |||
1274 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, | ||
1275 | tsf_info, sizeof(*tsf_info)); | ||
1276 | if (ret < 0) { | ||
1277 | wl1271_warning("acx tsf info interrogate failed"); | ||
1278 | goto out; | ||
1279 | } | ||
1280 | |||
1281 | *mactime = le32_to_cpu(tsf_info->current_tsf_low) | | ||
1282 | ((u64) le32_to_cpu(tsf_info->current_tsf_high) << 32); | ||
1283 | |||
1284 | out: | ||
1285 | kfree(tsf_info); | ||
1286 | return ret; | ||
1287 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 4c87e601df2f..4235bc56f750 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -993,6 +993,17 @@ struct wl1271_acx_rssi_snr_avg_weights { | |||
993 | u8 snr_data; | 993 | u8 snr_data; |
994 | }; | 994 | }; |
995 | 995 | ||
996 | struct wl1271_acx_fw_tsf_information { | ||
997 | struct acx_header header; | ||
998 | |||
999 | __le32 current_tsf_high; | ||
1000 | __le32 current_tsf_low; | ||
1001 | __le32 last_bttt_high; | ||
1002 | __le32 last_tbtt_low; | ||
1003 | u8 last_dtim_count; | ||
1004 | u8 padding[3]; | ||
1005 | } __packed; | ||
1006 | |||
996 | enum { | 1007 | enum { |
997 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1008 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
998 | ACX_MEM_CFG = 0x0003, | 1009 | ACX_MEM_CFG = 0x0003, |
@@ -1106,13 +1117,13 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl); | |||
1106 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1117 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1107 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | 1118 | int wl1271_acx_smart_reflex(struct wl1271 *wl); |
1108 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1119 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1109 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1120 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address); |
1110 | u8 version); | ||
1111 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1121 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1112 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | 1122 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); |
1113 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | 1123 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); |
1114 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | 1124 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, |
1115 | s16 thold, u8 hyst); | 1125 | s16 thold, u8 hyst); |
1116 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); | 1126 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); |
1127 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | ||
1117 | 1128 | ||
1118 | #endif /* __WL1271_ACX_H__ */ | 1129 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 1a36d8a2196e..f36430b0336d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -414,7 +414,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
414 | PS_REPORT_EVENT_ID | | 414 | PS_REPORT_EVENT_ID | |
415 | JOIN_EVENT_COMPLETE_ID | | 415 | JOIN_EVENT_COMPLETE_ID | |
416 | DISCONNECT_EVENT_COMPLETE_ID | | 416 | DISCONNECT_EVENT_COMPLETE_ID | |
417 | RSSI_SNR_TRIGGER_0_EVENT_ID; | 417 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
418 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | ||
419 | SOFT_GEMINI_SENSE_EVENT_ID; | ||
418 | 420 | ||
419 | ret = wl1271_event_unmask(wl); | 421 | ret = wl1271_event_unmask(wl); |
420 | if (ret < 0) { | 422 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 530678e45a13..ce503ddd5a41 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -104,100 +104,6 @@ out: | |||
104 | return ret; | 104 | return ret; |
105 | } | 105 | } |
106 | 106 | ||
107 | static int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) | ||
108 | { | ||
109 | struct wl1271_cmd_cal_channel_tune *cmd; | ||
110 | int ret = 0; | ||
111 | |||
112 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
113 | if (!cmd) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | cmd->test.id = TEST_CMD_CHANNEL_TUNE; | ||
117 | |||
118 | cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4; | ||
119 | /* set up any channel, 7 is in the middle of the range */ | ||
120 | cmd->channel = 7; | ||
121 | |||
122 | ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); | ||
123 | if (ret < 0) | ||
124 | wl1271_warning("TEST_CMD_CHANNEL_TUNE failed"); | ||
125 | |||
126 | kfree(cmd); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) | ||
131 | { | ||
132 | struct wl1271_cmd_cal_update_ref_point *cmd; | ||
133 | int ret = 0; | ||
134 | |||
135 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
136 | if (!cmd) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT; | ||
140 | |||
141 | /* FIXME: still waiting for the correct values */ | ||
142 | cmd->ref_power = 0; | ||
143 | cmd->ref_detector = 0; | ||
144 | |||
145 | cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G; | ||
146 | |||
147 | ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); | ||
148 | if (ret < 0) | ||
149 | wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed"); | ||
150 | |||
151 | kfree(cmd); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int wl1271_cmd_cal_p2g(struct wl1271 *wl) | ||
156 | { | ||
157 | struct wl1271_cmd_cal_p2g *cmd; | ||
158 | int ret = 0; | ||
159 | |||
160 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
161 | if (!cmd) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | cmd->test.id = TEST_CMD_P2G_CAL; | ||
165 | |||
166 | cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G; | ||
167 | |||
168 | ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); | ||
169 | if (ret < 0) | ||
170 | wl1271_warning("TEST_CMD_P2G_CAL failed"); | ||
171 | |||
172 | kfree(cmd); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static int wl1271_cmd_cal(struct wl1271 *wl) | ||
177 | { | ||
178 | /* | ||
179 | * FIXME: we must make sure that we're not sleeping when calibration | ||
180 | * is done | ||
181 | */ | ||
182 | int ret; | ||
183 | |||
184 | wl1271_notice("performing tx calibration"); | ||
185 | |||
186 | ret = wl1271_cmd_cal_channel_tune(wl); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | ret = wl1271_cmd_cal_update_ref_point(wl); | ||
191 | if (ret < 0) | ||
192 | return ret; | ||
193 | |||
194 | ret = wl1271_cmd_cal_p2g(wl); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | |||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | int wl1271_cmd_general_parms(struct wl1271 *wl) | 107 | int wl1271_cmd_general_parms(struct wl1271 *wl) |
202 | { | 108 | { |
203 | struct wl1271_general_parms_cmd *gen_parms; | 109 | struct wl1271_general_parms_cmd *gen_parms; |
@@ -226,7 +132,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
226 | int wl1271_cmd_radio_parms(struct wl1271 *wl) | 132 | int wl1271_cmd_radio_parms(struct wl1271 *wl) |
227 | { | 133 | { |
228 | struct wl1271_radio_parms_cmd *radio_parms; | 134 | struct wl1271_radio_parms_cmd *radio_parms; |
229 | struct conf_radio_parms *rparam = &wl->conf.init.radioparam; | 135 | struct wl1271_ini_general_params *gp = &wl->nvs->general_params; |
230 | int ret; | 136 | int ret; |
231 | 137 | ||
232 | if (!wl->nvs) | 138 | if (!wl->nvs) |
@@ -242,7 +148,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
242 | memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, | 148 | memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, |
243 | sizeof(struct wl1271_ini_band_params_2)); | 149 | sizeof(struct wl1271_ini_band_params_2)); |
244 | memcpy(&radio_parms->dyn_params_2, | 150 | memcpy(&radio_parms->dyn_params_2, |
245 | &wl->nvs->dyn_radio_params_2[rparam->fem].params, | 151 | &wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, |
246 | sizeof(struct wl1271_ini_fem_params_2)); | 152 | sizeof(struct wl1271_ini_fem_params_2)); |
247 | 153 | ||
248 | /* 5GHz parameters */ | 154 | /* 5GHz parameters */ |
@@ -250,7 +156,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
250 | &wl->nvs->stat_radio_params_5, | 156 | &wl->nvs->stat_radio_params_5, |
251 | sizeof(struct wl1271_ini_band_params_5)); | 157 | sizeof(struct wl1271_ini_band_params_5)); |
252 | memcpy(&radio_parms->dyn_params_5, | 158 | memcpy(&radio_parms->dyn_params_5, |
253 | &wl->nvs->dyn_radio_params_5[rparam->fem].params, | 159 | &wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, |
254 | sizeof(struct wl1271_ini_fem_params_5)); | 160 | sizeof(struct wl1271_ini_fem_params_5)); |
255 | 161 | ||
256 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 162 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
@@ -295,20 +201,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
295 | 201 | ||
296 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | 202 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) |
297 | { | 203 | { |
298 | static bool do_cal = true; | ||
299 | struct wl1271_cmd_join *join; | 204 | struct wl1271_cmd_join *join; |
300 | int ret, i; | 205 | int ret, i; |
301 | u8 *bssid; | 206 | u8 *bssid; |
302 | 207 | ||
303 | /* FIXME: remove when we get calibration from the factory */ | ||
304 | if (do_cal) { | ||
305 | ret = wl1271_cmd_cal(wl); | ||
306 | if (ret < 0) | ||
307 | wl1271_warning("couldn't calibrate"); | ||
308 | else | ||
309 | do_cal = false; | ||
310 | } | ||
311 | |||
312 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 208 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
313 | if (!join) { | 209 | if (!join) { |
314 | ret = -ENOMEM; | 210 | ret = -ENOMEM; |
@@ -567,142 +463,6 @@ out: | |||
567 | return ret; | 463 | return ret; |
568 | } | 464 | } |
569 | 465 | ||
570 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
571 | struct cfg80211_scan_request *req, u8 active_scan, | ||
572 | u8 high_prio, u8 band, u8 probe_requests) | ||
573 | { | ||
574 | |||
575 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | ||
576 | struct wl1271_cmd_scan *params = NULL; | ||
577 | struct ieee80211_channel *channels; | ||
578 | u32 rate; | ||
579 | int i, j, n_ch, ret; | ||
580 | u16 scan_options = 0; | ||
581 | u8 ieee_band; | ||
582 | |||
583 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { | ||
584 | ieee_band = IEEE80211_BAND_2GHZ; | ||
585 | rate = wl->conf.tx.basic_rate; | ||
586 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
587 | ieee_band = IEEE80211_BAND_2GHZ; | ||
588 | rate = wl->conf.tx.basic_rate; | ||
589 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
590 | ieee_band = IEEE80211_BAND_5GHZ; | ||
591 | rate = wl->conf.tx.basic_rate_5; | ||
592 | } else | ||
593 | return -EINVAL; | ||
594 | |||
595 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | ||
596 | return -EINVAL; | ||
597 | |||
598 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | ||
599 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | ||
600 | |||
601 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) | ||
602 | return -EINVAL; | ||
603 | |||
604 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
605 | if (!params) | ||
606 | return -ENOMEM; | ||
607 | |||
608 | params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
609 | params->params.rx_filter_options = | ||
610 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
611 | |||
612 | if (!active_scan) | ||
613 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
614 | if (high_prio) | ||
615 | scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; | ||
616 | params->params.scan_options = cpu_to_le16(scan_options); | ||
617 | |||
618 | params->params.num_probe_requests = probe_requests; | ||
619 | params->params.tx_rate = cpu_to_le32(rate); | ||
620 | params->params.tid_trigger = 0; | ||
621 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
622 | |||
623 | if (band == WL1271_SCAN_BAND_DUAL) | ||
624 | params->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
625 | else | ||
626 | params->params.band = band; | ||
627 | |||
628 | for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { | ||
629 | if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { | ||
630 | params->channels[j].min_duration = | ||
631 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | ||
632 | params->channels[j].max_duration = | ||
633 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | ||
634 | memset(¶ms->channels[j].bssid_lsb, 0xff, 4); | ||
635 | memset(¶ms->channels[j].bssid_msb, 0xff, 2); | ||
636 | params->channels[j].early_termination = 0; | ||
637 | params->channels[j].tx_power_att = | ||
638 | WL1271_SCAN_CURRENT_TX_PWR; | ||
639 | params->channels[j].channel = channels[i].hw_value; | ||
640 | j++; | ||
641 | } | ||
642 | } | ||
643 | |||
644 | params->params.num_channels = j; | ||
645 | |||
646 | if (ssid_len && ssid) { | ||
647 | params->params.ssid_len = ssid_len; | ||
648 | memcpy(params->params.ssid, ssid, ssid_len); | ||
649 | } | ||
650 | |||
651 | ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len, | ||
652 | req->ie, req->ie_len, ieee_band); | ||
653 | if (ret < 0) { | ||
654 | wl1271_error("PROBE request template failed"); | ||
655 | goto out; | ||
656 | } | ||
657 | |||
658 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
659 | if (!trigger) { | ||
660 | ret = -ENOMEM; | ||
661 | goto out; | ||
662 | } | ||
663 | |||
664 | /* disable the timeout */ | ||
665 | trigger->timeout = 0; | ||
666 | |||
667 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
668 | sizeof(*trigger), 0); | ||
669 | if (ret < 0) { | ||
670 | wl1271_error("trigger scan to failed for hw scan"); | ||
671 | goto out; | ||
672 | } | ||
673 | |||
674 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | ||
675 | |||
676 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
677 | if (wl1271_11a_enabled()) { | ||
678 | wl->scan.state = band; | ||
679 | if (band == WL1271_SCAN_BAND_DUAL) { | ||
680 | wl->scan.active = active_scan; | ||
681 | wl->scan.high_prio = high_prio; | ||
682 | wl->scan.probe_requests = probe_requests; | ||
683 | if (ssid_len && ssid) { | ||
684 | wl->scan.ssid_len = ssid_len; | ||
685 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
686 | } else | ||
687 | wl->scan.ssid_len = 0; | ||
688 | wl->scan.req = req; | ||
689 | } else | ||
690 | wl->scan.req = NULL; | ||
691 | } | ||
692 | |||
693 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | ||
694 | if (ret < 0) { | ||
695 | wl1271_error("SCAN failed"); | ||
696 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | ||
697 | goto out; | ||
698 | } | ||
699 | |||
700 | out: | ||
701 | kfree(params); | ||
702 | kfree(trigger); | ||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 466 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
707 | void *buf, size_t buf_len, int index, u32 rates) | 467 | void *buf, size_t buf_len, int index, u32 rates) |
708 | { | 468 | { |
@@ -807,7 +567,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | |||
807 | goto out; | 567 | goto out; |
808 | 568 | ||
809 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, | 569 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
810 | skb->len, 0, wl->basic_rate); | 570 | skb->len, 0, wl->basic_rate_set); |
811 | 571 | ||
812 | out: | 572 | out: |
813 | dev_kfree_skb(skb); | 573 | dev_kfree_skb(skb); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index f5745d829c9b..af577ee8eb02 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -41,9 +41,6 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | |||
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
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); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
45 | struct cfg80211_scan_request *req, u8 active_scan, | ||
46 | u8 high_prio, u8 band, u8 probe_requests); | ||
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 44 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len, int index, u32 rates); | 45 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 46 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
@@ -350,71 +347,6 @@ struct wl1271_cmd_set_keys { | |||
350 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | 347 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; |
351 | } __packed; | 348 | } __packed; |
352 | 349 | ||
353 | |||
354 | #define WL1271_SCAN_MAX_CHANNELS 24 | ||
355 | #define WL1271_SCAN_DEFAULT_TAG 1 | ||
356 | #define WL1271_SCAN_CURRENT_TX_PWR 0 | ||
357 | #define WL1271_SCAN_OPT_ACTIVE 0 | ||
358 | #define WL1271_SCAN_OPT_PASSIVE 1 | ||
359 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | ||
360 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | ||
361 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | ||
362 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | ||
363 | #define WL1271_SCAN_BAND_5_GHZ 1 | ||
364 | #define WL1271_SCAN_BAND_DUAL 2 | ||
365 | |||
366 | struct basic_scan_params { | ||
367 | __le32 rx_config_options; | ||
368 | __le32 rx_filter_options; | ||
369 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
370 | __le16 scan_options; | ||
371 | /* Number of scan channels in the list (maximum 30) */ | ||
372 | u8 num_channels; | ||
373 | /* This field indicates the number of probe requests to send | ||
374 | per channel for an active scan */ | ||
375 | u8 num_probe_requests; | ||
376 | /* Rate bit field for sending the probes */ | ||
377 | __le32 tx_rate; | ||
378 | u8 tid_trigger; | ||
379 | u8 ssid_len; | ||
380 | /* in order to align */ | ||
381 | u8 padding1[2]; | ||
382 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
383 | /* Band to scan */ | ||
384 | u8 band; | ||
385 | u8 use_ssid_list; | ||
386 | u8 scan_tag; | ||
387 | u8 padding2; | ||
388 | } __packed; | ||
389 | |||
390 | struct basic_scan_channel_params { | ||
391 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
392 | __le32 min_duration; | ||
393 | __le32 max_duration; | ||
394 | __le32 bssid_lsb; | ||
395 | __le16 bssid_msb; | ||
396 | u8 early_termination; | ||
397 | u8 tx_power_att; | ||
398 | u8 channel; | ||
399 | /* FW internal use only! */ | ||
400 | u8 dfs_candidate; | ||
401 | u8 activity_detected; | ||
402 | u8 pad; | ||
403 | } __packed; | ||
404 | |||
405 | struct wl1271_cmd_scan { | ||
406 | struct wl1271_cmd_header header; | ||
407 | |||
408 | struct basic_scan_params params; | ||
409 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
410 | } __packed; | ||
411 | |||
412 | struct wl1271_cmd_trigger_scan_to { | ||
413 | struct wl1271_cmd_header header; | ||
414 | |||
415 | __le32 timeout; | ||
416 | } __packed; | ||
417 | |||
418 | struct wl1271_cmd_test_header { | 350 | struct wl1271_cmd_test_header { |
419 | u8 id; | 351 | u8 id; |
420 | u8 padding[3]; | 352 | u8 padding[3]; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index d046d044b5bd..0435ffda8f73 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -874,6 +874,13 @@ struct conf_conn_settings { | |||
874 | u8 ps_poll_threshold; | 874 | u8 ps_poll_threshold; |
875 | 875 | ||
876 | /* | 876 | /* |
877 | * PS Poll failure recovery ACTIVE period length | ||
878 | * | ||
879 | * Range: u32 (ms) | ||
880 | */ | ||
881 | u32 ps_poll_recovery_period; | ||
882 | |||
883 | /* | ||
877 | * Configuration of signal average weights. | 884 | * Configuration of signal average weights. |
878 | */ | 885 | */ |
879 | struct conf_sig_weights sig_weights; | 886 | struct conf_sig_weights sig_weights; |
@@ -948,14 +955,6 @@ struct conf_radio_parms { | |||
948 | u8 fem; | 955 | u8 fem; |
949 | }; | 956 | }; |
950 | 957 | ||
951 | struct conf_init_settings { | ||
952 | /* | ||
953 | * Configure radio parameters. | ||
954 | */ | ||
955 | struct conf_radio_parms radioparam; | ||
956 | |||
957 | }; | ||
958 | |||
959 | struct conf_itrim_settings { | 958 | struct conf_itrim_settings { |
960 | /* enable dco itrim */ | 959 | /* enable dco itrim */ |
961 | u8 enable; | 960 | u8 enable; |
@@ -1022,7 +1021,6 @@ struct conf_drv_settings { | |||
1022 | struct conf_rx_settings rx; | 1021 | struct conf_rx_settings rx; |
1023 | struct conf_tx_settings tx; | 1022 | struct conf_tx_settings tx; |
1024 | struct conf_conn_settings conn; | 1023 | struct conf_conn_settings conn; |
1025 | struct conf_init_settings init; | ||
1026 | struct conf_itrim_settings itrim; | 1024 | struct conf_itrim_settings itrim; |
1027 | struct conf_pm_config_settings pm_config; | 1025 | struct conf_pm_config_settings pm_config; |
1028 | struct conf_roam_trigger_settings roam_trigger; | 1026 | struct conf_roam_trigger_settings roam_trigger; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index ca52cdec7a8f..25ce2cd5e3f3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -26,36 +26,64 @@ | |||
26 | #include "wl1271_io.h" | 26 | #include "wl1271_io.h" |
27 | #include "wl1271_event.h" | 27 | #include "wl1271_event.h" |
28 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
29 | #include "wl1271_scan.h" | ||
29 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
30 | 31 | ||
31 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 32 | void wl1271_pspoll_work(struct work_struct *work) |
32 | struct event_mailbox *mbox) | ||
33 | { | 33 | { |
34 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 34 | struct delayed_work *dwork; |
35 | mbox->scheduled_scan_status); | 35 | struct wl1271 *wl; |
36 | 36 | ||
37 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 37 | dwork = container_of(work, struct delayed_work, work); |
38 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 38 | wl = container_of(dwork, struct wl1271, pspoll_work); |
39 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | 39 | |
40 | * to the wl1271_cmd_scan function that we are not | 40 | wl1271_debug(DEBUG_EVENT, "pspoll work"); |
41 | * scanning as it checks that. | 41 | |
42 | */ | 42 | mutex_lock(&wl->mutex); |
43 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 43 | |
44 | /* FIXME: ie missing! */ | 44 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) |
45 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 45 | goto out; |
46 | wl->scan.req, | 46 | |
47 | wl->scan.active, | 47 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
48 | wl->scan.high_prio, | 48 | goto out; |
49 | WL1271_SCAN_BAND_5_GHZ, | 49 | |
50 | wl->scan.probe_requests); | 50 | /* |
51 | } else { | 51 | * if we end up here, then we were in powersave when the pspoll |
52 | mutex_unlock(&wl->mutex); | 52 | * delivery failure occurred, and no-one changed state since, so |
53 | ieee80211_scan_completed(wl->hw, false); | 53 | * we should go back to powersave. |
54 | mutex_lock(&wl->mutex); | 54 | */ |
55 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); | 55 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); |
56 | } | 56 | |
57 | out: | ||
58 | mutex_unlock(&wl->mutex); | ||
59 | }; | ||
60 | |||
61 | static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) | ||
62 | { | ||
63 | int delay = wl->conf.conn.ps_poll_recovery_period; | ||
64 | int ret; | ||
65 | |||
66 | wl->ps_poll_failures++; | ||
67 | if (wl->ps_poll_failures == 1) | ||
68 | wl1271_info("AP with dysfunctional ps-poll, " | ||
69 | "trying to work around it."); | ||
70 | |||
71 | /* force active mode receive data from the AP */ | ||
72 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
73 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true); | ||
74 | if (ret < 0) | ||
75 | return; | ||
76 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | ||
77 | ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work, | ||
78 | msecs_to_jiffies(delay)); | ||
57 | } | 79 | } |
58 | return 0; | 80 | |
81 | /* | ||
82 | * If already in active mode, lets we should be getting data from | ||
83 | * the AP right away. If we enter PSM too fast after this, and data | ||
84 | * remains on the AP, we will get another event like this, and we'll | ||
85 | * go into active once more. | ||
86 | */ | ||
59 | } | 87 | } |
60 | 88 | ||
61 | static int wl1271_event_ps_report(struct wl1271 *wl, | 89 | static int wl1271_event_ps_report(struct wl1271 *wl, |
@@ -163,9 +191,19 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
163 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); | 191 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); |
164 | 192 | ||
165 | if (vector & SCAN_COMPLETE_EVENT_ID) { | 193 | if (vector & SCAN_COMPLETE_EVENT_ID) { |
166 | ret = wl1271_event_scan_complete(wl, mbox); | 194 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
167 | if (ret < 0) | 195 | mbox->scheduled_scan_status); |
168 | return ret; | 196 | |
197 | wl1271_scan_stm(wl); | ||
198 | } | ||
199 | |||
200 | /* disable dynamic PS when requested by the firmware */ | ||
201 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID && | ||
202 | wl->bss_type == BSS_TYPE_STA_BSS) { | ||
203 | if (mbox->soft_gemini_sense_info) | ||
204 | ieee80211_disable_dyn_ps(wl->vif); | ||
205 | else | ||
206 | ieee80211_enable_dyn_ps(wl->vif); | ||
169 | } | 207 | } |
170 | 208 | ||
171 | /* | 209 | /* |
@@ -191,6 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
191 | return ret; | 229 | return ret; |
192 | } | 230 | } |
193 | 231 | ||
232 | if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) | ||
233 | wl1271_event_pspoll_delivery_fail(wl); | ||
234 | |||
194 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 235 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
195 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); | 236 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
196 | if (wl->vif) | 237 | if (wl->vif) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 43d5aeae1783..e4751667cf5e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -121,5 +121,6 @@ struct event_mailbox { | |||
121 | int wl1271_event_unmask(struct wl1271 *wl); | 121 | int wl1271_event_unmask(struct wl1271 *wl); |
122 | void wl1271_event_mbox_config(struct wl1271 *wl); | 122 | void wl1271_event_mbox_config(struct wl1271 *wl); |
123 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 123 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
124 | void wl1271_pspoll_work(struct work_struct *work); | ||
124 | 125 | ||
125 | #endif | 126 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7a14da506d78..d30de58cef90 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/crc32.h> | 28 | #include <linux/crc32.h> |
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/inetdevice.h> | ||
32 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | 33 | ||
@@ -45,6 +44,7 @@ | |||
45 | #include "wl1271_cmd.h" | 44 | #include "wl1271_cmd.h" |
46 | #include "wl1271_boot.h" | 45 | #include "wl1271_boot.h" |
47 | #include "wl1271_testmode.h" | 46 | #include "wl1271_testmode.h" |
47 | #include "wl1271_scan.h" | ||
48 | 48 | ||
49 | #define WL1271_BOOT_RETRIES 3 | 49 | #define WL1271_BOOT_RETRIES 3 |
50 | 50 | ||
@@ -55,7 +55,7 @@ static struct conf_drv_settings default_conf = { | |||
55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | 55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | 56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
57 | [CONF_SG_BT_LOAD_RATIO] = 50, | 57 | [CONF_SG_BT_LOAD_RATIO] = 50, |
58 | [CONF_SG_AUTO_PS_MODE] = 0, | 58 | [CONF_SG_AUTO_PS_MODE] = 1, |
59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | 59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | 60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
61 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | 61 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, |
@@ -234,18 +234,14 @@ static struct conf_drv_settings default_conf = { | |||
234 | .beacon_rx_timeout = 10000, | 234 | .beacon_rx_timeout = 10000, |
235 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
236 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
237 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 10, |
238 | .ps_poll_recovery_period = 700, | ||
238 | .bet_enable = CONF_BET_MODE_ENABLE, | 239 | .bet_enable = CONF_BET_MODE_ENABLE, |
239 | .bet_max_consecutive = 10, | 240 | .bet_max_consecutive = 10, |
240 | .psm_entry_retries = 3, | 241 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | 242 | .keep_alive_interval = 55000, |
242 | .max_listen_interval = 20, | 243 | .max_listen_interval = 20, |
243 | }, | 244 | }, |
244 | .init = { | ||
245 | .radioparam = { | ||
246 | .fem = 1, | ||
247 | } | ||
248 | }, | ||
249 | .itrim = { | 245 | .itrim = { |
250 | .enable = false, | 246 | .enable = false, |
251 | .timeout = 50000, | 247 | .timeout = 50000, |
@@ -818,93 +814,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
818 | return NETDEV_TX_OK; | 814 | return NETDEV_TX_OK; |
819 | } | 815 | } |
820 | 816 | ||
821 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | ||
822 | void *arg) | ||
823 | { | ||
824 | struct net_device *dev; | ||
825 | struct wireless_dev *wdev; | ||
826 | struct wiphy *wiphy; | ||
827 | struct ieee80211_hw *hw; | ||
828 | struct wl1271 *wl; | ||
829 | struct wl1271 *wl_temp; | ||
830 | struct in_device *idev; | ||
831 | struct in_ifaddr *ifa = arg; | ||
832 | int ret = 0; | ||
833 | |||
834 | /* FIXME: this ugly function should probably be implemented in the | ||
835 | * mac80211, and here should only be a simple callback handling actual | ||
836 | * setting of the filters. Now we need to dig up references to | ||
837 | * various structures to gain access to what we need. | ||
838 | * Also, because of this, there is no "initial" setting of the filter | ||
839 | * in "op_start", because we don't want to dig up struct net_device | ||
840 | * there - the filter will be set upon first change of the interface | ||
841 | * IP address. */ | ||
842 | |||
843 | dev = ifa->ifa_dev->dev; | ||
844 | |||
845 | wdev = dev->ieee80211_ptr; | ||
846 | if (wdev == NULL) | ||
847 | return NOTIFY_DONE; | ||
848 | |||
849 | wiphy = wdev->wiphy; | ||
850 | if (wiphy == NULL) | ||
851 | return NOTIFY_DONE; | ||
852 | |||
853 | hw = wiphy_priv(wiphy); | ||
854 | if (hw == NULL) | ||
855 | return NOTIFY_DONE; | ||
856 | |||
857 | /* Check that the interface is one supported by this driver. */ | ||
858 | wl_temp = hw->priv; | ||
859 | list_for_each_entry(wl, &wl_list, list) { | ||
860 | if (wl == wl_temp) | ||
861 | break; | ||
862 | } | ||
863 | if (wl != wl_temp) | ||
864 | return NOTIFY_DONE; | ||
865 | |||
866 | /* Get the interface IP address for the device. "ifa" will become | ||
867 | NULL if: | ||
868 | - there is no IPV4 protocol address configured | ||
869 | - there are multiple (virtual) IPV4 addresses configured | ||
870 | When "ifa" is NULL, filtering will be disabled. | ||
871 | */ | ||
872 | ifa = NULL; | ||
873 | idev = dev->ip_ptr; | ||
874 | if (idev) | ||
875 | ifa = idev->ifa_list; | ||
876 | |||
877 | if (ifa && ifa->ifa_next) | ||
878 | ifa = NULL; | ||
879 | |||
880 | mutex_lock(&wl->mutex); | ||
881 | |||
882 | if (wl->state == WL1271_STATE_OFF) | ||
883 | goto out; | ||
884 | |||
885 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
886 | if (ret < 0) | ||
887 | goto out; | ||
888 | if (ifa) | ||
889 | ret = wl1271_acx_arp_ip_filter(wl, true, | ||
890 | (u8 *)&ifa->ifa_address, | ||
891 | ACX_IPV4_VERSION); | ||
892 | else | ||
893 | ret = wl1271_acx_arp_ip_filter(wl, false, NULL, | ||
894 | ACX_IPV4_VERSION); | ||
895 | wl1271_ps_elp_sleep(wl); | ||
896 | |||
897 | out: | ||
898 | mutex_unlock(&wl->mutex); | ||
899 | |||
900 | return NOTIFY_OK; | ||
901 | } | ||
902 | |||
903 | static struct notifier_block wl1271_dev_notifier = { | ||
904 | .notifier_call = wl1271_dev_notify, | ||
905 | }; | ||
906 | |||
907 | |||
908 | static int wl1271_op_start(struct ieee80211_hw *hw) | 817 | static int wl1271_op_start(struct ieee80211_hw *hw) |
909 | { | 818 | { |
910 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 819 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -1008,10 +917,8 @@ power_off: | |||
1008 | out: | 917 | out: |
1009 | mutex_unlock(&wl->mutex); | 918 | mutex_unlock(&wl->mutex); |
1010 | 919 | ||
1011 | if (!ret) { | 920 | if (!ret) |
1012 | list_add(&wl->list, &wl_list); | 921 | list_add(&wl->list, &wl_list); |
1013 | register_inetaddr_notifier(&wl1271_dev_notifier); | ||
1014 | } | ||
1015 | 922 | ||
1016 | return ret; | 923 | return ret; |
1017 | } | 924 | } |
@@ -1022,8 +929,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1022 | struct wl1271 *wl = hw->priv; | 929 | struct wl1271 *wl = hw->priv; |
1023 | int i; | 930 | int i; |
1024 | 931 | ||
1025 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | ||
1026 | |||
1027 | mutex_lock(&wl->mutex); | 932 | mutex_lock(&wl->mutex); |
1028 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 933 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
1029 | 934 | ||
@@ -1033,10 +938,17 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1033 | 938 | ||
1034 | WARN_ON(wl->state != WL1271_STATE_ON); | 939 | WARN_ON(wl->state != WL1271_STATE_ON); |
1035 | 940 | ||
1036 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 941 | /* enable dyn ps just in case (if left on due to fw crash etc) */ |
942 | if (wl->bss_type == BSS_TYPE_STA_BSS) | ||
943 | ieee80211_enable_dyn_ps(wl->vif); | ||
944 | |||
945 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | ||
1037 | mutex_unlock(&wl->mutex); | 946 | mutex_unlock(&wl->mutex); |
1038 | ieee80211_scan_completed(wl->hw, true); | 947 | ieee80211_scan_completed(wl->hw, true); |
1039 | mutex_lock(&wl->mutex); | 948 | mutex_lock(&wl->mutex); |
949 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
950 | kfree(wl->scan.scanned_ch); | ||
951 | wl->scan.scanned_ch = NULL; | ||
1040 | } | 952 | } |
1041 | 953 | ||
1042 | wl->state = WL1271_STATE_OFF; | 954 | wl->state = WL1271_STATE_OFF; |
@@ -1047,6 +959,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1047 | 959 | ||
1048 | cancel_work_sync(&wl->irq_work); | 960 | cancel_work_sync(&wl->irq_work); |
1049 | cancel_work_sync(&wl->tx_work); | 961 | cancel_work_sync(&wl->tx_work); |
962 | cancel_delayed_work_sync(&wl->pspoll_work); | ||
1050 | 963 | ||
1051 | mutex_lock(&wl->mutex); | 964 | mutex_lock(&wl->mutex); |
1052 | 965 | ||
@@ -1352,6 +1265,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1352 | wl1271_warning("idle mode change failed %d", ret); | 1265 | wl1271_warning("idle mode change failed %d", ret); |
1353 | } | 1266 | } |
1354 | 1267 | ||
1268 | /* | ||
1269 | * if mac80211 changes the PSM mode, make sure the mode is not | ||
1270 | * incorrectly changed after the pspoll failure active window. | ||
1271 | */ | ||
1272 | if (changed & IEEE80211_CONF_CHANGE_PS) | ||
1273 | clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | ||
1274 | |||
1355 | if (conf->flags & IEEE80211_CONF_PS && | 1275 | if (conf->flags & IEEE80211_CONF_PS && |
1356 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1276 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1357 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1277 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1634,11 +1554,9 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1634 | goto out; | 1554 | goto out; |
1635 | 1555 | ||
1636 | if (wl1271_11a_enabled()) | 1556 | if (wl1271_11a_enabled()) |
1637 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, | 1557 | ret = wl1271_scan(hw->priv, ssid, len, req); |
1638 | 1, 0, WL1271_SCAN_BAND_DUAL, 3); | ||
1639 | else | 1558 | else |
1640 | ret = wl1271_cmd_scan(hw->priv, ssid, len, req, | 1559 | ret = wl1271_scan(hw->priv, ssid, len, req); |
1641 | 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3); | ||
1642 | 1560 | ||
1643 | wl1271_ps_elp_sleep(wl); | 1561 | wl1271_ps_elp_sleep(wl); |
1644 | 1562 | ||
@@ -1811,6 +1729,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1811 | wl->aid = bss_conf->aid; | 1729 | wl->aid = bss_conf->aid; |
1812 | set_assoc = true; | 1730 | set_assoc = true; |
1813 | 1731 | ||
1732 | wl->ps_poll_failures = 0; | ||
1733 | |||
1814 | /* | 1734 | /* |
1815 | * use basic rates from AP, and determine lowest rate | 1735 | * use basic rates from AP, and determine lowest rate |
1816 | * to use with control frames. | 1736 | * to use with control frames. |
@@ -1860,6 +1780,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1860 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1780 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1861 | wl->aid = 0; | 1781 | wl->aid = 0; |
1862 | 1782 | ||
1783 | /* re-enable dynamic ps - just in case */ | ||
1784 | ieee80211_enable_dyn_ps(wl->vif); | ||
1785 | |||
1863 | /* revert back to minimum rates for the current band */ | 1786 | /* revert back to minimum rates for the current band */ |
1864 | wl1271_set_band_rate(wl); | 1787 | wl1271_set_band_rate(wl); |
1865 | wl->basic_rate = wl1271_min_rate_get(wl); | 1788 | wl->basic_rate = wl1271_min_rate_get(wl); |
@@ -1908,6 +1831,19 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1908 | } | 1831 | } |
1909 | } | 1832 | } |
1910 | 1833 | ||
1834 | if (changed & BSS_CHANGED_ARP_FILTER) { | ||
1835 | __be32 addr = bss_conf->arp_addr_list[0]; | ||
1836 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
1837 | |||
1838 | if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) | ||
1839 | ret = wl1271_acx_arp_ip_filter(wl, true, addr); | ||
1840 | else | ||
1841 | ret = wl1271_acx_arp_ip_filter(wl, false, addr); | ||
1842 | |||
1843 | if (ret < 0) | ||
1844 | goto out_sleep; | ||
1845 | } | ||
1846 | |||
1911 | if (do_join) { | 1847 | if (do_join) { |
1912 | ret = wl1271_join(wl, set_assoc); | 1848 | ret = wl1271_join(wl, set_assoc); |
1913 | if (ret < 0) { | 1849 | if (ret < 0) { |
@@ -1966,6 +1902,32 @@ out: | |||
1966 | return ret; | 1902 | return ret; |
1967 | } | 1903 | } |
1968 | 1904 | ||
1905 | static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) | ||
1906 | { | ||
1907 | |||
1908 | struct wl1271 *wl = hw->priv; | ||
1909 | u64 mactime = ULLONG_MAX; | ||
1910 | int ret; | ||
1911 | |||
1912 | wl1271_debug(DEBUG_MAC80211, "mac80211 get tsf"); | ||
1913 | |||
1914 | mutex_lock(&wl->mutex); | ||
1915 | |||
1916 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1917 | if (ret < 0) | ||
1918 | goto out; | ||
1919 | |||
1920 | ret = wl1271_acx_tsf_info(wl, &mactime); | ||
1921 | if (ret < 0) | ||
1922 | goto out_sleep; | ||
1923 | |||
1924 | out_sleep: | ||
1925 | wl1271_ps_elp_sleep(wl); | ||
1926 | |||
1927 | out: | ||
1928 | mutex_unlock(&wl->mutex); | ||
1929 | return mactime; | ||
1930 | } | ||
1969 | 1931 | ||
1970 | /* can't be const, mac80211 writes to this */ | 1932 | /* can't be const, mac80211 writes to this */ |
1971 | static struct ieee80211_rate wl1271_rates[] = { | 1933 | static struct ieee80211_rate wl1271_rates[] = { |
@@ -2195,6 +2157,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
2195 | .bss_info_changed = wl1271_op_bss_info_changed, | 2157 | .bss_info_changed = wl1271_op_bss_info_changed, |
2196 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 2158 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
2197 | .conf_tx = wl1271_op_conf_tx, | 2159 | .conf_tx = wl1271_op_conf_tx, |
2160 | .get_tsf = wl1271_op_get_tsf, | ||
2198 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2161 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
2199 | }; | 2162 | }; |
2200 | 2163 | ||
@@ -2407,6 +2370,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2407 | skb_queue_head_init(&wl->tx_queue); | 2370 | skb_queue_head_init(&wl->tx_queue); |
2408 | 2371 | ||
2409 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2372 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2373 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | ||
2410 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2374 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2411 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 2375 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
2412 | wl->default_key = 0; | 2376 | wl->default_key = 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index b98fb643fab0..e98f22b3c3ba 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -53,12 +53,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
53 | status->band = wl->band; | 53 | status->band = wl->band; |
54 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); | 54 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); |
55 | 55 | ||
56 | /* | ||
57 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | ||
58 | * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we | ||
59 | * only need the mactime for monitor mode. For now the mactime is | ||
60 | * not valid, so RX_FLAG_TSFT should not be set | ||
61 | */ | ||
62 | status->signal = desc->rssi; | 56 | status->signal = desc->rssi; |
63 | 57 | ||
64 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 58 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c new file mode 100644 index 000000000000..fec43eed8c55 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/ieee80211.h> | ||
25 | |||
26 | #include "wl1271.h" | ||
27 | #include "wl1271_cmd.h" | ||
28 | #include "wl1271_scan.h" | ||
29 | #include "wl1271_acx.h" | ||
30 | |||
31 | static int wl1271_get_scan_channels(struct wl1271 *wl, | ||
32 | struct cfg80211_scan_request *req, | ||
33 | struct basic_scan_channel_params *channels, | ||
34 | enum ieee80211_band band, bool passive) | ||
35 | { | ||
36 | int i, j; | ||
37 | u32 flags; | ||
38 | |||
39 | for (i = 0, j = 0; | ||
40 | i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; | ||
41 | i++) { | ||
42 | |||
43 | flags = req->channels[i]->flags; | ||
44 | |||
45 | if (!wl->scan.scanned_ch[i] && | ||
46 | !(flags & IEEE80211_CHAN_DISABLED) && | ||
47 | ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && | ||
48 | (req->channels[i]->band == band)) { | ||
49 | |||
50 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | ||
51 | req->channels[i]->band, | ||
52 | req->channels[i]->center_freq); | ||
53 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
54 | req->channels[i]->hw_value, | ||
55 | req->channels[i]->flags); | ||
56 | wl1271_debug(DEBUG_SCAN, | ||
57 | "max_antenna_gain %d, max_power %d", | ||
58 | req->channels[i]->max_antenna_gain, | ||
59 | req->channels[i]->max_power); | ||
60 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", | ||
61 | req->channels[i]->beacon_found); | ||
62 | |||
63 | channels[j].min_duration = | ||
64 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | ||
65 | channels[j].max_duration = | ||
66 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | ||
67 | channels[j].early_termination = 0; | ||
68 | channels[j].tx_power_att = req->channels[i]->max_power; | ||
69 | channels[j].channel = req->channels[i]->hw_value; | ||
70 | |||
71 | memset(&channels[j].bssid_lsb, 0xff, 4); | ||
72 | memset(&channels[j].bssid_msb, 0xff, 2); | ||
73 | |||
74 | /* Mark the channels we already used */ | ||
75 | wl->scan.scanned_ch[i] = true; | ||
76 | |||
77 | j++; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return j; | ||
82 | } | ||
83 | |||
84 | #define WL1271_NOTHING_TO_SCAN 1 | ||
85 | |||
86 | static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | ||
87 | bool passive, u32 basic_rate) | ||
88 | { | ||
89 | struct wl1271_cmd_scan *cmd; | ||
90 | struct wl1271_cmd_trigger_scan_to *trigger; | ||
91 | int ret; | ||
92 | u16 scan_options = 0; | ||
93 | |||
94 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
95 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | ||
96 | if (!cmd || !trigger) { | ||
97 | ret = -ENOMEM; | ||
98 | goto out; | ||
99 | } | ||
100 | |||
101 | /* We always use high priority scans */ | ||
102 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; | ||
103 | if(passive) | ||
104 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | ||
105 | cmd->params.scan_options = cpu_to_le16(scan_options); | ||
106 | |||
107 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | ||
108 | cmd->channels, | ||
109 | band, passive); | ||
110 | if (cmd->params.n_ch == 0) { | ||
111 | ret = WL1271_NOTHING_TO_SCAN; | ||
112 | goto out; | ||
113 | } | ||
114 | |||
115 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | ||
116 | cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
117 | cmd->params.rx_filter_options = | ||
118 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | ||
119 | |||
120 | cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS; | ||
121 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | ||
122 | cmd->params.tid_trigger = 0; | ||
123 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | ||
124 | |||
125 | if (band == IEEE80211_BAND_2GHZ) | ||
126 | cmd->params.band = WL1271_SCAN_BAND_2_4_GHZ; | ||
127 | else | ||
128 | cmd->params.band = WL1271_SCAN_BAND_5_GHZ; | ||
129 | |||
130 | if (wl->scan.ssid_len && wl->scan.ssid) { | ||
131 | cmd->params.ssid_len = wl->scan.ssid_len; | ||
132 | memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); | ||
133 | } | ||
134 | |||
135 | ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, | ||
136 | wl->scan.req->ie, wl->scan.req->ie_len, | ||
137 | band); | ||
138 | if (ret < 0) { | ||
139 | wl1271_error("PROBE request template failed"); | ||
140 | goto out; | ||
141 | } | ||
142 | |||
143 | /* disable the timeout */ | ||
144 | trigger->timeout = 0; | ||
145 | ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, | ||
146 | sizeof(*trigger), 0); | ||
147 | if (ret < 0) { | ||
148 | wl1271_error("trigger scan to failed for hw scan"); | ||
149 | goto out; | ||
150 | } | ||
151 | |||
152 | wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd)); | ||
153 | |||
154 | ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0); | ||
155 | if (ret < 0) { | ||
156 | wl1271_error("SCAN failed"); | ||
157 | goto out; | ||
158 | } | ||
159 | |||
160 | out: | ||
161 | kfree(cmd); | ||
162 | kfree(trigger); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | void wl1271_scan_stm(struct wl1271 *wl) | ||
167 | { | ||
168 | int ret; | ||
169 | |||
170 | switch (wl->scan.state) { | ||
171 | case WL1271_SCAN_STATE_IDLE: | ||
172 | break; | ||
173 | |||
174 | case WL1271_SCAN_STATE_2GHZ_ACTIVE: | ||
175 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, | ||
176 | wl->conf.tx.basic_rate); | ||
177 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
178 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; | ||
179 | wl1271_scan_stm(wl); | ||
180 | } | ||
181 | |||
182 | break; | ||
183 | |||
184 | case WL1271_SCAN_STATE_2GHZ_PASSIVE: | ||
185 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, | ||
186 | wl->conf.tx.basic_rate); | ||
187 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
188 | if (wl1271_11a_enabled()) | ||
189 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | ||
190 | else | ||
191 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
192 | wl1271_scan_stm(wl); | ||
193 | } | ||
194 | |||
195 | break; | ||
196 | |||
197 | case WL1271_SCAN_STATE_5GHZ_ACTIVE: | ||
198 | ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, | ||
199 | wl->conf.tx.basic_rate_5); | ||
200 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
201 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; | ||
202 | wl1271_scan_stm(wl); | ||
203 | } | ||
204 | |||
205 | break; | ||
206 | |||
207 | case WL1271_SCAN_STATE_5GHZ_PASSIVE: | ||
208 | ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, | ||
209 | wl->conf.tx.basic_rate_5); | ||
210 | if (ret == WL1271_NOTHING_TO_SCAN) { | ||
211 | wl->scan.state = WL1271_SCAN_STATE_DONE; | ||
212 | wl1271_scan_stm(wl); | ||
213 | } | ||
214 | |||
215 | break; | ||
216 | |||
217 | case WL1271_SCAN_STATE_DONE: | ||
218 | mutex_unlock(&wl->mutex); | ||
219 | ieee80211_scan_completed(wl->hw, false); | ||
220 | mutex_lock(&wl->mutex); | ||
221 | |||
222 | kfree(wl->scan.scanned_ch); | ||
223 | wl->scan.scanned_ch = NULL; | ||
224 | |||
225 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
226 | break; | ||
227 | |||
228 | default: | ||
229 | wl1271_error("invalid scan state"); | ||
230 | break; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
235 | struct cfg80211_scan_request *req) | ||
236 | { | ||
237 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) | ||
238 | return -EBUSY; | ||
239 | |||
240 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_ACTIVE; | ||
241 | |||
242 | if (ssid_len && ssid) { | ||
243 | wl->scan.ssid_len = ssid_len; | ||
244 | memcpy(wl->scan.ssid, ssid, ssid_len); | ||
245 | } else { | ||
246 | wl->scan.ssid_len = 0; | ||
247 | } | ||
248 | |||
249 | wl->scan.req = req; | ||
250 | |||
251 | wl->scan.scanned_ch = kzalloc(req->n_channels * | ||
252 | sizeof(*wl->scan.scanned_ch), | ||
253 | GFP_KERNEL); | ||
254 | wl1271_scan_stm(wl); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h new file mode 100644 index 000000000000..f1815700f5f9 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_SCAN_H__ | ||
25 | #define __WL1271_SCAN_H__ | ||
26 | |||
27 | #include "wl1271.h" | ||
28 | |||
29 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | ||
30 | struct cfg80211_scan_request *req); | ||
31 | int wl1271_scan_build_probe_req(struct wl1271 *wl, | ||
32 | const u8 *ssid, size_t ssid_len, | ||
33 | const u8 *ie, size_t ie_len, u8 band); | ||
34 | void wl1271_scan_stm(struct wl1271 *wl); | ||
35 | |||
36 | #define WL1271_SCAN_MAX_CHANNELS 24 | ||
37 | #define WL1271_SCAN_DEFAULT_TAG 1 | ||
38 | #define WL1271_SCAN_CURRENT_TX_PWR 0 | ||
39 | #define WL1271_SCAN_OPT_ACTIVE 0 | ||
40 | #define WL1271_SCAN_OPT_PASSIVE 1 | ||
41 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | ||
42 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | ||
43 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | ||
44 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | ||
45 | #define WL1271_SCAN_BAND_5_GHZ 1 | ||
46 | #define WL1271_SCAN_PROBE_REQS 3 | ||
47 | |||
48 | enum { | ||
49 | WL1271_SCAN_STATE_IDLE, | ||
50 | WL1271_SCAN_STATE_2GHZ_ACTIVE, | ||
51 | WL1271_SCAN_STATE_2GHZ_PASSIVE, | ||
52 | WL1271_SCAN_STATE_5GHZ_ACTIVE, | ||
53 | WL1271_SCAN_STATE_5GHZ_PASSIVE, | ||
54 | WL1271_SCAN_STATE_DONE | ||
55 | }; | ||
56 | |||
57 | struct basic_scan_params { | ||
58 | __le32 rx_config_options; | ||
59 | __le32 rx_filter_options; | ||
60 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | ||
61 | __le16 scan_options; | ||
62 | /* Number of scan channels in the list (maximum 30) */ | ||
63 | u8 n_ch; | ||
64 | /* This field indicates the number of probe requests to send | ||
65 | per channel for an active scan */ | ||
66 | u8 n_probe_reqs; | ||
67 | /* Rate bit field for sending the probes */ | ||
68 | __le32 tx_rate; | ||
69 | u8 tid_trigger; | ||
70 | u8 ssid_len; | ||
71 | /* in order to align */ | ||
72 | u8 padding1[2]; | ||
73 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
74 | /* Band to scan */ | ||
75 | u8 band; | ||
76 | u8 use_ssid_list; | ||
77 | u8 scan_tag; | ||
78 | u8 padding2; | ||
79 | } __packed; | ||
80 | |||
81 | struct basic_scan_channel_params { | ||
82 | /* Duration in TU to wait for frames on a channel for active scan */ | ||
83 | __le32 min_duration; | ||
84 | __le32 max_duration; | ||
85 | __le32 bssid_lsb; | ||
86 | __le16 bssid_msb; | ||
87 | u8 early_termination; | ||
88 | u8 tx_power_att; | ||
89 | u8 channel; | ||
90 | /* FW internal use only! */ | ||
91 | u8 dfs_candidate; | ||
92 | u8 activity_detected; | ||
93 | u8 pad; | ||
94 | } __packed; | ||
95 | |||
96 | struct wl1271_cmd_scan { | ||
97 | struct wl1271_cmd_header header; | ||
98 | |||
99 | struct basic_scan_params params; | ||
100 | struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; | ||
101 | } __packed; | ||
102 | |||
103 | struct wl1271_cmd_trigger_scan_to { | ||
104 | struct wl1271_cmd_header header; | ||
105 | |||
106 | __le32 timeout; | ||
107 | } __packed; | ||
108 | |||
109 | #endif /* __WL1271_SCAN_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 5189b812f939..96d25fb50495 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -461,3 +461,4 @@ MODULE_LICENSE("GPL"); | |||
461 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 461 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
462 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 462 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
463 | MODULE_FIRMWARE(WL1271_FW_NAME); | 463 | MODULE_FIRMWARE(WL1271_FW_NAME); |
464 | MODULE_ALIAS("spi:wl1271"); | ||