blob: 00ddcc2d37c171925515506967befd61ddffbb0b [file] [log] [blame]
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/interrupt.h>
27#include <linux/firmware.h>
28#include <linux/delay.h>
29#include <linux/irq.h>
30#include <linux/spi/spi.h>
31#include <linux/crc32.h>
32#include <linux/etherdevice.h>
Juuso Oikarinen1fba4972009-10-08 21:56:32 +030033#include <linux/vmalloc.h>
Luciano Coelhof5fc0f82009-08-06 16:25:28 +030034#include <linux/spi/wl12xx.h>
Juuso Oikarinen01c09162009-10-13 12:47:55 +030035#include <linux/inetdevice.h>
Luciano Coelhof5fc0f82009-08-06 16:25:28 +030036
37#include "wl1271.h"
38#include "wl12xx_80211.h"
39#include "wl1271_reg.h"
40#include "wl1271_spi.h"
41#include "wl1271_event.h"
42#include "wl1271_tx.h"
43#include "wl1271_rx.h"
44#include "wl1271_ps.h"
45#include "wl1271_init.h"
46#include "wl1271_debugfs.h"
47#include "wl1271_cmd.h"
48#include "wl1271_boot.h"
49
Juuso Oikarinen8a080482009-10-13 12:47:44 +030050static struct conf_drv_settings default_conf = {
51 .sg = {
52 .per_threshold = 7500,
53 .max_scan_compensation_time = 120000,
54 .nfs_sample_interval = 400,
55 .load_ratio = 50,
56 .auto_ps_mode = 0,
57 .probe_req_compensation = 170,
58 .scan_window_compensation = 50,
59 .antenna_config = 0,
60 .beacon_miss_threshold = 60,
61 .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS,
62 .rate_adaptation_snr = 0
63 },
64 .rx = {
65 .rx_msdu_life_time = 512000,
66 .packet_detection_threshold = 0,
67 .ps_poll_timeout = 15,
68 .upsd_timeout = 15,
69 .rts_threshold = 2347,
70 .rx_cca_threshold = 0xFFEF,
71 .irq_blk_threshold = 0,
72 .irq_pkt_threshold = USHORT_MAX,
73 .irq_timeout = 5,
74 .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
75 },
76 .tx = {
77 .tx_energy_detection = 0,
78 .rc_conf = {
79 .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED,
80 .short_retry_limit = 10,
81 .long_retry_limit = 10,
82 .aflags = 0
83 },
84 .ac_conf_count = 4,
85 .ac_conf = {
86 [0] = {
87 .ac = CONF_TX_AC_BE,
88 .cw_min = 15,
89 .cw_max = 63,
90 .aifsn = 3,
91 .tx_op_limit = 0,
92 },
93 [1] = {
94 .ac = CONF_TX_AC_BK,
95 .cw_min = 15,
96 .cw_max = 63,
97 .aifsn = 7,
98 .tx_op_limit = 0,
99 },
100 [2] = {
101 .ac = CONF_TX_AC_VI,
102 .cw_min = 15,
103 .cw_max = 63,
104 .aifsn = CONF_TX_AIFS_PIFS,
105 .tx_op_limit = 3008,
106 },
107 [3] = {
108 .ac = CONF_TX_AC_VO,
109 .cw_min = 15,
110 .cw_max = 63,
111 .aifsn = CONF_TX_AIFS_PIFS,
112 .tx_op_limit = 1504,
113 },
114 },
115 .tid_conf_count = 7,
116 .tid_conf = {
117 [0] = {
118 .queue_id = 0,
119 .channel_type = CONF_CHANNEL_TYPE_DCF,
120 .tsid = CONF_TX_AC_BE,
121 .ps_scheme = CONF_PS_SCHEME_LEGACY,
122 .ack_policy = CONF_ACK_POLICY_LEGACY,
123 .apsd_conf = {0, 0},
124 },
125 [1] = {
126 .queue_id = 1,
127 .channel_type = CONF_CHANNEL_TYPE_DCF,
128 .tsid = CONF_TX_AC_BE,
129 .ps_scheme = CONF_PS_SCHEME_LEGACY,
130 .ack_policy = CONF_ACK_POLICY_LEGACY,
131 .apsd_conf = {0, 0},
132 },
133 [2] = {
134 .queue_id = 2,
135 .channel_type = CONF_CHANNEL_TYPE_DCF,
136 .tsid = CONF_TX_AC_BE,
137 .ps_scheme = CONF_PS_SCHEME_LEGACY,
138 .ack_policy = CONF_ACK_POLICY_LEGACY,
139 .apsd_conf = {0, 0},
140 },
141 [3] = {
142 .queue_id = 3,
143 .channel_type = CONF_CHANNEL_TYPE_DCF,
144 .tsid = CONF_TX_AC_BE,
145 .ps_scheme = CONF_PS_SCHEME_LEGACY,
146 .ack_policy = CONF_ACK_POLICY_LEGACY,
147 .apsd_conf = {0, 0},
148 },
149 [4] = {
150 .queue_id = 4,
151 .channel_type = CONF_CHANNEL_TYPE_DCF,
152 .tsid = CONF_TX_AC_BE,
153 .ps_scheme = CONF_PS_SCHEME_LEGACY,
154 .ack_policy = CONF_ACK_POLICY_LEGACY,
155 .apsd_conf = {0, 0},
156 },
157 [5] = {
158 .queue_id = 5,
159 .channel_type = CONF_CHANNEL_TYPE_DCF,
160 .tsid = CONF_TX_AC_BE,
161 .ps_scheme = CONF_PS_SCHEME_LEGACY,
162 .ack_policy = CONF_ACK_POLICY_LEGACY,
163 .apsd_conf = {0, 0},
164 },
165 [6] = {
166 .queue_id = 6,
167 .channel_type = CONF_CHANNEL_TYPE_DCF,
168 .tsid = CONF_TX_AC_BE,
169 .ps_scheme = CONF_PS_SCHEME_LEGACY,
170 .ack_policy = CONF_ACK_POLICY_LEGACY,
171 .apsd_conf = {0, 0},
172 }
173 },
174 .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
175 .tx_compl_timeout = 5,
176 .tx_compl_threshold = 5
177 },
178 .conn = {
179 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
180 .listen_interval = 0,
181 .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
182 .bcn_filt_ie_count = 1,
183 .bcn_filt_ie = {
184 [0] = {
185 .ie = WLAN_EID_CHANNEL_SWITCH,
186 .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
187 }
188 },
189 .synch_fail_thold = 5,
190 .bss_lose_timeout = 100,
191 .beacon_rx_timeout = 10000,
192 .broadcast_timeout = 20000,
193 .rx_broadcast_in_ps = 1,
194 .ps_poll_threshold = 4,
195 .sig_trigger_count = 2,
196 .sig_trigger = {
197 [0] = {
198 .threshold = -75,
199 .pacing = 500,
200 .metric = CONF_TRIG_METRIC_RSSI_BEACON,
201 .type = CONF_TRIG_EVENT_TYPE_EDGE,
202 .direction = CONF_TRIG_EVENT_DIR_LOW,
203 .hysteresis = 2,
204 .index = 0,
205 .enable = 1
206 },
207 [1] = {
208 .threshold = -75,
209 .pacing = 500,
210 .metric = CONF_TRIG_METRIC_RSSI_BEACON,
211 .type = CONF_TRIG_EVENT_TYPE_EDGE,
212 .direction = CONF_TRIG_EVENT_DIR_HIGH,
213 .hysteresis = 2,
214 .index = 1,
215 .enable = 1
216 }
217 },
218 .sig_weights = {
219 .rssi_bcn_avg_weight = 10,
220 .rssi_pkt_avg_weight = 10,
221 .snr_bcn_avg_weight = 10,
222 .snr_pkt_avg_weight = 10
Juuso Oikarinen11f70f92009-10-13 12:47:46 +0300223 },
224 .bet_enable = CONF_BET_MODE_ENABLE,
Juuso Oikarinen19ad0712009-11-02 20:22:11 +0200225 .bet_max_consecutive = 100,
226 .psm_entry_retries = 3
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300227 },
228 .init = {
229 .sr_err_tbl = {
230 [0] = {
231 .len = 7,
232 .upper_limit = 0x03,
233 .values = {
234 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
235 0x00 }
236 },
237 [1] = {
238 .len = 7,
239 .upper_limit = 0x03,
240 .values = {
241 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8,
242 0x00 }
243 },
244 [2] = {
245 .len = 7,
246 .upper_limit = 0x03,
247 .values = {
248 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
249 0x00 }
250 }
251 },
252 .sr_enable = 1,
253 .genparam = {
254 /*
255 * FIXME: The correct value CONF_REF_CLK_38_4_E
256 * causes the firmware to crash on boot.
257 * The value 5 apparently is an
258 * unnoficial XTAL configuration of the
259 * same frequency, which appears to work.
260 */
261 .ref_clk = 5,
262 .settling_time = 5,
263 .clk_valid_on_wakeup = 0,
264 .dc2dcmode = 0,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300265 .single_dual_band = CONF_SINGLE_BAND,
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300266 .tx_bip_fem_autodetect = 0,
267 .tx_bip_fem_manufacturer = 1,
268 .settings = 1,
269 },
270 .radioparam = {
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300271 .rx_trace_loss = 10,
272 .tx_trace_loss = 10,
273 .rx_rssi_and_proc_compens = {
274 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
275 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
276 0x00, 0x0a, 0x14 },
277 .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
278 .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
279 .rx_rssi_and_proc_compens_5 = {
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00 },
283 .tx_ref_pd_voltage = 0x24e,
284 .tx_ref_power = 0x78,
285 .tx_offset_db = 0x0,
286 .tx_rate_limits_normal = {
287 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
288 .tx_rate_limits_degraded = {
289 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
290 .tx_channel_limits_11b = {
291 0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
292 0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
293 0x22, 0x50 },
294 .tx_channel_limits_ofdm = {
295 0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
296 0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
297 0x20, 0x50 },
298 .tx_pdv_rate_offsets = {
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
300 .tx_ibias = {
301 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
302 .rx_fem_insertion_loss = 0x14,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300303 .tx_ref_pd_voltage_5 = {
304 0x0190, 0x01a4, 0x01c3, 0x01d8,
305 0x020a, 0x021c },
306 .tx_ref_power_5 = {
307 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
308 .tx_offset_db_5 = {
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300310 .tx_rate_limits_normal_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300311 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300312 .tx_rate_limits_degraded_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300313 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300314 .tx_channel_limits_ofdm_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300315 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
316 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
317 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
318 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
319 0x50, 0x50, 0x50 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300320 .tx_pdv_rate_offsets_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300321 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300322 .tx_ibias_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300323 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
324 .rx_fem_insertion_loss_5 = {
325 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300326 }
327 }
328};
329
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300330static LIST_HEAD(wl_list);
331
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300332static void wl1271_conf_init(struct wl1271 *wl)
333{
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300334
335 /*
336 * This function applies the default configuration to the driver. This
337 * function is invoked upon driver load (spi probe.)
338 *
339 * The configuration is stored in a run-time structure in order to
340 * facilitate for run-time adjustment of any of the parameters. Making
341 * changes to the configuration structure will apply the new values on
342 * the next interface up (wl1271_op_start.)
343 */
344
345 /* apply driver default configuration */
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300346 memcpy(&wl->conf, &default_conf, sizeof(default_conf));
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300347
348 if (wl1271_11a_enabled())
349 wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300350}
351
352
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300353static int wl1271_plt_init(struct wl1271 *wl)
354{
355 int ret;
356
357 ret = wl1271_acx_init_mem_config(wl);
358 if (ret < 0)
359 return ret;
360
361 ret = wl1271_cmd_data_path(wl, wl->channel, 1);
362 if (ret < 0)
363 return ret;
364
365 return 0;
366}
367
368static void wl1271_disable_interrupts(struct wl1271 *wl)
369{
370 disable_irq(wl->irq);
371}
372
373static void wl1271_power_off(struct wl1271 *wl)
374{
375 wl->set_power(false);
376}
377
378static void wl1271_power_on(struct wl1271 *wl)
379{
380 wl->set_power(true);
381}
382
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300383static void wl1271_fw_status(struct wl1271 *wl,
384 struct wl1271_fw_status *status)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300385{
386 u32 total = 0;
387 int i;
388
Juuso Oikarinen74621412009-10-12 15:08:54 +0300389 wl1271_spi_read(wl, FW_STATUS_ADDR, status,
390 sizeof(*status), false);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300391
392 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
393 "drv_rx_counter = %d, tx_results_counter = %d)",
394 status->intr,
395 status->fw_rx_counter,
396 status->drv_rx_counter,
397 status->tx_results_counter);
398
399 /* update number of available TX blocks */
400 for (i = 0; i < NUM_TX_QUEUES; i++) {
Luciano Coelhod0f63b22009-10-15 10:33:29 +0300401 u32 cnt = le32_to_cpu(status->tx_released_blks[i]) -
402 wl->tx_blocks_freed[i];
403
404 wl->tx_blocks_freed[i] =
405 le32_to_cpu(status->tx_released_blks[i]);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300406 wl->tx_blocks_available += cnt;
407 total += cnt;
408 }
409
410 /* if more blocks are available now, schedule some tx work */
411 if (total && !skb_queue_empty(&wl->tx_queue))
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300412 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300413
414 /* update the host-chipset time offset */
Luciano Coelhod0f63b22009-10-15 10:33:29 +0300415 wl->time_offset = jiffies_to_usecs(jiffies) -
416 le32_to_cpu(status->fw_localtime);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300417}
418
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300419static void wl1271_irq_work(struct work_struct *work)
420{
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300421 int ret;
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300422 u32 intr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300423 struct wl1271 *wl =
424 container_of(work, struct wl1271, irq_work);
425
426 mutex_lock(&wl->mutex);
427
428 wl1271_debug(DEBUG_IRQ, "IRQ work");
429
430 if (wl->state == WL1271_STATE_OFF)
431 goto out;
432
433 ret = wl1271_ps_elp_wakeup(wl, true);
434 if (ret < 0)
435 goto out;
436
Juuso Oikarinen74621412009-10-12 15:08:54 +0300437 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300438
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300439 wl1271_fw_status(wl, wl->fw_status);
Luciano Coelhod0f63b22009-10-15 10:33:29 +0300440 intr = le32_to_cpu(wl->fw_status->intr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300441 if (!intr) {
442 wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
443 goto out_sleep;
444 }
445
446 intr &= WL1271_INTR_MASK;
447
Juuso Oikarinen1fd27942009-10-13 12:47:54 +0300448 if (intr & WL1271_ACX_INTR_EVENT_A) {
449 bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true;
450 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
451 wl1271_event_handle(wl, 0, do_ack);
452 }
453
454 if (intr & WL1271_ACX_INTR_EVENT_B) {
455 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
456 wl1271_event_handle(wl, 1, true);
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300457 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300458
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300459 if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
460 wl1271_debug(DEBUG_IRQ,
461 "WL1271_ACX_INTR_INIT_COMPLETE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300462
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300463 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
464 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300465
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300466 if (intr & WL1271_ACX_INTR_DATA) {
467 u8 tx_res_cnt = wl->fw_status->tx_results_counter -
468 wl->tx_results_count;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300469
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300470 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300471
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300472 /* check for tx results */
473 if (tx_res_cnt)
474 wl1271_tx_complete(wl, tx_res_cnt);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300475
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300476 wl1271_rx(wl, wl->fw_status);
477 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300478
479out_sleep:
Juuso Oikarinen74621412009-10-12 15:08:54 +0300480 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
Luciano Coelho73d0a132009-08-11 11:58:27 +0300481 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300482 wl1271_ps_elp_sleep(wl);
483
484out:
485 mutex_unlock(&wl->mutex);
486}
487
488static irqreturn_t wl1271_irq(int irq, void *cookie)
489{
490 struct wl1271 *wl;
491 unsigned long flags;
492
493 wl1271_debug(DEBUG_IRQ, "IRQ");
494
495 wl = cookie;
496
497 /* complete the ELP completion */
498 spin_lock_irqsave(&wl->wl_lock, flags);
499 if (wl->elp_compl) {
500 complete(wl->elp_compl);
501 wl->elp_compl = NULL;
502 }
503
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300504 ieee80211_queue_work(wl->hw, &wl->irq_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300505 spin_unlock_irqrestore(&wl->wl_lock, flags);
506
507 return IRQ_HANDLED;
508}
509
510static int wl1271_fetch_firmware(struct wl1271 *wl)
511{
512 const struct firmware *fw;
513 int ret;
514
515 ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
516
517 if (ret < 0) {
518 wl1271_error("could not get firmware: %d", ret);
519 return ret;
520 }
521
522 if (fw->size % 4) {
523 wl1271_error("firmware size is not multiple of 32 bits: %zu",
524 fw->size);
525 ret = -EILSEQ;
526 goto out;
527 }
528
529 wl->fw_len = fw->size;
Juuso Oikarinen1fba4972009-10-08 21:56:32 +0300530 wl->fw = vmalloc(wl->fw_len);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300531
532 if (!wl->fw) {
533 wl1271_error("could not allocate memory for the firmware");
534 ret = -ENOMEM;
535 goto out;
536 }
537
538 memcpy(wl->fw, fw->data, wl->fw_len);
539
540 ret = 0;
541
542out:
543 release_firmware(fw);
544
545 return ret;
546}
547
548static int wl1271_fetch_nvs(struct wl1271 *wl)
549{
550 const struct firmware *fw;
551 int ret;
552
553 ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
554
555 if (ret < 0) {
556 wl1271_error("could not get nvs file: %d", ret);
557 return ret;
558 }
559
560 if (fw->size % 4) {
561 wl1271_error("nvs size is not multiple of 32 bits: %zu",
562 fw->size);
563 ret = -EILSEQ;
564 goto out;
565 }
566
567 wl->nvs_len = fw->size;
568 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
569
570 if (!wl->nvs) {
571 wl1271_error("could not allocate memory for the nvs file");
572 ret = -ENOMEM;
573 goto out;
574 }
575
576 memcpy(wl->nvs, fw->data, wl->nvs_len);
577
578 ret = 0;
579
580out:
581 release_firmware(fw);
582
583 return ret;
584}
585
586static void wl1271_fw_wakeup(struct wl1271 *wl)
587{
588 u32 elp_reg;
589
590 elp_reg = ELPCTRL_WAKE_UP;
Juuso Oikarinen74621412009-10-12 15:08:54 +0300591 wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300592}
593
594static int wl1271_setup(struct wl1271 *wl)
595{
596 wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
597 if (!wl->fw_status)
598 return -ENOMEM;
599
600 wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
601 if (!wl->tx_res_if) {
602 kfree(wl->fw_status);
603 return -ENOMEM;
604 }
605
606 INIT_WORK(&wl->irq_work, wl1271_irq_work);
607 INIT_WORK(&wl->tx_work, wl1271_tx_work);
608 return 0;
609}
610
611static int wl1271_chip_wakeup(struct wl1271 *wl)
612{
Juuso Oikarinen451de972009-10-12 15:08:46 +0300613 struct wl1271_partition_set partition;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300614 int ret = 0;
615
616 wl1271_power_on(wl);
617 msleep(WL1271_POWER_ON_SLEEP);
618 wl1271_spi_reset(wl);
619 wl1271_spi_init(wl);
620
621 /* We don't need a real memory partition here, because we only want
622 * to use the registers at this point. */
Juuso Oikarinen451de972009-10-12 15:08:46 +0300623 memset(&partition, 0, sizeof(partition));
624 partition.reg.start = REGISTERS_BASE;
625 partition.reg.size = REGISTERS_DOWN_SIZE;
626 wl1271_set_partition(wl, &partition);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300627
628 /* ELP module wake up */
629 wl1271_fw_wakeup(wl);
630
631 /* whal_FwCtrl_BootSm() */
632
633 /* 0. read chip id from CHIP_ID */
Juuso Oikarinen74621412009-10-12 15:08:54 +0300634 wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300635
636 /* 1. check if chip id is valid */
637
638 switch (wl->chip.id) {
639 case CHIP_ID_1271_PG10:
640 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
641 wl->chip.id);
642
643 ret = wl1271_setup(wl);
644 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300645 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300646 break;
647 case CHIP_ID_1271_PG20:
648 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
649 wl->chip.id);
650
651 ret = wl1271_setup(wl);
652 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300653 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300654 break;
655 default:
656 wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
657 ret = -ENODEV;
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300658 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300659 }
660
661 if (wl->fw == NULL) {
662 ret = wl1271_fetch_firmware(wl);
663 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300664 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300665 }
666
667 /* No NVS from netlink, try to get it from the filesystem */
668 if (wl->nvs == NULL) {
669 ret = wl1271_fetch_nvs(wl);
670 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300671 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300672 }
673
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300674 goto out;
675
676out_power_off:
677 wl1271_power_off(wl);
678
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300679out:
680 return ret;
681}
682
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300683int wl1271_plt_start(struct wl1271 *wl)
684{
685 int ret;
686
687 mutex_lock(&wl->mutex);
688
689 wl1271_notice("power up");
690
691 if (wl->state != WL1271_STATE_OFF) {
692 wl1271_error("cannot go into PLT state because not "
693 "in off state: %d", wl->state);
694 ret = -EBUSY;
695 goto out;
696 }
697
698 wl->state = WL1271_STATE_PLT;
699
700 ret = wl1271_chip_wakeup(wl);
701 if (ret < 0)
702 goto out;
703
704 ret = wl1271_boot(wl);
705 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300706 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300707
708 wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
709
710 ret = wl1271_plt_init(wl);
711 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300712 goto out_irq_disable;
713
Luciano Coelhobd5ea182009-10-13 12:47:58 +0300714 /* Make sure power saving is disabled */
715 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
716 if (ret < 0)
717 goto out_irq_disable;
718
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300719 goto out;
720
721out_irq_disable:
722 wl1271_disable_interrupts(wl);
723
724out_power_off:
725 wl1271_power_off(wl);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300726
727out:
728 mutex_unlock(&wl->mutex);
729
730 return ret;
731}
732
733int wl1271_plt_stop(struct wl1271 *wl)
734{
735 int ret = 0;
736
737 mutex_lock(&wl->mutex);
738
739 wl1271_notice("power down");
740
741 if (wl->state != WL1271_STATE_PLT) {
742 wl1271_error("cannot power down because not in PLT "
743 "state: %d", wl->state);
744 ret = -EBUSY;
745 goto out;
746 }
747
748 wl1271_disable_interrupts(wl);
749 wl1271_power_off(wl);
750
751 wl->state = WL1271_STATE_OFF;
Luciano Coelhobd5ea182009-10-13 12:47:58 +0300752 wl->rx_counter = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300753
754out:
755 mutex_unlock(&wl->mutex);
756
757 return ret;
758}
759
760
761static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
762{
763 struct wl1271 *wl = hw->priv;
764
765 skb_queue_tail(&wl->tx_queue, skb);
766
767 /*
768 * The chip specific setup must run before the first TX packet -
769 * before that, the tx_work will not be initialized!
770 */
771
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300772 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300773
774 /*
775 * The workqueue is slow to process the tx_queue and we need stop
776 * the queue here, otherwise the queue will get too long.
777 */
778 if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
779 ieee80211_stop_queues(wl->hw);
780
781 /*
782 * FIXME: this is racy, the variable is not properly
783 * protected. Maybe fix this by removing the stupid
784 * variable altogether and checking the real queue state?
785 */
786 wl->tx_queue_stopped = true;
787 }
788
789 return NETDEV_TX_OK;
790}
791
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300792static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
793 void *arg)
794{
795 struct net_device *dev;
796 struct wireless_dev *wdev;
797 struct wiphy *wiphy;
798 struct ieee80211_hw *hw;
799 struct wl1271 *wl;
800 struct wl1271 *wl_temp;
801 struct in_device *idev;
802 struct in_ifaddr *ifa = arg;
803 int ret = 0;
804
805 /* FIXME: this ugly function should probably be implemented in the
806 * mac80211, and here should only be a simple callback handling actual
807 * setting of the filters. Now we need to dig up references to
808 * various structures to gain access to what we need.
809 * Also, because of this, there is no "initial" setting of the filter
810 * in "op_start", because we don't want to dig up struct net_device
811 * there - the filter will be set upon first change of the interface
812 * IP address. */
813
814 dev = ifa->ifa_dev->dev;
815
816 wdev = dev->ieee80211_ptr;
817 if (wdev == NULL)
818 return -ENODEV;
819
820 wiphy = wdev->wiphy;
821 if (wiphy == NULL)
822 return -ENODEV;
823
824 hw = wiphy_priv(wiphy);
825 if (hw == NULL)
826 return -ENODEV;
827
828 /* Check that the interface is one supported by this driver. */
829 wl_temp = hw->priv;
830 list_for_each_entry(wl, &wl_list, list) {
831 if (wl == wl_temp)
832 break;
833 }
834 if (wl == NULL)
835 return -ENODEV;
836
837 /* Get the interface IP address for the device. "ifa" will become
838 NULL if:
839 - there is no IPV4 protocol address configured
840 - there are multiple (virtual) IPV4 addresses configured
841 When "ifa" is NULL, filtering will be disabled.
842 */
843 ifa = NULL;
844 idev = dev->ip_ptr;
845 if (idev)
846 ifa = idev->ifa_list;
847
848 if (ifa && ifa->ifa_next)
849 ifa = NULL;
850
851 mutex_lock(&wl->mutex);
852
853 if (wl->state == WL1271_STATE_OFF)
854 goto out;
855
856 ret = wl1271_ps_elp_wakeup(wl, false);
857 if (ret < 0)
858 goto out;
859 if (ifa)
860 ret = wl1271_acx_arp_ip_filter(wl, true,
861 (u8 *)&ifa->ifa_address,
862 ACX_IPV4_VERSION);
863 else
864 ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
865 ACX_IPV4_VERSION);
866 wl1271_ps_elp_sleep(wl);
867
868out:
869 mutex_unlock(&wl->mutex);
870
871 return ret;
872}
873
874static struct notifier_block wl1271_dev_notifier = {
875 .notifier_call = wl1271_dev_notify,
876};
877
878
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300879static int wl1271_op_start(struct ieee80211_hw *hw)
880{
881 struct wl1271 *wl = hw->priv;
882 int ret = 0;
883
884 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
885
886 mutex_lock(&wl->mutex);
887
888 if (wl->state != WL1271_STATE_OFF) {
889 wl1271_error("cannot start because not in off state: %d",
890 wl->state);
891 ret = -EBUSY;
892 goto out;
893 }
894
895 ret = wl1271_chip_wakeup(wl);
896 if (ret < 0)
897 goto out;
898
899 ret = wl1271_boot(wl);
900 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300901 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300902
903 ret = wl1271_hw_init(wl);
904 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300905 goto out_irq_disable;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300906
907 wl->state = WL1271_STATE_ON;
908
909 wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
910
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300911 goto out;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300912
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300913out_irq_disable:
914 wl1271_disable_interrupts(wl);
915
916out_power_off:
917 wl1271_power_off(wl);
918
919out:
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300920 mutex_unlock(&wl->mutex);
921
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300922 if (!ret) {
923 list_add(&wl->list, &wl_list);
924 register_inetaddr_notifier(&wl1271_dev_notifier);
925 }
926
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300927 return ret;
928}
929
930static void wl1271_op_stop(struct ieee80211_hw *hw)
931{
932 struct wl1271 *wl = hw->priv;
933 int i;
934
935 wl1271_info("down");
936
937 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
938
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300939 unregister_inetaddr_notifier(&wl1271_dev_notifier);
940 list_del(&wl->list);
941
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300942 mutex_lock(&wl->mutex);
943
944 WARN_ON(wl->state != WL1271_STATE_ON);
945
946 if (wl->scanning) {
947 mutex_unlock(&wl->mutex);
948 ieee80211_scan_completed(wl->hw, true);
949 mutex_lock(&wl->mutex);
950 wl->scanning = false;
951 }
952
953 wl->state = WL1271_STATE_OFF;
954
955 wl1271_disable_interrupts(wl);
956
957 mutex_unlock(&wl->mutex);
958
959 cancel_work_sync(&wl->irq_work);
960 cancel_work_sync(&wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300961
962 mutex_lock(&wl->mutex);
963
964 /* let's notify MAC80211 about the remaining pending TX frames */
965 wl1271_tx_flush(wl);
966 wl1271_power_off(wl);
967
968 memset(wl->bssid, 0, ETH_ALEN);
969 memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
970 wl->ssid_len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300971 wl->bss_type = MAX_BSS_TYPE;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +0300972 wl->band = IEEE80211_BAND_2GHZ;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300973
974 wl->rx_counter = 0;
975 wl->elp = false;
976 wl->psm = 0;
Juuso Oikarinen19ad0712009-11-02 20:22:11 +0200977 wl->psm_entry_retry = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300978 wl->tx_queue_stopped = false;
979 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
980 wl->tx_blocks_available = 0;
981 wl->tx_results_count = 0;
982 wl->tx_packets_count = 0;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +0300983 wl->tx_security_last_seq = 0;
984 wl->tx_security_seq_16 = 0;
985 wl->tx_security_seq_32 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300986 wl->time_offset = 0;
987 wl->session_counter = 0;
Luciano Coelhod6e19d12009-10-12 15:08:43 +0300988 wl->joined = false;
989
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300990 for (i = 0; i < NUM_TX_QUEUES; i++)
991 wl->tx_blocks_freed[i] = 0;
992
993 wl1271_debugfs_reset(wl);
994 mutex_unlock(&wl->mutex);
995}
996
997static int wl1271_op_add_interface(struct ieee80211_hw *hw,
998 struct ieee80211_if_init_conf *conf)
999{
1000 struct wl1271 *wl = hw->priv;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001001 int ret = 0;
1002
John W. Linvillee5539bc2009-08-18 10:50:34 -04001003 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
1004 conf->type, conf->mac_addr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001005
1006 mutex_lock(&wl->mutex);
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001007 if (wl->vif) {
1008 ret = -EBUSY;
1009 goto out;
1010 }
1011
1012 wl->vif = conf->vif;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001013
1014 switch (conf->type) {
1015 case NL80211_IFTYPE_STATION:
1016 wl->bss_type = BSS_TYPE_STA_BSS;
1017 break;
1018 case NL80211_IFTYPE_ADHOC:
1019 wl->bss_type = BSS_TYPE_IBSS;
1020 break;
1021 default:
1022 ret = -EOPNOTSUPP;
1023 goto out;
1024 }
1025
1026 /* FIXME: what if conf->mac_addr changes? */
1027
1028out:
1029 mutex_unlock(&wl->mutex);
1030 return ret;
1031}
1032
1033static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1034 struct ieee80211_if_init_conf *conf)
1035{
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001036 struct wl1271 *wl = hw->priv;
1037
1038 mutex_lock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001039 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001040 wl->vif = NULL;
1041 mutex_unlock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001042}
1043
1044#if 0
1045static int wl1271_op_config_interface(struct ieee80211_hw *hw,
1046 struct ieee80211_vif *vif,
1047 struct ieee80211_if_conf *conf)
1048{
1049 struct wl1271 *wl = hw->priv;
1050 struct sk_buff *beacon;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001051 int ret;
1052
David S. Miller32646902009-09-17 10:18:30 -07001053 wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM",
1054 conf->bssid);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001055 wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
1056 conf->ssid_len);
1057
1058 mutex_lock(&wl->mutex);
1059
1060 ret = wl1271_ps_elp_wakeup(wl, false);
1061 if (ret < 0)
1062 goto out;
1063
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001064 if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) {
1065 wl1271_debug(DEBUG_MAC80211, "bssid changed");
1066
1067 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
1068
1069 ret = wl1271_cmd_join(wl);
1070 if (ret < 0)
1071 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001072
Juuso Oikarinenc6317a52009-11-02 20:22:08 +02001073 ret = wl1271_cmd_build_null_data(wl);
1074 if (ret < 0)
1075 goto out_sleep;
1076 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001077
1078 wl->ssid_len = conf->ssid_len;
1079 if (wl->ssid_len)
1080 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
1081
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001082 if (conf->changed & IEEE80211_IFCC_BEACON) {
1083 beacon = ieee80211_beacon_get(hw, vif);
1084 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
1085 beacon->data, beacon->len);
1086
1087 if (ret < 0) {
1088 dev_kfree_skb(beacon);
1089 goto out_sleep;
1090 }
1091
1092 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
1093 beacon->data, beacon->len);
1094
1095 dev_kfree_skb(beacon);
1096
1097 if (ret < 0)
1098 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001099 }
1100
1101out_sleep:
1102 wl1271_ps_elp_sleep(wl);
1103
1104out:
1105 mutex_unlock(&wl->mutex);
1106
1107 return ret;
1108}
1109#endif
1110
1111static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
1112{
1113 struct wl1271 *wl = hw->priv;
1114 struct ieee80211_conf *conf = &hw->conf;
1115 int channel, ret = 0;
1116
1117 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
1118
1119 wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
1120 channel,
1121 conf->flags & IEEE80211_CONF_PS ? "on" : "off",
1122 conf->power_level);
1123
1124 mutex_lock(&wl->mutex);
1125
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001126 wl->band = conf->channel->band;
1127
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001128 ret = wl1271_ps_elp_wakeup(wl, false);
1129 if (ret < 0)
1130 goto out;
1131
1132 if (channel != wl->channel) {
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001133 /*
1134 * We assume that the stack will configure the right channel
1135 * before associating, so we don't need to send a join
1136 * command here. We will join the right channel when the
1137 * BSSID changes
1138 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001139 wl->channel = channel;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001140 }
1141
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001142 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
1143 wl1271_info("psm enabled");
1144
1145 wl->psm_requested = true;
1146
1147 /*
1148 * We enter PSM only if we're already associated.
1149 * If we're not, we'll enter it when joining an SSID,
1150 * through the bss_info_changed() hook.
1151 */
1152 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
1153 } else if (!(conf->flags & IEEE80211_CONF_PS) &&
1154 wl->psm_requested) {
1155 wl1271_info("psm disabled");
1156
1157 wl->psm_requested = false;
1158
1159 if (wl->psm)
1160 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
1161 }
1162
1163 if (conf->power_level != wl->power_level) {
1164 ret = wl1271_acx_tx_power(wl, conf->power_level);
1165 if (ret < 0)
Juuso Oikarinenc6317a52009-11-02 20:22:08 +02001166 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001167
1168 wl->power_level = conf->power_level;
1169 }
1170
1171out_sleep:
1172 wl1271_ps_elp_sleep(wl);
1173
1174out:
1175 mutex_unlock(&wl->mutex);
1176
1177 return ret;
1178}
1179
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001180struct wl1271_filter_params {
1181 bool enabled;
1182 int mc_list_length;
1183 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
1184};
1185
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001186static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
1187 struct dev_addr_list *mc_list)
1188{
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001189 struct wl1271_filter_params *fp;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001190 int i;
1191
Juuso Oikarinen74441132009-10-13 12:47:53 +03001192 fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001193 if (!fp) {
1194 wl1271_error("Out of memory setting filters.");
1195 return 0;
1196 }
1197
1198 /* update multicast filtering parameters */
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001199 fp->enabled = true;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001200 if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
1201 mc_count = 0;
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001202 fp->enabled = false;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001203 }
1204
1205 fp->mc_list_length = 0;
1206 for (i = 0; i < mc_count; i++) {
1207 if (mc_list->da_addrlen == ETH_ALEN) {
1208 memcpy(fp->mc_list[fp->mc_list_length],
1209 mc_list->da_addr, ETH_ALEN);
1210 fp->mc_list_length++;
1211 } else
1212 wl1271_warning("Unknown mc address length.");
Juuso Oikarinen74441132009-10-13 12:47:53 +03001213 mc_list = mc_list->next;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001214 }
1215
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001216 return (u64)(unsigned long)fp;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001217}
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001218
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001219#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1220 FIF_ALLMULTI | \
1221 FIF_FCSFAIL | \
1222 FIF_BCN_PRBRESP_PROMISC | \
1223 FIF_CONTROL | \
1224 FIF_OTHER_BSS)
1225
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001226static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
1227 unsigned int changed,
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001228 unsigned int *total, u64 multicast)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001229{
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001230 struct wl1271_filter_params *fp = (void *)(unsigned long)multicast;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001231 struct wl1271 *wl = hw->priv;
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001232 int ret;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001233
1234 wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
1235
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001236 mutex_lock(&wl->mutex);
1237
1238 if (wl->state == WL1271_STATE_OFF)
1239 goto out;
1240
1241 ret = wl1271_ps_elp_wakeup(wl, false);
1242 if (ret < 0)
1243 goto out;
1244
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001245 *total &= WL1271_SUPPORTED_FILTERS;
1246 changed &= WL1271_SUPPORTED_FILTERS;
1247
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001248 if (*total & FIF_ALLMULTI)
1249 ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
1250 else if (fp)
1251 ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
1252 fp->mc_list,
1253 fp->mc_list_length);
1254 if (ret < 0)
1255 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001256
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001257 kfree(fp);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001258
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001259 /* FIXME: We still need to set our filters properly */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001260
Juuso Oikarinenb54853f2009-10-13 12:47:59 +03001261 /* determine, whether supported filter values have changed */
1262 if (changed == 0)
1263 goto out_sleep;
1264
1265 /* apply configured filters */
1266 ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
1267 if (ret < 0)
1268 goto out_sleep;
1269
1270out_sleep:
1271 wl1271_ps_elp_sleep(wl);
1272
1273out:
1274 mutex_unlock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001275}
1276
1277static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1278 struct ieee80211_vif *vif,
1279 struct ieee80211_sta *sta,
1280 struct ieee80211_key_conf *key_conf)
1281{
1282 struct wl1271 *wl = hw->priv;
1283 const u8 *addr;
1284 int ret;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001285 u32 tx_seq_32 = 0;
1286 u16 tx_seq_16 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001287 u8 key_type;
1288
1289 static const u8 bcast_addr[ETH_ALEN] =
1290 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1291
1292 wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
1293
1294 addr = sta ? sta->addr : bcast_addr;
1295
1296 wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
1297 wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
1298 wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
1299 key_conf->alg, key_conf->keyidx,
1300 key_conf->keylen, key_conf->flags);
1301 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
1302
1303 if (is_zero_ether_addr(addr)) {
1304 /* We dont support TX only encryption */
1305 ret = -EOPNOTSUPP;
1306 goto out;
1307 }
1308
1309 mutex_lock(&wl->mutex);
1310
1311 ret = wl1271_ps_elp_wakeup(wl, false);
1312 if (ret < 0)
1313 goto out_unlock;
1314
1315 switch (key_conf->alg) {
1316 case ALG_WEP:
1317 key_type = KEY_WEP;
1318
1319 key_conf->hw_key_idx = key_conf->keyidx;
1320 break;
1321 case ALG_TKIP:
1322 key_type = KEY_TKIP;
1323
1324 key_conf->hw_key_idx = key_conf->keyidx;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001325 tx_seq_32 = wl->tx_security_seq_32;
1326 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001327 break;
1328 case ALG_CCMP:
1329 key_type = KEY_AES;
1330
1331 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001332 tx_seq_32 = wl->tx_security_seq_32;
1333 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001334 break;
1335 default:
1336 wl1271_error("Unknown key algo 0x%x", key_conf->alg);
1337
1338 ret = -EOPNOTSUPP;
1339 goto out_sleep;
1340 }
1341
1342 switch (cmd) {
1343 case SET_KEY:
1344 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
1345 key_conf->keyidx, key_type,
1346 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001347 addr, tx_seq_32, tx_seq_16);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001348 if (ret < 0) {
1349 wl1271_error("Could not add or replace key");
1350 goto out_sleep;
1351 }
1352 break;
1353
1354 case DISABLE_KEY:
1355 ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
1356 key_conf->keyidx, key_type,
1357 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001358 addr, 0, 0);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001359 if (ret < 0) {
1360 wl1271_error("Could not remove key");
1361 goto out_sleep;
1362 }
1363 break;
1364
1365 default:
1366 wl1271_error("Unsupported key cmd 0x%x", cmd);
1367 ret = -EOPNOTSUPP;
1368 goto out_sleep;
1369
1370 break;
1371 }
1372
1373out_sleep:
1374 wl1271_ps_elp_sleep(wl);
1375
1376out_unlock:
1377 mutex_unlock(&wl->mutex);
1378
1379out:
1380 return ret;
1381}
1382
1383static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
1384 struct cfg80211_scan_request *req)
1385{
1386 struct wl1271 *wl = hw->priv;
1387 int ret;
1388 u8 *ssid = NULL;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001389 size_t len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001390
1391 wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
1392
1393 if (req->n_ssids) {
1394 ssid = req->ssids[0].ssid;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001395 len = req->ssids[0].ssid_len;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001396 }
1397
1398 mutex_lock(&wl->mutex);
1399
1400 ret = wl1271_ps_elp_wakeup(wl, false);
1401 if (ret < 0)
1402 goto out;
1403
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001404 if (wl1271_11a_enabled())
1405 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1406 WL1271_SCAN_BAND_DUAL, 3);
1407 else
1408 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1409 WL1271_SCAN_BAND_2_4_GHZ, 3);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001410
1411 wl1271_ps_elp_sleep(wl);
1412
1413out:
1414 mutex_unlock(&wl->mutex);
1415
1416 return ret;
1417}
1418
1419static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1420{
1421 struct wl1271 *wl = hw->priv;
1422 int ret;
1423
1424 mutex_lock(&wl->mutex);
1425
1426 ret = wl1271_ps_elp_wakeup(wl, false);
1427 if (ret < 0)
1428 goto out;
1429
1430 ret = wl1271_acx_rts_threshold(wl, (u16) value);
1431 if (ret < 0)
1432 wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
1433
1434 wl1271_ps_elp_sleep(wl);
1435
1436out:
1437 mutex_unlock(&wl->mutex);
1438
1439 return ret;
1440}
1441
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001442static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
1443{
1444 struct ieee80211_supported_band *band;
1445 u32 enabled_rates = 0;
1446 int bit;
1447
1448 band = wl->hw->wiphy->bands[wl->band];
1449 for (bit = 0; bit < band->n_bitrates; bit++) {
1450 if (basic_rate_set & 0x1)
1451 enabled_rates |= band->bitrates[bit].hw_value;
1452 basic_rate_set >>= 1;
1453 }
1454
1455 return enabled_rates;
1456}
1457
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001458static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1459 struct ieee80211_vif *vif,
1460 struct ieee80211_bss_conf *bss_conf,
1461 u32 changed)
1462{
1463 enum wl1271_cmd_ps_mode mode;
1464 struct wl1271 *wl = hw->priv;
1465 int ret;
1466
1467 wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
1468
1469 mutex_lock(&wl->mutex);
1470
1471 ret = wl1271_ps_elp_wakeup(wl, false);
1472 if (ret < 0)
1473 goto out;
1474
1475 if (changed & BSS_CHANGED_ASSOC) {
1476 if (bss_conf->assoc) {
1477 wl->aid = bss_conf->aid;
1478
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001479 /*
1480 * with wl1271, we don't need to update the
1481 * beacon_int and dtim_period, because the firmware
1482 * updates it by itself when the first beacon is
1483 * received after a join.
1484 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001485 ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
1486 if (ret < 0)
1487 goto out_sleep;
1488
1489 ret = wl1271_acx_aid(wl, wl->aid);
1490 if (ret < 0)
1491 goto out_sleep;
1492
1493 /* If we want to go in PSM but we're not there yet */
1494 if (wl->psm_requested && !wl->psm) {
1495 mode = STATION_POWER_SAVE_MODE;
1496 ret = wl1271_ps_set_mode(wl, mode);
1497 if (ret < 0)
1498 goto out_sleep;
1499 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001500 } else {
1501 /* use defaults when not associated */
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001502 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
1503 wl->aid = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001504 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001505
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001506 }
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001507
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001508 if (changed & BSS_CHANGED_ERP_SLOT) {
1509 if (bss_conf->use_short_slot)
1510 ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
1511 else
1512 ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
1513 if (ret < 0) {
1514 wl1271_warning("Set slot time failed %d", ret);
1515 goto out_sleep;
1516 }
1517 }
1518
1519 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1520 if (bss_conf->use_short_preamble)
1521 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
1522 else
1523 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
1524 }
1525
1526 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1527 if (bss_conf->use_cts_prot)
1528 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
1529 else
1530 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
1531 if (ret < 0) {
1532 wl1271_warning("Set ctsprotect failed %d", ret);
1533 goto out_sleep;
1534 }
1535 }
1536
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001537 if (changed & BSS_CHANGED_BASIC_RATES) {
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001538 wl->basic_rate_set = wl1271_enabled_rates_get(
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001539 wl, bss_conf->basic_rates);
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001540
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001541 ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001542 if (ret < 0) {
1543 wl1271_warning("Set rate policies failed %d", ret);
1544 goto out_sleep;
1545 }
1546 }
1547
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001548out_sleep:
1549 wl1271_ps_elp_sleep(wl);
1550
1551out:
1552 mutex_unlock(&wl->mutex);
1553}
1554
1555
1556/* can't be const, mac80211 writes to this */
1557static struct ieee80211_rate wl1271_rates[] = {
1558 { .bitrate = 10,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001559 .hw_value = CONF_HW_BIT_RATE_1MBPS,
1560 .hw_value_short = CONF_HW_BIT_RATE_1MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001561 { .bitrate = 20,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001562 .hw_value = CONF_HW_BIT_RATE_2MBPS,
1563 .hw_value_short = CONF_HW_BIT_RATE_2MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001564 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1565 { .bitrate = 55,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001566 .hw_value = CONF_HW_BIT_RATE_5_5MBPS,
1567 .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001568 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1569 { .bitrate = 110,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001570 .hw_value = CONF_HW_BIT_RATE_11MBPS,
1571 .hw_value_short = CONF_HW_BIT_RATE_11MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001572 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1573 { .bitrate = 60,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001574 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1575 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001576 { .bitrate = 90,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001577 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1578 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001579 { .bitrate = 120,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001580 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1581 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001582 { .bitrate = 180,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001583 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1584 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001585 { .bitrate = 240,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001586 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1587 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001588 { .bitrate = 360,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001589 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1590 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001591 { .bitrate = 480,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001592 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1593 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001594 { .bitrate = 540,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001595 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1596 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001597};
1598
1599/* can't be const, mac80211 writes to this */
1600static struct ieee80211_channel wl1271_channels[] = {
1601 { .hw_value = 1, .center_freq = 2412},
1602 { .hw_value = 2, .center_freq = 2417},
1603 { .hw_value = 3, .center_freq = 2422},
1604 { .hw_value = 4, .center_freq = 2427},
1605 { .hw_value = 5, .center_freq = 2432},
1606 { .hw_value = 6, .center_freq = 2437},
1607 { .hw_value = 7, .center_freq = 2442},
1608 { .hw_value = 8, .center_freq = 2447},
1609 { .hw_value = 9, .center_freq = 2452},
1610 { .hw_value = 10, .center_freq = 2457},
1611 { .hw_value = 11, .center_freq = 2462},
1612 { .hw_value = 12, .center_freq = 2467},
1613 { .hw_value = 13, .center_freq = 2472},
1614};
1615
1616/* can't be const, mac80211 writes to this */
1617static struct ieee80211_supported_band wl1271_band_2ghz = {
1618 .channels = wl1271_channels,
1619 .n_channels = ARRAY_SIZE(wl1271_channels),
1620 .bitrates = wl1271_rates,
1621 .n_bitrates = ARRAY_SIZE(wl1271_rates),
1622};
1623
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001624/* 5 GHz data rates for WL1273 */
1625static struct ieee80211_rate wl1271_rates_5ghz[] = {
1626 { .bitrate = 60,
1627 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1628 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
1629 { .bitrate = 90,
1630 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1631 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
1632 { .bitrate = 120,
1633 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1634 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
1635 { .bitrate = 180,
1636 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1637 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
1638 { .bitrate = 240,
1639 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1640 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
1641 { .bitrate = 360,
1642 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1643 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
1644 { .bitrate = 480,
1645 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1646 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
1647 { .bitrate = 540,
1648 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1649 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
1650};
1651
1652/* 5 GHz band channels for WL1273 */
1653static struct ieee80211_channel wl1271_channels_5ghz[] = {
1654 { .hw_value = 183, .center_freq = 4915},
1655 { .hw_value = 184, .center_freq = 4920},
1656 { .hw_value = 185, .center_freq = 4925},
1657 { .hw_value = 187, .center_freq = 4935},
1658 { .hw_value = 188, .center_freq = 4940},
1659 { .hw_value = 189, .center_freq = 4945},
1660 { .hw_value = 192, .center_freq = 4960},
1661 { .hw_value = 196, .center_freq = 4980},
1662 { .hw_value = 7, .center_freq = 5035},
1663 { .hw_value = 8, .center_freq = 5040},
1664 { .hw_value = 9, .center_freq = 5045},
1665 { .hw_value = 11, .center_freq = 5055},
1666 { .hw_value = 12, .center_freq = 5060},
1667 { .hw_value = 16, .center_freq = 5080},
1668 { .hw_value = 34, .center_freq = 5170},
1669 { .hw_value = 36, .center_freq = 5180},
1670 { .hw_value = 38, .center_freq = 5190},
1671 { .hw_value = 40, .center_freq = 5200},
1672 { .hw_value = 42, .center_freq = 5210},
1673 { .hw_value = 44, .center_freq = 5220},
1674 { .hw_value = 46, .center_freq = 5230},
1675 { .hw_value = 48, .center_freq = 5240},
1676 { .hw_value = 52, .center_freq = 5260},
1677 { .hw_value = 56, .center_freq = 5280},
1678 { .hw_value = 60, .center_freq = 5300},
1679 { .hw_value = 64, .center_freq = 5320},
1680 { .hw_value = 100, .center_freq = 5500},
1681 { .hw_value = 104, .center_freq = 5520},
1682 { .hw_value = 108, .center_freq = 5540},
1683 { .hw_value = 112, .center_freq = 5560},
1684 { .hw_value = 116, .center_freq = 5580},
1685 { .hw_value = 120, .center_freq = 5600},
1686 { .hw_value = 124, .center_freq = 5620},
1687 { .hw_value = 128, .center_freq = 5640},
1688 { .hw_value = 132, .center_freq = 5660},
1689 { .hw_value = 136, .center_freq = 5680},
1690 { .hw_value = 140, .center_freq = 5700},
1691 { .hw_value = 149, .center_freq = 5745},
1692 { .hw_value = 153, .center_freq = 5765},
1693 { .hw_value = 157, .center_freq = 5785},
1694 { .hw_value = 161, .center_freq = 5805},
1695 { .hw_value = 165, .center_freq = 5825},
1696};
1697
1698
1699static struct ieee80211_supported_band wl1271_band_5ghz = {
1700 .channels = wl1271_channels_5ghz,
1701 .n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
1702 .bitrates = wl1271_rates_5ghz,
1703 .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
1704};
1705
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001706static const struct ieee80211_ops wl1271_ops = {
1707 .start = wl1271_op_start,
1708 .stop = wl1271_op_stop,
1709 .add_interface = wl1271_op_add_interface,
1710 .remove_interface = wl1271_op_remove_interface,
1711 .config = wl1271_op_config,
1712/* .config_interface = wl1271_op_config_interface, */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001713 .prepare_multicast = wl1271_op_prepare_multicast,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001714 .configure_filter = wl1271_op_configure_filter,
1715 .tx = wl1271_op_tx,
1716 .set_key = wl1271_op_set_key,
1717 .hw_scan = wl1271_op_hw_scan,
1718 .bss_info_changed = wl1271_op_bss_info_changed,
1719 .set_rts_threshold = wl1271_op_set_rts_threshold,
1720};
1721
1722static int wl1271_register_hw(struct wl1271 *wl)
1723{
1724 int ret;
1725
1726 if (wl->mac80211_registered)
1727 return 0;
1728
1729 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1730
1731 ret = ieee80211_register_hw(wl->hw);
1732 if (ret < 0) {
1733 wl1271_error("unable to register mac80211 hw: %d", ret);
1734 return ret;
1735 }
1736
1737 wl->mac80211_registered = true;
1738
1739 wl1271_notice("loaded");
1740
1741 return 0;
1742}
1743
1744static int wl1271_init_ieee80211(struct wl1271 *wl)
1745{
Juuso Oikarinen1e2b7972009-10-08 21:56:20 +03001746 /* The tx descriptor buffer and the TKIP space. */
1747 wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
1748 sizeof(struct wl1271_tx_hw_descr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001749
1750 /* unit us */
1751 /* FIXME: find a proper value */
1752 wl->hw->channel_change_time = 10000;
1753
1754 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
Juuso Oikarinen19221672009-10-08 21:56:35 +03001755 IEEE80211_HW_NOISE_DBM |
1756 IEEE80211_HW_BEACON_FILTER;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001757
1758 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1759 wl->hw->wiphy->max_scan_ssids = 1;
1760 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
1761
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001762 if (wl1271_11a_enabled())
1763 wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
1764
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001765 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1766
1767 return 0;
1768}
1769
1770static void wl1271_device_release(struct device *dev)
1771{
1772
1773}
1774
1775static struct platform_device wl1271_device = {
1776 .name = "wl1271",
1777 .id = -1,
1778
1779 /* device model insists to have a release function */
1780 .dev = {
1781 .release = wl1271_device_release,
1782 },
1783};
1784
1785#define WL1271_DEFAULT_CHANNEL 0
1786static int __devinit wl1271_probe(struct spi_device *spi)
1787{
1788 struct wl12xx_platform_data *pdata;
1789 struct ieee80211_hw *hw;
1790 struct wl1271 *wl;
1791 int ret, i;
1792 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1793
1794 pdata = spi->dev.platform_data;
1795 if (!pdata) {
1796 wl1271_error("no platform data");
1797 return -ENODEV;
1798 }
1799
1800 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
1801 if (!hw) {
1802 wl1271_error("could not alloc ieee80211_hw");
1803 return -ENOMEM;
1804 }
1805
1806 wl = hw->priv;
1807 memset(wl, 0, sizeof(*wl));
1808
Juuso Oikarinen01c09162009-10-13 12:47:55 +03001809 INIT_LIST_HEAD(&wl->list);
1810
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001811 wl->hw = hw;
1812 dev_set_drvdata(&spi->dev, wl);
1813 wl->spi = spi;
1814
1815 skb_queue_head_init(&wl->tx_queue);
1816
Juuso Oikarinen37b70a82009-10-08 21:56:21 +03001817 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001818 wl->channel = WL1271_DEFAULT_CHANNEL;
1819 wl->scanning = false;
1820 wl->default_key = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001821 wl->rx_counter = 0;
1822 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
1823 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
1824 wl->elp = false;
1825 wl->psm = 0;
1826 wl->psm_requested = false;
Juuso Oikarinen19ad0712009-11-02 20:22:11 +02001827 wl->psm_entry_retry = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001828 wl->tx_queue_stopped = false;
1829 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001830 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001831 wl->band = IEEE80211_BAND_2GHZ;
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001832 wl->vif = NULL;
Luciano Coelhod6e19d12009-10-12 15:08:43 +03001833 wl->joined = false;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001834
Juuso Oikarinenbe7078c2009-10-08 21:56:26 +03001835 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001836 wl->tx_frames[i] = NULL;
1837
1838 spin_lock_init(&wl->wl_lock);
1839
1840 /*
1841 * In case our MAC address is not correctly set,
1842 * we use a random but Nokia MAC.
1843 */
1844 memcpy(wl->mac_addr, nokia_oui, 3);
1845 get_random_bytes(wl->mac_addr + 3, 3);
1846
1847 wl->state = WL1271_STATE_OFF;
1848 mutex_init(&wl->mutex);
1849
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001850 /* This is the only SPI value that we need to set here, the rest
1851 * comes from the board-peripherals file */
1852 spi->bits_per_word = 32;
1853
1854 ret = spi_setup(spi);
1855 if (ret < 0) {
1856 wl1271_error("spi_setup failed");
1857 goto out_free;
1858 }
1859
1860 wl->set_power = pdata->set_power;
1861 if (!wl->set_power) {
1862 wl1271_error("set power function missing in platform data");
1863 ret = -ENODEV;
1864 goto out_free;
1865 }
1866
1867 wl->irq = spi->irq;
1868 if (wl->irq < 0) {
1869 wl1271_error("irq missing in platform data");
1870 ret = -ENODEV;
1871 goto out_free;
1872 }
1873
1874 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
1875 if (ret < 0) {
1876 wl1271_error("request_irq() failed: %d", ret);
1877 goto out_free;
1878 }
1879
1880 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1881
1882 disable_irq(wl->irq);
1883
1884 ret = platform_device_register(&wl1271_device);
1885 if (ret) {
1886 wl1271_error("couldn't register platform device");
1887 goto out_irq;
1888 }
1889 dev_set_drvdata(&wl1271_device.dev, wl);
1890
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001891 /* Apply default driver configuration. */
1892 wl1271_conf_init(wl);
1893
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001894 ret = wl1271_init_ieee80211(wl);
1895 if (ret)
1896 goto out_platform;
1897
1898 ret = wl1271_register_hw(wl);
1899 if (ret)
1900 goto out_platform;
1901
1902 wl1271_debugfs_init(wl);
1903
1904 wl1271_notice("initialized");
1905
1906 return 0;
1907
1908 out_platform:
1909 platform_device_unregister(&wl1271_device);
1910
1911 out_irq:
1912 free_irq(wl->irq, wl);
1913
1914 out_free:
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001915 ieee80211_free_hw(hw);
1916
1917 return ret;
1918}
1919
1920static int __devexit wl1271_remove(struct spi_device *spi)
1921{
1922 struct wl1271 *wl = dev_get_drvdata(&spi->dev);
1923
1924 ieee80211_unregister_hw(wl->hw);
1925
1926 wl1271_debugfs_exit(wl);
1927 platform_device_unregister(&wl1271_device);
1928 free_irq(wl->irq, wl);
1929 kfree(wl->target_mem_map);
Juuso Oikarinen1fba4972009-10-08 21:56:32 +03001930 vfree(wl->fw);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001931 wl->fw = NULL;
1932 kfree(wl->nvs);
1933 wl->nvs = NULL;
1934
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001935 kfree(wl->fw_status);
1936 kfree(wl->tx_res_if);
1937
1938 ieee80211_free_hw(wl->hw);
1939
1940 return 0;
1941}
1942
1943
1944static struct spi_driver wl1271_spi_driver = {
1945 .driver = {
1946 .name = "wl1271",
1947 .bus = &spi_bus_type,
1948 .owner = THIS_MODULE,
1949 },
1950
1951 .probe = wl1271_probe,
1952 .remove = __devexit_p(wl1271_remove),
1953};
1954
1955static int __init wl1271_init(void)
1956{
1957 int ret;
1958
1959 ret = spi_register_driver(&wl1271_spi_driver);
1960 if (ret < 0) {
1961 wl1271_error("failed to register spi driver: %d", ret);
1962 goto out;
1963 }
1964
1965out:
1966 return ret;
1967}
1968
1969static void __exit wl1271_exit(void)
1970{
1971 spi_unregister_driver(&wl1271_spi_driver);
1972
1973 wl1271_notice("unloaded");
1974}
1975
1976module_init(wl1271_init);
1977module_exit(wl1271_exit);
1978
1979MODULE_LICENSE("GPL");
1980MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
Luciano Coelho2f018722009-10-08 21:56:27 +03001981MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
Ben Hutchings49f146d2009-11-07 22:02:15 +00001982MODULE_FIRMWARE(WL1271_FW_NAME);