blob: 7b8d2799f23eea63d0c79668f09a9f52686cb58b [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,
225 .bet_max_consecutive = 100
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300226 },
227 .init = {
228 .sr_err_tbl = {
229 [0] = {
230 .len = 7,
231 .upper_limit = 0x03,
232 .values = {
233 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
234 0x00 }
235 },
236 [1] = {
237 .len = 7,
238 .upper_limit = 0x03,
239 .values = {
240 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8,
241 0x00 }
242 },
243 [2] = {
244 .len = 7,
245 .upper_limit = 0x03,
246 .values = {
247 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
248 0x00 }
249 }
250 },
251 .sr_enable = 1,
252 .genparam = {
253 /*
254 * FIXME: The correct value CONF_REF_CLK_38_4_E
255 * causes the firmware to crash on boot.
256 * The value 5 apparently is an
257 * unnoficial XTAL configuration of the
258 * same frequency, which appears to work.
259 */
260 .ref_clk = 5,
261 .settling_time = 5,
262 .clk_valid_on_wakeup = 0,
263 .dc2dcmode = 0,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300264 .single_dual_band = CONF_SINGLE_BAND,
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300265 .tx_bip_fem_autodetect = 0,
266 .tx_bip_fem_manufacturer = 1,
267 .settings = 1,
268 },
269 .radioparam = {
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300270 .rx_trace_loss = 10,
271 .tx_trace_loss = 10,
272 .rx_rssi_and_proc_compens = {
273 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
274 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
275 0x00, 0x0a, 0x14 },
276 .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
277 .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
278 .rx_rssi_and_proc_compens_5 = {
279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00 },
282 .tx_ref_pd_voltage = 0x24e,
283 .tx_ref_power = 0x78,
284 .tx_offset_db = 0x0,
285 .tx_rate_limits_normal = {
286 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
287 .tx_rate_limits_degraded = {
288 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
289 .tx_channel_limits_11b = {
290 0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
291 0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
292 0x22, 0x50 },
293 .tx_channel_limits_ofdm = {
294 0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
295 0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
296 0x20, 0x50 },
297 .tx_pdv_rate_offsets = {
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
299 .tx_ibias = {
300 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
301 .rx_fem_insertion_loss = 0x14,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300302 .tx_ref_pd_voltage_5 = {
303 0x0190, 0x01a4, 0x01c3, 0x01d8,
304 0x020a, 0x021c },
305 .tx_ref_power_5 = {
306 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
307 .tx_offset_db_5 = {
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300309 .tx_rate_limits_normal_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300310 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300311 .tx_rate_limits_degraded_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300312 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300313 .tx_channel_limits_ofdm_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300314 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
315 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 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300319 .tx_pdv_rate_offsets_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300320 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300321 .tx_ibias_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300322 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
323 .rx_fem_insertion_loss_5 = {
324 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300325 }
326 }
327};
328
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300329static LIST_HEAD(wl_list);
330
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300331static void wl1271_conf_init(struct wl1271 *wl)
332{
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300333
334 /*
335 * This function applies the default configuration to the driver. This
336 * function is invoked upon driver load (spi probe.)
337 *
338 * The configuration is stored in a run-time structure in order to
339 * facilitate for run-time adjustment of any of the parameters. Making
340 * changes to the configuration structure will apply the new values on
341 * the next interface up (wl1271_op_start.)
342 */
343
344 /* apply driver default configuration */
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300345 memcpy(&wl->conf, &default_conf, sizeof(default_conf));
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300346
347 if (wl1271_11a_enabled())
348 wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300349}
350
351
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300352static int wl1271_plt_init(struct wl1271 *wl)
353{
354 int ret;
355
356 ret = wl1271_acx_init_mem_config(wl);
357 if (ret < 0)
358 return ret;
359
360 ret = wl1271_cmd_data_path(wl, wl->channel, 1);
361 if (ret < 0)
362 return ret;
363
364 return 0;
365}
366
367static void wl1271_disable_interrupts(struct wl1271 *wl)
368{
369 disable_irq(wl->irq);
370}
371
372static void wl1271_power_off(struct wl1271 *wl)
373{
374 wl->set_power(false);
375}
376
377static void wl1271_power_on(struct wl1271 *wl)
378{
379 wl->set_power(true);
380}
381
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300382static void wl1271_fw_status(struct wl1271 *wl,
383 struct wl1271_fw_status *status)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300384{
385 u32 total = 0;
386 int i;
387
Juuso Oikarinen74621412009-10-12 15:08:54 +0300388 wl1271_spi_read(wl, FW_STATUS_ADDR, status,
389 sizeof(*status), false);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300390
391 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
392 "drv_rx_counter = %d, tx_results_counter = %d)",
393 status->intr,
394 status->fw_rx_counter,
395 status->drv_rx_counter,
396 status->tx_results_counter);
397
398 /* update number of available TX blocks */
399 for (i = 0; i < NUM_TX_QUEUES; i++) {
400 u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
401 wl->tx_blocks_freed[i] = status->tx_released_blks[i];
402 wl->tx_blocks_available += cnt;
403 total += cnt;
404 }
405
406 /* if more blocks are available now, schedule some tx work */
407 if (total && !skb_queue_empty(&wl->tx_queue))
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300408 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300409
410 /* update the host-chipset time offset */
411 wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
412}
413
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300414static void wl1271_irq_work(struct work_struct *work)
415{
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300416 int ret;
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300417 u32 intr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300418 struct wl1271 *wl =
419 container_of(work, struct wl1271, irq_work);
420
421 mutex_lock(&wl->mutex);
422
423 wl1271_debug(DEBUG_IRQ, "IRQ work");
424
425 if (wl->state == WL1271_STATE_OFF)
426 goto out;
427
428 ret = wl1271_ps_elp_wakeup(wl, true);
429 if (ret < 0)
430 goto out;
431
Juuso Oikarinen74621412009-10-12 15:08:54 +0300432 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300433
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300434 wl1271_fw_status(wl, wl->fw_status);
435 intr = wl->fw_status->intr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300436 if (!intr) {
437 wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
438 goto out_sleep;
439 }
440
441 intr &= WL1271_INTR_MASK;
442
Juuso Oikarinen1fd27942009-10-13 12:47:54 +0300443 if (intr & WL1271_ACX_INTR_EVENT_A) {
444 bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true;
445 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
446 wl1271_event_handle(wl, 0, do_ack);
447 }
448
449 if (intr & WL1271_ACX_INTR_EVENT_B) {
450 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
451 wl1271_event_handle(wl, 1, true);
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300452 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300453
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300454 if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
455 wl1271_debug(DEBUG_IRQ,
456 "WL1271_ACX_INTR_INIT_COMPLETE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300457
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300458 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
459 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300460
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300461 if (intr & WL1271_ACX_INTR_DATA) {
462 u8 tx_res_cnt = wl->fw_status->tx_results_counter -
463 wl->tx_results_count;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300464
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300465 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300466
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300467 /* check for tx results */
468 if (tx_res_cnt)
469 wl1271_tx_complete(wl, tx_res_cnt);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300470
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300471 wl1271_rx(wl, wl->fw_status);
472 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300473
474out_sleep:
Juuso Oikarinen74621412009-10-12 15:08:54 +0300475 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
Luciano Coelho73d0a132009-08-11 11:58:27 +0300476 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300477 wl1271_ps_elp_sleep(wl);
478
479out:
480 mutex_unlock(&wl->mutex);
481}
482
483static irqreturn_t wl1271_irq(int irq, void *cookie)
484{
485 struct wl1271 *wl;
486 unsigned long flags;
487
488 wl1271_debug(DEBUG_IRQ, "IRQ");
489
490 wl = cookie;
491
492 /* complete the ELP completion */
493 spin_lock_irqsave(&wl->wl_lock, flags);
494 if (wl->elp_compl) {
495 complete(wl->elp_compl);
496 wl->elp_compl = NULL;
497 }
498
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300499 ieee80211_queue_work(wl->hw, &wl->irq_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300500 spin_unlock_irqrestore(&wl->wl_lock, flags);
501
502 return IRQ_HANDLED;
503}
504
505static int wl1271_fetch_firmware(struct wl1271 *wl)
506{
507 const struct firmware *fw;
508 int ret;
509
510 ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
511
512 if (ret < 0) {
513 wl1271_error("could not get firmware: %d", ret);
514 return ret;
515 }
516
517 if (fw->size % 4) {
518 wl1271_error("firmware size is not multiple of 32 bits: %zu",
519 fw->size);
520 ret = -EILSEQ;
521 goto out;
522 }
523
524 wl->fw_len = fw->size;
Juuso Oikarinen1fba4972009-10-08 21:56:32 +0300525 wl->fw = vmalloc(wl->fw_len);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300526
527 if (!wl->fw) {
528 wl1271_error("could not allocate memory for the firmware");
529 ret = -ENOMEM;
530 goto out;
531 }
532
533 memcpy(wl->fw, fw->data, wl->fw_len);
534
535 ret = 0;
536
537out:
538 release_firmware(fw);
539
540 return ret;
541}
542
543static int wl1271_fetch_nvs(struct wl1271 *wl)
544{
545 const struct firmware *fw;
546 int ret;
547
548 ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
549
550 if (ret < 0) {
551 wl1271_error("could not get nvs file: %d", ret);
552 return ret;
553 }
554
555 if (fw->size % 4) {
556 wl1271_error("nvs size is not multiple of 32 bits: %zu",
557 fw->size);
558 ret = -EILSEQ;
559 goto out;
560 }
561
562 wl->nvs_len = fw->size;
563 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
564
565 if (!wl->nvs) {
566 wl1271_error("could not allocate memory for the nvs file");
567 ret = -ENOMEM;
568 goto out;
569 }
570
571 memcpy(wl->nvs, fw->data, wl->nvs_len);
572
573 ret = 0;
574
575out:
576 release_firmware(fw);
577
578 return ret;
579}
580
581static void wl1271_fw_wakeup(struct wl1271 *wl)
582{
583 u32 elp_reg;
584
585 elp_reg = ELPCTRL_WAKE_UP;
Juuso Oikarinen74621412009-10-12 15:08:54 +0300586 wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300587}
588
589static int wl1271_setup(struct wl1271 *wl)
590{
591 wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
592 if (!wl->fw_status)
593 return -ENOMEM;
594
595 wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
596 if (!wl->tx_res_if) {
597 kfree(wl->fw_status);
598 return -ENOMEM;
599 }
600
601 INIT_WORK(&wl->irq_work, wl1271_irq_work);
602 INIT_WORK(&wl->tx_work, wl1271_tx_work);
603 return 0;
604}
605
606static int wl1271_chip_wakeup(struct wl1271 *wl)
607{
Juuso Oikarinen451de972009-10-12 15:08:46 +0300608 struct wl1271_partition_set partition;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300609 int ret = 0;
610
611 wl1271_power_on(wl);
612 msleep(WL1271_POWER_ON_SLEEP);
613 wl1271_spi_reset(wl);
614 wl1271_spi_init(wl);
615
616 /* We don't need a real memory partition here, because we only want
617 * to use the registers at this point. */
Juuso Oikarinen451de972009-10-12 15:08:46 +0300618 memset(&partition, 0, sizeof(partition));
619 partition.reg.start = REGISTERS_BASE;
620 partition.reg.size = REGISTERS_DOWN_SIZE;
621 wl1271_set_partition(wl, &partition);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300622
623 /* ELP module wake up */
624 wl1271_fw_wakeup(wl);
625
626 /* whal_FwCtrl_BootSm() */
627
628 /* 0. read chip id from CHIP_ID */
Juuso Oikarinen74621412009-10-12 15:08:54 +0300629 wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300630
631 /* 1. check if chip id is valid */
632
633 switch (wl->chip.id) {
634 case CHIP_ID_1271_PG10:
635 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
636 wl->chip.id);
637
638 ret = wl1271_setup(wl);
639 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300640 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300641 break;
642 case CHIP_ID_1271_PG20:
643 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
644 wl->chip.id);
645
646 ret = wl1271_setup(wl);
647 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300648 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300649 break;
650 default:
651 wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
652 ret = -ENODEV;
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300653 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300654 }
655
656 if (wl->fw == NULL) {
657 ret = wl1271_fetch_firmware(wl);
658 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300659 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300660 }
661
662 /* No NVS from netlink, try to get it from the filesystem */
663 if (wl->nvs == NULL) {
664 ret = wl1271_fetch_nvs(wl);
665 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300666 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300667 }
668
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300669 goto out;
670
671out_power_off:
672 wl1271_power_off(wl);
673
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300674out:
675 return ret;
676}
677
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300678struct wl1271_filter_params {
679 unsigned int filters;
680 unsigned int changed;
681 int mc_list_length;
682 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
683};
684
685#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
686 FIF_ALLMULTI | \
687 FIF_FCSFAIL | \
688 FIF_BCN_PRBRESP_PROMISC | \
689 FIF_CONTROL | \
690 FIF_OTHER_BSS)
691
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300692static void wl1271_filter_work(struct work_struct *work)
693{
694 struct wl1271 *wl =
695 container_of(work, struct wl1271, filter_work);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300696 struct wl1271_filter_params *fp;
697 unsigned long flags;
698 bool enabled = true;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300699 int ret;
700
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300701 /* first, get the filter parameters */
702 spin_lock_irqsave(&wl->wl_lock, flags);
703 fp = wl->filter_params;
704 wl->filter_params = NULL;
705 spin_unlock_irqrestore(&wl->wl_lock, flags);
706
707 if (!fp)
708 return;
709
710 /* then, lock the mutex without risk of lock-up */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300711 mutex_lock(&wl->mutex);
712
713 if (wl->state == WL1271_STATE_OFF)
714 goto out;
715
716 ret = wl1271_ps_elp_wakeup(wl, false);
717 if (ret < 0)
718 goto out;
719
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300720 /* configure the mc filter regardless of the changed flags */
721 if (fp->filters & FIF_ALLMULTI)
722 enabled = false;
723
724 ret = wl1271_acx_group_address_tbl(wl, enabled,
725 fp->mc_list, fp->mc_list_length);
726 if (ret < 0)
727 goto out_sleep;
728
729 /* determine, whether supported filter values have changed */
730 if (fp->changed == 0)
731 goto out;
732
733 /* apply configured filters */
Luciano Coelho0535d9f2009-10-12 15:08:56 +0300734 ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300735 if (ret < 0)
736 goto out_sleep;
737
738out_sleep:
739 wl1271_ps_elp_sleep(wl);
740
741out:
742 mutex_unlock(&wl->mutex);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300743 kfree(fp);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300744}
745
746int wl1271_plt_start(struct wl1271 *wl)
747{
748 int ret;
749
750 mutex_lock(&wl->mutex);
751
752 wl1271_notice("power up");
753
754 if (wl->state != WL1271_STATE_OFF) {
755 wl1271_error("cannot go into PLT state because not "
756 "in off state: %d", wl->state);
757 ret = -EBUSY;
758 goto out;
759 }
760
761 wl->state = WL1271_STATE_PLT;
762
763 ret = wl1271_chip_wakeup(wl);
764 if (ret < 0)
765 goto out;
766
767 ret = wl1271_boot(wl);
768 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300769 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300770
771 wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
772
773 ret = wl1271_plt_init(wl);
774 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300775 goto out_irq_disable;
776
Luciano Coelhobd5ea182009-10-13 12:47:58 +0300777 /* Make sure power saving is disabled */
778 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
779 if (ret < 0)
780 goto out_irq_disable;
781
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300782 goto out;
783
784out_irq_disable:
785 wl1271_disable_interrupts(wl);
786
787out_power_off:
788 wl1271_power_off(wl);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300789
790out:
791 mutex_unlock(&wl->mutex);
792
793 return ret;
794}
795
796int wl1271_plt_stop(struct wl1271 *wl)
797{
798 int ret = 0;
799
800 mutex_lock(&wl->mutex);
801
802 wl1271_notice("power down");
803
804 if (wl->state != WL1271_STATE_PLT) {
805 wl1271_error("cannot power down because not in PLT "
806 "state: %d", wl->state);
807 ret = -EBUSY;
808 goto out;
809 }
810
811 wl1271_disable_interrupts(wl);
812 wl1271_power_off(wl);
813
814 wl->state = WL1271_STATE_OFF;
Luciano Coelhobd5ea182009-10-13 12:47:58 +0300815 wl->rx_counter = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300816
817out:
818 mutex_unlock(&wl->mutex);
819
820 return ret;
821}
822
823
824static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
825{
826 struct wl1271 *wl = hw->priv;
827
828 skb_queue_tail(&wl->tx_queue, skb);
829
830 /*
831 * The chip specific setup must run before the first TX packet -
832 * before that, the tx_work will not be initialized!
833 */
834
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300835 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300836
837 /*
838 * The workqueue is slow to process the tx_queue and we need stop
839 * the queue here, otherwise the queue will get too long.
840 */
841 if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
842 ieee80211_stop_queues(wl->hw);
843
844 /*
845 * FIXME: this is racy, the variable is not properly
846 * protected. Maybe fix this by removing the stupid
847 * variable altogether and checking the real queue state?
848 */
849 wl->tx_queue_stopped = true;
850 }
851
852 return NETDEV_TX_OK;
853}
854
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300855static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
856 void *arg)
857{
858 struct net_device *dev;
859 struct wireless_dev *wdev;
860 struct wiphy *wiphy;
861 struct ieee80211_hw *hw;
862 struct wl1271 *wl;
863 struct wl1271 *wl_temp;
864 struct in_device *idev;
865 struct in_ifaddr *ifa = arg;
866 int ret = 0;
867
868 /* FIXME: this ugly function should probably be implemented in the
869 * mac80211, and here should only be a simple callback handling actual
870 * setting of the filters. Now we need to dig up references to
871 * various structures to gain access to what we need.
872 * Also, because of this, there is no "initial" setting of the filter
873 * in "op_start", because we don't want to dig up struct net_device
874 * there - the filter will be set upon first change of the interface
875 * IP address. */
876
877 dev = ifa->ifa_dev->dev;
878
879 wdev = dev->ieee80211_ptr;
880 if (wdev == NULL)
881 return -ENODEV;
882
883 wiphy = wdev->wiphy;
884 if (wiphy == NULL)
885 return -ENODEV;
886
887 hw = wiphy_priv(wiphy);
888 if (hw == NULL)
889 return -ENODEV;
890
891 /* Check that the interface is one supported by this driver. */
892 wl_temp = hw->priv;
893 list_for_each_entry(wl, &wl_list, list) {
894 if (wl == wl_temp)
895 break;
896 }
897 if (wl == NULL)
898 return -ENODEV;
899
900 /* Get the interface IP address for the device. "ifa" will become
901 NULL if:
902 - there is no IPV4 protocol address configured
903 - there are multiple (virtual) IPV4 addresses configured
904 When "ifa" is NULL, filtering will be disabled.
905 */
906 ifa = NULL;
907 idev = dev->ip_ptr;
908 if (idev)
909 ifa = idev->ifa_list;
910
911 if (ifa && ifa->ifa_next)
912 ifa = NULL;
913
914 mutex_lock(&wl->mutex);
915
916 if (wl->state == WL1271_STATE_OFF)
917 goto out;
918
919 ret = wl1271_ps_elp_wakeup(wl, false);
920 if (ret < 0)
921 goto out;
922 if (ifa)
923 ret = wl1271_acx_arp_ip_filter(wl, true,
924 (u8 *)&ifa->ifa_address,
925 ACX_IPV4_VERSION);
926 else
927 ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
928 ACX_IPV4_VERSION);
929 wl1271_ps_elp_sleep(wl);
930
931out:
932 mutex_unlock(&wl->mutex);
933
934 return ret;
935}
936
937static struct notifier_block wl1271_dev_notifier = {
938 .notifier_call = wl1271_dev_notify,
939};
940
941
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300942static int wl1271_op_start(struct ieee80211_hw *hw)
943{
944 struct wl1271 *wl = hw->priv;
945 int ret = 0;
946
947 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
948
949 mutex_lock(&wl->mutex);
950
951 if (wl->state != WL1271_STATE_OFF) {
952 wl1271_error("cannot start because not in off state: %d",
953 wl->state);
954 ret = -EBUSY;
955 goto out;
956 }
957
958 ret = wl1271_chip_wakeup(wl);
959 if (ret < 0)
960 goto out;
961
962 ret = wl1271_boot(wl);
963 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300964 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300965
966 ret = wl1271_hw_init(wl);
967 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300968 goto out_irq_disable;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300969
970 wl->state = WL1271_STATE_ON;
971
972 wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
973
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300974 goto out;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300975
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300976out_irq_disable:
977 wl1271_disable_interrupts(wl);
978
979out_power_off:
980 wl1271_power_off(wl);
981
982out:
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300983 mutex_unlock(&wl->mutex);
984
Juuso Oikarinen01c09162009-10-13 12:47:55 +0300985 if (!ret) {
986 list_add(&wl->list, &wl_list);
987 register_inetaddr_notifier(&wl1271_dev_notifier);
988 }
989
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300990 return ret;
991}
992
993static void wl1271_op_stop(struct ieee80211_hw *hw)
994{
995 struct wl1271 *wl = hw->priv;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300996 unsigned long flags;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300997 int i;
998
999 wl1271_info("down");
1000
1001 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
1002
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001003 /* complete/cancel ongoing work */
1004 cancel_work_sync(&wl->filter_work);
1005 spin_lock_irqsave(&wl->wl_lock, flags);
1006 kfree(wl->filter_params);
1007 wl->filter_params = NULL;
1008 spin_unlock_irqrestore(&wl->wl_lock, flags);
1009
Juuso Oikarinen01c09162009-10-13 12:47:55 +03001010 unregister_inetaddr_notifier(&wl1271_dev_notifier);
1011 list_del(&wl->list);
1012
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001013 mutex_lock(&wl->mutex);
1014
1015 WARN_ON(wl->state != WL1271_STATE_ON);
1016
1017 if (wl->scanning) {
1018 mutex_unlock(&wl->mutex);
1019 ieee80211_scan_completed(wl->hw, true);
1020 mutex_lock(&wl->mutex);
1021 wl->scanning = false;
1022 }
1023
1024 wl->state = WL1271_STATE_OFF;
1025
1026 wl1271_disable_interrupts(wl);
1027
1028 mutex_unlock(&wl->mutex);
1029
1030 cancel_work_sync(&wl->irq_work);
1031 cancel_work_sync(&wl->tx_work);
1032 cancel_work_sync(&wl->filter_work);
1033
1034 mutex_lock(&wl->mutex);
1035
1036 /* let's notify MAC80211 about the remaining pending TX frames */
1037 wl1271_tx_flush(wl);
1038 wl1271_power_off(wl);
1039
1040 memset(wl->bssid, 0, ETH_ALEN);
1041 memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
1042 wl->ssid_len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001043 wl->bss_type = MAX_BSS_TYPE;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001044 wl->band = IEEE80211_BAND_2GHZ;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001045
1046 wl->rx_counter = 0;
1047 wl->elp = false;
1048 wl->psm = 0;
1049 wl->tx_queue_stopped = false;
1050 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
1051 wl->tx_blocks_available = 0;
1052 wl->tx_results_count = 0;
1053 wl->tx_packets_count = 0;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001054 wl->tx_security_last_seq = 0;
1055 wl->tx_security_seq_16 = 0;
1056 wl->tx_security_seq_32 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001057 wl->time_offset = 0;
1058 wl->session_counter = 0;
Luciano Coelhod6e19d12009-10-12 15:08:43 +03001059 wl->joined = false;
1060
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001061 for (i = 0; i < NUM_TX_QUEUES; i++)
1062 wl->tx_blocks_freed[i] = 0;
1063
1064 wl1271_debugfs_reset(wl);
1065 mutex_unlock(&wl->mutex);
1066}
1067
1068static int wl1271_op_add_interface(struct ieee80211_hw *hw,
1069 struct ieee80211_if_init_conf *conf)
1070{
1071 struct wl1271 *wl = hw->priv;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001072 int ret = 0;
1073
John W. Linvillee5539bc2009-08-18 10:50:34 -04001074 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
1075 conf->type, conf->mac_addr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001076
1077 mutex_lock(&wl->mutex);
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001078 if (wl->vif) {
1079 ret = -EBUSY;
1080 goto out;
1081 }
1082
1083 wl->vif = conf->vif;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001084
1085 switch (conf->type) {
1086 case NL80211_IFTYPE_STATION:
1087 wl->bss_type = BSS_TYPE_STA_BSS;
1088 break;
1089 case NL80211_IFTYPE_ADHOC:
1090 wl->bss_type = BSS_TYPE_IBSS;
1091 break;
1092 default:
1093 ret = -EOPNOTSUPP;
1094 goto out;
1095 }
1096
1097 /* FIXME: what if conf->mac_addr changes? */
1098
1099out:
1100 mutex_unlock(&wl->mutex);
1101 return ret;
1102}
1103
1104static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1105 struct ieee80211_if_init_conf *conf)
1106{
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001107 struct wl1271 *wl = hw->priv;
1108
1109 mutex_lock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001110 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001111 wl->vif = NULL;
1112 mutex_unlock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001113}
1114
1115#if 0
1116static int wl1271_op_config_interface(struct ieee80211_hw *hw,
1117 struct ieee80211_vif *vif,
1118 struct ieee80211_if_conf *conf)
1119{
1120 struct wl1271 *wl = hw->priv;
1121 struct sk_buff *beacon;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001122 int ret;
1123
David S. Miller32646902009-09-17 10:18:30 -07001124 wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM",
1125 conf->bssid);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001126 wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
1127 conf->ssid_len);
1128
1129 mutex_lock(&wl->mutex);
1130
1131 ret = wl1271_ps_elp_wakeup(wl, false);
1132 if (ret < 0)
1133 goto out;
1134
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001135 if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) {
1136 wl1271_debug(DEBUG_MAC80211, "bssid changed");
1137
1138 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
1139
1140 ret = wl1271_cmd_join(wl);
1141 if (ret < 0)
1142 goto out_sleep;
1143 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001144
1145 ret = wl1271_cmd_build_null_data(wl);
1146 if (ret < 0)
1147 goto out_sleep;
1148
1149 wl->ssid_len = conf->ssid_len;
1150 if (wl->ssid_len)
1151 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
1152
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001153 if (conf->changed & IEEE80211_IFCC_BEACON) {
1154 beacon = ieee80211_beacon_get(hw, vif);
1155 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
1156 beacon->data, beacon->len);
1157
1158 if (ret < 0) {
1159 dev_kfree_skb(beacon);
1160 goto out_sleep;
1161 }
1162
1163 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
1164 beacon->data, beacon->len);
1165
1166 dev_kfree_skb(beacon);
1167
1168 if (ret < 0)
1169 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001170 }
1171
1172out_sleep:
1173 wl1271_ps_elp_sleep(wl);
1174
1175out:
1176 mutex_unlock(&wl->mutex);
1177
1178 return ret;
1179}
1180#endif
1181
1182static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
1183{
1184 struct wl1271 *wl = hw->priv;
1185 struct ieee80211_conf *conf = &hw->conf;
1186 int channel, ret = 0;
1187
1188 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
1189
1190 wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
1191 channel,
1192 conf->flags & IEEE80211_CONF_PS ? "on" : "off",
1193 conf->power_level);
1194
1195 mutex_lock(&wl->mutex);
1196
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001197 wl->band = conf->channel->band;
1198
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001199 ret = wl1271_ps_elp_wakeup(wl, false);
1200 if (ret < 0)
1201 goto out;
1202
1203 if (channel != wl->channel) {
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001204 /*
1205 * We assume that the stack will configure the right channel
1206 * before associating, so we don't need to send a join
1207 * command here. We will join the right channel when the
1208 * BSSID changes
1209 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001210 wl->channel = channel;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001211 }
1212
1213 ret = wl1271_cmd_build_null_data(wl);
1214 if (ret < 0)
1215 goto out_sleep;
1216
1217 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
1218 wl1271_info("psm enabled");
1219
1220 wl->psm_requested = true;
1221
1222 /*
1223 * We enter PSM only if we're already associated.
1224 * If we're not, we'll enter it when joining an SSID,
1225 * through the bss_info_changed() hook.
1226 */
1227 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
1228 } else if (!(conf->flags & IEEE80211_CONF_PS) &&
1229 wl->psm_requested) {
1230 wl1271_info("psm disabled");
1231
1232 wl->psm_requested = false;
1233
1234 if (wl->psm)
1235 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
1236 }
1237
1238 if (conf->power_level != wl->power_level) {
1239 ret = wl1271_acx_tx_power(wl, conf->power_level);
1240 if (ret < 0)
1241 goto out;
1242
1243 wl->power_level = conf->power_level;
1244 }
1245
1246out_sleep:
1247 wl1271_ps_elp_sleep(wl);
1248
1249out:
1250 mutex_unlock(&wl->mutex);
1251
1252 return ret;
1253}
1254
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001255static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
1256 struct dev_addr_list *mc_list)
1257{
1258 struct wl1271 *wl = hw->priv;
1259 struct wl1271_filter_params *fp;
1260 unsigned long flags;
1261 int i;
1262
1263 /*
1264 * FIXME: we should return a hash that will be passed to
1265 * configure_filter() instead of saving everything in the context.
1266 */
1267
Juuso Oikarinen74441132009-10-13 12:47:53 +03001268 fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001269 if (!fp) {
1270 wl1271_error("Out of memory setting filters.");
1271 return 0;
1272 }
1273
1274 /* update multicast filtering parameters */
1275 if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
1276 mc_count = 0;
1277 fp->filters |= FIF_ALLMULTI;
1278 }
1279
1280 fp->mc_list_length = 0;
1281 for (i = 0; i < mc_count; i++) {
1282 if (mc_list->da_addrlen == ETH_ALEN) {
1283 memcpy(fp->mc_list[fp->mc_list_length],
1284 mc_list->da_addr, ETH_ALEN);
1285 fp->mc_list_length++;
1286 } else
1287 wl1271_warning("Unknown mc address length.");
Juuso Oikarinen74441132009-10-13 12:47:53 +03001288 mc_list = mc_list->next;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001289 }
1290
Luciano Coelho0535d9f2009-10-12 15:08:56 +03001291 /* FIXME: We still need to set our filters properly */
1292
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001293 spin_lock_irqsave(&wl->wl_lock, flags);
1294 kfree(wl->filter_params);
1295 wl->filter_params = fp;
1296 spin_unlock_irqrestore(&wl->wl_lock, flags);
1297
1298 return 1;
1299}
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001300
1301static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
1302 unsigned int changed,
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001303 unsigned int *total, u64 multicast)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001304{
1305 struct wl1271 *wl = hw->priv;
1306
1307 wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
1308
1309 *total &= WL1271_SUPPORTED_FILTERS;
1310 changed &= WL1271_SUPPORTED_FILTERS;
1311
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001312 if (!multicast)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001313 return;
1314
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001315 /*
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001316 * FIXME: for now we are still using a workqueue for filter
1317 * configuration, but with the new mac80211, this is not needed,
1318 * since configure_filter can now sleep. We now have
1319 * prepare_multicast, which needs to be atomic instead.
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001320 */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001321
1322 /* store current filter config */
1323 wl->filter_params->filters = *total;
1324 wl->filter_params->changed = changed;
1325
1326 ieee80211_queue_work(wl->hw, &wl->filter_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001327}
1328
1329static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1330 struct ieee80211_vif *vif,
1331 struct ieee80211_sta *sta,
1332 struct ieee80211_key_conf *key_conf)
1333{
1334 struct wl1271 *wl = hw->priv;
1335 const u8 *addr;
1336 int ret;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001337 u32 tx_seq_32 = 0;
1338 u16 tx_seq_16 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001339 u8 key_type;
1340
1341 static const u8 bcast_addr[ETH_ALEN] =
1342 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1343
1344 wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
1345
1346 addr = sta ? sta->addr : bcast_addr;
1347
1348 wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
1349 wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
1350 wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
1351 key_conf->alg, key_conf->keyidx,
1352 key_conf->keylen, key_conf->flags);
1353 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
1354
1355 if (is_zero_ether_addr(addr)) {
1356 /* We dont support TX only encryption */
1357 ret = -EOPNOTSUPP;
1358 goto out;
1359 }
1360
1361 mutex_lock(&wl->mutex);
1362
1363 ret = wl1271_ps_elp_wakeup(wl, false);
1364 if (ret < 0)
1365 goto out_unlock;
1366
1367 switch (key_conf->alg) {
1368 case ALG_WEP:
1369 key_type = KEY_WEP;
1370
1371 key_conf->hw_key_idx = key_conf->keyidx;
1372 break;
1373 case ALG_TKIP:
1374 key_type = KEY_TKIP;
1375
1376 key_conf->hw_key_idx = key_conf->keyidx;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001377 tx_seq_32 = wl->tx_security_seq_32;
1378 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001379 break;
1380 case ALG_CCMP:
1381 key_type = KEY_AES;
1382
1383 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001384 tx_seq_32 = wl->tx_security_seq_32;
1385 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001386 break;
1387 default:
1388 wl1271_error("Unknown key algo 0x%x", key_conf->alg);
1389
1390 ret = -EOPNOTSUPP;
1391 goto out_sleep;
1392 }
1393
1394 switch (cmd) {
1395 case SET_KEY:
1396 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
1397 key_conf->keyidx, key_type,
1398 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001399 addr, tx_seq_32, tx_seq_16);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001400 if (ret < 0) {
1401 wl1271_error("Could not add or replace key");
1402 goto out_sleep;
1403 }
1404 break;
1405
1406 case DISABLE_KEY:
1407 ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
1408 key_conf->keyidx, key_type,
1409 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001410 addr, 0, 0);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001411 if (ret < 0) {
1412 wl1271_error("Could not remove key");
1413 goto out_sleep;
1414 }
1415 break;
1416
1417 default:
1418 wl1271_error("Unsupported key cmd 0x%x", cmd);
1419 ret = -EOPNOTSUPP;
1420 goto out_sleep;
1421
1422 break;
1423 }
1424
1425out_sleep:
1426 wl1271_ps_elp_sleep(wl);
1427
1428out_unlock:
1429 mutex_unlock(&wl->mutex);
1430
1431out:
1432 return ret;
1433}
1434
1435static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
1436 struct cfg80211_scan_request *req)
1437{
1438 struct wl1271 *wl = hw->priv;
1439 int ret;
1440 u8 *ssid = NULL;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001441 size_t len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001442
1443 wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
1444
1445 if (req->n_ssids) {
1446 ssid = req->ssids[0].ssid;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001447 len = req->ssids[0].ssid_len;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001448 }
1449
1450 mutex_lock(&wl->mutex);
1451
1452 ret = wl1271_ps_elp_wakeup(wl, false);
1453 if (ret < 0)
1454 goto out;
1455
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001456 if (wl1271_11a_enabled())
1457 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1458 WL1271_SCAN_BAND_DUAL, 3);
1459 else
1460 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1461 WL1271_SCAN_BAND_2_4_GHZ, 3);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001462
1463 wl1271_ps_elp_sleep(wl);
1464
1465out:
1466 mutex_unlock(&wl->mutex);
1467
1468 return ret;
1469}
1470
1471static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1472{
1473 struct wl1271 *wl = hw->priv;
1474 int ret;
1475
1476 mutex_lock(&wl->mutex);
1477
1478 ret = wl1271_ps_elp_wakeup(wl, false);
1479 if (ret < 0)
1480 goto out;
1481
1482 ret = wl1271_acx_rts_threshold(wl, (u16) value);
1483 if (ret < 0)
1484 wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
1485
1486 wl1271_ps_elp_sleep(wl);
1487
1488out:
1489 mutex_unlock(&wl->mutex);
1490
1491 return ret;
1492}
1493
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001494static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
1495{
1496 struct ieee80211_supported_band *band;
1497 u32 enabled_rates = 0;
1498 int bit;
1499
1500 band = wl->hw->wiphy->bands[wl->band];
1501 for (bit = 0; bit < band->n_bitrates; bit++) {
1502 if (basic_rate_set & 0x1)
1503 enabled_rates |= band->bitrates[bit].hw_value;
1504 basic_rate_set >>= 1;
1505 }
1506
1507 return enabled_rates;
1508}
1509
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001510static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1511 struct ieee80211_vif *vif,
1512 struct ieee80211_bss_conf *bss_conf,
1513 u32 changed)
1514{
1515 enum wl1271_cmd_ps_mode mode;
1516 struct wl1271 *wl = hw->priv;
1517 int ret;
1518
1519 wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
1520
1521 mutex_lock(&wl->mutex);
1522
1523 ret = wl1271_ps_elp_wakeup(wl, false);
1524 if (ret < 0)
1525 goto out;
1526
1527 if (changed & BSS_CHANGED_ASSOC) {
1528 if (bss_conf->assoc) {
1529 wl->aid = bss_conf->aid;
1530
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001531 /*
1532 * with wl1271, we don't need to update the
1533 * beacon_int and dtim_period, because the firmware
1534 * updates it by itself when the first beacon is
1535 * received after a join.
1536 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001537 ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
1538 if (ret < 0)
1539 goto out_sleep;
1540
1541 ret = wl1271_acx_aid(wl, wl->aid);
1542 if (ret < 0)
1543 goto out_sleep;
1544
1545 /* If we want to go in PSM but we're not there yet */
1546 if (wl->psm_requested && !wl->psm) {
1547 mode = STATION_POWER_SAVE_MODE;
1548 ret = wl1271_ps_set_mode(wl, mode);
1549 if (ret < 0)
1550 goto out_sleep;
1551 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001552 } else {
1553 /* use defaults when not associated */
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001554 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
1555 wl->aid = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001556 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001557
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001558 }
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001559
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001560 if (changed & BSS_CHANGED_ERP_SLOT) {
1561 if (bss_conf->use_short_slot)
1562 ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
1563 else
1564 ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
1565 if (ret < 0) {
1566 wl1271_warning("Set slot time failed %d", ret);
1567 goto out_sleep;
1568 }
1569 }
1570
1571 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1572 if (bss_conf->use_short_preamble)
1573 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
1574 else
1575 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
1576 }
1577
1578 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1579 if (bss_conf->use_cts_prot)
1580 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
1581 else
1582 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
1583 if (ret < 0) {
1584 wl1271_warning("Set ctsprotect failed %d", ret);
1585 goto out_sleep;
1586 }
1587 }
1588
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001589 if (changed & BSS_CHANGED_BASIC_RATES) {
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001590 wl->basic_rate_set = wl1271_enabled_rates_get(
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001591 wl, bss_conf->basic_rates);
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001592
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001593 ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001594 if (ret < 0) {
1595 wl1271_warning("Set rate policies failed %d", ret);
1596 goto out_sleep;
1597 }
1598 }
1599
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001600out_sleep:
1601 wl1271_ps_elp_sleep(wl);
1602
1603out:
1604 mutex_unlock(&wl->mutex);
1605}
1606
1607
1608/* can't be const, mac80211 writes to this */
1609static struct ieee80211_rate wl1271_rates[] = {
1610 { .bitrate = 10,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001611 .hw_value = CONF_HW_BIT_RATE_1MBPS,
1612 .hw_value_short = CONF_HW_BIT_RATE_1MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001613 { .bitrate = 20,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001614 .hw_value = CONF_HW_BIT_RATE_2MBPS,
1615 .hw_value_short = CONF_HW_BIT_RATE_2MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001616 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1617 { .bitrate = 55,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001618 .hw_value = CONF_HW_BIT_RATE_5_5MBPS,
1619 .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001620 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1621 { .bitrate = 110,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001622 .hw_value = CONF_HW_BIT_RATE_11MBPS,
1623 .hw_value_short = CONF_HW_BIT_RATE_11MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001624 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1625 { .bitrate = 60,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001626 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1627 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001628 { .bitrate = 90,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001629 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1630 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001631 { .bitrate = 120,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001632 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1633 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001634 { .bitrate = 180,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001635 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1636 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001637 { .bitrate = 240,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001638 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1639 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001640 { .bitrate = 360,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001641 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1642 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001643 { .bitrate = 480,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001644 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1645 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001646 { .bitrate = 540,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001647 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1648 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001649};
1650
1651/* can't be const, mac80211 writes to this */
1652static struct ieee80211_channel wl1271_channels[] = {
1653 { .hw_value = 1, .center_freq = 2412},
1654 { .hw_value = 2, .center_freq = 2417},
1655 { .hw_value = 3, .center_freq = 2422},
1656 { .hw_value = 4, .center_freq = 2427},
1657 { .hw_value = 5, .center_freq = 2432},
1658 { .hw_value = 6, .center_freq = 2437},
1659 { .hw_value = 7, .center_freq = 2442},
1660 { .hw_value = 8, .center_freq = 2447},
1661 { .hw_value = 9, .center_freq = 2452},
1662 { .hw_value = 10, .center_freq = 2457},
1663 { .hw_value = 11, .center_freq = 2462},
1664 { .hw_value = 12, .center_freq = 2467},
1665 { .hw_value = 13, .center_freq = 2472},
1666};
1667
1668/* can't be const, mac80211 writes to this */
1669static struct ieee80211_supported_band wl1271_band_2ghz = {
1670 .channels = wl1271_channels,
1671 .n_channels = ARRAY_SIZE(wl1271_channels),
1672 .bitrates = wl1271_rates,
1673 .n_bitrates = ARRAY_SIZE(wl1271_rates),
1674};
1675
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001676/* 5 GHz data rates for WL1273 */
1677static struct ieee80211_rate wl1271_rates_5ghz[] = {
1678 { .bitrate = 60,
1679 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1680 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
1681 { .bitrate = 90,
1682 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1683 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
1684 { .bitrate = 120,
1685 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1686 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
1687 { .bitrate = 180,
1688 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1689 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
1690 { .bitrate = 240,
1691 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1692 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
1693 { .bitrate = 360,
1694 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1695 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
1696 { .bitrate = 480,
1697 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1698 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
1699 { .bitrate = 540,
1700 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1701 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
1702};
1703
1704/* 5 GHz band channels for WL1273 */
1705static struct ieee80211_channel wl1271_channels_5ghz[] = {
1706 { .hw_value = 183, .center_freq = 4915},
1707 { .hw_value = 184, .center_freq = 4920},
1708 { .hw_value = 185, .center_freq = 4925},
1709 { .hw_value = 187, .center_freq = 4935},
1710 { .hw_value = 188, .center_freq = 4940},
1711 { .hw_value = 189, .center_freq = 4945},
1712 { .hw_value = 192, .center_freq = 4960},
1713 { .hw_value = 196, .center_freq = 4980},
1714 { .hw_value = 7, .center_freq = 5035},
1715 { .hw_value = 8, .center_freq = 5040},
1716 { .hw_value = 9, .center_freq = 5045},
1717 { .hw_value = 11, .center_freq = 5055},
1718 { .hw_value = 12, .center_freq = 5060},
1719 { .hw_value = 16, .center_freq = 5080},
1720 { .hw_value = 34, .center_freq = 5170},
1721 { .hw_value = 36, .center_freq = 5180},
1722 { .hw_value = 38, .center_freq = 5190},
1723 { .hw_value = 40, .center_freq = 5200},
1724 { .hw_value = 42, .center_freq = 5210},
1725 { .hw_value = 44, .center_freq = 5220},
1726 { .hw_value = 46, .center_freq = 5230},
1727 { .hw_value = 48, .center_freq = 5240},
1728 { .hw_value = 52, .center_freq = 5260},
1729 { .hw_value = 56, .center_freq = 5280},
1730 { .hw_value = 60, .center_freq = 5300},
1731 { .hw_value = 64, .center_freq = 5320},
1732 { .hw_value = 100, .center_freq = 5500},
1733 { .hw_value = 104, .center_freq = 5520},
1734 { .hw_value = 108, .center_freq = 5540},
1735 { .hw_value = 112, .center_freq = 5560},
1736 { .hw_value = 116, .center_freq = 5580},
1737 { .hw_value = 120, .center_freq = 5600},
1738 { .hw_value = 124, .center_freq = 5620},
1739 { .hw_value = 128, .center_freq = 5640},
1740 { .hw_value = 132, .center_freq = 5660},
1741 { .hw_value = 136, .center_freq = 5680},
1742 { .hw_value = 140, .center_freq = 5700},
1743 { .hw_value = 149, .center_freq = 5745},
1744 { .hw_value = 153, .center_freq = 5765},
1745 { .hw_value = 157, .center_freq = 5785},
1746 { .hw_value = 161, .center_freq = 5805},
1747 { .hw_value = 165, .center_freq = 5825},
1748};
1749
1750
1751static struct ieee80211_supported_band wl1271_band_5ghz = {
1752 .channels = wl1271_channels_5ghz,
1753 .n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
1754 .bitrates = wl1271_rates_5ghz,
1755 .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
1756};
1757
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001758static const struct ieee80211_ops wl1271_ops = {
1759 .start = wl1271_op_start,
1760 .stop = wl1271_op_stop,
1761 .add_interface = wl1271_op_add_interface,
1762 .remove_interface = wl1271_op_remove_interface,
1763 .config = wl1271_op_config,
1764/* .config_interface = wl1271_op_config_interface, */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001765 .prepare_multicast = wl1271_op_prepare_multicast,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001766 .configure_filter = wl1271_op_configure_filter,
1767 .tx = wl1271_op_tx,
1768 .set_key = wl1271_op_set_key,
1769 .hw_scan = wl1271_op_hw_scan,
1770 .bss_info_changed = wl1271_op_bss_info_changed,
1771 .set_rts_threshold = wl1271_op_set_rts_threshold,
1772};
1773
1774static int wl1271_register_hw(struct wl1271 *wl)
1775{
1776 int ret;
1777
1778 if (wl->mac80211_registered)
1779 return 0;
1780
1781 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1782
1783 ret = ieee80211_register_hw(wl->hw);
1784 if (ret < 0) {
1785 wl1271_error("unable to register mac80211 hw: %d", ret);
1786 return ret;
1787 }
1788
1789 wl->mac80211_registered = true;
1790
1791 wl1271_notice("loaded");
1792
1793 return 0;
1794}
1795
1796static int wl1271_init_ieee80211(struct wl1271 *wl)
1797{
Juuso Oikarinen1e2b7972009-10-08 21:56:20 +03001798 /* The tx descriptor buffer and the TKIP space. */
1799 wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
1800 sizeof(struct wl1271_tx_hw_descr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001801
1802 /* unit us */
1803 /* FIXME: find a proper value */
1804 wl->hw->channel_change_time = 10000;
1805
1806 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
Juuso Oikarinen19221672009-10-08 21:56:35 +03001807 IEEE80211_HW_NOISE_DBM |
1808 IEEE80211_HW_BEACON_FILTER;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001809
1810 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1811 wl->hw->wiphy->max_scan_ssids = 1;
1812 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
1813
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001814 if (wl1271_11a_enabled())
1815 wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
1816
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001817 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1818
1819 return 0;
1820}
1821
1822static void wl1271_device_release(struct device *dev)
1823{
1824
1825}
1826
1827static struct platform_device wl1271_device = {
1828 .name = "wl1271",
1829 .id = -1,
1830
1831 /* device model insists to have a release function */
1832 .dev = {
1833 .release = wl1271_device_release,
1834 },
1835};
1836
1837#define WL1271_DEFAULT_CHANNEL 0
1838static int __devinit wl1271_probe(struct spi_device *spi)
1839{
1840 struct wl12xx_platform_data *pdata;
1841 struct ieee80211_hw *hw;
1842 struct wl1271 *wl;
1843 int ret, i;
1844 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1845
1846 pdata = spi->dev.platform_data;
1847 if (!pdata) {
1848 wl1271_error("no platform data");
1849 return -ENODEV;
1850 }
1851
1852 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
1853 if (!hw) {
1854 wl1271_error("could not alloc ieee80211_hw");
1855 return -ENOMEM;
1856 }
1857
1858 wl = hw->priv;
1859 memset(wl, 0, sizeof(*wl));
1860
Juuso Oikarinen01c09162009-10-13 12:47:55 +03001861 INIT_LIST_HEAD(&wl->list);
1862
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001863 wl->hw = hw;
1864 dev_set_drvdata(&spi->dev, wl);
1865 wl->spi = spi;
1866
1867 skb_queue_head_init(&wl->tx_queue);
1868
1869 INIT_WORK(&wl->filter_work, wl1271_filter_work);
Juuso Oikarinen37b70a82009-10-08 21:56:21 +03001870 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001871 wl->channel = WL1271_DEFAULT_CHANNEL;
1872 wl->scanning = false;
1873 wl->default_key = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001874 wl->rx_counter = 0;
1875 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
1876 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
1877 wl->elp = false;
1878 wl->psm = 0;
1879 wl->psm_requested = false;
1880 wl->tx_queue_stopped = false;
1881 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001882 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001883 wl->band = IEEE80211_BAND_2GHZ;
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001884 wl->vif = NULL;
Luciano Coelhod6e19d12009-10-12 15:08:43 +03001885 wl->joined = false;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001886
Juuso Oikarinenbe7078c2009-10-08 21:56:26 +03001887 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001888 wl->tx_frames[i] = NULL;
1889
1890 spin_lock_init(&wl->wl_lock);
1891
1892 /*
1893 * In case our MAC address is not correctly set,
1894 * we use a random but Nokia MAC.
1895 */
1896 memcpy(wl->mac_addr, nokia_oui, 3);
1897 get_random_bytes(wl->mac_addr + 3, 3);
1898
1899 wl->state = WL1271_STATE_OFF;
1900 mutex_init(&wl->mutex);
1901
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001902 /* This is the only SPI value that we need to set here, the rest
1903 * comes from the board-peripherals file */
1904 spi->bits_per_word = 32;
1905
1906 ret = spi_setup(spi);
1907 if (ret < 0) {
1908 wl1271_error("spi_setup failed");
1909 goto out_free;
1910 }
1911
1912 wl->set_power = pdata->set_power;
1913 if (!wl->set_power) {
1914 wl1271_error("set power function missing in platform data");
1915 ret = -ENODEV;
1916 goto out_free;
1917 }
1918
1919 wl->irq = spi->irq;
1920 if (wl->irq < 0) {
1921 wl1271_error("irq missing in platform data");
1922 ret = -ENODEV;
1923 goto out_free;
1924 }
1925
1926 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
1927 if (ret < 0) {
1928 wl1271_error("request_irq() failed: %d", ret);
1929 goto out_free;
1930 }
1931
1932 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1933
1934 disable_irq(wl->irq);
1935
1936 ret = platform_device_register(&wl1271_device);
1937 if (ret) {
1938 wl1271_error("couldn't register platform device");
1939 goto out_irq;
1940 }
1941 dev_set_drvdata(&wl1271_device.dev, wl);
1942
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001943 /* Apply default driver configuration. */
1944 wl1271_conf_init(wl);
1945
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001946 ret = wl1271_init_ieee80211(wl);
1947 if (ret)
1948 goto out_platform;
1949
1950 ret = wl1271_register_hw(wl);
1951 if (ret)
1952 goto out_platform;
1953
1954 wl1271_debugfs_init(wl);
1955
1956 wl1271_notice("initialized");
1957
1958 return 0;
1959
1960 out_platform:
1961 platform_device_unregister(&wl1271_device);
1962
1963 out_irq:
1964 free_irq(wl->irq, wl);
1965
1966 out_free:
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001967 ieee80211_free_hw(hw);
1968
1969 return ret;
1970}
1971
1972static int __devexit wl1271_remove(struct spi_device *spi)
1973{
1974 struct wl1271 *wl = dev_get_drvdata(&spi->dev);
1975
1976 ieee80211_unregister_hw(wl->hw);
1977
1978 wl1271_debugfs_exit(wl);
1979 platform_device_unregister(&wl1271_device);
1980 free_irq(wl->irq, wl);
1981 kfree(wl->target_mem_map);
Juuso Oikarinen1fba4972009-10-08 21:56:32 +03001982 vfree(wl->fw);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001983 wl->fw = NULL;
1984 kfree(wl->nvs);
1985 wl->nvs = NULL;
1986
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001987 kfree(wl->fw_status);
1988 kfree(wl->tx_res_if);
1989
1990 ieee80211_free_hw(wl->hw);
1991
1992 return 0;
1993}
1994
1995
1996static struct spi_driver wl1271_spi_driver = {
1997 .driver = {
1998 .name = "wl1271",
1999 .bus = &spi_bus_type,
2000 .owner = THIS_MODULE,
2001 },
2002
2003 .probe = wl1271_probe,
2004 .remove = __devexit_p(wl1271_remove),
2005};
2006
2007static int __init wl1271_init(void)
2008{
2009 int ret;
2010
2011 ret = spi_register_driver(&wl1271_spi_driver);
2012 if (ret < 0) {
2013 wl1271_error("failed to register spi driver: %d", ret);
2014 goto out;
2015 }
2016
2017out:
2018 return ret;
2019}
2020
2021static void __exit wl1271_exit(void)
2022{
2023 spi_unregister_driver(&wl1271_spi_driver);
2024
2025 wl1271_notice("unloaded");
2026}
2027
2028module_init(wl1271_init);
2029module_exit(wl1271_exit);
2030
2031MODULE_LICENSE("GPL");
2032MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
Luciano Coelho2f018722009-10-08 21:56:27 +03002033MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");