blob: ae41a70955086188f6590ae63beecde65a6d3ef9 [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>
35
36#include "wl1271.h"
37#include "wl12xx_80211.h"
38#include "wl1271_reg.h"
39#include "wl1271_spi.h"
40#include "wl1271_event.h"
41#include "wl1271_tx.h"
42#include "wl1271_rx.h"
43#include "wl1271_ps.h"
44#include "wl1271_init.h"
45#include "wl1271_debugfs.h"
46#include "wl1271_cmd.h"
47#include "wl1271_boot.h"
48
Juuso Oikarinen8a080482009-10-13 12:47:44 +030049static struct conf_drv_settings default_conf = {
50 .sg = {
51 .per_threshold = 7500,
52 .max_scan_compensation_time = 120000,
53 .nfs_sample_interval = 400,
54 .load_ratio = 50,
55 .auto_ps_mode = 0,
56 .probe_req_compensation = 170,
57 .scan_window_compensation = 50,
58 .antenna_config = 0,
59 .beacon_miss_threshold = 60,
60 .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS,
61 .rate_adaptation_snr = 0
62 },
63 .rx = {
64 .rx_msdu_life_time = 512000,
65 .packet_detection_threshold = 0,
66 .ps_poll_timeout = 15,
67 .upsd_timeout = 15,
68 .rts_threshold = 2347,
69 .rx_cca_threshold = 0xFFEF,
70 .irq_blk_threshold = 0,
71 .irq_pkt_threshold = USHORT_MAX,
72 .irq_timeout = 5,
73 .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
74 },
75 .tx = {
76 .tx_energy_detection = 0,
77 .rc_conf = {
78 .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED,
79 .short_retry_limit = 10,
80 .long_retry_limit = 10,
81 .aflags = 0
82 },
83 .ac_conf_count = 4,
84 .ac_conf = {
85 [0] = {
86 .ac = CONF_TX_AC_BE,
87 .cw_min = 15,
88 .cw_max = 63,
89 .aifsn = 3,
90 .tx_op_limit = 0,
91 },
92 [1] = {
93 .ac = CONF_TX_AC_BK,
94 .cw_min = 15,
95 .cw_max = 63,
96 .aifsn = 7,
97 .tx_op_limit = 0,
98 },
99 [2] = {
100 .ac = CONF_TX_AC_VI,
101 .cw_min = 15,
102 .cw_max = 63,
103 .aifsn = CONF_TX_AIFS_PIFS,
104 .tx_op_limit = 3008,
105 },
106 [3] = {
107 .ac = CONF_TX_AC_VO,
108 .cw_min = 15,
109 .cw_max = 63,
110 .aifsn = CONF_TX_AIFS_PIFS,
111 .tx_op_limit = 1504,
112 },
113 },
114 .tid_conf_count = 7,
115 .tid_conf = {
116 [0] = {
117 .queue_id = 0,
118 .channel_type = CONF_CHANNEL_TYPE_DCF,
119 .tsid = CONF_TX_AC_BE,
120 .ps_scheme = CONF_PS_SCHEME_LEGACY,
121 .ack_policy = CONF_ACK_POLICY_LEGACY,
122 .apsd_conf = {0, 0},
123 },
124 [1] = {
125 .queue_id = 1,
126 .channel_type = CONF_CHANNEL_TYPE_DCF,
127 .tsid = CONF_TX_AC_BE,
128 .ps_scheme = CONF_PS_SCHEME_LEGACY,
129 .ack_policy = CONF_ACK_POLICY_LEGACY,
130 .apsd_conf = {0, 0},
131 },
132 [2] = {
133 .queue_id = 2,
134 .channel_type = CONF_CHANNEL_TYPE_DCF,
135 .tsid = CONF_TX_AC_BE,
136 .ps_scheme = CONF_PS_SCHEME_LEGACY,
137 .ack_policy = CONF_ACK_POLICY_LEGACY,
138 .apsd_conf = {0, 0},
139 },
140 [3] = {
141 .queue_id = 3,
142 .channel_type = CONF_CHANNEL_TYPE_DCF,
143 .tsid = CONF_TX_AC_BE,
144 .ps_scheme = CONF_PS_SCHEME_LEGACY,
145 .ack_policy = CONF_ACK_POLICY_LEGACY,
146 .apsd_conf = {0, 0},
147 },
148 [4] = {
149 .queue_id = 4,
150 .channel_type = CONF_CHANNEL_TYPE_DCF,
151 .tsid = CONF_TX_AC_BE,
152 .ps_scheme = CONF_PS_SCHEME_LEGACY,
153 .ack_policy = CONF_ACK_POLICY_LEGACY,
154 .apsd_conf = {0, 0},
155 },
156 [5] = {
157 .queue_id = 5,
158 .channel_type = CONF_CHANNEL_TYPE_DCF,
159 .tsid = CONF_TX_AC_BE,
160 .ps_scheme = CONF_PS_SCHEME_LEGACY,
161 .ack_policy = CONF_ACK_POLICY_LEGACY,
162 .apsd_conf = {0, 0},
163 },
164 [6] = {
165 .queue_id = 6,
166 .channel_type = CONF_CHANNEL_TYPE_DCF,
167 .tsid = CONF_TX_AC_BE,
168 .ps_scheme = CONF_PS_SCHEME_LEGACY,
169 .ack_policy = CONF_ACK_POLICY_LEGACY,
170 .apsd_conf = {0, 0},
171 }
172 },
173 .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
174 .tx_compl_timeout = 5,
175 .tx_compl_threshold = 5
176 },
177 .conn = {
178 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
179 .listen_interval = 0,
180 .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
181 .bcn_filt_ie_count = 1,
182 .bcn_filt_ie = {
183 [0] = {
184 .ie = WLAN_EID_CHANNEL_SWITCH,
185 .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
186 }
187 },
188 .synch_fail_thold = 5,
189 .bss_lose_timeout = 100,
190 .beacon_rx_timeout = 10000,
191 .broadcast_timeout = 20000,
192 .rx_broadcast_in_ps = 1,
193 .ps_poll_threshold = 4,
194 .sig_trigger_count = 2,
195 .sig_trigger = {
196 [0] = {
197 .threshold = -75,
198 .pacing = 500,
199 .metric = CONF_TRIG_METRIC_RSSI_BEACON,
200 .type = CONF_TRIG_EVENT_TYPE_EDGE,
201 .direction = CONF_TRIG_EVENT_DIR_LOW,
202 .hysteresis = 2,
203 .index = 0,
204 .enable = 1
205 },
206 [1] = {
207 .threshold = -75,
208 .pacing = 500,
209 .metric = CONF_TRIG_METRIC_RSSI_BEACON,
210 .type = CONF_TRIG_EVENT_TYPE_EDGE,
211 .direction = CONF_TRIG_EVENT_DIR_HIGH,
212 .hysteresis = 2,
213 .index = 1,
214 .enable = 1
215 }
216 },
217 .sig_weights = {
218 .rssi_bcn_avg_weight = 10,
219 .rssi_pkt_avg_weight = 10,
220 .snr_bcn_avg_weight = 10,
221 .snr_pkt_avg_weight = 10
Juuso Oikarinen11f70f92009-10-13 12:47:46 +0300222 },
223 .bet_enable = CONF_BET_MODE_ENABLE,
224 .bet_max_consecutive = 100
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300225 },
226 .init = {
227 .sr_err_tbl = {
228 [0] = {
229 .len = 7,
230 .upper_limit = 0x03,
231 .values = {
232 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
233 0x00 }
234 },
235 [1] = {
236 .len = 7,
237 .upper_limit = 0x03,
238 .values = {
239 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8,
240 0x00 }
241 },
242 [2] = {
243 .len = 7,
244 .upper_limit = 0x03,
245 .values = {
246 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
247 0x00 }
248 }
249 },
250 .sr_enable = 1,
251 .genparam = {
252 /*
253 * FIXME: The correct value CONF_REF_CLK_38_4_E
254 * causes the firmware to crash on boot.
255 * The value 5 apparently is an
256 * unnoficial XTAL configuration of the
257 * same frequency, which appears to work.
258 */
259 .ref_clk = 5,
260 .settling_time = 5,
261 .clk_valid_on_wakeup = 0,
262 .dc2dcmode = 0,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300263 .single_dual_band = CONF_SINGLE_BAND,
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300264 .tx_bip_fem_autodetect = 0,
265 .tx_bip_fem_manufacturer = 1,
266 .settings = 1,
267 },
268 .radioparam = {
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300269 .rx_trace_loss = 10,
270 .tx_trace_loss = 10,
271 .rx_rssi_and_proc_compens = {
272 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
273 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
274 0x00, 0x0a, 0x14 },
275 .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
276 .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
277 .rx_rssi_and_proc_compens_5 = {
278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x00 },
281 .tx_ref_pd_voltage = 0x24e,
282 .tx_ref_power = 0x78,
283 .tx_offset_db = 0x0,
284 .tx_rate_limits_normal = {
285 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
286 .tx_rate_limits_degraded = {
287 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
288 .tx_channel_limits_11b = {
289 0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
290 0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
291 0x22, 0x50 },
292 .tx_channel_limits_ofdm = {
293 0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
294 0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
295 0x20, 0x50 },
296 .tx_pdv_rate_offsets = {
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
298 .tx_ibias = {
299 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
300 .rx_fem_insertion_loss = 0x14,
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300301 .tx_ref_pd_voltage_5 = {
302 0x0190, 0x01a4, 0x01c3, 0x01d8,
303 0x020a, 0x021c },
304 .tx_ref_power_5 = {
305 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
306 .tx_offset_db_5 = {
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300308 .tx_rate_limits_normal_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300309 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300310 .tx_rate_limits_degraded_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300311 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300312 .tx_channel_limits_ofdm_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300313 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
314 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 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300318 .tx_pdv_rate_offsets_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300319 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300320 .tx_ibias_5 = {
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300321 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
322 .rx_fem_insertion_loss_5 = {
323 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300324 }
325 }
326};
327
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300328static void wl1271_conf_init(struct wl1271 *wl)
329{
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300330
331 /*
332 * This function applies the default configuration to the driver. This
333 * function is invoked upon driver load (spi probe.)
334 *
335 * The configuration is stored in a run-time structure in order to
336 * facilitate for run-time adjustment of any of the parameters. Making
337 * changes to the configuration structure will apply the new values on
338 * the next interface up (wl1271_op_start.)
339 */
340
341 /* apply driver default configuration */
Juuso Oikarinen8a080482009-10-13 12:47:44 +0300342 memcpy(&wl->conf, &default_conf, sizeof(default_conf));
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +0300343
344 if (wl1271_11a_enabled())
345 wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +0300346}
347
348
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300349static int wl1271_plt_init(struct wl1271 *wl)
350{
351 int ret;
352
353 ret = wl1271_acx_init_mem_config(wl);
354 if (ret < 0)
355 return ret;
356
357 ret = wl1271_cmd_data_path(wl, wl->channel, 1);
358 if (ret < 0)
359 return ret;
360
361 return 0;
362}
363
364static void wl1271_disable_interrupts(struct wl1271 *wl)
365{
366 disable_irq(wl->irq);
367}
368
369static void wl1271_power_off(struct wl1271 *wl)
370{
371 wl->set_power(false);
372}
373
374static void wl1271_power_on(struct wl1271 *wl)
375{
376 wl->set_power(true);
377}
378
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300379static void wl1271_fw_status(struct wl1271 *wl,
380 struct wl1271_fw_status *status)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300381{
382 u32 total = 0;
383 int i;
384
Juuso Oikarinen74621412009-10-12 15:08:54 +0300385 wl1271_spi_read(wl, FW_STATUS_ADDR, status,
386 sizeof(*status), false);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300387
388 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
389 "drv_rx_counter = %d, tx_results_counter = %d)",
390 status->intr,
391 status->fw_rx_counter,
392 status->drv_rx_counter,
393 status->tx_results_counter);
394
395 /* update number of available TX blocks */
396 for (i = 0; i < NUM_TX_QUEUES; i++) {
397 u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
398 wl->tx_blocks_freed[i] = status->tx_released_blks[i];
399 wl->tx_blocks_available += cnt;
400 total += cnt;
401 }
402
403 /* if more blocks are available now, schedule some tx work */
404 if (total && !skb_queue_empty(&wl->tx_queue))
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300405 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300406
407 /* update the host-chipset time offset */
408 wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
409}
410
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300411static void wl1271_irq_work(struct work_struct *work)
412{
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300413 int ret;
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300414 u32 intr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300415 struct wl1271 *wl =
416 container_of(work, struct wl1271, irq_work);
417
418 mutex_lock(&wl->mutex);
419
420 wl1271_debug(DEBUG_IRQ, "IRQ work");
421
422 if (wl->state == WL1271_STATE_OFF)
423 goto out;
424
425 ret = wl1271_ps_elp_wakeup(wl, true);
426 if (ret < 0)
427 goto out;
428
Juuso Oikarinen74621412009-10-12 15:08:54 +0300429 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300430
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300431 wl1271_fw_status(wl, wl->fw_status);
432 intr = wl->fw_status->intr;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300433 if (!intr) {
434 wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
435 goto out_sleep;
436 }
437
438 intr &= WL1271_INTR_MASK;
439
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300440 if (intr & (WL1271_ACX_INTR_EVENT_A |
441 WL1271_ACX_INTR_EVENT_B)) {
442 wl1271_debug(DEBUG_IRQ,
443 "WL1271_ACX_INTR_EVENT (0x%x)", intr);
444 if (intr & WL1271_ACX_INTR_EVENT_A)
445 wl1271_event_handle(wl, 0);
446 else
447 wl1271_event_handle(wl, 1);
448 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300449
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300450 if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
451 wl1271_debug(DEBUG_IRQ,
452 "WL1271_ACX_INTR_INIT_COMPLETE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300453
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300454 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
455 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300456
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300457 if (intr & WL1271_ACX_INTR_DATA) {
458 u8 tx_res_cnt = wl->fw_status->tx_results_counter -
459 wl->tx_results_count;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300460
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300461 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300462
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300463 /* check for tx results */
464 if (tx_res_cnt)
465 wl1271_tx_complete(wl, tx_res_cnt);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300466
Juuso Oikarinenc15f63b2009-10-12 15:08:50 +0300467 wl1271_rx(wl, wl->fw_status);
468 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300469
470out_sleep:
Juuso Oikarinen74621412009-10-12 15:08:54 +0300471 wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
Luciano Coelho73d0a132009-08-11 11:58:27 +0300472 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300473 wl1271_ps_elp_sleep(wl);
474
475out:
476 mutex_unlock(&wl->mutex);
477}
478
479static irqreturn_t wl1271_irq(int irq, void *cookie)
480{
481 struct wl1271 *wl;
482 unsigned long flags;
483
484 wl1271_debug(DEBUG_IRQ, "IRQ");
485
486 wl = cookie;
487
488 /* complete the ELP completion */
489 spin_lock_irqsave(&wl->wl_lock, flags);
490 if (wl->elp_compl) {
491 complete(wl->elp_compl);
492 wl->elp_compl = NULL;
493 }
494
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300495 ieee80211_queue_work(wl->hw, &wl->irq_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300496 spin_unlock_irqrestore(&wl->wl_lock, flags);
497
498 return IRQ_HANDLED;
499}
500
501static int wl1271_fetch_firmware(struct wl1271 *wl)
502{
503 const struct firmware *fw;
504 int ret;
505
506 ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
507
508 if (ret < 0) {
509 wl1271_error("could not get firmware: %d", ret);
510 return ret;
511 }
512
513 if (fw->size % 4) {
514 wl1271_error("firmware size is not multiple of 32 bits: %zu",
515 fw->size);
516 ret = -EILSEQ;
517 goto out;
518 }
519
520 wl->fw_len = fw->size;
Juuso Oikarinen1fba4972009-10-08 21:56:32 +0300521 wl->fw = vmalloc(wl->fw_len);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300522
523 if (!wl->fw) {
524 wl1271_error("could not allocate memory for the firmware");
525 ret = -ENOMEM;
526 goto out;
527 }
528
529 memcpy(wl->fw, fw->data, wl->fw_len);
530
531 ret = 0;
532
533out:
534 release_firmware(fw);
535
536 return ret;
537}
538
539static int wl1271_fetch_nvs(struct wl1271 *wl)
540{
541 const struct firmware *fw;
542 int ret;
543
544 ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
545
546 if (ret < 0) {
547 wl1271_error("could not get nvs file: %d", ret);
548 return ret;
549 }
550
551 if (fw->size % 4) {
552 wl1271_error("nvs size is not multiple of 32 bits: %zu",
553 fw->size);
554 ret = -EILSEQ;
555 goto out;
556 }
557
558 wl->nvs_len = fw->size;
559 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
560
561 if (!wl->nvs) {
562 wl1271_error("could not allocate memory for the nvs file");
563 ret = -ENOMEM;
564 goto out;
565 }
566
567 memcpy(wl->nvs, fw->data, wl->nvs_len);
568
569 ret = 0;
570
571out:
572 release_firmware(fw);
573
574 return ret;
575}
576
577static void wl1271_fw_wakeup(struct wl1271 *wl)
578{
579 u32 elp_reg;
580
581 elp_reg = ELPCTRL_WAKE_UP;
Juuso Oikarinen74621412009-10-12 15:08:54 +0300582 wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300583}
584
585static int wl1271_setup(struct wl1271 *wl)
586{
587 wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
588 if (!wl->fw_status)
589 return -ENOMEM;
590
591 wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
592 if (!wl->tx_res_if) {
593 kfree(wl->fw_status);
594 return -ENOMEM;
595 }
596
597 INIT_WORK(&wl->irq_work, wl1271_irq_work);
598 INIT_WORK(&wl->tx_work, wl1271_tx_work);
599 return 0;
600}
601
602static int wl1271_chip_wakeup(struct wl1271 *wl)
603{
Juuso Oikarinen451de972009-10-12 15:08:46 +0300604 struct wl1271_partition_set partition;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300605 int ret = 0;
606
607 wl1271_power_on(wl);
608 msleep(WL1271_POWER_ON_SLEEP);
609 wl1271_spi_reset(wl);
610 wl1271_spi_init(wl);
611
612 /* We don't need a real memory partition here, because we only want
613 * to use the registers at this point. */
Juuso Oikarinen451de972009-10-12 15:08:46 +0300614 memset(&partition, 0, sizeof(partition));
615 partition.reg.start = REGISTERS_BASE;
616 partition.reg.size = REGISTERS_DOWN_SIZE;
617 wl1271_set_partition(wl, &partition);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300618
619 /* ELP module wake up */
620 wl1271_fw_wakeup(wl);
621
622 /* whal_FwCtrl_BootSm() */
623
624 /* 0. read chip id from CHIP_ID */
Juuso Oikarinen74621412009-10-12 15:08:54 +0300625 wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300626
627 /* 1. check if chip id is valid */
628
629 switch (wl->chip.id) {
630 case CHIP_ID_1271_PG10:
631 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
632 wl->chip.id);
633
634 ret = wl1271_setup(wl);
635 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300636 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300637 break;
638 case CHIP_ID_1271_PG20:
639 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
640 wl->chip.id);
641
642 ret = wl1271_setup(wl);
643 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300644 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300645 break;
646 default:
647 wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
648 ret = -ENODEV;
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300649 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300650 }
651
652 if (wl->fw == NULL) {
653 ret = wl1271_fetch_firmware(wl);
654 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300655 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300656 }
657
658 /* No NVS from netlink, try to get it from the filesystem */
659 if (wl->nvs == NULL) {
660 ret = wl1271_fetch_nvs(wl);
661 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300662 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300663 }
664
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300665 goto out;
666
667out_power_off:
668 wl1271_power_off(wl);
669
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300670out:
671 return ret;
672}
673
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300674struct wl1271_filter_params {
675 unsigned int filters;
676 unsigned int changed;
677 int mc_list_length;
678 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
679};
680
681#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
682 FIF_ALLMULTI | \
683 FIF_FCSFAIL | \
684 FIF_BCN_PRBRESP_PROMISC | \
685 FIF_CONTROL | \
686 FIF_OTHER_BSS)
687
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300688static void wl1271_filter_work(struct work_struct *work)
689{
690 struct wl1271 *wl =
691 container_of(work, struct wl1271, filter_work);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300692 struct wl1271_filter_params *fp;
693 unsigned long flags;
694 bool enabled = true;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300695 int ret;
696
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300697 /* first, get the filter parameters */
698 spin_lock_irqsave(&wl->wl_lock, flags);
699 fp = wl->filter_params;
700 wl->filter_params = NULL;
701 spin_unlock_irqrestore(&wl->wl_lock, flags);
702
703 if (!fp)
704 return;
705
706 /* then, lock the mutex without risk of lock-up */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300707 mutex_lock(&wl->mutex);
708
709 if (wl->state == WL1271_STATE_OFF)
710 goto out;
711
712 ret = wl1271_ps_elp_wakeup(wl, false);
713 if (ret < 0)
714 goto out;
715
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300716 /* configure the mc filter regardless of the changed flags */
717 if (fp->filters & FIF_ALLMULTI)
718 enabled = false;
719
720 ret = wl1271_acx_group_address_tbl(wl, enabled,
721 fp->mc_list, fp->mc_list_length);
722 if (ret < 0)
723 goto out_sleep;
724
725 /* determine, whether supported filter values have changed */
726 if (fp->changed == 0)
727 goto out;
728
729 /* apply configured filters */
Luciano Coelho0535d9f2009-10-12 15:08:56 +0300730 ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300731 if (ret < 0)
732 goto out_sleep;
733
734out_sleep:
735 wl1271_ps_elp_sleep(wl);
736
737out:
738 mutex_unlock(&wl->mutex);
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300739 kfree(fp);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300740}
741
742int wl1271_plt_start(struct wl1271 *wl)
743{
744 int ret;
745
746 mutex_lock(&wl->mutex);
747
748 wl1271_notice("power up");
749
750 if (wl->state != WL1271_STATE_OFF) {
751 wl1271_error("cannot go into PLT state because not "
752 "in off state: %d", wl->state);
753 ret = -EBUSY;
754 goto out;
755 }
756
757 wl->state = WL1271_STATE_PLT;
758
759 ret = wl1271_chip_wakeup(wl);
760 if (ret < 0)
761 goto out;
762
763 ret = wl1271_boot(wl);
764 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300765 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300766
767 wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
768
769 ret = wl1271_plt_init(wl);
770 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300771 goto out_irq_disable;
772
773 goto out;
774
775out_irq_disable:
776 wl1271_disable_interrupts(wl);
777
778out_power_off:
779 wl1271_power_off(wl);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300780
781out:
782 mutex_unlock(&wl->mutex);
783
784 return ret;
785}
786
787int wl1271_plt_stop(struct wl1271 *wl)
788{
789 int ret = 0;
790
791 mutex_lock(&wl->mutex);
792
793 wl1271_notice("power down");
794
795 if (wl->state != WL1271_STATE_PLT) {
796 wl1271_error("cannot power down because not in PLT "
797 "state: %d", wl->state);
798 ret = -EBUSY;
799 goto out;
800 }
801
802 wl1271_disable_interrupts(wl);
803 wl1271_power_off(wl);
804
805 wl->state = WL1271_STATE_OFF;
806
807out:
808 mutex_unlock(&wl->mutex);
809
810 return ret;
811}
812
813
814static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
815{
816 struct wl1271 *wl = hw->priv;
817
818 skb_queue_tail(&wl->tx_queue, skb);
819
820 /*
821 * The chip specific setup must run before the first TX packet -
822 * before that, the tx_work will not be initialized!
823 */
824
Juuso Oikarinena64b07e2009-10-08 21:56:29 +0300825 ieee80211_queue_work(wl->hw, &wl->tx_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300826
827 /*
828 * The workqueue is slow to process the tx_queue and we need stop
829 * the queue here, otherwise the queue will get too long.
830 */
831 if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
832 ieee80211_stop_queues(wl->hw);
833
834 /*
835 * FIXME: this is racy, the variable is not properly
836 * protected. Maybe fix this by removing the stupid
837 * variable altogether and checking the real queue state?
838 */
839 wl->tx_queue_stopped = true;
840 }
841
842 return NETDEV_TX_OK;
843}
844
845static int wl1271_op_start(struct ieee80211_hw *hw)
846{
847 struct wl1271 *wl = hw->priv;
848 int ret = 0;
849
850 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
851
852 mutex_lock(&wl->mutex);
853
854 if (wl->state != WL1271_STATE_OFF) {
855 wl1271_error("cannot start because not in off state: %d",
856 wl->state);
857 ret = -EBUSY;
858 goto out;
859 }
860
861 ret = wl1271_chip_wakeup(wl);
862 if (ret < 0)
863 goto out;
864
865 ret = wl1271_boot(wl);
866 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300867 goto out_power_off;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300868
869 ret = wl1271_hw_init(wl);
870 if (ret < 0)
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300871 goto out_irq_disable;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300872
873 wl->state = WL1271_STATE_ON;
874
875 wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
876
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300877 goto out;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300878
Juuso Oikarineneb5b28d2009-10-13 12:47:45 +0300879out_irq_disable:
880 wl1271_disable_interrupts(wl);
881
882out_power_off:
883 wl1271_power_off(wl);
884
885out:
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300886 mutex_unlock(&wl->mutex);
887
888 return ret;
889}
890
891static void wl1271_op_stop(struct ieee80211_hw *hw)
892{
893 struct wl1271 *wl = hw->priv;
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300894 unsigned long flags;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300895 int i;
896
897 wl1271_info("down");
898
899 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
900
Juuso Oikarinenc87dec92009-10-08 21:56:31 +0300901 /* complete/cancel ongoing work */
902 cancel_work_sync(&wl->filter_work);
903 spin_lock_irqsave(&wl->wl_lock, flags);
904 kfree(wl->filter_params);
905 wl->filter_params = NULL;
906 spin_unlock_irqrestore(&wl->wl_lock, flags);
907
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300908 mutex_lock(&wl->mutex);
909
910 WARN_ON(wl->state != WL1271_STATE_ON);
911
912 if (wl->scanning) {
913 mutex_unlock(&wl->mutex);
914 ieee80211_scan_completed(wl->hw, true);
915 mutex_lock(&wl->mutex);
916 wl->scanning = false;
917 }
918
919 wl->state = WL1271_STATE_OFF;
920
921 wl1271_disable_interrupts(wl);
922
923 mutex_unlock(&wl->mutex);
924
925 cancel_work_sync(&wl->irq_work);
926 cancel_work_sync(&wl->tx_work);
927 cancel_work_sync(&wl->filter_work);
928
929 mutex_lock(&wl->mutex);
930
931 /* let's notify MAC80211 about the remaining pending TX frames */
932 wl1271_tx_flush(wl);
933 wl1271_power_off(wl);
934
935 memset(wl->bssid, 0, ETH_ALEN);
936 memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
937 wl->ssid_len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300938 wl->bss_type = MAX_BSS_TYPE;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +0300939 wl->band = IEEE80211_BAND_2GHZ;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300940
941 wl->rx_counter = 0;
942 wl->elp = false;
943 wl->psm = 0;
944 wl->tx_queue_stopped = false;
945 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
946 wl->tx_blocks_available = 0;
947 wl->tx_results_count = 0;
948 wl->tx_packets_count = 0;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +0300949 wl->tx_security_last_seq = 0;
950 wl->tx_security_seq_16 = 0;
951 wl->tx_security_seq_32 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300952 wl->time_offset = 0;
953 wl->session_counter = 0;
Luciano Coelhod6e19d12009-10-12 15:08:43 +0300954 wl->joined = false;
955
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300956 for (i = 0; i < NUM_TX_QUEUES; i++)
957 wl->tx_blocks_freed[i] = 0;
958
959 wl1271_debugfs_reset(wl);
960 mutex_unlock(&wl->mutex);
961}
962
963static int wl1271_op_add_interface(struct ieee80211_hw *hw,
964 struct ieee80211_if_init_conf *conf)
965{
966 struct wl1271 *wl = hw->priv;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300967 int ret = 0;
968
John W. Linvillee5539bc2009-08-18 10:50:34 -0400969 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
970 conf->type, conf->mac_addr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300971
972 mutex_lock(&wl->mutex);
Juuso Oikarinenb771eee2009-10-08 21:56:34 +0300973 if (wl->vif) {
974 ret = -EBUSY;
975 goto out;
976 }
977
978 wl->vif = conf->vif;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +0300979
980 switch (conf->type) {
981 case NL80211_IFTYPE_STATION:
982 wl->bss_type = BSS_TYPE_STA_BSS;
983 break;
984 case NL80211_IFTYPE_ADHOC:
985 wl->bss_type = BSS_TYPE_IBSS;
986 break;
987 default:
988 ret = -EOPNOTSUPP;
989 goto out;
990 }
991
992 /* FIXME: what if conf->mac_addr changes? */
993
994out:
995 mutex_unlock(&wl->mutex);
996 return ret;
997}
998
999static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1000 struct ieee80211_if_init_conf *conf)
1001{
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001002 struct wl1271 *wl = hw->priv;
1003
1004 mutex_lock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001005 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001006 wl->vif = NULL;
1007 mutex_unlock(&wl->mutex);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001008}
1009
1010#if 0
1011static int wl1271_op_config_interface(struct ieee80211_hw *hw,
1012 struct ieee80211_vif *vif,
1013 struct ieee80211_if_conf *conf)
1014{
1015 struct wl1271 *wl = hw->priv;
1016 struct sk_buff *beacon;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001017 int ret;
1018
David S. Miller32646902009-09-17 10:18:30 -07001019 wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM",
1020 conf->bssid);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001021 wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
1022 conf->ssid_len);
1023
1024 mutex_lock(&wl->mutex);
1025
1026 ret = wl1271_ps_elp_wakeup(wl, false);
1027 if (ret < 0)
1028 goto out;
1029
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001030 if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) {
1031 wl1271_debug(DEBUG_MAC80211, "bssid changed");
1032
1033 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
1034
1035 ret = wl1271_cmd_join(wl);
1036 if (ret < 0)
1037 goto out_sleep;
1038 }
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001039
1040 ret = wl1271_cmd_build_null_data(wl);
1041 if (ret < 0)
1042 goto out_sleep;
1043
1044 wl->ssid_len = conf->ssid_len;
1045 if (wl->ssid_len)
1046 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
1047
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001048 if (conf->changed & IEEE80211_IFCC_BEACON) {
1049 beacon = ieee80211_beacon_get(hw, vif);
1050 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
1051 beacon->data, beacon->len);
1052
1053 if (ret < 0) {
1054 dev_kfree_skb(beacon);
1055 goto out_sleep;
1056 }
1057
1058 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
1059 beacon->data, beacon->len);
1060
1061 dev_kfree_skb(beacon);
1062
1063 if (ret < 0)
1064 goto out_sleep;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001065 }
1066
1067out_sleep:
1068 wl1271_ps_elp_sleep(wl);
1069
1070out:
1071 mutex_unlock(&wl->mutex);
1072
1073 return ret;
1074}
1075#endif
1076
1077static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
1078{
1079 struct wl1271 *wl = hw->priv;
1080 struct ieee80211_conf *conf = &hw->conf;
1081 int channel, ret = 0;
1082
1083 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
1084
1085 wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
1086 channel,
1087 conf->flags & IEEE80211_CONF_PS ? "on" : "off",
1088 conf->power_level);
1089
1090 mutex_lock(&wl->mutex);
1091
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001092 wl->band = conf->channel->band;
1093
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001094 ret = wl1271_ps_elp_wakeup(wl, false);
1095 if (ret < 0)
1096 goto out;
1097
1098 if (channel != wl->channel) {
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001099 /*
1100 * We assume that the stack will configure the right channel
1101 * before associating, so we don't need to send a join
1102 * command here. We will join the right channel when the
1103 * BSSID changes
1104 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001105 wl->channel = channel;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001106 }
1107
1108 ret = wl1271_cmd_build_null_data(wl);
1109 if (ret < 0)
1110 goto out_sleep;
1111
1112 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
1113 wl1271_info("psm enabled");
1114
1115 wl->psm_requested = true;
1116
1117 /*
1118 * We enter PSM only if we're already associated.
1119 * If we're not, we'll enter it when joining an SSID,
1120 * through the bss_info_changed() hook.
1121 */
1122 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
1123 } else if (!(conf->flags & IEEE80211_CONF_PS) &&
1124 wl->psm_requested) {
1125 wl1271_info("psm disabled");
1126
1127 wl->psm_requested = false;
1128
1129 if (wl->psm)
1130 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
1131 }
1132
1133 if (conf->power_level != wl->power_level) {
1134 ret = wl1271_acx_tx_power(wl, conf->power_level);
1135 if (ret < 0)
1136 goto out;
1137
1138 wl->power_level = conf->power_level;
1139 }
1140
1141out_sleep:
1142 wl1271_ps_elp_sleep(wl);
1143
1144out:
1145 mutex_unlock(&wl->mutex);
1146
1147 return ret;
1148}
1149
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001150static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
1151 struct dev_addr_list *mc_list)
1152{
1153 struct wl1271 *wl = hw->priv;
1154 struct wl1271_filter_params *fp;
1155 unsigned long flags;
1156 int i;
1157
1158 /*
1159 * FIXME: we should return a hash that will be passed to
1160 * configure_filter() instead of saving everything in the context.
1161 */
1162
1163 fp = kzalloc(sizeof(*fp), GFP_KERNEL);
1164 if (!fp) {
1165 wl1271_error("Out of memory setting filters.");
1166 return 0;
1167 }
1168
1169 /* update multicast filtering parameters */
1170 if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
1171 mc_count = 0;
1172 fp->filters |= FIF_ALLMULTI;
1173 }
1174
1175 fp->mc_list_length = 0;
1176 for (i = 0; i < mc_count; i++) {
1177 if (mc_list->da_addrlen == ETH_ALEN) {
1178 memcpy(fp->mc_list[fp->mc_list_length],
1179 mc_list->da_addr, ETH_ALEN);
1180 fp->mc_list_length++;
1181 } else
1182 wl1271_warning("Unknown mc address length.");
1183 }
1184
Luciano Coelho0535d9f2009-10-12 15:08:56 +03001185 /* FIXME: We still need to set our filters properly */
1186
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001187 spin_lock_irqsave(&wl->wl_lock, flags);
1188 kfree(wl->filter_params);
1189 wl->filter_params = fp;
1190 spin_unlock_irqrestore(&wl->wl_lock, flags);
1191
1192 return 1;
1193}
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001194
1195static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
1196 unsigned int changed,
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001197 unsigned int *total, u64 multicast)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001198{
1199 struct wl1271 *wl = hw->priv;
1200
1201 wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
1202
1203 *total &= WL1271_SUPPORTED_FILTERS;
1204 changed &= WL1271_SUPPORTED_FILTERS;
1205
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001206 if (!multicast)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001207 return;
1208
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001209 /*
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001210 * FIXME: for now we are still using a workqueue for filter
1211 * configuration, but with the new mac80211, this is not needed,
1212 * since configure_filter can now sleep. We now have
1213 * prepare_multicast, which needs to be atomic instead.
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001214 */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001215
1216 /* store current filter config */
1217 wl->filter_params->filters = *total;
1218 wl->filter_params->changed = changed;
1219
1220 ieee80211_queue_work(wl->hw, &wl->filter_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001221}
1222
1223static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1224 struct ieee80211_vif *vif,
1225 struct ieee80211_sta *sta,
1226 struct ieee80211_key_conf *key_conf)
1227{
1228 struct wl1271 *wl = hw->priv;
1229 const u8 *addr;
1230 int ret;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001231 u32 tx_seq_32 = 0;
1232 u16 tx_seq_16 = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001233 u8 key_type;
1234
1235 static const u8 bcast_addr[ETH_ALEN] =
1236 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1237
1238 wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
1239
1240 addr = sta ? sta->addr : bcast_addr;
1241
1242 wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
1243 wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
1244 wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
1245 key_conf->alg, key_conf->keyidx,
1246 key_conf->keylen, key_conf->flags);
1247 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
1248
1249 if (is_zero_ether_addr(addr)) {
1250 /* We dont support TX only encryption */
1251 ret = -EOPNOTSUPP;
1252 goto out;
1253 }
1254
1255 mutex_lock(&wl->mutex);
1256
1257 ret = wl1271_ps_elp_wakeup(wl, false);
1258 if (ret < 0)
1259 goto out_unlock;
1260
1261 switch (key_conf->alg) {
1262 case ALG_WEP:
1263 key_type = KEY_WEP;
1264
1265 key_conf->hw_key_idx = key_conf->keyidx;
1266 break;
1267 case ALG_TKIP:
1268 key_type = KEY_TKIP;
1269
1270 key_conf->hw_key_idx = key_conf->keyidx;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001271 tx_seq_32 = wl->tx_security_seq_32;
1272 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001273 break;
1274 case ALG_CCMP:
1275 key_type = KEY_AES;
1276
1277 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001278 tx_seq_32 = wl->tx_security_seq_32;
1279 tx_seq_16 = wl->tx_security_seq_16;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001280 break;
1281 default:
1282 wl1271_error("Unknown key algo 0x%x", key_conf->alg);
1283
1284 ret = -EOPNOTSUPP;
1285 goto out_sleep;
1286 }
1287
1288 switch (cmd) {
1289 case SET_KEY:
1290 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
1291 key_conf->keyidx, key_type,
1292 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001293 addr, tx_seq_32, tx_seq_16);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001294 if (ret < 0) {
1295 wl1271_error("Could not add or replace key");
1296 goto out_sleep;
1297 }
1298 break;
1299
1300 case DISABLE_KEY:
1301 ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
1302 key_conf->keyidx, key_type,
1303 key_conf->keylen, key_conf->key,
Juuso Oikarinenac4e4ce2009-10-08 21:56:19 +03001304 addr, 0, 0);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001305 if (ret < 0) {
1306 wl1271_error("Could not remove key");
1307 goto out_sleep;
1308 }
1309 break;
1310
1311 default:
1312 wl1271_error("Unsupported key cmd 0x%x", cmd);
1313 ret = -EOPNOTSUPP;
1314 goto out_sleep;
1315
1316 break;
1317 }
1318
1319out_sleep:
1320 wl1271_ps_elp_sleep(wl);
1321
1322out_unlock:
1323 mutex_unlock(&wl->mutex);
1324
1325out:
1326 return ret;
1327}
1328
1329static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
1330 struct cfg80211_scan_request *req)
1331{
1332 struct wl1271 *wl = hw->priv;
1333 int ret;
1334 u8 *ssid = NULL;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001335 size_t len = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001336
1337 wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
1338
1339 if (req->n_ssids) {
1340 ssid = req->ssids[0].ssid;
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001341 len = req->ssids[0].ssid_len;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001342 }
1343
1344 mutex_lock(&wl->mutex);
1345
1346 ret = wl1271_ps_elp_wakeup(wl, false);
1347 if (ret < 0)
1348 goto out;
1349
Teemu Paasikiviabb0b3b2009-10-13 12:47:50 +03001350 if (wl1271_11a_enabled())
1351 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1352 WL1271_SCAN_BAND_DUAL, 3);
1353 else
1354 ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
1355 WL1271_SCAN_BAND_2_4_GHZ, 3);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001356
1357 wl1271_ps_elp_sleep(wl);
1358
1359out:
1360 mutex_unlock(&wl->mutex);
1361
1362 return ret;
1363}
1364
1365static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1366{
1367 struct wl1271 *wl = hw->priv;
1368 int ret;
1369
1370 mutex_lock(&wl->mutex);
1371
1372 ret = wl1271_ps_elp_wakeup(wl, false);
1373 if (ret < 0)
1374 goto out;
1375
1376 ret = wl1271_acx_rts_threshold(wl, (u16) value);
1377 if (ret < 0)
1378 wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
1379
1380 wl1271_ps_elp_sleep(wl);
1381
1382out:
1383 mutex_unlock(&wl->mutex);
1384
1385 return ret;
1386}
1387
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001388static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
1389{
1390 struct ieee80211_supported_band *band;
1391 u32 enabled_rates = 0;
1392 int bit;
1393
1394 band = wl->hw->wiphy->bands[wl->band];
1395 for (bit = 0; bit < band->n_bitrates; bit++) {
1396 if (basic_rate_set & 0x1)
1397 enabled_rates |= band->bitrates[bit].hw_value;
1398 basic_rate_set >>= 1;
1399 }
1400
1401 return enabled_rates;
1402}
1403
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001404static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
1405 struct ieee80211_vif *vif,
1406 struct ieee80211_bss_conf *bss_conf,
1407 u32 changed)
1408{
1409 enum wl1271_cmd_ps_mode mode;
1410 struct wl1271 *wl = hw->priv;
1411 int ret;
1412
1413 wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
1414
1415 mutex_lock(&wl->mutex);
1416
1417 ret = wl1271_ps_elp_wakeup(wl, false);
1418 if (ret < 0)
1419 goto out;
1420
1421 if (changed & BSS_CHANGED_ASSOC) {
1422 if (bss_conf->assoc) {
1423 wl->aid = bss_conf->aid;
1424
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001425 /*
1426 * with wl1271, we don't need to update the
1427 * beacon_int and dtim_period, because the firmware
1428 * updates it by itself when the first beacon is
1429 * received after a join.
1430 */
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001431 ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
1432 if (ret < 0)
1433 goto out_sleep;
1434
1435 ret = wl1271_acx_aid(wl, wl->aid);
1436 if (ret < 0)
1437 goto out_sleep;
1438
1439 /* If we want to go in PSM but we're not there yet */
1440 if (wl->psm_requested && !wl->psm) {
1441 mode = STATION_POWER_SAVE_MODE;
1442 ret = wl1271_ps_set_mode(wl, mode);
1443 if (ret < 0)
1444 goto out_sleep;
1445 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001446 } else {
1447 /* use defaults when not associated */
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001448 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
1449 wl->aid = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001450 }
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001451
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001452 }
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001453
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001454 if (changed & BSS_CHANGED_ERP_SLOT) {
1455 if (bss_conf->use_short_slot)
1456 ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
1457 else
1458 ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
1459 if (ret < 0) {
1460 wl1271_warning("Set slot time failed %d", ret);
1461 goto out_sleep;
1462 }
1463 }
1464
1465 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1466 if (bss_conf->use_short_preamble)
1467 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
1468 else
1469 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
1470 }
1471
1472 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1473 if (bss_conf->use_cts_prot)
1474 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
1475 else
1476 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
1477 if (ret < 0) {
1478 wl1271_warning("Set ctsprotect failed %d", ret);
1479 goto out_sleep;
1480 }
1481 }
1482
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001483 if (changed & BSS_CHANGED_BASIC_RATES) {
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001484 wl->basic_rate_set = wl1271_enabled_rates_get(
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001485 wl, bss_conf->basic_rates);
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001486
Luciano Coelhoae751ba2009-10-12 15:08:57 +03001487 ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001488 if (ret < 0) {
1489 wl1271_warning("Set rate policies failed %d", ret);
1490 goto out_sleep;
1491 }
1492 }
1493
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001494out_sleep:
1495 wl1271_ps_elp_sleep(wl);
1496
1497out:
1498 mutex_unlock(&wl->mutex);
1499}
1500
1501
1502/* can't be const, mac80211 writes to this */
1503static struct ieee80211_rate wl1271_rates[] = {
1504 { .bitrate = 10,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001505 .hw_value = CONF_HW_BIT_RATE_1MBPS,
1506 .hw_value_short = CONF_HW_BIT_RATE_1MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001507 { .bitrate = 20,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001508 .hw_value = CONF_HW_BIT_RATE_2MBPS,
1509 .hw_value_short = CONF_HW_BIT_RATE_2MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001510 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1511 { .bitrate = 55,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001512 .hw_value = CONF_HW_BIT_RATE_5_5MBPS,
1513 .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001514 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1515 { .bitrate = 110,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001516 .hw_value = CONF_HW_BIT_RATE_11MBPS,
1517 .hw_value_short = CONF_HW_BIT_RATE_11MBPS,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001518 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1519 { .bitrate = 60,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001520 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1521 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001522 { .bitrate = 90,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001523 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1524 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001525 { .bitrate = 120,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001526 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1527 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001528 { .bitrate = 180,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001529 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1530 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001531 { .bitrate = 240,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001532 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1533 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001534 { .bitrate = 360,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001535 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1536 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001537 { .bitrate = 480,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001538 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1539 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001540 { .bitrate = 540,
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001541 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1542 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001543};
1544
1545/* can't be const, mac80211 writes to this */
1546static struct ieee80211_channel wl1271_channels[] = {
1547 { .hw_value = 1, .center_freq = 2412},
1548 { .hw_value = 2, .center_freq = 2417},
1549 { .hw_value = 3, .center_freq = 2422},
1550 { .hw_value = 4, .center_freq = 2427},
1551 { .hw_value = 5, .center_freq = 2432},
1552 { .hw_value = 6, .center_freq = 2437},
1553 { .hw_value = 7, .center_freq = 2442},
1554 { .hw_value = 8, .center_freq = 2447},
1555 { .hw_value = 9, .center_freq = 2452},
1556 { .hw_value = 10, .center_freq = 2457},
1557 { .hw_value = 11, .center_freq = 2462},
1558 { .hw_value = 12, .center_freq = 2467},
1559 { .hw_value = 13, .center_freq = 2472},
1560};
1561
1562/* can't be const, mac80211 writes to this */
1563static struct ieee80211_supported_band wl1271_band_2ghz = {
1564 .channels = wl1271_channels,
1565 .n_channels = ARRAY_SIZE(wl1271_channels),
1566 .bitrates = wl1271_rates,
1567 .n_bitrates = ARRAY_SIZE(wl1271_rates),
1568};
1569
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001570/* 5 GHz data rates for WL1273 */
1571static struct ieee80211_rate wl1271_rates_5ghz[] = {
1572 { .bitrate = 60,
1573 .hw_value = CONF_HW_BIT_RATE_6MBPS,
1574 .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
1575 { .bitrate = 90,
1576 .hw_value = CONF_HW_BIT_RATE_9MBPS,
1577 .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
1578 { .bitrate = 120,
1579 .hw_value = CONF_HW_BIT_RATE_12MBPS,
1580 .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
1581 { .bitrate = 180,
1582 .hw_value = CONF_HW_BIT_RATE_18MBPS,
1583 .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
1584 { .bitrate = 240,
1585 .hw_value = CONF_HW_BIT_RATE_24MBPS,
1586 .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
1587 { .bitrate = 360,
1588 .hw_value = CONF_HW_BIT_RATE_36MBPS,
1589 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
1590 { .bitrate = 480,
1591 .hw_value = CONF_HW_BIT_RATE_48MBPS,
1592 .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
1593 { .bitrate = 540,
1594 .hw_value = CONF_HW_BIT_RATE_54MBPS,
1595 .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
1596};
1597
1598/* 5 GHz band channels for WL1273 */
1599static struct ieee80211_channel wl1271_channels_5ghz[] = {
1600 { .hw_value = 183, .center_freq = 4915},
1601 { .hw_value = 184, .center_freq = 4920},
1602 { .hw_value = 185, .center_freq = 4925},
1603 { .hw_value = 187, .center_freq = 4935},
1604 { .hw_value = 188, .center_freq = 4940},
1605 { .hw_value = 189, .center_freq = 4945},
1606 { .hw_value = 192, .center_freq = 4960},
1607 { .hw_value = 196, .center_freq = 4980},
1608 { .hw_value = 7, .center_freq = 5035},
1609 { .hw_value = 8, .center_freq = 5040},
1610 { .hw_value = 9, .center_freq = 5045},
1611 { .hw_value = 11, .center_freq = 5055},
1612 { .hw_value = 12, .center_freq = 5060},
1613 { .hw_value = 16, .center_freq = 5080},
1614 { .hw_value = 34, .center_freq = 5170},
1615 { .hw_value = 36, .center_freq = 5180},
1616 { .hw_value = 38, .center_freq = 5190},
1617 { .hw_value = 40, .center_freq = 5200},
1618 { .hw_value = 42, .center_freq = 5210},
1619 { .hw_value = 44, .center_freq = 5220},
1620 { .hw_value = 46, .center_freq = 5230},
1621 { .hw_value = 48, .center_freq = 5240},
1622 { .hw_value = 52, .center_freq = 5260},
1623 { .hw_value = 56, .center_freq = 5280},
1624 { .hw_value = 60, .center_freq = 5300},
1625 { .hw_value = 64, .center_freq = 5320},
1626 { .hw_value = 100, .center_freq = 5500},
1627 { .hw_value = 104, .center_freq = 5520},
1628 { .hw_value = 108, .center_freq = 5540},
1629 { .hw_value = 112, .center_freq = 5560},
1630 { .hw_value = 116, .center_freq = 5580},
1631 { .hw_value = 120, .center_freq = 5600},
1632 { .hw_value = 124, .center_freq = 5620},
1633 { .hw_value = 128, .center_freq = 5640},
1634 { .hw_value = 132, .center_freq = 5660},
1635 { .hw_value = 136, .center_freq = 5680},
1636 { .hw_value = 140, .center_freq = 5700},
1637 { .hw_value = 149, .center_freq = 5745},
1638 { .hw_value = 153, .center_freq = 5765},
1639 { .hw_value = 157, .center_freq = 5785},
1640 { .hw_value = 161, .center_freq = 5805},
1641 { .hw_value = 165, .center_freq = 5825},
1642};
1643
1644
1645static struct ieee80211_supported_band wl1271_band_5ghz = {
1646 .channels = wl1271_channels_5ghz,
1647 .n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
1648 .bitrates = wl1271_rates_5ghz,
1649 .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
1650};
1651
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001652static const struct ieee80211_ops wl1271_ops = {
1653 .start = wl1271_op_start,
1654 .stop = wl1271_op_stop,
1655 .add_interface = wl1271_op_add_interface,
1656 .remove_interface = wl1271_op_remove_interface,
1657 .config = wl1271_op_config,
1658/* .config_interface = wl1271_op_config_interface, */
Juuso Oikarinenc87dec92009-10-08 21:56:31 +03001659 .prepare_multicast = wl1271_op_prepare_multicast,
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001660 .configure_filter = wl1271_op_configure_filter,
1661 .tx = wl1271_op_tx,
1662 .set_key = wl1271_op_set_key,
1663 .hw_scan = wl1271_op_hw_scan,
1664 .bss_info_changed = wl1271_op_bss_info_changed,
1665 .set_rts_threshold = wl1271_op_set_rts_threshold,
1666};
1667
1668static int wl1271_register_hw(struct wl1271 *wl)
1669{
1670 int ret;
1671
1672 if (wl->mac80211_registered)
1673 return 0;
1674
1675 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1676
1677 ret = ieee80211_register_hw(wl->hw);
1678 if (ret < 0) {
1679 wl1271_error("unable to register mac80211 hw: %d", ret);
1680 return ret;
1681 }
1682
1683 wl->mac80211_registered = true;
1684
1685 wl1271_notice("loaded");
1686
1687 return 0;
1688}
1689
1690static int wl1271_init_ieee80211(struct wl1271 *wl)
1691{
Juuso Oikarinen1e2b7972009-10-08 21:56:20 +03001692 /* The tx descriptor buffer and the TKIP space. */
1693 wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
1694 sizeof(struct wl1271_tx_hw_descr);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001695
1696 /* unit us */
1697 /* FIXME: find a proper value */
1698 wl->hw->channel_change_time = 10000;
1699
1700 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
Juuso Oikarinen19221672009-10-08 21:56:35 +03001701 IEEE80211_HW_NOISE_DBM |
1702 IEEE80211_HW_BEACON_FILTER;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001703
1704 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1705 wl->hw->wiphy->max_scan_ssids = 1;
1706 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
1707
Teemu Paasikivi1ebec3d2009-10-13 12:47:48 +03001708 if (wl1271_11a_enabled())
1709 wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
1710
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001711 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1712
1713 return 0;
1714}
1715
1716static void wl1271_device_release(struct device *dev)
1717{
1718
1719}
1720
1721static struct platform_device wl1271_device = {
1722 .name = "wl1271",
1723 .id = -1,
1724
1725 /* device model insists to have a release function */
1726 .dev = {
1727 .release = wl1271_device_release,
1728 },
1729};
1730
1731#define WL1271_DEFAULT_CHANNEL 0
1732static int __devinit wl1271_probe(struct spi_device *spi)
1733{
1734 struct wl12xx_platform_data *pdata;
1735 struct ieee80211_hw *hw;
1736 struct wl1271 *wl;
1737 int ret, i;
1738 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1739
1740 pdata = spi->dev.platform_data;
1741 if (!pdata) {
1742 wl1271_error("no platform data");
1743 return -ENODEV;
1744 }
1745
1746 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
1747 if (!hw) {
1748 wl1271_error("could not alloc ieee80211_hw");
1749 return -ENOMEM;
1750 }
1751
1752 wl = hw->priv;
1753 memset(wl, 0, sizeof(*wl));
1754
1755 wl->hw = hw;
1756 dev_set_drvdata(&spi->dev, wl);
1757 wl->spi = spi;
1758
1759 skb_queue_head_init(&wl->tx_queue);
1760
1761 INIT_WORK(&wl->filter_work, wl1271_filter_work);
Juuso Oikarinen37b70a82009-10-08 21:56:21 +03001762 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001763 wl->channel = WL1271_DEFAULT_CHANNEL;
1764 wl->scanning = false;
1765 wl->default_key = 0;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001766 wl->rx_counter = 0;
1767 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
1768 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
1769 wl->elp = false;
1770 wl->psm = 0;
1771 wl->psm_requested = false;
1772 wl->tx_queue_stopped = false;
1773 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
Juuso Oikarinend94cd292009-10-08 21:56:25 +03001774 wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
Juuso Oikarinen8a5a37a2009-10-08 21:56:24 +03001775 wl->band = IEEE80211_BAND_2GHZ;
Juuso Oikarinenb771eee2009-10-08 21:56:34 +03001776 wl->vif = NULL;
Luciano Coelhod6e19d12009-10-12 15:08:43 +03001777 wl->joined = false;
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001778
Juuso Oikarinenbe7078c2009-10-08 21:56:26 +03001779 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001780 wl->tx_frames[i] = NULL;
1781
1782 spin_lock_init(&wl->wl_lock);
1783
1784 /*
1785 * In case our MAC address is not correctly set,
1786 * we use a random but Nokia MAC.
1787 */
1788 memcpy(wl->mac_addr, nokia_oui, 3);
1789 get_random_bytes(wl->mac_addr + 3, 3);
1790
1791 wl->state = WL1271_STATE_OFF;
1792 mutex_init(&wl->mutex);
1793
1794 wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
1795 if (!wl->rx_descriptor) {
1796 wl1271_error("could not allocate memory for rx descriptor");
1797 ret = -ENOMEM;
1798 goto out_free;
1799 }
1800
1801 /* This is the only SPI value that we need to set here, the rest
1802 * comes from the board-peripherals file */
1803 spi->bits_per_word = 32;
1804
1805 ret = spi_setup(spi);
1806 if (ret < 0) {
1807 wl1271_error("spi_setup failed");
1808 goto out_free;
1809 }
1810
1811 wl->set_power = pdata->set_power;
1812 if (!wl->set_power) {
1813 wl1271_error("set power function missing in platform data");
1814 ret = -ENODEV;
1815 goto out_free;
1816 }
1817
1818 wl->irq = spi->irq;
1819 if (wl->irq < 0) {
1820 wl1271_error("irq missing in platform data");
1821 ret = -ENODEV;
1822 goto out_free;
1823 }
1824
1825 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
1826 if (ret < 0) {
1827 wl1271_error("request_irq() failed: %d", ret);
1828 goto out_free;
1829 }
1830
1831 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1832
1833 disable_irq(wl->irq);
1834
1835 ret = platform_device_register(&wl1271_device);
1836 if (ret) {
1837 wl1271_error("couldn't register platform device");
1838 goto out_irq;
1839 }
1840 dev_set_drvdata(&wl1271_device.dev, wl);
1841
Juuso Oikarinen2b60100b2009-10-13 12:47:39 +03001842 /* Apply default driver configuration. */
1843 wl1271_conf_init(wl);
1844
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001845 ret = wl1271_init_ieee80211(wl);
1846 if (ret)
1847 goto out_platform;
1848
1849 ret = wl1271_register_hw(wl);
1850 if (ret)
1851 goto out_platform;
1852
1853 wl1271_debugfs_init(wl);
1854
1855 wl1271_notice("initialized");
1856
1857 return 0;
1858
1859 out_platform:
1860 platform_device_unregister(&wl1271_device);
1861
1862 out_irq:
1863 free_irq(wl->irq, wl);
1864
1865 out_free:
1866 kfree(wl->rx_descriptor);
1867 wl->rx_descriptor = NULL;
1868
1869 ieee80211_free_hw(hw);
1870
1871 return ret;
1872}
1873
1874static int __devexit wl1271_remove(struct spi_device *spi)
1875{
1876 struct wl1271 *wl = dev_get_drvdata(&spi->dev);
1877
1878 ieee80211_unregister_hw(wl->hw);
1879
1880 wl1271_debugfs_exit(wl);
1881 platform_device_unregister(&wl1271_device);
1882 free_irq(wl->irq, wl);
1883 kfree(wl->target_mem_map);
Juuso Oikarinen1fba4972009-10-08 21:56:32 +03001884 vfree(wl->fw);
Luciano Coelhof5fc0f82009-08-06 16:25:28 +03001885 wl->fw = NULL;
1886 kfree(wl->nvs);
1887 wl->nvs = NULL;
1888
1889 kfree(wl->rx_descriptor);
1890 wl->rx_descriptor = NULL;
1891
1892 kfree(wl->fw_status);
1893 kfree(wl->tx_res_if);
1894
1895 ieee80211_free_hw(wl->hw);
1896
1897 return 0;
1898}
1899
1900
1901static struct spi_driver wl1271_spi_driver = {
1902 .driver = {
1903 .name = "wl1271",
1904 .bus = &spi_bus_type,
1905 .owner = THIS_MODULE,
1906 },
1907
1908 .probe = wl1271_probe,
1909 .remove = __devexit_p(wl1271_remove),
1910};
1911
1912static int __init wl1271_init(void)
1913{
1914 int ret;
1915
1916 ret = spi_register_driver(&wl1271_spi_driver);
1917 if (ret < 0) {
1918 wl1271_error("failed to register spi driver: %d", ret);
1919 goto out;
1920 }
1921
1922out:
1923 return ret;
1924}
1925
1926static void __exit wl1271_exit(void)
1927{
1928 spi_unregister_driver(&wl1271_spi_driver);
1929
1930 wl1271_notice("unloaded");
1931}
1932
1933module_init(wl1271_init);
1934module_exit(wl1271_exit);
1935
1936MODULE_LICENSE("GPL");
1937MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
Luciano Coelho2f018722009-10-08 21:56:27 +03001938MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");