blob: 0f30d0a62aa9acc3d87dde6da49f337259fe1ad2 [file] [log] [blame]
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001/*
Kalle Valo80301cd2009-06-12 14:17:39 +03002 * This file is part of wl1251
Kalle Valo2f01a1f2009-04-29 23:33:31 +03003 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Kalle Valo <kalle.valo@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/interrupt.h>
26#include <linux/firmware.h>
27#include <linux/delay.h>
28#include <linux/irq.h>
29#include <linux/spi/spi.h>
30#include <linux/crc32.h>
31#include <linux/etherdevice.h>
32#include <linux/spi/wl12xx.h>
33
Kalle Valo13674112009-06-12 14:17:25 +030034#include "wl1251.h"
Kalle Valo2f01a1f2009-04-29 23:33:31 +030035#include "wl12xx_80211.h"
36#include "reg.h"
Kalle Valoe6f0b5c2009-06-12 14:16:58 +030037#include "wl1251_ops.h"
Bob Copeland0764de62009-08-07 13:32:56 +030038#include "wl1251_io.h"
Kalle Valoef2f8d42009-06-12 14:17:19 +030039#include "wl1251_spi.h"
40#include "wl1251_event.h"
Juuso Oikarinen9f2ad4f2009-06-12 14:15:54 +030041#include "wl1251_tx.h"
Kalle Valoef2f8d42009-06-12 14:17:19 +030042#include "wl1251_rx.h"
43#include "wl1251_ps.h"
44#include "wl1251_init.h"
45#include "wl1251_debugfs.h"
Kalle Valo2f01a1f2009-04-29 23:33:31 +030046
Kalle Valo80301cd2009-06-12 14:17:39 +030047static void wl1251_disable_interrupts(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +030048{
49 disable_irq(wl->irq);
50}
51
Kalle Valo80301cd2009-06-12 14:17:39 +030052static void wl1251_power_off(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +030053{
54 wl->set_power(false);
55}
56
Kalle Valo80301cd2009-06-12 14:17:39 +030057static void wl1251_power_on(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +030058{
59 wl->set_power(true);
60}
61
Kalle Valo80301cd2009-06-12 14:17:39 +030062static irqreturn_t wl1251_irq(int irq, void *cookie)
Kalle Valo2f01a1f2009-04-29 23:33:31 +030063{
Kalle Valo80301cd2009-06-12 14:17:39 +030064 struct wl1251 *wl;
Kalle Valo2f01a1f2009-04-29 23:33:31 +030065
Kalle Valo80301cd2009-06-12 14:17:39 +030066 wl1251_debug(DEBUG_IRQ, "IRQ");
Kalle Valo2f01a1f2009-04-29 23:33:31 +030067
68 wl = cookie;
69
70 schedule_work(&wl->irq_work);
71
72 return IRQ_HANDLED;
73}
74
Kalle Valo80301cd2009-06-12 14:17:39 +030075static int wl1251_fetch_firmware(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +030076{
77 const struct firmware *fw;
Bob Copeland6c766f42009-08-07 13:33:04 +030078 struct device *dev = wiphy_dev(wl->hw->wiphy);
Kalle Valo2f01a1f2009-04-29 23:33:31 +030079 int ret;
80
Bob Copeland6c766f42009-08-07 13:33:04 +030081 ret = request_firmware(&fw, wl->chip.fw_filename, dev);
Kalle Valo2f01a1f2009-04-29 23:33:31 +030082
83 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +030084 wl1251_error("could not get firmware: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +030085 return ret;
86 }
87
88 if (fw->size % 4) {
Kalle Valo80301cd2009-06-12 14:17:39 +030089 wl1251_error("firmware size is not multiple of 32 bits: %zu",
Kalle Valo2f01a1f2009-04-29 23:33:31 +030090 fw->size);
91 ret = -EILSEQ;
92 goto out;
93 }
94
95 wl->fw_len = fw->size;
96 wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
97
98 if (!wl->fw) {
Kalle Valo80301cd2009-06-12 14:17:39 +030099 wl1251_error("could not allocate memory for the firmware");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300100 ret = -ENOMEM;
101 goto out;
102 }
103
104 memcpy(wl->fw, fw->data, wl->fw_len);
105
106 ret = 0;
107
108out:
109 release_firmware(fw);
110
111 return ret;
112}
113
Kalle Valo80301cd2009-06-12 14:17:39 +0300114static int wl1251_fetch_nvs(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300115{
116 const struct firmware *fw;
Bob Copeland6c766f42009-08-07 13:33:04 +0300117 struct device *dev = wiphy_dev(wl->hw->wiphy);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300118 int ret;
119
Bob Copeland6c766f42009-08-07 13:33:04 +0300120 ret = request_firmware(&fw, wl->chip.nvs_filename, dev);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300121
122 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300123 wl1251_error("could not get nvs file: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300124 return ret;
125 }
126
127 if (fw->size % 4) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300128 wl1251_error("nvs size is not multiple of 32 bits: %zu",
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300129 fw->size);
130 ret = -EILSEQ;
131 goto out;
132 }
133
134 wl->nvs_len = fw->size;
135 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
136
137 if (!wl->nvs) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300138 wl1251_error("could not allocate memory for the nvs file");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300139 ret = -ENOMEM;
140 goto out;
141 }
142
143 memcpy(wl->nvs, fw->data, wl->nvs_len);
144
145 ret = 0;
146
147out:
148 release_firmware(fw);
149
150 return ret;
151}
152
Kalle Valo80301cd2009-06-12 14:17:39 +0300153static void wl1251_fw_wakeup(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300154{
155 u32 elp_reg;
156
157 elp_reg = ELPCTRL_WAKE_UP;
Kalle Valo80301cd2009-06-12 14:17:39 +0300158 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
159 elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300160
Kalle Valo05fac682009-06-12 14:17:47 +0300161 if (!(elp_reg & ELPCTRL_WLAN_READY))
Kalle Valo80301cd2009-06-12 14:17:39 +0300162 wl1251_warning("WLAN not ready");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300163}
164
Kalle Valo80301cd2009-06-12 14:17:39 +0300165static int wl1251_chip_wakeup(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300166{
167 int ret = 0;
168
Kalle Valo80301cd2009-06-12 14:17:39 +0300169 wl1251_power_on(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300170 msleep(wl->chip.power_on_sleep);
Bob Copeland08d9f5722009-08-07 13:33:11 +0300171 wl->if_ops->reset(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300172
173 /* We don't need a real memory partition here, because we only want
174 * to use the registers at this point. */
Kalle Valo80301cd2009-06-12 14:17:39 +0300175 wl1251_set_partition(wl,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300176 0x00000000,
177 0x00000000,
178 REGISTERS_BASE,
179 REGISTERS_DOWN_SIZE);
180
181 /* ELP module wake up */
Kalle Valo80301cd2009-06-12 14:17:39 +0300182 wl1251_fw_wakeup(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300183
184 /* whal_FwCtrl_BootSm() */
185
186 /* 0. read chip id from CHIP_ID */
Kalle Valo80301cd2009-06-12 14:17:39 +0300187 wl->chip.id = wl1251_reg_read32(wl, CHIP_ID_B);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300188
189 /* 1. check if chip id is valid */
190
191 switch (wl->chip.id) {
192 case CHIP_ID_1251_PG12:
Kalle Valo80301cd2009-06-12 14:17:39 +0300193 wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300194 wl->chip.id);
195
196 wl1251_setup(wl);
197
198 break;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300199 case CHIP_ID_1251_PG10:
200 case CHIP_ID_1251_PG11:
201 default:
Kalle Valo80301cd2009-06-12 14:17:39 +0300202 wl1251_error("unsupported chip id: 0x%x", wl->chip.id);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300203 ret = -ENODEV;
204 goto out;
205 }
206
207 if (wl->fw == NULL) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300208 ret = wl1251_fetch_firmware(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300209 if (ret < 0)
210 goto out;
211 }
212
213 /* No NVS from netlink, try to get it from the filesystem */
214 if (wl->nvs == NULL) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300215 ret = wl1251_fetch_nvs(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300216 if (ret < 0)
217 goto out;
218 }
219
220out:
221 return ret;
222}
223
Kalle Valo80301cd2009-06-12 14:17:39 +0300224static void wl1251_filter_work(struct work_struct *work)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300225{
Kalle Valo80301cd2009-06-12 14:17:39 +0300226 struct wl1251 *wl =
227 container_of(work, struct wl1251, filter_work);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300228 int ret;
229
230 mutex_lock(&wl->mutex);
231
Kalle Valo80301cd2009-06-12 14:17:39 +0300232 if (wl->state == WL1251_STATE_OFF)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300233 goto out;
234
Kalle Valo80301cd2009-06-12 14:17:39 +0300235 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300236 if (ret < 0)
237 goto out;
238
Juuso Oikarinen77cc9e42009-06-12 14:16:52 +0300239 /* FIXME: replace the magic numbers with proper definitions */
240 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
Kalle Valoc5483b72009-06-12 14:16:32 +0300241 if (ret < 0)
242 goto out_sleep;
243
244out_sleep:
Kalle Valo80301cd2009-06-12 14:17:39 +0300245 wl1251_ps_elp_sleep(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300246
247out:
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300248 mutex_unlock(&wl->mutex);
249}
250
Kalle Valo80301cd2009-06-12 14:17:39 +0300251static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300252{
Kalle Valo80301cd2009-06-12 14:17:39 +0300253 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300254
255 skb_queue_tail(&wl->tx_queue, skb);
256
Juuso Oikarinen9f2ad4f2009-06-12 14:15:54 +0300257 /*
258 * The chip specific setup must run before the first TX packet -
259 * before that, the tx_work will not be initialized!
260 */
261
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300262 schedule_work(&wl->tx_work);
263
264 /*
265 * The workqueue is slow to process the tx_queue and we need stop
266 * the queue here, otherwise the queue will get too long.
267 */
Kalle Valo80301cd2009-06-12 14:17:39 +0300268 if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) {
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300269 ieee80211_stop_queues(wl->hw);
270
271 /*
272 * FIXME: this is racy, the variable is not properly
273 * protected. Maybe fix this by removing the stupid
274 * variable altogether and checking the real queue state?
275 */
276 wl->tx_queue_stopped = true;
277 }
278
279 return NETDEV_TX_OK;
280}
281
Kalle Valo80301cd2009-06-12 14:17:39 +0300282static int wl1251_op_start(struct ieee80211_hw *hw)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300283{
Kalle Valo80301cd2009-06-12 14:17:39 +0300284 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300285 int ret = 0;
286
Kalle Valo80301cd2009-06-12 14:17:39 +0300287 wl1251_debug(DEBUG_MAC80211, "mac80211 start");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300288
289 mutex_lock(&wl->mutex);
290
Kalle Valo80301cd2009-06-12 14:17:39 +0300291 if (wl->state != WL1251_STATE_OFF) {
292 wl1251_error("cannot start because not in off state: %d",
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300293 wl->state);
294 ret = -EBUSY;
295 goto out;
296 }
297
Kalle Valo80301cd2009-06-12 14:17:39 +0300298 ret = wl1251_chip_wakeup(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300299 if (ret < 0)
Jiri Slabyfe643412009-07-14 22:37:13 +0200300 goto out;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300301
302 ret = wl->chip.op_boot(wl);
303 if (ret < 0)
304 goto out;
305
306 ret = wl->chip.op_hw_init(wl);
307 if (ret < 0)
308 goto out;
309
Kalle Valo80301cd2009-06-12 14:17:39 +0300310 ret = wl1251_acx_station_id(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300311 if (ret < 0)
312 goto out;
313
Kalle Valo80301cd2009-06-12 14:17:39 +0300314 wl->state = WL1251_STATE_ON;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300315
Kalle Valo80301cd2009-06-12 14:17:39 +0300316 wl1251_info("firmware booted (%s)", wl->chip.fw_ver);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300317
318out:
319 if (ret < 0)
Kalle Valo80301cd2009-06-12 14:17:39 +0300320 wl1251_power_off(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300321
322 mutex_unlock(&wl->mutex);
323
324 return ret;
325}
326
Kalle Valo80301cd2009-06-12 14:17:39 +0300327static void wl1251_op_stop(struct ieee80211_hw *hw)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300328{
Kalle Valo80301cd2009-06-12 14:17:39 +0300329 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300330
Kalle Valo80301cd2009-06-12 14:17:39 +0300331 wl1251_info("down");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300332
Kalle Valo80301cd2009-06-12 14:17:39 +0300333 wl1251_debug(DEBUG_MAC80211, "mac80211 stop");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300334
335 mutex_lock(&wl->mutex);
336
Kalle Valo80301cd2009-06-12 14:17:39 +0300337 WARN_ON(wl->state != WL1251_STATE_ON);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300338
339 if (wl->scanning) {
340 mutex_unlock(&wl->mutex);
341 ieee80211_scan_completed(wl->hw, true);
342 mutex_lock(&wl->mutex);
343 wl->scanning = false;
344 }
345
Kalle Valo80301cd2009-06-12 14:17:39 +0300346 wl->state = WL1251_STATE_OFF;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300347
Kalle Valo80301cd2009-06-12 14:17:39 +0300348 wl1251_disable_interrupts(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300349
350 mutex_unlock(&wl->mutex);
351
352 cancel_work_sync(&wl->irq_work);
353 cancel_work_sync(&wl->tx_work);
354 cancel_work_sync(&wl->filter_work);
355
356 mutex_lock(&wl->mutex);
357
358 /* let's notify MAC80211 about the remaining pending TX frames */
Juuso Oikarinen9f2ad4f2009-06-12 14:15:54 +0300359 wl->chip.op_tx_flush(wl);
Kalle Valo80301cd2009-06-12 14:17:39 +0300360 wl1251_power_off(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300361
362 memset(wl->bssid, 0, ETH_ALEN);
363 wl->listen_int = 1;
364 wl->bss_type = MAX_BSS_TYPE;
365
366 wl->data_in_count = 0;
367 wl->rx_counter = 0;
368 wl->rx_handled = 0;
369 wl->rx_current_buffer = 0;
370 wl->rx_last_id = 0;
371 wl->next_tx_complete = 0;
372 wl->elp = false;
373 wl->psm = 0;
374 wl->tx_queue_stopped = false;
Kalle Valo80301cd2009-06-12 14:17:39 +0300375 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300376
Kalle Valo80301cd2009-06-12 14:17:39 +0300377 wl1251_debugfs_reset(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300378
379 mutex_unlock(&wl->mutex);
380}
381
Kalle Valo80301cd2009-06-12 14:17:39 +0300382static int wl1251_op_add_interface(struct ieee80211_hw *hw,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300383 struct ieee80211_if_init_conf *conf)
384{
Kalle Valo80301cd2009-06-12 14:17:39 +0300385 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300386 int ret = 0;
387
Johannes Berge91d8332009-07-15 17:21:41 +0200388 wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
389 conf->type, conf->mac_addr);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300390
391 mutex_lock(&wl->mutex);
392
393 switch (conf->type) {
394 case NL80211_IFTYPE_STATION:
395 wl->bss_type = BSS_TYPE_STA_BSS;
396 break;
397 case NL80211_IFTYPE_ADHOC:
398 wl->bss_type = BSS_TYPE_IBSS;
399 break;
400 default:
401 ret = -EOPNOTSUPP;
402 goto out;
403 }
404
405 if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
406 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
407 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
Kalle Valo80301cd2009-06-12 14:17:39 +0300408 ret = wl1251_acx_station_id(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300409 if (ret < 0)
410 goto out;
411 }
412
413out:
414 mutex_unlock(&wl->mutex);
415 return ret;
416}
417
Kalle Valo80301cd2009-06-12 14:17:39 +0300418static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300419 struct ieee80211_if_init_conf *conf)
420{
Kalle Valo80301cd2009-06-12 14:17:39 +0300421 wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300422}
423
Kalle Valo80301cd2009-06-12 14:17:39 +0300424static int wl1251_build_null_data(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300425{
426 struct wl12xx_null_data_template template;
427
428 if (!is_zero_ether_addr(wl->bssid)) {
429 memcpy(template.header.da, wl->bssid, ETH_ALEN);
430 memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
431 } else {
432 memset(template.header.da, 0xff, ETH_ALEN);
433 memset(template.header.bssid, 0xff, ETH_ALEN);
434 }
435
436 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
437 template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
438 IEEE80211_STYPE_NULLFUNC);
439
Kalle Valo80301cd2009-06-12 14:17:39 +0300440 return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300441 sizeof(template));
442
443}
444
Kalle Valo80301cd2009-06-12 14:17:39 +0300445static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300446{
447 struct wl12xx_ps_poll_template template;
448
449 memcpy(template.bssid, wl->bssid, ETH_ALEN);
450 memcpy(template.ta, wl->mac_addr, ETH_ALEN);
451 template.aid = aid;
452 template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
453
Kalle Valo80301cd2009-06-12 14:17:39 +0300454 return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300455 sizeof(template));
456
457}
458
Kalle Valo80301cd2009-06-12 14:17:39 +0300459static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300460{
Kalle Valo80301cd2009-06-12 14:17:39 +0300461 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300462 struct ieee80211_conf *conf = &hw->conf;
463 int channel, ret = 0;
464
465 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
466
Kalle Valo80301cd2009-06-12 14:17:39 +0300467 wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300468 channel,
469 conf->flags & IEEE80211_CONF_PS ? "on" : "off",
470 conf->power_level);
471
472 mutex_lock(&wl->mutex);
473
Kalle Valo80301cd2009-06-12 14:17:39 +0300474 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300475 if (ret < 0)
476 goto out;
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300477
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300478 if (channel != wl->channel) {
479 /* FIXME: use beacon interval provided by mac80211 */
Juuso Oikarinen77cc9e42009-06-12 14:16:52 +0300480 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300481 if (ret < 0)
Kalle Valoc5483b72009-06-12 14:16:32 +0300482 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300483
484 wl->channel = channel;
485 }
486
Kalle Valo80301cd2009-06-12 14:17:39 +0300487 ret = wl1251_build_null_data(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300488 if (ret < 0)
Kalle Valoc5483b72009-06-12 14:16:32 +0300489 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300490
491 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
Luciano Coelho47af3fe2009-06-12 14:17:53 +0300492 wl1251_debug(DEBUG_PSM, "psm enabled");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300493
494 wl->psm_requested = true;
495
496 /*
497 * We enter PSM only if we're already associated.
498 * If we're not, we'll enter it when joining an SSID,
499 * through the bss_info_changed() hook.
500 */
Kalle Valo80301cd2009-06-12 14:17:39 +0300501 ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300502 } else if (!(conf->flags & IEEE80211_CONF_PS) &&
503 wl->psm_requested) {
Luciano Coelho47af3fe2009-06-12 14:17:53 +0300504 wl1251_debug(DEBUG_PSM, "psm disabled");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300505
506 wl->psm_requested = false;
507
508 if (wl->psm)
Kalle Valo80301cd2009-06-12 14:17:39 +0300509 ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300510 }
511
512 if (conf->power_level != wl->power_level) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300513 ret = wl1251_acx_tx_power(wl, conf->power_level);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300514 if (ret < 0)
515 goto out;
516
517 wl->power_level = conf->power_level;
518 }
519
Kalle Valoc5483b72009-06-12 14:16:32 +0300520out_sleep:
Kalle Valo80301cd2009-06-12 14:17:39 +0300521 wl1251_ps_elp_sleep(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300522
523out:
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300524 mutex_unlock(&wl->mutex);
Kalle Valoc5483b72009-06-12 14:16:32 +0300525
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300526 return ret;
527}
528
Kalle Valo80301cd2009-06-12 14:17:39 +0300529#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300530 FIF_ALLMULTI | \
531 FIF_FCSFAIL | \
532 FIF_BCN_PRBRESP_PROMISC | \
533 FIF_CONTROL | \
534 FIF_OTHER_BSS)
535
Kalle Valo80301cd2009-06-12 14:17:39 +0300536static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300537 unsigned int changed,
538 unsigned int *total,
539 int mc_count,
540 struct dev_addr_list *mc_list)
541{
Kalle Valo80301cd2009-06-12 14:17:39 +0300542 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300543
Kalle Valo80301cd2009-06-12 14:17:39 +0300544 wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300545
Kalle Valo80301cd2009-06-12 14:17:39 +0300546 *total &= WL1251_SUPPORTED_FILTERS;
547 changed &= WL1251_SUPPORTED_FILTERS;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300548
549 if (changed == 0)
550 /* no filters which we support changed */
551 return;
552
553 /* FIXME: wl->rx_config and wl->rx_filter are not protected */
554
Kalle Valo80301cd2009-06-12 14:17:39 +0300555 wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
556 wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300557
558 if (*total & FIF_PROMISC_IN_BSS) {
559 wl->rx_config |= CFG_BSSID_FILTER_EN;
560 wl->rx_config |= CFG_RX_ALL_GOOD;
561 }
562 if (*total & FIF_ALLMULTI)
563 /*
564 * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive
565 * all multicast frames
566 */
567 wl->rx_config &= ~CFG_MC_FILTER_EN;
568 if (*total & FIF_FCSFAIL)
569 wl->rx_filter |= CFG_RX_FCS_ERROR;
570 if (*total & FIF_BCN_PRBRESP_PROMISC) {
571 wl->rx_config &= ~CFG_BSSID_FILTER_EN;
572 wl->rx_config &= ~CFG_SSID_FILTER_EN;
573 }
574 if (*total & FIF_CONTROL)
575 wl->rx_filter |= CFG_RX_CTL_EN;
576 if (*total & FIF_OTHER_BSS)
577 wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
578
579 /*
580 * FIXME: workqueues need to be properly cancelled on stop(), for
581 * now let's just disable changing the filter settings. They will
582 * be updated any on config().
583 */
584 /* schedule_work(&wl->filter_work); */
585}
586
587/* HW encryption */
Kalle Valo80301cd2009-06-12 14:17:39 +0300588static int wl1251_set_key_type(struct wl1251 *wl,
589 struct wl1251_cmd_set_keys *key,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300590 enum set_key_cmd cmd,
591 struct ieee80211_key_conf *mac80211_key,
592 const u8 *addr)
593{
594 switch (mac80211_key->alg) {
595 case ALG_WEP:
596 if (is_broadcast_ether_addr(addr))
597 key->key_type = KEY_WEP_DEFAULT;
598 else
599 key->key_type = KEY_WEP_ADDR;
600
601 mac80211_key->hw_key_idx = mac80211_key->keyidx;
602 break;
603 case ALG_TKIP:
604 if (is_broadcast_ether_addr(addr))
605 key->key_type = KEY_TKIP_MIC_GROUP;
606 else
607 key->key_type = KEY_TKIP_MIC_PAIRWISE;
608
609 mac80211_key->hw_key_idx = mac80211_key->keyidx;
610 break;
611 case ALG_CCMP:
612 if (is_broadcast_ether_addr(addr))
613 key->key_type = KEY_AES_GROUP;
614 else
615 key->key_type = KEY_AES_PAIRWISE;
616 mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
617 break;
618 default:
Kalle Valo80301cd2009-06-12 14:17:39 +0300619 wl1251_error("Unknown key algo 0x%x", mac80211_key->alg);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300620 return -EOPNOTSUPP;
621 }
622
623 return 0;
624}
625
Kalle Valo80301cd2009-06-12 14:17:39 +0300626static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300627 struct ieee80211_vif *vif,
628 struct ieee80211_sta *sta,
629 struct ieee80211_key_conf *key)
630{
Kalle Valo80301cd2009-06-12 14:17:39 +0300631 struct wl1251 *wl = hw->priv;
632 struct wl1251_cmd_set_keys *wl_cmd;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300633 const u8 *addr;
634 int ret;
635
636 static const u8 bcast_addr[ETH_ALEN] =
637 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
638
Kalle Valo80301cd2009-06-12 14:17:39 +0300639 wl1251_debug(DEBUG_MAC80211, "mac80211 set key");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300640
Kalle Valoff258392009-06-12 14:14:19 +0300641 wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL);
642 if (!wl_cmd) {
643 ret = -ENOMEM;
644 goto out;
645 }
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300646
647 addr = sta ? sta->addr : bcast_addr;
648
Kalle Valo80301cd2009-06-12 14:17:39 +0300649 wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
650 wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
651 wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300652 key->alg, key->keyidx, key->keylen, key->flags);
Kalle Valo80301cd2009-06-12 14:17:39 +0300653 wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300654
Kalle Valoff258392009-06-12 14:14:19 +0300655 if (is_zero_ether_addr(addr)) {
656 /* We dont support TX only encryption */
657 ret = -EOPNOTSUPP;
658 goto out;
659 }
660
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300661 mutex_lock(&wl->mutex);
662
Kalle Valo80301cd2009-06-12 14:17:39 +0300663 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300664 if (ret < 0)
665 goto out_unlock;
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300666
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300667 switch (cmd) {
668 case SET_KEY:
Kalle Valoff258392009-06-12 14:14:19 +0300669 wl_cmd->key_action = KEY_ADD_OR_REPLACE;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300670 break;
671 case DISABLE_KEY:
Kalle Valoff258392009-06-12 14:14:19 +0300672 wl_cmd->key_action = KEY_REMOVE;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300673 break;
674 default:
Kalle Valo80301cd2009-06-12 14:17:39 +0300675 wl1251_error("Unsupported key cmd 0x%x", cmd);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300676 break;
677 }
678
Kalle Valo80301cd2009-06-12 14:17:39 +0300679 ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300680 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300681 wl1251_error("Set KEY type failed");
Kalle Valoc5483b72009-06-12 14:16:32 +0300682 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300683 }
684
Kalle Valoff258392009-06-12 14:14:19 +0300685 if (wl_cmd->key_type != KEY_WEP_DEFAULT)
686 memcpy(wl_cmd->addr, addr, ETH_ALEN);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300687
Kalle Valoff258392009-06-12 14:14:19 +0300688 if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) ||
689 (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) {
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300690 /*
691 * We get the key in the following form:
692 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
693 * but the target is expecting:
694 * TKIP - RX MIC - TX MIC
695 */
Kalle Valoff258392009-06-12 14:14:19 +0300696 memcpy(wl_cmd->key, key->key, 16);
697 memcpy(wl_cmd->key + 16, key->key + 24, 8);
698 memcpy(wl_cmd->key + 24, key->key + 16, 8);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300699
700 } else {
Kalle Valoff258392009-06-12 14:14:19 +0300701 memcpy(wl_cmd->key, key->key, key->keylen);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300702 }
Kalle Valoff258392009-06-12 14:14:19 +0300703 wl_cmd->key_size = key->keylen;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300704
Kalle Valoff258392009-06-12 14:14:19 +0300705 wl_cmd->id = key->keyidx;
706 wl_cmd->ssid_profile = 0;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300707
Kalle Valo80301cd2009-06-12 14:17:39 +0300708 wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd));
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300709
Kalle Valo80301cd2009-06-12 14:17:39 +0300710 ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd));
Kalle Valoff258392009-06-12 14:14:19 +0300711 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300712 wl1251_warning("could not set keys");
Kalle Valoc5483b72009-06-12 14:16:32 +0300713 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300714 }
715
Kalle Valoc5483b72009-06-12 14:16:32 +0300716out_sleep:
Kalle Valo80301cd2009-06-12 14:17:39 +0300717 wl1251_ps_elp_sleep(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300718
719out_unlock:
Kalle Valoff258392009-06-12 14:14:19 +0300720 mutex_unlock(&wl->mutex);
721
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300722out:
Kalle Valoff258392009-06-12 14:14:19 +0300723 kfree(wl_cmd);
724
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300725 return ret;
726}
727
Kalle Valo80301cd2009-06-12 14:17:39 +0300728static int wl1251_build_basic_rates(char *rates)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300729{
730 u8 index = 0;
731
732 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
733 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
734 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
735 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
736
737 return index;
738}
739
Kalle Valo80301cd2009-06-12 14:17:39 +0300740static int wl1251_build_extended_rates(char *rates)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300741{
742 u8 index = 0;
743
744 rates[index++] = IEEE80211_OFDM_RATE_6MB;
745 rates[index++] = IEEE80211_OFDM_RATE_9MB;
746 rates[index++] = IEEE80211_OFDM_RATE_12MB;
747 rates[index++] = IEEE80211_OFDM_RATE_18MB;
748 rates[index++] = IEEE80211_OFDM_RATE_24MB;
749 rates[index++] = IEEE80211_OFDM_RATE_36MB;
750 rates[index++] = IEEE80211_OFDM_RATE_48MB;
751 rates[index++] = IEEE80211_OFDM_RATE_54MB;
752
753 return index;
754}
755
756
Kalle Valo80301cd2009-06-12 14:17:39 +0300757static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300758{
759 struct wl12xx_probe_req_template template;
760 struct wl12xx_ie_rates *rates;
761 char *ptr;
762 u16 size;
763
764 ptr = (char *)&template;
765 size = sizeof(struct ieee80211_header);
766
767 memset(template.header.da, 0xff, ETH_ALEN);
768 memset(template.header.bssid, 0xff, ETH_ALEN);
769 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
770 template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
771
772 /* IEs */
773 /* SSID */
774 template.ssid.header.id = WLAN_EID_SSID;
775 template.ssid.header.len = ssid_len;
776 if (ssid_len && ssid)
777 memcpy(template.ssid.ssid, ssid, ssid_len);
778 size += sizeof(struct wl12xx_ie_header) + ssid_len;
779 ptr += size;
780
781 /* Basic Rates */
782 rates = (struct wl12xx_ie_rates *)ptr;
783 rates->header.id = WLAN_EID_SUPP_RATES;
Kalle Valo80301cd2009-06-12 14:17:39 +0300784 rates->header.len = wl1251_build_basic_rates(rates->rates);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300785 size += sizeof(struct wl12xx_ie_header) + rates->header.len;
786 ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
787
788 /* Extended rates */
789 rates = (struct wl12xx_ie_rates *)ptr;
790 rates->header.id = WLAN_EID_EXT_SUPP_RATES;
Kalle Valo80301cd2009-06-12 14:17:39 +0300791 rates->header.len = wl1251_build_extended_rates(rates->rates);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300792 size += sizeof(struct wl12xx_ie_header) + rates->header.len;
793
Kalle Valo80301cd2009-06-12 14:17:39 +0300794 wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300795
Kalle Valo80301cd2009-06-12 14:17:39 +0300796 return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300797 size);
798}
799
Kalle Valo80301cd2009-06-12 14:17:39 +0300800static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300801 u8 active_scan, u8 high_prio, u8 num_channels,
802 u8 probe_requests)
803{
Kalle Valo80301cd2009-06-12 14:17:39 +0300804 struct wl1251_cmd_trigger_scan_to *trigger = NULL;
Kalle Valoff258392009-06-12 14:14:19 +0300805 struct cmd_scan *params = NULL;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300806 int i, ret;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300807 u16 scan_options = 0;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300808
809 if (wl->scanning)
810 return -EINVAL;
811
812 params = kzalloc(sizeof(*params), GFP_KERNEL);
813 if (!params)
814 return -ENOMEM;
815
816 params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
817 params->params.rx_filter_options =
818 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
819
820 /* High priority scan */
821 if (!active_scan)
822 scan_options |= SCAN_PASSIVE;
823 if (high_prio)
824 scan_options |= SCAN_PRIORITY_HIGH;
825 params->params.scan_options = scan_options;
826
827 params->params.num_channels = num_channels;
828 params->params.num_probe_requests = probe_requests;
829 params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
830 params->params.tid_trigger = 0;
831
832 for (i = 0; i < num_channels; i++) {
833 params->channels[i].min_duration = cpu_to_le32(30000);
834 params->channels[i].max_duration = cpu_to_le32(60000);
835 memset(&params->channels[i].bssid_lsb, 0xff, 4);
836 memset(&params->channels[i].bssid_msb, 0xff, 2);
837 params->channels[i].early_termination = 0;
838 params->channels[i].tx_power_att = 0;
839 params->channels[i].channel = i + 1;
840 memset(params->channels[i].pad, 0, 3);
841 }
842
843 for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++)
844 memset(&params->channels[i], 0,
845 sizeof(struct basic_scan_channel_parameters));
846
847 if (len && ssid) {
848 params->params.ssid_len = len;
849 memcpy(params->params.ssid, ssid, len);
850 } else {
851 params->params.ssid_len = 0;
852 memset(params->params.ssid, 0, 32);
853 }
854
Kalle Valo80301cd2009-06-12 14:17:39 +0300855 ret = wl1251_build_probe_req(wl, ssid, len);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300856 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300857 wl1251_error("PROBE request template failed");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300858 goto out;
859 }
860
Kalle Valoff258392009-06-12 14:14:19 +0300861 trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
862 if (!trigger)
863 goto out;
864
865 trigger->timeout = 0;
866
Kalle Valo80301cd2009-06-12 14:17:39 +0300867 ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
Kalle Valoff258392009-06-12 14:14:19 +0300868 sizeof(*trigger));
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300869 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300870 wl1251_error("trigger scan to failed for hw scan");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300871 goto out;
872 }
873
Kalle Valo80301cd2009-06-12 14:17:39 +0300874 wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300875
876 wl->scanning = true;
877
Kalle Valo80301cd2009-06-12 14:17:39 +0300878 ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300879 if (ret < 0)
Kalle Valo80301cd2009-06-12 14:17:39 +0300880 wl1251_error("SCAN failed");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300881
Bob Copeland0764de62009-08-07 13:32:56 +0300882 wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300883
Kalle Valoff258392009-06-12 14:14:19 +0300884 if (params->header.status != CMD_STATUS_SUCCESS) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300885 wl1251_error("TEST command answer error: %d",
Kalle Valoff258392009-06-12 14:14:19 +0300886 params->header.status);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300887 wl->scanning = false;
888 ret = -EIO;
889 goto out;
890 }
891
892out:
893 kfree(params);
894 return ret;
895
896}
897
Kalle Valo80301cd2009-06-12 14:17:39 +0300898static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300899 struct cfg80211_scan_request *req)
900{
Kalle Valo80301cd2009-06-12 14:17:39 +0300901 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300902 int ret;
903 u8 *ssid = NULL;
904 size_t ssid_len = 0;
905
Kalle Valo80301cd2009-06-12 14:17:39 +0300906 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300907
908 if (req->n_ssids) {
909 ssid = req->ssids[0].ssid;
910 ssid_len = req->ssids[0].ssid_len;
911 }
912
913 mutex_lock(&wl->mutex);
Kalle Valoc5483b72009-06-12 14:16:32 +0300914
Kalle Valo80301cd2009-06-12 14:17:39 +0300915 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300916 if (ret < 0)
917 goto out;
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300918
Kalle Valo80301cd2009-06-12 14:17:39 +0300919 ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300920
Kalle Valo80301cd2009-06-12 14:17:39 +0300921 wl1251_ps_elp_sleep(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300922
923out:
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300924 mutex_unlock(&wl->mutex);
925
926 return ret;
927}
928
Kalle Valo80301cd2009-06-12 14:17:39 +0300929static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300930{
Kalle Valo80301cd2009-06-12 14:17:39 +0300931 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300932 int ret;
933
Kalle Valocee4fd22009-06-12 14:16:20 +0300934 mutex_lock(&wl->mutex);
935
Kalle Valo80301cd2009-06-12 14:17:39 +0300936 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300937 if (ret < 0)
938 goto out;
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300939
Kalle Valo80301cd2009-06-12 14:17:39 +0300940 ret = wl1251_acx_rts_threshold(wl, (u16) value);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300941 if (ret < 0)
Kalle Valo80301cd2009-06-12 14:17:39 +0300942 wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300943
Kalle Valo80301cd2009-06-12 14:17:39 +0300944 wl1251_ps_elp_sleep(wl);
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300945
Kalle Valoc5483b72009-06-12 14:16:32 +0300946out:
Kalle Valocee4fd22009-06-12 14:16:20 +0300947 mutex_unlock(&wl->mutex);
948
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300949 return ret;
950}
951
Kalle Valo80301cd2009-06-12 14:17:39 +0300952static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300953 struct ieee80211_vif *vif,
954 struct ieee80211_bss_conf *bss_conf,
955 u32 changed)
956{
Kalle Valo80301cd2009-06-12 14:17:39 +0300957 enum wl1251_cmd_ps_mode mode;
958 struct wl1251 *wl = hw->priv;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300959 struct sk_buff *beacon;
960 int ret;
961
Kalle Valo80301cd2009-06-12 14:17:39 +0300962 wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300963
964 mutex_lock(&wl->mutex);
965
Kalle Valo80301cd2009-06-12 14:17:39 +0300966 ret = wl1251_ps_elp_wakeup(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +0300967 if (ret < 0)
968 goto out;
Kalle Valo01d9cfb2009-06-12 14:16:26 +0300969
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300970 if (changed & BSS_CHANGED_ASSOC) {
971 if (bss_conf->assoc) {
972 wl->aid = bss_conf->aid;
973
Kalle Valo80301cd2009-06-12 14:17:39 +0300974 ret = wl1251_build_ps_poll(wl, wl->aid);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300975 if (ret < 0)
Kalle Valoc5483b72009-06-12 14:16:32 +0300976 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300977
Kalle Valo80301cd2009-06-12 14:17:39 +0300978 ret = wl1251_acx_aid(wl, wl->aid);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300979 if (ret < 0)
Kalle Valoc5483b72009-06-12 14:16:32 +0300980 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300981
982 /* If we want to go in PSM but we're not there yet */
983 if (wl->psm_requested && !wl->psm) {
984 mode = STATION_POWER_SAVE_MODE;
Kalle Valo80301cd2009-06-12 14:17:39 +0300985 ret = wl1251_ps_set_mode(wl, mode);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300986 if (ret < 0)
Kalle Valoc5483b72009-06-12 14:16:32 +0300987 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300988 }
989 }
990 }
991 if (changed & BSS_CHANGED_ERP_SLOT) {
992 if (bss_conf->use_short_slot)
Kalle Valo80301cd2009-06-12 14:17:39 +0300993 ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300994 else
Kalle Valo80301cd2009-06-12 14:17:39 +0300995 ret = wl1251_acx_slot(wl, SLOT_TIME_LONG);
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300996 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +0300997 wl1251_warning("Set slot time failed %d", ret);
Kalle Valoc5483b72009-06-12 14:16:32 +0300998 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +0300999 }
1000 }
1001
1002 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1003 if (bss_conf->use_short_preamble)
Kalle Valo80301cd2009-06-12 14:17:39 +03001004 wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001005 else
Kalle Valo80301cd2009-06-12 14:17:39 +03001006 wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001007 }
1008
1009 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1010 if (bss_conf->use_cts_prot)
Kalle Valo80301cd2009-06-12 14:17:39 +03001011 ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001012 else
Kalle Valo80301cd2009-06-12 14:17:39 +03001013 ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001014 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001015 wl1251_warning("Set ctsprotect failed %d", ret);
1016 goto out;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001017 }
1018 }
1019
1020 if (changed & BSS_CHANGED_BSSID) {
1021 memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
1022
Kalle Valo80301cd2009-06-12 14:17:39 +03001023 ret = wl1251_build_null_data(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001024 if (ret < 0)
1025 goto out;
1026
1027 if (wl->bss_type != BSS_TYPE_IBSS) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001028 ret = wl1251_cmd_join(wl, wl->bss_type, 5, 100, 1);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001029 if (ret < 0)
Kalle Valo80301cd2009-06-12 14:17:39 +03001030 goto out_sleep;
1031 wl1251_warning("Set ctsprotect failed %d", ret);
1032 goto out_sleep;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001033 }
1034 }
1035
1036 if (changed & BSS_CHANGED_BEACON) {
1037 beacon = ieee80211_beacon_get(hw, vif);
Kalle Valo80301cd2009-06-12 14:17:39 +03001038 ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001039 beacon->len);
1040
1041 if (ret < 0) {
1042 dev_kfree_skb(beacon);
1043 goto out;
1044 }
1045
Kalle Valo80301cd2009-06-12 14:17:39 +03001046 ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001047 beacon->len);
1048
1049 dev_kfree_skb(beacon);
1050
1051 if (ret < 0)
1052 goto out;
1053
Juuso Oikarinen77cc9e42009-06-12 14:16:52 +03001054 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001055
1056 if (ret < 0)
1057 goto out;
1058 }
1059
Kalle Valoc5483b72009-06-12 14:16:32 +03001060out_sleep:
Kalle Valo80301cd2009-06-12 14:17:39 +03001061 wl1251_ps_elp_sleep(wl);
Kalle Valoc5483b72009-06-12 14:16:32 +03001062
1063out:
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001064 mutex_unlock(&wl->mutex);
1065}
1066
1067
1068/* can't be const, mac80211 writes to this */
Kalle Valo80301cd2009-06-12 14:17:39 +03001069static struct ieee80211_rate wl1251_rates[] = {
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001070 { .bitrate = 10,
1071 .hw_value = 0x1,
1072 .hw_value_short = 0x1, },
1073 { .bitrate = 20,
1074 .hw_value = 0x2,
1075 .hw_value_short = 0x2,
1076 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1077 { .bitrate = 55,
1078 .hw_value = 0x4,
1079 .hw_value_short = 0x4,
1080 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1081 { .bitrate = 110,
1082 .hw_value = 0x20,
1083 .hw_value_short = 0x20,
1084 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1085 { .bitrate = 60,
1086 .hw_value = 0x8,
1087 .hw_value_short = 0x8, },
1088 { .bitrate = 90,
1089 .hw_value = 0x10,
1090 .hw_value_short = 0x10, },
1091 { .bitrate = 120,
1092 .hw_value = 0x40,
1093 .hw_value_short = 0x40, },
1094 { .bitrate = 180,
1095 .hw_value = 0x80,
1096 .hw_value_short = 0x80, },
1097 { .bitrate = 240,
1098 .hw_value = 0x200,
1099 .hw_value_short = 0x200, },
1100 { .bitrate = 360,
1101 .hw_value = 0x400,
1102 .hw_value_short = 0x400, },
1103 { .bitrate = 480,
1104 .hw_value = 0x800,
1105 .hw_value_short = 0x800, },
1106 { .bitrate = 540,
1107 .hw_value = 0x1000,
1108 .hw_value_short = 0x1000, },
1109};
1110
1111/* can't be const, mac80211 writes to this */
Kalle Valo80301cd2009-06-12 14:17:39 +03001112static struct ieee80211_channel wl1251_channels[] = {
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001113 { .hw_value = 1, .center_freq = 2412},
1114 { .hw_value = 2, .center_freq = 2417},
1115 { .hw_value = 3, .center_freq = 2422},
1116 { .hw_value = 4, .center_freq = 2427},
1117 { .hw_value = 5, .center_freq = 2432},
1118 { .hw_value = 6, .center_freq = 2437},
1119 { .hw_value = 7, .center_freq = 2442},
1120 { .hw_value = 8, .center_freq = 2447},
1121 { .hw_value = 9, .center_freq = 2452},
1122 { .hw_value = 10, .center_freq = 2457},
1123 { .hw_value = 11, .center_freq = 2462},
1124 { .hw_value = 12, .center_freq = 2467},
1125 { .hw_value = 13, .center_freq = 2472},
1126};
1127
1128/* can't be const, mac80211 writes to this */
Kalle Valo80301cd2009-06-12 14:17:39 +03001129static struct ieee80211_supported_band wl1251_band_2ghz = {
1130 .channels = wl1251_channels,
1131 .n_channels = ARRAY_SIZE(wl1251_channels),
1132 .bitrates = wl1251_rates,
1133 .n_bitrates = ARRAY_SIZE(wl1251_rates),
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001134};
1135
Kalle Valo80301cd2009-06-12 14:17:39 +03001136static const struct ieee80211_ops wl1251_ops = {
1137 .start = wl1251_op_start,
1138 .stop = wl1251_op_stop,
1139 .add_interface = wl1251_op_add_interface,
1140 .remove_interface = wl1251_op_remove_interface,
1141 .config = wl1251_op_config,
1142 .configure_filter = wl1251_op_configure_filter,
1143 .tx = wl1251_op_tx,
1144 .set_key = wl1251_op_set_key,
1145 .hw_scan = wl1251_op_hw_scan,
1146 .bss_info_changed = wl1251_op_bss_info_changed,
1147 .set_rts_threshold = wl1251_op_set_rts_threshold,
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001148};
1149
Kalle Valo80301cd2009-06-12 14:17:39 +03001150static int wl1251_register_hw(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001151{
1152 int ret;
1153
1154 if (wl->mac80211_registered)
1155 return 0;
1156
1157 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1158
1159 ret = ieee80211_register_hw(wl->hw);
1160 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001161 wl1251_error("unable to register mac80211 hw: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001162 return ret;
1163 }
1164
1165 wl->mac80211_registered = true;
1166
Kalle Valo80301cd2009-06-12 14:17:39 +03001167 wl1251_notice("loaded");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001168
1169 return 0;
1170}
1171
Kalle Valo80301cd2009-06-12 14:17:39 +03001172static int wl1251_init_ieee80211(struct wl1251 *wl)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001173{
1174 /* The tx descriptor buffer and the TKIP space */
1175 wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
Juuso Oikarinen9f2ad4f2009-06-12 14:15:54 +03001176 + WL1251_TKIP_IV_SPACE;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001177
1178 /* unit us */
1179 /* FIXME: find a proper value */
1180 wl->hw->channel_change_time = 10000;
1181
1182 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1183 IEEE80211_HW_NOISE_DBM;
1184
1185 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1186 wl->hw->wiphy->max_scan_ssids = 1;
Kalle Valo80301cd2009-06-12 14:17:39 +03001187 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001188
1189 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1190
1191 return 0;
1192}
1193
Bob Copeland08d9f5722009-08-07 13:33:11 +03001194extern struct wl1251_if_operations wl1251_spi_ops;
1195
Kalle Valo80301cd2009-06-12 14:17:39 +03001196#define WL1251_DEFAULT_CHANNEL 1
1197static int __devinit wl1251_probe(struct spi_device *spi)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001198{
1199 struct wl12xx_platform_data *pdata;
1200 struct ieee80211_hw *hw;
Kalle Valo80301cd2009-06-12 14:17:39 +03001201 struct wl1251 *wl;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001202 int ret, i;
1203 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1204
1205 pdata = spi->dev.platform_data;
1206 if (!pdata) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001207 wl1251_error("no platform data");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001208 return -ENODEV;
1209 }
1210
Kalle Valo80301cd2009-06-12 14:17:39 +03001211 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001212 if (!hw) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001213 wl1251_error("could not alloc ieee80211_hw");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001214 return -ENOMEM;
1215 }
1216
1217 wl = hw->priv;
1218 memset(wl, 0, sizeof(*wl));
1219
1220 wl->hw = hw;
1221 dev_set_drvdata(&spi->dev, wl);
1222 wl->spi = spi;
Bob Copeland08d9f5722009-08-07 13:33:11 +03001223 wl->if_ops = &wl1251_spi_ops;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001224
1225 wl->data_in_count = 0;
1226
1227 skb_queue_head_init(&wl->tx_queue);
1228
Kalle Valo80301cd2009-06-12 14:17:39 +03001229 INIT_WORK(&wl->filter_work, wl1251_filter_work);
1230 wl->channel = WL1251_DEFAULT_CHANNEL;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001231 wl->scanning = false;
1232 wl->default_key = 0;
1233 wl->listen_int = 1;
1234 wl->rx_counter = 0;
1235 wl->rx_handled = 0;
1236 wl->rx_current_buffer = 0;
1237 wl->rx_last_id = 0;
Kalle Valo80301cd2009-06-12 14:17:39 +03001238 wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
1239 wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001240 wl->elp = false;
1241 wl->psm = 0;
1242 wl->psm_requested = false;
1243 wl->tx_queue_stopped = false;
Kalle Valo80301cd2009-06-12 14:17:39 +03001244 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001245
1246 /* We use the default power on sleep time until we know which chip
1247 * we're using */
Kalle Valo80301cd2009-06-12 14:17:39 +03001248 wl->chip.power_on_sleep = WL1251_DEFAULT_POWER_ON_SLEEP;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001249
1250 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1251 wl->tx_frames[i] = NULL;
1252
1253 wl->next_tx_complete = 0;
1254
1255 /*
1256 * In case our MAC address is not correctly set,
1257 * we use a random but Nokia MAC.
1258 */
1259 memcpy(wl->mac_addr, nokia_oui, 3);
1260 get_random_bytes(wl->mac_addr + 3, 3);
1261
Kalle Valo80301cd2009-06-12 14:17:39 +03001262 wl->state = WL1251_STATE_OFF;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001263 mutex_init(&wl->mutex);
1264
1265 wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
1266 wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
1267
Kalle Valo47212132009-06-12 14:15:08 +03001268 wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
1269 if (!wl->rx_descriptor) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001270 wl1251_error("could not allocate memory for rx descriptor");
Kalle Valo47212132009-06-12 14:15:08 +03001271 ret = -ENOMEM;
1272 goto out_free;
1273 }
1274
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001275 /* This is the only SPI value that we need to set here, the rest
1276 * comes from the board-peripherals file */
1277 spi->bits_per_word = 32;
1278
1279 ret = spi_setup(spi);
1280 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001281 wl1251_error("spi_setup failed");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001282 goto out_free;
1283 }
1284
1285 wl->set_power = pdata->set_power;
1286 if (!wl->set_power) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001287 wl1251_error("set power function missing in platform data");
Kalle Valoc4f5c852009-06-12 14:14:34 +03001288 ret = -ENODEV;
1289 goto out_free;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001290 }
1291
1292 wl->irq = spi->irq;
1293 if (wl->irq < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001294 wl1251_error("irq missing in platform data");
Kalle Valoc4f5c852009-06-12 14:14:34 +03001295 ret = -ENODEV;
1296 goto out_free;
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001297 }
1298
Kalle Valo80301cd2009-06-12 14:17:39 +03001299 ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001300 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001301 wl1251_error("request_irq() failed: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001302 goto out_free;
1303 }
1304
1305 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1306
1307 disable_irq(wl->irq);
1308
Kalle Valo80301cd2009-06-12 14:17:39 +03001309 ret = wl1251_init_ieee80211(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001310 if (ret)
1311 goto out_irq;
1312
Kalle Valo80301cd2009-06-12 14:17:39 +03001313 ret = wl1251_register_hw(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001314 if (ret)
1315 goto out_irq;
1316
Kalle Valo80301cd2009-06-12 14:17:39 +03001317 wl1251_debugfs_init(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001318
Kalle Valo80301cd2009-06-12 14:17:39 +03001319 wl1251_notice("initialized");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001320
1321 return 0;
1322
1323 out_irq:
1324 free_irq(wl->irq, wl);
1325
1326 out_free:
Kalle Valo47212132009-06-12 14:15:08 +03001327 kfree(wl->rx_descriptor);
1328 wl->rx_descriptor = NULL;
1329
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001330 ieee80211_free_hw(hw);
1331
1332 return ret;
1333}
1334
Kalle Valo80301cd2009-06-12 14:17:39 +03001335static int __devexit wl1251_remove(struct spi_device *spi)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001336{
Kalle Valo80301cd2009-06-12 14:17:39 +03001337 struct wl1251 *wl = dev_get_drvdata(&spi->dev);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001338
1339 ieee80211_unregister_hw(wl->hw);
1340
Kalle Valo80301cd2009-06-12 14:17:39 +03001341 wl1251_debugfs_exit(wl);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001342
1343 free_irq(wl->irq, wl);
1344 kfree(wl->target_mem_map);
1345 kfree(wl->data_path);
1346 kfree(wl->fw);
1347 wl->fw = NULL;
1348 kfree(wl->nvs);
1349 wl->nvs = NULL;
Kalle Valo47212132009-06-12 14:15:08 +03001350
1351 kfree(wl->rx_descriptor);
1352 wl->rx_descriptor = NULL;
1353
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001354 ieee80211_free_hw(wl->hw);
1355
1356 return 0;
1357}
1358
1359
Kalle Valo80301cd2009-06-12 14:17:39 +03001360static struct spi_driver wl1251_spi_driver = {
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001361 .driver = {
Kalle Valo80301cd2009-06-12 14:17:39 +03001362 /* FIXME: use wl12xx name to not break the user space */
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001363 .name = "wl12xx",
1364 .bus = &spi_bus_type,
1365 .owner = THIS_MODULE,
1366 },
1367
Kalle Valo80301cd2009-06-12 14:17:39 +03001368 .probe = wl1251_probe,
1369 .remove = __devexit_p(wl1251_remove),
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001370};
1371
Kalle Valo80301cd2009-06-12 14:17:39 +03001372static int __init wl1251_init(void)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001373{
1374 int ret;
1375
Kalle Valo80301cd2009-06-12 14:17:39 +03001376 ret = spi_register_driver(&wl1251_spi_driver);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001377 if (ret < 0) {
Kalle Valo80301cd2009-06-12 14:17:39 +03001378 wl1251_error("failed to register spi driver: %d", ret);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001379 goto out;
1380 }
1381
1382out:
1383 return ret;
1384}
1385
Kalle Valo80301cd2009-06-12 14:17:39 +03001386static void __exit wl1251_exit(void)
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001387{
Kalle Valo80301cd2009-06-12 14:17:39 +03001388 spi_unregister_driver(&wl1251_spi_driver);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001389
Kalle Valo80301cd2009-06-12 14:17:39 +03001390 wl1251_notice("unloaded");
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001391}
1392
Kalle Valo80301cd2009-06-12 14:17:39 +03001393module_init(wl1251_init);
1394module_exit(wl1251_exit);
Kalle Valo2f01a1f2009-04-29 23:33:31 +03001395
1396MODULE_LICENSE("GPL");
1397MODULE_AUTHOR("Kalle Valo <Kalle.Valo@nokia.com>, "
1398 "Luciano Coelho <luciano.coelho@nokia.com>");