diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 14:47:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 14:47:02 -0400 |
commit | 5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0 (patch) | |
tree | 7851ef1c93aa1aba7ef327ca4b75fd35e6d10f29 /drivers/net/wireless/wl12xx | |
parent | 02f36038c568111ad4fc433f6fa760ff5e38fab4 (diff) | |
parent | ec37a48d1d16c30b655ac5280209edf52a6775d4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits)
bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL.
vlan: Calling vlan_hwaccel_do_receive() is always valid.
tproxy: use the interface primary IP address as a default value for --on-ip
tproxy: added IPv6 support to the socket match
cxgb3: function namespace cleanup
tproxy: added IPv6 support to the TPROXY target
tproxy: added IPv6 socket lookup function to nf_tproxy_core
be2net: Changes to use only priority codes allowed by f/w
tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
tproxy: added tproxy sockopt interface in the IPV6 layer
tproxy: added udp6_lib_lookup function
tproxy: added const specifiers to udp lookup functions
tproxy: split off ipv6 defragmentation to a separate module
l2tp: small cleanup
nf_nat: restrict ICMP translation for embedded header
can: mcp251x: fix generation of error frames
can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set
can-raw: add msg_flags to distinguish local traffic
9p: client code cleanup
rds: make local functions/variables static
...
Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and
drivers/net/wireless/ath/ath9k/debug.c as per David
Diffstat (limited to 'drivers/net/wireless/wl12xx')
51 files changed, 941 insertions, 10882 deletions
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 2f98058be451..b447559f1db5 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -5,40 +5,6 @@ menuconfig WL12XX | |||
5 | This will enable TI wl12xx driver support. The drivers make | 5 | This will enable TI wl12xx driver support. The drivers make |
6 | use of the mac80211 stack. | 6 | use of the mac80211 stack. |
7 | 7 | ||
8 | config WL1251 | ||
9 | tristate "TI wl1251 support" | ||
10 | depends on WL12XX && GENERIC_HARDIRQS | ||
11 | select FW_LOADER | ||
12 | select CRC7 | ||
13 | ---help--- | ||
14 | This module adds support for wireless adapters based on | ||
15 | TI wl1251 chipset. | ||
16 | |||
17 | If you choose to build a module, it'll be called wl1251. Say | ||
18 | N if unsure. | ||
19 | |||
20 | config WL1251_SPI | ||
21 | tristate "TI wl1251 SPI support" | ||
22 | depends on WL1251 && SPI_MASTER | ||
23 | ---help--- | ||
24 | This module adds support for the SPI interface of adapters using | ||
25 | TI wl1251 chipset. Select this if your platform is using | ||
26 | the SPI bus. | ||
27 | |||
28 | If you choose to build a module, it'll be called wl1251_spi. | ||
29 | Say N if unsure. | ||
30 | |||
31 | config WL1251_SDIO | ||
32 | tristate "TI wl1251 SDIO support" | ||
33 | depends on WL1251 && MMC | ||
34 | ---help--- | ||
35 | This module adds support for the SDIO interface of adapters using | ||
36 | TI wl1251 chipset. Select this if your platform is using | ||
37 | the SDIO bus. | ||
38 | |||
39 | If you choose to build a module, it'll be called | ||
40 | wl1251_sdio. Say N if unsure. | ||
41 | |||
42 | config WL1271 | 8 | config WL1271 |
43 | tristate "TI wl1271 support" | 9 | tristate "TI wl1271 support" |
44 | depends on WL12XX && GENERIC_HARDIRQS | 10 | depends on WL12XX && GENERIC_HARDIRQS |
@@ -74,4 +40,7 @@ config WL1271_SDIO | |||
74 | If you choose to build a module, it'll be called | 40 | If you choose to build a module, it'll be called |
75 | wl1271_sdio. Say N if unsure. | 41 | wl1271_sdio. Say N if unsure. |
76 | 42 | ||
77 | 43 | config WL12XX_PLATFORM_DATA | |
44 | bool | ||
45 | depends on WL1271_SDIO != n | ||
46 | default y | ||
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 078b4398ac1f..3a807444b2af 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -1,12 +1,3 @@ | |||
1 | wl1251-objs = wl1251_main.o wl1251_event.o \ | ||
2 | wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \ | ||
3 | wl1251_acx.o wl1251_boot.o wl1251_init.o \ | ||
4 | wl1251_debugfs.o wl1251_io.o | ||
5 | |||
6 | obj-$(CONFIG_WL1251) += wl1251.o | ||
7 | obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o | ||
8 | obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | ||
9 | |||
10 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ | 1 | wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 2 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 3 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
@@ -16,3 +7,6 @@ wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | |||
16 | obj-$(CONFIG_WL1271) += wl1271.o | 7 | obj-$(CONFIG_WL1271) += wl1271.o |
17 | obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o | 8 | obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o |
18 | obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o | 9 | obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o |
10 | |||
11 | # small builtin driver bit | ||
12 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h deleted file mode 100644 index 6b942a28e6a5..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ /dev/null | |||
@@ -1,432 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008-2009 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_H__ | ||
26 | #define __WL1251_H__ | ||
27 | |||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/bitops.h> | ||
31 | #include <net/mac80211.h> | ||
32 | |||
33 | #define DRIVER_NAME "wl1251" | ||
34 | #define DRIVER_PREFIX DRIVER_NAME ": " | ||
35 | |||
36 | enum { | ||
37 | DEBUG_NONE = 0, | ||
38 | DEBUG_IRQ = BIT(0), | ||
39 | DEBUG_SPI = BIT(1), | ||
40 | DEBUG_BOOT = BIT(2), | ||
41 | DEBUG_MAILBOX = BIT(3), | ||
42 | DEBUG_NETLINK = BIT(4), | ||
43 | DEBUG_EVENT = BIT(5), | ||
44 | DEBUG_TX = BIT(6), | ||
45 | DEBUG_RX = BIT(7), | ||
46 | DEBUG_SCAN = BIT(8), | ||
47 | DEBUG_CRYPT = BIT(9), | ||
48 | DEBUG_PSM = BIT(10), | ||
49 | DEBUG_MAC80211 = BIT(11), | ||
50 | DEBUG_CMD = BIT(12), | ||
51 | DEBUG_ACX = BIT(13), | ||
52 | DEBUG_ALL = ~0, | ||
53 | }; | ||
54 | |||
55 | #define DEBUG_LEVEL (DEBUG_NONE) | ||
56 | |||
57 | #define DEBUG_DUMP_LIMIT 1024 | ||
58 | |||
59 | #define wl1251_error(fmt, arg...) \ | ||
60 | printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) | ||
61 | |||
62 | #define wl1251_warning(fmt, arg...) \ | ||
63 | printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) | ||
64 | |||
65 | #define wl1251_notice(fmt, arg...) \ | ||
66 | printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) | ||
67 | |||
68 | #define wl1251_info(fmt, arg...) \ | ||
69 | printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) | ||
70 | |||
71 | #define wl1251_debug(level, fmt, arg...) \ | ||
72 | do { \ | ||
73 | if (level & DEBUG_LEVEL) \ | ||
74 | printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ | ||
75 | } while (0) | ||
76 | |||
77 | #define wl1251_dump(level, prefix, buf, len) \ | ||
78 | do { \ | ||
79 | if (level & DEBUG_LEVEL) \ | ||
80 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | ||
81 | DUMP_PREFIX_OFFSET, 16, 1, \ | ||
82 | buf, \ | ||
83 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | ||
84 | 0); \ | ||
85 | } while (0) | ||
86 | |||
87 | #define wl1251_dump_ascii(level, prefix, buf, len) \ | ||
88 | do { \ | ||
89 | if (level & DEBUG_LEVEL) \ | ||
90 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | ||
91 | DUMP_PREFIX_OFFSET, 16, 1, \ | ||
92 | buf, \ | ||
93 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | ||
94 | true); \ | ||
95 | } while (0) | ||
96 | |||
97 | #define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ | ||
98 | CFG_BSSID_FILTER_EN) | ||
99 | |||
100 | #define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ | ||
101 | CFG_RX_MGMT_EN | \ | ||
102 | CFG_RX_DATA_EN | \ | ||
103 | CFG_RX_CTL_EN | \ | ||
104 | CFG_RX_BCN_EN | \ | ||
105 | CFG_RX_AUTH_EN | \ | ||
106 | CFG_RX_ASSOC_EN) | ||
107 | |||
108 | #define WL1251_BUSY_WORD_LEN 8 | ||
109 | |||
110 | struct boot_attr { | ||
111 | u32 radio_type; | ||
112 | u8 mac_clock; | ||
113 | u8 arm_clock; | ||
114 | int firmware_debug; | ||
115 | u32 minor; | ||
116 | u32 major; | ||
117 | u32 bugfix; | ||
118 | }; | ||
119 | |||
120 | enum wl1251_state { | ||
121 | WL1251_STATE_OFF, | ||
122 | WL1251_STATE_ON, | ||
123 | WL1251_STATE_PLT, | ||
124 | }; | ||
125 | |||
126 | enum wl1251_partition_type { | ||
127 | PART_DOWN, | ||
128 | PART_WORK, | ||
129 | PART_DRPW, | ||
130 | |||
131 | PART_TABLE_LEN | ||
132 | }; | ||
133 | |||
134 | struct wl1251_partition { | ||
135 | u32 size; | ||
136 | u32 start; | ||
137 | }; | ||
138 | |||
139 | struct wl1251_partition_set { | ||
140 | struct wl1251_partition mem; | ||
141 | struct wl1251_partition reg; | ||
142 | }; | ||
143 | |||
144 | struct wl1251; | ||
145 | |||
146 | struct wl1251_stats { | ||
147 | struct acx_statistics *fw_stats; | ||
148 | unsigned long fw_stats_update; | ||
149 | |||
150 | unsigned int retry_count; | ||
151 | unsigned int excessive_retries; | ||
152 | }; | ||
153 | |||
154 | struct wl1251_debugfs { | ||
155 | struct dentry *rootdir; | ||
156 | struct dentry *fw_statistics; | ||
157 | |||
158 | struct dentry *tx_internal_desc_overflow; | ||
159 | |||
160 | struct dentry *rx_out_of_mem; | ||
161 | struct dentry *rx_hdr_overflow; | ||
162 | struct dentry *rx_hw_stuck; | ||
163 | struct dentry *rx_dropped; | ||
164 | struct dentry *rx_fcs_err; | ||
165 | struct dentry *rx_xfr_hint_trig; | ||
166 | struct dentry *rx_path_reset; | ||
167 | struct dentry *rx_reset_counter; | ||
168 | |||
169 | struct dentry *dma_rx_requested; | ||
170 | struct dentry *dma_rx_errors; | ||
171 | struct dentry *dma_tx_requested; | ||
172 | struct dentry *dma_tx_errors; | ||
173 | |||
174 | struct dentry *isr_cmd_cmplt; | ||
175 | struct dentry *isr_fiqs; | ||
176 | struct dentry *isr_rx_headers; | ||
177 | struct dentry *isr_rx_mem_overflow; | ||
178 | struct dentry *isr_rx_rdys; | ||
179 | struct dentry *isr_irqs; | ||
180 | struct dentry *isr_tx_procs; | ||
181 | struct dentry *isr_decrypt_done; | ||
182 | struct dentry *isr_dma0_done; | ||
183 | struct dentry *isr_dma1_done; | ||
184 | struct dentry *isr_tx_exch_complete; | ||
185 | struct dentry *isr_commands; | ||
186 | struct dentry *isr_rx_procs; | ||
187 | struct dentry *isr_hw_pm_mode_changes; | ||
188 | struct dentry *isr_host_acknowledges; | ||
189 | struct dentry *isr_pci_pm; | ||
190 | struct dentry *isr_wakeups; | ||
191 | struct dentry *isr_low_rssi; | ||
192 | |||
193 | struct dentry *wep_addr_key_count; | ||
194 | struct dentry *wep_default_key_count; | ||
195 | /* skipping wep.reserved */ | ||
196 | struct dentry *wep_key_not_found; | ||
197 | struct dentry *wep_decrypt_fail; | ||
198 | struct dentry *wep_packets; | ||
199 | struct dentry *wep_interrupt; | ||
200 | |||
201 | struct dentry *pwr_ps_enter; | ||
202 | struct dentry *pwr_elp_enter; | ||
203 | struct dentry *pwr_missing_bcns; | ||
204 | struct dentry *pwr_wake_on_host; | ||
205 | struct dentry *pwr_wake_on_timer_exp; | ||
206 | struct dentry *pwr_tx_with_ps; | ||
207 | struct dentry *pwr_tx_without_ps; | ||
208 | struct dentry *pwr_rcvd_beacons; | ||
209 | struct dentry *pwr_power_save_off; | ||
210 | struct dentry *pwr_enable_ps; | ||
211 | struct dentry *pwr_disable_ps; | ||
212 | struct dentry *pwr_fix_tsf_ps; | ||
213 | /* skipping cont_miss_bcns_spread for now */ | ||
214 | struct dentry *pwr_rcvd_awake_beacons; | ||
215 | |||
216 | struct dentry *mic_rx_pkts; | ||
217 | struct dentry *mic_calc_failure; | ||
218 | |||
219 | struct dentry *aes_encrypt_fail; | ||
220 | struct dentry *aes_decrypt_fail; | ||
221 | struct dentry *aes_encrypt_packets; | ||
222 | struct dentry *aes_decrypt_packets; | ||
223 | struct dentry *aes_encrypt_interrupt; | ||
224 | struct dentry *aes_decrypt_interrupt; | ||
225 | |||
226 | struct dentry *event_heart_beat; | ||
227 | struct dentry *event_calibration; | ||
228 | struct dentry *event_rx_mismatch; | ||
229 | struct dentry *event_rx_mem_empty; | ||
230 | struct dentry *event_rx_pool; | ||
231 | struct dentry *event_oom_late; | ||
232 | struct dentry *event_phy_transmit_error; | ||
233 | struct dentry *event_tx_stuck; | ||
234 | |||
235 | struct dentry *ps_pspoll_timeouts; | ||
236 | struct dentry *ps_upsd_timeouts; | ||
237 | struct dentry *ps_upsd_max_sptime; | ||
238 | struct dentry *ps_upsd_max_apturn; | ||
239 | struct dentry *ps_pspoll_max_apturn; | ||
240 | struct dentry *ps_pspoll_utilization; | ||
241 | struct dentry *ps_upsd_utilization; | ||
242 | |||
243 | struct dentry *rxpipe_rx_prep_beacon_drop; | ||
244 | struct dentry *rxpipe_descr_host_int_trig_rx_data; | ||
245 | struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; | ||
246 | struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; | ||
247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; | ||
248 | |||
249 | struct dentry *tx_queue_len; | ||
250 | struct dentry *tx_queue_status; | ||
251 | |||
252 | struct dentry *retry_count; | ||
253 | struct dentry *excessive_retries; | ||
254 | }; | ||
255 | |||
256 | struct wl1251_if_operations { | ||
257 | void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); | ||
258 | void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); | ||
259 | void (*read_elp)(struct wl1251 *wl, int addr, u32 *val); | ||
260 | void (*write_elp)(struct wl1251 *wl, int addr, u32 val); | ||
261 | void (*reset)(struct wl1251 *wl); | ||
262 | void (*enable_irq)(struct wl1251 *wl); | ||
263 | void (*disable_irq)(struct wl1251 *wl); | ||
264 | }; | ||
265 | |||
266 | struct wl1251 { | ||
267 | struct ieee80211_hw *hw; | ||
268 | bool mac80211_registered; | ||
269 | |||
270 | void *if_priv; | ||
271 | const struct wl1251_if_operations *if_ops; | ||
272 | |||
273 | void (*set_power)(bool enable); | ||
274 | int irq; | ||
275 | bool use_eeprom; | ||
276 | |||
277 | enum wl1251_state state; | ||
278 | struct mutex mutex; | ||
279 | |||
280 | int physical_mem_addr; | ||
281 | int physical_reg_addr; | ||
282 | int virtual_mem_addr; | ||
283 | int virtual_reg_addr; | ||
284 | |||
285 | int cmd_box_addr; | ||
286 | int event_box_addr; | ||
287 | struct boot_attr boot_attr; | ||
288 | |||
289 | u8 *fw; | ||
290 | size_t fw_len; | ||
291 | u8 *nvs; | ||
292 | size_t nvs_len; | ||
293 | |||
294 | u8 bssid[ETH_ALEN]; | ||
295 | u8 mac_addr[ETH_ALEN]; | ||
296 | u8 bss_type; | ||
297 | u8 listen_int; | ||
298 | int channel; | ||
299 | |||
300 | void *target_mem_map; | ||
301 | struct acx_data_path_params_resp *data_path; | ||
302 | |||
303 | /* Number of TX packets transferred to the FW, modulo 16 */ | ||
304 | u32 data_in_count; | ||
305 | |||
306 | /* Frames scheduled for transmission, not handled yet */ | ||
307 | struct sk_buff_head tx_queue; | ||
308 | bool tx_queue_stopped; | ||
309 | |||
310 | struct work_struct tx_work; | ||
311 | struct work_struct filter_work; | ||
312 | |||
313 | /* Pending TX frames */ | ||
314 | struct sk_buff *tx_frames[16]; | ||
315 | |||
316 | /* | ||
317 | * Index pointing to the next TX complete entry | ||
318 | * in the cyclic XT complete array we get from | ||
319 | * the FW. | ||
320 | */ | ||
321 | u32 next_tx_complete; | ||
322 | |||
323 | /* FW Rx counter */ | ||
324 | u32 rx_counter; | ||
325 | |||
326 | /* Rx frames handled */ | ||
327 | u32 rx_handled; | ||
328 | |||
329 | /* Current double buffer */ | ||
330 | u32 rx_current_buffer; | ||
331 | u32 rx_last_id; | ||
332 | |||
333 | /* The target interrupt mask */ | ||
334 | u32 intr_mask; | ||
335 | struct work_struct irq_work; | ||
336 | |||
337 | /* The mbox event mask */ | ||
338 | u32 event_mask; | ||
339 | |||
340 | /* Mailbox pointers */ | ||
341 | u32 mbox_ptr[2]; | ||
342 | |||
343 | /* Are we currently scanning */ | ||
344 | bool scanning; | ||
345 | |||
346 | /* Default key (for WEP) */ | ||
347 | u32 default_key; | ||
348 | |||
349 | unsigned int tx_mgmt_frm_rate; | ||
350 | unsigned int tx_mgmt_frm_mod; | ||
351 | |||
352 | unsigned int rx_config; | ||
353 | unsigned int rx_filter; | ||
354 | |||
355 | /* is firmware in elp mode */ | ||
356 | bool elp; | ||
357 | |||
358 | struct delayed_work elp_work; | ||
359 | |||
360 | /* we can be in psm, but not in elp, we have to differentiate */ | ||
361 | bool psm; | ||
362 | |||
363 | /* PSM mode requested */ | ||
364 | bool psm_requested; | ||
365 | |||
366 | u16 beacon_int; | ||
367 | u8 dtim_period; | ||
368 | |||
369 | /* in dBm */ | ||
370 | int power_level; | ||
371 | |||
372 | struct wl1251_stats stats; | ||
373 | struct wl1251_debugfs debugfs; | ||
374 | |||
375 | u32 buffer_32; | ||
376 | u32 buffer_cmd; | ||
377 | u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; | ||
378 | struct wl1251_rx_descriptor *rx_descriptor; | ||
379 | |||
380 | struct ieee80211_vif *vif; | ||
381 | |||
382 | u32 chip_id; | ||
383 | char fw_ver[21]; | ||
384 | |||
385 | /* Most recently reported noise in dBm */ | ||
386 | s8 noise; | ||
387 | }; | ||
388 | |||
389 | int wl1251_plt_start(struct wl1251 *wl); | ||
390 | int wl1251_plt_stop(struct wl1251 *wl); | ||
391 | |||
392 | struct ieee80211_hw *wl1251_alloc_hw(void); | ||
393 | int wl1251_free_hw(struct wl1251 *wl); | ||
394 | int wl1251_init_ieee80211(struct wl1251 *wl); | ||
395 | void wl1251_enable_interrupts(struct wl1251 *wl); | ||
396 | void wl1251_disable_interrupts(struct wl1251 *wl); | ||
397 | |||
398 | #define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ | ||
399 | #define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS | ||
400 | #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ | ||
401 | |||
402 | #define WL1251_DEFAULT_POWER_LEVEL 20 | ||
403 | |||
404 | #define WL1251_TX_QUEUE_MAX_LENGTH 20 | ||
405 | |||
406 | #define WL1251_DEFAULT_BEACON_INT 100 | ||
407 | #define WL1251_DEFAULT_DTIM_PERIOD 1 | ||
408 | |||
409 | #define WL1251_DEFAULT_CHANNEL 0 | ||
410 | |||
411 | #define CHIP_ID_1251_PG10 (0x7010101) | ||
412 | #define CHIP_ID_1251_PG11 (0x7020101) | ||
413 | #define CHIP_ID_1251_PG12 (0x7030101) | ||
414 | #define CHIP_ID_1271_PG10 (0x4030101) | ||
415 | #define CHIP_ID_1271_PG20 (0x4030111) | ||
416 | |||
417 | #define WL1251_FW_NAME "wl1251-fw.bin" | ||
418 | #define WL1251_NVS_NAME "wl1251-nvs.bin" | ||
419 | |||
420 | #define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */ | ||
421 | |||
422 | #define WL1251_PART_DOWN_MEM_START 0x0 | ||
423 | #define WL1251_PART_DOWN_MEM_SIZE 0x16800 | ||
424 | #define WL1251_PART_DOWN_REG_START REGISTERS_BASE | ||
425 | #define WL1251_PART_DOWN_REG_SIZE REGISTERS_DOWN_SIZE | ||
426 | |||
427 | #define WL1251_PART_WORK_MEM_START 0x28000 | ||
428 | #define WL1251_PART_WORK_MEM_SIZE 0x14000 | ||
429 | #define WL1251_PART_WORK_REG_START REGISTERS_BASE | ||
430 | #define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE | ||
431 | |||
432 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c deleted file mode 100644 index 91891f928070..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ /dev/null | |||
@@ -1,1048 +0,0 @@ | |||
1 | #include "wl1251_acx.h" | ||
2 | |||
3 | #include <linux/module.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/crc7.h> | ||
6 | |||
7 | #include "wl1251.h" | ||
8 | #include "wl1251_reg.h" | ||
9 | #include "wl1251_cmd.h" | ||
10 | #include "wl1251_ps.h" | ||
11 | |||
12 | int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, | ||
13 | u8 mgt_rate, u8 mgt_mod) | ||
14 | { | ||
15 | struct acx_fw_gen_frame_rates *rates; | ||
16 | int ret; | ||
17 | |||
18 | wl1251_debug(DEBUG_ACX, "acx frame rates"); | ||
19 | |||
20 | rates = kzalloc(sizeof(*rates), GFP_KERNEL); | ||
21 | if (!rates) { | ||
22 | ret = -ENOMEM; | ||
23 | goto out; | ||
24 | } | ||
25 | |||
26 | rates->tx_ctrl_frame_rate = ctrl_rate; | ||
27 | rates->tx_ctrl_frame_mod = ctrl_mod; | ||
28 | rates->tx_mgt_frame_rate = mgt_rate; | ||
29 | rates->tx_mgt_frame_mod = mgt_mod; | ||
30 | |||
31 | ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES, | ||
32 | rates, sizeof(*rates)); | ||
33 | if (ret < 0) { | ||
34 | wl1251_error("Failed to set FW rates and modulation"); | ||
35 | goto out; | ||
36 | } | ||
37 | |||
38 | out: | ||
39 | kfree(rates); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | |||
44 | int wl1251_acx_station_id(struct wl1251 *wl) | ||
45 | { | ||
46 | struct acx_dot11_station_id *mac; | ||
47 | int ret, i; | ||
48 | |||
49 | wl1251_debug(DEBUG_ACX, "acx dot11_station_id"); | ||
50 | |||
51 | mac = kzalloc(sizeof(*mac), GFP_KERNEL); | ||
52 | if (!mac) { | ||
53 | ret = -ENOMEM; | ||
54 | goto out; | ||
55 | } | ||
56 | |||
57 | for (i = 0; i < ETH_ALEN; i++) | ||
58 | mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; | ||
59 | |||
60 | ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac)); | ||
61 | if (ret < 0) | ||
62 | goto out; | ||
63 | |||
64 | out: | ||
65 | kfree(mac); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) | ||
70 | { | ||
71 | struct acx_dot11_default_key *default_key; | ||
72 | int ret; | ||
73 | |||
74 | wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); | ||
75 | |||
76 | default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); | ||
77 | if (!default_key) { | ||
78 | ret = -ENOMEM; | ||
79 | goto out; | ||
80 | } | ||
81 | |||
82 | default_key->id = key_id; | ||
83 | |||
84 | ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, | ||
85 | default_key, sizeof(*default_key)); | ||
86 | if (ret < 0) { | ||
87 | wl1251_error("Couldn't set default key"); | ||
88 | goto out; | ||
89 | } | ||
90 | |||
91 | wl->default_key = key_id; | ||
92 | |||
93 | out: | ||
94 | kfree(default_key); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, | ||
99 | u8 listen_interval) | ||
100 | { | ||
101 | struct acx_wake_up_condition *wake_up; | ||
102 | int ret; | ||
103 | |||
104 | wl1251_debug(DEBUG_ACX, "acx wake up conditions"); | ||
105 | |||
106 | wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); | ||
107 | if (!wake_up) { | ||
108 | ret = -ENOMEM; | ||
109 | goto out; | ||
110 | } | ||
111 | |||
112 | wake_up->wake_up_event = wake_up_event; | ||
113 | wake_up->listen_interval = listen_interval; | ||
114 | |||
115 | ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, | ||
116 | wake_up, sizeof(*wake_up)); | ||
117 | if (ret < 0) { | ||
118 | wl1251_warning("could not set wake up conditions: %d", ret); | ||
119 | goto out; | ||
120 | } | ||
121 | |||
122 | out: | ||
123 | kfree(wake_up); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth) | ||
128 | { | ||
129 | struct acx_sleep_auth *auth; | ||
130 | int ret; | ||
131 | |||
132 | wl1251_debug(DEBUG_ACX, "acx sleep auth"); | ||
133 | |||
134 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); | ||
135 | if (!auth) { | ||
136 | ret = -ENOMEM; | ||
137 | goto out; | ||
138 | } | ||
139 | |||
140 | auth->sleep_auth = sleep_auth; | ||
141 | |||
142 | ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); | ||
143 | if (ret < 0) | ||
144 | return ret; | ||
145 | |||
146 | out: | ||
147 | kfree(auth); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len) | ||
152 | { | ||
153 | struct acx_revision *rev; | ||
154 | int ret; | ||
155 | |||
156 | wl1251_debug(DEBUG_ACX, "acx fw rev"); | ||
157 | |||
158 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); | ||
159 | if (!rev) { | ||
160 | ret = -ENOMEM; | ||
161 | goto out; | ||
162 | } | ||
163 | |||
164 | ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); | ||
165 | if (ret < 0) { | ||
166 | wl1251_warning("ACX_FW_REV interrogate failed"); | ||
167 | goto out; | ||
168 | } | ||
169 | |||
170 | /* be careful with the buffer sizes */ | ||
171 | strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); | ||
172 | |||
173 | /* | ||
174 | * if the firmware version string is exactly | ||
175 | * sizeof(rev->fw_version) long or fw_len is less than | ||
176 | * sizeof(rev->fw_version) it won't be null terminated | ||
177 | */ | ||
178 | buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; | ||
179 | |||
180 | out: | ||
181 | kfree(rev); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | int wl1251_acx_tx_power(struct wl1251 *wl, int power) | ||
186 | { | ||
187 | struct acx_current_tx_power *acx; | ||
188 | int ret; | ||
189 | |||
190 | wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); | ||
191 | |||
192 | if (power < 0 || power > 25) | ||
193 | return -EINVAL; | ||
194 | |||
195 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
196 | if (!acx) { | ||
197 | ret = -ENOMEM; | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | acx->current_tx_power = power * 10; | ||
202 | |||
203 | ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | ||
204 | if (ret < 0) { | ||
205 | wl1251_warning("configure of tx power failed: %d", ret); | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | out: | ||
210 | kfree(acx); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | int wl1251_acx_feature_cfg(struct wl1251 *wl) | ||
215 | { | ||
216 | struct acx_feature_config *feature; | ||
217 | int ret; | ||
218 | |||
219 | wl1251_debug(DEBUG_ACX, "acx feature cfg"); | ||
220 | |||
221 | feature = kzalloc(sizeof(*feature), GFP_KERNEL); | ||
222 | if (!feature) { | ||
223 | ret = -ENOMEM; | ||
224 | goto out; | ||
225 | } | ||
226 | |||
227 | /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ | ||
228 | feature->data_flow_options = 0; | ||
229 | feature->options = 0; | ||
230 | |||
231 | ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, | ||
232 | feature, sizeof(*feature)); | ||
233 | if (ret < 0) { | ||
234 | wl1251_error("Couldn't set HW encryption"); | ||
235 | goto out; | ||
236 | } | ||
237 | |||
238 | out: | ||
239 | kfree(feature); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map, | ||
244 | size_t len) | ||
245 | { | ||
246 | int ret; | ||
247 | |||
248 | wl1251_debug(DEBUG_ACX, "acx mem map"); | ||
249 | |||
250 | ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); | ||
251 | if (ret < 0) | ||
252 | return ret; | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | int wl1251_acx_data_path_params(struct wl1251 *wl, | ||
258 | struct acx_data_path_params_resp *resp) | ||
259 | { | ||
260 | struct acx_data_path_params *params; | ||
261 | int ret; | ||
262 | |||
263 | wl1251_debug(DEBUG_ACX, "acx data path params"); | ||
264 | |||
265 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
266 | if (!params) { | ||
267 | ret = -ENOMEM; | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; | ||
272 | params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; | ||
273 | |||
274 | params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; | ||
275 | params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; | ||
276 | |||
277 | params->tx_complete_threshold = 1; | ||
278 | |||
279 | params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; | ||
280 | |||
281 | params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; | ||
282 | |||
283 | ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS, | ||
284 | params, sizeof(*params)); | ||
285 | if (ret < 0) | ||
286 | goto out; | ||
287 | |||
288 | /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */ | ||
289 | ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, | ||
290 | resp, sizeof(*resp)); | ||
291 | |||
292 | if (ret < 0) { | ||
293 | wl1251_warning("failed to read data path parameters: %d", ret); | ||
294 | goto out; | ||
295 | } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) { | ||
296 | wl1251_warning("data path parameter acx status failed"); | ||
297 | ret = -EIO; | ||
298 | goto out; | ||
299 | } | ||
300 | |||
301 | out: | ||
302 | kfree(params); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time) | ||
307 | { | ||
308 | struct acx_rx_msdu_lifetime *acx; | ||
309 | int ret; | ||
310 | |||
311 | wl1251_debug(DEBUG_ACX, "acx rx msdu life time"); | ||
312 | |||
313 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
314 | if (!acx) { | ||
315 | ret = -ENOMEM; | ||
316 | goto out; | ||
317 | } | ||
318 | |||
319 | acx->lifetime = life_time; | ||
320 | ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, | ||
321 | acx, sizeof(*acx)); | ||
322 | if (ret < 0) { | ||
323 | wl1251_warning("failed to set rx msdu life time: %d", ret); | ||
324 | goto out; | ||
325 | } | ||
326 | |||
327 | out: | ||
328 | kfree(acx); | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter) | ||
333 | { | ||
334 | struct acx_rx_config *rx_config; | ||
335 | int ret; | ||
336 | |||
337 | wl1251_debug(DEBUG_ACX, "acx rx config"); | ||
338 | |||
339 | rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); | ||
340 | if (!rx_config) { | ||
341 | ret = -ENOMEM; | ||
342 | goto out; | ||
343 | } | ||
344 | |||
345 | rx_config->config_options = config; | ||
346 | rx_config->filter_options = filter; | ||
347 | |||
348 | ret = wl1251_cmd_configure(wl, ACX_RX_CFG, | ||
349 | rx_config, sizeof(*rx_config)); | ||
350 | if (ret < 0) { | ||
351 | wl1251_warning("failed to set rx config: %d", ret); | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | out: | ||
356 | kfree(rx_config); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | int wl1251_acx_pd_threshold(struct wl1251 *wl) | ||
361 | { | ||
362 | struct acx_packet_detection *pd; | ||
363 | int ret; | ||
364 | |||
365 | wl1251_debug(DEBUG_ACX, "acx data pd threshold"); | ||
366 | |||
367 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
368 | if (!pd) { | ||
369 | ret = -ENOMEM; | ||
370 | goto out; | ||
371 | } | ||
372 | |||
373 | /* FIXME: threshold value not set */ | ||
374 | |||
375 | ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); | ||
376 | if (ret < 0) { | ||
377 | wl1251_warning("failed to set pd threshold: %d", ret); | ||
378 | goto out; | ||
379 | } | ||
380 | |||
381 | out: | ||
382 | kfree(pd); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) | ||
387 | { | ||
388 | struct acx_slot *slot; | ||
389 | int ret; | ||
390 | |||
391 | wl1251_debug(DEBUG_ACX, "acx slot"); | ||
392 | |||
393 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
394 | if (!slot) { | ||
395 | ret = -ENOMEM; | ||
396 | goto out; | ||
397 | } | ||
398 | |||
399 | slot->wone_index = STATION_WONE_INDEX; | ||
400 | slot->slot_time = slot_time; | ||
401 | |||
402 | ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot)); | ||
403 | if (ret < 0) { | ||
404 | wl1251_warning("failed to set slot time: %d", ret); | ||
405 | goto out; | ||
406 | } | ||
407 | |||
408 | out: | ||
409 | kfree(slot); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | int wl1251_acx_group_address_tbl(struct wl1251 *wl) | ||
414 | { | ||
415 | struct acx_dot11_grp_addr_tbl *acx; | ||
416 | int ret; | ||
417 | |||
418 | wl1251_debug(DEBUG_ACX, "acx group address tbl"); | ||
419 | |||
420 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
421 | if (!acx) { | ||
422 | ret = -ENOMEM; | ||
423 | goto out; | ||
424 | } | ||
425 | |||
426 | /* MAC filtering */ | ||
427 | acx->enabled = 0; | ||
428 | acx->num_groups = 0; | ||
429 | memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); | ||
430 | |||
431 | ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, | ||
432 | acx, sizeof(*acx)); | ||
433 | if (ret < 0) { | ||
434 | wl1251_warning("failed to set group addr table: %d", ret); | ||
435 | goto out; | ||
436 | } | ||
437 | |||
438 | out: | ||
439 | kfree(acx); | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | int wl1251_acx_service_period_timeout(struct wl1251 *wl) | ||
444 | { | ||
445 | struct acx_rx_timeout *rx_timeout; | ||
446 | int ret; | ||
447 | |||
448 | rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); | ||
449 | if (!rx_timeout) { | ||
450 | ret = -ENOMEM; | ||
451 | goto out; | ||
452 | } | ||
453 | |||
454 | wl1251_debug(DEBUG_ACX, "acx service period timeout"); | ||
455 | |||
456 | rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; | ||
457 | rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; | ||
458 | |||
459 | ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, | ||
460 | rx_timeout, sizeof(*rx_timeout)); | ||
461 | if (ret < 0) { | ||
462 | wl1251_warning("failed to set service period timeout: %d", | ||
463 | ret); | ||
464 | goto out; | ||
465 | } | ||
466 | |||
467 | out: | ||
468 | kfree(rx_timeout); | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold) | ||
473 | { | ||
474 | struct acx_rts_threshold *rts; | ||
475 | int ret; | ||
476 | |||
477 | wl1251_debug(DEBUG_ACX, "acx rts threshold"); | ||
478 | |||
479 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); | ||
480 | if (!rts) { | ||
481 | ret = -ENOMEM; | ||
482 | goto out; | ||
483 | } | ||
484 | |||
485 | rts->threshold = rts_threshold; | ||
486 | |||
487 | ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); | ||
488 | if (ret < 0) { | ||
489 | wl1251_warning("failed to set rts threshold: %d", ret); | ||
490 | goto out; | ||
491 | } | ||
492 | |||
493 | out: | ||
494 | kfree(rts); | ||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter) | ||
499 | { | ||
500 | struct acx_beacon_filter_option *beacon_filter; | ||
501 | int ret; | ||
502 | |||
503 | wl1251_debug(DEBUG_ACX, "acx beacon filter opt"); | ||
504 | |||
505 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); | ||
506 | if (!beacon_filter) { | ||
507 | ret = -ENOMEM; | ||
508 | goto out; | ||
509 | } | ||
510 | |||
511 | beacon_filter->enable = enable_filter; | ||
512 | beacon_filter->max_num_beacons = 0; | ||
513 | |||
514 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT, | ||
515 | beacon_filter, sizeof(*beacon_filter)); | ||
516 | if (ret < 0) { | ||
517 | wl1251_warning("failed to set beacon filter opt: %d", ret); | ||
518 | goto out; | ||
519 | } | ||
520 | |||
521 | out: | ||
522 | kfree(beacon_filter); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl) | ||
527 | { | ||
528 | struct acx_beacon_filter_ie_table *ie_table; | ||
529 | int idx = 0; | ||
530 | int ret; | ||
531 | |||
532 | wl1251_debug(DEBUG_ACX, "acx beacon filter table"); | ||
533 | |||
534 | ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); | ||
535 | if (!ie_table) { | ||
536 | ret = -ENOMEM; | ||
537 | goto out; | ||
538 | } | ||
539 | |||
540 | /* configure default beacon pass-through rules */ | ||
541 | ie_table->num_ie = 1; | ||
542 | ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN; | ||
543 | ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE; | ||
544 | |||
545 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, | ||
546 | ie_table, sizeof(*ie_table)); | ||
547 | if (ret < 0) { | ||
548 | wl1251_warning("failed to set beacon filter table: %d", ret); | ||
549 | goto out; | ||
550 | } | ||
551 | |||
552 | out: | ||
553 | kfree(ie_table); | ||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | int wl1251_acx_conn_monit_params(struct wl1251 *wl) | ||
558 | { | ||
559 | struct acx_conn_monit_params *acx; | ||
560 | int ret; | ||
561 | |||
562 | wl1251_debug(DEBUG_ACX, "acx connection monitor parameters"); | ||
563 | |||
564 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
565 | if (!acx) { | ||
566 | ret = -ENOMEM; | ||
567 | goto out; | ||
568 | } | ||
569 | |||
570 | acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD; | ||
571 | acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT; | ||
572 | |||
573 | ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | ||
574 | acx, sizeof(*acx)); | ||
575 | if (ret < 0) { | ||
576 | wl1251_warning("failed to set connection monitor " | ||
577 | "parameters: %d", ret); | ||
578 | goto out; | ||
579 | } | ||
580 | |||
581 | out: | ||
582 | kfree(acx); | ||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | int wl1251_acx_sg_enable(struct wl1251 *wl) | ||
587 | { | ||
588 | struct acx_bt_wlan_coex *pta; | ||
589 | int ret; | ||
590 | |||
591 | wl1251_debug(DEBUG_ACX, "acx sg enable"); | ||
592 | |||
593 | pta = kzalloc(sizeof(*pta), GFP_KERNEL); | ||
594 | if (!pta) { | ||
595 | ret = -ENOMEM; | ||
596 | goto out; | ||
597 | } | ||
598 | |||
599 | pta->enable = SG_ENABLE; | ||
600 | |||
601 | ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); | ||
602 | if (ret < 0) { | ||
603 | wl1251_warning("failed to set softgemini enable: %d", ret); | ||
604 | goto out; | ||
605 | } | ||
606 | |||
607 | out: | ||
608 | kfree(pta); | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | int wl1251_acx_sg_cfg(struct wl1251 *wl) | ||
613 | { | ||
614 | struct acx_bt_wlan_coex_param *param; | ||
615 | int ret; | ||
616 | |||
617 | wl1251_debug(DEBUG_ACX, "acx sg cfg"); | ||
618 | |||
619 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
620 | if (!param) { | ||
621 | ret = -ENOMEM; | ||
622 | goto out; | ||
623 | } | ||
624 | |||
625 | /* BT-WLAN coext parameters */ | ||
626 | param->min_rate = RATE_INDEX_24MBPS; | ||
627 | param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; | ||
628 | param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; | ||
629 | param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; | ||
630 | param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; | ||
631 | param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; | ||
632 | param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; | ||
633 | param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; | ||
634 | param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; | ||
635 | param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; | ||
636 | param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; | ||
637 | param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; | ||
638 | param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; | ||
639 | param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; | ||
640 | param->antenna_type = PTA_ANTENNA_TYPE_DEF; | ||
641 | param->signal_type = PTA_SIGNALING_TYPE_DEF; | ||
642 | param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; | ||
643 | param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; | ||
644 | param->max_cts = PTA_MAX_NUM_CTS_DEF; | ||
645 | param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; | ||
646 | param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; | ||
647 | param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; | ||
648 | param->wlan_elp_hp = PTA_ELP_HP_DEF; | ||
649 | param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; | ||
650 | param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; | ||
651 | param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; | ||
652 | param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; | ||
653 | param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; | ||
654 | |||
655 | ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | ||
656 | if (ret < 0) { | ||
657 | wl1251_warning("failed to set sg config: %d", ret); | ||
658 | goto out; | ||
659 | } | ||
660 | |||
661 | out: | ||
662 | kfree(param); | ||
663 | return ret; | ||
664 | } | ||
665 | |||
666 | int wl1251_acx_cca_threshold(struct wl1251 *wl) | ||
667 | { | ||
668 | struct acx_energy_detection *detection; | ||
669 | int ret; | ||
670 | |||
671 | wl1251_debug(DEBUG_ACX, "acx cca threshold"); | ||
672 | |||
673 | detection = kzalloc(sizeof(*detection), GFP_KERNEL); | ||
674 | if (!detection) { | ||
675 | ret = -ENOMEM; | ||
676 | goto out; | ||
677 | } | ||
678 | |||
679 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; | ||
680 | detection->tx_energy_detection = 0; | ||
681 | |||
682 | ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD, | ||
683 | detection, sizeof(*detection)); | ||
684 | if (ret < 0) { | ||
685 | wl1251_warning("failed to set cca threshold: %d", ret); | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | out: | ||
690 | kfree(detection); | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | int wl1251_acx_bcn_dtim_options(struct wl1251 *wl) | ||
695 | { | ||
696 | struct acx_beacon_broadcast *bb; | ||
697 | int ret; | ||
698 | |||
699 | wl1251_debug(DEBUG_ACX, "acx bcn dtim options"); | ||
700 | |||
701 | bb = kzalloc(sizeof(*bb), GFP_KERNEL); | ||
702 | if (!bb) { | ||
703 | ret = -ENOMEM; | ||
704 | goto out; | ||
705 | } | ||
706 | |||
707 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; | ||
708 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; | ||
709 | bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; | ||
710 | bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; | ||
711 | |||
712 | ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); | ||
713 | if (ret < 0) { | ||
714 | wl1251_warning("failed to set rx config: %d", ret); | ||
715 | goto out; | ||
716 | } | ||
717 | |||
718 | out: | ||
719 | kfree(bb); | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | int wl1251_acx_aid(struct wl1251 *wl, u16 aid) | ||
724 | { | ||
725 | struct acx_aid *acx_aid; | ||
726 | int ret; | ||
727 | |||
728 | wl1251_debug(DEBUG_ACX, "acx aid"); | ||
729 | |||
730 | acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); | ||
731 | if (!acx_aid) { | ||
732 | ret = -ENOMEM; | ||
733 | goto out; | ||
734 | } | ||
735 | |||
736 | acx_aid->aid = aid; | ||
737 | |||
738 | ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); | ||
739 | if (ret < 0) { | ||
740 | wl1251_warning("failed to set aid: %d", ret); | ||
741 | goto out; | ||
742 | } | ||
743 | |||
744 | out: | ||
745 | kfree(acx_aid); | ||
746 | return ret; | ||
747 | } | ||
748 | |||
749 | int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask) | ||
750 | { | ||
751 | struct acx_event_mask *mask; | ||
752 | int ret; | ||
753 | |||
754 | wl1251_debug(DEBUG_ACX, "acx event mbox mask"); | ||
755 | |||
756 | mask = kzalloc(sizeof(*mask), GFP_KERNEL); | ||
757 | if (!mask) { | ||
758 | ret = -ENOMEM; | ||
759 | goto out; | ||
760 | } | ||
761 | |||
762 | /* high event mask is unused */ | ||
763 | mask->high_event_mask = 0xffffffff; | ||
764 | |||
765 | mask->event_mask = event_mask; | ||
766 | |||
767 | ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK, | ||
768 | mask, sizeof(*mask)); | ||
769 | if (ret < 0) { | ||
770 | wl1251_warning("failed to set acx_event_mbox_mask: %d", ret); | ||
771 | goto out; | ||
772 | } | ||
773 | |||
774 | out: | ||
775 | kfree(mask); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) | ||
780 | { | ||
781 | struct acx_preamble *acx; | ||
782 | int ret; | ||
783 | |||
784 | wl1251_debug(DEBUG_ACX, "acx_set_preamble"); | ||
785 | |||
786 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
787 | if (!acx) { | ||
788 | ret = -ENOMEM; | ||
789 | goto out; | ||
790 | } | ||
791 | |||
792 | acx->preamble = preamble; | ||
793 | |||
794 | ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); | ||
795 | if (ret < 0) { | ||
796 | wl1251_warning("Setting of preamble failed: %d", ret); | ||
797 | goto out; | ||
798 | } | ||
799 | |||
800 | out: | ||
801 | kfree(acx); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | int wl1251_acx_cts_protect(struct wl1251 *wl, | ||
806 | enum acx_ctsprotect_type ctsprotect) | ||
807 | { | ||
808 | struct acx_ctsprotect *acx; | ||
809 | int ret; | ||
810 | |||
811 | wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect"); | ||
812 | |||
813 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
814 | if (!acx) { | ||
815 | ret = -ENOMEM; | ||
816 | goto out; | ||
817 | } | ||
818 | |||
819 | acx->ctsprotect = ctsprotect; | ||
820 | |||
821 | ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); | ||
822 | if (ret < 0) { | ||
823 | wl1251_warning("Setting of ctsprotect failed: %d", ret); | ||
824 | goto out; | ||
825 | } | ||
826 | |||
827 | out: | ||
828 | kfree(acx); | ||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime) | ||
833 | { | ||
834 | struct acx_tsf_info *tsf_info; | ||
835 | int ret; | ||
836 | |||
837 | tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); | ||
838 | if (!tsf_info) { | ||
839 | ret = -ENOMEM; | ||
840 | goto out; | ||
841 | } | ||
842 | |||
843 | ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, | ||
844 | tsf_info, sizeof(*tsf_info)); | ||
845 | if (ret < 0) { | ||
846 | wl1251_warning("ACX_FW_REV interrogate failed"); | ||
847 | goto out; | ||
848 | } | ||
849 | |||
850 | *mactime = tsf_info->current_tsf_lsb | | ||
851 | (tsf_info->current_tsf_msb << 31); | ||
852 | |||
853 | out: | ||
854 | kfree(tsf_info); | ||
855 | return ret; | ||
856 | } | ||
857 | |||
858 | int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats) | ||
859 | { | ||
860 | int ret; | ||
861 | |||
862 | wl1251_debug(DEBUG_ACX, "acx statistics"); | ||
863 | |||
864 | ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats, | ||
865 | sizeof(*stats)); | ||
866 | if (ret < 0) { | ||
867 | wl1251_warning("acx statistics failed: %d", ret); | ||
868 | return -ENOMEM; | ||
869 | } | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | int wl1251_acx_rate_policies(struct wl1251 *wl) | ||
875 | { | ||
876 | struct acx_rate_policy *acx; | ||
877 | int ret = 0; | ||
878 | |||
879 | wl1251_debug(DEBUG_ACX, "acx rate policies"); | ||
880 | |||
881 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
882 | |||
883 | if (!acx) { | ||
884 | ret = -ENOMEM; | ||
885 | goto out; | ||
886 | } | ||
887 | |||
888 | /* configure one default (one-size-fits-all) rate class */ | ||
889 | acx->rate_class_cnt = 1; | ||
890 | acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED; | ||
891 | acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; | ||
892 | acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; | ||
893 | acx->rate_class[0].aflags = 0; | ||
894 | |||
895 | ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | ||
896 | if (ret < 0) { | ||
897 | wl1251_warning("Setting of rate policies failed: %d", ret); | ||
898 | goto out; | ||
899 | } | ||
900 | |||
901 | out: | ||
902 | kfree(acx); | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | int wl1251_acx_mem_cfg(struct wl1251 *wl) | ||
907 | { | ||
908 | struct wl1251_acx_config_memory *mem_conf; | ||
909 | int ret, i; | ||
910 | |||
911 | wl1251_debug(DEBUG_ACX, "acx mem cfg"); | ||
912 | |||
913 | mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); | ||
914 | if (!mem_conf) { | ||
915 | ret = -ENOMEM; | ||
916 | goto out; | ||
917 | } | ||
918 | |||
919 | /* memory config */ | ||
920 | mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); | ||
921 | mem_conf->mem_config.rx_mem_block_num = 35; | ||
922 | mem_conf->mem_config.tx_min_mem_block_num = 64; | ||
923 | mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES; | ||
924 | mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING; | ||
925 | mem_conf->mem_config.num_ssid_profiles = 1; | ||
926 | mem_conf->mem_config.debug_buffer_size = | ||
927 | cpu_to_le16(TRACE_BUFFER_MAX_SIZE); | ||
928 | |||
929 | /* RX queue config */ | ||
930 | mem_conf->rx_queue_config.dma_address = 0; | ||
931 | mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF; | ||
932 | mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY; | ||
933 | mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE; | ||
934 | |||
935 | /* TX queue config */ | ||
936 | for (i = 0; i < MAX_TX_QUEUES; i++) { | ||
937 | mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF; | ||
938 | mem_conf->tx_queue_config[i].attributes = i; | ||
939 | } | ||
940 | |||
941 | ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf, | ||
942 | sizeof(*mem_conf)); | ||
943 | if (ret < 0) { | ||
944 | wl1251_warning("wl1251 mem config failed: %d", ret); | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | out: | ||
949 | kfree(mem_conf); | ||
950 | return ret; | ||
951 | } | ||
952 | |||
953 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim) | ||
954 | { | ||
955 | struct wl1251_acx_wr_tbtt_and_dtim *acx; | ||
956 | int ret; | ||
957 | |||
958 | wl1251_debug(DEBUG_ACX, "acx tbtt and dtim"); | ||
959 | |||
960 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
961 | if (!acx) { | ||
962 | ret = -ENOMEM; | ||
963 | goto out; | ||
964 | } | ||
965 | |||
966 | acx->tbtt = tbtt; | ||
967 | acx->dtim = dtim; | ||
968 | |||
969 | ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM, | ||
970 | acx, sizeof(*acx)); | ||
971 | if (ret < 0) { | ||
972 | wl1251_warning("failed to set tbtt and dtim: %d", ret); | ||
973 | goto out; | ||
974 | } | ||
975 | |||
976 | out: | ||
977 | kfree(acx); | ||
978 | return ret; | ||
979 | } | ||
980 | |||
981 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
982 | u8 aifs, u16 txop) | ||
983 | { | ||
984 | struct wl1251_acx_ac_cfg *acx; | ||
985 | int ret = 0; | ||
986 | |||
987 | wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " | ||
988 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); | ||
989 | |||
990 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
991 | |||
992 | if (!acx) { | ||
993 | ret = -ENOMEM; | ||
994 | goto out; | ||
995 | } | ||
996 | |||
997 | acx->ac = ac; | ||
998 | acx->cw_min = cw_min; | ||
999 | acx->cw_max = cw_max; | ||
1000 | acx->aifsn = aifs; | ||
1001 | acx->txop_limit = txop; | ||
1002 | |||
1003 | ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | ||
1004 | if (ret < 0) { | ||
1005 | wl1251_warning("acx ac cfg failed: %d", ret); | ||
1006 | goto out; | ||
1007 | } | ||
1008 | |||
1009 | out: | ||
1010 | kfree(acx); | ||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1015 | enum wl1251_acx_channel_type type, | ||
1016 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1017 | enum wl1251_acx_ack_policy ack_policy) | ||
1018 | { | ||
1019 | struct wl1251_acx_tid_cfg *acx; | ||
1020 | int ret = 0; | ||
1021 | |||
1022 | wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d " | ||
1023 | "ps_scheme %d ack_policy %d", queue, type, tsid, | ||
1024 | ps_scheme, ack_policy); | ||
1025 | |||
1026 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1027 | |||
1028 | if (!acx) { | ||
1029 | ret = -ENOMEM; | ||
1030 | goto out; | ||
1031 | } | ||
1032 | |||
1033 | acx->queue = queue; | ||
1034 | acx->type = type; | ||
1035 | acx->tsid = tsid; | ||
1036 | acx->ps_scheme = ps_scheme; | ||
1037 | acx->ack_policy = ack_policy; | ||
1038 | |||
1039 | ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1251_warning("acx tid cfg failed: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | out: | ||
1046 | kfree(acx); | ||
1047 | return ret; | ||
1048 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h deleted file mode 100644 index 842df310d92a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ /dev/null | |||
@@ -1,1413 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_ACX_H__ | ||
26 | #define __WL1251_ACX_H__ | ||
27 | |||
28 | #include "wl1251.h" | ||
29 | #include "wl1251_cmd.h" | ||
30 | |||
31 | /* Target's information element */ | ||
32 | struct acx_header { | ||
33 | struct wl1251_cmd_header cmd; | ||
34 | |||
35 | /* acx (or information element) header */ | ||
36 | u16 id; | ||
37 | |||
38 | /* payload length (not including headers */ | ||
39 | u16 len; | ||
40 | }; | ||
41 | |||
42 | struct acx_error_counter { | ||
43 | struct acx_header header; | ||
44 | |||
45 | /* The number of PLCP errors since the last time this */ | ||
46 | /* information element was interrogated. This field is */ | ||
47 | /* automatically cleared when it is interrogated.*/ | ||
48 | u32 PLCP_error; | ||
49 | |||
50 | /* The number of FCS errors since the last time this */ | ||
51 | /* information element was interrogated. This field is */ | ||
52 | /* automatically cleared when it is interrogated.*/ | ||
53 | u32 FCS_error; | ||
54 | |||
55 | /* The number of MPDUs without PLCP header errors received*/ | ||
56 | /* since the last time this information element was interrogated. */ | ||
57 | /* This field is automatically cleared when it is interrogated.*/ | ||
58 | u32 valid_frame; | ||
59 | |||
60 | /* the number of missed sequence numbers in the squentially */ | ||
61 | /* values of frames seq numbers */ | ||
62 | u32 seq_num_miss; | ||
63 | } __packed; | ||
64 | |||
65 | struct acx_revision { | ||
66 | struct acx_header header; | ||
67 | |||
68 | /* | ||
69 | * The WiLink firmware version, an ASCII string x.x.x.x, | ||
70 | * that uniquely identifies the current firmware. | ||
71 | * The left most digit is incremented each time a | ||
72 | * significant change is made to the firmware, such as | ||
73 | * code redesign or new platform support. | ||
74 | * The second digit is incremented when major enhancements | ||
75 | * are added or major fixes are made. | ||
76 | * The third digit is incremented for each GA release. | ||
77 | * The fourth digit is incremented for each build. | ||
78 | * The first two digits identify a firmware release version, | ||
79 | * in other words, a unique set of features. | ||
80 | * The first three digits identify a GA release. | ||
81 | */ | ||
82 | char fw_version[20]; | ||
83 | |||
84 | /* | ||
85 | * This 4 byte field specifies the WiLink hardware version. | ||
86 | * bits 0 - 15: Reserved. | ||
87 | * bits 16 - 23: Version ID - The WiLink version ID | ||
88 | * (1 = first spin, 2 = second spin, and so on). | ||
89 | * bits 24 - 31: Chip ID - The WiLink chip ID. | ||
90 | */ | ||
91 | u32 hw_version; | ||
92 | } __packed; | ||
93 | |||
94 | enum wl1251_psm_mode { | ||
95 | /* Active mode */ | ||
96 | WL1251_PSM_CAM = 0, | ||
97 | |||
98 | /* Power save mode */ | ||
99 | WL1251_PSM_PS = 1, | ||
100 | |||
101 | /* Extreme low power */ | ||
102 | WL1251_PSM_ELP = 2, | ||
103 | }; | ||
104 | |||
105 | struct acx_sleep_auth { | ||
106 | struct acx_header header; | ||
107 | |||
108 | /* The sleep level authorization of the device. */ | ||
109 | /* 0 - Always active*/ | ||
110 | /* 1 - Power down mode: light / fast sleep*/ | ||
111 | /* 2 - ELP mode: Deep / Max sleep*/ | ||
112 | u8 sleep_auth; | ||
113 | u8 padding[3]; | ||
114 | } __packed; | ||
115 | |||
116 | enum { | ||
117 | HOSTIF_PCI_MASTER_HOST_INDIRECT, | ||
118 | HOSTIF_PCI_MASTER_HOST_DIRECT, | ||
119 | HOSTIF_SLAVE, | ||
120 | HOSTIF_PKT_RING, | ||
121 | HOSTIF_DONTCARE = 0xFF | ||
122 | }; | ||
123 | |||
124 | #define DEFAULT_UCAST_PRIORITY 0 | ||
125 | #define DEFAULT_RX_Q_PRIORITY 0 | ||
126 | #define DEFAULT_NUM_STATIONS 1 | ||
127 | #define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */ | ||
128 | #define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */ | ||
129 | #define TRACE_BUFFER_MAX_SIZE 256 | ||
130 | |||
131 | #define DP_RX_PACKET_RING_CHUNK_SIZE 1600 | ||
132 | #define DP_TX_PACKET_RING_CHUNK_SIZE 1600 | ||
133 | #define DP_RX_PACKET_RING_CHUNK_NUM 2 | ||
134 | #define DP_TX_PACKET_RING_CHUNK_NUM 2 | ||
135 | #define DP_TX_COMPLETE_TIME_OUT 20 | ||
136 | #define FW_TX_CMPLT_BLOCK_SIZE 16 | ||
137 | |||
138 | struct acx_data_path_params { | ||
139 | struct acx_header header; | ||
140 | |||
141 | u16 rx_packet_ring_chunk_size; | ||
142 | u16 tx_packet_ring_chunk_size; | ||
143 | |||
144 | u8 rx_packet_ring_chunk_num; | ||
145 | u8 tx_packet_ring_chunk_num; | ||
146 | |||
147 | /* | ||
148 | * Maximum number of packets that can be gathered | ||
149 | * in the TX complete ring before an interrupt | ||
150 | * is generated. | ||
151 | */ | ||
152 | u8 tx_complete_threshold; | ||
153 | |||
154 | /* Number of pending TX complete entries in cyclic ring.*/ | ||
155 | u8 tx_complete_ring_depth; | ||
156 | |||
157 | /* | ||
158 | * Max num microseconds since a packet enters the TX | ||
159 | * complete ring until an interrupt is generated. | ||
160 | */ | ||
161 | u32 tx_complete_timeout; | ||
162 | } __packed; | ||
163 | |||
164 | |||
165 | struct acx_data_path_params_resp { | ||
166 | struct acx_header header; | ||
167 | |||
168 | u16 rx_packet_ring_chunk_size; | ||
169 | u16 tx_packet_ring_chunk_size; | ||
170 | |||
171 | u8 rx_packet_ring_chunk_num; | ||
172 | u8 tx_packet_ring_chunk_num; | ||
173 | |||
174 | u8 pad[2]; | ||
175 | |||
176 | u32 rx_packet_ring_addr; | ||
177 | u32 tx_packet_ring_addr; | ||
178 | |||
179 | u32 rx_control_addr; | ||
180 | u32 tx_control_addr; | ||
181 | |||
182 | u32 tx_complete_addr; | ||
183 | } __packed; | ||
184 | |||
185 | #define TX_MSDU_LIFETIME_MIN 0 | ||
186 | #define TX_MSDU_LIFETIME_MAX 3000 | ||
187 | #define TX_MSDU_LIFETIME_DEF 512 | ||
188 | #define RX_MSDU_LIFETIME_MIN 0 | ||
189 | #define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF | ||
190 | #define RX_MSDU_LIFETIME_DEF 512000 | ||
191 | |||
192 | struct acx_rx_msdu_lifetime { | ||
193 | struct acx_header header; | ||
194 | |||
195 | /* | ||
196 | * The maximum amount of time, in TU, before the | ||
197 | * firmware discards the MSDU. | ||
198 | */ | ||
199 | u32 lifetime; | ||
200 | } __packed; | ||
201 | |||
202 | /* | ||
203 | * RX Config Options Table | ||
204 | * Bit Definition | ||
205 | * === ========== | ||
206 | * 31:14 Reserved | ||
207 | * 13 Copy RX Status - when set, write three receive status words | ||
208 | * to top of rx'd MPDUs. | ||
209 | * When cleared, do not write three status words (added rev 1.5) | ||
210 | * 12 Reserved | ||
211 | * 11 RX Complete upon FCS error - when set, give rx complete | ||
212 | * interrupt for FCS errors, after the rx filtering, e.g. unicast | ||
213 | * frames not to us with FCS error will not generate an interrupt. | ||
214 | * 10 SSID Filter Enable - When set, the WiLink discards all beacon, | ||
215 | * probe request, and probe response frames with an SSID that does | ||
216 | * not match the SSID specified by the host in the START/JOIN | ||
217 | * command. | ||
218 | * When clear, the WiLink receives frames with any SSID. | ||
219 | * 9 Broadcast Filter Enable - When set, the WiLink discards all | ||
220 | * broadcast frames. When clear, the WiLink receives all received | ||
221 | * broadcast frames. | ||
222 | * 8:6 Reserved | ||
223 | * 5 BSSID Filter Enable - When set, the WiLink discards any frames | ||
224 | * with a BSSID that does not match the BSSID specified by the | ||
225 | * host. | ||
226 | * When clear, the WiLink receives frames from any BSSID. | ||
227 | * 4 MAC Addr Filter - When set, the WiLink discards any frames | ||
228 | * with a destination address that does not match the MAC address | ||
229 | * of the adaptor. | ||
230 | * When clear, the WiLink receives frames destined to any MAC | ||
231 | * address. | ||
232 | * 3 Promiscuous - When set, the WiLink receives all valid frames | ||
233 | * (i.e., all frames that pass the FCS check). | ||
234 | * When clear, only frames that pass the other filters specified | ||
235 | * are received. | ||
236 | * 2 FCS - When set, the WiLink includes the FCS with the received | ||
237 | * frame. | ||
238 | * When cleared, the FCS is discarded. | ||
239 | * 1 PLCP header - When set, write all data from baseband to frame | ||
240 | * buffer including PHY header. | ||
241 | * 0 Reserved - Always equal to 0. | ||
242 | * | ||
243 | * RX Filter Options Table | ||
244 | * Bit Definition | ||
245 | * === ========== | ||
246 | * 31:12 Reserved - Always equal to 0. | ||
247 | * 11 Association - When set, the WiLink receives all association | ||
248 | * related frames (association request/response, reassocation | ||
249 | * request/response, and disassociation). When clear, these frames | ||
250 | * are discarded. | ||
251 | * 10 Auth/De auth - When set, the WiLink receives all authentication | ||
252 | * and de-authentication frames. When clear, these frames are | ||
253 | * discarded. | ||
254 | * 9 Beacon - When set, the WiLink receives all beacon frames. | ||
255 | * When clear, these frames are discarded. | ||
256 | * 8 Contention Free - When set, the WiLink receives all contention | ||
257 | * free frames. | ||
258 | * When clear, these frames are discarded. | ||
259 | * 7 Control - When set, the WiLink receives all control frames. | ||
260 | * When clear, these frames are discarded. | ||
261 | * 6 Data - When set, the WiLink receives all data frames. | ||
262 | * When clear, these frames are discarded. | ||
263 | * 5 FCS Error - When set, the WiLink receives frames that have FCS | ||
264 | * errors. | ||
265 | * When clear, these frames are discarded. | ||
266 | * 4 Management - When set, the WiLink receives all management | ||
267 | * frames. | ||
268 | * When clear, these frames are discarded. | ||
269 | * 3 Probe Request - When set, the WiLink receives all probe request | ||
270 | * frames. | ||
271 | * When clear, these frames are discarded. | ||
272 | * 2 Probe Response - When set, the WiLink receives all probe | ||
273 | * response frames. | ||
274 | * When clear, these frames are discarded. | ||
275 | * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK | ||
276 | * frames. | ||
277 | * When clear, these frames are discarded. | ||
278 | * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames | ||
279 | * that have reserved frame types and sub types as defined by the | ||
280 | * 802.11 specification. | ||
281 | * When clear, these frames are discarded. | ||
282 | */ | ||
283 | struct acx_rx_config { | ||
284 | struct acx_header header; | ||
285 | |||
286 | u32 config_options; | ||
287 | u32 filter_options; | ||
288 | } __packed; | ||
289 | |||
290 | enum { | ||
291 | QOS_AC_BE = 0, | ||
292 | QOS_AC_BK, | ||
293 | QOS_AC_VI, | ||
294 | QOS_AC_VO, | ||
295 | QOS_HIGHEST_AC_INDEX = QOS_AC_VO, | ||
296 | }; | ||
297 | |||
298 | #define MAX_NUM_OF_AC (QOS_HIGHEST_AC_INDEX+1) | ||
299 | #define FIRST_AC_INDEX QOS_AC_BE | ||
300 | #define MAX_NUM_OF_802_1d_TAGS 8 | ||
301 | #define AC_PARAMS_MAX_TSID 15 | ||
302 | #define MAX_APSD_CONF 0xffff | ||
303 | |||
304 | #define QOS_TX_HIGH_MIN (0) | ||
305 | #define QOS_TX_HIGH_MAX (100) | ||
306 | |||
307 | #define QOS_TX_HIGH_BK_DEF (25) | ||
308 | #define QOS_TX_HIGH_BE_DEF (35) | ||
309 | #define QOS_TX_HIGH_VI_DEF (35) | ||
310 | #define QOS_TX_HIGH_VO_DEF (35) | ||
311 | |||
312 | #define QOS_TX_LOW_BK_DEF (15) | ||
313 | #define QOS_TX_LOW_BE_DEF (25) | ||
314 | #define QOS_TX_LOW_VI_DEF (25) | ||
315 | #define QOS_TX_LOW_VO_DEF (25) | ||
316 | |||
317 | struct acx_tx_queue_qos_config { | ||
318 | struct acx_header header; | ||
319 | |||
320 | u8 qid; | ||
321 | u8 pad[3]; | ||
322 | |||
323 | /* Max number of blocks allowd in the queue */ | ||
324 | u16 high_threshold; | ||
325 | |||
326 | /* Lowest memory blocks guaranteed for this queue */ | ||
327 | u16 low_threshold; | ||
328 | } __packed; | ||
329 | |||
330 | struct acx_packet_detection { | ||
331 | struct acx_header header; | ||
332 | |||
333 | u32 threshold; | ||
334 | } __packed; | ||
335 | |||
336 | |||
337 | enum acx_slot_type { | ||
338 | SLOT_TIME_LONG = 0, | ||
339 | SLOT_TIME_SHORT = 1, | ||
340 | DEFAULT_SLOT_TIME = SLOT_TIME_SHORT, | ||
341 | MAX_SLOT_TIMES = 0xFF | ||
342 | }; | ||
343 | |||
344 | #define STATION_WONE_INDEX 0 | ||
345 | |||
346 | struct acx_slot { | ||
347 | struct acx_header header; | ||
348 | |||
349 | u8 wone_index; /* Reserved */ | ||
350 | u8 slot_time; | ||
351 | u8 reserved[6]; | ||
352 | } __packed; | ||
353 | |||
354 | |||
355 | #define ADDRESS_GROUP_MAX (8) | ||
356 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) | ||
357 | |||
358 | struct acx_dot11_grp_addr_tbl { | ||
359 | struct acx_header header; | ||
360 | |||
361 | u8 enabled; | ||
362 | u8 num_groups; | ||
363 | u8 pad[2]; | ||
364 | u8 mac_table[ADDRESS_GROUP_MAX_LEN]; | ||
365 | } __packed; | ||
366 | |||
367 | |||
368 | #define RX_TIMEOUT_PS_POLL_MIN 0 | ||
369 | #define RX_TIMEOUT_PS_POLL_MAX (200000) | ||
370 | #define RX_TIMEOUT_PS_POLL_DEF (15) | ||
371 | #define RX_TIMEOUT_UPSD_MIN 0 | ||
372 | #define RX_TIMEOUT_UPSD_MAX (200000) | ||
373 | #define RX_TIMEOUT_UPSD_DEF (15) | ||
374 | |||
375 | struct acx_rx_timeout { | ||
376 | struct acx_header header; | ||
377 | |||
378 | /* | ||
379 | * The longest time the STA will wait to receive | ||
380 | * traffic from the AP after a PS-poll has been | ||
381 | * transmitted. | ||
382 | */ | ||
383 | u16 ps_poll_timeout; | ||
384 | |||
385 | /* | ||
386 | * The longest time the STA will wait to receive | ||
387 | * traffic from the AP after a frame has been sent | ||
388 | * from an UPSD enabled queue. | ||
389 | */ | ||
390 | u16 upsd_timeout; | ||
391 | } __packed; | ||
392 | |||
393 | #define RTS_THRESHOLD_MIN 0 | ||
394 | #define RTS_THRESHOLD_MAX 4096 | ||
395 | #define RTS_THRESHOLD_DEF 2347 | ||
396 | |||
397 | struct acx_rts_threshold { | ||
398 | struct acx_header header; | ||
399 | |||
400 | u16 threshold; | ||
401 | u8 pad[2]; | ||
402 | } __packed; | ||
403 | |||
404 | struct acx_beacon_filter_option { | ||
405 | struct acx_header header; | ||
406 | |||
407 | u8 enable; | ||
408 | |||
409 | /* | ||
410 | * The number of beacons without the unicast TIM | ||
411 | * bit set that the firmware buffers before | ||
412 | * signaling the host about ready frames. | ||
413 | * When set to 0 and the filter is enabled, beacons | ||
414 | * without the unicast TIM bit set are dropped. | ||
415 | */ | ||
416 | u8 max_num_beacons; | ||
417 | u8 pad[2]; | ||
418 | } __packed; | ||
419 | |||
420 | /* | ||
421 | * ACXBeaconFilterEntry (not 221) | ||
422 | * Byte Offset Size (Bytes) Definition | ||
423 | * =========== ============ ========== | ||
424 | * 0 1 IE identifier | ||
425 | * 1 1 Treatment bit mask | ||
426 | * | ||
427 | * ACXBeaconFilterEntry (221) | ||
428 | * Byte Offset Size (Bytes) Definition | ||
429 | * =========== ============ ========== | ||
430 | * 0 1 IE identifier | ||
431 | * 1 1 Treatment bit mask | ||
432 | * 2 3 OUI | ||
433 | * 5 1 Type | ||
434 | * 6 2 Version | ||
435 | * | ||
436 | * | ||
437 | * Treatment bit mask - The information element handling: | ||
438 | * bit 0 - The information element is compared and transferred | ||
439 | * in case of change. | ||
440 | * bit 1 - The information element is transferred to the host | ||
441 | * with each appearance or disappearance. | ||
442 | * Note that both bits can be set at the same time. | ||
443 | */ | ||
444 | #define BEACON_FILTER_TABLE_MAX_IE_NUM (32) | ||
445 | #define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6) | ||
446 | #define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2) | ||
447 | #define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6) | ||
448 | #define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \ | ||
449 | BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \ | ||
450 | (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ | ||
451 | BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) | ||
452 | |||
453 | #define BEACON_RULE_PASS_ON_CHANGE BIT(0) | ||
454 | #define BEACON_RULE_PASS_ON_APPEARANCE BIT(1) | ||
455 | |||
456 | #define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN (37) | ||
457 | |||
458 | struct acx_beacon_filter_ie_table { | ||
459 | struct acx_header header; | ||
460 | |||
461 | u8 num_ie; | ||
462 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
463 | u8 pad[3]; | ||
464 | } __packed; | ||
465 | |||
466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ | ||
467 | #define NO_BEACON_DEFAULT_TIMEOUT (500) /* in microseconds */ | ||
468 | |||
469 | struct acx_conn_monit_params { | ||
470 | struct acx_header header; | ||
471 | |||
472 | u32 synch_fail_thold; /* number of beacons missed */ | ||
473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ | ||
474 | }; | ||
475 | |||
476 | enum { | ||
477 | SG_ENABLE = 0, | ||
478 | SG_DISABLE, | ||
479 | SG_SENSE_NO_ACTIVITY, | ||
480 | SG_SENSE_ACTIVE | ||
481 | }; | ||
482 | |||
483 | struct acx_bt_wlan_coex { | ||
484 | struct acx_header header; | ||
485 | |||
486 | /* | ||
487 | * 0 -> PTA enabled | ||
488 | * 1 -> PTA disabled | ||
489 | * 2 -> sense no active mode, i.e. | ||
490 | * an interrupt is sent upon | ||
491 | * BT activity. | ||
492 | * 3 -> PTA is switched on in response | ||
493 | * to the interrupt sending. | ||
494 | */ | ||
495 | u8 enable; | ||
496 | u8 pad[3]; | ||
497 | } __packed; | ||
498 | |||
499 | #define PTA_ANTENNA_TYPE_DEF (0) | ||
500 | #define PTA_BT_HP_MAXTIME_DEF (2000) | ||
501 | #define PTA_WLAN_HP_MAX_TIME_DEF (5000) | ||
502 | #define PTA_SENSE_DISABLE_TIMER_DEF (1350) | ||
503 | #define PTA_PROTECTIVE_RX_TIME_DEF (1500) | ||
504 | #define PTA_PROTECTIVE_TX_TIME_DEF (1500) | ||
505 | #define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) | ||
506 | #define PTA_SIGNALING_TYPE_DEF (1) | ||
507 | #define PTA_AFH_LEVERAGE_ON_DEF (0) | ||
508 | #define PTA_NUMBER_QUIET_CYCLE_DEF (0) | ||
509 | #define PTA_MAX_NUM_CTS_DEF (3) | ||
510 | #define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) | ||
511 | #define PTA_NUMBER_OF_BT_PACKETS_DEF (2) | ||
512 | #define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) | ||
513 | #define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) | ||
514 | #define PTA_CYCLE_TIME_FAST_DEF (8700) | ||
515 | #define PTA_RX_FOR_AVALANCHE_DEF (5) | ||
516 | #define PTA_ELP_HP_DEF (0) | ||
517 | #define PTA_ANTI_STARVE_PERIOD_DEF (500) | ||
518 | #define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) | ||
519 | #define PTA_ALLOW_PA_SD_DEF (1) | ||
520 | #define PTA_TIME_BEFORE_BEACON_DEF (6300) | ||
521 | #define PTA_HPDM_MAX_TIME_DEF (1600) | ||
522 | #define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) | ||
523 | #define PTA_AUTO_MODE_NO_CTS_DEF (0) | ||
524 | #define PTA_BT_HP_RESPECTED_DEF (3) | ||
525 | #define PTA_WLAN_RX_MIN_RATE_DEF (24) | ||
526 | #define PTA_ACK_MODE_DEF (1) | ||
527 | |||
528 | struct acx_bt_wlan_coex_param { | ||
529 | struct acx_header header; | ||
530 | |||
531 | /* | ||
532 | * The minimum rate of a received WLAN packet in the STA, | ||
533 | * during protective mode, of which a new BT-HP request | ||
534 | * during this Rx will always be respected and gain the antenna. | ||
535 | */ | ||
536 | u32 min_rate; | ||
537 | |||
538 | /* Max time the BT HP will be respected. */ | ||
539 | u16 bt_hp_max_time; | ||
540 | |||
541 | /* Max time the WLAN HP will be respected. */ | ||
542 | u16 wlan_hp_max_time; | ||
543 | |||
544 | /* | ||
545 | * The time between the last BT activity | ||
546 | * and the moment when the sense mode returns | ||
547 | * to SENSE_INACTIVE. | ||
548 | */ | ||
549 | u16 sense_disable_timer; | ||
550 | |||
551 | /* Time before the next BT HP instance */ | ||
552 | u16 rx_time_bt_hp; | ||
553 | u16 tx_time_bt_hp; | ||
554 | |||
555 | /* range: 10-20000 default: 1500 */ | ||
556 | u16 rx_time_bt_hp_fast; | ||
557 | u16 tx_time_bt_hp_fast; | ||
558 | |||
559 | /* range: 2000-65535 default: 8700 */ | ||
560 | u16 wlan_cycle_fast; | ||
561 | |||
562 | /* range: 0 - 15000 (Msec) default: 1000 */ | ||
563 | u16 bt_anti_starvation_period; | ||
564 | |||
565 | /* range 400-10000(Usec) default: 3000 */ | ||
566 | u16 next_bt_lp_packet; | ||
567 | |||
568 | /* Deafult: worst case for BT DH5 traffic */ | ||
569 | u16 wake_up_beacon; | ||
570 | |||
571 | /* range: 0-50000(Usec) default: 1050 */ | ||
572 | u16 hp_dm_max_guard_time; | ||
573 | |||
574 | /* | ||
575 | * This is to prevent both BT & WLAN antenna | ||
576 | * starvation. | ||
577 | * Range: 100-50000(Usec) default:2550 | ||
578 | */ | ||
579 | u16 next_wlan_packet; | ||
580 | |||
581 | /* 0 -> shared antenna */ | ||
582 | u8 antenna_type; | ||
583 | |||
584 | /* | ||
585 | * 0 -> TI legacy | ||
586 | * 1 -> Palau | ||
587 | */ | ||
588 | u8 signal_type; | ||
589 | |||
590 | /* | ||
591 | * BT AFH status | ||
592 | * 0 -> no AFH | ||
593 | * 1 -> from dedicated GPIO | ||
594 | * 2 -> AFH on (from host) | ||
595 | */ | ||
596 | u8 afh_leverage_on; | ||
597 | |||
598 | /* | ||
599 | * The number of cycles during which no | ||
600 | * TX will be sent after 1 cycle of RX | ||
601 | * transaction in protective mode | ||
602 | */ | ||
603 | u8 quiet_cycle_num; | ||
604 | |||
605 | /* | ||
606 | * The maximum number of CTSs that will | ||
607 | * be sent for receiving RX packet in | ||
608 | * protective mode | ||
609 | */ | ||
610 | u8 max_cts; | ||
611 | |||
612 | /* | ||
613 | * The number of WLAN packets | ||
614 | * transferred in common mode before | ||
615 | * switching to BT. | ||
616 | */ | ||
617 | u8 wlan_packets_num; | ||
618 | |||
619 | /* | ||
620 | * The number of BT packets | ||
621 | * transferred in common mode before | ||
622 | * switching to WLAN. | ||
623 | */ | ||
624 | u8 bt_packets_num; | ||
625 | |||
626 | /* range: 1-255 default: 5 */ | ||
627 | u8 missed_rx_avalanche; | ||
628 | |||
629 | /* range: 0-1 default: 1 */ | ||
630 | u8 wlan_elp_hp; | ||
631 | |||
632 | /* range: 0 - 15 default: 4 */ | ||
633 | u8 bt_anti_starvation_cycles; | ||
634 | |||
635 | u8 ack_mode_dual_ant; | ||
636 | |||
637 | /* | ||
638 | * Allow PA_SD assertion/de-assertion | ||
639 | * during enabled BT activity. | ||
640 | */ | ||
641 | u8 pa_sd_enable; | ||
642 | |||
643 | /* | ||
644 | * Enable/Disable PTA in auto mode: | ||
645 | * Support Both Active & P.S modes | ||
646 | */ | ||
647 | u8 pta_auto_mode_enable; | ||
648 | |||
649 | /* range: 0 - 20 default: 1 */ | ||
650 | u8 bt_hp_respected_num; | ||
651 | } __packed; | ||
652 | |||
653 | #define CCA_THRSH_ENABLE_ENERGY_D 0x140A | ||
654 | #define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF | ||
655 | |||
656 | struct acx_energy_detection { | ||
657 | struct acx_header header; | ||
658 | |||
659 | /* The RX Clear Channel Assessment threshold in the PHY */ | ||
660 | u16 rx_cca_threshold; | ||
661 | u8 tx_energy_detection; | ||
662 | u8 pad; | ||
663 | } __packed; | ||
664 | |||
665 | #define BCN_RX_TIMEOUT_DEF_VALUE 10000 | ||
666 | #define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 | ||
667 | #define RX_BROADCAST_IN_PS_DEF_VALUE 1 | ||
668 | #define CONSECUTIVE_PS_POLL_FAILURE_DEF 4 | ||
669 | |||
670 | struct acx_beacon_broadcast { | ||
671 | struct acx_header header; | ||
672 | |||
673 | u16 beacon_rx_timeout; | ||
674 | u16 broadcast_timeout; | ||
675 | |||
676 | /* Enables receiving of broadcast packets in PS mode */ | ||
677 | u8 rx_broadcast_in_ps; | ||
678 | |||
679 | /* Consecutive PS Poll failures before updating the host */ | ||
680 | u8 ps_poll_threshold; | ||
681 | u8 pad[2]; | ||
682 | } __packed; | ||
683 | |||
684 | struct acx_event_mask { | ||
685 | struct acx_header header; | ||
686 | |||
687 | u32 event_mask; | ||
688 | u32 high_event_mask; /* Unused */ | ||
689 | } __packed; | ||
690 | |||
691 | #define CFG_RX_FCS BIT(2) | ||
692 | #define CFG_RX_ALL_GOOD BIT(3) | ||
693 | #define CFG_UNI_FILTER_EN BIT(4) | ||
694 | #define CFG_BSSID_FILTER_EN BIT(5) | ||
695 | #define CFG_MC_FILTER_EN BIT(6) | ||
696 | #define CFG_MC_ADDR0_EN BIT(7) | ||
697 | #define CFG_MC_ADDR1_EN BIT(8) | ||
698 | #define CFG_BC_REJECT_EN BIT(9) | ||
699 | #define CFG_SSID_FILTER_EN BIT(10) | ||
700 | #define CFG_RX_INT_FCS_ERROR BIT(11) | ||
701 | #define CFG_RX_INT_ENCRYPTED BIT(12) | ||
702 | #define CFG_RX_WR_RX_STATUS BIT(13) | ||
703 | #define CFG_RX_FILTER_NULTI BIT(14) | ||
704 | #define CFG_RX_RESERVE BIT(15) | ||
705 | #define CFG_RX_TIMESTAMP_TSF BIT(16) | ||
706 | |||
707 | #define CFG_RX_RSV_EN BIT(0) | ||
708 | #define CFG_RX_RCTS_ACK BIT(1) | ||
709 | #define CFG_RX_PRSP_EN BIT(2) | ||
710 | #define CFG_RX_PREQ_EN BIT(3) | ||
711 | #define CFG_RX_MGMT_EN BIT(4) | ||
712 | #define CFG_RX_FCS_ERROR BIT(5) | ||
713 | #define CFG_RX_DATA_EN BIT(6) | ||
714 | #define CFG_RX_CTL_EN BIT(7) | ||
715 | #define CFG_RX_CF_EN BIT(8) | ||
716 | #define CFG_RX_BCN_EN BIT(9) | ||
717 | #define CFG_RX_AUTH_EN BIT(10) | ||
718 | #define CFG_RX_ASSOC_EN BIT(11) | ||
719 | |||
720 | #define SCAN_PASSIVE BIT(0) | ||
721 | #define SCAN_5GHZ_BAND BIT(1) | ||
722 | #define SCAN_TRIGGERED BIT(2) | ||
723 | #define SCAN_PRIORITY_HIGH BIT(3) | ||
724 | |||
725 | struct acx_fw_gen_frame_rates { | ||
726 | struct acx_header header; | ||
727 | |||
728 | u8 tx_ctrl_frame_rate; /* RATE_* */ | ||
729 | u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */ | ||
730 | u8 tx_mgt_frame_rate; | ||
731 | u8 tx_mgt_frame_mod; | ||
732 | } __packed; | ||
733 | |||
734 | /* STA MAC */ | ||
735 | struct acx_dot11_station_id { | ||
736 | struct acx_header header; | ||
737 | |||
738 | u8 mac[ETH_ALEN]; | ||
739 | u8 pad[2]; | ||
740 | } __packed; | ||
741 | |||
742 | struct acx_feature_config { | ||
743 | struct acx_header header; | ||
744 | |||
745 | u32 options; | ||
746 | u32 data_flow_options; | ||
747 | } __packed; | ||
748 | |||
749 | struct acx_current_tx_power { | ||
750 | struct acx_header header; | ||
751 | |||
752 | u8 current_tx_power; | ||
753 | u8 padding[3]; | ||
754 | } __packed; | ||
755 | |||
756 | struct acx_dot11_default_key { | ||
757 | struct acx_header header; | ||
758 | |||
759 | u8 id; | ||
760 | u8 pad[3]; | ||
761 | } __packed; | ||
762 | |||
763 | struct acx_tsf_info { | ||
764 | struct acx_header header; | ||
765 | |||
766 | u32 current_tsf_msb; | ||
767 | u32 current_tsf_lsb; | ||
768 | u32 last_TBTT_msb; | ||
769 | u32 last_TBTT_lsb; | ||
770 | u8 last_dtim_count; | ||
771 | u8 pad[3]; | ||
772 | } __packed; | ||
773 | |||
774 | enum acx_wake_up_event { | ||
775 | WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ | ||
776 | WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ | ||
777 | WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */ | ||
778 | WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */ | ||
779 | WAKE_UP_EVENT_BITS_MASK = 0x0F | ||
780 | }; | ||
781 | |||
782 | struct acx_wake_up_condition { | ||
783 | struct acx_header header; | ||
784 | |||
785 | u8 wake_up_event; /* Only one bit can be set */ | ||
786 | u8 listen_interval; | ||
787 | u8 pad[2]; | ||
788 | } __packed; | ||
789 | |||
790 | struct acx_aid { | ||
791 | struct acx_header header; | ||
792 | |||
793 | /* | ||
794 | * To be set when associated with an AP. | ||
795 | */ | ||
796 | u16 aid; | ||
797 | u8 pad[2]; | ||
798 | } __packed; | ||
799 | |||
800 | enum acx_preamble_type { | ||
801 | ACX_PREAMBLE_LONG = 0, | ||
802 | ACX_PREAMBLE_SHORT = 1 | ||
803 | }; | ||
804 | |||
805 | struct acx_preamble { | ||
806 | struct acx_header header; | ||
807 | |||
808 | /* | ||
809 | * When set, the WiLink transmits the frames with a short preamble and | ||
810 | * when cleared, the WiLink transmits the frames with a long preamble. | ||
811 | */ | ||
812 | u8 preamble; | ||
813 | u8 padding[3]; | ||
814 | } __packed; | ||
815 | |||
816 | enum acx_ctsprotect_type { | ||
817 | CTSPROTECT_DISABLE = 0, | ||
818 | CTSPROTECT_ENABLE = 1 | ||
819 | }; | ||
820 | |||
821 | struct acx_ctsprotect { | ||
822 | struct acx_header header; | ||
823 | u8 ctsprotect; | ||
824 | u8 padding[3]; | ||
825 | } __packed; | ||
826 | |||
827 | struct acx_tx_statistics { | ||
828 | u32 internal_desc_overflow; | ||
829 | } __packed; | ||
830 | |||
831 | struct acx_rx_statistics { | ||
832 | u32 out_of_mem; | ||
833 | u32 hdr_overflow; | ||
834 | u32 hw_stuck; | ||
835 | u32 dropped; | ||
836 | u32 fcs_err; | ||
837 | u32 xfr_hint_trig; | ||
838 | u32 path_reset; | ||
839 | u32 reset_counter; | ||
840 | } __packed; | ||
841 | |||
842 | struct acx_dma_statistics { | ||
843 | u32 rx_requested; | ||
844 | u32 rx_errors; | ||
845 | u32 tx_requested; | ||
846 | u32 tx_errors; | ||
847 | } __packed; | ||
848 | |||
849 | struct acx_isr_statistics { | ||
850 | /* host command complete */ | ||
851 | u32 cmd_cmplt; | ||
852 | |||
853 | /* fiqisr() */ | ||
854 | u32 fiqs; | ||
855 | |||
856 | /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ | ||
857 | u32 rx_headers; | ||
858 | |||
859 | /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ | ||
860 | u32 rx_completes; | ||
861 | |||
862 | /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ | ||
863 | u32 rx_mem_overflow; | ||
864 | |||
865 | /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ | ||
866 | u32 rx_rdys; | ||
867 | |||
868 | /* irqisr() */ | ||
869 | u32 irqs; | ||
870 | |||
871 | /* (INT_STS_ND & INT_TRIG_TX_PROC) */ | ||
872 | u32 tx_procs; | ||
873 | |||
874 | /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ | ||
875 | u32 decrypt_done; | ||
876 | |||
877 | /* (INT_STS_ND & INT_TRIG_DMA0) */ | ||
878 | u32 dma0_done; | ||
879 | |||
880 | /* (INT_STS_ND & INT_TRIG_DMA1) */ | ||
881 | u32 dma1_done; | ||
882 | |||
883 | /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ | ||
884 | u32 tx_exch_complete; | ||
885 | |||
886 | /* (INT_STS_ND & INT_TRIG_COMMAND) */ | ||
887 | u32 commands; | ||
888 | |||
889 | /* (INT_STS_ND & INT_TRIG_RX_PROC) */ | ||
890 | u32 rx_procs; | ||
891 | |||
892 | /* (INT_STS_ND & INT_TRIG_PM_802) */ | ||
893 | u32 hw_pm_mode_changes; | ||
894 | |||
895 | /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ | ||
896 | u32 host_acknowledges; | ||
897 | |||
898 | /* (INT_STS_ND & INT_TRIG_PM_PCI) */ | ||
899 | u32 pci_pm; | ||
900 | |||
901 | /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ | ||
902 | u32 wakeups; | ||
903 | |||
904 | /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ | ||
905 | u32 low_rssi; | ||
906 | } __packed; | ||
907 | |||
908 | struct acx_wep_statistics { | ||
909 | /* WEP address keys configured */ | ||
910 | u32 addr_key_count; | ||
911 | |||
912 | /* default keys configured */ | ||
913 | u32 default_key_count; | ||
914 | |||
915 | u32 reserved; | ||
916 | |||
917 | /* number of times that WEP key not found on lookup */ | ||
918 | u32 key_not_found; | ||
919 | |||
920 | /* number of times that WEP key decryption failed */ | ||
921 | u32 decrypt_fail; | ||
922 | |||
923 | /* WEP packets decrypted */ | ||
924 | u32 packets; | ||
925 | |||
926 | /* WEP decrypt interrupts */ | ||
927 | u32 interrupt; | ||
928 | } __packed; | ||
929 | |||
930 | #define ACX_MISSED_BEACONS_SPREAD 10 | ||
931 | |||
932 | struct acx_pwr_statistics { | ||
933 | /* the amount of enters into power save mode (both PD & ELP) */ | ||
934 | u32 ps_enter; | ||
935 | |||
936 | /* the amount of enters into ELP mode */ | ||
937 | u32 elp_enter; | ||
938 | |||
939 | /* the amount of missing beacon interrupts to the host */ | ||
940 | u32 missing_bcns; | ||
941 | |||
942 | /* the amount of wake on host-access times */ | ||
943 | u32 wake_on_host; | ||
944 | |||
945 | /* the amount of wake on timer-expire */ | ||
946 | u32 wake_on_timer_exp; | ||
947 | |||
948 | /* the number of packets that were transmitted with PS bit set */ | ||
949 | u32 tx_with_ps; | ||
950 | |||
951 | /* the number of packets that were transmitted with PS bit clear */ | ||
952 | u32 tx_without_ps; | ||
953 | |||
954 | /* the number of received beacons */ | ||
955 | u32 rcvd_beacons; | ||
956 | |||
957 | /* the number of entering into PowerOn (power save off) */ | ||
958 | u32 power_save_off; | ||
959 | |||
960 | /* the number of entries into power save mode */ | ||
961 | u16 enable_ps; | ||
962 | |||
963 | /* | ||
964 | * the number of exits from power save, not including failed PS | ||
965 | * transitions | ||
966 | */ | ||
967 | u16 disable_ps; | ||
968 | |||
969 | /* | ||
970 | * the number of times the TSF counter was adjusted because | ||
971 | * of drift | ||
972 | */ | ||
973 | u32 fix_tsf_ps; | ||
974 | |||
975 | /* Gives statistics about the spread continuous missed beacons. | ||
976 | * The 16 LSB are dedicated for the PS mode. | ||
977 | * The 16 MSB are dedicated for the PS mode. | ||
978 | * cont_miss_bcns_spread[0] - single missed beacon. | ||
979 | * cont_miss_bcns_spread[1] - two continuous missed beacons. | ||
980 | * cont_miss_bcns_spread[2] - three continuous missed beacons. | ||
981 | * ... | ||
982 | * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. | ||
983 | */ | ||
984 | u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; | ||
985 | |||
986 | /* the number of beacons in awake mode */ | ||
987 | u32 rcvd_awake_beacons; | ||
988 | } __packed; | ||
989 | |||
990 | struct acx_mic_statistics { | ||
991 | u32 rx_pkts; | ||
992 | u32 calc_failure; | ||
993 | } __packed; | ||
994 | |||
995 | struct acx_aes_statistics { | ||
996 | u32 encrypt_fail; | ||
997 | u32 decrypt_fail; | ||
998 | u32 encrypt_packets; | ||
999 | u32 decrypt_packets; | ||
1000 | u32 encrypt_interrupt; | ||
1001 | u32 decrypt_interrupt; | ||
1002 | } __packed; | ||
1003 | |||
1004 | struct acx_event_statistics { | ||
1005 | u32 heart_beat; | ||
1006 | u32 calibration; | ||
1007 | u32 rx_mismatch; | ||
1008 | u32 rx_mem_empty; | ||
1009 | u32 rx_pool; | ||
1010 | u32 oom_late; | ||
1011 | u32 phy_transmit_error; | ||
1012 | u32 tx_stuck; | ||
1013 | } __packed; | ||
1014 | |||
1015 | struct acx_ps_statistics { | ||
1016 | u32 pspoll_timeouts; | ||
1017 | u32 upsd_timeouts; | ||
1018 | u32 upsd_max_sptime; | ||
1019 | u32 upsd_max_apturn; | ||
1020 | u32 pspoll_max_apturn; | ||
1021 | u32 pspoll_utilization; | ||
1022 | u32 upsd_utilization; | ||
1023 | } __packed; | ||
1024 | |||
1025 | struct acx_rxpipe_statistics { | ||
1026 | u32 rx_prep_beacon_drop; | ||
1027 | u32 descr_host_int_trig_rx_data; | ||
1028 | u32 beacon_buffer_thres_host_int_trig_rx_data; | ||
1029 | u32 missed_beacon_host_int_trig_rx_data; | ||
1030 | u32 tx_xfr_host_int_trig_rx_data; | ||
1031 | } __packed; | ||
1032 | |||
1033 | struct acx_statistics { | ||
1034 | struct acx_header header; | ||
1035 | |||
1036 | struct acx_tx_statistics tx; | ||
1037 | struct acx_rx_statistics rx; | ||
1038 | struct acx_dma_statistics dma; | ||
1039 | struct acx_isr_statistics isr; | ||
1040 | struct acx_wep_statistics wep; | ||
1041 | struct acx_pwr_statistics pwr; | ||
1042 | struct acx_aes_statistics aes; | ||
1043 | struct acx_mic_statistics mic; | ||
1044 | struct acx_event_statistics event; | ||
1045 | struct acx_ps_statistics ps; | ||
1046 | struct acx_rxpipe_statistics rxpipe; | ||
1047 | } __packed; | ||
1048 | |||
1049 | #define ACX_MAX_RATE_CLASSES 8 | ||
1050 | #define ACX_RATE_MASK_UNSPECIFIED 0 | ||
1051 | #define ACX_RATE_RETRY_LIMIT 10 | ||
1052 | |||
1053 | struct acx_rate_class { | ||
1054 | u32 enabled_rates; | ||
1055 | u8 short_retry_limit; | ||
1056 | u8 long_retry_limit; | ||
1057 | u8 aflags; | ||
1058 | u8 reserved; | ||
1059 | }; | ||
1060 | |||
1061 | struct acx_rate_policy { | ||
1062 | struct acx_header header; | ||
1063 | |||
1064 | u32 rate_class_cnt; | ||
1065 | struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES]; | ||
1066 | } __packed; | ||
1067 | |||
1068 | struct wl1251_acx_memory { | ||
1069 | __le16 num_stations; /* number of STAs to be supported. */ | ||
1070 | u16 reserved_1; | ||
1071 | |||
1072 | /* | ||
1073 | * Nmber of memory buffers for the RX mem pool. | ||
1074 | * The actual number may be less if there are | ||
1075 | * not enough blocks left for the minimum num | ||
1076 | * of TX ones. | ||
1077 | */ | ||
1078 | u8 rx_mem_block_num; | ||
1079 | u8 reserved_2; | ||
1080 | u8 num_tx_queues; /* From 1 to 16 */ | ||
1081 | u8 host_if_options; /* HOST_IF* */ | ||
1082 | u8 tx_min_mem_block_num; | ||
1083 | u8 num_ssid_profiles; | ||
1084 | __le16 debug_buffer_size; | ||
1085 | } __packed; | ||
1086 | |||
1087 | |||
1088 | #define ACX_RX_DESC_MIN 1 | ||
1089 | #define ACX_RX_DESC_MAX 127 | ||
1090 | #define ACX_RX_DESC_DEF 32 | ||
1091 | struct wl1251_acx_rx_queue_config { | ||
1092 | u8 num_descs; | ||
1093 | u8 pad; | ||
1094 | u8 type; | ||
1095 | u8 priority; | ||
1096 | __le32 dma_address; | ||
1097 | } __packed; | ||
1098 | |||
1099 | #define ACX_TX_DESC_MIN 1 | ||
1100 | #define ACX_TX_DESC_MAX 127 | ||
1101 | #define ACX_TX_DESC_DEF 16 | ||
1102 | struct wl1251_acx_tx_queue_config { | ||
1103 | u8 num_descs; | ||
1104 | u8 pad[2]; | ||
1105 | u8 attributes; | ||
1106 | } __packed; | ||
1107 | |||
1108 | #define MAX_TX_QUEUE_CONFIGS 5 | ||
1109 | #define MAX_TX_QUEUES 4 | ||
1110 | struct wl1251_acx_config_memory { | ||
1111 | struct acx_header header; | ||
1112 | |||
1113 | struct wl1251_acx_memory mem_config; | ||
1114 | struct wl1251_acx_rx_queue_config rx_queue_config; | ||
1115 | struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS]; | ||
1116 | } __packed; | ||
1117 | |||
1118 | struct wl1251_acx_mem_map { | ||
1119 | struct acx_header header; | ||
1120 | |||
1121 | void *code_start; | ||
1122 | void *code_end; | ||
1123 | |||
1124 | void *wep_defkey_start; | ||
1125 | void *wep_defkey_end; | ||
1126 | |||
1127 | void *sta_table_start; | ||
1128 | void *sta_table_end; | ||
1129 | |||
1130 | void *packet_template_start; | ||
1131 | void *packet_template_end; | ||
1132 | |||
1133 | void *queue_memory_start; | ||
1134 | void *queue_memory_end; | ||
1135 | |||
1136 | void *packet_memory_pool_start; | ||
1137 | void *packet_memory_pool_end; | ||
1138 | |||
1139 | void *debug_buffer1_start; | ||
1140 | void *debug_buffer1_end; | ||
1141 | |||
1142 | void *debug_buffer2_start; | ||
1143 | void *debug_buffer2_end; | ||
1144 | |||
1145 | /* Number of blocks FW allocated for TX packets */ | ||
1146 | u32 num_tx_mem_blocks; | ||
1147 | |||
1148 | /* Number of blocks FW allocated for RX packets */ | ||
1149 | u32 num_rx_mem_blocks; | ||
1150 | } __packed; | ||
1151 | |||
1152 | |||
1153 | struct wl1251_acx_wr_tbtt_and_dtim { | ||
1154 | |||
1155 | struct acx_header header; | ||
1156 | |||
1157 | /* Time in TUs between two consecutive beacons */ | ||
1158 | u16 tbtt; | ||
1159 | |||
1160 | /* | ||
1161 | * DTIM period | ||
1162 | * For BSS: Number of TBTTs in a DTIM period (range: 1-10) | ||
1163 | * For IBSS: value shall be set to 1 | ||
1164 | */ | ||
1165 | u8 dtim; | ||
1166 | u8 padding; | ||
1167 | } __packed; | ||
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 | } __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 | } __packed; | ||
1249 | |||
1250 | /************************************************************************* | ||
1251 | |||
1252 | Host Interrupt Register (WiLink -> Host) | ||
1253 | |||
1254 | **************************************************************************/ | ||
1255 | |||
1256 | /* RX packet is ready in Xfer buffer #0 */ | ||
1257 | #define WL1251_ACX_INTR_RX0_DATA BIT(0) | ||
1258 | |||
1259 | /* TX result(s) are in the TX complete buffer */ | ||
1260 | #define WL1251_ACX_INTR_TX_RESULT BIT(1) | ||
1261 | |||
1262 | /* OBSOLETE */ | ||
1263 | #define WL1251_ACX_INTR_TX_XFR BIT(2) | ||
1264 | |||
1265 | /* RX packet is ready in Xfer buffer #1 */ | ||
1266 | #define WL1251_ACX_INTR_RX1_DATA BIT(3) | ||
1267 | |||
1268 | /* Event was entered to Event MBOX #A */ | ||
1269 | #define WL1251_ACX_INTR_EVENT_A BIT(4) | ||
1270 | |||
1271 | /* Event was entered to Event MBOX #B */ | ||
1272 | #define WL1251_ACX_INTR_EVENT_B BIT(5) | ||
1273 | |||
1274 | /* OBSOLETE */ | ||
1275 | #define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6) | ||
1276 | |||
1277 | /* Trace meassge on MBOX #A */ | ||
1278 | #define WL1251_ACX_INTR_TRACE_A BIT(7) | ||
1279 | |||
1280 | /* Trace meassge on MBOX #B */ | ||
1281 | #define WL1251_ACX_INTR_TRACE_B BIT(8) | ||
1282 | |||
1283 | /* Command processing completion */ | ||
1284 | #define WL1251_ACX_INTR_CMD_COMPLETE BIT(9) | ||
1285 | |||
1286 | /* Init sequence is done */ | ||
1287 | #define WL1251_ACX_INTR_INIT_COMPLETE BIT(14) | ||
1288 | |||
1289 | #define WL1251_ACX_INTR_ALL 0xFFFFFFFF | ||
1290 | |||
1291 | enum { | ||
1292 | ACX_WAKE_UP_CONDITIONS = 0x0002, | ||
1293 | ACX_MEM_CFG = 0x0003, | ||
1294 | ACX_SLOT = 0x0004, | ||
1295 | ACX_QUEUE_HEAD = 0x0005, /* for MASTER mode only */ | ||
1296 | ACX_AC_CFG = 0x0007, | ||
1297 | ACX_MEM_MAP = 0x0008, | ||
1298 | ACX_AID = 0x000A, | ||
1299 | ACX_RADIO_PARAM = 0x000B, /* Not used */ | ||
1300 | ACX_CFG = 0x000C, /* Not used */ | ||
1301 | ACX_FW_REV = 0x000D, | ||
1302 | ACX_MEDIUM_USAGE = 0x000F, | ||
1303 | ACX_RX_CFG = 0x0010, | ||
1304 | ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ | ||
1305 | ACX_BSS_IN_PS = 0x0012, /* for AP only */ | ||
1306 | ACX_STATISTICS = 0x0013, /* Debug API */ | ||
1307 | ACX_FEATURE_CFG = 0x0015, | ||
1308 | ACX_MISC_CFG = 0x0017, /* Not used */ | ||
1309 | ACX_TID_CFG = 0x001A, | ||
1310 | ACX_BEACON_FILTER_OPT = 0x001F, | ||
1311 | ACX_LOW_RSSI = 0x0020, | ||
1312 | ACX_NOISE_HIST = 0x0021, | ||
1313 | ACX_HDK_VERSION = 0x0022, /* ??? */ | ||
1314 | ACX_PD_THRESHOLD = 0x0023, | ||
1315 | ACX_DATA_PATH_PARAMS = 0x0024, /* WO */ | ||
1316 | ACX_DATA_PATH_RESP_PARAMS = 0x0024, /* RO */ | ||
1317 | ACX_CCA_THRESHOLD = 0x0025, | ||
1318 | ACX_EVENT_MBOX_MASK = 0x0026, | ||
1319 | #ifdef FW_RUNNING_AS_AP | ||
1320 | ACX_DTIM_PERIOD = 0x0027, /* for AP only */ | ||
1321 | #else | ||
1322 | ACX_WR_TBTT_AND_DTIM = 0x0027, /* STA only */ | ||
1323 | #endif | ||
1324 | ACX_ACI_OPTION_CFG = 0x0029, /* OBSOLETE (for 1251)*/ | ||
1325 | ACX_GPIO_CFG = 0x002A, /* Not used */ | ||
1326 | ACX_GPIO_SET = 0x002B, /* Not used */ | ||
1327 | ACX_PM_CFG = 0x002C, /* To Be Documented */ | ||
1328 | ACX_CONN_MONIT_PARAMS = 0x002D, | ||
1329 | ACX_AVERAGE_RSSI = 0x002E, /* Not used */ | ||
1330 | ACX_CONS_TX_FAILURE = 0x002F, | ||
1331 | ACX_BCN_DTIM_OPTIONS = 0x0031, | ||
1332 | ACX_SG_ENABLE = 0x0032, | ||
1333 | ACX_SG_CFG = 0x0033, | ||
1334 | ACX_ANTENNA_DIVERSITY_CFG = 0x0035, /* To Be Documented */ | ||
1335 | ACX_LOW_SNR = 0x0037, /* To Be Documented */ | ||
1336 | ACX_BEACON_FILTER_TABLE = 0x0038, | ||
1337 | ACX_ARP_IP_FILTER = 0x0039, | ||
1338 | ACX_ROAMING_STATISTICS_TBL = 0x003B, | ||
1339 | ACX_RATE_POLICY = 0x003D, | ||
1340 | ACX_CTS_PROTECTION = 0x003E, | ||
1341 | ACX_SLEEP_AUTH = 0x003F, | ||
1342 | ACX_PREAMBLE_TYPE = 0x0040, | ||
1343 | ACX_ERROR_CNT = 0x0041, | ||
1344 | ACX_FW_GEN_FRAME_RATES = 0x0042, | ||
1345 | ACX_IBSS_FILTER = 0x0044, | ||
1346 | ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, | ||
1347 | ACX_TSF_INFO = 0x0046, | ||
1348 | ACX_CONFIG_PS_WMM = 0x0049, | ||
1349 | ACX_ENABLE_RX_DATA_FILTER = 0x004A, | ||
1350 | ACX_SET_RX_DATA_FILTER = 0x004B, | ||
1351 | ACX_GET_DATA_FILTER_STATISTICS = 0x004C, | ||
1352 | ACX_POWER_LEVEL_TABLE = 0x004D, | ||
1353 | ACX_BET_ENABLE = 0x0050, | ||
1354 | DOT11_STATION_ID = 0x1001, | ||
1355 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | ||
1356 | DOT11_CUR_TX_PWR = 0x100D, | ||
1357 | DOT11_DEFAULT_KEY = 0x1010, | ||
1358 | DOT11_RX_DOT11_MODE = 0x1012, | ||
1359 | DOT11_RTS_THRESHOLD = 0x1013, | ||
1360 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | ||
1361 | |||
1362 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, | ||
1363 | |||
1364 | MAX_IE = 0xFFFF | ||
1365 | }; | ||
1366 | |||
1367 | |||
1368 | int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, | ||
1369 | u8 mgt_rate, u8 mgt_mod); | ||
1370 | int wl1251_acx_station_id(struct wl1251 *wl); | ||
1371 | int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id); | ||
1372 | int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, | ||
1373 | u8 listen_interval); | ||
1374 | int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth); | ||
1375 | int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len); | ||
1376 | int wl1251_acx_tx_power(struct wl1251 *wl, int power); | ||
1377 | int wl1251_acx_feature_cfg(struct wl1251 *wl); | ||
1378 | int wl1251_acx_mem_map(struct wl1251 *wl, | ||
1379 | struct acx_header *mem_map, size_t len); | ||
1380 | int wl1251_acx_data_path_params(struct wl1251 *wl, | ||
1381 | struct acx_data_path_params_resp *data_path); | ||
1382 | int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time); | ||
1383 | int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter); | ||
1384 | int wl1251_acx_pd_threshold(struct wl1251 *wl); | ||
1385 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); | ||
1386 | int wl1251_acx_group_address_tbl(struct wl1251 *wl); | ||
1387 | int wl1251_acx_service_period_timeout(struct wl1251 *wl); | ||
1388 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); | ||
1389 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter); | ||
1390 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl); | ||
1391 | int wl1251_acx_conn_monit_params(struct wl1251 *wl); | ||
1392 | int wl1251_acx_sg_enable(struct wl1251 *wl); | ||
1393 | int wl1251_acx_sg_cfg(struct wl1251 *wl); | ||
1394 | int wl1251_acx_cca_threshold(struct wl1251 *wl); | ||
1395 | int wl1251_acx_bcn_dtim_options(struct wl1251 *wl); | ||
1396 | int wl1251_acx_aid(struct wl1251 *wl, u16 aid); | ||
1397 | int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask); | ||
1398 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble); | ||
1399 | int wl1251_acx_cts_protect(struct wl1251 *wl, | ||
1400 | enum acx_ctsprotect_type ctsprotect); | ||
1401 | int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats); | ||
1402 | int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | ||
1403 | int wl1251_acx_rate_policies(struct wl1251 *wl); | ||
1404 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | ||
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); | ||
1412 | |||
1413 | #endif /* __WL1251_ACX_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c deleted file mode 100644 index 65e0416be5b6..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ /dev/null | |||
@@ -1,559 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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/gpio.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include "wl1251_reg.h" | ||
28 | #include "wl1251_boot.h" | ||
29 | #include "wl1251_io.h" | ||
30 | #include "wl1251_spi.h" | ||
31 | #include "wl1251_event.h" | ||
32 | #include "wl1251_acx.h" | ||
33 | |||
34 | void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) | ||
35 | { | ||
36 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); | ||
37 | wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | ||
38 | } | ||
39 | |||
40 | int wl1251_boot_soft_reset(struct wl1251 *wl) | ||
41 | { | ||
42 | unsigned long timeout; | ||
43 | u32 boot_data; | ||
44 | |||
45 | /* perform soft reset */ | ||
46 | wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | ||
47 | |||
48 | /* SOFT_RESET is self clearing */ | ||
49 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | ||
50 | while (1) { | ||
51 | boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); | ||
52 | wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | ||
53 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | ||
54 | break; | ||
55 | |||
56 | if (time_after(jiffies, timeout)) { | ||
57 | /* 1.2 check pWhalBus->uSelfClearTime if the | ||
58 | * timeout was reached */ | ||
59 | wl1251_error("soft reset timeout"); | ||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | udelay(SOFT_RESET_STALL_TIME); | ||
64 | } | ||
65 | |||
66 | /* disable Rx/Tx */ | ||
67 | wl1251_reg_write32(wl, ENABLE, 0x0); | ||
68 | |||
69 | /* disable auto calibration on start*/ | ||
70 | wl1251_reg_write32(wl, SPARE_A2, 0xffff); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int wl1251_boot_init_seq(struct wl1251 *wl) | ||
76 | { | ||
77 | u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq; | ||
78 | |||
79 | /* | ||
80 | * col #1: INTEGER_DIVIDER | ||
81 | * col #2: FRACTIONAL_DIVIDER | ||
82 | * col #3: ATTN_BB | ||
83 | * col #4: ALPHA_BB | ||
84 | * col #5: STOP_TIME_BB | ||
85 | * col #6: BB_PLL_LOOP_FILTER | ||
86 | */ | ||
87 | static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = { | ||
88 | |||
89 | { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/ | ||
90 | { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/ | ||
91 | { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/ | ||
92 | { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/ | ||
93 | { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */ | ||
94 | }; | ||
95 | |||
96 | /* read NVS params */ | ||
97 | scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6); | ||
98 | wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6); | ||
99 | |||
100 | /* read ELP_CMD */ | ||
101 | elp_cmd = wl1251_reg_read32(wl, ELP_CMD); | ||
102 | wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd); | ||
103 | |||
104 | /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */ | ||
105 | ref_freq = scr_pad6 & 0x000000FF; | ||
106 | wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq); | ||
107 | |||
108 | wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9); | ||
109 | |||
110 | /* | ||
111 | * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME) | ||
112 | */ | ||
113 | wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6); | ||
114 | |||
115 | /* | ||
116 | * set the clock detect feature to work in the restart wu procedure | ||
117 | * (ELP_CFG_MODE[14]) and Select the clock source type | ||
118 | * (ELP_CFG_MODE[13:12]) | ||
119 | */ | ||
120 | tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000; | ||
121 | wl1251_reg_write32(wl, ELP_CFG_MODE, tmp); | ||
122 | |||
123 | /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */ | ||
124 | elp_cmd |= 0x00000040; | ||
125 | wl1251_reg_write32(wl, ELP_CMD, elp_cmd); | ||
126 | |||
127 | /* PG 1.2: Set the BB PLL stable time to be 1000usec | ||
128 | * (PLL_STABLE_TIME) */ | ||
129 | wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20); | ||
130 | |||
131 | /* PG 1.2: read clock request time */ | ||
132 | init_data = wl1251_reg_read32(wl, CLK_REQ_TIME); | ||
133 | |||
134 | /* | ||
135 | * PG 1.2: set the clock request time to be ref_clk_settling_time - | ||
136 | * 1ms = 4ms | ||
137 | */ | ||
138 | if (init_data > 0x21) | ||
139 | tmp = init_data - 0x21; | ||
140 | else | ||
141 | tmp = 0; | ||
142 | wl1251_reg_write32(wl, CLK_REQ_TIME, tmp); | ||
143 | |||
144 | /* set BB PLL configurations in RF AFE */ | ||
145 | wl1251_reg_write32(wl, 0x003058cc, 0x4B5); | ||
146 | |||
147 | /* set RF_AFE_REG_5 */ | ||
148 | wl1251_reg_write32(wl, 0x003058d4, 0x50); | ||
149 | |||
150 | /* set RF_AFE_CTRL_REG_2 */ | ||
151 | wl1251_reg_write32(wl, 0x00305948, 0x11c001); | ||
152 | |||
153 | /* | ||
154 | * change RF PLL and BB PLL divider for VCO clock and adjust VCO | ||
155 | * bais current(RF_AFE_REG_13) | ||
156 | */ | ||
157 | wl1251_reg_write32(wl, 0x003058f4, 0x1e); | ||
158 | |||
159 | /* set BB PLL configurations */ | ||
160 | tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000; | ||
161 | wl1251_reg_write32(wl, 0x00305840, tmp); | ||
162 | |||
163 | /* set fractional divider according to Appendix C-BB PLL | ||
164 | * Calculations | ||
165 | */ | ||
166 | tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER]; | ||
167 | wl1251_reg_write32(wl, 0x00305844, tmp); | ||
168 | |||
169 | /* set the initial data for the sigma delta */ | ||
170 | wl1251_reg_write32(wl, 0x00305848, 0x3039); | ||
171 | |||
172 | /* | ||
173 | * set the accumulator attenuation value, calibration loop1 | ||
174 | * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and | ||
175 | * the VCO gain | ||
176 | */ | ||
177 | tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) | | ||
178 | (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1; | ||
179 | wl1251_reg_write32(wl, 0x00305854, tmp); | ||
180 | |||
181 | /* | ||
182 | * set the calibration stop time after holdoff time expires and set | ||
183 | * settling time HOLD_OFF_TIME_BB | ||
184 | */ | ||
185 | tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000; | ||
186 | wl1251_reg_write32(wl, 0x00305858, tmp); | ||
187 | |||
188 | /* | ||
189 | * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL | ||
190 | * constant leakage current to linearize PFD to 0uA - | ||
191 | * BB_ILOOPF[7:3] | ||
192 | */ | ||
193 | tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030; | ||
194 | wl1251_reg_write32(wl, 0x003058f8, tmp); | ||
195 | |||
196 | /* | ||
197 | * set regulator output voltage for n divider to | ||
198 | * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2], | ||
199 | * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB | ||
200 | * PLL auto-call to normal mode- BB_CALGAIN_3DB[8] | ||
201 | */ | ||
202 | wl1251_reg_write32(wl, 0x003058f0, 0x29); | ||
203 | |||
204 | /* enable restart wakeup sequence (ELP_CMD[0]) */ | ||
205 | wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1); | ||
206 | |||
207 | /* restart sequence completed */ | ||
208 | udelay(2000); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag) | ||
214 | { | ||
215 | u32 cpu_ctrl; | ||
216 | |||
217 | /* 10.5.0 run the firmware (I) */ | ||
218 | cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL); | ||
219 | |||
220 | /* 10.5.1 run the firmware (II) */ | ||
221 | cpu_ctrl &= ~flag; | ||
222 | wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | ||
223 | } | ||
224 | |||
225 | int wl1251_boot_run_firmware(struct wl1251 *wl) | ||
226 | { | ||
227 | int loop, ret; | ||
228 | u32 chip_id, acx_intr; | ||
229 | |||
230 | wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | ||
231 | |||
232 | chip_id = wl1251_reg_read32(wl, CHIP_ID_B); | ||
233 | |||
234 | wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | ||
235 | |||
236 | if (chip_id != wl->chip_id) { | ||
237 | wl1251_error("chip id doesn't match after firmware boot"); | ||
238 | return -EIO; | ||
239 | } | ||
240 | |||
241 | /* wait for init to complete */ | ||
242 | loop = 0; | ||
243 | while (loop++ < INIT_LOOP) { | ||
244 | udelay(INIT_LOOP_DELAY); | ||
245 | acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | ||
246 | |||
247 | if (acx_intr == 0xffffffff) { | ||
248 | wl1251_error("error reading hardware complete " | ||
249 | "init indication"); | ||
250 | return -EIO; | ||
251 | } | ||
252 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | ||
253 | else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) { | ||
254 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, | ||
255 | WL1251_ACX_INTR_INIT_COMPLETE); | ||
256 | break; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | if (loop > INIT_LOOP) { | ||
261 | wl1251_error("timeout waiting for the hardware to " | ||
262 | "complete initialization"); | ||
263 | return -EIO; | ||
264 | } | ||
265 | |||
266 | /* get hardware config command mail box */ | ||
267 | wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); | ||
268 | |||
269 | /* get hardware config event mail box */ | ||
270 | wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); | ||
271 | |||
272 | /* set the working partition to its "running" mode offset */ | ||
273 | wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START, | ||
274 | WL1251_PART_WORK_MEM_SIZE, | ||
275 | WL1251_PART_WORK_REG_START, | ||
276 | WL1251_PART_WORK_REG_SIZE); | ||
277 | |||
278 | wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", | ||
279 | wl->cmd_box_addr, wl->event_box_addr); | ||
280 | |||
281 | wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver)); | ||
282 | |||
283 | /* | ||
284 | * in case of full asynchronous mode the firmware event must be | ||
285 | * ready to receive event from the command mailbox | ||
286 | */ | ||
287 | |||
288 | /* enable gpio interrupts */ | ||
289 | wl1251_enable_interrupts(wl); | ||
290 | |||
291 | /* Enable target's interrupts */ | ||
292 | wl->intr_mask = WL1251_ACX_INTR_RX0_DATA | | ||
293 | WL1251_ACX_INTR_RX1_DATA | | ||
294 | WL1251_ACX_INTR_TX_RESULT | | ||
295 | WL1251_ACX_INTR_EVENT_A | | ||
296 | WL1251_ACX_INTR_EVENT_B | | ||
297 | WL1251_ACX_INTR_INIT_COMPLETE; | ||
298 | wl1251_boot_target_enable_interrupts(wl); | ||
299 | |||
300 | wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID | | ||
301 | SYNCHRONIZATION_TIMEOUT_EVENT_ID | | ||
302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | ||
303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | ||
304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | ||
305 | BT_PTA_PREDICTION_EVENT_ID; | ||
306 | |||
307 | ret = wl1251_event_unmask(wl); | ||
308 | if (ret < 0) { | ||
309 | wl1251_error("EVENT mask setting failed"); | ||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | wl1251_event_mbox_config(wl); | ||
314 | |||
315 | /* firmware startup completed */ | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) | ||
320 | { | ||
321 | int addr, chunk_num, partition_limit; | ||
322 | size_t fw_data_len, len; | ||
323 | u8 *p, *buf; | ||
324 | |||
325 | /* whal_FwCtrl_LoadFwImageSm() */ | ||
326 | |||
327 | wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x", | ||
328 | wl1251_reg_read32(wl, CHIP_ID_B)); | ||
329 | |||
330 | /* 10.0 check firmware length and set partition */ | ||
331 | fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) | | ||
332 | (wl->fw[6] << 8) | (wl->fw[7]); | ||
333 | |||
334 | wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len, | ||
335 | CHUNK_SIZE); | ||
336 | |||
337 | if ((fw_data_len % 4) != 0) { | ||
338 | wl1251_error("firmware length not multiple of four"); | ||
339 | return -EIO; | ||
340 | } | ||
341 | |||
342 | buf = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
343 | if (!buf) { | ||
344 | wl1251_error("allocation for firmware upload chunk failed"); | ||
345 | return -ENOMEM; | ||
346 | } | ||
347 | |||
348 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, | ||
349 | WL1251_PART_DOWN_MEM_SIZE, | ||
350 | WL1251_PART_DOWN_REG_START, | ||
351 | WL1251_PART_DOWN_REG_SIZE); | ||
352 | |||
353 | /* 10.1 set partition limit and chunk num */ | ||
354 | chunk_num = 0; | ||
355 | partition_limit = WL1251_PART_DOWN_MEM_SIZE; | ||
356 | |||
357 | while (chunk_num < fw_data_len / CHUNK_SIZE) { | ||
358 | /* 10.2 update partition, if needed */ | ||
359 | addr = WL1251_PART_DOWN_MEM_START + | ||
360 | (chunk_num + 2) * CHUNK_SIZE; | ||
361 | if (addr > partition_limit) { | ||
362 | addr = WL1251_PART_DOWN_MEM_START + | ||
363 | chunk_num * CHUNK_SIZE; | ||
364 | partition_limit = chunk_num * CHUNK_SIZE + | ||
365 | WL1251_PART_DOWN_MEM_SIZE; | ||
366 | wl1251_set_partition(wl, | ||
367 | addr, | ||
368 | WL1251_PART_DOWN_MEM_SIZE, | ||
369 | WL1251_PART_DOWN_REG_START, | ||
370 | WL1251_PART_DOWN_REG_SIZE); | ||
371 | } | ||
372 | |||
373 | /* 10.3 upload the chunk */ | ||
374 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; | ||
375 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | ||
376 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | ||
377 | p, addr); | ||
378 | |||
379 | /* need to copy the chunk for dma */ | ||
380 | len = CHUNK_SIZE; | ||
381 | memcpy(buf, p, len); | ||
382 | wl1251_mem_write(wl, addr, buf, len); | ||
383 | |||
384 | chunk_num++; | ||
385 | } | ||
386 | |||
387 | /* 10.4 upload the last chunk */ | ||
388 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; | ||
389 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | ||
390 | |||
391 | /* need to copy the chunk for dma */ | ||
392 | len = fw_data_len % CHUNK_SIZE; | ||
393 | memcpy(buf, p, len); | ||
394 | |||
395 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", | ||
396 | len, p, addr); | ||
397 | wl1251_mem_write(wl, addr, buf, len); | ||
398 | |||
399 | kfree(buf); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int wl1251_boot_upload_nvs(struct wl1251 *wl) | ||
405 | { | ||
406 | size_t nvs_len, nvs_bytes_written, burst_len; | ||
407 | int nvs_start, i; | ||
408 | u32 dest_addr, val; | ||
409 | u8 *nvs_ptr, *nvs; | ||
410 | |||
411 | nvs = wl->nvs; | ||
412 | if (nvs == NULL) | ||
413 | return -ENODEV; | ||
414 | |||
415 | nvs_ptr = nvs; | ||
416 | |||
417 | nvs_len = wl->nvs_len; | ||
418 | nvs_start = wl->fw_len; | ||
419 | |||
420 | /* | ||
421 | * Layout before the actual NVS tables: | ||
422 | * 1 byte : burst length. | ||
423 | * 2 bytes: destination address. | ||
424 | * n bytes: data to burst copy. | ||
425 | * | ||
426 | * This is ended by a 0 length, then the NVS tables. | ||
427 | */ | ||
428 | |||
429 | while (nvs_ptr[0]) { | ||
430 | burst_len = nvs_ptr[0]; | ||
431 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); | ||
432 | |||
433 | /* We move our pointer to the data */ | ||
434 | nvs_ptr += 3; | ||
435 | |||
436 | for (i = 0; i < burst_len; i++) { | ||
437 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | ||
438 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | ||
439 | |||
440 | wl1251_debug(DEBUG_BOOT, | ||
441 | "nvs burst write 0x%x: 0x%x", | ||
442 | dest_addr, val); | ||
443 | wl1251_mem_write32(wl, dest_addr, val); | ||
444 | |||
445 | nvs_ptr += 4; | ||
446 | dest_addr += 4; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * We've reached the first zero length, the first NVS table | ||
452 | * is 7 bytes further. | ||
453 | */ | ||
454 | nvs_ptr += 7; | ||
455 | nvs_len -= nvs_ptr - nvs; | ||
456 | nvs_len = ALIGN(nvs_len, 4); | ||
457 | |||
458 | /* Now we must set the partition correctly */ | ||
459 | wl1251_set_partition(wl, nvs_start, | ||
460 | WL1251_PART_DOWN_MEM_SIZE, | ||
461 | WL1251_PART_DOWN_REG_START, | ||
462 | WL1251_PART_DOWN_REG_SIZE); | ||
463 | |||
464 | /* And finally we upload the NVS tables */ | ||
465 | nvs_bytes_written = 0; | ||
466 | while (nvs_bytes_written < nvs_len) { | ||
467 | val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | ||
468 | | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); | ||
469 | |||
470 | val = cpu_to_le32(val); | ||
471 | |||
472 | wl1251_debug(DEBUG_BOOT, | ||
473 | "nvs write table 0x%x: 0x%x", | ||
474 | nvs_start, val); | ||
475 | wl1251_mem_write32(wl, nvs_start, val); | ||
476 | |||
477 | nvs_ptr += 4; | ||
478 | nvs_bytes_written += 4; | ||
479 | nvs_start += 4; | ||
480 | } | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | int wl1251_boot(struct wl1251 *wl) | ||
486 | { | ||
487 | int ret = 0, minor_minor_e2_ver; | ||
488 | u32 tmp, boot_data; | ||
489 | |||
490 | /* halt embedded ARM CPU while loading firmware */ | ||
491 | wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT); | ||
492 | |||
493 | ret = wl1251_boot_soft_reset(wl); | ||
494 | if (ret < 0) | ||
495 | goto out; | ||
496 | |||
497 | /* 2. start processing NVS file */ | ||
498 | if (wl->use_eeprom) { | ||
499 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); | ||
500 | /* Wait for EEPROM NVS burst read to complete */ | ||
501 | msleep(40); | ||
502 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | ||
503 | } else { | ||
504 | ret = wl1251_boot_upload_nvs(wl); | ||
505 | if (ret < 0) | ||
506 | goto out; | ||
507 | |||
508 | /* write firmware's last address (ie. it's length) to | ||
509 | * ACX_EEPROMLESS_IND_REG */ | ||
510 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); | ||
511 | } | ||
512 | |||
513 | /* 6. read the EEPROM parameters */ | ||
514 | tmp = wl1251_reg_read32(wl, SCR_PAD2); | ||
515 | |||
516 | /* 7. read bootdata */ | ||
517 | wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8; | ||
518 | wl->boot_attr.major = (tmp & 0x00FF0000) >> 16; | ||
519 | tmp = wl1251_reg_read32(wl, SCR_PAD3); | ||
520 | |||
521 | /* 8. check bootdata and call restart sequence */ | ||
522 | wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16; | ||
523 | minor_minor_e2_ver = (tmp & 0xFF000000) >> 24; | ||
524 | |||
525 | wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x " | ||
526 | "minorE2Ver 0x%x minor_minor_e2_ver 0x%x", | ||
527 | wl->boot_attr.radio_type, wl->boot_attr.major, | ||
528 | wl->boot_attr.minor, minor_minor_e2_ver); | ||
529 | |||
530 | ret = wl1251_boot_init_seq(wl); | ||
531 | if (ret < 0) | ||
532 | goto out; | ||
533 | |||
534 | /* 9. NVS processing done */ | ||
535 | boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL); | ||
536 | |||
537 | wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data); | ||
538 | |||
539 | /* 10. check that ECPU_CONTROL_HALT bits are set in | ||
540 | * pWhalBus->uBootData and start uploading firmware | ||
541 | */ | ||
542 | if ((boot_data & ECPU_CONTROL_HALT) == 0) { | ||
543 | wl1251_error("boot failed, ECPU_CONTROL_HALT not set"); | ||
544 | ret = -EIO; | ||
545 | goto out; | ||
546 | } | ||
547 | |||
548 | ret = wl1251_boot_upload_firmware(wl); | ||
549 | if (ret < 0) | ||
550 | goto out; | ||
551 | |||
552 | /* 10.5 start firmware */ | ||
553 | ret = wl1251_boot_run_firmware(wl); | ||
554 | if (ret < 0) | ||
555 | goto out; | ||
556 | |||
557 | out: | ||
558 | return ret; | ||
559 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h deleted file mode 100644 index 90063697e8f2..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_boot.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 __BOOT_H__ | ||
25 | #define __BOOT_H__ | ||
26 | |||
27 | #include "wl1251.h" | ||
28 | |||
29 | int wl1251_boot_soft_reset(struct wl1251 *wl); | ||
30 | int wl1251_boot_init_seq(struct wl1251 *wl); | ||
31 | int wl1251_boot_run_firmware(struct wl1251 *wl); | ||
32 | void wl1251_boot_target_enable_interrupts(struct wl1251 *wl); | ||
33 | int wl1251_boot(struct wl1251 *wl); | ||
34 | |||
35 | /* number of times we try to read the INIT interrupt */ | ||
36 | #define INIT_LOOP 20000 | ||
37 | |||
38 | /* delay between retries */ | ||
39 | #define INIT_LOOP_DELAY 50 | ||
40 | |||
41 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c deleted file mode 100644 index ce3722f4c3e3..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ /dev/null | |||
@@ -1,496 +0,0 @@ | |||
1 | #include "wl1251_cmd.h" | ||
2 | |||
3 | #include <linux/module.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/crc7.h> | ||
6 | |||
7 | #include "wl1251.h" | ||
8 | #include "wl1251_reg.h" | ||
9 | #include "wl1251_io.h" | ||
10 | #include "wl1251_ps.h" | ||
11 | #include "wl1251_acx.h" | ||
12 | |||
13 | /** | ||
14 | * send command to firmware | ||
15 | * | ||
16 | * @wl: wl struct | ||
17 | * @id: command id | ||
18 | * @buf: buffer containing the command, must work with dma | ||
19 | * @len: length of the buffer | ||
20 | */ | ||
21 | int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len) | ||
22 | { | ||
23 | struct wl1251_cmd_header *cmd; | ||
24 | unsigned long timeout; | ||
25 | u32 intr; | ||
26 | int ret = 0; | ||
27 | |||
28 | cmd = buf; | ||
29 | cmd->id = id; | ||
30 | cmd->status = 0; | ||
31 | |||
32 | WARN_ON(len % 4 != 0); | ||
33 | |||
34 | wl1251_mem_write(wl, wl->cmd_box_addr, buf, len); | ||
35 | |||
36 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | ||
37 | |||
38 | timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT); | ||
39 | |||
40 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | ||
41 | while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) { | ||
42 | if (time_after(jiffies, timeout)) { | ||
43 | wl1251_error("command complete timeout"); | ||
44 | ret = -ETIMEDOUT; | ||
45 | goto out; | ||
46 | } | ||
47 | |||
48 | msleep(1); | ||
49 | |||
50 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | ||
51 | } | ||
52 | |||
53 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, | ||
54 | WL1251_ACX_INTR_CMD_COMPLETE); | ||
55 | |||
56 | out: | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * send test command to firmware | ||
62 | * | ||
63 | * @wl: wl struct | ||
64 | * @buf: buffer containing the command, with all headers, must work with dma | ||
65 | * @len: length of the buffer | ||
66 | * @answer: is answer needed | ||
67 | */ | ||
68 | int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) | ||
69 | { | ||
70 | int ret; | ||
71 | |||
72 | wl1251_debug(DEBUG_CMD, "cmd test"); | ||
73 | |||
74 | ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len); | ||
75 | |||
76 | if (ret < 0) { | ||
77 | wl1251_warning("TEST command failed"); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | if (answer) { | ||
82 | struct wl1251_command *cmd_answer; | ||
83 | |||
84 | /* | ||
85 | * The test command got in, we can read the answer. | ||
86 | * The answer would be a wl1251_command, where the | ||
87 | * parameter array contains the actual answer. | ||
88 | */ | ||
89 | wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len); | ||
90 | |||
91 | cmd_answer = buf; | ||
92 | |||
93 | if (cmd_answer->header.status != CMD_STATUS_SUCCESS) | ||
94 | wl1251_error("TEST command answer error: %d", | ||
95 | cmd_answer->header.status); | ||
96 | } | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * read acx from firmware | ||
103 | * | ||
104 | * @wl: wl struct | ||
105 | * @id: acx id | ||
106 | * @buf: buffer for the response, including all headers, must work with dma | ||
107 | * @len: lenght of buf | ||
108 | */ | ||
109 | int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) | ||
110 | { | ||
111 | struct acx_header *acx = buf; | ||
112 | int ret; | ||
113 | |||
114 | wl1251_debug(DEBUG_CMD, "cmd interrogate"); | ||
115 | |||
116 | acx->id = id; | ||
117 | |||
118 | /* payload length, does not include any headers */ | ||
119 | acx->len = len - sizeof(*acx); | ||
120 | |||
121 | ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); | ||
122 | if (ret < 0) { | ||
123 | wl1251_error("INTERROGATE command failed"); | ||
124 | goto out; | ||
125 | } | ||
126 | |||
127 | /* the interrogate command got in, we can read the answer */ | ||
128 | wl1251_mem_read(wl, wl->cmd_box_addr, buf, len); | ||
129 | |||
130 | acx = buf; | ||
131 | if (acx->cmd.status != CMD_STATUS_SUCCESS) | ||
132 | wl1251_error("INTERROGATE command error: %d", | ||
133 | acx->cmd.status); | ||
134 | |||
135 | out: | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * write acx value to firmware | ||
141 | * | ||
142 | * @wl: wl struct | ||
143 | * @id: acx id | ||
144 | * @buf: buffer containing acx, including all headers, must work with dma | ||
145 | * @len: length of buf | ||
146 | */ | ||
147 | int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len) | ||
148 | { | ||
149 | struct acx_header *acx = buf; | ||
150 | int ret; | ||
151 | |||
152 | wl1251_debug(DEBUG_CMD, "cmd configure"); | ||
153 | |||
154 | acx->id = id; | ||
155 | |||
156 | /* payload length, does not include any headers */ | ||
157 | acx->len = len - sizeof(*acx); | ||
158 | |||
159 | ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len); | ||
160 | if (ret < 0) { | ||
161 | wl1251_warning("CONFIGURE command NOK"); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, | ||
169 | void *bitmap, u16 bitmap_len, u8 bitmap_control) | ||
170 | { | ||
171 | struct wl1251_cmd_vbm_update *vbm; | ||
172 | int ret; | ||
173 | |||
174 | wl1251_debug(DEBUG_CMD, "cmd vbm"); | ||
175 | |||
176 | vbm = kzalloc(sizeof(*vbm), GFP_KERNEL); | ||
177 | if (!vbm) { | ||
178 | ret = -ENOMEM; | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | /* Count and period will be filled by the target */ | ||
183 | vbm->tim.bitmap_ctrl = bitmap_control; | ||
184 | if (bitmap_len > PARTIAL_VBM_MAX) { | ||
185 | wl1251_warning("cmd vbm len is %d B, truncating to %d", | ||
186 | bitmap_len, PARTIAL_VBM_MAX); | ||
187 | bitmap_len = PARTIAL_VBM_MAX; | ||
188 | } | ||
189 | memcpy(vbm->tim.pvb_field, bitmap, bitmap_len); | ||
190 | vbm->tim.identity = identity; | ||
191 | vbm->tim.length = bitmap_len + 3; | ||
192 | |||
193 | vbm->len = cpu_to_le16(bitmap_len + 5); | ||
194 | |||
195 | ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm)); | ||
196 | if (ret < 0) { | ||
197 | wl1251_error("VBM command failed"); | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | out: | ||
202 | kfree(vbm); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | ||
207 | { | ||
208 | struct cmd_enabledisable_path *cmd; | ||
209 | int ret; | ||
210 | u16 cmd_rx, cmd_tx; | ||
211 | |||
212 | wl1251_debug(DEBUG_CMD, "cmd data path"); | ||
213 | |||
214 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
215 | if (!cmd) { | ||
216 | ret = -ENOMEM; | ||
217 | goto out; | ||
218 | } | ||
219 | |||
220 | cmd->channel = channel; | ||
221 | |||
222 | if (enable) { | ||
223 | cmd_rx = CMD_ENABLE_RX; | ||
224 | cmd_tx = CMD_ENABLE_TX; | ||
225 | } else { | ||
226 | cmd_rx = CMD_DISABLE_RX; | ||
227 | cmd_tx = CMD_DISABLE_TX; | ||
228 | } | ||
229 | |||
230 | ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); | ||
231 | if (ret < 0) { | ||
232 | wl1251_error("rx %s cmd for channel %d failed", | ||
233 | enable ? "start" : "stop", channel); | ||
234 | goto out; | ||
235 | } | ||
236 | |||
237 | wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", | ||
238 | enable ? "start" : "stop", channel); | ||
239 | |||
240 | ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); | ||
241 | if (ret < 0) { | ||
242 | wl1251_error("tx %s cmd for channel %d failed", | ||
243 | enable ? "start" : "stop", channel); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", | ||
248 | enable ? "start" : "stop", channel); | ||
249 | |||
250 | out: | ||
251 | kfree(cmd); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, | ||
256 | u16 beacon_interval, u8 dtim_interval) | ||
257 | { | ||
258 | struct cmd_join *join; | ||
259 | int ret, i; | ||
260 | u8 *bssid; | ||
261 | |||
262 | join = kzalloc(sizeof(*join), GFP_KERNEL); | ||
263 | if (!join) { | ||
264 | ret = -ENOMEM; | ||
265 | goto out; | ||
266 | } | ||
267 | |||
268 | wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d", | ||
269 | bss_type == BSS_TYPE_IBSS ? " ibss" : "", | ||
270 | channel, beacon_interval, dtim_interval); | ||
271 | |||
272 | /* Reverse order BSSID */ | ||
273 | bssid = (u8 *) &join->bssid_lsb; | ||
274 | for (i = 0; i < ETH_ALEN; i++) | ||
275 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; | ||
276 | |||
277 | join->rx_config_options = wl->rx_config; | ||
278 | join->rx_filter_options = wl->rx_filter; | ||
279 | |||
280 | /* | ||
281 | * FIXME: disable temporarily all filters because after commit | ||
282 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
283 | * association. The filter logic needs to be implemented properly | ||
284 | * and once that is done, this hack can be removed. | ||
285 | */ | ||
286 | join->rx_config_options = 0; | ||
287 | join->rx_filter_options = WL1251_DEFAULT_RX_FILTER; | ||
288 | |||
289 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | | ||
290 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; | ||
291 | |||
292 | join->beacon_interval = beacon_interval; | ||
293 | join->dtim_interval = dtim_interval; | ||
294 | join->bss_type = bss_type; | ||
295 | join->channel = channel; | ||
296 | join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; | ||
297 | |||
298 | ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); | ||
299 | if (ret < 0) { | ||
300 | wl1251_error("failed to initiate cmd join"); | ||
301 | goto out; | ||
302 | } | ||
303 | |||
304 | out: | ||
305 | kfree(join); | ||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) | ||
310 | { | ||
311 | struct wl1251_cmd_ps_params *ps_params = NULL; | ||
312 | int ret = 0; | ||
313 | |||
314 | wl1251_debug(DEBUG_CMD, "cmd set ps mode"); | ||
315 | |||
316 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); | ||
317 | if (!ps_params) { | ||
318 | ret = -ENOMEM; | ||
319 | goto out; | ||
320 | } | ||
321 | |||
322 | ps_params->ps_mode = ps_mode; | ||
323 | ps_params->send_null_data = 1; | ||
324 | ps_params->retries = 5; | ||
325 | ps_params->hang_over_period = 128; | ||
326 | ps_params->null_data_rate = 1; /* 1 Mbps */ | ||
327 | |||
328 | ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | ||
329 | sizeof(*ps_params)); | ||
330 | if (ret < 0) { | ||
331 | wl1251_error("cmd set_ps_mode failed"); | ||
332 | goto out; | ||
333 | } | ||
334 | |||
335 | out: | ||
336 | kfree(ps_params); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, | ||
341 | size_t len) | ||
342 | { | ||
343 | struct cmd_read_write_memory *cmd; | ||
344 | int ret = 0; | ||
345 | |||
346 | wl1251_debug(DEBUG_CMD, "cmd read memory"); | ||
347 | |||
348 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
349 | if (!cmd) { | ||
350 | ret = -ENOMEM; | ||
351 | goto out; | ||
352 | } | ||
353 | |||
354 | WARN_ON(len > MAX_READ_SIZE); | ||
355 | len = min_t(size_t, len, MAX_READ_SIZE); | ||
356 | |||
357 | cmd->addr = addr; | ||
358 | cmd->size = len; | ||
359 | |||
360 | ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); | ||
361 | if (ret < 0) { | ||
362 | wl1251_error("read memory command failed: %d", ret); | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | /* the read command got in, we can now read the answer */ | ||
367 | wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); | ||
368 | |||
369 | if (cmd->header.status != CMD_STATUS_SUCCESS) | ||
370 | wl1251_error("error in read command result: %d", | ||
371 | cmd->header.status); | ||
372 | |||
373 | memcpy(answer, cmd->value, len); | ||
374 | |||
375 | out: | ||
376 | kfree(cmd); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, | ||
381 | void *buf, size_t buf_len) | ||
382 | { | ||
383 | struct wl1251_cmd_packet_template *cmd; | ||
384 | size_t cmd_len; | ||
385 | int ret = 0; | ||
386 | |||
387 | wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id); | ||
388 | |||
389 | WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE); | ||
390 | buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE); | ||
391 | cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4); | ||
392 | |||
393 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
394 | if (!cmd) { | ||
395 | ret = -ENOMEM; | ||
396 | goto out; | ||
397 | } | ||
398 | |||
399 | cmd->size = cpu_to_le16(buf_len); | ||
400 | |||
401 | if (buf) | ||
402 | memcpy(cmd->data, buf, buf_len); | ||
403 | |||
404 | ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len); | ||
405 | if (ret < 0) { | ||
406 | wl1251_warning("cmd set_template failed: %d", ret); | ||
407 | goto out; | ||
408 | } | ||
409 | |||
410 | out: | ||
411 | kfree(cmd); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, | ||
416 | struct ieee80211_channel *channels[], | ||
417 | unsigned int n_channels, unsigned int n_probes) | ||
418 | { | ||
419 | struct wl1251_cmd_scan *cmd; | ||
420 | int i, ret = 0; | ||
421 | |||
422 | wl1251_debug(DEBUG_CMD, "cmd scan"); | ||
423 | |||
424 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
425 | if (!cmd) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); | ||
429 | cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | | ||
430 | CFG_RX_MGMT_EN | | ||
431 | CFG_RX_BCN_EN); | ||
432 | cmd->params.scan_options = 0; | ||
433 | cmd->params.num_channels = n_channels; | ||
434 | cmd->params.num_probe_requests = n_probes; | ||
435 | cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ | ||
436 | cmd->params.tid_trigger = 0; | ||
437 | |||
438 | for (i = 0; i < n_channels; i++) { | ||
439 | cmd->channels[i].min_duration = | ||
440 | cpu_to_le32(WL1251_SCAN_MIN_DURATION); | ||
441 | cmd->channels[i].max_duration = | ||
442 | cpu_to_le32(WL1251_SCAN_MAX_DURATION); | ||
443 | memset(&cmd->channels[i].bssid_lsb, 0xff, 4); | ||
444 | memset(&cmd->channels[i].bssid_msb, 0xff, 2); | ||
445 | cmd->channels[i].early_termination = 0; | ||
446 | cmd->channels[i].tx_power_att = 0; | ||
447 | cmd->channels[i].channel = channels[i]->hw_value; | ||
448 | } | ||
449 | |||
450 | cmd->params.ssid_len = ssid_len; | ||
451 | if (ssid) | ||
452 | memcpy(cmd->params.ssid, ssid, ssid_len); | ||
453 | |||
454 | ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); | ||
455 | if (ret < 0) { | ||
456 | wl1251_error("cmd scan failed: %d", ret); | ||
457 | goto out; | ||
458 | } | ||
459 | |||
460 | wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); | ||
461 | |||
462 | if (cmd->header.status != CMD_STATUS_SUCCESS) { | ||
463 | wl1251_error("cmd scan status wasn't success: %d", | ||
464 | cmd->header.status); | ||
465 | ret = -EIO; | ||
466 | goto out; | ||
467 | } | ||
468 | |||
469 | out: | ||
470 | kfree(cmd); | ||
471 | return ret; | ||
472 | } | ||
473 | |||
474 | int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) | ||
475 | { | ||
476 | struct wl1251_cmd_trigger_scan_to *cmd; | ||
477 | int ret; | ||
478 | |||
479 | wl1251_debug(DEBUG_CMD, "cmd trigger scan to"); | ||
480 | |||
481 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
482 | if (!cmd) | ||
483 | return -ENOMEM; | ||
484 | |||
485 | cmd->timeout = timeout; | ||
486 | |||
487 | ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd)); | ||
488 | if (ret < 0) { | ||
489 | wl1251_error("cmd trigger scan to failed: %d", ret); | ||
490 | goto out; | ||
491 | } | ||
492 | |||
493 | out: | ||
494 | kfree(cmd); | ||
495 | return ret; | ||
496 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h deleted file mode 100644 index a9e4991369be..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ /dev/null | |||
@@ -1,417 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_CMD_H__ | ||
26 | #define __WL1251_CMD_H__ | ||
27 | |||
28 | #include "wl1251.h" | ||
29 | |||
30 | #include <net/cfg80211.h> | ||
31 | |||
32 | struct acx_header; | ||
33 | |||
34 | int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); | ||
35 | int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer); | ||
36 | int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len); | ||
37 | int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len); | ||
38 | int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, | ||
39 | void *bitmap, u16 bitmap_len, u8 bitmap_control); | ||
40 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable); | ||
41 | int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, | ||
42 | u16 beacon_interval, u8 dtim_interval); | ||
43 | int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode); | ||
44 | int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, | ||
45 | size_t len); | ||
46 | int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, | ||
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); | ||
52 | |||
53 | /* unit ms */ | ||
54 | #define WL1251_COMMAND_TIMEOUT 2000 | ||
55 | |||
56 | enum wl1251_commands { | ||
57 | CMD_RESET = 0, | ||
58 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | ||
59 | CMD_CONFIGURE = 2, /*use this to write information elements*/ | ||
60 | CMD_ENABLE_RX = 3, | ||
61 | CMD_ENABLE_TX = 4, | ||
62 | CMD_DISABLE_RX = 5, | ||
63 | CMD_DISABLE_TX = 6, | ||
64 | CMD_SCAN = 8, | ||
65 | CMD_STOP_SCAN = 9, | ||
66 | CMD_VBM = 10, | ||
67 | CMD_START_JOIN = 11, | ||
68 | CMD_SET_KEYS = 12, | ||
69 | CMD_READ_MEMORY = 13, | ||
70 | CMD_WRITE_MEMORY = 14, | ||
71 | CMD_BEACON = 19, | ||
72 | CMD_PROBE_RESP = 20, | ||
73 | CMD_NULL_DATA = 21, | ||
74 | CMD_PROBE_REQ = 22, | ||
75 | CMD_TEST = 23, | ||
76 | CMD_RADIO_CALIBRATE = 25, /* OBSOLETE */ | ||
77 | CMD_ENABLE_RX_PATH = 27, /* OBSOLETE */ | ||
78 | CMD_NOISE_HIST = 28, | ||
79 | CMD_RX_RESET = 29, | ||
80 | CMD_PS_POLL = 30, | ||
81 | CMD_QOS_NULL_DATA = 31, | ||
82 | CMD_LNA_CONTROL = 32, | ||
83 | CMD_SET_BCN_MODE = 33, | ||
84 | CMD_MEASUREMENT = 34, | ||
85 | CMD_STOP_MEASUREMENT = 35, | ||
86 | CMD_DISCONNECT = 36, | ||
87 | CMD_SET_PS_MODE = 37, | ||
88 | CMD_CHANNEL_SWITCH = 38, | ||
89 | CMD_STOP_CHANNEL_SWICTH = 39, | ||
90 | CMD_AP_DISCOVERY = 40, | ||
91 | CMD_STOP_AP_DISCOVERY = 41, | ||
92 | CMD_SPS_SCAN = 42, | ||
93 | CMD_STOP_SPS_SCAN = 43, | ||
94 | CMD_HEALTH_CHECK = 45, | ||
95 | CMD_DEBUG = 46, | ||
96 | CMD_TRIGGER_SCAN_TO = 47, | ||
97 | |||
98 | NUM_COMMANDS, | ||
99 | MAX_COMMAND_ID = 0xFFFF, | ||
100 | }; | ||
101 | |||
102 | #define MAX_CMD_PARAMS 572 | ||
103 | |||
104 | struct wl1251_cmd_header { | ||
105 | u16 id; | ||
106 | u16 status; | ||
107 | /* payload */ | ||
108 | u8 data[0]; | ||
109 | } __packed; | ||
110 | |||
111 | struct wl1251_command { | ||
112 | struct wl1251_cmd_header header; | ||
113 | u8 parameters[MAX_CMD_PARAMS]; | ||
114 | }; | ||
115 | |||
116 | enum { | ||
117 | CMD_MAILBOX_IDLE = 0, | ||
118 | CMD_STATUS_SUCCESS = 1, | ||
119 | CMD_STATUS_UNKNOWN_CMD = 2, | ||
120 | CMD_STATUS_UNKNOWN_IE = 3, | ||
121 | CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11, | ||
122 | CMD_STATUS_RX_BUSY = 13, | ||
123 | CMD_STATUS_INVALID_PARAM = 14, | ||
124 | CMD_STATUS_TEMPLATE_TOO_LARGE = 15, | ||
125 | CMD_STATUS_OUT_OF_MEMORY = 16, | ||
126 | CMD_STATUS_STA_TABLE_FULL = 17, | ||
127 | CMD_STATUS_RADIO_ERROR = 18, | ||
128 | CMD_STATUS_WRONG_NESTING = 19, | ||
129 | CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ | ||
130 | CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ | ||
131 | MAX_COMMAND_STATUS = 0xff | ||
132 | }; | ||
133 | |||
134 | |||
135 | /* | ||
136 | * CMD_READ_MEMORY | ||
137 | * | ||
138 | * The host issues this command to read the WiLink device memory/registers. | ||
139 | * | ||
140 | * Note: The Base Band address has special handling (16 bits registers and | ||
141 | * addresses). For more information, see the hardware specification. | ||
142 | */ | ||
143 | /* | ||
144 | * CMD_WRITE_MEMORY | ||
145 | * | ||
146 | * The host issues this command to write the WiLink device memory/registers. | ||
147 | * | ||
148 | * The Base Band address has special handling (16 bits registers and | ||
149 | * addresses). For more information, see the hardware specification. | ||
150 | */ | ||
151 | #define MAX_READ_SIZE 256 | ||
152 | |||
153 | struct cmd_read_write_memory { | ||
154 | struct wl1251_cmd_header header; | ||
155 | |||
156 | /* The address of the memory to read from or write to.*/ | ||
157 | u32 addr; | ||
158 | |||
159 | /* The amount of data in bytes to read from or write to the WiLink | ||
160 | * device.*/ | ||
161 | u32 size; | ||
162 | |||
163 | /* The actual value read from or written to the Wilink. The source | ||
164 | of this field is the Host in WRITE command or the Wilink in READ | ||
165 | command. */ | ||
166 | u8 value[MAX_READ_SIZE]; | ||
167 | }; | ||
168 | |||
169 | #define CMDMBOX_HEADER_LEN 4 | ||
170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | ||
171 | |||
172 | #define WL1251_SCAN_MIN_DURATION 30000 | ||
173 | #define WL1251_SCAN_MAX_DURATION 60000 | ||
174 | |||
175 | #define WL1251_SCAN_NUM_PROBES 3 | ||
176 | |||
177 | struct wl1251_scan_parameters { | ||
178 | __le32 rx_config_options; | ||
179 | __le32 rx_filter_options; | ||
180 | |||
181 | /* | ||
182 | * Scan options: | ||
183 | * bit 0: When this bit is set, passive scan. | ||
184 | * bit 1: Band, when this bit is set we scan | ||
185 | * in the 5Ghz band. | ||
186 | * bit 2: voice mode, 0 for normal scan. | ||
187 | * bit 3: scan priority, 1 for high priority. | ||
188 | */ | ||
189 | __le16 scan_options; | ||
190 | |||
191 | /* Number of channels to scan */ | ||
192 | u8 num_channels; | ||
193 | |||
194 | /* Number opf probe requests to send, per channel */ | ||
195 | u8 num_probe_requests; | ||
196 | |||
197 | /* Rate and modulation for probe requests */ | ||
198 | __le16 tx_rate; | ||
199 | |||
200 | u8 tid_trigger; | ||
201 | u8 ssid_len; | ||
202 | u8 ssid[32]; | ||
203 | |||
204 | } __packed; | ||
205 | |||
206 | struct wl1251_scan_ch_parameters { | ||
207 | __le32 min_duration; /* in TU */ | ||
208 | __le32 max_duration; /* in TU */ | ||
209 | u32 bssid_lsb; | ||
210 | u16 bssid_msb; | ||
211 | |||
212 | /* | ||
213 | * bits 0-3: Early termination count. | ||
214 | * bits 4-5: Early termination condition. | ||
215 | */ | ||
216 | u8 early_termination; | ||
217 | |||
218 | u8 tx_power_att; | ||
219 | u8 channel; | ||
220 | u8 pad[3]; | ||
221 | } __packed; | ||
222 | |||
223 | /* SCAN parameters */ | ||
224 | #define SCAN_MAX_NUM_OF_CHANNELS 16 | ||
225 | |||
226 | struct wl1251_cmd_scan { | ||
227 | struct wl1251_cmd_header header; | ||
228 | |||
229 | struct wl1251_scan_parameters params; | ||
230 | struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; | ||
231 | } __packed; | ||
232 | |||
233 | enum { | ||
234 | BSS_TYPE_IBSS = 0, | ||
235 | BSS_TYPE_STA_BSS = 2, | ||
236 | BSS_TYPE_AP_BSS = 3, | ||
237 | MAX_BSS_TYPE = 0xFF | ||
238 | }; | ||
239 | |||
240 | #define JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ | ||
241 | #define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE 0x01 /* Early wakeup time */ | ||
242 | |||
243 | |||
244 | struct cmd_join { | ||
245 | struct wl1251_cmd_header header; | ||
246 | |||
247 | u32 bssid_lsb; | ||
248 | u16 bssid_msb; | ||
249 | u16 beacon_interval; /* in TBTTs */ | ||
250 | u32 rx_config_options; | ||
251 | u32 rx_filter_options; | ||
252 | |||
253 | /* | ||
254 | * The target uses this field to determine the rate at | ||
255 | * which to transmit control frame responses (such as | ||
256 | * ACK or CTS frames). | ||
257 | */ | ||
258 | u16 basic_rate_set; | ||
259 | u8 dtim_interval; | ||
260 | u8 tx_ctrl_frame_rate; /* OBSOLETE */ | ||
261 | u8 tx_ctrl_frame_mod; /* OBSOLETE */ | ||
262 | /* | ||
263 | * bits 0-2: This bitwise field specifies the type | ||
264 | * of BSS to start or join (BSS_TYPE_*). | ||
265 | * bit 4: Band - The radio band in which to join | ||
266 | * or start. | ||
267 | * 0 - 2.4GHz band | ||
268 | * 1 - 5GHz band | ||
269 | * bits 3, 5-7: Reserved | ||
270 | */ | ||
271 | u8 bss_type; | ||
272 | u8 channel; | ||
273 | u8 ssid_len; | ||
274 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
275 | u8 ctrl; /* JOIN_CMD_CTRL_* */ | ||
276 | u8 tx_mgt_frame_rate; /* OBSOLETE */ | ||
277 | u8 tx_mgt_frame_mod; /* OBSOLETE */ | ||
278 | u8 reserved; | ||
279 | } __packed; | ||
280 | |||
281 | struct cmd_enabledisable_path { | ||
282 | struct wl1251_cmd_header header; | ||
283 | |||
284 | u8 channel; | ||
285 | u8 padding[3]; | ||
286 | } __packed; | ||
287 | |||
288 | #define WL1251_MAX_TEMPLATE_SIZE 300 | ||
289 | |||
290 | struct wl1251_cmd_packet_template { | ||
291 | struct wl1251_cmd_header header; | ||
292 | |||
293 | __le16 size; | ||
294 | u8 data[0]; | ||
295 | } __packed; | ||
296 | |||
297 | #define TIM_ELE_ID 5 | ||
298 | #define PARTIAL_VBM_MAX 251 | ||
299 | |||
300 | struct wl1251_tim { | ||
301 | u8 identity; | ||
302 | u8 length; | ||
303 | u8 dtim_count; | ||
304 | u8 dtim_period; | ||
305 | u8 bitmap_ctrl; | ||
306 | u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ | ||
307 | } __packed; | ||
308 | |||
309 | /* Virtual Bit Map update */ | ||
310 | struct wl1251_cmd_vbm_update { | ||
311 | struct wl1251_cmd_header header; | ||
312 | __le16 len; | ||
313 | u8 padding[2]; | ||
314 | struct wl1251_tim tim; | ||
315 | } __packed; | ||
316 | |||
317 | enum wl1251_cmd_ps_mode { | ||
318 | STATION_ACTIVE_MODE, | ||
319 | STATION_POWER_SAVE_MODE | ||
320 | }; | ||
321 | |||
322 | struct wl1251_cmd_ps_params { | ||
323 | struct wl1251_cmd_header header; | ||
324 | |||
325 | u8 ps_mode; /* STATION_* */ | ||
326 | u8 send_null_data; /* Do we have to send NULL data packet ? */ | ||
327 | u8 retries; /* Number of retires for the initial NULL data packet */ | ||
328 | |||
329 | /* | ||
330 | * TUs during which the target stays awake after switching | ||
331 | * to power save mode. | ||
332 | */ | ||
333 | u8 hang_over_period; | ||
334 | u16 null_data_rate; | ||
335 | u8 pad[2]; | ||
336 | } __packed; | ||
337 | |||
338 | struct wl1251_cmd_trigger_scan_to { | ||
339 | struct wl1251_cmd_header header; | ||
340 | |||
341 | u32 timeout; | ||
342 | }; | ||
343 | |||
344 | /* HW encryption keys */ | ||
345 | #define NUM_ACCESS_CATEGORIES_COPY 4 | ||
346 | #define MAX_KEY_SIZE 32 | ||
347 | |||
348 | /* When set, disable HW encryption */ | ||
349 | #define DF_ENCRYPTION_DISABLE 0x01 | ||
350 | /* When set, disable HW decryption */ | ||
351 | #define DF_SNIFF_MODE_ENABLE 0x80 | ||
352 | |||
353 | enum wl1251_cmd_key_action { | ||
354 | KEY_ADD_OR_REPLACE = 1, | ||
355 | KEY_REMOVE = 2, | ||
356 | KEY_SET_ID = 3, | ||
357 | MAX_KEY_ACTION = 0xffff, | ||
358 | }; | ||
359 | |||
360 | enum wl1251_cmd_key_type { | ||
361 | KEY_WEP_DEFAULT = 0, | ||
362 | KEY_WEP_ADDR = 1, | ||
363 | KEY_AES_GROUP = 4, | ||
364 | KEY_AES_PAIRWISE = 5, | ||
365 | KEY_WEP_GROUP = 6, | ||
366 | KEY_TKIP_MIC_GROUP = 10, | ||
367 | KEY_TKIP_MIC_PAIRWISE = 11, | ||
368 | }; | ||
369 | |||
370 | /* | ||
371 | * | ||
372 | * key_type_e key size key format | ||
373 | * ---------- --------- ---------- | ||
374 | * 0x00 5, 13, 29 Key data | ||
375 | * 0x01 5, 13, 29 Key data | ||
376 | * 0x04 16 16 bytes of key data | ||
377 | * 0x05 16 16 bytes of key data | ||
378 | * 0x0a 32 16 bytes of TKIP key data | ||
379 | * 8 bytes of RX MIC key data | ||
380 | * 8 bytes of TX MIC key data | ||
381 | * 0x0b 32 16 bytes of TKIP key data | ||
382 | * 8 bytes of RX MIC key data | ||
383 | * 8 bytes of TX MIC key data | ||
384 | * | ||
385 | */ | ||
386 | |||
387 | struct wl1251_cmd_set_keys { | ||
388 | struct wl1251_cmd_header header; | ||
389 | |||
390 | /* Ignored for default WEP key */ | ||
391 | u8 addr[ETH_ALEN]; | ||
392 | |||
393 | /* key_action_e */ | ||
394 | u16 key_action; | ||
395 | |||
396 | u16 reserved_1; | ||
397 | |||
398 | /* key size in bytes */ | ||
399 | u8 key_size; | ||
400 | |||
401 | /* key_type_e */ | ||
402 | u8 key_type; | ||
403 | u8 ssid_profile; | ||
404 | |||
405 | /* | ||
406 | * TKIP, AES: frame's key id field. | ||
407 | * For WEP default key: key id; | ||
408 | */ | ||
409 | u8 id; | ||
410 | u8 reserved_2[6]; | ||
411 | u8 key[MAX_KEY_SIZE]; | ||
412 | u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; | ||
413 | u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | ||
414 | } __packed; | ||
415 | |||
416 | |||
417 | #endif /* __WL1251_CMD_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c deleted file mode 100644 index fa620a5e5303..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ /dev/null | |||
@@ -1,547 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 "wl1251_debugfs.h" | ||
25 | |||
26 | #include <linux/skbuff.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | #include "wl1251.h" | ||
30 | #include "wl1251_acx.h" | ||
31 | #include "wl1251_ps.h" | ||
32 | |||
33 | /* ms */ | ||
34 | #define WL1251_DEBUGFS_STATS_LIFETIME 1000 | ||
35 | |||
36 | /* debugfs macros idea from mac80211 */ | ||
37 | |||
38 | #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ | ||
39 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | ||
40 | size_t count, loff_t *ppos) \ | ||
41 | { \ | ||
42 | struct wl1251 *wl = file->private_data; \ | ||
43 | char buf[buflen]; \ | ||
44 | int res; \ | ||
45 | \ | ||
46 | res = scnprintf(buf, buflen, fmt "\n", ##value); \ | ||
47 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | ||
48 | } \ | ||
49 | \ | ||
50 | static const struct file_operations name## _ops = { \ | ||
51 | .read = name## _read, \ | ||
52 | .open = wl1251_open_file_generic, \ | ||
53 | .llseek = generic_file_llseek, \ | ||
54 | }; | ||
55 | |||
56 | #define DEBUGFS_ADD(name, parent) \ | ||
57 | wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ | ||
58 | wl, &name## _ops); \ | ||
59 | if (IS_ERR(wl->debugfs.name)) { \ | ||
60 | ret = PTR_ERR(wl->debugfs.name); \ | ||
61 | wl->debugfs.name = NULL; \ | ||
62 | goto out; \ | ||
63 | } | ||
64 | |||
65 | #define DEBUGFS_DEL(name) \ | ||
66 | do { \ | ||
67 | debugfs_remove(wl->debugfs.name); \ | ||
68 | wl->debugfs.name = NULL; \ | ||
69 | } while (0) | ||
70 | |||
71 | #define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ | ||
72 | static ssize_t sub## _ ##name## _read(struct file *file, \ | ||
73 | char __user *userbuf, \ | ||
74 | size_t count, loff_t *ppos) \ | ||
75 | { \ | ||
76 | struct wl1251 *wl = file->private_data; \ | ||
77 | char buf[buflen]; \ | ||
78 | int res; \ | ||
79 | \ | ||
80 | wl1251_debugfs_update_stats(wl); \ | ||
81 | \ | ||
82 | res = scnprintf(buf, buflen, fmt "\n", \ | ||
83 | wl->stats.fw_stats->sub.name); \ | ||
84 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ | ||
85 | } \ | ||
86 | \ | ||
87 | static const struct file_operations sub## _ ##name## _ops = { \ | ||
88 | .read = sub## _ ##name## _read, \ | ||
89 | .open = wl1251_open_file_generic, \ | ||
90 | .llseek = generic_file_llseek, \ | ||
91 | }; | ||
92 | |||
93 | #define DEBUGFS_FWSTATS_ADD(sub, name) \ | ||
94 | DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) | ||
95 | |||
96 | #define DEBUGFS_FWSTATS_DEL(sub, name) \ | ||
97 | DEBUGFS_DEL(sub## _ ##name) | ||
98 | |||
99 | static void wl1251_debugfs_update_stats(struct wl1251 *wl) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | mutex_lock(&wl->mutex); | ||
104 | |||
105 | ret = wl1251_ps_elp_wakeup(wl); | ||
106 | if (ret < 0) | ||
107 | goto out; | ||
108 | |||
109 | if (wl->state == WL1251_STATE_ON && | ||
110 | time_after(jiffies, wl->stats.fw_stats_update + | ||
111 | msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) { | ||
112 | wl1251_acx_statistics(wl, wl->stats.fw_stats); | ||
113 | wl->stats.fw_stats_update = jiffies; | ||
114 | } | ||
115 | |||
116 | wl1251_ps_elp_sleep(wl); | ||
117 | |||
118 | out: | ||
119 | mutex_unlock(&wl->mutex); | ||
120 | } | ||
121 | |||
122 | static int wl1251_open_file_generic(struct inode *inode, struct file *file) | ||
123 | { | ||
124 | file->private_data = inode->i_private; | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); | ||
129 | |||
130 | DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); | ||
131 | DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); | ||
132 | DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); | ||
133 | DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); | ||
134 | DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); | ||
135 | DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); | ||
136 | DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); | ||
137 | DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); | ||
138 | |||
139 | DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); | ||
140 | DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); | ||
141 | DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); | ||
142 | DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); | ||
143 | |||
144 | DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); | ||
145 | DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); | ||
146 | DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); | ||
147 | DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); | ||
148 | DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); | ||
149 | DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); | ||
150 | DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); | ||
151 | DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); | ||
152 | DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); | ||
153 | DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); | ||
154 | DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); | ||
155 | DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); | ||
156 | DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); | ||
157 | DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); | ||
158 | DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); | ||
159 | DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); | ||
160 | DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); | ||
161 | DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); | ||
162 | |||
163 | DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); | ||
164 | DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); | ||
165 | /* skipping wep.reserved */ | ||
166 | DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); | ||
167 | DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); | ||
168 | DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); | ||
169 | DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); | ||
170 | |||
171 | DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); | ||
172 | DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); | ||
173 | DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); | ||
174 | DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); | ||
175 | DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); | ||
176 | DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); | ||
177 | DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); | ||
178 | DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); | ||
179 | DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); | ||
180 | DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); | ||
181 | DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); | ||
182 | DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); | ||
183 | /* skipping cont_miss_bcns_spread for now */ | ||
184 | DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); | ||
185 | |||
186 | DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); | ||
187 | DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); | ||
188 | |||
189 | DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); | ||
190 | DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); | ||
191 | DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); | ||
192 | DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); | ||
193 | DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); | ||
194 | DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); | ||
195 | |||
196 | DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); | ||
197 | DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); | ||
198 | DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); | ||
199 | DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); | ||
200 | DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); | ||
201 | DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); | ||
202 | DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); | ||
203 | DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); | ||
204 | |||
205 | DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); | ||
206 | DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); | ||
207 | DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); | ||
208 | DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); | ||
209 | DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); | ||
210 | DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); | ||
211 | DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); | ||
212 | |||
213 | DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); | ||
214 | DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); | ||
215 | DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, | ||
216 | 20, "%u"); | ||
217 | DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); | ||
218 | DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); | ||
219 | |||
220 | DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); | ||
221 | DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", | ||
222 | wl->stats.excessive_retries); | ||
223 | |||
224 | static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct wl1251 *wl = file->private_data; | ||
228 | u32 queue_len; | ||
229 | char buf[20]; | ||
230 | int res; | ||
231 | |||
232 | queue_len = skb_queue_len(&wl->tx_queue); | ||
233 | |||
234 | res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); | ||
235 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | ||
236 | } | ||
237 | |||
238 | static const struct file_operations tx_queue_len_ops = { | ||
239 | .read = tx_queue_len_read, | ||
240 | .open = wl1251_open_file_generic, | ||
241 | .llseek = generic_file_llseek, | ||
242 | }; | ||
243 | |||
244 | static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, | ||
245 | size_t count, loff_t *ppos) | ||
246 | { | ||
247 | struct wl1251 *wl = file->private_data; | ||
248 | char buf[3], status; | ||
249 | int len; | ||
250 | |||
251 | if (wl->tx_queue_stopped) | ||
252 | status = 's'; | ||
253 | else | ||
254 | status = 'r'; | ||
255 | |||
256 | len = scnprintf(buf, sizeof(buf), "%c\n", status); | ||
257 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
258 | } | ||
259 | |||
260 | static const struct file_operations tx_queue_status_ops = { | ||
261 | .read = tx_queue_status_read, | ||
262 | .open = wl1251_open_file_generic, | ||
263 | .llseek = generic_file_llseek, | ||
264 | }; | ||
265 | |||
266 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) | ||
267 | { | ||
268 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | ||
269 | |||
270 | DEBUGFS_FWSTATS_DEL(rx, out_of_mem); | ||
271 | DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); | ||
272 | DEBUGFS_FWSTATS_DEL(rx, hw_stuck); | ||
273 | DEBUGFS_FWSTATS_DEL(rx, dropped); | ||
274 | DEBUGFS_FWSTATS_DEL(rx, fcs_err); | ||
275 | DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); | ||
276 | DEBUGFS_FWSTATS_DEL(rx, path_reset); | ||
277 | DEBUGFS_FWSTATS_DEL(rx, reset_counter); | ||
278 | |||
279 | DEBUGFS_FWSTATS_DEL(dma, rx_requested); | ||
280 | DEBUGFS_FWSTATS_DEL(dma, rx_errors); | ||
281 | DEBUGFS_FWSTATS_DEL(dma, tx_requested); | ||
282 | DEBUGFS_FWSTATS_DEL(dma, tx_errors); | ||
283 | |||
284 | DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); | ||
285 | DEBUGFS_FWSTATS_DEL(isr, fiqs); | ||
286 | DEBUGFS_FWSTATS_DEL(isr, rx_headers); | ||
287 | DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); | ||
288 | DEBUGFS_FWSTATS_DEL(isr, rx_rdys); | ||
289 | DEBUGFS_FWSTATS_DEL(isr, irqs); | ||
290 | DEBUGFS_FWSTATS_DEL(isr, tx_procs); | ||
291 | DEBUGFS_FWSTATS_DEL(isr, decrypt_done); | ||
292 | DEBUGFS_FWSTATS_DEL(isr, dma0_done); | ||
293 | DEBUGFS_FWSTATS_DEL(isr, dma1_done); | ||
294 | DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); | ||
295 | DEBUGFS_FWSTATS_DEL(isr, commands); | ||
296 | DEBUGFS_FWSTATS_DEL(isr, rx_procs); | ||
297 | DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); | ||
298 | DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); | ||
299 | DEBUGFS_FWSTATS_DEL(isr, pci_pm); | ||
300 | DEBUGFS_FWSTATS_DEL(isr, wakeups); | ||
301 | DEBUGFS_FWSTATS_DEL(isr, low_rssi); | ||
302 | |||
303 | DEBUGFS_FWSTATS_DEL(wep, addr_key_count); | ||
304 | DEBUGFS_FWSTATS_DEL(wep, default_key_count); | ||
305 | /* skipping wep.reserved */ | ||
306 | DEBUGFS_FWSTATS_DEL(wep, key_not_found); | ||
307 | DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); | ||
308 | DEBUGFS_FWSTATS_DEL(wep, packets); | ||
309 | DEBUGFS_FWSTATS_DEL(wep, interrupt); | ||
310 | |||
311 | DEBUGFS_FWSTATS_DEL(pwr, ps_enter); | ||
312 | DEBUGFS_FWSTATS_DEL(pwr, elp_enter); | ||
313 | DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); | ||
314 | DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); | ||
315 | DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); | ||
316 | DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); | ||
317 | DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); | ||
318 | DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); | ||
319 | DEBUGFS_FWSTATS_DEL(pwr, power_save_off); | ||
320 | DEBUGFS_FWSTATS_DEL(pwr, enable_ps); | ||
321 | DEBUGFS_FWSTATS_DEL(pwr, disable_ps); | ||
322 | DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); | ||
323 | /* skipping cont_miss_bcns_spread for now */ | ||
324 | DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); | ||
325 | |||
326 | DEBUGFS_FWSTATS_DEL(mic, rx_pkts); | ||
327 | DEBUGFS_FWSTATS_DEL(mic, calc_failure); | ||
328 | |||
329 | DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); | ||
330 | DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); | ||
331 | DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); | ||
332 | DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); | ||
333 | DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); | ||
334 | DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); | ||
335 | |||
336 | DEBUGFS_FWSTATS_DEL(event, heart_beat); | ||
337 | DEBUGFS_FWSTATS_DEL(event, calibration); | ||
338 | DEBUGFS_FWSTATS_DEL(event, rx_mismatch); | ||
339 | DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); | ||
340 | DEBUGFS_FWSTATS_DEL(event, rx_pool); | ||
341 | DEBUGFS_FWSTATS_DEL(event, oom_late); | ||
342 | DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); | ||
343 | DEBUGFS_FWSTATS_DEL(event, tx_stuck); | ||
344 | |||
345 | DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); | ||
346 | DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); | ||
347 | DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); | ||
348 | DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); | ||
349 | DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); | ||
350 | DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); | ||
351 | DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); | ||
352 | |||
353 | DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); | ||
354 | DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); | ||
355 | DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); | ||
356 | DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); | ||
357 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); | ||
358 | |||
359 | DEBUGFS_DEL(tx_queue_len); | ||
360 | DEBUGFS_DEL(tx_queue_status); | ||
361 | DEBUGFS_DEL(retry_count); | ||
362 | DEBUGFS_DEL(excessive_retries); | ||
363 | } | ||
364 | |||
365 | static int wl1251_debugfs_add_files(struct wl1251 *wl) | ||
366 | { | ||
367 | int ret = 0; | ||
368 | |||
369 | DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); | ||
370 | |||
371 | DEBUGFS_FWSTATS_ADD(rx, out_of_mem); | ||
372 | DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); | ||
373 | DEBUGFS_FWSTATS_ADD(rx, hw_stuck); | ||
374 | DEBUGFS_FWSTATS_ADD(rx, dropped); | ||
375 | DEBUGFS_FWSTATS_ADD(rx, fcs_err); | ||
376 | DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); | ||
377 | DEBUGFS_FWSTATS_ADD(rx, path_reset); | ||
378 | DEBUGFS_FWSTATS_ADD(rx, reset_counter); | ||
379 | |||
380 | DEBUGFS_FWSTATS_ADD(dma, rx_requested); | ||
381 | DEBUGFS_FWSTATS_ADD(dma, rx_errors); | ||
382 | DEBUGFS_FWSTATS_ADD(dma, tx_requested); | ||
383 | DEBUGFS_FWSTATS_ADD(dma, tx_errors); | ||
384 | |||
385 | DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); | ||
386 | DEBUGFS_FWSTATS_ADD(isr, fiqs); | ||
387 | DEBUGFS_FWSTATS_ADD(isr, rx_headers); | ||
388 | DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); | ||
389 | DEBUGFS_FWSTATS_ADD(isr, rx_rdys); | ||
390 | DEBUGFS_FWSTATS_ADD(isr, irqs); | ||
391 | DEBUGFS_FWSTATS_ADD(isr, tx_procs); | ||
392 | DEBUGFS_FWSTATS_ADD(isr, decrypt_done); | ||
393 | DEBUGFS_FWSTATS_ADD(isr, dma0_done); | ||
394 | DEBUGFS_FWSTATS_ADD(isr, dma1_done); | ||
395 | DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); | ||
396 | DEBUGFS_FWSTATS_ADD(isr, commands); | ||
397 | DEBUGFS_FWSTATS_ADD(isr, rx_procs); | ||
398 | DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); | ||
399 | DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); | ||
400 | DEBUGFS_FWSTATS_ADD(isr, pci_pm); | ||
401 | DEBUGFS_FWSTATS_ADD(isr, wakeups); | ||
402 | DEBUGFS_FWSTATS_ADD(isr, low_rssi); | ||
403 | |||
404 | DEBUGFS_FWSTATS_ADD(wep, addr_key_count); | ||
405 | DEBUGFS_FWSTATS_ADD(wep, default_key_count); | ||
406 | /* skipping wep.reserved */ | ||
407 | DEBUGFS_FWSTATS_ADD(wep, key_not_found); | ||
408 | DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); | ||
409 | DEBUGFS_FWSTATS_ADD(wep, packets); | ||
410 | DEBUGFS_FWSTATS_ADD(wep, interrupt); | ||
411 | |||
412 | DEBUGFS_FWSTATS_ADD(pwr, ps_enter); | ||
413 | DEBUGFS_FWSTATS_ADD(pwr, elp_enter); | ||
414 | DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); | ||
415 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); | ||
416 | DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); | ||
417 | DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); | ||
418 | DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); | ||
419 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); | ||
420 | DEBUGFS_FWSTATS_ADD(pwr, power_save_off); | ||
421 | DEBUGFS_FWSTATS_ADD(pwr, enable_ps); | ||
422 | DEBUGFS_FWSTATS_ADD(pwr, disable_ps); | ||
423 | DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); | ||
424 | /* skipping cont_miss_bcns_spread for now */ | ||
425 | DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); | ||
426 | |||
427 | DEBUGFS_FWSTATS_ADD(mic, rx_pkts); | ||
428 | DEBUGFS_FWSTATS_ADD(mic, calc_failure); | ||
429 | |||
430 | DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); | ||
431 | DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); | ||
432 | DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); | ||
433 | DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); | ||
434 | DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); | ||
435 | DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); | ||
436 | |||
437 | DEBUGFS_FWSTATS_ADD(event, heart_beat); | ||
438 | DEBUGFS_FWSTATS_ADD(event, calibration); | ||
439 | DEBUGFS_FWSTATS_ADD(event, rx_mismatch); | ||
440 | DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); | ||
441 | DEBUGFS_FWSTATS_ADD(event, rx_pool); | ||
442 | DEBUGFS_FWSTATS_ADD(event, oom_late); | ||
443 | DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); | ||
444 | DEBUGFS_FWSTATS_ADD(event, tx_stuck); | ||
445 | |||
446 | DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); | ||
447 | DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); | ||
448 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); | ||
449 | DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); | ||
450 | DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); | ||
451 | DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); | ||
452 | DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); | ||
453 | |||
454 | DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); | ||
455 | DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); | ||
456 | DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); | ||
457 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); | ||
458 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | ||
459 | |||
460 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); | ||
461 | DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); | ||
462 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | ||
463 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | ||
464 | |||
465 | out: | ||
466 | if (ret < 0) | ||
467 | wl1251_debugfs_delete_files(wl); | ||
468 | |||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | void wl1251_debugfs_reset(struct wl1251 *wl) | ||
473 | { | ||
474 | if (wl->stats.fw_stats != NULL) | ||
475 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); | ||
476 | wl->stats.retry_count = 0; | ||
477 | wl->stats.excessive_retries = 0; | ||
478 | } | ||
479 | |||
480 | int wl1251_debugfs_init(struct wl1251 *wl) | ||
481 | { | ||
482 | int ret; | ||
483 | |||
484 | wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
485 | |||
486 | if (IS_ERR(wl->debugfs.rootdir)) { | ||
487 | ret = PTR_ERR(wl->debugfs.rootdir); | ||
488 | wl->debugfs.rootdir = NULL; | ||
489 | goto err; | ||
490 | } | ||
491 | |||
492 | wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", | ||
493 | wl->debugfs.rootdir); | ||
494 | |||
495 | if (IS_ERR(wl->debugfs.fw_statistics)) { | ||
496 | ret = PTR_ERR(wl->debugfs.fw_statistics); | ||
497 | wl->debugfs.fw_statistics = NULL; | ||
498 | goto err_root; | ||
499 | } | ||
500 | |||
501 | wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), | ||
502 | GFP_KERNEL); | ||
503 | |||
504 | if (!wl->stats.fw_stats) { | ||
505 | ret = -ENOMEM; | ||
506 | goto err_fw; | ||
507 | } | ||
508 | |||
509 | wl->stats.fw_stats_update = jiffies; | ||
510 | |||
511 | ret = wl1251_debugfs_add_files(wl); | ||
512 | |||
513 | if (ret < 0) | ||
514 | goto err_file; | ||
515 | |||
516 | return 0; | ||
517 | |||
518 | err_file: | ||
519 | kfree(wl->stats.fw_stats); | ||
520 | wl->stats.fw_stats = NULL; | ||
521 | |||
522 | err_fw: | ||
523 | debugfs_remove(wl->debugfs.fw_statistics); | ||
524 | wl->debugfs.fw_statistics = NULL; | ||
525 | |||
526 | err_root: | ||
527 | debugfs_remove(wl->debugfs.rootdir); | ||
528 | wl->debugfs.rootdir = NULL; | ||
529 | |||
530 | err: | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | void wl1251_debugfs_exit(struct wl1251 *wl) | ||
535 | { | ||
536 | wl1251_debugfs_delete_files(wl); | ||
537 | |||
538 | kfree(wl->stats.fw_stats); | ||
539 | wl->stats.fw_stats = NULL; | ||
540 | |||
541 | debugfs_remove(wl->debugfs.fw_statistics); | ||
542 | wl->debugfs.fw_statistics = NULL; | ||
543 | |||
544 | debugfs_remove(wl->debugfs.rootdir); | ||
545 | wl->debugfs.rootdir = NULL; | ||
546 | |||
547 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h deleted file mode 100644 index 6dc3d080853c..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 WL1251_DEBUGFS_H | ||
25 | #define WL1251_DEBUGFS_H | ||
26 | |||
27 | #include "wl1251.h" | ||
28 | |||
29 | int wl1251_debugfs_init(struct wl1251 *wl); | ||
30 | void wl1251_debugfs_exit(struct wl1251 *wl); | ||
31 | void wl1251_debugfs_reset(struct wl1251 *wl); | ||
32 | |||
33 | #endif /* WL1251_DEBUGFS_H */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c deleted file mode 100644 index 020d764f9c13..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ /dev/null | |||
@@ -1,143 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "wl1251.h" | ||
26 | #include "wl1251_reg.h" | ||
27 | #include "wl1251_io.h" | ||
28 | #include "wl1251_event.h" | ||
29 | #include "wl1251_ps.h" | ||
30 | |||
31 | static int wl1251_event_scan_complete(struct wl1251 *wl, | ||
32 | struct event_mailbox *mbox) | ||
33 | { | ||
34 | wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", | ||
35 | mbox->scheduled_scan_status, | ||
36 | mbox->scheduled_scan_channels); | ||
37 | |||
38 | if (wl->scanning) { | ||
39 | mutex_unlock(&wl->mutex); | ||
40 | ieee80211_scan_completed(wl->hw, false); | ||
41 | mutex_lock(&wl->mutex); | ||
42 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); | ||
43 | wl->scanning = false; | ||
44 | } | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) | ||
50 | { | ||
51 | wl1251_debug(DEBUG_EVENT, "MBOX DUMP:"); | ||
52 | wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); | ||
53 | wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); | ||
54 | } | ||
55 | |||
56 | static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | ||
57 | { | ||
58 | int ret; | ||
59 | u32 vector; | ||
60 | |||
61 | wl1251_event_mbox_dump(mbox); | ||
62 | |||
63 | vector = mbox->events_vector & ~(mbox->events_mask); | ||
64 | wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector); | ||
65 | |||
66 | if (vector & SCAN_COMPLETE_EVENT_ID) { | ||
67 | ret = wl1251_event_scan_complete(wl, mbox); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | if (vector & BSS_LOSE_EVENT_ID) { | ||
73 | wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | ||
74 | |||
75 | if (wl->psm_requested && wl->psm) { | ||
76 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) { | ||
83 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); | ||
84 | |||
85 | /* indicate to the stack, that beacons have been lost */ | ||
86 | ieee80211_beacon_loss(wl->vif); | ||
87 | } | ||
88 | |||
89 | if (vector & REGAINED_BSS_EVENT_ID) { | ||
90 | if (wl->psm_requested) { | ||
91 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | int wl1251_event_unmask(struct wl1251 *wl) | ||
101 | { | ||
102 | int ret; | ||
103 | |||
104 | ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask)); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | void wl1251_event_mbox_config(struct wl1251 *wl) | ||
112 | { | ||
113 | wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); | ||
114 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | ||
115 | |||
116 | wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", | ||
117 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | ||
118 | } | ||
119 | |||
120 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) | ||
121 | { | ||
122 | struct event_mailbox mbox; | ||
123 | int ret; | ||
124 | |||
125 | wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); | ||
126 | |||
127 | if (mbox_num > 1) | ||
128 | return -EINVAL; | ||
129 | |||
130 | /* first we read the mbox descriptor */ | ||
131 | wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, | ||
132 | sizeof(struct event_mailbox)); | ||
133 | |||
134 | /* process the descriptor */ | ||
135 | ret = wl1251_event_process(wl, &mbox); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* then we let the firmware know it can go on...*/ | ||
140 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h deleted file mode 100644 index f48a2b66bc5a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ /dev/null | |||
@@ -1,121 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_EVENT_H__ | ||
26 | #define __WL1251_EVENT_H__ | ||
27 | |||
28 | /* | ||
29 | * Mbox events | ||
30 | * | ||
31 | * The event mechanism is based on a pair of event buffers (buffers A and | ||
32 | * B) at fixed locations in the target's memory. The host processes one | ||
33 | * buffer while the other buffer continues to collect events. If the host | ||
34 | * is not processing events, an interrupt is issued to signal that a buffer | ||
35 | * is ready. Once the host is done with processing events from one buffer, | ||
36 | * it signals the target (with an ACK interrupt) that the event buffer is | ||
37 | * free. | ||
38 | */ | ||
39 | |||
40 | enum { | ||
41 | RESERVED1_EVENT_ID = BIT(0), | ||
42 | RESERVED2_EVENT_ID = BIT(1), | ||
43 | MEASUREMENT_START_EVENT_ID = BIT(2), | ||
44 | SCAN_COMPLETE_EVENT_ID = BIT(3), | ||
45 | CALIBRATION_COMPLETE_EVENT_ID = BIT(4), | ||
46 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID = BIT(5), | ||
47 | PS_REPORT_EVENT_ID = BIT(6), | ||
48 | SYNCHRONIZATION_TIMEOUT_EVENT_ID = BIT(7), | ||
49 | HEALTH_REPORT_EVENT_ID = BIT(8), | ||
50 | ACI_DETECTION_EVENT_ID = BIT(9), | ||
51 | DEBUG_REPORT_EVENT_ID = BIT(10), | ||
52 | MAC_STATUS_EVENT_ID = BIT(11), | ||
53 | DISCONNECT_EVENT_COMPLETE_ID = BIT(12), | ||
54 | JOIN_EVENT_COMPLETE_ID = BIT(13), | ||
55 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(14), | ||
56 | BSS_LOSE_EVENT_ID = BIT(15), | ||
57 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(16), | ||
58 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(17), | ||
59 | AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(18), | ||
60 | SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(19), | ||
61 | PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(20), | ||
62 | RESET_BSS_EVENT_ID = BIT(21), | ||
63 | REGAINED_BSS_EVENT_ID = BIT(22), | ||
64 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID = BIT(23), | ||
65 | ROAMING_TRIGGER_LOW_SNR_EVENT_ID = BIT(24), | ||
66 | ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID = BIT(25), | ||
67 | |||
68 | DBG_EVENT_ID = BIT(26), | ||
69 | BT_PTA_SENSE_EVENT_ID = BIT(27), | ||
70 | BT_PTA_PREDICTION_EVENT_ID = BIT(28), | ||
71 | BT_PTA_AVALANCHE_EVENT_ID = BIT(29), | ||
72 | |||
73 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(30), | ||
74 | |||
75 | EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, | ||
76 | }; | ||
77 | |||
78 | struct event_debug_report { | ||
79 | u8 debug_event_id; | ||
80 | u8 num_params; | ||
81 | u16 pad; | ||
82 | u32 report_1; | ||
83 | u32 report_2; | ||
84 | u32 report_3; | ||
85 | } __packed; | ||
86 | |||
87 | struct event_mailbox { | ||
88 | u32 events_vector; | ||
89 | u32 events_mask; | ||
90 | u32 reserved_1; | ||
91 | u32 reserved_2; | ||
92 | |||
93 | char average_rssi_level; | ||
94 | u8 ps_status; | ||
95 | u8 channel_switch_status; | ||
96 | u8 scheduled_scan_status; | ||
97 | |||
98 | /* Channels scanned by the scheduled scan */ | ||
99 | u16 scheduled_scan_channels; | ||
100 | |||
101 | /* If bit 0 is set -> target's fatal error */ | ||
102 | u16 health_report; | ||
103 | u16 bad_fft_counter; | ||
104 | u8 bt_pta_sense_info; | ||
105 | u8 bt_pta_protective_info; | ||
106 | u32 reserved; | ||
107 | u32 debug_report[2]; | ||
108 | |||
109 | /* Number of FCS errors since last event */ | ||
110 | u32 fcs_err_counter; | ||
111 | |||
112 | struct event_debug_report report; | ||
113 | u8 average_snr_level; | ||
114 | u8 padding[19]; | ||
115 | } __packed; | ||
116 | |||
117 | int wl1251_event_unmask(struct wl1251 *wl); | ||
118 | void wl1251_event_mbox_config(struct wl1251 *wl); | ||
119 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); | ||
120 | |||
121 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c deleted file mode 100644 index b538bdd7b320..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ /dev/null | |||
@@ -1,425 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #include "wl1251_init.h" | ||
29 | #include "wl12xx_80211.h" | ||
30 | #include "wl1251_acx.h" | ||
31 | #include "wl1251_cmd.h" | ||
32 | #include "wl1251_reg.h" | ||
33 | |||
34 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl) | ||
35 | { | ||
36 | int ret; | ||
37 | |||
38 | ret = wl1251_acx_feature_cfg(wl); | ||
39 | if (ret < 0) { | ||
40 | wl1251_warning("couldn't set feature config"); | ||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | ret = wl1251_acx_default_key(wl, wl->default_key); | ||
45 | if (ret < 0) { | ||
46 | wl1251_warning("couldn't set default key"); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int wl1251_hw_init_templates_config(struct wl1251 *wl) | ||
54 | { | ||
55 | int ret; | ||
56 | u8 partial_vbm[PARTIAL_VBM_MAX]; | ||
57 | |||
58 | /* send empty templates for fw memory reservation */ | ||
59 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL, | ||
60 | sizeof(struct wl12xx_probe_req_template)); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL, | ||
65 | sizeof(struct wl12xx_null_data_template)); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL, | ||
70 | sizeof(struct wl12xx_ps_poll_template)); | ||
71 | if (ret < 0) | ||
72 | return ret; | ||
73 | |||
74 | ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL, | ||
75 | sizeof | ||
76 | (struct wl12xx_qos_null_data_template)); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | |||
80 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL, | ||
81 | sizeof | ||
82 | (struct wl12xx_probe_resp_template)); | ||
83 | if (ret < 0) | ||
84 | return ret; | ||
85 | |||
86 | ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL, | ||
87 | sizeof | ||
88 | (struct wl12xx_beacon_template)); | ||
89 | if (ret < 0) | ||
90 | return ret; | ||
91 | |||
92 | /* tim templates, first reserve space then allocate an empty one */ | ||
93 | memset(partial_vbm, 0, PARTIAL_VBM_MAX); | ||
94 | ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | |||
98 | ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter) | ||
106 | { | ||
107 | int ret; | ||
108 | |||
109 | ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); | ||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | |||
113 | ret = wl1251_acx_rx_config(wl, config, filter); | ||
114 | if (ret < 0) | ||
115 | return ret; | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int wl1251_hw_init_phy_config(struct wl1251 *wl) | ||
121 | { | ||
122 | int ret; | ||
123 | |||
124 | ret = wl1251_acx_pd_threshold(wl); | ||
125 | if (ret < 0) | ||
126 | return ret; | ||
127 | |||
128 | ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME); | ||
129 | if (ret < 0) | ||
130 | return ret; | ||
131 | |||
132 | ret = wl1251_acx_group_address_tbl(wl); | ||
133 | if (ret < 0) | ||
134 | return ret; | ||
135 | |||
136 | ret = wl1251_acx_service_period_timeout(wl); | ||
137 | if (ret < 0) | ||
138 | return ret; | ||
139 | |||
140 | ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); | ||
141 | if (ret < 0) | ||
142 | return ret; | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | int wl1251_hw_init_beacon_filter(struct wl1251 *wl) | ||
148 | { | ||
149 | int ret; | ||
150 | |||
151 | /* disable beacon filtering at this stage */ | ||
152 | ret = wl1251_acx_beacon_filter_opt(wl, false); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | ret = wl1251_acx_beacon_filter_table(wl); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | int wl1251_hw_init_pta(struct wl1251 *wl) | ||
164 | { | ||
165 | int ret; | ||
166 | |||
167 | ret = wl1251_acx_sg_enable(wl); | ||
168 | if (ret < 0) | ||
169 | return ret; | ||
170 | |||
171 | ret = wl1251_acx_sg_cfg(wl); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | int wl1251_hw_init_energy_detection(struct wl1251 *wl) | ||
179 | { | ||
180 | int ret; | ||
181 | |||
182 | ret = wl1251_acx_cca_threshold(wl); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl) | ||
190 | { | ||
191 | int ret; | ||
192 | |||
193 | ret = wl1251_acx_bcn_dtim_options(wl); | ||
194 | if (ret < 0) | ||
195 | return ret; | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | int wl1251_hw_init_power_auth(struct wl1251 *wl) | ||
201 | { | ||
202 | return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); | ||
203 | } | ||
204 | |||
205 | int wl1251_hw_init_mem_config(struct wl1251 *wl) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | ret = wl1251_acx_mem_cfg(wl); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), | ||
214 | GFP_KERNEL); | ||
215 | if (!wl->target_mem_map) { | ||
216 | wl1251_error("couldn't allocate target memory map"); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | /* we now ask for the firmware built memory map */ | ||
221 | ret = wl1251_acx_mem_map(wl, wl->target_mem_map, | ||
222 | sizeof(struct wl1251_acx_mem_map)); | ||
223 | if (ret < 0) { | ||
224 | wl1251_error("couldn't retrieve firmware memory map"); | ||
225 | kfree(wl->target_mem_map); | ||
226 | wl->target_mem_map = NULL; | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int wl1251_hw_init_txq_fill(u8 qid, | ||
234 | struct acx_tx_queue_qos_config *config, | ||
235 | u32 num_blocks) | ||
236 | { | ||
237 | config->qid = qid; | ||
238 | |||
239 | switch (qid) { | ||
240 | case QOS_AC_BE: | ||
241 | config->high_threshold = | ||
242 | (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; | ||
243 | config->low_threshold = | ||
244 | (QOS_TX_LOW_BE_DEF * num_blocks) / 100; | ||
245 | break; | ||
246 | case QOS_AC_BK: | ||
247 | config->high_threshold = | ||
248 | (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; | ||
249 | config->low_threshold = | ||
250 | (QOS_TX_LOW_BK_DEF * num_blocks) / 100; | ||
251 | break; | ||
252 | case QOS_AC_VI: | ||
253 | config->high_threshold = | ||
254 | (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; | ||
255 | config->low_threshold = | ||
256 | (QOS_TX_LOW_VI_DEF * num_blocks) / 100; | ||
257 | break; | ||
258 | case QOS_AC_VO: | ||
259 | config->high_threshold = | ||
260 | (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; | ||
261 | config->low_threshold = | ||
262 | (QOS_TX_LOW_VO_DEF * num_blocks) / 100; | ||
263 | break; | ||
264 | default: | ||
265 | wl1251_error("Invalid TX queue id: %d", qid); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) | ||
273 | { | ||
274 | struct acx_tx_queue_qos_config *config; | ||
275 | struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; | ||
276 | int ret, i; | ||
277 | |||
278 | wl1251_debug(DEBUG_ACX, "acx tx queue config"); | ||
279 | |||
280 | config = kzalloc(sizeof(*config), GFP_KERNEL); | ||
281 | if (!config) { | ||
282 | ret = -ENOMEM; | ||
283 | goto out; | ||
284 | } | ||
285 | |||
286 | for (i = 0; i < MAX_NUM_OF_AC; i++) { | ||
287 | ret = wl1251_hw_init_txq_fill(i, config, | ||
288 | wl_mem_map->num_tx_mem_blocks); | ||
289 | if (ret < 0) | ||
290 | goto out; | ||
291 | |||
292 | ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG, | ||
293 | config, sizeof(*config)); | ||
294 | if (ret < 0) | ||
295 | goto out; | ||
296 | } | ||
297 | |||
298 | wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); | ||
299 | wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); | ||
300 | wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); | ||
301 | wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); | ||
302 | |||
303 | out: | ||
304 | kfree(config); | ||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static int wl1251_hw_init_data_path_config(struct wl1251 *wl) | ||
309 | { | ||
310 | int ret; | ||
311 | |||
312 | /* asking for the data path parameters */ | ||
313 | wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), | ||
314 | GFP_KERNEL); | ||
315 | if (!wl->data_path) { | ||
316 | wl1251_error("Couldnt allocate data path parameters"); | ||
317 | return -ENOMEM; | ||
318 | } | ||
319 | |||
320 | ret = wl1251_acx_data_path_params(wl, wl->data_path); | ||
321 | if (ret < 0) { | ||
322 | kfree(wl->data_path); | ||
323 | wl->data_path = NULL; | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | |||
331 | int wl1251_hw_init(struct wl1251 *wl) | ||
332 | { | ||
333 | struct wl1251_acx_mem_map *wl_mem_map; | ||
334 | int ret; | ||
335 | |||
336 | ret = wl1251_hw_init_hwenc_config(wl); | ||
337 | if (ret < 0) | ||
338 | return ret; | ||
339 | |||
340 | /* Template settings */ | ||
341 | ret = wl1251_hw_init_templates_config(wl); | ||
342 | if (ret < 0) | ||
343 | return ret; | ||
344 | |||
345 | /* Default memory configuration */ | ||
346 | ret = wl1251_hw_init_mem_config(wl); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | /* Default data path configuration */ | ||
351 | ret = wl1251_hw_init_data_path_config(wl); | ||
352 | if (ret < 0) | ||
353 | goto out_free_memmap; | ||
354 | |||
355 | /* RX config */ | ||
356 | ret = wl1251_hw_init_rx_config(wl, | ||
357 | RX_CFG_PROMISCUOUS | RX_CFG_TSF, | ||
358 | RX_FILTER_OPTION_DEF); | ||
359 | /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, | ||
360 | RX_FILTER_OPTION_FILTER_ALL); */ | ||
361 | if (ret < 0) | ||
362 | goto out_free_data_path; | ||
363 | |||
364 | /* TX queues config */ | ||
365 | ret = wl1251_hw_init_tx_queue_config(wl); | ||
366 | if (ret < 0) | ||
367 | goto out_free_data_path; | ||
368 | |||
369 | /* PHY layer config */ | ||
370 | ret = wl1251_hw_init_phy_config(wl); | ||
371 | if (ret < 0) | ||
372 | goto out_free_data_path; | ||
373 | |||
374 | /* Initialize connection monitoring thresholds */ | ||
375 | ret = wl1251_acx_conn_monit_params(wl); | ||
376 | if (ret < 0) | ||
377 | goto out_free_data_path; | ||
378 | |||
379 | /* Beacon filtering */ | ||
380 | ret = wl1251_hw_init_beacon_filter(wl); | ||
381 | if (ret < 0) | ||
382 | goto out_free_data_path; | ||
383 | |||
384 | /* Bluetooth WLAN coexistence */ | ||
385 | ret = wl1251_hw_init_pta(wl); | ||
386 | if (ret < 0) | ||
387 | goto out_free_data_path; | ||
388 | |||
389 | /* Energy detection */ | ||
390 | ret = wl1251_hw_init_energy_detection(wl); | ||
391 | if (ret < 0) | ||
392 | goto out_free_data_path; | ||
393 | |||
394 | /* Beacons and boradcast settings */ | ||
395 | ret = wl1251_hw_init_beacon_broadcast(wl); | ||
396 | if (ret < 0) | ||
397 | goto out_free_data_path; | ||
398 | |||
399 | /* Enable data path */ | ||
400 | ret = wl1251_cmd_data_path(wl, wl->channel, 1); | ||
401 | if (ret < 0) | ||
402 | goto out_free_data_path; | ||
403 | |||
404 | /* Default power state */ | ||
405 | ret = wl1251_hw_init_power_auth(wl); | ||
406 | if (ret < 0) | ||
407 | goto out_free_data_path; | ||
408 | |||
409 | wl_mem_map = wl->target_mem_map; | ||
410 | wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", | ||
411 | wl_mem_map->num_tx_mem_blocks, | ||
412 | wl->data_path->tx_control_addr, | ||
413 | wl_mem_map->num_rx_mem_blocks, | ||
414 | wl->data_path->rx_control_addr); | ||
415 | |||
416 | return 0; | ||
417 | |||
418 | out_free_data_path: | ||
419 | kfree(wl->data_path); | ||
420 | |||
421 | out_free_memmap: | ||
422 | kfree(wl->target_mem_map); | ||
423 | |||
424 | return ret; | ||
425 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h deleted file mode 100644 index 269cefb3e7d4..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 __WL1251_INIT_H__ | ||
25 | #define __WL1251_INIT_H__ | ||
26 | |||
27 | #include "wl1251.h" | ||
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 | |||
76 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); | ||
77 | int wl1251_hw_init_templates_config(struct wl1251 *wl); | ||
78 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); | ||
79 | int wl1251_hw_init_phy_config(struct wl1251 *wl); | ||
80 | int wl1251_hw_init_beacon_filter(struct wl1251 *wl); | ||
81 | int wl1251_hw_init_pta(struct wl1251 *wl); | ||
82 | int wl1251_hw_init_energy_detection(struct wl1251 *wl); | ||
83 | int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl); | ||
84 | int wl1251_hw_init_power_auth(struct wl1251 *wl); | ||
85 | int wl1251_hw_init_mem_config(struct wl1251 *wl); | ||
86 | int wl1251_hw_init(struct wl1251 *wl); | ||
87 | |||
88 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c deleted file mode 100644 index f1c232e0887f..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_io.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 "wl1251.h" | ||
25 | #include "wl1251_reg.h" | ||
26 | #include "wl1251_io.h" | ||
27 | |||
28 | /* FIXME: this is static data nowadays and the table can be removed */ | ||
29 | static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = { | ||
30 | [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474), | ||
31 | [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478), | ||
32 | [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494), | ||
33 | [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498), | ||
34 | [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C), | ||
35 | [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0), | ||
36 | [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4), | ||
37 | [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8), | ||
38 | [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000), | ||
39 | [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C), | ||
40 | [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804) | ||
41 | }; | ||
42 | |||
43 | static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr) | ||
44 | { | ||
45 | /* If the address is lower than REGISTERS_BASE, it means that this is | ||
46 | * a chip-specific register address, so look it up in the registers | ||
47 | * table */ | ||
48 | if (addr < REGISTERS_BASE) { | ||
49 | /* Make sure we don't go over the table */ | ||
50 | if (addr >= ACX_REG_TABLE_LEN) { | ||
51 | wl1251_error("address out of range (%d)", addr); | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | addr = wl1251_io_reg_table[addr]; | ||
55 | } | ||
56 | |||
57 | return addr - wl->physical_reg_addr + wl->virtual_reg_addr; | ||
58 | } | ||
59 | |||
60 | static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr) | ||
61 | { | ||
62 | return addr - wl->physical_mem_addr + wl->virtual_mem_addr; | ||
63 | } | ||
64 | |||
65 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len) | ||
66 | { | ||
67 | int physical; | ||
68 | |||
69 | physical = wl1251_translate_mem_addr(wl, addr); | ||
70 | |||
71 | wl->if_ops->read(wl, physical, buf, len); | ||
72 | } | ||
73 | |||
74 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len) | ||
75 | { | ||
76 | int physical; | ||
77 | |||
78 | physical = wl1251_translate_mem_addr(wl, addr); | ||
79 | |||
80 | wl->if_ops->write(wl, physical, buf, len); | ||
81 | } | ||
82 | |||
83 | u32 wl1251_mem_read32(struct wl1251 *wl, int addr) | ||
84 | { | ||
85 | return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr)); | ||
86 | } | ||
87 | |||
88 | void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val) | ||
89 | { | ||
90 | wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val); | ||
91 | } | ||
92 | |||
93 | u32 wl1251_reg_read32(struct wl1251 *wl, int addr) | ||
94 | { | ||
95 | return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr)); | ||
96 | } | ||
97 | |||
98 | void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val) | ||
99 | { | ||
100 | wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val); | ||
101 | } | ||
102 | |||
103 | /* Set the partitions to access the chip addresses. | ||
104 | * | ||
105 | * There are two VIRTUAL partitions (the memory partition and the | ||
106 | * registers partition), which are mapped to two different areas of the | ||
107 | * PHYSICAL (hardware) memory. This function also makes other checks to | ||
108 | * ensure that the partitions are not overlapping. In the diagram below, the | ||
109 | * memory partition comes before the register partition, but the opposite is | ||
110 | * also supported. | ||
111 | * | ||
112 | * PHYSICAL address | ||
113 | * space | ||
114 | * | ||
115 | * | | | ||
116 | * ...+----+--> mem_start | ||
117 | * VIRTUAL address ... | | | ||
118 | * space ... | | [PART_0] | ||
119 | * ... | | | ||
120 | * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size | ||
121 | * | | ... | | | ||
122 | * |MEM | ... | | | ||
123 | * | | ... | | | ||
124 | * part_size <--+----+... | | {unused area) | ||
125 | * | | ... | | | ||
126 | * |REG | ... | | | ||
127 | * part_size | | ... | | | ||
128 | * + <--+----+... ...+----+--> reg_start | ||
129 | * reg_size ... | | | ||
130 | * ... | | [PART_1] | ||
131 | * ... | | | ||
132 | * ...+----+--> reg_start + reg_size | ||
133 | * | | | ||
134 | * | ||
135 | */ | ||
136 | void wl1251_set_partition(struct wl1251 *wl, | ||
137 | u32 mem_start, u32 mem_size, | ||
138 | u32 reg_start, u32 reg_size) | ||
139 | { | ||
140 | struct wl1251_partition partition[2]; | ||
141 | |||
142 | wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
143 | mem_start, mem_size); | ||
144 | wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
145 | reg_start, reg_size); | ||
146 | |||
147 | /* Make sure that the two partitions together don't exceed the | ||
148 | * address range */ | ||
149 | if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { | ||
150 | wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual" | ||
151 | " address range. Truncating partition[0]."); | ||
152 | mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; | ||
153 | wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
154 | mem_start, mem_size); | ||
155 | wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
156 | reg_start, reg_size); | ||
157 | } | ||
158 | |||
159 | if ((mem_start < reg_start) && | ||
160 | ((mem_start + mem_size) > reg_start)) { | ||
161 | /* Guarantee that the memory partition doesn't overlap the | ||
162 | * registers partition */ | ||
163 | wl1251_debug(DEBUG_SPI, "End of partition[0] is " | ||
164 | "overlapping partition[1]. Adjusted."); | ||
165 | mem_size = reg_start - mem_start; | ||
166 | wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
167 | mem_start, mem_size); | ||
168 | wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
169 | reg_start, reg_size); | ||
170 | } else if ((reg_start < mem_start) && | ||
171 | ((reg_start + reg_size) > mem_start)) { | ||
172 | /* Guarantee that the register partition doesn't overlap the | ||
173 | * memory partition */ | ||
174 | wl1251_debug(DEBUG_SPI, "End of partition[1] is" | ||
175 | " overlapping partition[0]. Adjusted."); | ||
176 | reg_size = mem_start - reg_start; | ||
177 | wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
178 | mem_start, mem_size); | ||
179 | wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
180 | reg_start, reg_size); | ||
181 | } | ||
182 | |||
183 | partition[0].start = mem_start; | ||
184 | partition[0].size = mem_size; | ||
185 | partition[1].start = reg_start; | ||
186 | partition[1].size = reg_size; | ||
187 | |||
188 | wl->physical_mem_addr = mem_start; | ||
189 | wl->physical_reg_addr = reg_start; | ||
190 | |||
191 | wl->virtual_mem_addr = 0; | ||
192 | wl->virtual_reg_addr = mem_size; | ||
193 | |||
194 | wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition, | ||
195 | sizeof(partition)); | ||
196 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h deleted file mode 100644 index c545e9d5f512..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_io.h +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | #ifndef __WL1251_IO_H__ | ||
22 | #define __WL1251_IO_H__ | ||
23 | |||
24 | #include "wl1251.h" | ||
25 | |||
26 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | ||
27 | |||
28 | #define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0 | ||
29 | #define HW_ACCESS_PART0_START_ADDR 0x1FFC4 | ||
30 | #define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8 | ||
31 | #define HW_ACCESS_PART1_START_ADDR 0x1FFCC | ||
32 | |||
33 | #define HW_ACCESS_REGISTER_SIZE 4 | ||
34 | |||
35 | #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 | ||
36 | |||
37 | static inline u32 wl1251_read32(struct wl1251 *wl, int addr) | ||
38 | { | ||
39 | u32 response; | ||
40 | |||
41 | wl->if_ops->read(wl, addr, &response, sizeof(u32)); | ||
42 | |||
43 | return response; | ||
44 | } | ||
45 | |||
46 | static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) | ||
47 | { | ||
48 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | ||
49 | } | ||
50 | |||
51 | static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) | ||
52 | { | ||
53 | u32 response; | ||
54 | |||
55 | if (wl->if_ops->read_elp) | ||
56 | wl->if_ops->read_elp(wl, addr, &response); | ||
57 | else | ||
58 | wl->if_ops->read(wl, addr, &response, sizeof(u32)); | ||
59 | |||
60 | return response; | ||
61 | } | ||
62 | |||
63 | static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
64 | { | ||
65 | if (wl->if_ops->write_elp) | ||
66 | wl->if_ops->write_elp(wl, addr, val); | ||
67 | else | ||
68 | wl->if_ops->write(wl, addr, &val, sizeof(u32)); | ||
69 | } | ||
70 | |||
71 | /* Memory target IO, address is translated to partition 0 */ | ||
72 | void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); | ||
73 | void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); | ||
74 | u32 wl1251_mem_read32(struct wl1251 *wl, int addr); | ||
75 | void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val); | ||
76 | /* Registers IO */ | ||
77 | u32 wl1251_reg_read32(struct wl1251 *wl, int addr); | ||
78 | void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val); | ||
79 | |||
80 | void wl1251_set_partition(struct wl1251 *wl, | ||
81 | u32 part_start, u32 part_size, | ||
82 | u32 reg_start, u32 reg_size); | ||
83 | |||
84 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c deleted file mode 100644 index 861a5f33761e..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ /dev/null | |||
@@ -1,1442 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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/module.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/firmware.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/crc32.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/vmalloc.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | #include "wl1251.h" | ||
35 | #include "wl12xx_80211.h" | ||
36 | #include "wl1251_reg.h" | ||
37 | #include "wl1251_io.h" | ||
38 | #include "wl1251_cmd.h" | ||
39 | #include "wl1251_event.h" | ||
40 | #include "wl1251_tx.h" | ||
41 | #include "wl1251_rx.h" | ||
42 | #include "wl1251_ps.h" | ||
43 | #include "wl1251_init.h" | ||
44 | #include "wl1251_debugfs.h" | ||
45 | #include "wl1251_boot.h" | ||
46 | |||
47 | void wl1251_enable_interrupts(struct wl1251 *wl) | ||
48 | { | ||
49 | wl->if_ops->enable_irq(wl); | ||
50 | } | ||
51 | |||
52 | void wl1251_disable_interrupts(struct wl1251 *wl) | ||
53 | { | ||
54 | wl->if_ops->disable_irq(wl); | ||
55 | } | ||
56 | |||
57 | static void wl1251_power_off(struct wl1251 *wl) | ||
58 | { | ||
59 | wl->set_power(false); | ||
60 | } | ||
61 | |||
62 | static void wl1251_power_on(struct wl1251 *wl) | ||
63 | { | ||
64 | wl->set_power(true); | ||
65 | } | ||
66 | |||
67 | static int wl1251_fetch_firmware(struct wl1251 *wl) | ||
68 | { | ||
69 | const struct firmware *fw; | ||
70 | struct device *dev = wiphy_dev(wl->hw->wiphy); | ||
71 | int ret; | ||
72 | |||
73 | ret = request_firmware(&fw, WL1251_FW_NAME, dev); | ||
74 | |||
75 | if (ret < 0) { | ||
76 | wl1251_error("could not get firmware: %d", ret); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | if (fw->size % 4) { | ||
81 | wl1251_error("firmware size is not multiple of 32 bits: %zu", | ||
82 | fw->size); | ||
83 | ret = -EILSEQ; | ||
84 | goto out; | ||
85 | } | ||
86 | |||
87 | wl->fw_len = fw->size; | ||
88 | wl->fw = vmalloc(wl->fw_len); | ||
89 | |||
90 | if (!wl->fw) { | ||
91 | wl1251_error("could not allocate memory for the firmware"); | ||
92 | ret = -ENOMEM; | ||
93 | goto out; | ||
94 | } | ||
95 | |||
96 | memcpy(wl->fw, fw->data, wl->fw_len); | ||
97 | |||
98 | ret = 0; | ||
99 | |||
100 | out: | ||
101 | release_firmware(fw); | ||
102 | |||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | static int wl1251_fetch_nvs(struct wl1251 *wl) | ||
107 | { | ||
108 | const struct firmware *fw; | ||
109 | struct device *dev = wiphy_dev(wl->hw->wiphy); | ||
110 | int ret; | ||
111 | |||
112 | ret = request_firmware(&fw, WL1251_NVS_NAME, dev); | ||
113 | |||
114 | if (ret < 0) { | ||
115 | wl1251_error("could not get nvs file: %d", ret); | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | if (fw->size % 4) { | ||
120 | wl1251_error("nvs size is not multiple of 32 bits: %zu", | ||
121 | fw->size); | ||
122 | ret = -EILSEQ; | ||
123 | goto out; | ||
124 | } | ||
125 | |||
126 | wl->nvs_len = fw->size; | ||
127 | wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL); | ||
128 | |||
129 | if (!wl->nvs) { | ||
130 | wl1251_error("could not allocate memory for the nvs file"); | ||
131 | ret = -ENOMEM; | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | ret = 0; | ||
136 | |||
137 | out: | ||
138 | release_firmware(fw); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static void wl1251_fw_wakeup(struct wl1251 *wl) | ||
144 | { | ||
145 | u32 elp_reg; | ||
146 | |||
147 | elp_reg = ELPCTRL_WAKE_UP; | ||
148 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | ||
149 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | ||
150 | |||
151 | if (!(elp_reg & ELPCTRL_WLAN_READY)) | ||
152 | wl1251_warning("WLAN not ready"); | ||
153 | } | ||
154 | |||
155 | static int wl1251_chip_wakeup(struct wl1251 *wl) | ||
156 | { | ||
157 | int ret = 0; | ||
158 | |||
159 | wl1251_power_on(wl); | ||
160 | msleep(WL1251_POWER_ON_SLEEP); | ||
161 | wl->if_ops->reset(wl); | ||
162 | |||
163 | /* We don't need a real memory partition here, because we only want | ||
164 | * to use the registers at this point. */ | ||
165 | wl1251_set_partition(wl, | ||
166 | 0x00000000, | ||
167 | 0x00000000, | ||
168 | REGISTERS_BASE, | ||
169 | REGISTERS_DOWN_SIZE); | ||
170 | |||
171 | /* ELP module wake up */ | ||
172 | wl1251_fw_wakeup(wl); | ||
173 | |||
174 | /* whal_FwCtrl_BootSm() */ | ||
175 | |||
176 | /* 0. read chip id from CHIP_ID */ | ||
177 | wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B); | ||
178 | |||
179 | /* 1. check if chip id is valid */ | ||
180 | |||
181 | switch (wl->chip_id) { | ||
182 | case CHIP_ID_1251_PG12: | ||
183 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", | ||
184 | wl->chip_id); | ||
185 | break; | ||
186 | case CHIP_ID_1251_PG11: | ||
187 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)", | ||
188 | wl->chip_id); | ||
189 | break; | ||
190 | case CHIP_ID_1251_PG10: | ||
191 | default: | ||
192 | wl1251_error("unsupported chip id: 0x%x", wl->chip_id); | ||
193 | ret = -ENODEV; | ||
194 | goto out; | ||
195 | } | ||
196 | |||
197 | if (wl->fw == NULL) { | ||
198 | ret = wl1251_fetch_firmware(wl); | ||
199 | if (ret < 0) | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | if (wl->nvs == NULL && !wl->use_eeprom) { | ||
204 | /* No NVS from netlink, try to get it from the filesystem */ | ||
205 | ret = wl1251_fetch_nvs(wl); | ||
206 | if (ret < 0) | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | out: | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | #define WL1251_IRQ_LOOP_COUNT 10 | ||
215 | static void wl1251_irq_work(struct work_struct *work) | ||
216 | { | ||
217 | u32 intr, ctr = WL1251_IRQ_LOOP_COUNT; | ||
218 | struct wl1251 *wl = | ||
219 | container_of(work, struct wl1251, irq_work); | ||
220 | int ret; | ||
221 | |||
222 | mutex_lock(&wl->mutex); | ||
223 | |||
224 | wl1251_debug(DEBUG_IRQ, "IRQ work"); | ||
225 | |||
226 | if (wl->state == WL1251_STATE_OFF) | ||
227 | goto out; | ||
228 | |||
229 | ret = wl1251_ps_elp_wakeup(wl); | ||
230 | if (ret < 0) | ||
231 | goto out; | ||
232 | |||
233 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL); | ||
234 | |||
235 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | ||
236 | wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); | ||
237 | |||
238 | do { | ||
239 | if (wl->data_path) { | ||
240 | wl->rx_counter = wl1251_mem_read32( | ||
241 | wl, wl->data_path->rx_control_addr); | ||
242 | |||
243 | /* We handle a frmware bug here */ | ||
244 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { | ||
245 | case 0: | ||
246 | wl1251_debug(DEBUG_IRQ, | ||
247 | "RX: FW and host in sync"); | ||
248 | intr &= ~WL1251_ACX_INTR_RX0_DATA; | ||
249 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | ||
250 | break; | ||
251 | case 1: | ||
252 | wl1251_debug(DEBUG_IRQ, "RX: FW +1"); | ||
253 | intr |= WL1251_ACX_INTR_RX0_DATA; | ||
254 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | ||
255 | break; | ||
256 | case 2: | ||
257 | wl1251_debug(DEBUG_IRQ, "RX: FW +2"); | ||
258 | intr |= WL1251_ACX_INTR_RX0_DATA; | ||
259 | intr |= WL1251_ACX_INTR_RX1_DATA; | ||
260 | break; | ||
261 | default: | ||
262 | wl1251_warning( | ||
263 | "RX: FW and host out of sync: %d", | ||
264 | wl->rx_counter - wl->rx_handled); | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | wl->rx_handled = wl->rx_counter; | ||
269 | |||
270 | wl1251_debug(DEBUG_IRQ, "RX counter: %d", | ||
271 | wl->rx_counter); | ||
272 | } | ||
273 | |||
274 | intr &= wl->intr_mask; | ||
275 | |||
276 | if (intr == 0) { | ||
277 | wl1251_debug(DEBUG_IRQ, "INTR is 0"); | ||
278 | goto out_sleep; | ||
279 | } | ||
280 | |||
281 | if (intr & WL1251_ACX_INTR_RX0_DATA) { | ||
282 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); | ||
283 | wl1251_rx(wl); | ||
284 | } | ||
285 | |||
286 | if (intr & WL1251_ACX_INTR_RX1_DATA) { | ||
287 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); | ||
288 | wl1251_rx(wl); | ||
289 | } | ||
290 | |||
291 | if (intr & WL1251_ACX_INTR_TX_RESULT) { | ||
292 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); | ||
293 | wl1251_tx_complete(wl); | ||
294 | } | ||
295 | |||
296 | if (intr & (WL1251_ACX_INTR_EVENT_A | | ||
297 | WL1251_ACX_INTR_EVENT_B)) { | ||
298 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", | ||
299 | intr); | ||
300 | if (intr & WL1251_ACX_INTR_EVENT_A) | ||
301 | wl1251_event_handle(wl, 0); | ||
302 | else | ||
303 | wl1251_event_handle(wl, 1); | ||
304 | } | ||
305 | |||
306 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) | ||
307 | wl1251_debug(DEBUG_IRQ, | ||
308 | "WL1251_ACX_INTR_INIT_COMPLETE"); | ||
309 | |||
310 | if (--ctr == 0) | ||
311 | break; | ||
312 | |||
313 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | ||
314 | } while (intr); | ||
315 | |||
316 | out_sleep: | ||
317 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); | ||
318 | wl1251_ps_elp_sleep(wl); | ||
319 | |||
320 | out: | ||
321 | mutex_unlock(&wl->mutex); | ||
322 | } | ||
323 | |||
324 | static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, | ||
325 | u16 beacon_interval, u8 dtim_period) | ||
326 | { | ||
327 | int ret; | ||
328 | |||
329 | ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, | ||
330 | DEFAULT_HW_GEN_MODULATION_TYPE, | ||
331 | wl->tx_mgmt_frm_rate, | ||
332 | wl->tx_mgmt_frm_mod); | ||
333 | if (ret < 0) | ||
334 | goto out; | ||
335 | |||
336 | |||
337 | ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, | ||
338 | dtim_period); | ||
339 | if (ret < 0) | ||
340 | goto out; | ||
341 | |||
342 | /* | ||
343 | * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify | ||
344 | * locking we just sleep instead, for now | ||
345 | */ | ||
346 | msleep(10); | ||
347 | |||
348 | out: | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static void wl1251_filter_work(struct work_struct *work) | ||
353 | { | ||
354 | struct wl1251 *wl = | ||
355 | container_of(work, struct wl1251, filter_work); | ||
356 | int ret; | ||
357 | |||
358 | mutex_lock(&wl->mutex); | ||
359 | |||
360 | if (wl->state == WL1251_STATE_OFF) | ||
361 | goto out; | ||
362 | |||
363 | ret = wl1251_ps_elp_wakeup(wl); | ||
364 | if (ret < 0) | ||
365 | goto out; | ||
366 | |||
367 | ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, | ||
368 | wl->dtim_period); | ||
369 | if (ret < 0) | ||
370 | goto out_sleep; | ||
371 | |||
372 | out_sleep: | ||
373 | wl1251_ps_elp_sleep(wl); | ||
374 | |||
375 | out: | ||
376 | mutex_unlock(&wl->mutex); | ||
377 | } | ||
378 | |||
379 | static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
380 | { | ||
381 | struct wl1251 *wl = hw->priv; | ||
382 | |||
383 | skb_queue_tail(&wl->tx_queue, skb); | ||
384 | |||
385 | /* | ||
386 | * The chip specific setup must run before the first TX packet - | ||
387 | * before that, the tx_work will not be initialized! | ||
388 | */ | ||
389 | |||
390 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
391 | |||
392 | /* | ||
393 | * The workqueue is slow to process the tx_queue and we need stop | ||
394 | * the queue here, otherwise the queue will get too long. | ||
395 | */ | ||
396 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { | ||
397 | wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); | ||
398 | ieee80211_stop_queues(wl->hw); | ||
399 | |||
400 | /* | ||
401 | * FIXME: this is racy, the variable is not properly | ||
402 | * protected. Maybe fix this by removing the stupid | ||
403 | * variable altogether and checking the real queue state? | ||
404 | */ | ||
405 | wl->tx_queue_stopped = true; | ||
406 | } | ||
407 | |||
408 | return NETDEV_TX_OK; | ||
409 | } | ||
410 | |||
411 | static int wl1251_op_start(struct ieee80211_hw *hw) | ||
412 | { | ||
413 | struct wl1251 *wl = hw->priv; | ||
414 | struct wiphy *wiphy = hw->wiphy; | ||
415 | int ret = 0; | ||
416 | |||
417 | wl1251_debug(DEBUG_MAC80211, "mac80211 start"); | ||
418 | |||
419 | mutex_lock(&wl->mutex); | ||
420 | |||
421 | if (wl->state != WL1251_STATE_OFF) { | ||
422 | wl1251_error("cannot start because not in off state: %d", | ||
423 | wl->state); | ||
424 | ret = -EBUSY; | ||
425 | goto out; | ||
426 | } | ||
427 | |||
428 | ret = wl1251_chip_wakeup(wl); | ||
429 | if (ret < 0) | ||
430 | goto out; | ||
431 | |||
432 | ret = wl1251_boot(wl); | ||
433 | if (ret < 0) | ||
434 | goto out; | ||
435 | |||
436 | ret = wl1251_hw_init(wl); | ||
437 | if (ret < 0) | ||
438 | goto out; | ||
439 | |||
440 | ret = wl1251_acx_station_id(wl); | ||
441 | if (ret < 0) | ||
442 | goto out; | ||
443 | |||
444 | wl->state = WL1251_STATE_ON; | ||
445 | |||
446 | wl1251_info("firmware booted (%s)", wl->fw_ver); | ||
447 | |||
448 | /* update hw/fw version info in wiphy struct */ | ||
449 | wiphy->hw_version = wl->chip_id; | ||
450 | strncpy(wiphy->fw_version, wl->fw_ver, sizeof(wiphy->fw_version)); | ||
451 | |||
452 | out: | ||
453 | if (ret < 0) | ||
454 | wl1251_power_off(wl); | ||
455 | |||
456 | mutex_unlock(&wl->mutex); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | static void wl1251_op_stop(struct ieee80211_hw *hw) | ||
462 | { | ||
463 | struct wl1251 *wl = hw->priv; | ||
464 | |||
465 | wl1251_info("down"); | ||
466 | |||
467 | wl1251_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
468 | |||
469 | mutex_lock(&wl->mutex); | ||
470 | |||
471 | WARN_ON(wl->state != WL1251_STATE_ON); | ||
472 | |||
473 | if (wl->scanning) { | ||
474 | mutex_unlock(&wl->mutex); | ||
475 | ieee80211_scan_completed(wl->hw, true); | ||
476 | mutex_lock(&wl->mutex); | ||
477 | wl->scanning = false; | ||
478 | } | ||
479 | |||
480 | wl->state = WL1251_STATE_OFF; | ||
481 | |||
482 | wl1251_disable_interrupts(wl); | ||
483 | |||
484 | mutex_unlock(&wl->mutex); | ||
485 | |||
486 | cancel_work_sync(&wl->irq_work); | ||
487 | cancel_work_sync(&wl->tx_work); | ||
488 | cancel_work_sync(&wl->filter_work); | ||
489 | |||
490 | mutex_lock(&wl->mutex); | ||
491 | |||
492 | /* let's notify MAC80211 about the remaining pending TX frames */ | ||
493 | wl1251_tx_flush(wl); | ||
494 | wl1251_power_off(wl); | ||
495 | |||
496 | memset(wl->bssid, 0, ETH_ALEN); | ||
497 | wl->listen_int = 1; | ||
498 | wl->bss_type = MAX_BSS_TYPE; | ||
499 | |||
500 | wl->data_in_count = 0; | ||
501 | wl->rx_counter = 0; | ||
502 | wl->rx_handled = 0; | ||
503 | wl->rx_current_buffer = 0; | ||
504 | wl->rx_last_id = 0; | ||
505 | wl->next_tx_complete = 0; | ||
506 | wl->elp = false; | ||
507 | wl->psm = 0; | ||
508 | wl->tx_queue_stopped = false; | ||
509 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | ||
510 | wl->channel = WL1251_DEFAULT_CHANNEL; | ||
511 | |||
512 | wl1251_debugfs_reset(wl); | ||
513 | |||
514 | mutex_unlock(&wl->mutex); | ||
515 | } | ||
516 | |||
517 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, | ||
518 | struct ieee80211_vif *vif) | ||
519 | { | ||
520 | struct wl1251 *wl = hw->priv; | ||
521 | int ret = 0; | ||
522 | |||
523 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | ||
524 | vif->type, vif->addr); | ||
525 | |||
526 | mutex_lock(&wl->mutex); | ||
527 | if (wl->vif) { | ||
528 | ret = -EBUSY; | ||
529 | goto out; | ||
530 | } | ||
531 | |||
532 | wl->vif = vif; | ||
533 | |||
534 | switch (vif->type) { | ||
535 | case NL80211_IFTYPE_STATION: | ||
536 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
537 | break; | ||
538 | case NL80211_IFTYPE_ADHOC: | ||
539 | wl->bss_type = BSS_TYPE_IBSS; | ||
540 | break; | ||
541 | default: | ||
542 | ret = -EOPNOTSUPP; | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { | ||
547 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
548 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
549 | ret = wl1251_acx_station_id(wl); | ||
550 | if (ret < 0) | ||
551 | goto out; | ||
552 | } | ||
553 | |||
554 | out: | ||
555 | mutex_unlock(&wl->mutex); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | ||
560 | struct ieee80211_vif *vif) | ||
561 | { | ||
562 | struct wl1251 *wl = hw->priv; | ||
563 | |||
564 | mutex_lock(&wl->mutex); | ||
565 | wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
566 | wl->vif = NULL; | ||
567 | mutex_unlock(&wl->mutex); | ||
568 | } | ||
569 | |||
570 | static int wl1251_build_qos_null_data(struct wl1251 *wl) | ||
571 | { | ||
572 | struct ieee80211_qos_hdr template; | ||
573 | |||
574 | memset(&template, 0, sizeof(template)); | ||
575 | |||
576 | memcpy(template.addr1, wl->bssid, ETH_ALEN); | ||
577 | memcpy(template.addr2, wl->mac_addr, ETH_ALEN); | ||
578 | memcpy(template.addr3, wl->bssid, ETH_ALEN); | ||
579 | |||
580 | template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
581 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
582 | IEEE80211_FCTL_TODS); | ||
583 | |||
584 | /* FIXME: not sure what priority to use here */ | ||
585 | template.qos_ctrl = cpu_to_le16(0); | ||
586 | |||
587 | return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template, | ||
588 | sizeof(template)); | ||
589 | } | ||
590 | |||
591 | static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | ||
592 | { | ||
593 | struct wl1251 *wl = hw->priv; | ||
594 | struct ieee80211_conf *conf = &hw->conf; | ||
595 | int channel, ret = 0; | ||
596 | |||
597 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | ||
598 | |||
599 | wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | ||
600 | channel, | ||
601 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | ||
602 | conf->power_level); | ||
603 | |||
604 | mutex_lock(&wl->mutex); | ||
605 | |||
606 | ret = wl1251_ps_elp_wakeup(wl); | ||
607 | if (ret < 0) | ||
608 | goto out; | ||
609 | |||
610 | if (channel != wl->channel) { | ||
611 | wl->channel = channel; | ||
612 | |||
613 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | ||
614 | wl->beacon_int, wl->dtim_period); | ||
615 | if (ret < 0) | ||
616 | goto out_sleep; | ||
617 | } | ||
618 | |||
619 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | ||
620 | wl1251_debug(DEBUG_PSM, "psm enabled"); | ||
621 | |||
622 | wl->psm_requested = true; | ||
623 | |||
624 | wl->dtim_period = conf->ps_dtim_period; | ||
625 | |||
626 | ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int, | ||
627 | wl->dtim_period); | ||
628 | |||
629 | /* | ||
630 | * mac80211 enables PSM only if we're already associated. | ||
631 | */ | ||
632 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
633 | if (ret < 0) | ||
634 | goto out_sleep; | ||
635 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | ||
636 | wl->psm_requested) { | ||
637 | wl1251_debug(DEBUG_PSM, "psm disabled"); | ||
638 | |||
639 | wl->psm_requested = false; | ||
640 | |||
641 | if (wl->psm) { | ||
642 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | ||
643 | if (ret < 0) | ||
644 | goto out_sleep; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | if (conf->power_level != wl->power_level) { | ||
649 | ret = wl1251_acx_tx_power(wl, conf->power_level); | ||
650 | if (ret < 0) | ||
651 | goto out_sleep; | ||
652 | |||
653 | wl->power_level = conf->power_level; | ||
654 | } | ||
655 | |||
656 | out_sleep: | ||
657 | wl1251_ps_elp_sleep(wl); | ||
658 | |||
659 | out: | ||
660 | mutex_unlock(&wl->mutex); | ||
661 | |||
662 | return ret; | ||
663 | } | ||
664 | |||
665 | #define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ | ||
666 | FIF_ALLMULTI | \ | ||
667 | FIF_FCSFAIL | \ | ||
668 | FIF_BCN_PRBRESP_PROMISC | \ | ||
669 | FIF_CONTROL | \ | ||
670 | FIF_OTHER_BSS) | ||
671 | |||
672 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | ||
673 | unsigned int changed, | ||
674 | unsigned int *total,u64 multicast) | ||
675 | { | ||
676 | struct wl1251 *wl = hw->priv; | ||
677 | |||
678 | wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); | ||
679 | |||
680 | *total &= WL1251_SUPPORTED_FILTERS; | ||
681 | changed &= WL1251_SUPPORTED_FILTERS; | ||
682 | |||
683 | if (changed == 0) | ||
684 | /* no filters which we support changed */ | ||
685 | return; | ||
686 | |||
687 | /* FIXME: wl->rx_config and wl->rx_filter are not protected */ | ||
688 | |||
689 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; | ||
690 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; | ||
691 | |||
692 | if (*total & FIF_PROMISC_IN_BSS) { | ||
693 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
694 | wl->rx_config |= CFG_RX_ALL_GOOD; | ||
695 | } | ||
696 | if (*total & FIF_ALLMULTI) | ||
697 | /* | ||
698 | * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive | ||
699 | * all multicast frames | ||
700 | */ | ||
701 | wl->rx_config &= ~CFG_MC_FILTER_EN; | ||
702 | if (*total & FIF_FCSFAIL) | ||
703 | wl->rx_filter |= CFG_RX_FCS_ERROR; | ||
704 | if (*total & FIF_BCN_PRBRESP_PROMISC) { | ||
705 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
706 | wl->rx_config &= ~CFG_SSID_FILTER_EN; | ||
707 | } | ||
708 | if (*total & FIF_CONTROL) | ||
709 | wl->rx_filter |= CFG_RX_CTL_EN; | ||
710 | if (*total & FIF_OTHER_BSS) | ||
711 | wl->rx_filter &= ~CFG_BSSID_FILTER_EN; | ||
712 | |||
713 | /* | ||
714 | * FIXME: workqueues need to be properly cancelled on stop(), for | ||
715 | * now let's just disable changing the filter settings. They will | ||
716 | * be updated any on config(). | ||
717 | */ | ||
718 | /* schedule_work(&wl->filter_work); */ | ||
719 | } | ||
720 | |||
721 | /* HW encryption */ | ||
722 | static int wl1251_set_key_type(struct wl1251 *wl, | ||
723 | struct wl1251_cmd_set_keys *key, | ||
724 | enum set_key_cmd cmd, | ||
725 | struct ieee80211_key_conf *mac80211_key, | ||
726 | const u8 *addr) | ||
727 | { | ||
728 | switch (mac80211_key->alg) { | ||
729 | case ALG_WEP: | ||
730 | if (is_broadcast_ether_addr(addr)) | ||
731 | key->key_type = KEY_WEP_DEFAULT; | ||
732 | else | ||
733 | key->key_type = KEY_WEP_ADDR; | ||
734 | |||
735 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | ||
736 | break; | ||
737 | case ALG_TKIP: | ||
738 | if (is_broadcast_ether_addr(addr)) | ||
739 | key->key_type = KEY_TKIP_MIC_GROUP; | ||
740 | else | ||
741 | key->key_type = KEY_TKIP_MIC_PAIRWISE; | ||
742 | |||
743 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | ||
744 | break; | ||
745 | case ALG_CCMP: | ||
746 | if (is_broadcast_ether_addr(addr)) | ||
747 | key->key_type = KEY_AES_GROUP; | ||
748 | else | ||
749 | key->key_type = KEY_AES_PAIRWISE; | ||
750 | mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
751 | break; | ||
752 | default: | ||
753 | wl1251_error("Unknown key algo 0x%x", mac80211_key->alg); | ||
754 | return -EOPNOTSUPP; | ||
755 | } | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
761 | struct ieee80211_vif *vif, | ||
762 | struct ieee80211_sta *sta, | ||
763 | struct ieee80211_key_conf *key) | ||
764 | { | ||
765 | struct wl1251 *wl = hw->priv; | ||
766 | struct wl1251_cmd_set_keys *wl_cmd; | ||
767 | const u8 *addr; | ||
768 | int ret; | ||
769 | |||
770 | static const u8 bcast_addr[ETH_ALEN] = | ||
771 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
772 | |||
773 | wl1251_debug(DEBUG_MAC80211, "mac80211 set key"); | ||
774 | |||
775 | wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL); | ||
776 | if (!wl_cmd) { | ||
777 | ret = -ENOMEM; | ||
778 | goto out; | ||
779 | } | ||
780 | |||
781 | addr = sta ? sta->addr : bcast_addr; | ||
782 | |||
783 | wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | ||
784 | wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | ||
785 | wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | ||
786 | key->alg, key->keyidx, key->keylen, key->flags); | ||
787 | wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); | ||
788 | |||
789 | if (is_zero_ether_addr(addr)) { | ||
790 | /* We dont support TX only encryption */ | ||
791 | ret = -EOPNOTSUPP; | ||
792 | goto out; | ||
793 | } | ||
794 | |||
795 | mutex_lock(&wl->mutex); | ||
796 | |||
797 | ret = wl1251_ps_elp_wakeup(wl); | ||
798 | if (ret < 0) | ||
799 | goto out_unlock; | ||
800 | |||
801 | switch (cmd) { | ||
802 | case SET_KEY: | ||
803 | wl_cmd->key_action = KEY_ADD_OR_REPLACE; | ||
804 | break; | ||
805 | case DISABLE_KEY: | ||
806 | wl_cmd->key_action = KEY_REMOVE; | ||
807 | break; | ||
808 | default: | ||
809 | wl1251_error("Unsupported key cmd 0x%x", cmd); | ||
810 | break; | ||
811 | } | ||
812 | |||
813 | ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr); | ||
814 | if (ret < 0) { | ||
815 | wl1251_error("Set KEY type failed"); | ||
816 | goto out_sleep; | ||
817 | } | ||
818 | |||
819 | if (wl_cmd->key_type != KEY_WEP_DEFAULT) | ||
820 | memcpy(wl_cmd->addr, addr, ETH_ALEN); | ||
821 | |||
822 | if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) || | ||
823 | (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) { | ||
824 | /* | ||
825 | * We get the key in the following form: | ||
826 | * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) | ||
827 | * but the target is expecting: | ||
828 | * TKIP - RX MIC - TX MIC | ||
829 | */ | ||
830 | memcpy(wl_cmd->key, key->key, 16); | ||
831 | memcpy(wl_cmd->key + 16, key->key + 24, 8); | ||
832 | memcpy(wl_cmd->key + 24, key->key + 16, 8); | ||
833 | |||
834 | } else { | ||
835 | memcpy(wl_cmd->key, key->key, key->keylen); | ||
836 | } | ||
837 | wl_cmd->key_size = key->keylen; | ||
838 | |||
839 | wl_cmd->id = key->keyidx; | ||
840 | wl_cmd->ssid_profile = 0; | ||
841 | |||
842 | wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd)); | ||
843 | |||
844 | ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd)); | ||
845 | if (ret < 0) { | ||
846 | wl1251_warning("could not set keys"); | ||
847 | goto out_sleep; | ||
848 | } | ||
849 | |||
850 | out_sleep: | ||
851 | wl1251_ps_elp_sleep(wl); | ||
852 | |||
853 | out_unlock: | ||
854 | mutex_unlock(&wl->mutex); | ||
855 | |||
856 | out: | ||
857 | kfree(wl_cmd); | ||
858 | |||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | ||
863 | struct ieee80211_vif *vif, | ||
864 | struct cfg80211_scan_request *req) | ||
865 | { | ||
866 | struct wl1251 *wl = hw->priv; | ||
867 | struct sk_buff *skb; | ||
868 | size_t ssid_len = 0; | ||
869 | u8 *ssid = NULL; | ||
870 | int ret; | ||
871 | |||
872 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); | ||
873 | |||
874 | if (req->n_ssids) { | ||
875 | ssid = req->ssids[0].ssid; | ||
876 | ssid_len = req->ssids[0].ssid_len; | ||
877 | } | ||
878 | |||
879 | mutex_lock(&wl->mutex); | ||
880 | |||
881 | if (wl->scanning) { | ||
882 | wl1251_debug(DEBUG_SCAN, "scan already in progress"); | ||
883 | ret = -EINVAL; | ||
884 | goto out; | ||
885 | } | ||
886 | |||
887 | ret = wl1251_ps_elp_wakeup(wl); | ||
888 | if (ret < 0) | ||
889 | goto out; | ||
890 | |||
891 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, | ||
892 | req->ie, req->ie_len); | ||
893 | if (!skb) { | ||
894 | ret = -ENOMEM; | ||
895 | goto out; | ||
896 | } | ||
897 | |||
898 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, | ||
899 | skb->len); | ||
900 | dev_kfree_skb(skb); | ||
901 | if (ret < 0) | ||
902 | goto out_sleep; | ||
903 | |||
904 | ret = wl1251_cmd_trigger_scan_to(wl, 0); | ||
905 | if (ret < 0) | ||
906 | goto out_sleep; | ||
907 | |||
908 | wl->scanning = true; | ||
909 | |||
910 | ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, | ||
911 | req->n_channels, WL1251_SCAN_NUM_PROBES); | ||
912 | if (ret < 0) { | ||
913 | wl->scanning = false; | ||
914 | goto out_sleep; | ||
915 | } | ||
916 | |||
917 | out_sleep: | ||
918 | wl1251_ps_elp_sleep(wl); | ||
919 | |||
920 | out: | ||
921 | mutex_unlock(&wl->mutex); | ||
922 | |||
923 | return ret; | ||
924 | } | ||
925 | |||
926 | static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
927 | { | ||
928 | struct wl1251 *wl = hw->priv; | ||
929 | int ret; | ||
930 | |||
931 | mutex_lock(&wl->mutex); | ||
932 | |||
933 | ret = wl1251_ps_elp_wakeup(wl); | ||
934 | if (ret < 0) | ||
935 | goto out; | ||
936 | |||
937 | ret = wl1251_acx_rts_threshold(wl, (u16) value); | ||
938 | if (ret < 0) | ||
939 | wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret); | ||
940 | |||
941 | wl1251_ps_elp_sleep(wl); | ||
942 | |||
943 | out: | ||
944 | mutex_unlock(&wl->mutex); | ||
945 | |||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | ||
950 | struct ieee80211_vif *vif, | ||
951 | struct ieee80211_bss_conf *bss_conf, | ||
952 | u32 changed) | ||
953 | { | ||
954 | struct wl1251 *wl = hw->priv; | ||
955 | struct sk_buff *beacon, *skb; | ||
956 | int ret; | ||
957 | |||
958 | wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | ||
959 | |||
960 | mutex_lock(&wl->mutex); | ||
961 | |||
962 | ret = wl1251_ps_elp_wakeup(wl); | ||
963 | if (ret < 0) | ||
964 | goto out; | ||
965 | |||
966 | if (changed & BSS_CHANGED_BSSID) { | ||
967 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
968 | |||
969 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | ||
970 | if (!skb) | ||
971 | goto out_sleep; | ||
972 | |||
973 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, | ||
974 | skb->data, skb->len); | ||
975 | dev_kfree_skb(skb); | ||
976 | if (ret < 0) | ||
977 | goto out_sleep; | ||
978 | |||
979 | ret = wl1251_build_qos_null_data(wl); | ||
980 | if (ret < 0) | ||
981 | goto out; | ||
982 | |||
983 | if (wl->bss_type != BSS_TYPE_IBSS) { | ||
984 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | ||
985 | wl->beacon_int, wl->dtim_period); | ||
986 | if (ret < 0) | ||
987 | goto out_sleep; | ||
988 | } | ||
989 | } | ||
990 | |||
991 | if (changed & BSS_CHANGED_ASSOC) { | ||
992 | if (bss_conf->assoc) { | ||
993 | wl->beacon_int = bss_conf->beacon_int; | ||
994 | |||
995 | skb = ieee80211_pspoll_get(wl->hw, wl->vif); | ||
996 | if (!skb) | ||
997 | goto out_sleep; | ||
998 | |||
999 | ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, | ||
1000 | skb->data, | ||
1001 | skb->len); | ||
1002 | dev_kfree_skb(skb); | ||
1003 | if (ret < 0) | ||
1004 | goto out_sleep; | ||
1005 | |||
1006 | ret = wl1251_acx_aid(wl, bss_conf->aid); | ||
1007 | if (ret < 0) | ||
1008 | goto out_sleep; | ||
1009 | } else { | ||
1010 | /* use defaults when not associated */ | ||
1011 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; | ||
1012 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; | ||
1013 | } | ||
1014 | } | ||
1015 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
1016 | if (bss_conf->use_short_slot) | ||
1017 | ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT); | ||
1018 | else | ||
1019 | ret = wl1251_acx_slot(wl, SLOT_TIME_LONG); | ||
1020 | if (ret < 0) { | ||
1021 | wl1251_warning("Set slot time failed %d", ret); | ||
1022 | goto out_sleep; | ||
1023 | } | ||
1024 | } | ||
1025 | |||
1026 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
1027 | if (bss_conf->use_short_preamble) | ||
1028 | wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | ||
1029 | else | ||
1030 | wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | ||
1031 | } | ||
1032 | |||
1033 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | ||
1034 | if (bss_conf->use_cts_prot) | ||
1035 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE); | ||
1036 | else | ||
1037 | ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); | ||
1038 | if (ret < 0) { | ||
1039 | wl1251_warning("Set ctsprotect failed %d", ret); | ||
1040 | goto out_sleep; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | if (changed & BSS_CHANGED_BEACON) { | ||
1045 | beacon = ieee80211_beacon_get(hw, vif); | ||
1046 | ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data, | ||
1047 | beacon->len); | ||
1048 | |||
1049 | if (ret < 0) { | ||
1050 | dev_kfree_skb(beacon); | ||
1051 | goto out_sleep; | ||
1052 | } | ||
1053 | |||
1054 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, | ||
1055 | beacon->len); | ||
1056 | |||
1057 | dev_kfree_skb(beacon); | ||
1058 | |||
1059 | if (ret < 0) | ||
1060 | goto out_sleep; | ||
1061 | |||
1062 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, | ||
1063 | wl->channel, wl->dtim_period); | ||
1064 | |||
1065 | if (ret < 0) | ||
1066 | goto out_sleep; | ||
1067 | } | ||
1068 | |||
1069 | out_sleep: | ||
1070 | wl1251_ps_elp_sleep(wl); | ||
1071 | |||
1072 | out: | ||
1073 | mutex_unlock(&wl->mutex); | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /* can't be const, mac80211 writes to this */ | ||
1078 | static struct ieee80211_rate wl1251_rates[] = { | ||
1079 | { .bitrate = 10, | ||
1080 | .hw_value = 0x1, | ||
1081 | .hw_value_short = 0x1, }, | ||
1082 | { .bitrate = 20, | ||
1083 | .hw_value = 0x2, | ||
1084 | .hw_value_short = 0x2, | ||
1085 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
1086 | { .bitrate = 55, | ||
1087 | .hw_value = 0x4, | ||
1088 | .hw_value_short = 0x4, | ||
1089 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
1090 | { .bitrate = 110, | ||
1091 | .hw_value = 0x20, | ||
1092 | .hw_value_short = 0x20, | ||
1093 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
1094 | { .bitrate = 60, | ||
1095 | .hw_value = 0x8, | ||
1096 | .hw_value_short = 0x8, }, | ||
1097 | { .bitrate = 90, | ||
1098 | .hw_value = 0x10, | ||
1099 | .hw_value_short = 0x10, }, | ||
1100 | { .bitrate = 120, | ||
1101 | .hw_value = 0x40, | ||
1102 | .hw_value_short = 0x40, }, | ||
1103 | { .bitrate = 180, | ||
1104 | .hw_value = 0x80, | ||
1105 | .hw_value_short = 0x80, }, | ||
1106 | { .bitrate = 240, | ||
1107 | .hw_value = 0x200, | ||
1108 | .hw_value_short = 0x200, }, | ||
1109 | { .bitrate = 360, | ||
1110 | .hw_value = 0x400, | ||
1111 | .hw_value_short = 0x400, }, | ||
1112 | { .bitrate = 480, | ||
1113 | .hw_value = 0x800, | ||
1114 | .hw_value_short = 0x800, }, | ||
1115 | { .bitrate = 540, | ||
1116 | .hw_value = 0x1000, | ||
1117 | .hw_value_short = 0x1000, }, | ||
1118 | }; | ||
1119 | |||
1120 | /* can't be const, mac80211 writes to this */ | ||
1121 | static struct ieee80211_channel wl1251_channels[] = { | ||
1122 | { .hw_value = 1, .center_freq = 2412}, | ||
1123 | { .hw_value = 2, .center_freq = 2417}, | ||
1124 | { .hw_value = 3, .center_freq = 2422}, | ||
1125 | { .hw_value = 4, .center_freq = 2427}, | ||
1126 | { .hw_value = 5, .center_freq = 2432}, | ||
1127 | { .hw_value = 6, .center_freq = 2437}, | ||
1128 | { .hw_value = 7, .center_freq = 2442}, | ||
1129 | { .hw_value = 8, .center_freq = 2447}, | ||
1130 | { .hw_value = 9, .center_freq = 2452}, | ||
1131 | { .hw_value = 10, .center_freq = 2457}, | ||
1132 | { .hw_value = 11, .center_freq = 2462}, | ||
1133 | { .hw_value = 12, .center_freq = 2467}, | ||
1134 | { .hw_value = 13, .center_freq = 2472}, | ||
1135 | }; | ||
1136 | |||
1137 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1138 | const struct ieee80211_tx_queue_params *params) | ||
1139 | { | ||
1140 | enum wl1251_acx_ps_scheme ps_scheme; | ||
1141 | struct wl1251 *wl = hw->priv; | ||
1142 | int ret; | ||
1143 | |||
1144 | mutex_lock(&wl->mutex); | ||
1145 | |||
1146 | wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1147 | |||
1148 | ret = wl1251_ps_elp_wakeup(wl); | ||
1149 | if (ret < 0) | ||
1150 | goto out; | ||
1151 | |||
1152 | /* mac80211 uses units of 32 usec */ | ||
1153 | ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), | ||
1154 | params->cw_min, params->cw_max, | ||
1155 | params->aifs, params->txop * 32); | ||
1156 | if (ret < 0) | ||
1157 | goto out_sleep; | ||
1158 | |||
1159 | if (params->uapsd) | ||
1160 | ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER; | ||
1161 | else | ||
1162 | ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY; | ||
1163 | |||
1164 | ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), | ||
1165 | CHANNEL_TYPE_EDCF, | ||
1166 | wl1251_tx_get_queue(queue), ps_scheme, | ||
1167 | WL1251_ACX_ACK_POLICY_LEGACY); | ||
1168 | if (ret < 0) | ||
1169 | goto out_sleep; | ||
1170 | |||
1171 | out_sleep: | ||
1172 | wl1251_ps_elp_sleep(wl); | ||
1173 | |||
1174 | out: | ||
1175 | mutex_unlock(&wl->mutex); | ||
1176 | |||
1177 | return ret; | ||
1178 | } | ||
1179 | |||
1180 | static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx, | ||
1181 | struct survey_info *survey) | ||
1182 | { | ||
1183 | struct wl1251 *wl = hw->priv; | ||
1184 | struct ieee80211_conf *conf = &hw->conf; | ||
1185 | |||
1186 | if (idx != 0) | ||
1187 | return -ENOENT; | ||
1188 | |||
1189 | survey->channel = conf->channel; | ||
1190 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1191 | survey->noise = wl->noise; | ||
1192 | |||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | /* can't be const, mac80211 writes to this */ | ||
1197 | static struct ieee80211_supported_band wl1251_band_2ghz = { | ||
1198 | .channels = wl1251_channels, | ||
1199 | .n_channels = ARRAY_SIZE(wl1251_channels), | ||
1200 | .bitrates = wl1251_rates, | ||
1201 | .n_bitrates = ARRAY_SIZE(wl1251_rates), | ||
1202 | }; | ||
1203 | |||
1204 | static const struct ieee80211_ops wl1251_ops = { | ||
1205 | .start = wl1251_op_start, | ||
1206 | .stop = wl1251_op_stop, | ||
1207 | .add_interface = wl1251_op_add_interface, | ||
1208 | .remove_interface = wl1251_op_remove_interface, | ||
1209 | .config = wl1251_op_config, | ||
1210 | .configure_filter = wl1251_op_configure_filter, | ||
1211 | .tx = wl1251_op_tx, | ||
1212 | .set_key = wl1251_op_set_key, | ||
1213 | .hw_scan = wl1251_op_hw_scan, | ||
1214 | .bss_info_changed = wl1251_op_bss_info_changed, | ||
1215 | .set_rts_threshold = wl1251_op_set_rts_threshold, | ||
1216 | .conf_tx = wl1251_op_conf_tx, | ||
1217 | .get_survey = wl1251_op_get_survey, | ||
1218 | }; | ||
1219 | |||
1220 | static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data) | ||
1221 | { | ||
1222 | unsigned long timeout; | ||
1223 | |||
1224 | wl1251_reg_write32(wl, EE_ADDR, offset); | ||
1225 | wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ); | ||
1226 | |||
1227 | /* EE_CTL_READ clears when data is ready */ | ||
1228 | timeout = jiffies + msecs_to_jiffies(100); | ||
1229 | while (1) { | ||
1230 | if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ)) | ||
1231 | break; | ||
1232 | |||
1233 | if (time_after(jiffies, timeout)) | ||
1234 | return -ETIMEDOUT; | ||
1235 | |||
1236 | msleep(1); | ||
1237 | } | ||
1238 | |||
1239 | *data = wl1251_reg_read32(wl, EE_DATA); | ||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset, | ||
1244 | u8 *data, size_t len) | ||
1245 | { | ||
1246 | size_t i; | ||
1247 | int ret; | ||
1248 | |||
1249 | wl1251_reg_write32(wl, EE_START, 0); | ||
1250 | |||
1251 | for (i = 0; i < len; i++) { | ||
1252 | ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]); | ||
1253 | if (ret < 0) | ||
1254 | return ret; | ||
1255 | } | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static int wl1251_read_eeprom_mac(struct wl1251 *wl) | ||
1261 | { | ||
1262 | u8 mac[ETH_ALEN]; | ||
1263 | int i, ret; | ||
1264 | |||
1265 | wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE); | ||
1266 | |||
1267 | ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac)); | ||
1268 | if (ret < 0) { | ||
1269 | wl1251_warning("failed to read MAC address from EEPROM"); | ||
1270 | return ret; | ||
1271 | } | ||
1272 | |||
1273 | /* MAC is stored in reverse order */ | ||
1274 | for (i = 0; i < ETH_ALEN; i++) | ||
1275 | wl->mac_addr[i] = mac[ETH_ALEN - i - 1]; | ||
1276 | |||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | static int wl1251_register_hw(struct wl1251 *wl) | ||
1281 | { | ||
1282 | int ret; | ||
1283 | |||
1284 | if (wl->mac80211_registered) | ||
1285 | return 0; | ||
1286 | |||
1287 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
1288 | |||
1289 | ret = ieee80211_register_hw(wl->hw); | ||
1290 | if (ret < 0) { | ||
1291 | wl1251_error("unable to register mac80211 hw: %d", ret); | ||
1292 | return ret; | ||
1293 | } | ||
1294 | |||
1295 | wl->mac80211_registered = true; | ||
1296 | |||
1297 | wl1251_notice("loaded"); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | int wl1251_init_ieee80211(struct wl1251 *wl) | ||
1303 | { | ||
1304 | int ret; | ||
1305 | |||
1306 | /* The tx descriptor buffer and the TKIP space */ | ||
1307 | wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc) | ||
1308 | + WL1251_TKIP_IV_SPACE; | ||
1309 | |||
1310 | /* unit us */ | ||
1311 | /* FIXME: find a proper value */ | ||
1312 | wl->hw->channel_change_time = 10000; | ||
1313 | |||
1314 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1315 | IEEE80211_HW_SUPPORTS_PS | | ||
1316 | IEEE80211_HW_BEACON_FILTER | | ||
1317 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
1318 | |||
1319 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
1320 | wl->hw->wiphy->max_scan_ssids = 1; | ||
1321 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; | ||
1322 | |||
1323 | wl->hw->queues = 4; | ||
1324 | |||
1325 | if (wl->use_eeprom) | ||
1326 | wl1251_read_eeprom_mac(wl); | ||
1327 | |||
1328 | ret = wl1251_register_hw(wl); | ||
1329 | if (ret) | ||
1330 | goto out; | ||
1331 | |||
1332 | wl1251_debugfs_init(wl); | ||
1333 | wl1251_notice("initialized"); | ||
1334 | |||
1335 | ret = 0; | ||
1336 | |||
1337 | out: | ||
1338 | return ret; | ||
1339 | } | ||
1340 | EXPORT_SYMBOL_GPL(wl1251_init_ieee80211); | ||
1341 | |||
1342 | struct ieee80211_hw *wl1251_alloc_hw(void) | ||
1343 | { | ||
1344 | struct ieee80211_hw *hw; | ||
1345 | struct wl1251 *wl; | ||
1346 | int i; | ||
1347 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
1348 | |||
1349 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops); | ||
1350 | if (!hw) { | ||
1351 | wl1251_error("could not alloc ieee80211_hw"); | ||
1352 | return ERR_PTR(-ENOMEM); | ||
1353 | } | ||
1354 | |||
1355 | wl = hw->priv; | ||
1356 | memset(wl, 0, sizeof(*wl)); | ||
1357 | |||
1358 | wl->hw = hw; | ||
1359 | |||
1360 | wl->data_in_count = 0; | ||
1361 | |||
1362 | skb_queue_head_init(&wl->tx_queue); | ||
1363 | |||
1364 | INIT_WORK(&wl->filter_work, wl1251_filter_work); | ||
1365 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | ||
1366 | wl->channel = WL1251_DEFAULT_CHANNEL; | ||
1367 | wl->scanning = false; | ||
1368 | wl->default_key = 0; | ||
1369 | wl->listen_int = 1; | ||
1370 | wl->rx_counter = 0; | ||
1371 | wl->rx_handled = 0; | ||
1372 | wl->rx_current_buffer = 0; | ||
1373 | wl->rx_last_id = 0; | ||
1374 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; | ||
1375 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; | ||
1376 | wl->elp = false; | ||
1377 | wl->psm = 0; | ||
1378 | wl->psm_requested = false; | ||
1379 | wl->tx_queue_stopped = false; | ||
1380 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | ||
1381 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; | ||
1382 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; | ||
1383 | wl->vif = NULL; | ||
1384 | |||
1385 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | ||
1386 | wl->tx_frames[i] = NULL; | ||
1387 | |||
1388 | wl->next_tx_complete = 0; | ||
1389 | |||
1390 | INIT_WORK(&wl->irq_work, wl1251_irq_work); | ||
1391 | INIT_WORK(&wl->tx_work, wl1251_tx_work); | ||
1392 | |||
1393 | /* | ||
1394 | * In case our MAC address is not correctly set, | ||
1395 | * we use a random but Nokia MAC. | ||
1396 | */ | ||
1397 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
1398 | get_random_bytes(wl->mac_addr + 3, 3); | ||
1399 | |||
1400 | wl->state = WL1251_STATE_OFF; | ||
1401 | mutex_init(&wl->mutex); | ||
1402 | |||
1403 | wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; | ||
1404 | wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; | ||
1405 | |||
1406 | wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); | ||
1407 | if (!wl->rx_descriptor) { | ||
1408 | wl1251_error("could not allocate memory for rx descriptor"); | ||
1409 | ieee80211_free_hw(hw); | ||
1410 | return ERR_PTR(-ENOMEM); | ||
1411 | } | ||
1412 | |||
1413 | return hw; | ||
1414 | } | ||
1415 | EXPORT_SYMBOL_GPL(wl1251_alloc_hw); | ||
1416 | |||
1417 | int wl1251_free_hw(struct wl1251 *wl) | ||
1418 | { | ||
1419 | ieee80211_unregister_hw(wl->hw); | ||
1420 | |||
1421 | wl1251_debugfs_exit(wl); | ||
1422 | |||
1423 | kfree(wl->target_mem_map); | ||
1424 | kfree(wl->data_path); | ||
1425 | vfree(wl->fw); | ||
1426 | wl->fw = NULL; | ||
1427 | kfree(wl->nvs); | ||
1428 | wl->nvs = NULL; | ||
1429 | |||
1430 | kfree(wl->rx_descriptor); | ||
1431 | wl->rx_descriptor = NULL; | ||
1432 | |||
1433 | ieee80211_free_hw(wl->hw); | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | EXPORT_SYMBOL_GPL(wl1251_free_hw); | ||
1438 | |||
1439 | MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); | ||
1440 | MODULE_LICENSE("GPL"); | ||
1441 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | ||
1442 | MODULE_FIRMWARE(WL1251_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c deleted file mode 100644 index b55cb2bd459a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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 "wl1251_reg.h" | ||
25 | #include "wl1251_ps.h" | ||
26 | #include "wl1251_cmd.h" | ||
27 | #include "wl1251_io.h" | ||
28 | |||
29 | /* in ms */ | ||
30 | #define WL1251_WAKEUP_TIMEOUT 100 | ||
31 | |||
32 | void wl1251_elp_work(struct work_struct *work) | ||
33 | { | ||
34 | struct delayed_work *dwork; | ||
35 | struct wl1251 *wl; | ||
36 | |||
37 | dwork = container_of(work, struct delayed_work, work); | ||
38 | wl = container_of(dwork, struct wl1251, elp_work); | ||
39 | |||
40 | wl1251_debug(DEBUG_PSM, "elp work"); | ||
41 | |||
42 | mutex_lock(&wl->mutex); | ||
43 | |||
44 | if (wl->elp || !wl->psm) | ||
45 | goto out; | ||
46 | |||
47 | wl1251_debug(DEBUG_PSM, "chip to elp"); | ||
48 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | ||
49 | wl->elp = true; | ||
50 | |||
51 | out: | ||
52 | mutex_unlock(&wl->mutex); | ||
53 | } | ||
54 | |||
55 | #define ELP_ENTRY_DELAY 5 | ||
56 | |||
57 | /* Routines to toggle sleep mode while in ELP */ | ||
58 | void wl1251_ps_elp_sleep(struct wl1251 *wl) | ||
59 | { | ||
60 | unsigned long delay; | ||
61 | |||
62 | if (wl->psm) { | ||
63 | cancel_delayed_work(&wl->elp_work); | ||
64 | delay = msecs_to_jiffies(ELP_ENTRY_DELAY); | ||
65 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | ||
70 | { | ||
71 | unsigned long timeout, start; | ||
72 | u32 elp_reg; | ||
73 | |||
74 | if (!wl->elp) | ||
75 | return 0; | ||
76 | |||
77 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); | ||
78 | |||
79 | start = jiffies; | ||
80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | ||
81 | |||
82 | wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | ||
83 | |||
84 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | ||
85 | |||
86 | /* | ||
87 | * FIXME: we should wait for irq from chip but, as a temporary | ||
88 | * solution to simplify locking, let's poll instead | ||
89 | */ | ||
90 | while (!(elp_reg & ELPCTRL_WLAN_READY)) { | ||
91 | if (time_after(jiffies, timeout)) { | ||
92 | wl1251_error("elp wakeup timeout"); | ||
93 | return -ETIMEDOUT; | ||
94 | } | ||
95 | msleep(1); | ||
96 | elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); | ||
97 | } | ||
98 | |||
99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | ||
100 | jiffies_to_msecs(jiffies - start)); | ||
101 | |||
102 | wl->elp = false; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | if (enable) { | ||
112 | wl1251_debug(DEBUG_PSM, "sleep auth psm/elp"); | ||
113 | |||
114 | ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); | ||
115 | if (ret < 0) | ||
116 | return ret; | ||
117 | |||
118 | wl1251_ps_elp_sleep(wl); | ||
119 | } else { | ||
120 | wl1251_debug(DEBUG_PSM, "sleep auth cam"); | ||
121 | |||
122 | /* | ||
123 | * When the target is in ELP, we can only | ||
124 | * access the ELP control register. Thus, | ||
125 | * we have to wake the target up before | ||
126 | * changing the power authorization. | ||
127 | */ | ||
128 | |||
129 | wl1251_ps_elp_wakeup(wl); | ||
130 | |||
131 | ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); | ||
132 | if (ret < 0) | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) | ||
140 | { | ||
141 | int ret; | ||
142 | |||
143 | switch (mode) { | ||
144 | case STATION_POWER_SAVE_MODE: | ||
145 | wl1251_debug(DEBUG_PSM, "entering psm"); | ||
146 | |||
147 | /* enable beacon filtering */ | ||
148 | ret = wl1251_acx_beacon_filter_opt(wl, true); | ||
149 | if (ret < 0) | ||
150 | return ret; | ||
151 | |||
152 | ret = wl1251_acx_wake_up_conditions(wl, | ||
153 | WAKE_UP_EVENT_DTIM_BITMAP, | ||
154 | wl->listen_int); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | |||
158 | ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); | ||
159 | if (ret < 0) | ||
160 | return ret; | ||
161 | |||
162 | ret = wl1251_ps_set_elp(wl, true); | ||
163 | if (ret < 0) | ||
164 | return ret; | ||
165 | |||
166 | wl->psm = 1; | ||
167 | break; | ||
168 | case STATION_ACTIVE_MODE: | ||
169 | default: | ||
170 | wl1251_debug(DEBUG_PSM, "leaving psm"); | ||
171 | ret = wl1251_ps_set_elp(wl, false); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | |||
175 | /* disable beacon filtering */ | ||
176 | ret = wl1251_acx_beacon_filter_opt(wl, false); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | ret = wl1251_acx_wake_up_conditions(wl, | ||
181 | WAKE_UP_EVENT_DTIM_BITMAP, | ||
182 | wl->listen_int); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | wl->psm = 0; | ||
191 | break; | ||
192 | } | ||
193 | |||
194 | return ret; | ||
195 | } | ||
196 | |||
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h deleted file mode 100644 index c688ac57aee4..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | #ifndef __WL1251_PS_H__ | ||
2 | #define __WL1251_PS_H__ | ||
3 | |||
4 | /* | ||
5 | * This file is part of wl1251 | ||
6 | * | ||
7 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
8 | * Copyright (C) 2008 Nokia Corporation | ||
9 | * | ||
10 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 as published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
24 | * 02110-1301 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include "wl1251.h" | ||
29 | #include "wl1251_acx.h" | ||
30 | |||
31 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); | ||
32 | void wl1251_ps_elp_sleep(struct wl1251 *wl); | ||
33 | int wl1251_ps_elp_wakeup(struct wl1251 *wl); | ||
34 | void wl1251_elp_work(struct work_struct *work); | ||
35 | |||
36 | |||
37 | #endif /* __WL1251_PS_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h deleted file mode 100644 index d16edd9bf06c..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ /dev/null | |||
@@ -1,657 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl12xx | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __REG_H__ | ||
26 | #define __REG_H__ | ||
27 | |||
28 | #include <linux/bitops.h> | ||
29 | |||
30 | #define REGISTERS_BASE 0x00300000 | ||
31 | #define DRPW_BASE 0x00310000 | ||
32 | |||
33 | #define REGISTERS_DOWN_SIZE 0x00008800 | ||
34 | #define REGISTERS_WORK_SIZE 0x0000b000 | ||
35 | |||
36 | #define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC | ||
37 | |||
38 | /* ELP register commands */ | ||
39 | #define ELPCTRL_WAKE_UP 0x1 | ||
40 | #define ELPCTRL_WAKE_UP_WLAN_READY 0x5 | ||
41 | #define ELPCTRL_SLEEP 0x0 | ||
42 | /* ELP WLAN_READY bit */ | ||
43 | #define ELPCTRL_WLAN_READY 0x2 | ||
44 | |||
45 | /* Device Configuration registers*/ | ||
46 | #define SOR_CFG (REGISTERS_BASE + 0x0800) | ||
47 | #define ECPU_CTRL (REGISTERS_BASE + 0x0804) | ||
48 | #define HI_CFG (REGISTERS_BASE + 0x0808) | ||
49 | |||
50 | /* EEPROM registers */ | ||
51 | #define EE_START (REGISTERS_BASE + 0x080C) | ||
52 | #define EE_CTL (REGISTERS_BASE + 0x2000) | ||
53 | #define EE_DATA (REGISTERS_BASE + 0x2004) | ||
54 | #define EE_ADDR (REGISTERS_BASE + 0x2008) | ||
55 | |||
56 | #define EE_CTL_READ 2 | ||
57 | |||
58 | #define CHIP_ID_B (REGISTERS_BASE + 0x5674) | ||
59 | |||
60 | #define CHIP_ID_1251_PG10 (0x7010101) | ||
61 | #define CHIP_ID_1251_PG11 (0x7020101) | ||
62 | #define CHIP_ID_1251_PG12 (0x7030101) | ||
63 | |||
64 | #define ENABLE (REGISTERS_BASE + 0x5450) | ||
65 | |||
66 | /* Power Management registers */ | ||
67 | #define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) | ||
68 | #define ELP_CMD (REGISTERS_BASE + 0x5808) | ||
69 | #define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) | ||
70 | #define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) | ||
71 | #define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) | ||
72 | |||
73 | #define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) | ||
74 | |||
75 | /* Scratch Pad registers*/ | ||
76 | #define SCR_PAD0 (REGISTERS_BASE + 0x5608) | ||
77 | #define SCR_PAD1 (REGISTERS_BASE + 0x560C) | ||
78 | #define SCR_PAD2 (REGISTERS_BASE + 0x5610) | ||
79 | #define SCR_PAD3 (REGISTERS_BASE + 0x5614) | ||
80 | #define SCR_PAD4 (REGISTERS_BASE + 0x5618) | ||
81 | #define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) | ||
82 | #define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) | ||
83 | #define SCR_PAD5 (REGISTERS_BASE + 0x5624) | ||
84 | #define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) | ||
85 | #define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) | ||
86 | #define SCR_PAD6 (REGISTERS_BASE + 0x5630) | ||
87 | #define SCR_PAD7 (REGISTERS_BASE + 0x5634) | ||
88 | #define SCR_PAD8 (REGISTERS_BASE + 0x5638) | ||
89 | #define SCR_PAD9 (REGISTERS_BASE + 0x563C) | ||
90 | |||
91 | /* Spare registers*/ | ||
92 | #define SPARE_A1 (REGISTERS_BASE + 0x0994) | ||
93 | #define SPARE_A2 (REGISTERS_BASE + 0x0998) | ||
94 | #define SPARE_A3 (REGISTERS_BASE + 0x099C) | ||
95 | #define SPARE_A4 (REGISTERS_BASE + 0x09A0) | ||
96 | #define SPARE_A5 (REGISTERS_BASE + 0x09A4) | ||
97 | #define SPARE_A6 (REGISTERS_BASE + 0x09A8) | ||
98 | #define SPARE_A7 (REGISTERS_BASE + 0x09AC) | ||
99 | #define SPARE_A8 (REGISTERS_BASE + 0x09B0) | ||
100 | #define SPARE_B1 (REGISTERS_BASE + 0x5420) | ||
101 | #define SPARE_B2 (REGISTERS_BASE + 0x5424) | ||
102 | #define SPARE_B3 (REGISTERS_BASE + 0x5428) | ||
103 | #define SPARE_B4 (REGISTERS_BASE + 0x542C) | ||
104 | #define SPARE_B5 (REGISTERS_BASE + 0x5430) | ||
105 | #define SPARE_B6 (REGISTERS_BASE + 0x5434) | ||
106 | #define SPARE_B7 (REGISTERS_BASE + 0x5438) | ||
107 | #define SPARE_B8 (REGISTERS_BASE + 0x543C) | ||
108 | |||
109 | enum wl12xx_acx_int_reg { | ||
110 | ACX_REG_INTERRUPT_TRIG, | ||
111 | ACX_REG_INTERRUPT_TRIG_H, | ||
112 | |||
113 | /*============================================= | ||
114 | Host Interrupt Mask Register - 32bit (RW) | ||
115 | ------------------------------------------ | ||
116 | Setting a bit in this register masks the | ||
117 | corresponding interrupt to the host. | ||
118 | 0 - RX0 - Rx first dubble buffer Data Interrupt | ||
119 | 1 - TXD - Tx Data Interrupt | ||
120 | 2 - TXXFR - Tx Transfer Interrupt | ||
121 | 3 - RX1 - Rx second dubble buffer Data Interrupt | ||
122 | 4 - RXXFR - Rx Transfer Interrupt | ||
123 | 5 - EVENT_A - Event Mailbox interrupt | ||
124 | 6 - EVENT_B - Event Mailbox interrupt | ||
125 | 7 - WNONHST - Wake On Host Interrupt | ||
126 | 8 - TRACE_A - Debug Trace interrupt | ||
127 | 9 - TRACE_B - Debug Trace interrupt | ||
128 | 10 - CDCMP - Command Complete Interrupt | ||
129 | 11 - | ||
130 | 12 - | ||
131 | 13 - | ||
132 | 14 - ICOMP - Initialization Complete Interrupt | ||
133 | 16 - SG SE - Soft Gemini - Sense enable interrupt | ||
134 | 17 - SG SD - Soft Gemini - Sense disable interrupt | ||
135 | 18 - - | ||
136 | 19 - - | ||
137 | 20 - - | ||
138 | 21- - | ||
139 | Default: 0x0001 | ||
140 | *==============================================*/ | ||
141 | ACX_REG_INTERRUPT_MASK, | ||
142 | |||
143 | /*============================================= | ||
144 | Host Interrupt Mask Set 16bit, (Write only) | ||
145 | ------------------------------------------ | ||
146 | Setting a bit in this register sets | ||
147 | the corresponding bin in ACX_HINT_MASK register | ||
148 | without effecting the mask | ||
149 | state of other bits (0 = no effect). | ||
150 | ==============================================*/ | ||
151 | ACX_REG_HINT_MASK_SET, | ||
152 | |||
153 | /*============================================= | ||
154 | Host Interrupt Mask Clear 16bit,(Write only) | ||
155 | ------------------------------------------ | ||
156 | Setting a bit in this register clears | ||
157 | the corresponding bin in ACX_HINT_MASK register | ||
158 | without effecting the mask | ||
159 | state of other bits (0 = no effect). | ||
160 | =============================================*/ | ||
161 | ACX_REG_HINT_MASK_CLR, | ||
162 | |||
163 | /*============================================= | ||
164 | Host Interrupt Status Nondestructive Read | ||
165 | 16bit,(Read only) | ||
166 | ------------------------------------------ | ||
167 | The host can read this register to determine | ||
168 | which interrupts are active. | ||
169 | Reading this register doesn't | ||
170 | effect its content. | ||
171 | =============================================*/ | ||
172 | ACX_REG_INTERRUPT_NO_CLEAR, | ||
173 | |||
174 | /*============================================= | ||
175 | Host Interrupt Status Clear on Read Register | ||
176 | 16bit,(Read only) | ||
177 | ------------------------------------------ | ||
178 | The host can read this register to determine | ||
179 | which interrupts are active. | ||
180 | Reading this register clears it, | ||
181 | thus making all interrupts inactive. | ||
182 | ==============================================*/ | ||
183 | ACX_REG_INTERRUPT_CLEAR, | ||
184 | |||
185 | /*============================================= | ||
186 | Host Interrupt Acknowledge Register | ||
187 | 16bit,(Write only) | ||
188 | ------------------------------------------ | ||
189 | The host can set individual bits in this | ||
190 | register to clear (acknowledge) the corresp. | ||
191 | interrupt status bits in the HINT_STS_CLR and | ||
192 | HINT_STS_ND registers, thus making the | ||
193 | assotiated interrupt inactive. (0-no effect) | ||
194 | ==============================================*/ | ||
195 | ACX_REG_INTERRUPT_ACK, | ||
196 | |||
197 | /*=============================================== | ||
198 | Host Software Reset - 32bit RW | ||
199 | ------------------------------------------ | ||
200 | [31:1] Reserved | ||
201 | 0 SOFT_RESET Soft Reset - When this bit is set, | ||
202 | it holds the Wlan hardware in a soft reset state. | ||
203 | This reset disables all MAC and baseband processor | ||
204 | clocks except the CardBus/PCI interface clock. | ||
205 | It also initializes all MAC state machines except | ||
206 | the host interface. It does not reload the | ||
207 | contents of the EEPROM. When this bit is cleared | ||
208 | (not self-clearing), the Wlan hardware | ||
209 | exits the software reset state. | ||
210 | ===============================================*/ | ||
211 | ACX_REG_SLV_SOFT_RESET, | ||
212 | |||
213 | /*=============================================== | ||
214 | EEPROM Burst Read Start - 32bit RW | ||
215 | ------------------------------------------ | ||
216 | [31:1] Reserved | ||
217 | 0 ACX_EE_START - EEPROM Burst Read Start 0 | ||
218 | Setting this bit starts a burst read from | ||
219 | the external EEPROM. | ||
220 | If this bit is set (after reset) before an EEPROM read/write, | ||
221 | the burst read starts at EEPROM address 0. | ||
222 | Otherwise, it starts at the address | ||
223 | following the address of the previous access. | ||
224 | TheWlan hardware hardware clears this bit automatically. | ||
225 | |||
226 | Default: 0x00000000 | ||
227 | *================================================*/ | ||
228 | ACX_REG_EE_START, | ||
229 | |||
230 | /* Embedded ARM CPU Control */ | ||
231 | |||
232 | /*=============================================== | ||
233 | Halt eCPU - 32bit RW | ||
234 | ------------------------------------------ | ||
235 | 0 HALT_ECPU Halt Embedded CPU - This bit is the | ||
236 | compliment of bit 1 (MDATA2) in the SOR_CFG register. | ||
237 | During a hardware reset, this bit holds | ||
238 | the inverse of MDATA2. | ||
239 | When downloading firmware from the host, | ||
240 | set this bit (pull down MDATA2). | ||
241 | The host clears this bit after downloading the firmware into | ||
242 | zero-wait-state SSRAM. | ||
243 | When loading firmware from Flash, clear this bit (pull up MDATA2) | ||
244 | so that the eCPU can run the bootloader code in Flash | ||
245 | HALT_ECPU eCPU State | ||
246 | -------------------- | ||
247 | 1 halt eCPU | ||
248 | 0 enable eCPU | ||
249 | ===============================================*/ | ||
250 | ACX_REG_ECPU_CONTROL, | ||
251 | |||
252 | ACX_REG_TABLE_LEN | ||
253 | }; | ||
254 | |||
255 | #define ACX_SLV_SOFT_RESET_BIT BIT(0) | ||
256 | #define ACX_REG_EEPROM_START_BIT BIT(0) | ||
257 | |||
258 | /* Command/Information Mailbox Pointers */ | ||
259 | |||
260 | /*=============================================== | ||
261 | Command Mailbox Pointer - 32bit RW | ||
262 | ------------------------------------------ | ||
263 | This register holds the start address of | ||
264 | the command mailbox located in the Wlan hardware memory. | ||
265 | The host must read this pointer after a reset to | ||
266 | find the location of the command mailbox. | ||
267 | The Wlan hardware initializes the command mailbox | ||
268 | pointer with the default address of the command mailbox. | ||
269 | The command mailbox pointer is not valid until after | ||
270 | the host receives the Init Complete interrupt from | ||
271 | the Wlan hardware. | ||
272 | ===============================================*/ | ||
273 | #define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) | ||
274 | |||
275 | /*=============================================== | ||
276 | Information Mailbox Pointer - 32bit RW | ||
277 | ------------------------------------------ | ||
278 | This register holds the start address of | ||
279 | the information mailbox located in the Wlan hardware memory. | ||
280 | The host must read this pointer after a reset to find | ||
281 | the location of the information mailbox. | ||
282 | The Wlan hardware initializes the information mailbox pointer | ||
283 | with the default address of the information mailbox. | ||
284 | The information mailbox pointer is not valid | ||
285 | until after the host receives the Init Complete interrupt from | ||
286 | the Wlan hardware. | ||
287 | ===============================================*/ | ||
288 | #define REG_EVENT_MAILBOX_PTR (SCR_PAD1) | ||
289 | |||
290 | |||
291 | /* Misc */ | ||
292 | |||
293 | #define REG_ENABLE_TX_RX (ENABLE) | ||
294 | /* | ||
295 | * Rx configuration (filter) information element | ||
296 | * --------------------------------------------- | ||
297 | */ | ||
298 | #define REG_RX_CONFIG (RX_CFG) | ||
299 | #define REG_RX_FILTER (RX_FILTER_CFG) | ||
300 | |||
301 | |||
302 | #define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 | ||
303 | |||
304 | /* promiscuous - receives all valid frames */ | ||
305 | #define RX_CFG_PROMISCUOUS 0x0008 | ||
306 | |||
307 | /* receives frames from any BSSID */ | ||
308 | #define RX_CFG_BSSID 0x0020 | ||
309 | |||
310 | /* receives frames destined to any MAC address */ | ||
311 | #define RX_CFG_MAC 0x0010 | ||
312 | |||
313 | #define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 | ||
314 | #define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 | ||
315 | #define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 | ||
316 | #define RX_CFG_ENABLE_ANY_BSSID 0x0000 | ||
317 | |||
318 | /* discards all broadcast frames */ | ||
319 | #define RX_CFG_DISABLE_BCAST 0x0200 | ||
320 | |||
321 | #define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 | ||
322 | #define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 | ||
323 | #define RX_CFG_COPY_RX_STATUS 0x2000 | ||
324 | #define RX_CFG_TSF 0x10000 | ||
325 | |||
326 | #define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ | ||
327 | RX_CFG_ENABLE_ONLY_MY_BSSID) | ||
328 | |||
329 | #define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ | ||
330 | | RX_CFG_ENABLE_ANY_BSSID) | ||
331 | |||
332 | #define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ | ||
333 | RX_CFG_ENABLE_ANY_BSSID) | ||
334 | |||
335 | #define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ | ||
336 | | RX_CFG_ENABLE_ONLY_MY_BSSID) | ||
337 | |||
338 | #define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ | ||
339 | | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ | ||
340 | | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) | ||
341 | |||
342 | #define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) | ||
343 | |||
344 | #define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ | ||
345 | RX_CFG_ENABLE_ONLY_MY_DEST_MAC) | ||
346 | |||
347 | #define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ | ||
348 | RX_CFG_ENABLE_ONLY_MY_DEST_MAC) | ||
349 | |||
350 | #define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ | ||
351 | | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ | ||
352 | | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | ||
353 | |||
354 | #define RX_FILTER_OPTION_FILTER_ALL 0 | ||
355 | |||
356 | #define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ | ||
357 | | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) | ||
358 | |||
359 | #define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ | ||
360 | | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ | ||
361 | | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ | ||
362 | | CFG_RX_PRSP_EN) | ||
363 | |||
364 | |||
365 | /*=============================================== | ||
366 | EEPROM Read/Write Request 32bit RW | ||
367 | ------------------------------------------ | ||
368 | 1 EE_READ - EEPROM Read Request 1 - Setting this bit | ||
369 | loads a single byte of data into the EE_DATA | ||
370 | register from the EEPROM location specified in | ||
371 | the EE_ADDR register. | ||
372 | The Wlan hardware hardware clears this bit automatically. | ||
373 | EE_DATA is valid when this bit is cleared. | ||
374 | |||
375 | 0 EE_WRITE - EEPROM Write Request - Setting this bit | ||
376 | writes a single byte of data from the EE_DATA register into the | ||
377 | EEPROM location specified in the EE_ADDR register. | ||
378 | The Wlan hardware hardware clears this bit automatically. | ||
379 | *===============================================*/ | ||
380 | #define EE_CTL (REGISTERS_BASE + 0x2000) | ||
381 | #define ACX_EE_CTL_REG EE_CTL | ||
382 | #define EE_WRITE 0x00000001ul | ||
383 | #define EE_READ 0x00000002ul | ||
384 | |||
385 | /*=============================================== | ||
386 | EEPROM Address - 32bit RW | ||
387 | ------------------------------------------ | ||
388 | This register specifies the address | ||
389 | within the EEPROM from/to which to read/write data. | ||
390 | ===============================================*/ | ||
391 | #define EE_ADDR (REGISTERS_BASE + 0x2008) | ||
392 | #define ACX_EE_ADDR_REG EE_ADDR | ||
393 | |||
394 | /*=============================================== | ||
395 | EEPROM Data - 32bit RW | ||
396 | ------------------------------------------ | ||
397 | This register either holds the read 8 bits of | ||
398 | data from the EEPROM or the write data | ||
399 | to be written to the EEPROM. | ||
400 | ===============================================*/ | ||
401 | #define EE_DATA (REGISTERS_BASE + 0x2004) | ||
402 | #define ACX_EE_DATA_REG EE_DATA | ||
403 | |||
404 | #define EEPROM_ACCESS_TO 10000 /* timeout counter */ | ||
405 | #define START_EEPROM_MGR 0x00000001 | ||
406 | |||
407 | /*=============================================== | ||
408 | EEPROM Base Address - 32bit RW | ||
409 | ------------------------------------------ | ||
410 | This register holds the upper nine bits | ||
411 | [23:15] of the 24-bit Wlan hardware memory | ||
412 | address for burst reads from EEPROM accesses. | ||
413 | The EEPROM provides the lower 15 bits of this address. | ||
414 | The MSB of the address from the EEPROM is ignored. | ||
415 | ===============================================*/ | ||
416 | #define ACX_EE_CFG EE_CFG | ||
417 | |||
418 | /*=============================================== | ||
419 | GPIO Output Values -32bit, RW | ||
420 | ------------------------------------------ | ||
421 | [31:16] Reserved | ||
422 | [15: 0] Specify the output values (at the output driver inputs) for | ||
423 | GPIO[15:0], respectively. | ||
424 | ===============================================*/ | ||
425 | #define ACX_GPIO_OUT_REG GPIO_OUT | ||
426 | #define ACX_MAX_GPIO_LINES 15 | ||
427 | |||
428 | /*=============================================== | ||
429 | Contention window -32bit, RW | ||
430 | ------------------------------------------ | ||
431 | [31:26] Reserved | ||
432 | [25:16] Max (0x3ff) | ||
433 | [15:07] Reserved | ||
434 | [06:00] Current contention window value - default is 0x1F | ||
435 | ===============================================*/ | ||
436 | #define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG | ||
437 | #define ACX_CONT_WIND_MIN_MASK 0x0000007f | ||
438 | #define ACX_CONT_WIND_MAX 0x03ff0000 | ||
439 | |||
440 | /*=============================================== | ||
441 | HI_CFG Interface Configuration Register Values | ||
442 | ------------------------------------------ | ||
443 | ===============================================*/ | ||
444 | #define HI_CFG_UART_ENABLE 0x00000004 | ||
445 | #define HI_CFG_RST232_ENABLE 0x00000008 | ||
446 | #define HI_CFG_CLOCK_REQ_SELECT 0x00000010 | ||
447 | #define HI_CFG_HOST_INT_ENABLE 0x00000020 | ||
448 | #define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 | ||
449 | #define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 | ||
450 | #define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 | ||
451 | #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 | ||
452 | #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 | ||
453 | |||
454 | /* | ||
455 | * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile | ||
456 | * for platforms using active high interrupt level | ||
457 | */ | ||
458 | #ifdef USE_ACTIVE_HIGH | ||
459 | #define HI_CFG_DEF_VAL \ | ||
460 | (HI_CFG_UART_ENABLE | \ | ||
461 | HI_CFG_RST232_ENABLE | \ | ||
462 | HI_CFG_CLOCK_REQ_SELECT | \ | ||
463 | HI_CFG_HOST_INT_ENABLE) | ||
464 | #else | ||
465 | #define HI_CFG_DEF_VAL \ | ||
466 | (HI_CFG_UART_ENABLE | \ | ||
467 | HI_CFG_RST232_ENABLE | \ | ||
468 | HI_CFG_CLOCK_REQ_SELECT | \ | ||
469 | HI_CFG_HOST_INT_ENABLE) | ||
470 | |||
471 | #endif | ||
472 | |||
473 | #define REF_FREQ_19_2 0 | ||
474 | #define REF_FREQ_26_0 1 | ||
475 | #define REF_FREQ_38_4 2 | ||
476 | #define REF_FREQ_40_0 3 | ||
477 | #define REF_FREQ_33_6 4 | ||
478 | #define REF_FREQ_NUM 5 | ||
479 | |||
480 | #define LUT_PARAM_INTEGER_DIVIDER 0 | ||
481 | #define LUT_PARAM_FRACTIONAL_DIVIDER 1 | ||
482 | #define LUT_PARAM_ATTN_BB 2 | ||
483 | #define LUT_PARAM_ALPHA_BB 3 | ||
484 | #define LUT_PARAM_STOP_TIME_BB 4 | ||
485 | #define LUT_PARAM_BB_PLL_LOOP_FILTER 5 | ||
486 | #define LUT_PARAM_NUM 6 | ||
487 | |||
488 | #define ACX_EEPROMLESS_IND_REG (SCR_PAD4) | ||
489 | #define USE_EEPROM 0 | ||
490 | #define SOFT_RESET_MAX_TIME 1000000 | ||
491 | #define SOFT_RESET_STALL_TIME 1000 | ||
492 | #define NVS_DATA_BUNDARY_ALIGNMENT 4 | ||
493 | |||
494 | |||
495 | /* Firmware image load chunk size */ | ||
496 | #define CHUNK_SIZE 512 | ||
497 | |||
498 | /* Firmware image header size */ | ||
499 | #define FW_HDR_SIZE 8 | ||
500 | |||
501 | #define ECPU_CONTROL_HALT 0x00000101 | ||
502 | |||
503 | |||
504 | /****************************************************************************** | ||
505 | |||
506 | CHANNELS, BAND & REG DOMAINS definitions | ||
507 | |||
508 | ******************************************************************************/ | ||
509 | |||
510 | |||
511 | enum { | ||
512 | RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ | ||
513 | RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ | ||
514 | RADIO_BAND_JAPAN_4_9_GHZ = 2, | ||
515 | DEFAULT_BAND = RADIO_BAND_2_4GHZ, | ||
516 | INVALID_BAND = 0xFE, | ||
517 | MAX_RADIO_BANDS = 0xFF | ||
518 | }; | ||
519 | |||
520 | enum { | ||
521 | NO_RATE = 0, | ||
522 | RATE_1MBPS = 0x0A, | ||
523 | RATE_2MBPS = 0x14, | ||
524 | RATE_5_5MBPS = 0x37, | ||
525 | RATE_6MBPS = 0x0B, | ||
526 | RATE_9MBPS = 0x0F, | ||
527 | RATE_11MBPS = 0x6E, | ||
528 | RATE_12MBPS = 0x0A, | ||
529 | RATE_18MBPS = 0x0E, | ||
530 | RATE_22MBPS = 0xDC, | ||
531 | RATE_24MBPS = 0x09, | ||
532 | RATE_36MBPS = 0x0D, | ||
533 | RATE_48MBPS = 0x08, | ||
534 | RATE_54MBPS = 0x0C | ||
535 | }; | ||
536 | |||
537 | enum { | ||
538 | RATE_INDEX_1MBPS = 0, | ||
539 | RATE_INDEX_2MBPS = 1, | ||
540 | RATE_INDEX_5_5MBPS = 2, | ||
541 | RATE_INDEX_6MBPS = 3, | ||
542 | RATE_INDEX_9MBPS = 4, | ||
543 | RATE_INDEX_11MBPS = 5, | ||
544 | RATE_INDEX_12MBPS = 6, | ||
545 | RATE_INDEX_18MBPS = 7, | ||
546 | RATE_INDEX_22MBPS = 8, | ||
547 | RATE_INDEX_24MBPS = 9, | ||
548 | RATE_INDEX_36MBPS = 10, | ||
549 | RATE_INDEX_48MBPS = 11, | ||
550 | RATE_INDEX_54MBPS = 12, | ||
551 | RATE_INDEX_MAX = RATE_INDEX_54MBPS, | ||
552 | MAX_RATE_INDEX, | ||
553 | INVALID_RATE_INDEX = MAX_RATE_INDEX, | ||
554 | RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF | ||
555 | }; | ||
556 | |||
557 | enum { | ||
558 | RATE_MASK_1MBPS = 0x1, | ||
559 | RATE_MASK_2MBPS = 0x2, | ||
560 | RATE_MASK_5_5MBPS = 0x4, | ||
561 | RATE_MASK_11MBPS = 0x20, | ||
562 | }; | ||
563 | |||
564 | #define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ | ||
565 | #define OFDM_RATE_BIT BIT(6) | ||
566 | #define PBCC_RATE_BIT BIT(7) | ||
567 | |||
568 | enum { | ||
569 | CCK_LONG = 0, | ||
570 | CCK_SHORT = SHORT_PREAMBLE_BIT, | ||
571 | PBCC_LONG = PBCC_RATE_BIT, | ||
572 | PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, | ||
573 | OFDM = OFDM_RATE_BIT | ||
574 | }; | ||
575 | |||
576 | /****************************************************************************** | ||
577 | |||
578 | Transmit-Descriptor RATE-SET field definitions... | ||
579 | |||
580 | Define a new "Rate-Set" for TX path that incorporates the | ||
581 | Rate & Modulation info into a single 16-bit field. | ||
582 | |||
583 | TxdRateSet_t: | ||
584 | b15 - Indicates Preamble type (1=SHORT, 0=LONG). | ||
585 | Notes: | ||
586 | Must be LONG (0) for 1Mbps rate. | ||
587 | Does not apply (set to 0) for RevG-OFDM rates. | ||
588 | b14 - Indicates PBCC encoding (1=PBCC, 0=not). | ||
589 | Notes: | ||
590 | Does not apply (set to 0) for rates 1 and 2 Mbps. | ||
591 | Does not apply (set to 0) for RevG-OFDM rates. | ||
592 | b13 - Unused (set to 0). | ||
593 | b12-b0 - Supported Rate indicator bits as defined below. | ||
594 | |||
595 | ******************************************************************************/ | ||
596 | |||
597 | |||
598 | /************************************************************************* | ||
599 | |||
600 | Interrupt Trigger Register (Host -> WiLink) | ||
601 | |||
602 | **************************************************************************/ | ||
603 | |||
604 | /* Hardware to Embedded CPU Interrupts - first 32-bit register set */ | ||
605 | |||
606 | /* | ||
607 | * Host Command Interrupt. Setting this bit masks | ||
608 | * the interrupt that the host issues to inform | ||
609 | * the FW that it has sent a command | ||
610 | * to the Wlan hardware Command Mailbox. | ||
611 | */ | ||
612 | #define INTR_TRIG_CMD BIT(0) | ||
613 | |||
614 | /* | ||
615 | * Host Event Acknowlegde Interrupt. The host | ||
616 | * sets this bit to acknowledge that it received | ||
617 | * the unsolicited information from the event | ||
618 | * mailbox. | ||
619 | */ | ||
620 | #define INTR_TRIG_EVENT_ACK BIT(1) | ||
621 | |||
622 | /* | ||
623 | * The host sets this bit to inform the Wlan | ||
624 | * FW that a TX packet is in the XFER | ||
625 | * Buffer #0. | ||
626 | */ | ||
627 | #define INTR_TRIG_TX_PROC0 BIT(2) | ||
628 | |||
629 | /* | ||
630 | * The host sets this bit to inform the FW | ||
631 | * that it read a packet from RX XFER | ||
632 | * Buffer #0. | ||
633 | */ | ||
634 | #define INTR_TRIG_RX_PROC0 BIT(3) | ||
635 | |||
636 | #define INTR_TRIG_DEBUG_ACK BIT(4) | ||
637 | |||
638 | #define INTR_TRIG_STATE_CHANGED BIT(5) | ||
639 | |||
640 | |||
641 | /* Hardware to Embedded CPU Interrupts - second 32-bit register set */ | ||
642 | |||
643 | /* | ||
644 | * The host sets this bit to inform the FW | ||
645 | * that it read a packet from RX XFER | ||
646 | * Buffer #1. | ||
647 | */ | ||
648 | #define INTR_TRIG_RX_PROC1 BIT(17) | ||
649 | |||
650 | /* | ||
651 | * The host sets this bit to inform the Wlan | ||
652 | * hardware that a TX packet is in the XFER | ||
653 | * Buffer #1. | ||
654 | */ | ||
655 | #define INTR_TRIG_TX_PROC1 BIT(18) | ||
656 | |||
657 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c deleted file mode 100644 index 1b6294b3b996..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ /dev/null | |||
@@ -1,192 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/skbuff.h> | ||
26 | #include <linux/gfp.h> | ||
27 | #include <net/mac80211.h> | ||
28 | |||
29 | #include "wl1251.h" | ||
30 | #include "wl1251_reg.h" | ||
31 | #include "wl1251_io.h" | ||
32 | #include "wl1251_rx.h" | ||
33 | #include "wl1251_cmd.h" | ||
34 | #include "wl1251_acx.h" | ||
35 | |||
36 | static void wl1251_rx_header(struct wl1251 *wl, | ||
37 | struct wl1251_rx_descriptor *desc) | ||
38 | { | ||
39 | u32 rx_packet_ring_addr; | ||
40 | |||
41 | rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr; | ||
42 | if (wl->rx_current_buffer) | ||
43 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; | ||
44 | |||
45 | wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc)); | ||
46 | } | ||
47 | |||
48 | static void wl1251_rx_status(struct wl1251 *wl, | ||
49 | struct wl1251_rx_descriptor *desc, | ||
50 | struct ieee80211_rx_status *status, | ||
51 | u8 beacon) | ||
52 | { | ||
53 | u64 mactime; | ||
54 | int ret; | ||
55 | |||
56 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | ||
57 | |||
58 | status->band = IEEE80211_BAND_2GHZ; | ||
59 | status->mactime = desc->timestamp; | ||
60 | |||
61 | /* | ||
62 | * The rx status timestamp is a 32 bits value while the TSF is a | ||
63 | * 64 bits one. | ||
64 | * For IBSS merging, TSF is mandatory, so we have to get it | ||
65 | * somehow, so we ask for ACX_TSF_INFO. | ||
66 | * That could be moved to the get_tsf() hook, but unfortunately, | ||
67 | * this one must be atomic, while our SPI routines can sleep. | ||
68 | */ | ||
69 | if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) { | ||
70 | ret = wl1251_acx_tsf_info(wl, &mactime); | ||
71 | if (ret == 0) | ||
72 | status->mactime = mactime; | ||
73 | } | ||
74 | |||
75 | status->signal = desc->rssi; | ||
76 | |||
77 | /* | ||
78 | * FIXME: guessing that snr needs to be divided by two, otherwise | ||
79 | * the values don't make any sense | ||
80 | */ | ||
81 | wl->noise = desc->rssi - desc->snr / 2; | ||
82 | |||
83 | status->freq = ieee80211_channel_to_frequency(desc->channel); | ||
84 | |||
85 | status->flag |= RX_FLAG_TSFT; | ||
86 | |||
87 | if (desc->flags & RX_DESC_ENCRYPTION_MASK) { | ||
88 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | ||
89 | |||
90 | if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) | ||
91 | status->flag |= RX_FLAG_DECRYPTED; | ||
92 | |||
93 | if (unlikely(desc->flags & RX_DESC_MIC_FAIL)) | ||
94 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
95 | } | ||
96 | |||
97 | if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) | ||
98 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
99 | |||
100 | |||
101 | /* FIXME: set status->rate_idx */ | ||
102 | } | ||
103 | |||
104 | static void wl1251_rx_body(struct wl1251 *wl, | ||
105 | struct wl1251_rx_descriptor *desc) | ||
106 | { | ||
107 | struct sk_buff *skb; | ||
108 | struct ieee80211_rx_status status; | ||
109 | u8 *rx_buffer, beacon = 0; | ||
110 | u16 length, *fc; | ||
111 | u32 curr_id, last_id_inc, rx_packet_ring_addr; | ||
112 | |||
113 | length = WL1251_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH); | ||
114 | curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT; | ||
115 | last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1); | ||
116 | |||
117 | if (last_id_inc != curr_id) { | ||
118 | wl1251_warning("curr ID:%d, last ID inc:%d", | ||
119 | curr_id, last_id_inc); | ||
120 | wl->rx_last_id = curr_id; | ||
121 | } else { | ||
122 | wl->rx_last_id = last_id_inc; | ||
123 | } | ||
124 | |||
125 | rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + | ||
126 | sizeof(struct wl1251_rx_descriptor) + 20; | ||
127 | if (wl->rx_current_buffer) | ||
128 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; | ||
129 | |||
130 | skb = __dev_alloc_skb(length, GFP_KERNEL); | ||
131 | if (!skb) { | ||
132 | wl1251_error("Couldn't allocate RX frame"); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | rx_buffer = skb_put(skb, length); | ||
137 | wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); | ||
138 | |||
139 | /* The actual lenght doesn't include the target's alignment */ | ||
140 | skb->len = desc->length - PLCP_HEADER_LENGTH; | ||
141 | |||
142 | fc = (u16 *)skb->data; | ||
143 | |||
144 | if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) | ||
145 | beacon = 1; | ||
146 | |||
147 | wl1251_rx_status(wl, desc, &status, beacon); | ||
148 | |||
149 | wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | ||
150 | beacon ? "beacon" : ""); | ||
151 | |||
152 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
153 | ieee80211_rx_ni(wl->hw, skb); | ||
154 | } | ||
155 | |||
156 | static void wl1251_rx_ack(struct wl1251 *wl) | ||
157 | { | ||
158 | u32 data, addr; | ||
159 | |||
160 | if (wl->rx_current_buffer) { | ||
161 | addr = ACX_REG_INTERRUPT_TRIG_H; | ||
162 | data = INTR_TRIG_RX_PROC1; | ||
163 | } else { | ||
164 | addr = ACX_REG_INTERRUPT_TRIG; | ||
165 | data = INTR_TRIG_RX_PROC0; | ||
166 | } | ||
167 | |||
168 | wl1251_reg_write32(wl, addr, data); | ||
169 | |||
170 | /* Toggle buffer ring */ | ||
171 | wl->rx_current_buffer = !wl->rx_current_buffer; | ||
172 | } | ||
173 | |||
174 | |||
175 | void wl1251_rx(struct wl1251 *wl) | ||
176 | { | ||
177 | struct wl1251_rx_descriptor *rx_desc; | ||
178 | |||
179 | if (wl->state != WL1251_STATE_ON) | ||
180 | return; | ||
181 | |||
182 | rx_desc = wl->rx_descriptor; | ||
183 | |||
184 | /* We first read the frame's header */ | ||
185 | wl1251_rx_header(wl, rx_desc); | ||
186 | |||
187 | /* Now we can read the body */ | ||
188 | wl1251_rx_body(wl, rx_desc); | ||
189 | |||
190 | /* Finally, we need to ACK the RX */ | ||
191 | wl1251_rx_ack(wl); | ||
192 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h deleted file mode 100644 index da4e53406a0e..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_RX_H__ | ||
26 | #define __WL1251_RX_H__ | ||
27 | |||
28 | #include <linux/bitops.h> | ||
29 | |||
30 | #include "wl1251.h" | ||
31 | |||
32 | /* | ||
33 | * RX PATH | ||
34 | * | ||
35 | * The Rx path uses a double buffer and an rx_contro structure, each located | ||
36 | * at a fixed address in the device memory. The host keeps track of which | ||
37 | * buffer is available and alternates between them on a per packet basis. | ||
38 | * The size of each of the two buffers is large enough to hold the longest | ||
39 | * 802.3 packet. | ||
40 | * The RX path goes like that: | ||
41 | * 1) The target generates an interrupt each time a new packet is received. | ||
42 | * There are 2 RX interrupts, one for each buffer. | ||
43 | * 2) The host reads the received packet from one of the double buffers. | ||
44 | * 3) The host triggers a target interrupt. | ||
45 | * 4) The target prepares the next RX packet. | ||
46 | */ | ||
47 | |||
48 | #define WL1251_RX_MAX_RSSI -30 | ||
49 | #define WL1251_RX_MIN_RSSI -95 | ||
50 | |||
51 | #define WL1251_RX_ALIGN_TO 4 | ||
52 | #define WL1251_RX_ALIGN(len) (((len) + WL1251_RX_ALIGN_TO - 1) & \ | ||
53 | ~(WL1251_RX_ALIGN_TO - 1)) | ||
54 | |||
55 | #define SHORT_PREAMBLE_BIT BIT(0) | ||
56 | #define OFDM_RATE_BIT BIT(6) | ||
57 | #define PBCC_RATE_BIT BIT(7) | ||
58 | |||
59 | #define PLCP_HEADER_LENGTH 8 | ||
60 | #define RX_DESC_PACKETID_SHIFT 11 | ||
61 | #define RX_MAX_PACKET_ID 3 | ||
62 | |||
63 | #define RX_DESC_VALID_FCS 0x0001 | ||
64 | #define RX_DESC_MATCH_RXADDR1 0x0002 | ||
65 | #define RX_DESC_MCAST 0x0004 | ||
66 | #define RX_DESC_STAINTIM 0x0008 | ||
67 | #define RX_DESC_VIRTUAL_BM 0x0010 | ||
68 | #define RX_DESC_BCAST 0x0020 | ||
69 | #define RX_DESC_MATCH_SSID 0x0040 | ||
70 | #define RX_DESC_MATCH_BSSID 0x0080 | ||
71 | #define RX_DESC_ENCRYPTION_MASK 0x0300 | ||
72 | #define RX_DESC_MEASURMENT 0x0400 | ||
73 | #define RX_DESC_SEQNUM_MASK 0x1800 | ||
74 | #define RX_DESC_MIC_FAIL 0x2000 | ||
75 | #define RX_DESC_DECRYPT_FAIL 0x4000 | ||
76 | |||
77 | struct wl1251_rx_descriptor { | ||
78 | u32 timestamp; /* In microseconds */ | ||
79 | u16 length; /* Paylod length, including headers */ | ||
80 | u16 flags; | ||
81 | |||
82 | /* | ||
83 | * 0 - 802.11 | ||
84 | * 1 - 802.3 | ||
85 | * 2 - IP | ||
86 | * 3 - Raw Codec | ||
87 | */ | ||
88 | u8 type; | ||
89 | |||
90 | /* | ||
91 | * Received Rate: | ||
92 | * 0x0A - 1MBPS | ||
93 | * 0x14 - 2MBPS | ||
94 | * 0x37 - 5_5MBPS | ||
95 | * 0x0B - 6MBPS | ||
96 | * 0x0F - 9MBPS | ||
97 | * 0x6E - 11MBPS | ||
98 | * 0x0A - 12MBPS | ||
99 | * 0x0E - 18MBPS | ||
100 | * 0xDC - 22MBPS | ||
101 | * 0x09 - 24MBPS | ||
102 | * 0x0D - 36MBPS | ||
103 | * 0x08 - 48MBPS | ||
104 | * 0x0C - 54MBPS | ||
105 | */ | ||
106 | u8 rate; | ||
107 | |||
108 | u8 mod_pre; /* Modulation and preamble */ | ||
109 | u8 channel; | ||
110 | |||
111 | /* | ||
112 | * 0 - 2.4 Ghz | ||
113 | * 1 - 5 Ghz | ||
114 | */ | ||
115 | u8 band; | ||
116 | |||
117 | s8 rssi; /* in dB */ | ||
118 | u8 rcpi; /* in dB */ | ||
119 | u8 snr; /* in dB */ | ||
120 | } __packed; | ||
121 | |||
122 | void wl1251_rx(struct wl1251 *wl); | ||
123 | |||
124 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c deleted file mode 100644 index b901b6135654..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ /dev/null | |||
@@ -1,342 +0,0 @@ | |||
1 | /* | ||
2 | * wl12xx SDIO routines | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
16 | * 02110-1301 USA | ||
17 | * | ||
18 | * Copyright (C) 2005 Texas Instruments Incorporated | ||
19 | * Copyright (C) 2008 Google Inc | ||
20 | * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/mod_devicetable.h> | ||
24 | #include <linux/mmc/sdio_func.h> | ||
25 | #include <linux/mmc/sdio_ids.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/spi/wl12xx.h> | ||
28 | #include <linux/irq.h> | ||
29 | |||
30 | #include "wl1251.h" | ||
31 | |||
32 | #ifndef SDIO_VENDOR_ID_TI | ||
33 | #define SDIO_VENDOR_ID_TI 0x104c | ||
34 | #endif | ||
35 | |||
36 | #ifndef SDIO_DEVICE_ID_TI_WL1251 | ||
37 | #define SDIO_DEVICE_ID_TI_WL1251 0x9066 | ||
38 | #endif | ||
39 | |||
40 | struct wl1251_sdio { | ||
41 | struct sdio_func *func; | ||
42 | u32 elp_val; | ||
43 | }; | ||
44 | |||
45 | static struct wl12xx_platform_data *wl12xx_board_data; | ||
46 | |||
47 | static struct sdio_func *wl_to_func(struct wl1251 *wl) | ||
48 | { | ||
49 | struct wl1251_sdio *wl_sdio = wl->if_priv; | ||
50 | return wl_sdio->func; | ||
51 | } | ||
52 | |||
53 | static void wl1251_sdio_interrupt(struct sdio_func *func) | ||
54 | { | ||
55 | struct wl1251 *wl = sdio_get_drvdata(func); | ||
56 | |||
57 | wl1251_debug(DEBUG_IRQ, "IRQ"); | ||
58 | |||
59 | /* FIXME should be synchronous for sdio */ | ||
60 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
61 | } | ||
62 | |||
63 | static const struct sdio_device_id wl1251_devices[] = { | ||
64 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) }, | ||
65 | {} | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(sdio, wl1251_devices); | ||
68 | |||
69 | |||
70 | static void wl1251_sdio_read(struct wl1251 *wl, int addr, | ||
71 | void *buf, size_t len) | ||
72 | { | ||
73 | int ret; | ||
74 | struct sdio_func *func = wl_to_func(wl); | ||
75 | |||
76 | sdio_claim_host(func); | ||
77 | ret = sdio_memcpy_fromio(func, buf, addr, len); | ||
78 | if (ret) | ||
79 | wl1251_error("sdio read failed (%d)", ret); | ||
80 | sdio_release_host(func); | ||
81 | } | ||
82 | |||
83 | static void wl1251_sdio_write(struct wl1251 *wl, int addr, | ||
84 | void *buf, size_t len) | ||
85 | { | ||
86 | int ret; | ||
87 | struct sdio_func *func = wl_to_func(wl); | ||
88 | |||
89 | sdio_claim_host(func); | ||
90 | ret = sdio_memcpy_toio(func, addr, buf, len); | ||
91 | if (ret) | ||
92 | wl1251_error("sdio write failed (%d)", ret); | ||
93 | sdio_release_host(func); | ||
94 | } | ||
95 | |||
96 | static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) | ||
97 | { | ||
98 | int ret = 0; | ||
99 | struct wl1251_sdio *wl_sdio = wl->if_priv; | ||
100 | struct sdio_func *func = wl_sdio->func; | ||
101 | |||
102 | /* | ||
103 | * The hardware only supports RAW (read after write) access for | ||
104 | * reading, regular sdio_readb won't work here (it interprets | ||
105 | * the unused bits of CMD52 as write data even if we send read | ||
106 | * request). | ||
107 | */ | ||
108 | sdio_claim_host(func); | ||
109 | *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret); | ||
110 | sdio_release_host(func); | ||
111 | |||
112 | if (ret) | ||
113 | wl1251_error("sdio_readb failed (%d)", ret); | ||
114 | } | ||
115 | |||
116 | static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) | ||
117 | { | ||
118 | int ret = 0; | ||
119 | struct wl1251_sdio *wl_sdio = wl->if_priv; | ||
120 | struct sdio_func *func = wl_sdio->func; | ||
121 | |||
122 | sdio_claim_host(func); | ||
123 | sdio_writeb(func, val, addr, &ret); | ||
124 | sdio_release_host(func); | ||
125 | |||
126 | if (ret) | ||
127 | wl1251_error("sdio_writeb failed (%d)", ret); | ||
128 | else | ||
129 | wl_sdio->elp_val = val; | ||
130 | } | ||
131 | |||
132 | static void wl1251_sdio_reset(struct wl1251 *wl) | ||
133 | { | ||
134 | } | ||
135 | |||
136 | static void wl1251_sdio_enable_irq(struct wl1251 *wl) | ||
137 | { | ||
138 | struct sdio_func *func = wl_to_func(wl); | ||
139 | |||
140 | sdio_claim_host(func); | ||
141 | sdio_claim_irq(func, wl1251_sdio_interrupt); | ||
142 | sdio_release_host(func); | ||
143 | } | ||
144 | |||
145 | static void wl1251_sdio_disable_irq(struct wl1251 *wl) | ||
146 | { | ||
147 | struct sdio_func *func = wl_to_func(wl); | ||
148 | |||
149 | sdio_claim_host(func); | ||
150 | sdio_release_irq(func); | ||
151 | sdio_release_host(func); | ||
152 | } | ||
153 | |||
154 | /* Interrupts when using dedicated WLAN_IRQ pin */ | ||
155 | static irqreturn_t wl1251_line_irq(int irq, void *cookie) | ||
156 | { | ||
157 | struct wl1251 *wl = cookie; | ||
158 | |||
159 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
160 | |||
161 | return IRQ_HANDLED; | ||
162 | } | ||
163 | |||
164 | static void wl1251_enable_line_irq(struct wl1251 *wl) | ||
165 | { | ||
166 | return enable_irq(wl->irq); | ||
167 | } | ||
168 | |||
169 | static void wl1251_disable_line_irq(struct wl1251 *wl) | ||
170 | { | ||
171 | return disable_irq(wl->irq); | ||
172 | } | ||
173 | |||
174 | static void wl1251_sdio_set_power(bool enable) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static struct wl1251_if_operations wl1251_sdio_ops = { | ||
179 | .read = wl1251_sdio_read, | ||
180 | .write = wl1251_sdio_write, | ||
181 | .write_elp = wl1251_sdio_write_elp, | ||
182 | .read_elp = wl1251_sdio_read_elp, | ||
183 | .reset = wl1251_sdio_reset, | ||
184 | }; | ||
185 | |||
186 | static int wl1251_platform_probe(struct platform_device *pdev) | ||
187 | { | ||
188 | if (pdev->id != -1) { | ||
189 | wl1251_error("can only handle single device"); | ||
190 | return -ENODEV; | ||
191 | } | ||
192 | |||
193 | wl12xx_board_data = pdev->dev.platform_data; | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Dummy platform_driver for passing platform_data to this driver, | ||
199 | * until we have a way to pass this through SDIO subsystem or | ||
200 | * some other way. | ||
201 | */ | ||
202 | static struct platform_driver wl1251_platform_driver = { | ||
203 | .driver = { | ||
204 | .name = "wl1251_data", | ||
205 | .owner = THIS_MODULE, | ||
206 | }, | ||
207 | .probe = wl1251_platform_probe, | ||
208 | }; | ||
209 | |||
210 | static int wl1251_sdio_probe(struct sdio_func *func, | ||
211 | const struct sdio_device_id *id) | ||
212 | { | ||
213 | int ret; | ||
214 | struct wl1251 *wl; | ||
215 | struct ieee80211_hw *hw; | ||
216 | struct wl1251_sdio *wl_sdio; | ||
217 | |||
218 | hw = wl1251_alloc_hw(); | ||
219 | if (IS_ERR(hw)) | ||
220 | return PTR_ERR(hw); | ||
221 | |||
222 | wl = hw->priv; | ||
223 | |||
224 | wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL); | ||
225 | if (wl_sdio == NULL) { | ||
226 | ret = -ENOMEM; | ||
227 | goto out_free_hw; | ||
228 | } | ||
229 | |||
230 | sdio_claim_host(func); | ||
231 | ret = sdio_enable_func(func); | ||
232 | if (ret) | ||
233 | goto release; | ||
234 | |||
235 | sdio_set_block_size(func, 512); | ||
236 | sdio_release_host(func); | ||
237 | |||
238 | SET_IEEE80211_DEV(hw, &func->dev); | ||
239 | wl_sdio->func = func; | ||
240 | wl->if_priv = wl_sdio; | ||
241 | wl->if_ops = &wl1251_sdio_ops; | ||
242 | wl->set_power = wl1251_sdio_set_power; | ||
243 | |||
244 | if (wl12xx_board_data != NULL) { | ||
245 | wl->set_power = wl12xx_board_data->set_power; | ||
246 | wl->irq = wl12xx_board_data->irq; | ||
247 | wl->use_eeprom = wl12xx_board_data->use_eeprom; | ||
248 | } | ||
249 | |||
250 | if (wl->irq) { | ||
251 | ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); | ||
252 | if (ret < 0) { | ||
253 | wl1251_error("request_irq() failed: %d", ret); | ||
254 | goto disable; | ||
255 | } | ||
256 | |||
257 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
258 | disable_irq(wl->irq); | ||
259 | |||
260 | wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; | ||
261 | wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; | ||
262 | |||
263 | wl1251_info("using dedicated interrupt line"); | ||
264 | } else { | ||
265 | wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; | ||
266 | wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; | ||
267 | |||
268 | wl1251_info("using SDIO interrupt"); | ||
269 | } | ||
270 | |||
271 | ret = wl1251_init_ieee80211(wl); | ||
272 | if (ret) | ||
273 | goto out_free_irq; | ||
274 | |||
275 | sdio_set_drvdata(func, wl); | ||
276 | return ret; | ||
277 | |||
278 | out_free_irq: | ||
279 | if (wl->irq) | ||
280 | free_irq(wl->irq, wl); | ||
281 | disable: | ||
282 | sdio_claim_host(func); | ||
283 | sdio_disable_func(func); | ||
284 | release: | ||
285 | sdio_release_host(func); | ||
286 | kfree(wl_sdio); | ||
287 | out_free_hw: | ||
288 | wl1251_free_hw(wl); | ||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static void __devexit wl1251_sdio_remove(struct sdio_func *func) | ||
293 | { | ||
294 | struct wl1251 *wl = sdio_get_drvdata(func); | ||
295 | struct wl1251_sdio *wl_sdio = wl->if_priv; | ||
296 | |||
297 | if (wl->irq) | ||
298 | free_irq(wl->irq, wl); | ||
299 | kfree(wl_sdio); | ||
300 | wl1251_free_hw(wl); | ||
301 | |||
302 | sdio_claim_host(func); | ||
303 | sdio_release_irq(func); | ||
304 | sdio_disable_func(func); | ||
305 | sdio_release_host(func); | ||
306 | } | ||
307 | |||
308 | static struct sdio_driver wl1251_sdio_driver = { | ||
309 | .name = "wl1251_sdio", | ||
310 | .id_table = wl1251_devices, | ||
311 | .probe = wl1251_sdio_probe, | ||
312 | .remove = __devexit_p(wl1251_sdio_remove), | ||
313 | }; | ||
314 | |||
315 | static int __init wl1251_sdio_init(void) | ||
316 | { | ||
317 | int err; | ||
318 | |||
319 | err = platform_driver_register(&wl1251_platform_driver); | ||
320 | if (err) { | ||
321 | wl1251_error("failed to register platform driver: %d", err); | ||
322 | return err; | ||
323 | } | ||
324 | |||
325 | err = sdio_register_driver(&wl1251_sdio_driver); | ||
326 | if (err) | ||
327 | wl1251_error("failed to register sdio driver: %d", err); | ||
328 | return err; | ||
329 | } | ||
330 | |||
331 | static void __exit wl1251_sdio_exit(void) | ||
332 | { | ||
333 | sdio_unregister_driver(&wl1251_sdio_driver); | ||
334 | platform_driver_unregister(&wl1251_platform_driver); | ||
335 | wl1251_notice("unloaded"); | ||
336 | } | ||
337 | |||
338 | module_init(wl1251_sdio_init); | ||
339 | module_exit(wl1251_sdio_exit); | ||
340 | |||
341 | MODULE_LICENSE("GPL"); | ||
342 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c deleted file mode 100644 index 27fdfaaeb074..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ /dev/null | |||
@@ -1,348 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@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/irq.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/crc7.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | #include <linux/spi/wl12xx.h> | ||
30 | |||
31 | #include "wl1251.h" | ||
32 | #include "wl1251_reg.h" | ||
33 | #include "wl1251_spi.h" | ||
34 | |||
35 | static irqreturn_t wl1251_irq(int irq, void *cookie) | ||
36 | { | ||
37 | struct wl1251 *wl; | ||
38 | |||
39 | wl1251_debug(DEBUG_IRQ, "IRQ"); | ||
40 | |||
41 | wl = cookie; | ||
42 | |||
43 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
44 | |||
45 | return IRQ_HANDLED; | ||
46 | } | ||
47 | |||
48 | static struct spi_device *wl_to_spi(struct wl1251 *wl) | ||
49 | { | ||
50 | return wl->if_priv; | ||
51 | } | ||
52 | |||
53 | static void wl1251_spi_reset(struct wl1251 *wl) | ||
54 | { | ||
55 | u8 *cmd; | ||
56 | struct spi_transfer t; | ||
57 | struct spi_message m; | ||
58 | |||
59 | cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
60 | if (!cmd) { | ||
61 | wl1251_error("could not allocate cmd for spi reset"); | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | memset(&t, 0, sizeof(t)); | ||
66 | spi_message_init(&m); | ||
67 | |||
68 | memset(cmd, 0xff, WSPI_INIT_CMD_LEN); | ||
69 | |||
70 | t.tx_buf = cmd; | ||
71 | t.len = WSPI_INIT_CMD_LEN; | ||
72 | spi_message_add_tail(&t, &m); | ||
73 | |||
74 | spi_sync(wl_to_spi(wl), &m); | ||
75 | |||
76 | wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | ||
77 | } | ||
78 | |||
79 | static void wl1251_spi_wake(struct wl1251 *wl) | ||
80 | { | ||
81 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | ||
82 | struct spi_transfer t; | ||
83 | struct spi_message m; | ||
84 | |||
85 | cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
86 | if (!cmd) { | ||
87 | wl1251_error("could not allocate cmd for spi init"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | memset(crc, 0, sizeof(crc)); | ||
92 | memset(&t, 0, sizeof(t)); | ||
93 | spi_message_init(&m); | ||
94 | |||
95 | /* | ||
96 | * Set WSPI_INIT_COMMAND | ||
97 | * the data is being send from the MSB to LSB | ||
98 | */ | ||
99 | cmd[2] = 0xff; | ||
100 | cmd[3] = 0xff; | ||
101 | cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; | ||
102 | cmd[0] = 0; | ||
103 | cmd[7] = 0; | ||
104 | cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; | ||
105 | cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; | ||
106 | |||
107 | if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) | ||
108 | cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; | ||
109 | else | ||
110 | cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; | ||
111 | |||
112 | cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | ||
113 | | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; | ||
114 | |||
115 | crc[0] = cmd[1]; | ||
116 | crc[1] = cmd[0]; | ||
117 | crc[2] = cmd[7]; | ||
118 | crc[3] = cmd[6]; | ||
119 | crc[4] = cmd[5]; | ||
120 | |||
121 | cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; | ||
122 | cmd[4] |= WSPI_INIT_CMD_END; | ||
123 | |||
124 | t.tx_buf = cmd; | ||
125 | t.len = WSPI_INIT_CMD_LEN; | ||
126 | spi_message_add_tail(&t, &m); | ||
127 | |||
128 | spi_sync(wl_to_spi(wl), &m); | ||
129 | |||
130 | wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | ||
131 | } | ||
132 | |||
133 | static void wl1251_spi_reset_wake(struct wl1251 *wl) | ||
134 | { | ||
135 | wl1251_spi_reset(wl); | ||
136 | wl1251_spi_wake(wl); | ||
137 | } | ||
138 | |||
139 | static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, | ||
140 | size_t len) | ||
141 | { | ||
142 | struct spi_transfer t[3]; | ||
143 | struct spi_message m; | ||
144 | u8 *busy_buf; | ||
145 | u32 *cmd; | ||
146 | |||
147 | cmd = &wl->buffer_cmd; | ||
148 | busy_buf = wl->buffer_busyword; | ||
149 | |||
150 | *cmd = 0; | ||
151 | *cmd |= WSPI_CMD_READ; | ||
152 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
153 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
154 | |||
155 | spi_message_init(&m); | ||
156 | memset(t, 0, sizeof(t)); | ||
157 | |||
158 | t[0].tx_buf = cmd; | ||
159 | t[0].len = 4; | ||
160 | spi_message_add_tail(&t[0], &m); | ||
161 | |||
162 | /* Busy and non busy words read */ | ||
163 | t[1].rx_buf = busy_buf; | ||
164 | t[1].len = WL1251_BUSY_WORD_LEN; | ||
165 | spi_message_add_tail(&t[1], &m); | ||
166 | |||
167 | t[2].rx_buf = buf; | ||
168 | t[2].len = len; | ||
169 | spi_message_add_tail(&t[2], &m); | ||
170 | |||
171 | spi_sync(wl_to_spi(wl), &m); | ||
172 | |||
173 | /* FIXME: check busy words */ | ||
174 | |||
175 | wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | ||
176 | wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | ||
177 | } | ||
178 | |||
179 | static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, | ||
180 | size_t len) | ||
181 | { | ||
182 | struct spi_transfer t[2]; | ||
183 | struct spi_message m; | ||
184 | u32 *cmd; | ||
185 | |||
186 | cmd = &wl->buffer_cmd; | ||
187 | |||
188 | *cmd = 0; | ||
189 | *cmd |= WSPI_CMD_WRITE; | ||
190 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
191 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
192 | |||
193 | spi_message_init(&m); | ||
194 | memset(t, 0, sizeof(t)); | ||
195 | |||
196 | t[0].tx_buf = cmd; | ||
197 | t[0].len = sizeof(*cmd); | ||
198 | spi_message_add_tail(&t[0], &m); | ||
199 | |||
200 | t[1].tx_buf = buf; | ||
201 | t[1].len = len; | ||
202 | spi_message_add_tail(&t[1], &m); | ||
203 | |||
204 | spi_sync(wl_to_spi(wl), &m); | ||
205 | |||
206 | wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | ||
207 | wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | ||
208 | } | ||
209 | |||
210 | static void wl1251_spi_enable_irq(struct wl1251 *wl) | ||
211 | { | ||
212 | return enable_irq(wl->irq); | ||
213 | } | ||
214 | |||
215 | static void wl1251_spi_disable_irq(struct wl1251 *wl) | ||
216 | { | ||
217 | return disable_irq(wl->irq); | ||
218 | } | ||
219 | |||
220 | static const struct wl1251_if_operations wl1251_spi_ops = { | ||
221 | .read = wl1251_spi_read, | ||
222 | .write = wl1251_spi_write, | ||
223 | .reset = wl1251_spi_reset_wake, | ||
224 | .enable_irq = wl1251_spi_enable_irq, | ||
225 | .disable_irq = wl1251_spi_disable_irq, | ||
226 | }; | ||
227 | |||
228 | static int __devinit wl1251_spi_probe(struct spi_device *spi) | ||
229 | { | ||
230 | struct wl12xx_platform_data *pdata; | ||
231 | struct ieee80211_hw *hw; | ||
232 | struct wl1251 *wl; | ||
233 | int ret; | ||
234 | |||
235 | pdata = spi->dev.platform_data; | ||
236 | if (!pdata) { | ||
237 | wl1251_error("no platform data"); | ||
238 | return -ENODEV; | ||
239 | } | ||
240 | |||
241 | hw = wl1251_alloc_hw(); | ||
242 | if (IS_ERR(hw)) | ||
243 | return PTR_ERR(hw); | ||
244 | |||
245 | wl = hw->priv; | ||
246 | |||
247 | SET_IEEE80211_DEV(hw, &spi->dev); | ||
248 | dev_set_drvdata(&spi->dev, wl); | ||
249 | wl->if_priv = spi; | ||
250 | wl->if_ops = &wl1251_spi_ops; | ||
251 | |||
252 | /* This is the only SPI value that we need to set here, the rest | ||
253 | * comes from the board-peripherals file */ | ||
254 | spi->bits_per_word = 32; | ||
255 | |||
256 | ret = spi_setup(spi); | ||
257 | if (ret < 0) { | ||
258 | wl1251_error("spi_setup failed"); | ||
259 | goto out_free; | ||
260 | } | ||
261 | |||
262 | wl->set_power = pdata->set_power; | ||
263 | if (!wl->set_power) { | ||
264 | wl1251_error("set power function missing in platform data"); | ||
265 | return -ENODEV; | ||
266 | } | ||
267 | |||
268 | wl->irq = spi->irq; | ||
269 | if (wl->irq < 0) { | ||
270 | wl1251_error("irq missing in platform data"); | ||
271 | return -ENODEV; | ||
272 | } | ||
273 | |||
274 | wl->use_eeprom = pdata->use_eeprom; | ||
275 | |||
276 | ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); | ||
277 | if (ret < 0) { | ||
278 | wl1251_error("request_irq() failed: %d", ret); | ||
279 | goto out_free; | ||
280 | } | ||
281 | |||
282 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
283 | |||
284 | disable_irq(wl->irq); | ||
285 | |||
286 | ret = wl1251_init_ieee80211(wl); | ||
287 | if (ret) | ||
288 | goto out_irq; | ||
289 | |||
290 | return 0; | ||
291 | |||
292 | out_irq: | ||
293 | free_irq(wl->irq, wl); | ||
294 | |||
295 | out_free: | ||
296 | ieee80211_free_hw(hw); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int __devexit wl1251_spi_remove(struct spi_device *spi) | ||
302 | { | ||
303 | struct wl1251 *wl = dev_get_drvdata(&spi->dev); | ||
304 | |||
305 | free_irq(wl->irq, wl); | ||
306 | wl1251_free_hw(wl); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static struct spi_driver wl1251_spi_driver = { | ||
312 | .driver = { | ||
313 | .name = DRIVER_NAME, | ||
314 | .bus = &spi_bus_type, | ||
315 | .owner = THIS_MODULE, | ||
316 | }, | ||
317 | |||
318 | .probe = wl1251_spi_probe, | ||
319 | .remove = __devexit_p(wl1251_spi_remove), | ||
320 | }; | ||
321 | |||
322 | static int __init wl1251_spi_init(void) | ||
323 | { | ||
324 | int ret; | ||
325 | |||
326 | ret = spi_register_driver(&wl1251_spi_driver); | ||
327 | if (ret < 0) { | ||
328 | wl1251_error("failed to register spi driver: %d", ret); | ||
329 | goto out; | ||
330 | } | ||
331 | |||
332 | out: | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | static void __exit wl1251_spi_exit(void) | ||
337 | { | ||
338 | spi_unregister_driver(&wl1251_spi_driver); | ||
339 | |||
340 | wl1251_notice("unloaded"); | ||
341 | } | ||
342 | |||
343 | module_init(wl1251_spi_init); | ||
344 | module_exit(wl1251_spi_exit); | ||
345 | |||
346 | MODULE_LICENSE("GPL"); | ||
347 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | ||
348 | MODULE_ALIAS("spi:wl1251"); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h deleted file mode 100644 index 2e273a97e7f3..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_spi.h +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_SPI_H__ | ||
26 | #define __WL1251_SPI_H__ | ||
27 | |||
28 | #include "wl1251_cmd.h" | ||
29 | #include "wl1251_acx.h" | ||
30 | #include "wl1251_reg.h" | ||
31 | |||
32 | #define WSPI_CMD_READ 0x40000000 | ||
33 | #define WSPI_CMD_WRITE 0x00000000 | ||
34 | #define WSPI_CMD_FIXED 0x20000000 | ||
35 | #define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 | ||
36 | #define WSPI_CMD_BYTE_LENGTH_OFFSET 17 | ||
37 | #define WSPI_CMD_BYTE_ADDR 0x0001FFFF | ||
38 | |||
39 | #define WSPI_INIT_CMD_CRC_LEN 5 | ||
40 | |||
41 | #define WSPI_INIT_CMD_START 0x00 | ||
42 | #define WSPI_INIT_CMD_TX 0x40 | ||
43 | /* the extra bypass bit is sampled by the TNET as '1' */ | ||
44 | #define WSPI_INIT_CMD_BYPASS_BIT 0x80 | ||
45 | #define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 | ||
46 | #define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 | ||
47 | #define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 | ||
48 | #define WSPI_INIT_CMD_IOD 0x40 | ||
49 | #define WSPI_INIT_CMD_IP 0x20 | ||
50 | #define WSPI_INIT_CMD_CS 0x10 | ||
51 | #define WSPI_INIT_CMD_WS 0x08 | ||
52 | #define WSPI_INIT_CMD_WSPI 0x01 | ||
53 | #define WSPI_INIT_CMD_END 0x01 | ||
54 | |||
55 | #define WSPI_INIT_CMD_LEN 8 | ||
56 | |||
57 | #define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ | ||
58 | ((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32)) | ||
59 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | ||
60 | |||
61 | #endif /* __WL1251_SPI_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c deleted file mode 100644 index a38ec199187a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ /dev/null | |||
@@ -1,562 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | |||
28 | #include "wl1251.h" | ||
29 | #include "wl1251_reg.h" | ||
30 | #include "wl1251_tx.h" | ||
31 | #include "wl1251_ps.h" | ||
32 | #include "wl1251_io.h" | ||
33 | |||
34 | static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) | ||
35 | { | ||
36 | int used, data_in_count; | ||
37 | |||
38 | data_in_count = wl->data_in_count; | ||
39 | |||
40 | if (data_in_count < data_out_count) | ||
41 | /* data_in_count has wrapped */ | ||
42 | data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1; | ||
43 | |||
44 | used = data_in_count - data_out_count; | ||
45 | |||
46 | WARN_ON(used < 0); | ||
47 | WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM); | ||
48 | |||
49 | if (used >= DP_TX_PACKET_RING_CHUNK_NUM) | ||
50 | return true; | ||
51 | else | ||
52 | return false; | ||
53 | } | ||
54 | |||
55 | static int wl1251_tx_path_status(struct wl1251 *wl) | ||
56 | { | ||
57 | u32 status, addr, data_out_count; | ||
58 | bool busy; | ||
59 | |||
60 | addr = wl->data_path->tx_control_addr; | ||
61 | status = wl1251_mem_read32(wl, addr); | ||
62 | data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK; | ||
63 | busy = wl1251_tx_double_buffer_busy(wl, data_out_count); | ||
64 | |||
65 | if (busy) | ||
66 | return -EBUSY; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int wl1251_tx_id(struct wl1251 *wl, struct sk_buff *skb) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | ||
76 | if (wl->tx_frames[i] == NULL) { | ||
77 | wl->tx_frames[i] = skb; | ||
78 | return i; | ||
79 | } | ||
80 | |||
81 | return -EBUSY; | ||
82 | } | ||
83 | |||
84 | static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr, | ||
85 | struct ieee80211_tx_info *control, u16 fc) | ||
86 | { | ||
87 | *(u16 *)&tx_hdr->control = 0; | ||
88 | |||
89 | tx_hdr->control.rate_policy = 0; | ||
90 | |||
91 | /* 802.11 packets */ | ||
92 | tx_hdr->control.packet_type = 0; | ||
93 | |||
94 | if (control->flags & IEEE80211_TX_CTL_NO_ACK) | ||
95 | tx_hdr->control.ack_policy = 1; | ||
96 | |||
97 | tx_hdr->control.tx_complete = 1; | ||
98 | |||
99 | if ((fc & IEEE80211_FTYPE_DATA) && | ||
100 | ((fc & IEEE80211_STYPE_QOS_DATA) || | ||
101 | (fc & IEEE80211_STYPE_QOS_NULLFUNC))) | ||
102 | tx_hdr->control.qos = 1; | ||
103 | } | ||
104 | |||
105 | /* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */ | ||
106 | #define MAX_MSDU_SECURITY_LENGTH 16 | ||
107 | #define MAX_MPDU_SECURITY_LENGTH 16 | ||
108 | #define WLAN_QOS_HDR_LEN 26 | ||
109 | #define MAX_MPDU_HEADER_AND_SECURITY (MAX_MPDU_SECURITY_LENGTH + \ | ||
110 | WLAN_QOS_HDR_LEN) | ||
111 | #define HW_BLOCK_SIZE 252 | ||
112 | static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr) | ||
113 | { | ||
114 | u16 payload_len, frag_threshold, mem_blocks; | ||
115 | u16 num_mpdus, mem_blocks_per_frag; | ||
116 | |||
117 | frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
118 | tx_hdr->frag_threshold = cpu_to_le16(frag_threshold); | ||
119 | |||
120 | payload_len = le16_to_cpu(tx_hdr->length) + MAX_MSDU_SECURITY_LENGTH; | ||
121 | |||
122 | if (payload_len > frag_threshold) { | ||
123 | mem_blocks_per_frag = | ||
124 | ((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) / | ||
125 | HW_BLOCK_SIZE) + 1; | ||
126 | num_mpdus = payload_len / frag_threshold; | ||
127 | mem_blocks = num_mpdus * mem_blocks_per_frag; | ||
128 | payload_len -= num_mpdus * frag_threshold; | ||
129 | num_mpdus++; | ||
130 | |||
131 | } else { | ||
132 | mem_blocks_per_frag = 0; | ||
133 | mem_blocks = 0; | ||
134 | num_mpdus = 1; | ||
135 | } | ||
136 | |||
137 | mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1; | ||
138 | |||
139 | if (num_mpdus > 1) | ||
140 | mem_blocks += min(num_mpdus, mem_blocks_per_frag); | ||
141 | |||
142 | tx_hdr->num_mem_blocks = mem_blocks; | ||
143 | } | ||
144 | |||
145 | static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, | ||
146 | struct ieee80211_tx_info *control) | ||
147 | { | ||
148 | struct tx_double_buffer_desc *tx_hdr; | ||
149 | struct ieee80211_rate *rate; | ||
150 | int id; | ||
151 | u16 fc; | ||
152 | |||
153 | if (!skb) | ||
154 | return -EINVAL; | ||
155 | |||
156 | id = wl1251_tx_id(wl, skb); | ||
157 | if (id < 0) | ||
158 | return id; | ||
159 | |||
160 | fc = *(u16 *)skb->data; | ||
161 | tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb, | ||
162 | sizeof(*tx_hdr)); | ||
163 | |||
164 | tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr)); | ||
165 | rate = ieee80211_get_tx_rate(wl->hw, control); | ||
166 | tx_hdr->rate = cpu_to_le16(rate->hw_value); | ||
167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); | ||
168 | tx_hdr->id = id; | ||
169 | |||
170 | tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb)); | ||
171 | |||
172 | wl1251_tx_control(tx_hdr, control, fc); | ||
173 | wl1251_tx_frag_block_num(tx_hdr); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /* We copy the packet to the target */ | ||
179 | static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | ||
180 | struct ieee80211_tx_info *control) | ||
181 | { | ||
182 | struct tx_double_buffer_desc *tx_hdr; | ||
183 | int len; | ||
184 | u32 addr; | ||
185 | |||
186 | if (!skb) | ||
187 | return -EINVAL; | ||
188 | |||
189 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | ||
190 | |||
191 | if (control->control.hw_key && | ||
192 | control->control.hw_key->alg == ALG_TKIP) { | ||
193 | int hdrlen; | ||
194 | __le16 fc; | ||
195 | u16 length; | ||
196 | u8 *pos; | ||
197 | |||
198 | fc = *(__le16 *)(skb->data + sizeof(*tx_hdr)); | ||
199 | length = le16_to_cpu(tx_hdr->length) + WL1251_TKIP_IV_SPACE; | ||
200 | tx_hdr->length = cpu_to_le16(length); | ||
201 | |||
202 | hdrlen = ieee80211_hdrlen(fc); | ||
203 | |||
204 | pos = skb_push(skb, WL1251_TKIP_IV_SPACE); | ||
205 | memmove(pos, pos + WL1251_TKIP_IV_SPACE, | ||
206 | sizeof(*tx_hdr) + hdrlen); | ||
207 | } | ||
208 | |||
209 | /* Revisit. This is a workaround for getting non-aligned packets. | ||
210 | This happens at least with EAPOL packets from the user space. | ||
211 | Our DMA requires packets to be aligned on a 4-byte boundary. | ||
212 | */ | ||
213 | if (unlikely((long)skb->data & 0x03)) { | ||
214 | int offset = (4 - (long)skb->data) & 0x03; | ||
215 | wl1251_debug(DEBUG_TX, "skb offset %d", offset); | ||
216 | |||
217 | /* check whether the current skb can be used */ | ||
218 | if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { | ||
219 | unsigned char *src = skb->data; | ||
220 | |||
221 | /* align the buffer on a 4-byte boundary */ | ||
222 | skb_reserve(skb, offset); | ||
223 | memmove(skb->data, src, skb->len); | ||
224 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | ||
225 | } else { | ||
226 | wl1251_info("No handler, fixme!"); | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* Our skb->data at this point includes the HW header */ | ||
232 | len = WL1251_TX_ALIGN(skb->len); | ||
233 | |||
234 | if (wl->data_in_count & 0x1) | ||
235 | addr = wl->data_path->tx_packet_ring_addr + | ||
236 | wl->data_path->tx_packet_ring_chunk_size; | ||
237 | else | ||
238 | addr = wl->data_path->tx_packet_ring_addr; | ||
239 | |||
240 | wl1251_mem_write(wl, addr, skb->data, len); | ||
241 | |||
242 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x " | ||
243 | "queue %d", tx_hdr->id, skb, tx_hdr->length, | ||
244 | tx_hdr->rate, tx_hdr->xmit_queue); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static void wl1251_tx_trigger(struct wl1251 *wl) | ||
250 | { | ||
251 | u32 data, addr; | ||
252 | |||
253 | if (wl->data_in_count & 0x1) { | ||
254 | addr = ACX_REG_INTERRUPT_TRIG_H; | ||
255 | data = INTR_TRIG_TX_PROC1; | ||
256 | } else { | ||
257 | addr = ACX_REG_INTERRUPT_TRIG; | ||
258 | data = INTR_TRIG_TX_PROC0; | ||
259 | } | ||
260 | |||
261 | wl1251_reg_write32(wl, addr, data); | ||
262 | |||
263 | /* Bumping data in */ | ||
264 | wl->data_in_count = (wl->data_in_count + 1) & | ||
265 | TX_STATUS_DATA_OUT_COUNT_MASK; | ||
266 | } | ||
267 | |||
268 | /* caller must hold wl->mutex */ | ||
269 | static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) | ||
270 | { | ||
271 | struct ieee80211_tx_info *info; | ||
272 | int ret = 0; | ||
273 | u8 idx; | ||
274 | |||
275 | info = IEEE80211_SKB_CB(skb); | ||
276 | |||
277 | if (info->control.hw_key) { | ||
278 | idx = info->control.hw_key->hw_key_idx; | ||
279 | if (unlikely(wl->default_key != idx)) { | ||
280 | ret = wl1251_acx_default_key(wl, idx); | ||
281 | if (ret < 0) | ||
282 | return ret; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | ret = wl1251_tx_path_status(wl); | ||
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | |||
290 | ret = wl1251_tx_fill_hdr(wl, skb, info); | ||
291 | if (ret < 0) | ||
292 | return ret; | ||
293 | |||
294 | ret = wl1251_tx_send_packet(wl, skb, info); | ||
295 | if (ret < 0) | ||
296 | return ret; | ||
297 | |||
298 | wl1251_tx_trigger(wl); | ||
299 | |||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | void wl1251_tx_work(struct work_struct *work) | ||
304 | { | ||
305 | struct wl1251 *wl = container_of(work, struct wl1251, tx_work); | ||
306 | struct sk_buff *skb; | ||
307 | bool woken_up = false; | ||
308 | int ret; | ||
309 | |||
310 | mutex_lock(&wl->mutex); | ||
311 | |||
312 | if (unlikely(wl->state == WL1251_STATE_OFF)) | ||
313 | goto out; | ||
314 | |||
315 | while ((skb = skb_dequeue(&wl->tx_queue))) { | ||
316 | if (!woken_up) { | ||
317 | ret = wl1251_ps_elp_wakeup(wl); | ||
318 | if (ret < 0) | ||
319 | goto out; | ||
320 | woken_up = true; | ||
321 | } | ||
322 | |||
323 | ret = wl1251_tx_frame(wl, skb); | ||
324 | if (ret == -EBUSY) { | ||
325 | /* firmware buffer is full, stop queues */ | ||
326 | wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, " | ||
327 | "stop queues"); | ||
328 | ieee80211_stop_queues(wl->hw); | ||
329 | wl->tx_queue_stopped = true; | ||
330 | skb_queue_head(&wl->tx_queue, skb); | ||
331 | goto out; | ||
332 | } else if (ret < 0) { | ||
333 | dev_kfree_skb(skb); | ||
334 | goto out; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | out: | ||
339 | if (woken_up) | ||
340 | wl1251_ps_elp_sleep(wl); | ||
341 | |||
342 | mutex_unlock(&wl->mutex); | ||
343 | } | ||
344 | |||
345 | static const char *wl1251_tx_parse_status(u8 status) | ||
346 | { | ||
347 | /* 8 bit status field, one character per bit plus null */ | ||
348 | static char buf[9]; | ||
349 | int i = 0; | ||
350 | |||
351 | memset(buf, 0, sizeof(buf)); | ||
352 | |||
353 | if (status & TX_DMA_ERROR) | ||
354 | buf[i++] = 'm'; | ||
355 | if (status & TX_DISABLED) | ||
356 | buf[i++] = 'd'; | ||
357 | if (status & TX_RETRY_EXCEEDED) | ||
358 | buf[i++] = 'r'; | ||
359 | if (status & TX_TIMEOUT) | ||
360 | buf[i++] = 't'; | ||
361 | if (status & TX_KEY_NOT_FOUND) | ||
362 | buf[i++] = 'k'; | ||
363 | if (status & TX_ENCRYPT_FAIL) | ||
364 | buf[i++] = 'e'; | ||
365 | if (status & TX_UNAVAILABLE_PRIORITY) | ||
366 | buf[i++] = 'p'; | ||
367 | |||
368 | /* bit 0 is unused apparently */ | ||
369 | |||
370 | return buf; | ||
371 | } | ||
372 | |||
373 | static void wl1251_tx_packet_cb(struct wl1251 *wl, | ||
374 | struct tx_result *result) | ||
375 | { | ||
376 | struct ieee80211_tx_info *info; | ||
377 | struct sk_buff *skb; | ||
378 | int hdrlen, ret; | ||
379 | u8 *frame; | ||
380 | |||
381 | skb = wl->tx_frames[result->id]; | ||
382 | if (skb == NULL) { | ||
383 | wl1251_error("SKB for packet %d is NULL", result->id); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | info = IEEE80211_SKB_CB(skb); | ||
388 | |||
389 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
390 | (result->status == TX_SUCCESS)) | ||
391 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
392 | |||
393 | info->status.rates[0].count = result->ack_failures + 1; | ||
394 | wl->stats.retry_count += result->ack_failures; | ||
395 | |||
396 | /* | ||
397 | * We have to remove our private TX header before pushing | ||
398 | * the skb back to mac80211. | ||
399 | */ | ||
400 | frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); | ||
401 | if (info->control.hw_key && | ||
402 | info->control.hw_key->alg == ALG_TKIP) { | ||
403 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
404 | memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); | ||
405 | skb_pull(skb, WL1251_TKIP_IV_SPACE); | ||
406 | } | ||
407 | |||
408 | wl1251_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" | ||
409 | " status 0x%x (%s)", | ||
410 | result->id, skb, result->ack_failures, result->rate, | ||
411 | result->status, wl1251_tx_parse_status(result->status)); | ||
412 | |||
413 | |||
414 | ieee80211_tx_status(wl->hw, skb); | ||
415 | |||
416 | wl->tx_frames[result->id] = NULL; | ||
417 | |||
418 | if (wl->tx_queue_stopped) { | ||
419 | wl1251_debug(DEBUG_TX, "cb: queue was stopped"); | ||
420 | |||
421 | skb = skb_dequeue(&wl->tx_queue); | ||
422 | |||
423 | /* The skb can be NULL because tx_work might have been | ||
424 | scheduled before the queue was stopped making the | ||
425 | queue empty */ | ||
426 | |||
427 | if (skb) { | ||
428 | ret = wl1251_tx_frame(wl, skb); | ||
429 | if (ret == -EBUSY) { | ||
430 | /* firmware buffer is still full */ | ||
431 | wl1251_debug(DEBUG_TX, "cb: fw buffer " | ||
432 | "still full"); | ||
433 | skb_queue_head(&wl->tx_queue, skb); | ||
434 | return; | ||
435 | } else if (ret < 0) { | ||
436 | dev_kfree_skb(skb); | ||
437 | return; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | wl1251_debug(DEBUG_TX, "cb: waking queues"); | ||
442 | ieee80211_wake_queues(wl->hw); | ||
443 | wl->tx_queue_stopped = false; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* Called upon reception of a TX complete interrupt */ | ||
448 | void wl1251_tx_complete(struct wl1251 *wl) | ||
449 | { | ||
450 | int i, result_index, num_complete = 0; | ||
451 | struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; | ||
452 | |||
453 | if (unlikely(wl->state != WL1251_STATE_ON)) | ||
454 | return; | ||
455 | |||
456 | /* First we read the result */ | ||
457 | wl1251_mem_read(wl, wl->data_path->tx_complete_addr, | ||
458 | result, sizeof(result)); | ||
459 | |||
460 | result_index = wl->next_tx_complete; | ||
461 | |||
462 | for (i = 0; i < ARRAY_SIZE(result); i++) { | ||
463 | result_ptr = &result[result_index]; | ||
464 | |||
465 | if (result_ptr->done_1 == 1 && | ||
466 | result_ptr->done_2 == 1) { | ||
467 | wl1251_tx_packet_cb(wl, result_ptr); | ||
468 | |||
469 | result_ptr->done_1 = 0; | ||
470 | result_ptr->done_2 = 0; | ||
471 | |||
472 | result_index = (result_index + 1) & | ||
473 | (FW_TX_CMPLT_BLOCK_SIZE - 1); | ||
474 | num_complete++; | ||
475 | } else { | ||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* Every completed frame needs to be acknowledged */ | ||
481 | if (num_complete) { | ||
482 | /* | ||
483 | * If we've wrapped, we have to clear | ||
484 | * the results in 2 steps. | ||
485 | */ | ||
486 | if (result_index > wl->next_tx_complete) { | ||
487 | /* Only 1 write is needed */ | ||
488 | wl1251_mem_write(wl, | ||
489 | wl->data_path->tx_complete_addr + | ||
490 | (wl->next_tx_complete * | ||
491 | sizeof(struct tx_result)), | ||
492 | &result[wl->next_tx_complete], | ||
493 | num_complete * | ||
494 | sizeof(struct tx_result)); | ||
495 | |||
496 | |||
497 | } else if (result_index < wl->next_tx_complete) { | ||
498 | /* 2 writes are needed */ | ||
499 | wl1251_mem_write(wl, | ||
500 | wl->data_path->tx_complete_addr + | ||
501 | (wl->next_tx_complete * | ||
502 | sizeof(struct tx_result)), | ||
503 | &result[wl->next_tx_complete], | ||
504 | (FW_TX_CMPLT_BLOCK_SIZE - | ||
505 | wl->next_tx_complete) * | ||
506 | sizeof(struct tx_result)); | ||
507 | |||
508 | wl1251_mem_write(wl, | ||
509 | wl->data_path->tx_complete_addr, | ||
510 | result, | ||
511 | (num_complete - | ||
512 | FW_TX_CMPLT_BLOCK_SIZE + | ||
513 | wl->next_tx_complete) * | ||
514 | sizeof(struct tx_result)); | ||
515 | |||
516 | } else { | ||
517 | /* We have to write the whole array */ | ||
518 | wl1251_mem_write(wl, | ||
519 | wl->data_path->tx_complete_addr, | ||
520 | result, | ||
521 | FW_TX_CMPLT_BLOCK_SIZE * | ||
522 | sizeof(struct tx_result)); | ||
523 | } | ||
524 | |||
525 | } | ||
526 | |||
527 | wl->next_tx_complete = result_index; | ||
528 | } | ||
529 | |||
530 | /* caller must hold wl->mutex */ | ||
531 | void wl1251_tx_flush(struct wl1251 *wl) | ||
532 | { | ||
533 | int i; | ||
534 | struct sk_buff *skb; | ||
535 | struct ieee80211_tx_info *info; | ||
536 | |||
537 | /* TX failure */ | ||
538 | /* control->flags = 0; FIXME */ | ||
539 | |||
540 | while ((skb = skb_dequeue(&wl->tx_queue))) { | ||
541 | info = IEEE80211_SKB_CB(skb); | ||
542 | |||
543 | wl1251_debug(DEBUG_TX, "flushing skb 0x%p", skb); | ||
544 | |||
545 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
546 | continue; | ||
547 | |||
548 | ieee80211_tx_status(wl->hw, skb); | ||
549 | } | ||
550 | |||
551 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | ||
552 | if (wl->tx_frames[i] != NULL) { | ||
553 | skb = wl->tx_frames[i]; | ||
554 | info = IEEE80211_SKB_CB(skb); | ||
555 | |||
556 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
557 | continue; | ||
558 | |||
559 | ieee80211_tx_status(wl->hw, skb); | ||
560 | wl->tx_frames[i] = NULL; | ||
561 | } | ||
562 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h deleted file mode 100644 index f40eeb37f5aa..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ /dev/null | |||
@@ -1,233 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1251_TX_H__ | ||
26 | #define __WL1251_TX_H__ | ||
27 | |||
28 | #include <linux/bitops.h> | ||
29 | #include "wl1251_acx.h" | ||
30 | |||
31 | /* | ||
32 | * | ||
33 | * TX PATH | ||
34 | * | ||
35 | * The Tx path uses a double buffer and a tx_control structure, each located | ||
36 | * at a fixed address in the device's memory. On startup, the host retrieves | ||
37 | * the pointers to these addresses. A double buffer allows for continuous data | ||
38 | * flow towards the device. The host keeps track of which buffer is available | ||
39 | * and alternates between these two buffers on a per packet basis. | ||
40 | * | ||
41 | * The size of each of the two buffers is large enough to hold the longest | ||
42 | * 802.3 packet - maximum size Ethernet packet + header + descriptor. | ||
43 | * TX complete indication will be received a-synchronously in a TX done cyclic | ||
44 | * buffer which is composed of 16 tx_result descriptors structures and is used | ||
45 | * in a cyclic manner. | ||
46 | * | ||
47 | * The TX (HOST) procedure is as follows: | ||
48 | * 1. Read the Tx path status, that will give the data_out_count. | ||
49 | * 2. goto 1, if not possible. | ||
50 | * i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double | ||
51 | * buffer). | ||
52 | * 3. Copy the packet (preceded by double_buffer_desc), if possible. | ||
53 | * i.e. if data_in_count - data_out_count < HwBuffer size (2 for double | ||
54 | * buffer). | ||
55 | * 4. increment data_in_count. | ||
56 | * 5. Inform the firmware by generating a firmware internal interrupt. | ||
57 | * 6. FW will increment data_out_count after it reads the buffer. | ||
58 | * | ||
59 | * The TX Complete procedure: | ||
60 | * 1. To get a TX complete indication the host enables the tx_complete flag in | ||
61 | * the TX descriptor Structure. | ||
62 | * 2. For each packet with a Tx Complete field set, the firmware adds the | ||
63 | * transmit results to the cyclic buffer (txDoneRing) and sets both done_1 | ||
64 | * and done_2 to 1 to indicate driver ownership. | ||
65 | * 3. The firmware sends a Tx Complete interrupt to the host to trigger the | ||
66 | * host to process the new data. Note: interrupt will be send per packet if | ||
67 | * TX complete indication was requested in tx_control or per crossing | ||
68 | * aggregation threshold. | ||
69 | * 4. After receiving the Tx Complete interrupt, the host reads the | ||
70 | * TxDescriptorDone information in a cyclic manner and clears both done_1 | ||
71 | * and done_2 fields. | ||
72 | * | ||
73 | */ | ||
74 | |||
75 | #define TX_COMPLETE_REQUIRED_BIT 0x80 | ||
76 | #define TX_STATUS_DATA_OUT_COUNT_MASK 0xf | ||
77 | |||
78 | #define WL1251_TX_ALIGN_TO 4 | ||
79 | #define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \ | ||
80 | ~(WL1251_TX_ALIGN_TO - 1)) | ||
81 | #define WL1251_TKIP_IV_SPACE 4 | ||
82 | |||
83 | struct tx_control { | ||
84 | /* Rate Policy (class) index */ | ||
85 | unsigned rate_policy:3; | ||
86 | |||
87 | /* When set, no ack policy is expected */ | ||
88 | unsigned ack_policy:1; | ||
89 | |||
90 | /* | ||
91 | * Packet type: | ||
92 | * 0 -> 802.11 | ||
93 | * 1 -> 802.3 | ||
94 | * 2 -> IP | ||
95 | * 3 -> raw codec | ||
96 | */ | ||
97 | unsigned packet_type:2; | ||
98 | |||
99 | /* If set, this is a QoS-Null or QoS-Data frame */ | ||
100 | unsigned qos:1; | ||
101 | |||
102 | /* | ||
103 | * If set, the target triggers the tx complete INT | ||
104 | * upon frame sending completion. | ||
105 | */ | ||
106 | unsigned tx_complete:1; | ||
107 | |||
108 | /* 2 bytes padding before packet header */ | ||
109 | unsigned xfer_pad:1; | ||
110 | |||
111 | unsigned reserved:7; | ||
112 | } __packed; | ||
113 | |||
114 | |||
115 | struct tx_double_buffer_desc { | ||
116 | /* Length of payload, including headers. */ | ||
117 | __le16 length; | ||
118 | |||
119 | /* | ||
120 | * A bit mask that specifies the initial rate to be used | ||
121 | * Possible values are: | ||
122 | * 0x0001 - 1Mbits | ||
123 | * 0x0002 - 2Mbits | ||
124 | * 0x0004 - 5.5Mbits | ||
125 | * 0x0008 - 6Mbits | ||
126 | * 0x0010 - 9Mbits | ||
127 | * 0x0020 - 11Mbits | ||
128 | * 0x0040 - 12Mbits | ||
129 | * 0x0080 - 18Mbits | ||
130 | * 0x0100 - 22Mbits | ||
131 | * 0x0200 - 24Mbits | ||
132 | * 0x0400 - 36Mbits | ||
133 | * 0x0800 - 48Mbits | ||
134 | * 0x1000 - 54Mbits | ||
135 | */ | ||
136 | __le16 rate; | ||
137 | |||
138 | /* Time in us that a packet can spend in the target */ | ||
139 | __le32 expiry_time; | ||
140 | |||
141 | /* index of the TX queue used for this packet */ | ||
142 | u8 xmit_queue; | ||
143 | |||
144 | /* Used to identify a packet */ | ||
145 | u8 id; | ||
146 | |||
147 | struct tx_control control; | ||
148 | |||
149 | /* | ||
150 | * The FW should cut the packet into fragments | ||
151 | * of this size. | ||
152 | */ | ||
153 | __le16 frag_threshold; | ||
154 | |||
155 | /* Numbers of HW queue blocks to be allocated */ | ||
156 | u8 num_mem_blocks; | ||
157 | |||
158 | u8 reserved; | ||
159 | } __packed; | ||
160 | |||
161 | enum { | ||
162 | TX_SUCCESS = 0, | ||
163 | TX_DMA_ERROR = BIT(7), | ||
164 | TX_DISABLED = BIT(6), | ||
165 | TX_RETRY_EXCEEDED = BIT(5), | ||
166 | TX_TIMEOUT = BIT(4), | ||
167 | TX_KEY_NOT_FOUND = BIT(3), | ||
168 | TX_ENCRYPT_FAIL = BIT(2), | ||
169 | TX_UNAVAILABLE_PRIORITY = BIT(1), | ||
170 | }; | ||
171 | |||
172 | struct tx_result { | ||
173 | /* | ||
174 | * Ownership synchronization between the host and | ||
175 | * the firmware. If done_1 and done_2 are cleared, | ||
176 | * owned by the FW (no info ready). | ||
177 | */ | ||
178 | u8 done_1; | ||
179 | |||
180 | /* same as double_buffer_desc->id */ | ||
181 | u8 id; | ||
182 | |||
183 | /* | ||
184 | * Total air access duration consumed by this | ||
185 | * packet, including all retries and overheads. | ||
186 | */ | ||
187 | u16 medium_usage; | ||
188 | |||
189 | /* Total media delay (from 1st EDCA AIFS counter until TX Complete). */ | ||
190 | u32 medium_delay; | ||
191 | |||
192 | /* Time between host xfer and tx complete */ | ||
193 | u32 fw_hnadling_time; | ||
194 | |||
195 | /* The LS-byte of the last TKIP sequence number. */ | ||
196 | u8 lsb_seq_num; | ||
197 | |||
198 | /* Retry count */ | ||
199 | u8 ack_failures; | ||
200 | |||
201 | /* At which rate we got a ACK */ | ||
202 | u16 rate; | ||
203 | |||
204 | u16 reserved; | ||
205 | |||
206 | /* TX_* */ | ||
207 | u8 status; | ||
208 | |||
209 | /* See done_1 */ | ||
210 | u8 done_2; | ||
211 | } __packed; | ||
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 | |||
229 | void wl1251_tx_work(struct work_struct *work); | ||
230 | void wl1251_tx_complete(struct wl1251 *wl); | ||
231 | void wl1251_tx_flush(struct wl1251 *wl); | ||
232 | |||
233 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index dd3cee6ea5bb..8a4cd763e5a2 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -117,10 +117,7 @@ enum { | |||
117 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 117 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
118 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) | 118 | #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) |
119 | 119 | ||
120 | /* | 120 | #define WL1271_CIPHER_SUITE_GEM 0x00147201 |
121 | * Enable/disable 802.11a support for WL1273 | ||
122 | */ | ||
123 | #undef WL1271_80211A_ENABLED | ||
124 | 121 | ||
125 | #define WL1271_BUSY_WORD_CNT 1 | 122 | #define WL1271_BUSY_WORD_CNT 1 |
126 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 123 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
@@ -133,6 +130,8 @@ enum { | |||
133 | 130 | ||
134 | #define ACX_TX_DESCRIPTORS 32 | 131 | #define ACX_TX_DESCRIPTORS 32 |
135 | 132 | ||
133 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | ||
134 | |||
136 | enum wl1271_state { | 135 | enum wl1271_state { |
137 | WL1271_STATE_OFF, | 136 | WL1271_STATE_OFF, |
138 | WL1271_STATE_ON, | 137 | WL1271_STATE_ON, |
@@ -301,6 +300,7 @@ struct wl1271_rx_mem_pool_addr { | |||
301 | struct wl1271_scan { | 300 | struct wl1271_scan { |
302 | struct cfg80211_scan_request *req; | 301 | struct cfg80211_scan_request *req; |
303 | bool *scanned_ch; | 302 | bool *scanned_ch; |
303 | bool failed; | ||
304 | u8 state; | 304 | u8 state; |
305 | u8 ssid[IW_ESSID_MAX_SIZE+1]; | 305 | u8 ssid[IW_ESSID_MAX_SIZE+1]; |
306 | size_t ssid_len; | 306 | size_t ssid_len; |
@@ -313,7 +313,7 @@ struct wl1271_if_operations { | |||
313 | bool fixed); | 313 | bool fixed); |
314 | void (*reset)(struct wl1271 *wl); | 314 | void (*reset)(struct wl1271 *wl); |
315 | void (*init)(struct wl1271 *wl); | 315 | void (*init)(struct wl1271 *wl); |
316 | void (*power)(struct wl1271 *wl, bool enable); | 316 | int (*power)(struct wl1271 *wl, bool enable); |
317 | struct device* (*dev)(struct wl1271 *wl); | 317 | struct device* (*dev)(struct wl1271 *wl); |
318 | void (*enable_irq)(struct wl1271 *wl); | 318 | void (*enable_irq)(struct wl1271 *wl); |
319 | void (*disable_irq)(struct wl1271 *wl); | 319 | void (*disable_irq)(struct wl1271 *wl); |
@@ -330,6 +330,7 @@ struct wl1271 { | |||
330 | 330 | ||
331 | void (*set_power)(bool enable); | 331 | void (*set_power)(bool enable); |
332 | int irq; | 332 | int irq; |
333 | int ref_clock; | ||
333 | 334 | ||
334 | spinlock_t wl_lock; | 335 | spinlock_t wl_lock; |
335 | 336 | ||
@@ -349,6 +350,7 @@ struct wl1271 { | |||
349 | #define WL1271_FLAG_IDLE (10) | 350 | #define WL1271_FLAG_IDLE (10) |
350 | #define WL1271_FLAG_IDLE_REQUESTED (11) | 351 | #define WL1271_FLAG_IDLE_REQUESTED (11) |
351 | #define WL1271_FLAG_PSPOLL_FAILURE (12) | 352 | #define WL1271_FLAG_PSPOLL_FAILURE (12) |
353 | #define WL1271_FLAG_STA_STATE_SENT (13) | ||
352 | unsigned long flags; | 354 | unsigned long flags; |
353 | 355 | ||
354 | struct wl1271_partition_set part; | 356 | struct wl1271_partition_set part; |
@@ -361,6 +363,7 @@ struct wl1271 { | |||
361 | u8 *fw; | 363 | u8 *fw; |
362 | size_t fw_len; | 364 | size_t fw_len; |
363 | struct wl1271_nvs_file *nvs; | 365 | struct wl1271_nvs_file *nvs; |
366 | size_t nvs_len; | ||
364 | 367 | ||
365 | s8 hw_pg_ver; | 368 | s8 hw_pg_ver; |
366 | 369 | ||
@@ -407,9 +410,15 @@ struct wl1271 { | |||
407 | /* Rx memory pool address */ | 410 | /* Rx memory pool address */ |
408 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; | 411 | struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; |
409 | 412 | ||
413 | /* Intermediate buffer, used for packet aggregation */ | ||
414 | u8 *aggr_buf; | ||
415 | |||
410 | /* The target interrupt mask */ | 416 | /* The target interrupt mask */ |
411 | struct work_struct irq_work; | 417 | struct work_struct irq_work; |
412 | 418 | ||
419 | /* Hardware recovery work */ | ||
420 | struct work_struct recovery_work; | ||
421 | |||
413 | /* The mbox event mask */ | 422 | /* The mbox event mask */ |
414 | u32 event_mask; | 423 | u32 event_mask; |
415 | 424 | ||
@@ -418,6 +427,7 @@ struct wl1271 { | |||
418 | 427 | ||
419 | /* Are we currently scanning */ | 428 | /* Are we currently scanning */ |
420 | struct wl1271_scan scan; | 429 | struct wl1271_scan scan; |
430 | struct delayed_work scan_complete_work; | ||
421 | 431 | ||
422 | /* Our association ID */ | 432 | /* Our association ID */ |
423 | u16 aid; | 433 | u16 aid; |
@@ -474,6 +484,8 @@ struct wl1271 { | |||
474 | 484 | ||
475 | bool sg_enabled; | 485 | bool sg_enabled; |
476 | 486 | ||
487 | bool enable_11a; | ||
488 | |||
477 | struct list_head list; | 489 | struct list_head list; |
478 | 490 | ||
479 | /* Most recently reported noise in dBm */ | 491 | /* Most recently reported noise in dBm */ |
@@ -497,14 +509,4 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
497 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | 509 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ |
498 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 510 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
499 | 511 | ||
500 | static inline bool wl1271_11a_enabled(void) | ||
501 | { | ||
502 | /* FIXME: this could be determined based on the NVS-INI file */ | ||
503 | #ifdef WL1271_80211A_ENABLED | ||
504 | return true; | ||
505 | #else | ||
506 | return false; | ||
507 | #endif | ||
508 | } | ||
509 | |||
510 | #endif | 512 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index bb245f05af49..618993405262 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -86,40 +86,6 @@ out: | |||
86 | return ret; | 86 | return ret; |
87 | } | 87 | } |
88 | 88 | ||
89 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len) | ||
90 | { | ||
91 | struct acx_revision *rev; | ||
92 | int ret; | ||
93 | |||
94 | wl1271_debug(DEBUG_ACX, "acx fw rev"); | ||
95 | |||
96 | rev = kzalloc(sizeof(*rev), GFP_KERNEL); | ||
97 | if (!rev) { | ||
98 | ret = -ENOMEM; | ||
99 | goto out; | ||
100 | } | ||
101 | |||
102 | ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); | ||
103 | if (ret < 0) { | ||
104 | wl1271_warning("ACX_FW_REV interrogate failed"); | ||
105 | goto out; | ||
106 | } | ||
107 | |||
108 | /* be careful with the buffer sizes */ | ||
109 | strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); | ||
110 | |||
111 | /* | ||
112 | * if the firmware version string is exactly | ||
113 | * sizeof(rev->fw_version) long or fw_len is less than | ||
114 | * sizeof(rev->fw_version) it won't be null terminated | ||
115 | */ | ||
116 | buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; | ||
117 | |||
118 | out: | ||
119 | kfree(rev); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | int wl1271_acx_tx_power(struct wl1271 *wl, int power) | 89 | int wl1271_acx_tx_power(struct wl1271 *wl, int power) |
124 | { | 90 | { |
125 | struct acx_current_tx_power *acx; | 91 | struct acx_current_tx_power *acx; |
@@ -269,7 +235,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) | |||
269 | 235 | ||
270 | out: | 236 | out: |
271 | kfree(pd); | 237 | kfree(pd); |
272 | return 0; | 238 | return ret; |
273 | } | 239 | } |
274 | 240 | ||
275 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) | 241 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 4235bc56f750..ebb341d36e8c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -100,35 +100,6 @@ struct acx_error_counter { | |||
100 | __le32 seq_num_miss; | 100 | __le32 seq_num_miss; |
101 | } __packed; | 101 | } __packed; |
102 | 102 | ||
103 | struct acx_revision { | ||
104 | struct acx_header header; | ||
105 | |||
106 | /* | ||
107 | * The WiLink firmware version, an ASCII string x.x.x.x, | ||
108 | * that uniquely identifies the current firmware. | ||
109 | * The left most digit is incremented each time a | ||
110 | * significant change is made to the firmware, such as | ||
111 | * code redesign or new platform support. | ||
112 | * The second digit is incremented when major enhancements | ||
113 | * are added or major fixes are made. | ||
114 | * The third digit is incremented for each GA release. | ||
115 | * The fourth digit is incremented for each build. | ||
116 | * The first two digits identify a firmware release version, | ||
117 | * in other words, a unique set of features. | ||
118 | * The first three digits identify a GA release. | ||
119 | */ | ||
120 | char fw_version[20]; | ||
121 | |||
122 | /* | ||
123 | * This 4 byte field specifies the WiLink hardware version. | ||
124 | * bits 0 - 15: Reserved. | ||
125 | * bits 16 - 23: Version ID - The WiLink version ID | ||
126 | * (1 = first spin, 2 = second spin, and so on). | ||
127 | * bits 24 - 31: Chip ID - The WiLink chip ID. | ||
128 | */ | ||
129 | __le32 hw_version; | ||
130 | } __packed; | ||
131 | |||
132 | enum wl1271_psm_mode { | 103 | enum wl1271_psm_mode { |
133 | /* Active mode */ | 104 | /* Active mode */ |
134 | WL1271_PSM_CAM = 0, | 105 | WL1271_PSM_CAM = 0, |
@@ -1060,7 +1031,6 @@ enum { | |||
1060 | ACX_PEER_HT_CAP = 0x0057, | 1031 | ACX_PEER_HT_CAP = 0x0057, |
1061 | ACX_HT_BSS_OPERATION = 0x0058, | 1032 | ACX_HT_BSS_OPERATION = 0x0058, |
1062 | ACX_COEX_ACTIVITY = 0x0059, | 1033 | ACX_COEX_ACTIVITY = 0x0059, |
1063 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | ||
1064 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, | 1034 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1065 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1035 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1066 | DOT11_CUR_TX_PWR = 0x100D, | 1036 | DOT11_CUR_TX_PWR = 0x100D, |
@@ -1077,7 +1047,6 @@ enum { | |||
1077 | 1047 | ||
1078 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl); | 1048 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl); |
1079 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); | 1049 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); |
1080 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len); | ||
1081 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); | 1050 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); |
1082 | int wl1271_acx_feature_cfg(struct wl1271 *wl); | 1051 | int wl1271_acx_feature_cfg(struct wl1271 *wl); |
1083 | int wl1271_acx_mem_map(struct wl1271 *wl, | 1052 | int wl1271_acx_mem_map(struct wl1271 *wl, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index f36430b0336d..b91021242098 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
225 | if (wl->nvs == NULL) | 225 | if (wl->nvs == NULL) |
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | /* | ||
229 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
230 | * configurations) can be removed when those NVS files stop floating | ||
231 | * around. | ||
232 | */ | ||
233 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || | ||
234 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { | ||
235 | if (wl->nvs->general_params.dual_mode_select) | ||
236 | wl->enable_11a = true; | ||
237 | } | ||
238 | |||
239 | if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && | ||
240 | (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
241 | wl->enable_11a)) { | ||
242 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
243 | wl->nvs_len, sizeof(struct wl1271_nvs_file)); | ||
244 | kfree(wl->nvs); | ||
245 | wl->nvs = NULL; | ||
246 | wl->nvs_len = 0; | ||
247 | return -EILSEQ; | ||
248 | } | ||
249 | |||
228 | /* only the first part of the NVS needs to be uploaded */ | 250 | /* only the first part of the NVS needs to be uploaded */ |
229 | nvs_len = sizeof(wl->nvs->nvs); | 251 | nvs_len = sizeof(wl->nvs->nvs); |
230 | nvs_ptr = (u8 *)wl->nvs->nvs; | 252 | nvs_ptr = (u8 *)wl->nvs->nvs; |
@@ -251,8 +273,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
251 | burst_len = nvs_ptr[0]; | 273 | burst_len = nvs_ptr[0]; |
252 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); | 274 | dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); |
253 | 275 | ||
254 | /* FIXME: Due to our new wl1271_translate_reg_addr function, | 276 | /* |
255 | we need to add the REGISTER_BASE to the destination */ | 277 | * Due to our new wl1271_translate_reg_addr function, |
278 | * we need to add the REGISTER_BASE to the destination | ||
279 | */ | ||
256 | dest_addr += REGISTERS_BASE; | 280 | dest_addr += REGISTERS_BASE; |
257 | 281 | ||
258 | /* We move our pointer to the data */ | 282 | /* We move our pointer to the data */ |
@@ -274,31 +298,21 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
274 | 298 | ||
275 | /* | 299 | /* |
276 | * We've reached the first zero length, the first NVS table | 300 | * We've reached the first zero length, the first NVS table |
277 | * is 7 bytes further. | 301 | * is located at an aligned offset which is at least 7 bytes further. |
278 | */ | 302 | */ |
279 | nvs_ptr += 7; | 303 | nvs_ptr = (u8 *)wl->nvs->nvs + |
304 | ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); | ||
280 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; | 305 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; |
281 | nvs_len = ALIGN(nvs_len, 4); | ||
282 | 306 | ||
283 | /* FIXME: The driver sets the partition here, but this is not needed, | ||
284 | since it sets to the same one as currently in use */ | ||
285 | /* Now we must set the partition correctly */ | 307 | /* Now we must set the partition correctly */ |
286 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 308 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
287 | 309 | ||
288 | /* Copy the NVS tables to a new block to ensure alignment */ | 310 | /* Copy the NVS tables to a new block to ensure alignment */ |
289 | /* FIXME: We jump 3 more bytes before uploading the NVS. It seems | 311 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
290 | that our NVS files have three extra zeros here. I'm not sure whether | 312 | if (!nvs_aligned) |
291 | the problem is in our NVS generation or we should really jumpt these | 313 | return -ENOMEM; |
292 | 3 bytes here */ | ||
293 | nvs_ptr += 3; | ||
294 | |||
295 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if | ||
296 | (!nvs_aligned) return -ENOMEM; | ||
297 | 314 | ||
298 | /* And finally we upload the NVS tables */ | 315 | /* And finally we upload the NVS tables */ |
299 | /* FIXME: In wl1271, we upload everything at once. | ||
300 | No endianness handling needed here?! The ref driver doesn't do | ||
301 | anything about it at this point */ | ||
302 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); | 316 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
303 | 317 | ||
304 | kfree(nvs_aligned); | 318 | kfree(nvs_aligned); |
@@ -457,17 +471,20 @@ int wl1271_boot(struct wl1271 *wl) | |||
457 | { | 471 | { |
458 | int ret = 0; | 472 | int ret = 0; |
459 | u32 tmp, clk, pause; | 473 | u32 tmp, clk, pause; |
474 | int ref_clock = wl->ref_clock; | ||
460 | 475 | ||
461 | wl1271_boot_hw_version(wl); | 476 | wl1271_boot_hw_version(wl); |
462 | 477 | ||
463 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) | 478 | if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4) |
464 | /* ref clk: 19.2/38.4/38.4-XTAL */ | 479 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
465 | clk = 0x3; | 480 | clk = 0x3; |
466 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) | 481 | else if (ref_clock == 1 || ref_clock == 3) |
467 | /* ref clk: 26/52 */ | 482 | /* ref clk: 26/52 */ |
468 | clk = 0x5; | 483 | clk = 0x5; |
484 | else | ||
485 | return -EINVAL; | ||
469 | 486 | ||
470 | if (REF_CLOCK != 0) { | 487 | if (ref_clock != 0) { |
471 | u16 val; | 488 | u16 val; |
472 | /* Set clock type (open drain) */ | 489 | /* Set clock type (open drain) */ |
473 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 490 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
@@ -493,10 +510,7 @@ int wl1271_boot(struct wl1271 *wl) | |||
493 | 510 | ||
494 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 511 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
495 | 512 | ||
496 | pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be | 513 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
497 | * WU_COUNTER_PAUSE_VAL instead of | ||
498 | * 0x3ff (magic number ). How does | ||
499 | * this work?! */ | ||
500 | pause |= WU_COUNTER_PAUSE_VAL; | 514 | pause |= WU_COUNTER_PAUSE_VAL; |
501 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); | 515 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); |
502 | 516 | ||
@@ -516,7 +530,7 @@ int wl1271_boot(struct wl1271 *wl) | |||
516 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 530 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
517 | 531 | ||
518 | /* 2 */ | 532 | /* 2 */ |
519 | clk |= (REF_CLOCK << 1) << 4; | 533 | clk |= (ref_clock << 1) << 4; |
520 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); | 534 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
521 | 535 | ||
522 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 536 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
@@ -550,7 +564,6 @@ int wl1271_boot(struct wl1271 *wl) | |||
550 | if (ret < 0) | 564 | if (ret < 0) |
551 | goto out; | 565 | goto out; |
552 | 566 | ||
553 | /* FIXME: Need to check whether this is really what we want */ | ||
554 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 567 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
555 | WL1271_ACX_ALL_EVENTS_VECTOR); | 568 | WL1271_ACX_ALL_EVENTS_VECTOR); |
556 | 569 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index f829699d597e..f73b0b15a280 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -46,7 +46,6 @@ struct wl1271_static_data { | |||
46 | /* delay between retries */ | 46 | /* delay between retries */ |
47 | #define INIT_LOOP_DELAY 50 | 47 | #define INIT_LOOP_DELAY 50 |
48 | 48 | ||
49 | #define REF_CLOCK 2 | ||
50 | #define WU_COUNTER_PAUSE_VAL 0x3FF | 49 | #define WU_COUNTER_PAUSE_VAL 0x3FF |
51 | #define WELP_ARM_COMMAND_VAL 0x4 | 50 | #define WELP_ARM_COMMAND_VAL 0x4 |
52 | 51 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index ce503ddd5a41..5d3e8485ea4e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
94 | status = le16_to_cpu(cmd->status); | 94 | status = le16_to_cpu(cmd->status); |
95 | if (status != CMD_STATUS_SUCCESS) { | 95 | if (status != CMD_STATUS_SUCCESS) { |
96 | wl1271_error("command execute failure %d", status); | 96 | wl1271_error("command execute failure %d", status); |
97 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
97 | ret = -EIO; | 98 | ret = -EIO; |
98 | } | 99 | } |
99 | 100 | ||
@@ -107,6 +108,8 @@ out: | |||
107 | int wl1271_cmd_general_parms(struct wl1271 *wl) | 108 | int wl1271_cmd_general_parms(struct wl1271 *wl) |
108 | { | 109 | { |
109 | struct wl1271_general_parms_cmd *gen_parms; | 110 | struct wl1271_general_parms_cmd *gen_parms; |
111 | struct wl1271_ini_general_params *gp = &wl->nvs->general_params; | ||
112 | bool answer = false; | ||
110 | int ret; | 113 | int ret; |
111 | 114 | ||
112 | if (!wl->nvs) | 115 | if (!wl->nvs) |
@@ -118,13 +121,24 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
118 | 121 | ||
119 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 122 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
120 | 123 | ||
121 | memcpy(&gen_parms->general_params, &wl->nvs->general_params, | 124 | memcpy(&gen_parms->general_params, gp, sizeof(*gp)); |
122 | sizeof(struct wl1271_ini_general_params)); | ||
123 | 125 | ||
124 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 126 | if (gp->tx_bip_fem_auto_detect) |
125 | if (ret < 0) | 127 | answer = true; |
128 | |||
129 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | ||
130 | if (ret < 0) { | ||
126 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 131 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
132 | goto out; | ||
133 | } | ||
134 | |||
135 | gp->tx_bip_fem_manufacturer = | ||
136 | gen_parms->general_params.tx_bip_fem_manufacturer; | ||
137 | |||
138 | wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", | ||
139 | answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); | ||
127 | 140 | ||
141 | out: | ||
128 | kfree(gen_parms); | 142 | kfree(gen_parms); |
129 | return ret; | 143 | return ret; |
130 | } | 144 | } |
@@ -170,6 +184,39 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
170 | return ret; | 184 | return ret; |
171 | } | 185 | } |
172 | 186 | ||
187 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) | ||
188 | { | ||
189 | struct wl1271_ext_radio_parms_cmd *ext_radio_parms; | ||
190 | struct conf_rf_settings *rf = &wl->conf.rf; | ||
191 | int ret; | ||
192 | |||
193 | if (!wl->nvs) | ||
194 | return -ENODEV; | ||
195 | |||
196 | ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); | ||
197 | if (!ext_radio_parms) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; | ||
201 | |||
202 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, | ||
203 | rf->tx_per_channel_power_compensation_2, | ||
204 | CONF_TX_PWR_COMPENSATION_LEN_2); | ||
205 | memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, | ||
206 | rf->tx_per_channel_power_compensation_5, | ||
207 | CONF_TX_PWR_COMPENSATION_LEN_5); | ||
208 | |||
209 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", | ||
210 | ext_radio_parms, sizeof(*ext_radio_parms)); | ||
211 | |||
212 | ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); | ||
213 | if (ret < 0) | ||
214 | wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); | ||
215 | |||
216 | kfree(ext_radio_parms); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
173 | /* | 220 | /* |
174 | * Poll the mailbox event field until any of the bits in the mask is set or a | 221 | * Poll the mailbox event field until any of the bits in the mask is set or a |
175 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 222 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
@@ -182,8 +229,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
182 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 229 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
183 | 230 | ||
184 | do { | 231 | do { |
185 | if (time_after(jiffies, timeout)) | 232 | if (time_after(jiffies, timeout)) { |
233 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
186 | return -ETIMEDOUT; | 234 | return -ETIMEDOUT; |
235 | } | ||
187 | 236 | ||
188 | msleep(1); | 237 | msleep(1); |
189 | 238 | ||
@@ -390,18 +439,11 @@ out: | |||
390 | return ret; | 439 | return ret; |
391 | } | 440 | } |
392 | 441 | ||
393 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | 442 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send) |
394 | { | 443 | { |
395 | struct wl1271_cmd_ps_params *ps_params = NULL; | 444 | struct wl1271_cmd_ps_params *ps_params = NULL; |
396 | int ret = 0; | 445 | int ret = 0; |
397 | 446 | ||
398 | /* FIXME: this should be in ps.c */ | ||
399 | ret = wl1271_acx_wake_up_conditions(wl); | ||
400 | if (ret < 0) { | ||
401 | wl1271_error("couldn't set wake up conditions"); | ||
402 | goto out; | ||
403 | } | ||
404 | |||
405 | wl1271_debug(DEBUG_CMD, "cmd set ps mode"); | 447 | wl1271_debug(DEBUG_CMD, "cmd set ps mode"); |
406 | 448 | ||
407 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); | 449 | ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); |
@@ -412,9 +454,9 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) | |||
412 | 454 | ||
413 | ps_params->ps_mode = ps_mode; | 455 | ps_params->ps_mode = ps_mode; |
414 | ps_params->send_null_data = send; | 456 | ps_params->send_null_data = send; |
415 | ps_params->retries = 5; | 457 | ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries; |
416 | ps_params->hang_over_period = 1; | 458 | ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period; |
417 | ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set); | 459 | ps_params->null_data_rate = cpu_to_le32(rates); |
418 | 460 | ||
419 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 461 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
420 | sizeof(*ps_params), 0); | 462 | sizeof(*ps_params), 0); |
@@ -428,41 +470,6 @@ out: | |||
428 | return ret; | 470 | return ret; |
429 | } | 471 | } |
430 | 472 | ||
431 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | ||
432 | size_t len) | ||
433 | { | ||
434 | struct cmd_read_write_memory *cmd; | ||
435 | int ret = 0; | ||
436 | |||
437 | wl1271_debug(DEBUG_CMD, "cmd read memory"); | ||
438 | |||
439 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
440 | if (!cmd) { | ||
441 | ret = -ENOMEM; | ||
442 | goto out; | ||
443 | } | ||
444 | |||
445 | WARN_ON(len > MAX_READ_SIZE); | ||
446 | len = min_t(size_t, len, MAX_READ_SIZE); | ||
447 | |||
448 | cmd->addr = cpu_to_le32(addr); | ||
449 | cmd->size = cpu_to_le32(len); | ||
450 | |||
451 | ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), | ||
452 | sizeof(*cmd)); | ||
453 | if (ret < 0) { | ||
454 | wl1271_error("read memory command failed: %d", ret); | ||
455 | goto out; | ||
456 | } | ||
457 | |||
458 | /* the read command got in */ | ||
459 | memcpy(answer, cmd->value, len); | ||
460 | |||
461 | out: | ||
462 | kfree(cmd); | ||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 473 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
467 | void *buf, size_t buf_len, int index, u32 rates) | 474 | void *buf, size_t buf_len, int index, u32 rates) |
468 | { | 475 | { |
@@ -523,7 +530,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) | |||
523 | } | 530 | } |
524 | 531 | ||
525 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, | 532 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
526 | WL1271_RATE_AUTOMATIC); | 533 | wl->basic_rate); |
527 | 534 | ||
528 | out: | 535 | out: |
529 | dev_kfree_skb(skb); | 536 | dev_kfree_skb(skb); |
@@ -546,7 +553,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) | |||
546 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, | 553 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, |
547 | skb->data, skb->len, | 554 | skb->data, skb->len, |
548 | CMD_TEMPL_KLV_IDX_NULL_DATA, | 555 | CMD_TEMPL_KLV_IDX_NULL_DATA, |
549 | WL1271_RATE_AUTOMATIC); | 556 | wl->basic_rate); |
550 | 557 | ||
551 | out: | 558 | out: |
552 | dev_kfree_skb(skb); | 559 | dev_kfree_skb(skb); |
@@ -623,7 +630,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
623 | 630 | ||
624 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | 631 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, |
625 | sizeof(template), 0, | 632 | sizeof(template), 0, |
626 | WL1271_RATE_AUTOMATIC); | 633 | wl->basic_rate); |
627 | } | 634 | } |
628 | 635 | ||
629 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 636 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
@@ -746,3 +753,31 @@ out_free: | |||
746 | out: | 753 | out: |
747 | return ret; | 754 | return ret; |
748 | } | 755 | } |
756 | |||
757 | int wl1271_cmd_set_sta_state(struct wl1271 *wl) | ||
758 | { | ||
759 | struct wl1271_cmd_set_sta_state *cmd; | ||
760 | int ret = 0; | ||
761 | |||
762 | wl1271_debug(DEBUG_CMD, "cmd set sta state"); | ||
763 | |||
764 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
765 | if (!cmd) { | ||
766 | ret = -ENOMEM; | ||
767 | goto out; | ||
768 | } | ||
769 | |||
770 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; | ||
771 | |||
772 | ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); | ||
773 | if (ret < 0) { | ||
774 | wl1271_error("failed to send set STA state command"); | ||
775 | goto out_free; | ||
776 | } | ||
777 | |||
778 | out_free: | ||
779 | kfree(cmd); | ||
780 | |||
781 | out: | ||
782 | return ret; | ||
783 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index af577ee8eb02..a0caf4fc37b1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -33,12 +33,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wl1271_cmd_general_parms(struct wl1271 *wl); | 34 | int wl1271_cmd_general_parms(struct wl1271 *wl); |
35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); | 35 | int wl1271_cmd_radio_parms(struct wl1271 *wl); |
36 | int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); | ||
36 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); | 37 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); |
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 38 | 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); | 39 | 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); | 40 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | 41 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); | 42 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 43 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 44 | size_t len); |
44 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 45 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
@@ -55,6 +56,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
55 | u8 key_size, const u8 *key, const u8 *addr, | 56 | u8 key_size, const u8 *key, const u8 *addr, |
56 | u32 tx_seq_32, u16 tx_seq_16); | 57 | u32 tx_seq_32, u16 tx_seq_16); |
57 | int wl1271_cmd_disconnect(struct wl1271 *wl); | 58 | int wl1271_cmd_disconnect(struct wl1271 *wl); |
59 | int wl1271_cmd_set_sta_state(struct wl1271 *wl); | ||
58 | 60 | ||
59 | enum wl1271_commands { | 61 | enum wl1271_commands { |
60 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 62 | CMD_INTERROGATE = 1, /*use this to read information elements*/ |
@@ -160,41 +162,6 @@ enum { | |||
160 | MAX_COMMAND_STATUS = 0xff | 162 | MAX_COMMAND_STATUS = 0xff |
161 | }; | 163 | }; |
162 | 164 | ||
163 | |||
164 | /* | ||
165 | * CMD_READ_MEMORY | ||
166 | * | ||
167 | * The host issues this command to read the WiLink device memory/registers. | ||
168 | * | ||
169 | * Note: The Base Band address has special handling (16 bits registers and | ||
170 | * addresses). For more information, see the hardware specification. | ||
171 | */ | ||
172 | /* | ||
173 | * CMD_WRITE_MEMORY | ||
174 | * | ||
175 | * The host issues this command to write the WiLink device memory/registers. | ||
176 | * | ||
177 | * The Base Band address has special handling (16 bits registers and | ||
178 | * addresses). For more information, see the hardware specification. | ||
179 | */ | ||
180 | #define MAX_READ_SIZE 256 | ||
181 | |||
182 | struct cmd_read_write_memory { | ||
183 | struct wl1271_cmd_header header; | ||
184 | |||
185 | /* The address of the memory to read from or write to.*/ | ||
186 | __le32 addr; | ||
187 | |||
188 | /* The amount of data in bytes to read from or write to the WiLink | ||
189 | * device.*/ | ||
190 | __le32 size; | ||
191 | |||
192 | /* The actual value read from or written to the Wilink. The source | ||
193 | of this field is the Host in WRITE command or the Wilink in READ | ||
194 | command. */ | ||
195 | u8 value[MAX_READ_SIZE]; | ||
196 | } __packed; | ||
197 | |||
198 | #define CMDMBOX_HEADER_LEN 4 | 165 | #define CMDMBOX_HEADER_LEN 4 |
199 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 166 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
200 | 167 | ||
@@ -313,7 +280,7 @@ enum wl1271_cmd_key_type { | |||
313 | KEY_WEP = 1, | 280 | KEY_WEP = 1, |
314 | KEY_TKIP = 2, | 281 | KEY_TKIP = 2, |
315 | KEY_AES = 3, | 282 | KEY_AES = 3, |
316 | KEY_GEM = 4 | 283 | KEY_GEM = 4, |
317 | }; | 284 | }; |
318 | 285 | ||
319 | /* FIXME: Add description for key-types */ | 286 | /* FIXME: Add description for key-types */ |
@@ -358,13 +325,14 @@ enum wl1271_channel_tune_bands { | |||
358 | WL1271_CHANNEL_TUNE_BAND_4_9 | 325 | WL1271_CHANNEL_TUNE_BAND_4_9 |
359 | }; | 326 | }; |
360 | 327 | ||
361 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 | 328 | #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 |
362 | 329 | ||
363 | #define TEST_CMD_P2G_CAL 0x02 | 330 | #define TEST_CMD_P2G_CAL 0x02 |
364 | #define TEST_CMD_CHANNEL_TUNE 0x0d | 331 | #define TEST_CMD_CHANNEL_TUNE 0x0d |
365 | #define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d | 332 | #define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d |
366 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 | 333 | #define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 |
367 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E | 334 | #define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E |
335 | #define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 | ||
368 | 336 | ||
369 | struct wl1271_general_parms_cmd { | 337 | struct wl1271_general_parms_cmd { |
370 | struct wl1271_cmd_header header; | 338 | struct wl1271_cmd_header header; |
@@ -397,6 +365,16 @@ struct wl1271_radio_parms_cmd { | |||
397 | u8 padding3[2]; | 365 | u8 padding3[2]; |
398 | } __packed; | 366 | } __packed; |
399 | 367 | ||
368 | struct wl1271_ext_radio_parms_cmd { | ||
369 | struct wl1271_cmd_header header; | ||
370 | |||
371 | struct wl1271_cmd_test_header test; | ||
372 | |||
373 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
374 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
375 | u8 padding[3]; | ||
376 | } __packed; | ||
377 | |||
400 | struct wl1271_cmd_cal_channel_tune { | 378 | struct wl1271_cmd_cal_channel_tune { |
401 | struct wl1271_cmd_header header; | 379 | struct wl1271_cmd_header header; |
402 | 380 | ||
@@ -469,4 +447,13 @@ struct wl1271_cmd_disconnect { | |||
469 | u8 padding; | 447 | u8 padding; |
470 | } __packed; | 448 | } __packed; |
471 | 449 | ||
450 | #define WL1271_CMD_STA_STATE_CONNECTED 1 | ||
451 | |||
452 | struct wl1271_cmd_set_sta_state { | ||
453 | struct wl1271_cmd_header header; | ||
454 | |||
455 | u8 state; | ||
456 | u8 padding[3]; | ||
457 | } __packed; | ||
458 | |||
472 | #endif /* __WL1271_CMD_H__ */ | 459 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 0435ffda8f73..5f78a6cb1433 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -595,7 +595,7 @@ struct conf_tx_ac_category { | |||
595 | u16 tx_op_limit; | 595 | u16 tx_op_limit; |
596 | }; | 596 | }; |
597 | 597 | ||
598 | #define CONF_TX_MAX_TID_COUNT 7 | 598 | #define CONF_TX_MAX_TID_COUNT 8 |
599 | 599 | ||
600 | enum { | 600 | enum { |
601 | CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ | 601 | CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ |
@@ -912,6 +912,22 @@ struct conf_conn_settings { | |||
912 | u8 psm_entry_retries; | 912 | u8 psm_entry_retries; |
913 | 913 | ||
914 | /* | 914 | /* |
915 | * Specifies the maximum number of times to try transmit the PSM entry | ||
916 | * null-func frame for each PSM entry attempt | ||
917 | * | ||
918 | * Range 0 - 255 | ||
919 | */ | ||
920 | u8 psm_entry_nullfunc_retries; | ||
921 | |||
922 | /* | ||
923 | * Specifies the time to linger in active mode after successfully | ||
924 | * transmitting the PSM entry null-func frame. | ||
925 | * | ||
926 | * Range 0 - 255 TU's | ||
927 | */ | ||
928 | u8 psm_entry_hangover_period; | ||
929 | |||
930 | /* | ||
915 | * | 931 | * |
916 | * Specifies the interval of the connection keep-alive null-func | 932 | * Specifies the interval of the connection keep-alive null-func |
917 | * frame in ms. | 933 | * frame in ms. |
@@ -1016,6 +1032,64 @@ struct conf_roam_trigger_settings { | |||
1016 | u8 avg_weight_snr_data; | 1032 | u8 avg_weight_snr_data; |
1017 | }; | 1033 | }; |
1018 | 1034 | ||
1035 | struct conf_scan_settings { | ||
1036 | /* | ||
1037 | * The minimum time to wait on each channel for active scans | ||
1038 | * | ||
1039 | * Range: 0 - 65536 tu | ||
1040 | */ | ||
1041 | u16 min_dwell_time_active; | ||
1042 | |||
1043 | /* | ||
1044 | * The maximum time to wait on each channel for active scans | ||
1045 | * | ||
1046 | * Range: 0 - 65536 tu | ||
1047 | */ | ||
1048 | u16 max_dwell_time_active; | ||
1049 | |||
1050 | /* | ||
1051 | * The maximum time to wait on each channel for passive scans | ||
1052 | * | ||
1053 | * Range: 0 - 65536 tu | ||
1054 | */ | ||
1055 | u16 min_dwell_time_passive; | ||
1056 | |||
1057 | /* | ||
1058 | * The maximum time to wait on each channel for passive scans | ||
1059 | * | ||
1060 | * Range: 0 - 65536 tu | ||
1061 | */ | ||
1062 | u16 max_dwell_time_passive; | ||
1063 | |||
1064 | /* | ||
1065 | * Number of probe requests to transmit on each active scan channel | ||
1066 | * | ||
1067 | * Range: u8 | ||
1068 | */ | ||
1069 | u16 num_probe_reqs; | ||
1070 | |||
1071 | }; | ||
1072 | |||
1073 | /* these are number of channels on the band divided by two, rounded up */ | ||
1074 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | ||
1075 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | ||
1076 | |||
1077 | struct conf_rf_settings { | ||
1078 | /* | ||
1079 | * Per channel power compensation for 2.4GHz | ||
1080 | * | ||
1081 | * Range: s8 | ||
1082 | */ | ||
1083 | u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; | ||
1084 | |||
1085 | /* | ||
1086 | * Per channel power compensation for 5GHz | ||
1087 | * | ||
1088 | * Range: s8 | ||
1089 | */ | ||
1090 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | ||
1091 | }; | ||
1092 | |||
1019 | struct conf_drv_settings { | 1093 | struct conf_drv_settings { |
1020 | struct conf_sg_settings sg; | 1094 | struct conf_sg_settings sg; |
1021 | struct conf_rx_settings rx; | 1095 | struct conf_rx_settings rx; |
@@ -1024,6 +1098,8 @@ struct conf_drv_settings { | |||
1024 | struct conf_itrim_settings itrim; | 1098 | struct conf_itrim_settings itrim; |
1025 | struct conf_pm_config_settings pm_config; | 1099 | struct conf_pm_config_settings pm_config; |
1026 | struct conf_roam_trigger_settings roam_trigger; | 1100 | struct conf_roam_trigger_settings roam_trigger; |
1101 | struct conf_scan_settings scan; | ||
1102 | struct conf_rf_settings rf; | ||
1027 | }; | 1103 | }; |
1028 | 1104 | ||
1029 | #endif | 1105 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 25ce2cd5e3f3..7b3f50382963 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work) | |||
41 | 41 | ||
42 | mutex_lock(&wl->mutex); | 42 | mutex_lock(&wl->mutex); |
43 | 43 | ||
44 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
45 | goto out; | ||
46 | |||
44 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) | 47 | if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) |
45 | goto out; | 48 | goto out; |
46 | 49 | ||
@@ -52,7 +55,7 @@ void wl1271_pspoll_work(struct work_struct *work) | |||
52 | * delivery failure occurred, and no-one changed state since, so | 55 | * delivery failure occurred, and no-one changed state since, so |
53 | * we should go back to powersave. | 56 | * we should go back to powersave. |
54 | */ | 57 | */ |
55 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); | 58 | wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); |
56 | 59 | ||
57 | out: | 60 | out: |
58 | mutex_unlock(&wl->mutex); | 61 | mutex_unlock(&wl->mutex); |
@@ -70,7 +73,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) | |||
70 | 73 | ||
71 | /* force active mode receive data from the AP */ | 74 | /* force active mode receive data from the AP */ |
72 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 75 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
73 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true); | 76 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
77 | wl->basic_rate, true); | ||
74 | if (ret < 0) | 78 | if (ret < 0) |
75 | return; | 79 | return; |
76 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | 80 | set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); |
@@ -91,6 +95,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
91 | bool *beacon_loss) | 95 | bool *beacon_loss) |
92 | { | 96 | { |
93 | int ret = 0; | 97 | int ret = 0; |
98 | u32 total_retries = wl->conf.conn.psm_entry_retries; | ||
94 | 99 | ||
95 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); | 100 | wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); |
96 | 101 | ||
@@ -104,10 +109,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
104 | break; | 109 | break; |
105 | } | 110 | } |
106 | 111 | ||
107 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { | 112 | if (wl->psm_entry_retry < total_retries) { |
108 | wl->psm_entry_retry++; | 113 | wl->psm_entry_retry++; |
109 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 114 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
110 | true); | 115 | wl->basic_rate, true); |
111 | } else { | 116 | } else { |
112 | wl1271_info("No ack to nullfunc from AP."); | 117 | wl1271_info("No ack to nullfunc from AP."); |
113 | wl->psm_entry_retry = 0; | 118 | wl->psm_entry_retry = 0; |
@@ -143,7 +148,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
143 | /* make sure the firmware goes to active mode - the frame to | 148 | /* make sure the firmware goes to active mode - the frame to |
144 | be sent next will indicate to the AP, that we are active. */ | 149 | be sent next will indicate to the AP, that we are active. */ |
145 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 150 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
146 | false); | 151 | wl->basic_rate, false); |
147 | break; | 152 | break; |
148 | case EVENT_EXIT_POWER_SAVE_SUCCESS: | 153 | case EVENT_EXIT_POWER_SAVE_SUCCESS: |
149 | default: | 154 | default: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 4447af1557f5..8044bba70ee7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret, i; | 55 | int ret, i; |
56 | size_t size; | ||
56 | 57 | ||
57 | /* send empty templates for fw memory reservation */ | 58 | /* send empty templates for fw memory reservation */ |
58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 59 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
61 | if (ret < 0) | 62 | if (ret < 0) |
62 | return ret; | 63 | return ret; |
63 | 64 | ||
64 | if (wl1271_11a_enabled()) { | 65 | size = sizeof(struct wl12xx_probe_req_template); |
65 | size_t size = sizeof(struct wl12xx_probe_req_template); | 66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 67 | NULL, size, 0, |
67 | NULL, size, 0, | 68 | WL1271_RATE_AUTOMATIC); |
68 | WL1271_RATE_AUTOMATIC); | 69 | if (ret < 0) |
69 | if (ret < 0) | 70 | return ret; |
70 | return ret; | ||
71 | } | ||
72 | 71 | ||
73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 72 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
74 | sizeof(struct wl12xx_null_data_template), | 73 | sizeof(struct wl12xx_null_data_template), |
@@ -223,6 +222,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
223 | if (ret < 0) | 222 | if (ret < 0) |
224 | return ret; | 223 | return ret; |
225 | 224 | ||
225 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | |||
226 | /* Template settings */ | 229 | /* Template settings */ |
227 | ret = wl1271_init_templates_config(wl); | 230 | ret = wl1271_init_templates_config(wl); |
228 | if (ret < 0) | 231 | if (ret < 0) |
@@ -291,8 +294,16 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
291 | if (ret < 0) | 294 | if (ret < 0) |
292 | goto out_free_memmap; | 295 | goto out_free_memmap; |
293 | 296 | ||
294 | /* Default TID configuration */ | 297 | /* Default TID/AC configuration */ |
298 | BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); | ||
295 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 299 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
300 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
301 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
302 | conf_ac->cw_max, conf_ac->aifsn, | ||
303 | conf_ac->tx_op_limit); | ||
304 | if (ret < 0) | ||
305 | goto out_free_memmap; | ||
306 | |||
296 | conf_tid = &wl->conf.tx.tid_conf[i]; | 307 | conf_tid = &wl->conf.tx.tid_conf[i]; |
297 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | 308 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
298 | conf_tid->channel_type, | 309 | conf_tid->channel_type, |
@@ -305,16 +316,6 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
305 | goto out_free_memmap; | 316 | goto out_free_memmap; |
306 | } | 317 | } |
307 | 318 | ||
308 | /* Default AC configuration */ | ||
309 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
310 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
311 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
312 | conf_ac->cw_max, conf_ac->aifsn, | ||
313 | conf_ac->tx_op_limit); | ||
314 | if (ret < 0) | ||
315 | goto out_free_memmap; | ||
316 | } | ||
317 | |||
318 | /* Configure TX rate classes */ | 319 | /* Configure TX rate classes */ |
319 | ret = wl1271_acx_rate_policies(wl); | 320 | ret = wl1271_acx_rate_policies(wl); |
320 | if (ret < 0) | 321 | if (ret < 0) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index bc806c74c63a..c1f92e65ded0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -144,10 +144,13 @@ static inline void wl1271_power_off(struct wl1271 *wl) | |||
144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 144 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); |
145 | } | 145 | } |
146 | 146 | ||
147 | static inline void wl1271_power_on(struct wl1271 *wl) | 147 | static inline int wl1271_power_on(struct wl1271 *wl) |
148 | { | 148 | { |
149 | wl->if_ops->power(wl, true); | 149 | int ret = wl->if_ops->power(wl, true); |
150 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 150 | if (ret == 0) |
151 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
152 | |||
153 | return ret; | ||
151 | } | 154 | } |
152 | 155 | ||
153 | 156 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9d68f0012f05..48a4b9961ae6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -124,28 +124,28 @@ static struct conf_drv_settings default_conf = { | |||
124 | }, | 124 | }, |
125 | .ac_conf_count = 4, | 125 | .ac_conf_count = 4, |
126 | .ac_conf = { | 126 | .ac_conf = { |
127 | [0] = { | 127 | [CONF_TX_AC_BE] = { |
128 | .ac = CONF_TX_AC_BE, | 128 | .ac = CONF_TX_AC_BE, |
129 | .cw_min = 15, | 129 | .cw_min = 15, |
130 | .cw_max = 63, | 130 | .cw_max = 63, |
131 | .aifsn = 3, | 131 | .aifsn = 3, |
132 | .tx_op_limit = 0, | 132 | .tx_op_limit = 0, |
133 | }, | 133 | }, |
134 | [1] = { | 134 | [CONF_TX_AC_BK] = { |
135 | .ac = CONF_TX_AC_BK, | 135 | .ac = CONF_TX_AC_BK, |
136 | .cw_min = 15, | 136 | .cw_min = 15, |
137 | .cw_max = 63, | 137 | .cw_max = 63, |
138 | .aifsn = 7, | 138 | .aifsn = 7, |
139 | .tx_op_limit = 0, | 139 | .tx_op_limit = 0, |
140 | }, | 140 | }, |
141 | [2] = { | 141 | [CONF_TX_AC_VI] = { |
142 | .ac = CONF_TX_AC_VI, | 142 | .ac = CONF_TX_AC_VI, |
143 | .cw_min = 15, | 143 | .cw_min = 15, |
144 | .cw_max = 63, | 144 | .cw_max = 63, |
145 | .aifsn = CONF_TX_AIFS_PIFS, | 145 | .aifsn = CONF_TX_AIFS_PIFS, |
146 | .tx_op_limit = 3008, | 146 | .tx_op_limit = 3008, |
147 | }, | 147 | }, |
148 | [3] = { | 148 | [CONF_TX_AC_VO] = { |
149 | .ac = CONF_TX_AC_VO, | 149 | .ac = CONF_TX_AC_VO, |
150 | .cw_min = 15, | 150 | .cw_min = 15, |
151 | .cw_max = 63, | 151 | .cw_max = 63, |
@@ -153,64 +153,40 @@ static struct conf_drv_settings default_conf = { | |||
153 | .tx_op_limit = 1504, | 153 | .tx_op_limit = 1504, |
154 | }, | 154 | }, |
155 | }, | 155 | }, |
156 | .tid_conf_count = 7, | 156 | .tid_conf_count = 4, |
157 | .tid_conf = { | 157 | .tid_conf = { |
158 | [0] = { | 158 | [CONF_TX_AC_BE] = { |
159 | .queue_id = 0, | 159 | .queue_id = CONF_TX_AC_BE, |
160 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 160 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
161 | .tsid = CONF_TX_AC_BE, | ||
162 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
163 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
164 | .apsd_conf = {0, 0}, | ||
165 | }, | ||
166 | [1] = { | ||
167 | .queue_id = 1, | ||
168 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
169 | .tsid = CONF_TX_AC_BE, | 161 | .tsid = CONF_TX_AC_BE, |
170 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 162 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
171 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 163 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
172 | .apsd_conf = {0, 0}, | 164 | .apsd_conf = {0, 0}, |
173 | }, | 165 | }, |
174 | [2] = { | 166 | [CONF_TX_AC_BK] = { |
175 | .queue_id = 2, | 167 | .queue_id = CONF_TX_AC_BK, |
176 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 168 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
177 | .tsid = CONF_TX_AC_BE, | 169 | .tsid = CONF_TX_AC_BK, |
178 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 170 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
179 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 171 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
180 | .apsd_conf = {0, 0}, | 172 | .apsd_conf = {0, 0}, |
181 | }, | 173 | }, |
182 | [3] = { | 174 | [CONF_TX_AC_VI] = { |
183 | .queue_id = 3, | 175 | .queue_id = CONF_TX_AC_VI, |
184 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 176 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
185 | .tsid = CONF_TX_AC_BE, | 177 | .tsid = CONF_TX_AC_VI, |
186 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
187 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
188 | .apsd_conf = {0, 0}, | ||
189 | }, | ||
190 | [4] = { | ||
191 | .queue_id = 4, | ||
192 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
193 | .tsid = CONF_TX_AC_BE, | ||
194 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 178 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
195 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 179 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
196 | .apsd_conf = {0, 0}, | 180 | .apsd_conf = {0, 0}, |
197 | }, | 181 | }, |
198 | [5] = { | 182 | [CONF_TX_AC_VO] = { |
199 | .queue_id = 5, | 183 | .queue_id = CONF_TX_AC_VO, |
200 | .channel_type = CONF_CHANNEL_TYPE_DCF, | 184 | .channel_type = CONF_CHANNEL_TYPE_EDCF, |
201 | .tsid = CONF_TX_AC_BE, | 185 | .tsid = CONF_TX_AC_VO, |
202 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | 186 | .ps_scheme = CONF_PS_SCHEME_LEGACY, |
203 | .ack_policy = CONF_ACK_POLICY_LEGACY, | 187 | .ack_policy = CONF_ACK_POLICY_LEGACY, |
204 | .apsd_conf = {0, 0}, | 188 | .apsd_conf = {0, 0}, |
205 | }, | 189 | }, |
206 | [6] = { | ||
207 | .queue_id = 6, | ||
208 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
209 | .tsid = CONF_TX_AC_BE, | ||
210 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
211 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
212 | .apsd_conf = {0, 0}, | ||
213 | } | ||
214 | }, | 190 | }, |
215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 191 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
216 | .tx_compl_timeout = 700, | 192 | .tx_compl_timeout = 700, |
@@ -238,7 +214,9 @@ static struct conf_drv_settings default_conf = { | |||
238 | .ps_poll_recovery_period = 700, | 214 | .ps_poll_recovery_period = 700, |
239 | .bet_enable = CONF_BET_MODE_ENABLE, | 215 | .bet_enable = CONF_BET_MODE_ENABLE, |
240 | .bet_max_consecutive = 10, | 216 | .bet_max_consecutive = 10, |
241 | .psm_entry_retries = 3, | 217 | .psm_entry_retries = 5, |
218 | .psm_entry_nullfunc_retries = 3, | ||
219 | .psm_entry_hangover_period = 1, | ||
242 | .keep_alive_interval = 55000, | 220 | .keep_alive_interval = 55000, |
243 | .max_listen_interval = 20, | 221 | .max_listen_interval = 20, |
244 | }, | 222 | }, |
@@ -251,15 +229,34 @@ static struct conf_drv_settings default_conf = { | |||
251 | .host_fast_wakeup_support = false | 229 | .host_fast_wakeup_support = false |
252 | }, | 230 | }, |
253 | .roam_trigger = { | 231 | .roam_trigger = { |
254 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
255 | .trigger_pacing = 1, | 232 | .trigger_pacing = 1, |
256 | .avg_weight_rssi_beacon = 20, | 233 | .avg_weight_rssi_beacon = 20, |
257 | .avg_weight_rssi_data = 10, | 234 | .avg_weight_rssi_data = 10, |
258 | .avg_weight_snr_beacon = 20, | 235 | .avg_weight_snr_beacon = 20, |
259 | .avg_weight_snr_data = 10 | 236 | .avg_weight_snr_data = 10 |
260 | } | 237 | }, |
238 | .scan = { | ||
239 | .min_dwell_time_active = 7500, | ||
240 | .max_dwell_time_active = 30000, | ||
241 | .min_dwell_time_passive = 30000, | ||
242 | .max_dwell_time_passive = 60000, | ||
243 | .num_probe_reqs = 2, | ||
244 | }, | ||
245 | .rf = { | ||
246 | .tx_per_channel_power_compensation_2 = { | ||
247 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
248 | }, | ||
249 | .tx_per_channel_power_compensation_5 = { | ||
250 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
253 | }, | ||
254 | }, | ||
261 | }; | 255 | }; |
262 | 256 | ||
257 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | ||
258 | |||
259 | |||
263 | static void wl1271_device_release(struct device *dev) | 260 | static void wl1271_device_release(struct device *dev) |
264 | { | 261 | { |
265 | 262 | ||
@@ -277,6 +274,67 @@ static struct platform_device wl1271_device = { | |||
277 | 274 | ||
278 | static LIST_HEAD(wl_list); | 275 | static LIST_HEAD(wl_list); |
279 | 276 | ||
277 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | ||
278 | void *arg) | ||
279 | { | ||
280 | struct net_device *dev = arg; | ||
281 | struct wireless_dev *wdev; | ||
282 | struct wiphy *wiphy; | ||
283 | struct ieee80211_hw *hw; | ||
284 | struct wl1271 *wl; | ||
285 | struct wl1271 *wl_temp; | ||
286 | int ret = 0; | ||
287 | |||
288 | /* Check that this notification is for us. */ | ||
289 | if (what != NETDEV_CHANGE) | ||
290 | return NOTIFY_DONE; | ||
291 | |||
292 | wdev = dev->ieee80211_ptr; | ||
293 | if (wdev == NULL) | ||
294 | return NOTIFY_DONE; | ||
295 | |||
296 | wiphy = wdev->wiphy; | ||
297 | if (wiphy == NULL) | ||
298 | return NOTIFY_DONE; | ||
299 | |||
300 | hw = wiphy_priv(wiphy); | ||
301 | if (hw == NULL) | ||
302 | return NOTIFY_DONE; | ||
303 | |||
304 | wl_temp = hw->priv; | ||
305 | list_for_each_entry(wl, &wl_list, list) { | ||
306 | if (wl == wl_temp) | ||
307 | break; | ||
308 | } | ||
309 | if (wl != wl_temp) | ||
310 | return NOTIFY_DONE; | ||
311 | |||
312 | mutex_lock(&wl->mutex); | ||
313 | |||
314 | if (wl->state == WL1271_STATE_OFF) | ||
315 | goto out; | ||
316 | |||
317 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
318 | goto out; | ||
319 | |||
320 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
321 | if (ret < 0) | ||
322 | goto out; | ||
323 | |||
324 | if ((dev->operstate == IF_OPER_UP) && | ||
325 | !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) { | ||
326 | wl1271_cmd_set_sta_state(wl); | ||
327 | wl1271_info("Association completed."); | ||
328 | } | ||
329 | |||
330 | wl1271_ps_elp_sleep(wl); | ||
331 | |||
332 | out: | ||
333 | mutex_unlock(&wl->mutex); | ||
334 | |||
335 | return NOTIFY_OK; | ||
336 | } | ||
337 | |||
280 | static void wl1271_conf_init(struct wl1271 *wl) | 338 | static void wl1271_conf_init(struct wl1271 *wl) |
281 | { | 339 | { |
282 | 340 | ||
@@ -309,6 +367,10 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
309 | if (ret < 0) | 367 | if (ret < 0) |
310 | return ret; | 368 | return ret; |
311 | 369 | ||
370 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
371 | if (ret < 0) | ||
372 | return ret; | ||
373 | |||
312 | ret = wl1271_init_templates_config(wl); | 374 | ret = wl1271_init_templates_config(wl); |
313 | if (ret < 0) | 375 | if (ret < 0) |
314 | return ret; | 376 | return ret; |
@@ -346,8 +408,16 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
346 | if (ret < 0) | 408 | if (ret < 0) |
347 | goto out_free_memmap; | 409 | goto out_free_memmap; |
348 | 410 | ||
349 | /* Default TID configuration */ | 411 | /* Default TID/AC configuration */ |
412 | BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); | ||
350 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 413 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
414 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
415 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
416 | conf_ac->cw_max, conf_ac->aifsn, | ||
417 | conf_ac->tx_op_limit); | ||
418 | if (ret < 0) | ||
419 | goto out_free_memmap; | ||
420 | |||
351 | conf_tid = &wl->conf.tx.tid_conf[i]; | 421 | conf_tid = &wl->conf.tx.tid_conf[i]; |
352 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | 422 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
353 | conf_tid->channel_type, | 423 | conf_tid->channel_type, |
@@ -360,16 +430,6 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
360 | goto out_free_memmap; | 430 | goto out_free_memmap; |
361 | } | 431 | } |
362 | 432 | ||
363 | /* Default AC configuration */ | ||
364 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
365 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
366 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
367 | conf_ac->cw_max, conf_ac->aifsn, | ||
368 | conf_ac->tx_op_limit); | ||
369 | if (ret < 0) | ||
370 | goto out_free_memmap; | ||
371 | } | ||
372 | |||
373 | /* Enable data path */ | 433 | /* Enable data path */ |
374 | ret = wl1271_cmd_data_path(wl, 1); | 434 | ret = wl1271_cmd_data_path(wl, 1); |
375 | if (ret < 0) | 435 | if (ret < 0) |
@@ -562,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
562 | return ret; | 622 | return ret; |
563 | } | 623 | } |
564 | 624 | ||
565 | /* | ||
566 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
567 | * configurations) can be removed when those NVS files stop floating | ||
568 | * around. | ||
569 | */ | ||
570 | if (fw->size != sizeof(struct wl1271_nvs_file) && | ||
571 | (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
572 | wl1271_11a_enabled())) { | ||
573 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
574 | fw->size, sizeof(struct wl1271_nvs_file)); | ||
575 | ret = -EILSEQ; | ||
576 | goto out; | ||
577 | } | ||
578 | |||
579 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 625 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
580 | 626 | ||
581 | if (!wl->nvs) { | 627 | if (!wl->nvs) { |
@@ -584,12 +630,37 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
584 | goto out; | 630 | goto out; |
585 | } | 631 | } |
586 | 632 | ||
633 | wl->nvs_len = fw->size; | ||
634 | |||
587 | out: | 635 | out: |
588 | release_firmware(fw); | 636 | release_firmware(fw); |
589 | 637 | ||
590 | return ret; | 638 | return ret; |
591 | } | 639 | } |
592 | 640 | ||
641 | static void wl1271_recovery_work(struct work_struct *work) | ||
642 | { | ||
643 | struct wl1271 *wl = | ||
644 | container_of(work, struct wl1271, recovery_work); | ||
645 | |||
646 | mutex_lock(&wl->mutex); | ||
647 | |||
648 | if (wl->state != WL1271_STATE_ON) | ||
649 | goto out; | ||
650 | |||
651 | wl1271_info("Hardware recovery in progress."); | ||
652 | |||
653 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
654 | ieee80211_connection_loss(wl->vif); | ||
655 | |||
656 | /* reboot the chipset */ | ||
657 | __wl1271_op_remove_interface(wl); | ||
658 | ieee80211_restart_hw(wl->hw); | ||
659 | |||
660 | out: | ||
661 | mutex_unlock(&wl->mutex); | ||
662 | } | ||
663 | |||
593 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 664 | static void wl1271_fw_wakeup(struct wl1271 *wl) |
594 | { | 665 | { |
595 | u32 elp_reg; | 666 | u32 elp_reg; |
@@ -610,8 +681,6 @@ static int wl1271_setup(struct wl1271 *wl) | |||
610 | return -ENOMEM; | 681 | return -ENOMEM; |
611 | } | 682 | } |
612 | 683 | ||
613 | INIT_WORK(&wl->irq_work, wl1271_irq_work); | ||
614 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | ||
615 | return 0; | 684 | return 0; |
616 | } | 685 | } |
617 | 686 | ||
@@ -621,7 +690,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
621 | int ret = 0; | 690 | int ret = 0; |
622 | 691 | ||
623 | msleep(WL1271_PRE_POWER_ON_SLEEP); | 692 | msleep(WL1271_PRE_POWER_ON_SLEEP); |
624 | wl1271_power_on(wl); | 693 | ret = wl1271_power_on(wl); |
694 | if (ret < 0) | ||
695 | goto out; | ||
625 | msleep(WL1271_POWER_ON_SLEEP); | 696 | msleep(WL1271_POWER_ON_SLEEP); |
626 | wl1271_io_reset(wl); | 697 | wl1271_io_reset(wl); |
627 | wl1271_io_init(wl); | 698 | wl1271_io_init(wl); |
@@ -766,10 +837,12 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
766 | out: | 837 | out: |
767 | mutex_unlock(&wl->mutex); | 838 | mutex_unlock(&wl->mutex); |
768 | 839 | ||
840 | cancel_work_sync(&wl->irq_work); | ||
841 | cancel_work_sync(&wl->recovery_work); | ||
842 | |||
769 | return ret; | 843 | return ret; |
770 | } | 844 | } |
771 | 845 | ||
772 | |||
773 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 846 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
774 | { | 847 | { |
775 | struct wl1271 *wl = hw->priv; | 848 | struct wl1271 *wl = hw->priv; |
@@ -812,6 +885,10 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
812 | return NETDEV_TX_OK; | 885 | return NETDEV_TX_OK; |
813 | } | 886 | } |
814 | 887 | ||
888 | static struct notifier_block wl1271_dev_notifier = { | ||
889 | .notifier_call = wl1271_dev_notify, | ||
890 | }; | ||
891 | |||
815 | static int wl1271_op_start(struct ieee80211_hw *hw) | 892 | static int wl1271_op_start(struct ieee80211_hw *hw) |
816 | { | 893 | { |
817 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 894 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -928,13 +1005,10 @@ out: | |||
928 | return ret; | 1005 | return ret; |
929 | } | 1006 | } |
930 | 1007 | ||
931 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1008 | static void __wl1271_op_remove_interface(struct wl1271 *wl) |
932 | struct ieee80211_vif *vif) | ||
933 | { | 1009 | { |
934 | struct wl1271 *wl = hw->priv; | ||
935 | int i; | 1010 | int i; |
936 | 1011 | ||
937 | mutex_lock(&wl->mutex); | ||
938 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 1012 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
939 | 1013 | ||
940 | wl1271_info("down"); | 1014 | wl1271_info("down"); |
@@ -948,12 +1022,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
948 | ieee80211_enable_dyn_ps(wl->vif); | 1022 | ieee80211_enable_dyn_ps(wl->vif); |
949 | 1023 | ||
950 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | 1024 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { |
951 | mutex_unlock(&wl->mutex); | ||
952 | ieee80211_scan_completed(wl->hw, true); | ||
953 | mutex_lock(&wl->mutex); | ||
954 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 1025 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
955 | kfree(wl->scan.scanned_ch); | 1026 | kfree(wl->scan.scanned_ch); |
956 | wl->scan.scanned_ch = NULL; | 1027 | wl->scan.scanned_ch = NULL; |
1028 | ieee80211_scan_completed(wl->hw, true); | ||
957 | } | 1029 | } |
958 | 1030 | ||
959 | wl->state = WL1271_STATE_OFF; | 1031 | wl->state = WL1271_STATE_OFF; |
@@ -962,9 +1034,11 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
962 | 1034 | ||
963 | mutex_unlock(&wl->mutex); | 1035 | mutex_unlock(&wl->mutex); |
964 | 1036 | ||
1037 | cancel_delayed_work_sync(&wl->scan_complete_work); | ||
965 | cancel_work_sync(&wl->irq_work); | 1038 | cancel_work_sync(&wl->irq_work); |
966 | cancel_work_sync(&wl->tx_work); | 1039 | cancel_work_sync(&wl->tx_work); |
967 | cancel_delayed_work_sync(&wl->pspoll_work); | 1040 | cancel_delayed_work_sync(&wl->pspoll_work); |
1041 | cancel_delayed_work_sync(&wl->elp_work); | ||
968 | 1042 | ||
969 | mutex_lock(&wl->mutex); | 1043 | mutex_lock(&wl->mutex); |
970 | 1044 | ||
@@ -1006,8 +1080,19 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1006 | wl->tx_res_if = NULL; | 1080 | wl->tx_res_if = NULL; |
1007 | kfree(wl->target_mem_map); | 1081 | kfree(wl->target_mem_map); |
1008 | wl->target_mem_map = NULL; | 1082 | wl->target_mem_map = NULL; |
1083 | } | ||
1009 | 1084 | ||
1085 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | ||
1086 | struct ieee80211_vif *vif) | ||
1087 | { | ||
1088 | struct wl1271 *wl = hw->priv; | ||
1089 | |||
1090 | mutex_lock(&wl->mutex); | ||
1091 | WARN_ON(wl->vif != vif); | ||
1092 | __wl1271_op_remove_interface(wl); | ||
1010 | mutex_unlock(&wl->mutex); | 1093 | mutex_unlock(&wl->mutex); |
1094 | |||
1095 | cancel_work_sync(&wl->recovery_work); | ||
1011 | } | 1096 | } |
1012 | 1097 | ||
1013 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1098 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
@@ -1289,7 +1374,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1289 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1374 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1290 | wl1271_debug(DEBUG_PSM, "psm enabled"); | 1375 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1291 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1376 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1292 | true); | 1377 | wl->basic_rate, true); |
1293 | } | 1378 | } |
1294 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1379 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1295 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1380 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
@@ -1299,7 +1384,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1299 | 1384 | ||
1300 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) | 1385 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1301 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 1386 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
1302 | true); | 1387 | wl->basic_rate, true); |
1303 | } | 1388 | } |
1304 | 1389 | ||
1305 | if (conf->power_level != wl->power_level) { | 1390 | if (conf->power_level != wl->power_level) { |
@@ -1439,7 +1524,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1439 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | 1524 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); |
1440 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | 1525 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); |
1441 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 1526 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
1442 | key_conf->alg, key_conf->keyidx, | 1527 | key_conf->cipher, key_conf->keyidx, |
1443 | key_conf->keylen, key_conf->flags); | 1528 | key_conf->keylen, key_conf->flags); |
1444 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 1529 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
1445 | 1530 | ||
@@ -1455,28 +1540,34 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1455 | if (ret < 0) | 1540 | if (ret < 0) |
1456 | goto out_unlock; | 1541 | goto out_unlock; |
1457 | 1542 | ||
1458 | switch (key_conf->alg) { | 1543 | switch (key_conf->cipher) { |
1459 | case ALG_WEP: | 1544 | case WLAN_CIPHER_SUITE_WEP40: |
1545 | case WLAN_CIPHER_SUITE_WEP104: | ||
1460 | key_type = KEY_WEP; | 1546 | key_type = KEY_WEP; |
1461 | 1547 | ||
1462 | key_conf->hw_key_idx = key_conf->keyidx; | 1548 | key_conf->hw_key_idx = key_conf->keyidx; |
1463 | break; | 1549 | break; |
1464 | case ALG_TKIP: | 1550 | case WLAN_CIPHER_SUITE_TKIP: |
1465 | key_type = KEY_TKIP; | 1551 | key_type = KEY_TKIP; |
1466 | 1552 | ||
1467 | key_conf->hw_key_idx = key_conf->keyidx; | 1553 | key_conf->hw_key_idx = key_conf->keyidx; |
1468 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 1554 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1469 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1555 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1470 | break; | 1556 | break; |
1471 | case ALG_CCMP: | 1557 | case WLAN_CIPHER_SUITE_CCMP: |
1472 | key_type = KEY_AES; | 1558 | key_type = KEY_AES; |
1473 | 1559 | ||
1474 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1560 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1475 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 1561 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1476 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1562 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1477 | break; | 1563 | break; |
1564 | case WL1271_CIPHER_SUITE_GEM: | ||
1565 | key_type = KEY_GEM; | ||
1566 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | ||
1567 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | ||
1568 | break; | ||
1478 | default: | 1569 | default: |
1479 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1570 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
1480 | 1571 | ||
1481 | ret = -EOPNOTSUPP; | 1572 | ret = -EOPNOTSUPP; |
1482 | goto out_sleep; | 1573 | goto out_sleep; |
@@ -1558,10 +1649,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1558 | if (ret < 0) | 1649 | if (ret < 0) |
1559 | goto out; | 1650 | goto out; |
1560 | 1651 | ||
1561 | if (wl1271_11a_enabled()) | 1652 | ret = wl1271_scan(hw->priv, ssid, len, req); |
1562 | ret = wl1271_scan(hw->priv, ssid, len, req); | ||
1563 | else | ||
1564 | ret = wl1271_scan(hw->priv, ssid, len, req); | ||
1565 | 1653 | ||
1566 | wl1271_ps_elp_sleep(wl); | 1654 | wl1271_ps_elp_sleep(wl); |
1567 | 1655 | ||
@@ -1633,7 +1721,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1633 | if (ret < 0) | 1721 | if (ret < 0) |
1634 | goto out; | 1722 | goto out; |
1635 | 1723 | ||
1636 | if ((changed && BSS_CHANGED_BEACON_INT) && | 1724 | if ((changed & BSS_CHANGED_BEACON_INT) && |
1637 | (wl->bss_type == BSS_TYPE_IBSS)) { | 1725 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1638 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", | 1726 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1639 | bss_conf->beacon_int); | 1727 | bss_conf->beacon_int); |
@@ -1642,7 +1730,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1642 | do_join = true; | 1730 | do_join = true; |
1643 | } | 1731 | } |
1644 | 1732 | ||
1645 | if ((changed && BSS_CHANGED_BEACON) && | 1733 | if ((changed & BSS_CHANGED_BEACON) && |
1646 | (wl->bss_type == BSS_TYPE_IBSS)) { | 1734 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1647 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1735 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1648 | 1736 | ||
@@ -1776,12 +1864,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1776 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 1864 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1777 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 1865 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
1778 | mode = STATION_POWER_SAVE_MODE; | 1866 | mode = STATION_POWER_SAVE_MODE; |
1779 | ret = wl1271_ps_set_mode(wl, mode, true); | 1867 | ret = wl1271_ps_set_mode(wl, mode, |
1868 | wl->basic_rate, | ||
1869 | true); | ||
1780 | if (ret < 0) | 1870 | if (ret < 0) |
1781 | goto out_sleep; | 1871 | goto out_sleep; |
1782 | } | 1872 | } |
1783 | } else { | 1873 | } else { |
1784 | /* use defaults when not associated */ | 1874 | /* use defaults when not associated */ |
1875 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | ||
1785 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1876 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1786 | wl->aid = 0; | 1877 | wl->aid = 0; |
1787 | 1878 | ||
@@ -1993,21 +2084,24 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1993 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, | 2084 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, |
1994 | }; | 2085 | }; |
1995 | 2086 | ||
1996 | /* can't be const, mac80211 writes to this */ | 2087 | /* |
2088 | * Can't be const, mac80211 writes to this. The order of the channels here | ||
2089 | * is designed to improve scanning. | ||
2090 | */ | ||
1997 | static struct ieee80211_channel wl1271_channels[] = { | 2091 | static struct ieee80211_channel wl1271_channels[] = { |
1998 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, | 2092 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1999 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, | ||
2000 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, | ||
2001 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, | ||
2002 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, | 2093 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
2003 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, | ||
2004 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, | ||
2005 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, | ||
2006 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, | 2094 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
2007 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, | ||
2008 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | ||
2009 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | ||
2010 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 2095 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
2096 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, | ||
2097 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, | ||
2098 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | ||
2099 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, | ||
2100 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, | ||
2101 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | ||
2102 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, | ||
2103 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, | ||
2104 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, | ||
2011 | }; | 2105 | }; |
2012 | 2106 | ||
2013 | /* mapping to indexes for wl1271_rates */ | 2107 | /* mapping to indexes for wl1271_rates */ |
@@ -2076,49 +2170,52 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
2076 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, | 2170 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, |
2077 | }; | 2171 | }; |
2078 | 2172 | ||
2079 | /* 5 GHz band channels for WL1273 */ | 2173 | /* |
2174 | * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this. | ||
2175 | * The order of the channels here is designed to improve scanning. | ||
2176 | */ | ||
2080 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 2177 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
2081 | { .hw_value = 183, .center_freq = 4915}, | 2178 | { .hw_value = 183, .center_freq = 4915}, |
2082 | { .hw_value = 184, .center_freq = 4920}, | ||
2083 | { .hw_value = 185, .center_freq = 4925}, | ||
2084 | { .hw_value = 187, .center_freq = 4935}, | ||
2085 | { .hw_value = 188, .center_freq = 4940}, | 2179 | { .hw_value = 188, .center_freq = 4940}, |
2086 | { .hw_value = 189, .center_freq = 4945}, | ||
2087 | { .hw_value = 192, .center_freq = 4960}, | ||
2088 | { .hw_value = 196, .center_freq = 4980}, | ||
2089 | { .hw_value = 7, .center_freq = 5035}, | ||
2090 | { .hw_value = 8, .center_freq = 5040}, | 2180 | { .hw_value = 8, .center_freq = 5040}, |
2091 | { .hw_value = 9, .center_freq = 5045}, | ||
2092 | { .hw_value = 11, .center_freq = 5055}, | ||
2093 | { .hw_value = 12, .center_freq = 5060}, | ||
2094 | { .hw_value = 16, .center_freq = 5080}, | ||
2095 | { .hw_value = 34, .center_freq = 5170}, | 2181 | { .hw_value = 34, .center_freq = 5170}, |
2096 | { .hw_value = 36, .center_freq = 5180}, | ||
2097 | { .hw_value = 38, .center_freq = 5190}, | ||
2098 | { .hw_value = 40, .center_freq = 5200}, | ||
2099 | { .hw_value = 42, .center_freq = 5210}, | ||
2100 | { .hw_value = 44, .center_freq = 5220}, | 2182 | { .hw_value = 44, .center_freq = 5220}, |
2101 | { .hw_value = 46, .center_freq = 5230}, | ||
2102 | { .hw_value = 48, .center_freq = 5240}, | ||
2103 | { .hw_value = 52, .center_freq = 5260}, | ||
2104 | { .hw_value = 56, .center_freq = 5280}, | ||
2105 | { .hw_value = 60, .center_freq = 5300}, | 2183 | { .hw_value = 60, .center_freq = 5300}, |
2106 | { .hw_value = 64, .center_freq = 5320}, | ||
2107 | { .hw_value = 100, .center_freq = 5500}, | ||
2108 | { .hw_value = 104, .center_freq = 5520}, | ||
2109 | { .hw_value = 108, .center_freq = 5540}, | ||
2110 | { .hw_value = 112, .center_freq = 5560}, | 2184 | { .hw_value = 112, .center_freq = 5560}, |
2111 | { .hw_value = 116, .center_freq = 5580}, | ||
2112 | { .hw_value = 120, .center_freq = 5600}, | ||
2113 | { .hw_value = 124, .center_freq = 5620}, | ||
2114 | { .hw_value = 128, .center_freq = 5640}, | ||
2115 | { .hw_value = 132, .center_freq = 5660}, | 2185 | { .hw_value = 132, .center_freq = 5660}, |
2186 | { .hw_value = 157, .center_freq = 5785}, | ||
2187 | { .hw_value = 184, .center_freq = 4920}, | ||
2188 | { .hw_value = 189, .center_freq = 4945}, | ||
2189 | { .hw_value = 9, .center_freq = 5045}, | ||
2190 | { .hw_value = 36, .center_freq = 5180}, | ||
2191 | { .hw_value = 46, .center_freq = 5230}, | ||
2192 | { .hw_value = 64, .center_freq = 5320}, | ||
2193 | { .hw_value = 116, .center_freq = 5580}, | ||
2116 | { .hw_value = 136, .center_freq = 5680}, | 2194 | { .hw_value = 136, .center_freq = 5680}, |
2195 | { .hw_value = 192, .center_freq = 4960}, | ||
2196 | { .hw_value = 11, .center_freq = 5055}, | ||
2197 | { .hw_value = 38, .center_freq = 5190}, | ||
2198 | { .hw_value = 48, .center_freq = 5240}, | ||
2199 | { .hw_value = 100, .center_freq = 5500}, | ||
2200 | { .hw_value = 120, .center_freq = 5600}, | ||
2117 | { .hw_value = 140, .center_freq = 5700}, | 2201 | { .hw_value = 140, .center_freq = 5700}, |
2202 | { .hw_value = 185, .center_freq = 4925}, | ||
2203 | { .hw_value = 196, .center_freq = 4980}, | ||
2204 | { .hw_value = 12, .center_freq = 5060}, | ||
2205 | { .hw_value = 40, .center_freq = 5200}, | ||
2206 | { .hw_value = 52, .center_freq = 5260}, | ||
2207 | { .hw_value = 104, .center_freq = 5520}, | ||
2208 | { .hw_value = 124, .center_freq = 5620}, | ||
2118 | { .hw_value = 149, .center_freq = 5745}, | 2209 | { .hw_value = 149, .center_freq = 5745}, |
2119 | { .hw_value = 153, .center_freq = 5765}, | ||
2120 | { .hw_value = 157, .center_freq = 5785}, | ||
2121 | { .hw_value = 161, .center_freq = 5805}, | 2210 | { .hw_value = 161, .center_freq = 5805}, |
2211 | { .hw_value = 187, .center_freq = 4935}, | ||
2212 | { .hw_value = 7, .center_freq = 5035}, | ||
2213 | { .hw_value = 16, .center_freq = 5080}, | ||
2214 | { .hw_value = 42, .center_freq = 5210}, | ||
2215 | { .hw_value = 56, .center_freq = 5280}, | ||
2216 | { .hw_value = 108, .center_freq = 5540}, | ||
2217 | { .hw_value = 128, .center_freq = 5640}, | ||
2218 | { .hw_value = 153, .center_freq = 5765}, | ||
2122 | { .hw_value = 165, .center_freq = 5825}, | 2219 | { .hw_value = 165, .center_freq = 5825}, |
2123 | }; | 2220 | }; |
2124 | 2221 | ||
@@ -2211,8 +2308,7 @@ static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | |||
2211 | struct wl1271 *wl = dev_get_drvdata(dev); | 2308 | struct wl1271 *wl = dev_get_drvdata(dev); |
2212 | ssize_t len; | 2309 | ssize_t len; |
2213 | 2310 | ||
2214 | /* FIXME: what's the maximum length of buf? page size?*/ | 2311 | len = PAGE_SIZE; |
2215 | len = 500; | ||
2216 | 2312 | ||
2217 | mutex_lock(&wl->mutex); | 2313 | mutex_lock(&wl->mutex); |
2218 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | 2314 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", |
@@ -2273,8 +2369,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, | |||
2273 | struct wl1271 *wl = dev_get_drvdata(dev); | 2369 | struct wl1271 *wl = dev_get_drvdata(dev); |
2274 | ssize_t len; | 2370 | ssize_t len; |
2275 | 2371 | ||
2276 | /* FIXME: what's the maximum length of buf? page size?*/ | 2372 | len = PAGE_SIZE; |
2277 | len = 500; | ||
2278 | 2373 | ||
2279 | mutex_lock(&wl->mutex); | 2374 | mutex_lock(&wl->mutex); |
2280 | if (wl->hw_pg_ver >= 0) | 2375 | if (wl->hw_pg_ver >= 0) |
@@ -2306,6 +2401,8 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
2306 | 2401 | ||
2307 | wl->mac80211_registered = true; | 2402 | wl->mac80211_registered = true; |
2308 | 2403 | ||
2404 | register_netdevice_notifier(&wl1271_dev_notifier); | ||
2405 | |||
2309 | wl1271_notice("loaded"); | 2406 | wl1271_notice("loaded"); |
2310 | 2407 | ||
2311 | return 0; | 2408 | return 0; |
@@ -2314,6 +2411,7 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw); | |||
2314 | 2411 | ||
2315 | void wl1271_unregister_hw(struct wl1271 *wl) | 2412 | void wl1271_unregister_hw(struct wl1271 *wl) |
2316 | { | 2413 | { |
2414 | unregister_netdevice_notifier(&wl1271_dev_notifier); | ||
2317 | ieee80211_unregister_hw(wl->hw); | 2415 | ieee80211_unregister_hw(wl->hw); |
2318 | wl->mac80211_registered = false; | 2416 | wl->mac80211_registered = false; |
2319 | 2417 | ||
@@ -2322,6 +2420,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | |||
2322 | 2420 | ||
2323 | int wl1271_init_ieee80211(struct wl1271 *wl) | 2421 | int wl1271_init_ieee80211(struct wl1271 *wl) |
2324 | { | 2422 | { |
2423 | static const u32 cipher_suites[] = { | ||
2424 | WLAN_CIPHER_SUITE_WEP40, | ||
2425 | WLAN_CIPHER_SUITE_WEP104, | ||
2426 | WLAN_CIPHER_SUITE_TKIP, | ||
2427 | WLAN_CIPHER_SUITE_CCMP, | ||
2428 | WL1271_CIPHER_SUITE_GEM, | ||
2429 | }; | ||
2430 | |||
2325 | /* The tx descriptor buffer and the TKIP space. */ | 2431 | /* The tx descriptor buffer and the TKIP space. */ |
2326 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2432 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
2327 | sizeof(struct wl1271_tx_hw_descr); | 2433 | sizeof(struct wl1271_tx_hw_descr); |
@@ -2339,13 +2445,14 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2339 | IEEE80211_HW_CONNECTION_MONITOR | | 2445 | IEEE80211_HW_CONNECTION_MONITOR | |
2340 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | 2446 | IEEE80211_HW_SUPPORTS_CQM_RSSI; |
2341 | 2447 | ||
2448 | wl->hw->wiphy->cipher_suites = cipher_suites; | ||
2449 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
2450 | |||
2342 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2451 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2343 | BIT(NL80211_IFTYPE_ADHOC); | 2452 | BIT(NL80211_IFTYPE_ADHOC); |
2344 | wl->hw->wiphy->max_scan_ssids = 1; | 2453 | wl->hw->wiphy->max_scan_ssids = 1; |
2345 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 2454 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
2346 | 2455 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | |
2347 | if (wl1271_11a_enabled()) | ||
2348 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | ||
2349 | 2456 | ||
2350 | wl->hw->queues = 4; | 2457 | wl->hw->queues = 4; |
2351 | wl->hw->max_rates = 1; | 2458 | wl->hw->max_rates = 1; |
@@ -2364,6 +2471,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2364 | struct platform_device *plat_dev = NULL; | 2471 | struct platform_device *plat_dev = NULL; |
2365 | struct wl1271 *wl; | 2472 | struct wl1271 *wl; |
2366 | int i, ret; | 2473 | int i, ret; |
2474 | unsigned int order; | ||
2367 | 2475 | ||
2368 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2476 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2369 | if (!hw) { | 2477 | if (!hw) { |
@@ -2391,6 +2499,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2391 | 2499 | ||
2392 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2500 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2393 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | 2501 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); |
2502 | INIT_WORK(&wl->irq_work, wl1271_irq_work); | ||
2503 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | ||
2504 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | ||
2505 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | ||
2394 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2506 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2395 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 2507 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
2396 | wl->default_key = 0; | 2508 | wl->default_key = 0; |
@@ -2422,11 +2534,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2422 | 2534 | ||
2423 | wl1271_debugfs_init(wl); | 2535 | wl1271_debugfs_init(wl); |
2424 | 2536 | ||
2537 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | ||
2538 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | ||
2539 | if (!wl->aggr_buf) { | ||
2540 | ret = -ENOMEM; | ||
2541 | goto err_hw; | ||
2542 | } | ||
2543 | |||
2425 | /* Register platform device */ | 2544 | /* Register platform device */ |
2426 | ret = platform_device_register(wl->plat_dev); | 2545 | ret = platform_device_register(wl->plat_dev); |
2427 | if (ret) { | 2546 | if (ret) { |
2428 | wl1271_error("couldn't register platform device"); | 2547 | wl1271_error("couldn't register platform device"); |
2429 | goto err_hw; | 2548 | goto err_aggr; |
2430 | } | 2549 | } |
2431 | dev_set_drvdata(&wl->plat_dev->dev, wl); | 2550 | dev_set_drvdata(&wl->plat_dev->dev, wl); |
2432 | 2551 | ||
@@ -2452,6 +2571,9 @@ err_bt_coex_state: | |||
2452 | err_platform: | 2571 | err_platform: |
2453 | platform_device_unregister(wl->plat_dev); | 2572 | platform_device_unregister(wl->plat_dev); |
2454 | 2573 | ||
2574 | err_aggr: | ||
2575 | free_pages((unsigned long)wl->aggr_buf, order); | ||
2576 | |||
2455 | err_hw: | 2577 | err_hw: |
2456 | wl1271_debugfs_exit(wl); | 2578 | wl1271_debugfs_exit(wl); |
2457 | kfree(plat_dev); | 2579 | kfree(plat_dev); |
@@ -2468,6 +2590,8 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | |||
2468 | int wl1271_free_hw(struct wl1271 *wl) | 2590 | int wl1271_free_hw(struct wl1271 *wl) |
2469 | { | 2591 | { |
2470 | platform_device_unregister(wl->plat_dev); | 2592 | platform_device_unregister(wl->plat_dev); |
2593 | free_pages((unsigned long)wl->aggr_buf, | ||
2594 | get_order(WL1271_AGGR_BUFFER_SIZE)); | ||
2471 | kfree(wl->plat_dev); | 2595 | kfree(wl->plat_dev); |
2472 | 2596 | ||
2473 | wl1271_debugfs_exit(wl); | 2597 | wl1271_debugfs_exit(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index a5e60e0403e5..e3c332e2f97c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 39 | ||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
43 | goto out; | ||
44 | |||
42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 45 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && | 46 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
44 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | 47 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) |
@@ -61,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
61 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | 64 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { |
62 | cancel_delayed_work(&wl->elp_work); | 65 | cancel_delayed_work(&wl->elp_work); |
63 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 66 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
64 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 67 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -96,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
96 | &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); | 99 | &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); |
97 | if (ret == 0) { | 100 | if (ret == 0) { |
98 | wl1271_error("ELP wakeup timeout!"); | 101 | wl1271_error("ELP wakeup timeout!"); |
102 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
99 | ret = -ETIMEDOUT; | 103 | ret = -ETIMEDOUT; |
100 | goto err; | 104 | goto err; |
101 | } else if (ret < 0) { | 105 | } else if (ret < 0) { |
@@ -121,7 +125,7 @@ out: | |||
121 | } | 125 | } |
122 | 126 | ||
123 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | 127 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
124 | bool send) | 128 | u32 rates, bool send) |
125 | { | 129 | { |
126 | int ret; | 130 | int ret; |
127 | 131 | ||
@@ -129,7 +133,14 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
129 | case STATION_POWER_SAVE_MODE: | 133 | case STATION_POWER_SAVE_MODE: |
130 | wl1271_debug(DEBUG_PSM, "entering psm"); | 134 | wl1271_debug(DEBUG_PSM, "entering psm"); |
131 | 135 | ||
132 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send); | 136 | ret = wl1271_acx_wake_up_conditions(wl); |
137 | if (ret < 0) { | ||
138 | wl1271_error("couldn't set wake up conditions"); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, | ||
143 | rates, send); | ||
133 | if (ret < 0) | 144 | if (ret < 0) |
134 | return ret; | 145 | return ret; |
135 | 146 | ||
@@ -152,7 +163,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
152 | if (ret < 0) | 163 | if (ret < 0) |
153 | return ret; | 164 | return ret; |
154 | 165 | ||
155 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send); | 166 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, |
167 | rates, send); | ||
156 | if (ret < 0) | 168 | if (ret < 0) |
157 | return ret; | 169 | return ret; |
158 | 170 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index 940276f517a4..6ba7b032736f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
31 | bool send); | 31 | u32 rates, bool send); |
32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); |
34 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 019aa79cd9df..bea133b6e489 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -74,9 +74,8 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | 77 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) |
78 | { | 78 | { |
79 | struct ieee80211_rx_status rx_status; | ||
80 | struct wl1271_rx_descriptor *desc; | 79 | struct wl1271_rx_descriptor *desc; |
81 | struct sk_buff *skb; | 80 | struct sk_buff *skb; |
82 | u16 *fc; | 81 | u16 *fc; |
@@ -88,16 +87,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
88 | * workaround this by not retrieving them at all. | 87 | * workaround this by not retrieving them at all. |
89 | */ | 88 | */ |
90 | if (unlikely(wl->state == WL1271_STATE_PLT)) | 89 | if (unlikely(wl->state == WL1271_STATE_PLT)) |
91 | return; | 90 | return -EINVAL; |
92 | 91 | ||
93 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 92 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
94 | if (!skb) { | 93 | if (!skb) { |
95 | wl1271_error("Couldn't allocate RX frame"); | 94 | wl1271_error("Couldn't allocate RX frame"); |
96 | return; | 95 | return -ENOMEM; |
97 | } | 96 | } |
98 | 97 | ||
99 | buf = skb_put(skb, length); | 98 | buf = skb_put(skb, length); |
100 | wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); | 99 | memcpy(buf, data, length); |
101 | 100 | ||
102 | /* the data read starts with the descriptor */ | 101 | /* the data read starts with the descriptor */ |
103 | desc = (struct wl1271_rx_descriptor *) buf; | 102 | desc = (struct wl1271_rx_descriptor *) buf; |
@@ -109,15 +108,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
109 | if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) | 108 | if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) |
110 | beacon = 1; | 109 | beacon = 1; |
111 | 110 | ||
112 | wl1271_rx_status(wl, desc, &rx_status, beacon); | 111 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
113 | 112 | ||
114 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | 113 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, |
115 | beacon ? "beacon" : ""); | 114 | beacon ? "beacon" : ""); |
116 | 115 | ||
117 | skb_trim(skb, skb->len - desc->pad_len); | 116 | skb_trim(skb, skb->len - desc->pad_len); |
118 | 117 | ||
119 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | ||
120 | ieee80211_rx_ni(wl->hw, skb); | 118 | ieee80211_rx_ni(wl->hw, skb); |
119 | |||
120 | return 0; | ||
121 | } | 121 | } |
122 | 122 | ||
123 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | 123 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) |
@@ -126,31 +126,60 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
126 | u32 buf_size; | 126 | u32 buf_size; |
127 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 127 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
128 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 128 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
129 | u32 rx_counter; | ||
129 | u32 mem_block; | 130 | u32 mem_block; |
131 | u32 pkt_length; | ||
132 | u32 pkt_offset; | ||
130 | 133 | ||
131 | while (drv_rx_counter != fw_rx_counter) { | 134 | while (drv_rx_counter != fw_rx_counter) { |
132 | mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); | 135 | buf_size = 0; |
133 | buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter); | 136 | rx_counter = drv_rx_counter; |
137 | while (rx_counter != fw_rx_counter) { | ||
138 | pkt_length = wl1271_rx_get_buf_size(status, rx_counter); | ||
139 | if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) | ||
140 | break; | ||
141 | buf_size += pkt_length; | ||
142 | rx_counter++; | ||
143 | rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | ||
144 | } | ||
134 | 145 | ||
135 | if (buf_size == 0) { | 146 | if (buf_size == 0) { |
136 | wl1271_warning("received empty data"); | 147 | wl1271_warning("received empty data"); |
137 | break; | 148 | break; |
138 | } | 149 | } |
139 | 150 | ||
151 | /* | ||
152 | * Choose the block we want to read | ||
153 | * For aggregated packets, only the first memory block should | ||
154 | * be retrieved. The FW takes care of the rest. | ||
155 | */ | ||
156 | mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); | ||
140 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + | 157 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + |
141 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); | 158 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); |
142 | wl->rx_mem_pool_addr.addr_extra = | 159 | wl->rx_mem_pool_addr.addr_extra = |
143 | wl->rx_mem_pool_addr.addr + 4; | 160 | wl->rx_mem_pool_addr.addr + 4; |
144 | |||
145 | /* Choose the block we want to read */ | ||
146 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, | 161 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, |
147 | sizeof(wl->rx_mem_pool_addr), false); | 162 | sizeof(wl->rx_mem_pool_addr), false); |
148 | 163 | ||
149 | wl1271_rx_handle_data(wl, buf_size); | 164 | /* Read all available packets at once */ |
150 | 165 | wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, | |
151 | wl->rx_counter++; | 166 | buf_size, true); |
152 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 167 | |
168 | /* Split data into separate packets */ | ||
169 | pkt_offset = 0; | ||
170 | while (pkt_offset < buf_size) { | ||
171 | pkt_length = wl1271_rx_get_buf_size(status, | ||
172 | drv_rx_counter); | ||
173 | if (wl1271_rx_handle_data(wl, | ||
174 | wl->aggr_buf + pkt_offset, | ||
175 | pkt_length) < 0) | ||
176 | break; | ||
177 | wl->rx_counter++; | ||
178 | drv_rx_counter++; | ||
179 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | ||
180 | pkt_offset += pkt_length; | ||
181 | } | ||
153 | } | 182 | } |
154 | 183 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, | |
155 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 184 | cpu_to_le32(wl->rx_counter)); |
156 | } | 185 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c index fec43eed8c55..909bb47995b6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.c +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c | |||
@@ -28,11 +28,43 @@ | |||
28 | #include "wl1271_scan.h" | 28 | #include "wl1271_scan.h" |
29 | #include "wl1271_acx.h" | 29 | #include "wl1271_acx.h" |
30 | 30 | ||
31 | void wl1271_scan_complete_work(struct work_struct *work) | ||
32 | { | ||
33 | struct delayed_work *dwork; | ||
34 | struct wl1271 *wl; | ||
35 | |||
36 | dwork = container_of(work, struct delayed_work, work); | ||
37 | wl = container_of(dwork, struct wl1271, scan_complete_work); | ||
38 | |||
39 | wl1271_debug(DEBUG_SCAN, "Scanning complete"); | ||
40 | |||
41 | mutex_lock(&wl->mutex); | ||
42 | |||
43 | if (wl->scan.state == WL1271_SCAN_STATE_IDLE) { | ||
44 | mutex_unlock(&wl->mutex); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
49 | kfree(wl->scan.scanned_ch); | ||
50 | wl->scan.scanned_ch = NULL; | ||
51 | mutex_unlock(&wl->mutex); | ||
52 | |||
53 | ieee80211_scan_completed(wl->hw, false); | ||
54 | |||
55 | if (wl->scan.failed) { | ||
56 | wl1271_info("Scan completed due to error."); | ||
57 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | |||
31 | static int wl1271_get_scan_channels(struct wl1271 *wl, | 62 | static int wl1271_get_scan_channels(struct wl1271 *wl, |
32 | struct cfg80211_scan_request *req, | 63 | struct cfg80211_scan_request *req, |
33 | struct basic_scan_channel_params *channels, | 64 | struct basic_scan_channel_params *channels, |
34 | enum ieee80211_band band, bool passive) | 65 | enum ieee80211_band band, bool passive) |
35 | { | 66 | { |
67 | struct conf_scan_settings *c = &wl->conf.scan; | ||
36 | int i, j; | 68 | int i, j; |
37 | u32 flags; | 69 | u32 flags; |
38 | 70 | ||
@@ -60,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, | |||
60 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", | 92 | wl1271_debug(DEBUG_SCAN, "beacon_found %d", |
61 | req->channels[i]->beacon_found); | 93 | req->channels[i]->beacon_found); |
62 | 94 | ||
63 | channels[j].min_duration = | 95 | if (!passive) { |
64 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | 96 | channels[j].min_duration = |
65 | channels[j].max_duration = | 97 | cpu_to_le32(c->min_dwell_time_active); |
66 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | 98 | channels[j].max_duration = |
99 | cpu_to_le32(c->max_dwell_time_active); | ||
100 | } else { | ||
101 | channels[j].min_duration = | ||
102 | cpu_to_le32(c->min_dwell_time_passive); | ||
103 | channels[j].max_duration = | ||
104 | cpu_to_le32(c->max_dwell_time_passive); | ||
105 | } | ||
67 | channels[j].early_termination = 0; | 106 | channels[j].early_termination = 0; |
68 | channels[j].tx_power_att = req->channels[i]->max_power; | 107 | channels[j].tx_power_att = req->channels[i]->max_power; |
69 | channels[j].channel = req->channels[i]->hw_value; | 108 | channels[j].channel = req->channels[i]->hw_value; |
@@ -100,8 +139,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
100 | 139 | ||
101 | /* We always use high priority scans */ | 140 | /* We always use high priority scans */ |
102 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; | 141 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; |
103 | if(passive) | 142 | |
143 | /* No SSIDs means that we have a forced passive scan */ | ||
144 | if (passive || wl->scan.req->n_ssids == 0) | ||
104 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | 145 | scan_options |= WL1271_SCAN_OPT_PASSIVE; |
146 | |||
105 | cmd->params.scan_options = cpu_to_le16(scan_options); | 147 | cmd->params.scan_options = cpu_to_le16(scan_options); |
106 | 148 | ||
107 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, | 149 | cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, |
@@ -117,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
117 | cmd->params.rx_filter_options = | 159 | cmd->params.rx_filter_options = |
118 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); | 160 | cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); |
119 | 161 | ||
120 | cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS; | 162 | cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; |
121 | cmd->params.tx_rate = cpu_to_le32(basic_rate); | 163 | cmd->params.tx_rate = cpu_to_le32(basic_rate); |
122 | cmd->params.tid_trigger = 0; | 164 | cmd->params.tid_trigger = 0; |
123 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 165 | cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
@@ -165,7 +207,7 @@ out: | |||
165 | 207 | ||
166 | void wl1271_scan_stm(struct wl1271 *wl) | 208 | void wl1271_scan_stm(struct wl1271 *wl) |
167 | { | 209 | { |
168 | int ret; | 210 | int ret = 0; |
169 | 211 | ||
170 | switch (wl->scan.state) { | 212 | switch (wl->scan.state) { |
171 | case WL1271_SCAN_STATE_IDLE: | 213 | case WL1271_SCAN_STATE_IDLE: |
@@ -185,7 +227,7 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
185 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, | 227 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, |
186 | wl->conf.tx.basic_rate); | 228 | wl->conf.tx.basic_rate); |
187 | if (ret == WL1271_NOTHING_TO_SCAN) { | 229 | if (ret == WL1271_NOTHING_TO_SCAN) { |
188 | if (wl1271_11a_enabled()) | 230 | if (wl->enable_11a) |
189 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | 231 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; |
190 | else | 232 | else |
191 | wl->scan.state = WL1271_SCAN_STATE_DONE; | 233 | wl->scan.state = WL1271_SCAN_STATE_DONE; |
@@ -215,20 +257,22 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
215 | break; | 257 | break; |
216 | 258 | ||
217 | case WL1271_SCAN_STATE_DONE: | 259 | case WL1271_SCAN_STATE_DONE: |
218 | mutex_unlock(&wl->mutex); | 260 | wl->scan.failed = false; |
219 | ieee80211_scan_completed(wl->hw, false); | 261 | cancel_delayed_work(&wl->scan_complete_work); |
220 | mutex_lock(&wl->mutex); | 262 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, |
221 | 263 | msecs_to_jiffies(0)); | |
222 | kfree(wl->scan.scanned_ch); | ||
223 | wl->scan.scanned_ch = NULL; | ||
224 | |||
225 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | ||
226 | break; | 264 | break; |
227 | 265 | ||
228 | default: | 266 | default: |
229 | wl1271_error("invalid scan state"); | 267 | wl1271_error("invalid scan state"); |
230 | break; | 268 | break; |
231 | } | 269 | } |
270 | |||
271 | if (ret < 0) { | ||
272 | cancel_delayed_work(&wl->scan_complete_work); | ||
273 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
274 | msecs_to_jiffies(0)); | ||
275 | } | ||
232 | } | 276 | } |
233 | 277 | ||
234 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | 278 | int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, |
@@ -248,9 +292,14 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
248 | 292 | ||
249 | wl->scan.req = req; | 293 | wl->scan.req = req; |
250 | 294 | ||
251 | wl->scan.scanned_ch = kzalloc(req->n_channels * | 295 | wl->scan.scanned_ch = kcalloc(req->n_channels, |
252 | sizeof(*wl->scan.scanned_ch), | 296 | sizeof(*wl->scan.scanned_ch), |
253 | GFP_KERNEL); | 297 | GFP_KERNEL); |
298 | /* we assume failure so that timeout scenarios are handled correctly */ | ||
299 | wl->scan.failed = true; | ||
300 | ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, | ||
301 | msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); | ||
302 | |||
254 | wl1271_scan_stm(wl); | 303 | wl1271_scan_stm(wl); |
255 | 304 | ||
256 | return 0; | 305 | return 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h index f1815700f5f9..6d57127b5e6b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_scan.h +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h | |||
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, | |||
32 | const u8 *ssid, size_t ssid_len, | 32 | const u8 *ssid, size_t ssid_len, |
33 | const u8 *ie, size_t ie_len, u8 band); | 33 | const u8 *ie, size_t ie_len, u8 band); |
34 | void wl1271_scan_stm(struct wl1271 *wl); | 34 | void wl1271_scan_stm(struct wl1271 *wl); |
35 | void wl1271_scan_complete_work(struct work_struct *work); | ||
35 | 36 | ||
36 | #define WL1271_SCAN_MAX_CHANNELS 24 | 37 | #define WL1271_SCAN_MAX_CHANNELS 24 |
37 | #define WL1271_SCAN_DEFAULT_TAG 1 | 38 | #define WL1271_SCAN_DEFAULT_TAG 1 |
@@ -39,11 +40,10 @@ void wl1271_scan_stm(struct wl1271 *wl); | |||
39 | #define WL1271_SCAN_OPT_ACTIVE 0 | 40 | #define WL1271_SCAN_OPT_ACTIVE 0 |
40 | #define WL1271_SCAN_OPT_PASSIVE 1 | 41 | #define WL1271_SCAN_OPT_PASSIVE 1 |
41 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | 42 | #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 | 43 | #define WL1271_SCAN_BAND_2_4_GHZ 0 |
45 | #define WL1271_SCAN_BAND_5_GHZ 1 | 44 | #define WL1271_SCAN_BAND_5_GHZ 1 |
46 | #define WL1271_SCAN_PROBE_REQS 3 | 45 | |
46 | #define WL1271_SCAN_TIMEOUT 10000 /* msec */ | ||
47 | 47 | ||
48 | enum { | 48 | enum { |
49 | WL1271_SCAN_STATE_IDLE, | 49 | WL1271_SCAN_STATE_IDLE, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 7059b5cccf0f..784ef3432641 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -29,14 +29,13 @@ | |||
29 | #include <linux/mmc/sdio_ids.h> | 29 | #include <linux/mmc/sdio_ids.h> |
30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/wl12xx.h> | ||
33 | #include <linux/pm_runtime.h> | ||
32 | 34 | ||
33 | #include "wl1271.h" | 35 | #include "wl1271.h" |
34 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
35 | #include "wl1271_io.h" | 37 | #include "wl1271_io.h" |
36 | 38 | ||
37 | |||
38 | #define RX71_WL1271_IRQ_GPIO 42 | ||
39 | |||
40 | #ifndef SDIO_VENDOR_ID_TI | 39 | #ifndef SDIO_VENDOR_ID_TI |
41 | #define SDIO_VENDOR_ID_TI 0x0097 | 40 | #define SDIO_VENDOR_ID_TI 0x0097 |
42 | #endif | 41 | #endif |
@@ -107,6 +106,8 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
107 | int ret; | 106 | int ret; |
108 | struct sdio_func *func = wl_to_func(wl); | 107 | struct sdio_func *func = wl_to_func(wl); |
109 | 108 | ||
109 | sdio_claim_host(func); | ||
110 | |||
110 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 111 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
111 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 112 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
112 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", | 113 | wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", |
@@ -122,9 +123,10 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 123 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
123 | } | 124 | } |
124 | 125 | ||
126 | sdio_release_host(func); | ||
127 | |||
125 | if (ret) | 128 | if (ret) |
126 | wl1271_error("sdio read failed (%d)", ret); | 129 | wl1271_error("sdio read failed (%d)", ret); |
127 | |||
128 | } | 130 | } |
129 | 131 | ||
130 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | 132 | static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, |
@@ -133,6 +135,8 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
133 | int ret; | 135 | int ret; |
134 | struct sdio_func *func = wl_to_func(wl); | 136 | struct sdio_func *func = wl_to_func(wl); |
135 | 137 | ||
138 | sdio_claim_host(func); | ||
139 | |||
136 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 140 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
137 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 141 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | 142 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", |
@@ -147,26 +151,49 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
147 | else | 151 | else |
148 | ret = sdio_memcpy_toio(func, addr, buf, len); | 152 | ret = sdio_memcpy_toio(func, addr, buf, len); |
149 | } | 153 | } |
154 | |||
155 | sdio_release_host(func); | ||
156 | |||
150 | if (ret) | 157 | if (ret) |
151 | wl1271_error("sdio write failed (%d)", ret); | 158 | wl1271_error("sdio write failed (%d)", ret); |
159 | } | ||
152 | 160 | ||
161 | static int wl1271_sdio_power_on(struct wl1271 *wl) | ||
162 | { | ||
163 | struct sdio_func *func = wl_to_func(wl); | ||
164 | int ret; | ||
165 | |||
166 | /* Power up the card */ | ||
167 | ret = pm_runtime_get_sync(&func->dev); | ||
168 | if (ret < 0) | ||
169 | goto out; | ||
170 | |||
171 | sdio_claim_host(func); | ||
172 | sdio_enable_func(func); | ||
173 | sdio_release_host(func); | ||
174 | |||
175 | out: | ||
176 | return ret; | ||
153 | } | 177 | } |
154 | 178 | ||
155 | static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | 179 | static int wl1271_sdio_power_off(struct wl1271 *wl) |
156 | { | 180 | { |
157 | struct sdio_func *func = wl_to_func(wl); | 181 | struct sdio_func *func = wl_to_func(wl); |
158 | 182 | ||
159 | /* Let the SDIO stack handle wlan_enable control, so we | 183 | sdio_claim_host(func); |
160 | * keep host claimed while wlan is in use to keep wl1271 | 184 | sdio_disable_func(func); |
161 | * alive. | 185 | sdio_release_host(func); |
162 | */ | 186 | |
163 | if (enable) { | 187 | /* Power down the card */ |
164 | sdio_claim_host(func); | 188 | return pm_runtime_put_sync(&func->dev); |
165 | sdio_enable_func(func); | 189 | } |
166 | } else { | 190 | |
167 | sdio_disable_func(func); | 191 | static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) |
168 | sdio_release_host(func); | 192 | { |
169 | } | 193 | if (enable) |
194 | return wl1271_sdio_power_on(wl); | ||
195 | else | ||
196 | return wl1271_sdio_power_off(wl); | ||
170 | } | 197 | } |
171 | 198 | ||
172 | static struct wl1271_if_operations sdio_ops = { | 199 | static struct wl1271_if_operations sdio_ops = { |
@@ -184,6 +211,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
184 | const struct sdio_device_id *id) | 211 | const struct sdio_device_id *id) |
185 | { | 212 | { |
186 | struct ieee80211_hw *hw; | 213 | struct ieee80211_hw *hw; |
214 | const struct wl12xx_platform_data *wlan_data; | ||
187 | struct wl1271 *wl; | 215 | struct wl1271 *wl; |
188 | int ret; | 216 | int ret; |
189 | 217 | ||
@@ -203,13 +231,16 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
203 | /* Grab access to FN0 for ELP reg. */ | 231 | /* Grab access to FN0 for ELP reg. */ |
204 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | 232 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; |
205 | 233 | ||
206 | wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); | 234 | wlan_data = wl12xx_get_platform_data(); |
207 | if (wl->irq < 0) { | 235 | if (IS_ERR(wlan_data)) { |
208 | ret = wl->irq; | 236 | ret = PTR_ERR(wlan_data); |
209 | wl1271_error("could not get irq!"); | 237 | wl1271_error("missing wlan platform data: %d", ret); |
210 | goto out_free; | 238 | goto out_free; |
211 | } | 239 | } |
212 | 240 | ||
241 | wl->irq = wlan_data->irq; | ||
242 | wl->ref_clock = wlan_data->board_ref_clock; | ||
243 | |||
213 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | 244 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); |
214 | if (ret < 0) { | 245 | if (ret < 0) { |
215 | wl1271_error("request_irq() failed: %d", ret); | 246 | wl1271_error("request_irq() failed: %d", ret); |
@@ -230,6 +261,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
230 | 261 | ||
231 | sdio_set_drvdata(func, wl); | 262 | sdio_set_drvdata(func, wl); |
232 | 263 | ||
264 | /* Tell PM core that we don't need the card to be powered now */ | ||
265 | pm_runtime_put_noidle(&func->dev); | ||
266 | |||
233 | wl1271_notice("initialized"); | 267 | wl1271_notice("initialized"); |
234 | 268 | ||
235 | return 0; | 269 | return 0; |
@@ -248,17 +282,39 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
248 | { | 282 | { |
249 | struct wl1271 *wl = sdio_get_drvdata(func); | 283 | struct wl1271 *wl = sdio_get_drvdata(func); |
250 | 284 | ||
251 | free_irq(wl->irq, wl); | 285 | /* Undo decrement done above in wl1271_probe */ |
286 | pm_runtime_get_noresume(&func->dev); | ||
252 | 287 | ||
253 | wl1271_unregister_hw(wl); | 288 | wl1271_unregister_hw(wl); |
289 | free_irq(wl->irq, wl); | ||
254 | wl1271_free_hw(wl); | 290 | wl1271_free_hw(wl); |
255 | } | 291 | } |
256 | 292 | ||
293 | static int wl1271_suspend(struct device *dev) | ||
294 | { | ||
295 | /* Tell MMC/SDIO core it's OK to power down the card | ||
296 | * (if it isn't already), but not to remove it completely */ | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int wl1271_resume(struct device *dev) | ||
301 | { | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static const struct dev_pm_ops wl1271_sdio_pm_ops = { | ||
306 | .suspend = wl1271_suspend, | ||
307 | .resume = wl1271_resume, | ||
308 | }; | ||
309 | |||
257 | static struct sdio_driver wl1271_sdio_driver = { | 310 | static struct sdio_driver wl1271_sdio_driver = { |
258 | .name = "wl1271_sdio", | 311 | .name = "wl1271_sdio", |
259 | .id_table = wl1271_devices, | 312 | .id_table = wl1271_devices, |
260 | .probe = wl1271_probe, | 313 | .probe = wl1271_probe, |
261 | .remove = __devexit_p(wl1271_remove), | 314 | .remove = __devexit_p(wl1271_remove), |
315 | .drv = { | ||
316 | .pm = &wl1271_sdio_pm_ops, | ||
317 | }, | ||
262 | }; | 318 | }; |
263 | 319 | ||
264 | static int __init wl1271_init(void) | 320 | static int __init wl1271_init(void) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4cb99c541e2a..ef801680773f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/crc7.h> | 26 | #include <linux/crc7.h> |
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/spi/wl12xx.h> | 28 | #include <linux/wl12xx.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | #include "wl1271.h" | 31 | #include "wl1271.h" |
@@ -63,6 +63,11 @@ | |||
63 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | 63 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) |
64 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | 64 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 |
65 | 65 | ||
66 | /* HW limitation: maximum possible chunk size is 4095 bytes */ | ||
67 | #define WSPI_MAX_CHUNK_SIZE 4092 | ||
68 | |||
69 | #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) | ||
70 | |||
66 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) | 71 | static inline struct spi_device *wl_to_spi(struct wl1271 *wl) |
67 | { | 72 | { |
68 | return wl->if_priv; | 73 | return wl->if_priv; |
@@ -202,90 +207,117 @@ static int wl1271_spi_read_busy(struct wl1271 *wl) | |||
202 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 207 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
203 | size_t len, bool fixed) | 208 | size_t len, bool fixed) |
204 | { | 209 | { |
205 | struct spi_transfer t[3]; | 210 | struct spi_transfer t[2]; |
206 | struct spi_message m; | 211 | struct spi_message m; |
207 | u32 *busy_buf; | 212 | u32 *busy_buf; |
208 | u32 *cmd; | 213 | u32 *cmd; |
214 | u32 chunk_len; | ||
209 | 215 | ||
210 | cmd = &wl->buffer_cmd; | 216 | while (len > 0) { |
211 | busy_buf = wl->buffer_busyword; | 217 | chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len); |
212 | 218 | ||
213 | *cmd = 0; | 219 | cmd = &wl->buffer_cmd; |
214 | *cmd |= WSPI_CMD_READ; | 220 | busy_buf = wl->buffer_busyword; |
215 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
216 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
217 | 221 | ||
218 | if (fixed) | 222 | *cmd = 0; |
219 | *cmd |= WSPI_CMD_FIXED; | 223 | *cmd |= WSPI_CMD_READ; |
224 | *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & | ||
225 | WSPI_CMD_BYTE_LENGTH; | ||
226 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
220 | 227 | ||
221 | spi_message_init(&m); | 228 | if (fixed) |
222 | memset(t, 0, sizeof(t)); | 229 | *cmd |= WSPI_CMD_FIXED; |
223 | 230 | ||
224 | t[0].tx_buf = cmd; | 231 | spi_message_init(&m); |
225 | t[0].len = 4; | 232 | memset(t, 0, sizeof(t)); |
226 | t[0].cs_change = true; | ||
227 | spi_message_add_tail(&t[0], &m); | ||
228 | 233 | ||
229 | /* Busy and non busy words read */ | 234 | t[0].tx_buf = cmd; |
230 | t[1].rx_buf = busy_buf; | 235 | t[0].len = 4; |
231 | t[1].len = WL1271_BUSY_WORD_LEN; | 236 | t[0].cs_change = true; |
232 | t[1].cs_change = true; | 237 | spi_message_add_tail(&t[0], &m); |
233 | spi_message_add_tail(&t[1], &m); | ||
234 | 238 | ||
235 | spi_sync(wl_to_spi(wl), &m); | 239 | /* Busy and non busy words read */ |
240 | t[1].rx_buf = busy_buf; | ||
241 | t[1].len = WL1271_BUSY_WORD_LEN; | ||
242 | t[1].cs_change = true; | ||
243 | spi_message_add_tail(&t[1], &m); | ||
236 | 244 | ||
237 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && | 245 | spi_sync(wl_to_spi(wl), &m); |
238 | wl1271_spi_read_busy(wl)) { | ||
239 | memset(buf, 0, len); | ||
240 | return; | ||
241 | } | ||
242 | 246 | ||
243 | spi_message_init(&m); | 247 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
244 | memset(t, 0, sizeof(t)); | 248 | wl1271_spi_read_busy(wl)) { |
249 | memset(buf, 0, chunk_len); | ||
250 | return; | ||
251 | } | ||
245 | 252 | ||
246 | t[0].rx_buf = buf; | 253 | spi_message_init(&m); |
247 | t[0].len = len; | 254 | memset(t, 0, sizeof(t)); |
248 | t[0].cs_change = true; | ||
249 | spi_message_add_tail(&t[0], &m); | ||
250 | 255 | ||
251 | spi_sync(wl_to_spi(wl), &m); | 256 | t[0].rx_buf = buf; |
257 | t[0].len = chunk_len; | ||
258 | t[0].cs_change = true; | ||
259 | spi_message_add_tail(&t[0], &m); | ||
252 | 260 | ||
253 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 261 | spi_sync(wl_to_spi(wl), &m); |
254 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 262 | |
263 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | ||
264 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len); | ||
265 | |||
266 | if (!fixed) | ||
267 | addr += chunk_len; | ||
268 | buf += chunk_len; | ||
269 | len -= chunk_len; | ||
270 | } | ||
255 | } | 271 | } |
256 | 272 | ||
257 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | 273 | static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
258 | size_t len, bool fixed) | 274 | size_t len, bool fixed) |
259 | { | 275 | { |
260 | struct spi_transfer t[2]; | 276 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; |
261 | struct spi_message m; | 277 | struct spi_message m; |
278 | u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; | ||
262 | u32 *cmd; | 279 | u32 *cmd; |
280 | u32 chunk_len; | ||
281 | int i; | ||
263 | 282 | ||
264 | cmd = &wl->buffer_cmd; | 283 | WARN_ON(len > WL1271_AGGR_BUFFER_SIZE); |
265 | |||
266 | *cmd = 0; | ||
267 | *cmd |= WSPI_CMD_WRITE; | ||
268 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
269 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
270 | |||
271 | if (fixed) | ||
272 | *cmd |= WSPI_CMD_FIXED; | ||
273 | 284 | ||
274 | spi_message_init(&m); | 285 | spi_message_init(&m); |
275 | memset(t, 0, sizeof(t)); | 286 | memset(t, 0, sizeof(t)); |
276 | 287 | ||
277 | t[0].tx_buf = cmd; | 288 | cmd = &commands[0]; |
278 | t[0].len = sizeof(*cmd); | 289 | i = 0; |
279 | spi_message_add_tail(&t[0], &m); | 290 | while (len > 0) { |
291 | chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len); | ||
280 | 292 | ||
281 | t[1].tx_buf = buf; | 293 | *cmd = 0; |
282 | t[1].len = len; | 294 | *cmd |= WSPI_CMD_WRITE; |
283 | spi_message_add_tail(&t[1], &m); | 295 | *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & |
296 | WSPI_CMD_BYTE_LENGTH; | ||
297 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
284 | 298 | ||
285 | spi_sync(wl_to_spi(wl), &m); | 299 | if (fixed) |
300 | *cmd |= WSPI_CMD_FIXED; | ||
301 | |||
302 | t[i].tx_buf = cmd; | ||
303 | t[i].len = sizeof(*cmd); | ||
304 | spi_message_add_tail(&t[i++], &m); | ||
305 | |||
306 | t[i].tx_buf = buf; | ||
307 | t[i].len = chunk_len; | ||
308 | spi_message_add_tail(&t[i++], &m); | ||
286 | 309 | ||
287 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 310 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
288 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 311 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len); |
312 | |||
313 | if (!fixed) | ||
314 | addr += chunk_len; | ||
315 | buf += chunk_len; | ||
316 | len -= chunk_len; | ||
317 | cmd++; | ||
318 | } | ||
319 | |||
320 | spi_sync(wl_to_spi(wl), &m); | ||
289 | } | 321 | } |
290 | 322 | ||
291 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 323 | static irqreturn_t wl1271_irq(int irq, void *cookie) |
@@ -312,10 +344,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
312 | return IRQ_HANDLED; | 344 | return IRQ_HANDLED; |
313 | } | 345 | } |
314 | 346 | ||
315 | static void wl1271_spi_set_power(struct wl1271 *wl, bool enable) | 347 | static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) |
316 | { | 348 | { |
317 | if (wl->set_power) | 349 | if (wl->set_power) |
318 | wl->set_power(enable); | 350 | wl->set_power(enable); |
351 | |||
352 | return 0; | ||
319 | } | 353 | } |
320 | 354 | ||
321 | static struct wl1271_if_operations spi_ops = { | 355 | static struct wl1271_if_operations spi_ops = { |
@@ -370,6 +404,8 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
370 | goto out_free; | 404 | goto out_free; |
371 | } | 405 | } |
372 | 406 | ||
407 | wl->ref_clock = pdata->board_ref_clock; | ||
408 | |||
373 | wl->irq = spi->irq; | 409 | wl->irq = spi->irq; |
374 | if (wl->irq < 0) { | 410 | if (wl->irq < 0) { |
375 | wl1271_error("irq missing in platform data"); | 411 | wl1271_error("irq missing in platform data"); |
@@ -412,9 +448,8 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
412 | { | 448 | { |
413 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | 449 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); |
414 | 450 | ||
415 | free_irq(wl->irq, wl); | ||
416 | |||
417 | wl1271_unregister_hw(wl); | 451 | wl1271_unregister_hw(wl); |
452 | free_irq(wl->irq, wl); | ||
418 | wl1271_free_hw(wl); | 453 | wl1271_free_hw(wl); |
419 | 454 | ||
420 | return 0; | 455 | return 0; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c index 6e0952f79e9a..a3aa84386c88 100644 --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | 199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); |
200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); | 200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); |
201 | 201 | ||
202 | /* | ||
203 | * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band | ||
204 | * configurations) can be removed when those NVS files stop floating | ||
205 | * around. | ||
206 | */ | ||
207 | if (len != sizeof(struct wl1271_nvs_file) && | ||
208 | (len != WL1271_INI_LEGACY_NVS_FILE_SIZE || | ||
209 | wl1271_11a_enabled())) { | ||
210 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
211 | len, sizeof(struct wl1271_nvs_file)); | ||
212 | return -EMSGSIZE; | ||
213 | } | ||
214 | |||
215 | mutex_lock(&wl->mutex); | 202 | mutex_lock(&wl->mutex); |
216 | 203 | ||
217 | kfree(wl->nvs); | 204 | kfree(wl->nvs); |
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | |||
224 | } | 211 | } |
225 | 212 | ||
226 | memcpy(wl->nvs, buf, len); | 213 | memcpy(wl->nvs, buf, len); |
214 | wl->nvs_len = len; | ||
227 | 215 | ||
228 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); | 216 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); |
229 | 217 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index c592cc2e9fe8..e3dc13c4d01a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -43,13 +43,17 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
43 | return -EBUSY; | 43 | return -EBUSY; |
44 | } | 44 | } |
45 | 45 | ||
46 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | 46 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, |
47 | u32 buf_offset) | ||
47 | { | 48 | { |
48 | struct wl1271_tx_hw_descr *desc; | 49 | struct wl1271_tx_hw_descr *desc; |
49 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 50 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
50 | u32 total_blocks; | 51 | u32 total_blocks; |
51 | int id, ret = -EBUSY; | 52 | int id, ret = -EBUSY; |
52 | 53 | ||
54 | if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) | ||
55 | return -EBUSY; | ||
56 | |||
53 | /* allocate free identifier for the packet */ | 57 | /* allocate free identifier for the packet */ |
54 | id = wl1271_tx_id(wl, skb); | 58 | id = wl1271_tx_id(wl, skb); |
55 | if (id < 0) | 59 | if (id < 0) |
@@ -82,7 +86,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
82 | return ret; | 86 | return ret; |
83 | } | 87 | } |
84 | 88 | ||
85 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 89 | static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, |
86 | u32 extra, struct ieee80211_tx_info *control) | 90 | u32 extra, struct ieee80211_tx_info *control) |
87 | { | 91 | { |
88 | struct timespec ts; | 92 | struct timespec ts; |
@@ -110,9 +114,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
110 | /* configure the tx attributes */ | 114 | /* configure the tx attributes */ |
111 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 115 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
112 | 116 | ||
113 | /* queue */ | 117 | /* queue (we use same identifiers for tid's and ac's */ |
114 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 118 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
115 | desc->tid = wl1271_tx_ac_to_tid(ac); | 119 | desc->tid = ac; |
116 | 120 | ||
117 | desc->aid = TX_HW_DEFAULT_AID; | 121 | desc->aid = TX_HW_DEFAULT_AID; |
118 | desc->reserved = 0; | 122 | desc->reserved = 0; |
@@ -133,59 +137,17 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
133 | desc->tx_attr = cpu_to_le16(tx_attr); | 137 | desc->tx_attr = cpu_to_le16(tx_attr); |
134 | 138 | ||
135 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 139 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | ||
140 | struct ieee80211_tx_info *control) | ||
141 | { | ||
142 | |||
143 | struct wl1271_tx_hw_descr *desc; | ||
144 | int len; | ||
145 | |||
146 | /* FIXME: This is a workaround for getting non-aligned packets. | ||
147 | This happens at least with EAPOL packets from the user space. | ||
148 | Our DMA requires packets to be aligned on a 4-byte boundary. | ||
149 | */ | ||
150 | if (unlikely((long)skb->data & 0x03)) { | ||
151 | int offset = (4 - (long)skb->data) & 0x03; | ||
152 | wl1271_debug(DEBUG_TX, "skb offset %d", offset); | ||
153 | |||
154 | /* check whether the current skb can be used */ | ||
155 | if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { | ||
156 | unsigned char *src = skb->data; | ||
157 | |||
158 | /* align the buffer on a 4-byte boundary */ | ||
159 | skb_reserve(skb, offset); | ||
160 | memmove(skb->data, src, skb->len); | ||
161 | } else { | ||
162 | wl1271_info("No handler, fixme!"); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | len = WL1271_TX_ALIGN(skb->len); | ||
168 | |||
169 | /* perform a fixed address block write with the packet */ | ||
170 | wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); | ||
171 | |||
172 | /* write packet new counter into the write access register */ | ||
173 | wl->tx_packets_count++; | ||
174 | |||
175 | desc = (struct wl1271_tx_hw_descr *) skb->data; | ||
176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | ||
177 | desc->id, skb, len, desc->length); | ||
178 | |||
179 | return 0; | ||
180 | } | 140 | } |
181 | 141 | ||
182 | /* caller must hold wl->mutex */ | 142 | /* caller must hold wl->mutex */ |
183 | static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | 143 | static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, |
144 | u32 buf_offset) | ||
184 | { | 145 | { |
185 | struct ieee80211_tx_info *info; | 146 | struct ieee80211_tx_info *info; |
186 | u32 extra = 0; | 147 | u32 extra = 0; |
187 | int ret = 0; | 148 | int ret = 0; |
188 | u8 idx; | 149 | u8 idx; |
150 | u32 total_len; | ||
189 | 151 | ||
190 | if (!skb) | 152 | if (!skb) |
191 | return -EINVAL; | 153 | return -EINVAL; |
@@ -193,7 +155,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
193 | info = IEEE80211_SKB_CB(skb); | 155 | info = IEEE80211_SKB_CB(skb); |
194 | 156 | ||
195 | if (info->control.hw_key && | 157 | if (info->control.hw_key && |
196 | info->control.hw_key->alg == ALG_TKIP) | 158 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) |
197 | extra = WL1271_TKIP_IV_SPACE; | 159 | extra = WL1271_TKIP_IV_SPACE; |
198 | 160 | ||
199 | if (info->control.hw_key) { | 161 | if (info->control.hw_key) { |
@@ -208,19 +170,22 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
208 | } | 170 | } |
209 | } | 171 | } |
210 | 172 | ||
211 | ret = wl1271_tx_allocate(wl, skb, extra); | 173 | ret = wl1271_tx_allocate(wl, skb, extra, buf_offset); |
212 | if (ret < 0) | 174 | if (ret < 0) |
213 | return ret; | 175 | return ret; |
214 | 176 | ||
215 | ret = wl1271_tx_fill_hdr(wl, skb, extra, info); | 177 | wl1271_tx_fill_hdr(wl, skb, extra, info); |
216 | if (ret < 0) | ||
217 | return ret; | ||
218 | 178 | ||
219 | ret = wl1271_tx_send_packet(wl, skb, info); | 179 | /* |
220 | if (ret < 0) | 180 | * The length of each packet is stored in terms of words. Thus, we must |
221 | return ret; | 181 | * pad the skb data to make sure its length is aligned. |
182 | * The number of padding bytes is computed and set in wl1271_tx_fill_hdr | ||
183 | */ | ||
184 | total_len = WL1271_TX_ALIGN(skb->len); | ||
185 | memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); | ||
186 | memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); | ||
222 | 187 | ||
223 | return ret; | 188 | return total_len; |
224 | } | 189 | } |
225 | 190 | ||
226 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
@@ -245,7 +210,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
245 | struct sk_buff *skb; | 210 | struct sk_buff *skb; |
246 | bool woken_up = false; | 211 | bool woken_up = false; |
247 | u32 sta_rates = 0; | 212 | u32 sta_rates = 0; |
248 | u32 prev_tx_packets_count; | 213 | u32 buf_offset; |
249 | int ret; | 214 | int ret; |
250 | 215 | ||
251 | /* check if the rates supported by the AP have changed */ | 216 | /* check if the rates supported by the AP have changed */ |
@@ -262,14 +227,15 @@ void wl1271_tx_work(struct work_struct *work) | |||
262 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 227 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
263 | goto out; | 228 | goto out; |
264 | 229 | ||
265 | prev_tx_packets_count = wl->tx_packets_count; | ||
266 | |||
267 | /* if rates have changed, re-configure the rate policy */ | 230 | /* if rates have changed, re-configure the rate policy */ |
268 | if (unlikely(sta_rates)) { | 231 | if (unlikely(sta_rates)) { |
269 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | 232 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); |
270 | wl1271_acx_rate_policies(wl); | 233 | wl1271_acx_rate_policies(wl); |
271 | } | 234 | } |
272 | 235 | ||
236 | /* Prepare the transfer buffer, by aggregating all | ||
237 | * available packets */ | ||
238 | buf_offset = 0; | ||
273 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 239 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
274 | if (!woken_up) { | 240 | if (!woken_up) { |
275 | ret = wl1271_ps_elp_wakeup(wl, false); | 241 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -278,21 +244,30 @@ void wl1271_tx_work(struct work_struct *work) | |||
278 | woken_up = true; | 244 | woken_up = true; |
279 | } | 245 | } |
280 | 246 | ||
281 | ret = wl1271_tx_frame(wl, skb); | 247 | ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); |
282 | if (ret == -EBUSY) { | 248 | if (ret == -EBUSY) { |
283 | /* firmware buffer is full, lets stop transmitting. */ | 249 | /* |
250 | * Either the firmware buffer is full, or the | ||
251 | * aggregation buffer is. | ||
252 | * Queue back last skb, and stop aggregating. | ||
253 | */ | ||
284 | skb_queue_head(&wl->tx_queue, skb); | 254 | skb_queue_head(&wl->tx_queue, skb); |
285 | goto out_ack; | 255 | goto out_ack; |
286 | } else if (ret < 0) { | 256 | } else if (ret < 0) { |
287 | dev_kfree_skb(skb); | 257 | dev_kfree_skb(skb); |
288 | goto out_ack; | 258 | goto out_ack; |
289 | } | 259 | } |
260 | buf_offset += ret; | ||
261 | wl->tx_packets_count++; | ||
290 | } | 262 | } |
291 | 263 | ||
292 | out_ack: | 264 | out_ack: |
293 | /* interrupt the firmware with the new packets */ | 265 | if (buf_offset) { |
294 | if (prev_tx_packets_count != wl->tx_packets_count) | 266 | wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, |
267 | buf_offset, true); | ||
268 | /* interrupt the firmware with the new packets */ | ||
295 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | 269 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); |
270 | } | ||
296 | 271 | ||
297 | out: | 272 | out: |
298 | if (woken_up) | 273 | if (woken_up) |
@@ -347,7 +322,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
347 | 322 | ||
348 | /* remove TKIP header space if present */ | 323 | /* remove TKIP header space if present */ |
349 | if (info->control.hw_key && | 324 | if (info->control.hw_key && |
350 | info->control.hw_key->alg == ALG_TKIP) { | 325 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
351 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 326 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
352 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); | 327 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); |
353 | skb_pull(skb, WL1271_TKIP_IV_SPACE); | 328 | skb_pull(skb, WL1271_TKIP_IV_SPACE); |
@@ -422,8 +397,6 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
422 | struct sk_buff *skb; | 397 | struct sk_buff *skb; |
423 | 398 | ||
424 | /* TX failure */ | 399 | /* TX failure */ |
425 | /* control->flags = 0; FIXME */ | ||
426 | |||
427 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 400 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
428 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); | 401 | wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); |
429 | ieee80211_tx_status(wl->hw, skb); | 402 | ieee80211_tx_status(wl->hw, skb); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 48bf92621c03..d12a129ad11c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -139,23 +139,6 @@ static inline int wl1271_tx_get_queue(int queue) | |||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | /* wl1271 tx descriptor needs the tid and we need to convert it from ac */ | ||
143 | static inline int wl1271_tx_ac_to_tid(int ac) | ||
144 | { | ||
145 | switch (ac) { | ||
146 | case 0: | ||
147 | return 0; | ||
148 | case 1: | ||
149 | return 2; | ||
150 | case 2: | ||
151 | return 4; | ||
152 | case 3: | ||
153 | return 6; | ||
154 | default: | ||
155 | return 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | void wl1271_tx_work(struct work_struct *work); | 142 | void wl1271_tx_work(struct work_struct *work); |
160 | void wl1271_tx_complete(struct wl1271 *wl); | 143 | void wl1271_tx_complete(struct wl1271 *wl); |
161 | void wl1271_tx_reset(struct wl1271 *wl); | 144 | void wl1271_tx_reset(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c new file mode 100644 index 000000000000..973b11060a8f --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c | |||
@@ -0,0 +1,28 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/err.h> | ||
3 | #include <linux/wl12xx.h> | ||
4 | |||
5 | static const struct wl12xx_platform_data *platform_data; | ||
6 | |||
7 | int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) | ||
8 | { | ||
9 | if (platform_data) | ||
10 | return -EBUSY; | ||
11 | if (!data) | ||
12 | return -EINVAL; | ||
13 | |||
14 | platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); | ||
15 | if (!platform_data) | ||
16 | return -ENOMEM; | ||
17 | |||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | const struct wl12xx_platform_data *wl12xx_get_platform_data(void) | ||
22 | { | ||
23 | if (!platform_data) | ||
24 | return ERR_PTR(-ENODEV); | ||
25 | |||
26 | return platform_data; | ||
27 | } | ||
28 | EXPORT_SYMBOL(wl12xx_get_platform_data); | ||