1 /*
2 * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers
3 *
4 * Copyright (c) 2010, ST-Ericsson
5 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
6 *
7 * Based on:
8 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
9 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
10 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
11 *
12 * Based on:
13 * - the islsm (softmac prism54) driver, which is:
14 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
15 * - stlc45xx driver
16 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2 as
20 * published by the Free Software Foundation.
21 */
22
23 #include <linux/module.h>
24 #include <linux/firmware.h>
25 #include <linux/etherdevice.h>
26 #include <linux/vmalloc.h>
27 #include <linux/random.h>
28 #include <linux/sched.h>
29 #include <net/mac80211.h>
30
31 #include "cw1200.h"
32 #include "txrx.h"
33 #include "hwbus.h"
34 #include "fwio.h"
35 #include "hwio.h"
36 #include "bh.h"
37 #include "sta.h"
38 #include "scan.h"
39 #include "debug.h"
40 #include "pm.h"
41
42 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
43 MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
44 MODULE_LICENSE("GPL");
45 MODULE_ALIAS("cw1200_core");
46
47 /* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
48 static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
49 module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, S_IRUGO);
50 MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
51
52 static char *cw1200_sdd_path;
53 module_param(cw1200_sdd_path, charp, 0644);
54 MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
55 static int cw1200_refclk;
56 module_param(cw1200_refclk, int, 0644);
57 MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
58
59 int cw1200_power_mode = wsm_power_mode_quiescent;
60 module_param(cw1200_power_mode, int, 0644);
61 MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode. 0 == active, 1 == doze, 2 == quiescent (default)");
62
63 #define RATETAB_ENT(_rate, _rateid, _flags) \
64 { \
65 .bitrate = (_rate), \
66 .hw_value = (_rateid), \
67 .flags = (_flags), \
68 }
69
70 static struct ieee80211_rate cw1200_rates[] = {
71 RATETAB_ENT(10, 0, 0),
72 RATETAB_ENT(20, 1, 0),
73 RATETAB_ENT(55, 2, 0),
74 RATETAB_ENT(110, 3, 0),
75 RATETAB_ENT(60, 6, 0),
76 RATETAB_ENT(90, 7, 0),
77 RATETAB_ENT(120, 8, 0),
78 RATETAB_ENT(180, 9, 0),
79 RATETAB_ENT(240, 10, 0),
80 RATETAB_ENT(360, 11, 0),
81 RATETAB_ENT(480, 12, 0),
82 RATETAB_ENT(540, 13, 0),
83 };
84
85 static struct ieee80211_rate cw1200_mcs_rates[] = {
86 RATETAB_ENT(65, 14, IEEE80211_TX_RC_MCS),
87 RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
88 RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
89 RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
90 RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
91 RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
92 RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
93 RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
94 };
95
96 #define cw1200_a_rates (cw1200_rates + 4)
97 #define cw1200_a_rates_size (ARRAY_SIZE(cw1200_rates) - 4)
98 #define cw1200_g_rates (cw1200_rates + 0)
99 #define cw1200_g_rates_size (ARRAY_SIZE(cw1200_rates))
100 #define cw1200_n_rates (cw1200_mcs_rates)
101 #define cw1200_n_rates_size (ARRAY_SIZE(cw1200_mcs_rates))
102
103
104 #define CHAN2G(_channel, _freq, _flags) { \
105 .band = NL80211_BAND_2GHZ, \
106 .center_freq = (_freq), \
107 .hw_value = (_channel), \
108 .flags = (_flags), \
109 .max_antenna_gain = 0, \
110 .max_power = 30, \
111 }
112
113 #define CHAN5G(_channel, _flags) { \
114 .band = NL80211_BAND_5GHZ, \
115 .center_freq = 5000 + (5 * (_channel)), \
116 .hw_value = (_channel), \
117 .flags = (_flags), \
118 .max_antenna_gain = 0, \
119 .max_power = 30, \
120 }
121
122 static struct ieee80211_channel cw1200_2ghz_chantable[] = {
123 CHAN2G(1, 2412, 0),
124 CHAN2G(2, 2417, 0),
125 CHAN2G(3, 2422, 0),
126 CHAN2G(4, 2427, 0),
127 CHAN2G(5, 2432, 0),
128 CHAN2G(6, 2437, 0),
129 CHAN2G(7, 2442, 0),
130 CHAN2G(8, 2447, 0),
131 CHAN2G(9, 2452, 0),
132 CHAN2G(10, 2457, 0),
133 CHAN2G(11, 2462, 0),
134 CHAN2G(12, 2467, 0),
135 CHAN2G(13, 2472, 0),
136 CHAN2G(14, 2484, 0),
137 };
138
139 static struct ieee80211_channel cw1200_5ghz_chantable[] = {
140 CHAN5G(34, 0), CHAN5G(36, 0),
141 CHAN5G(38, 0), CHAN5G(40, 0),
142 CHAN5G(42, 0), CHAN5G(44, 0),
143 CHAN5G(46, 0), CHAN5G(48, 0),
144 CHAN5G(52, 0), CHAN5G(56, 0),
145 CHAN5G(60, 0), CHAN5G(64, 0),
146 CHAN5G(100, 0), CHAN5G(104, 0),
147 CHAN5G(108, 0), CHAN5G(112, 0),
148 CHAN5G(116, 0), CHAN5G(120, 0),
149 CHAN5G(124, 0), CHAN5G(128, 0),
150 CHAN5G(132, 0), CHAN5G(136, 0),
151 CHAN5G(140, 0), CHAN5G(149, 0),
152 CHAN5G(153, 0), CHAN5G(157, 0),
153 CHAN5G(161, 0), CHAN5G(165, 0),
154 CHAN5G(184, 0), CHAN5G(188, 0),
155 CHAN5G(192, 0), CHAN5G(196, 0),
156 CHAN5G(200, 0), CHAN5G(204, 0),
157 CHAN5G(208, 0), CHAN5G(212, 0),
158 CHAN5G(216, 0),
159 };
160
161 static struct ieee80211_supported_band cw1200_band_2ghz = {
162 .channels = cw1200_2ghz_chantable,
163 .n_channels = ARRAY_SIZE(cw1200_2ghz_chantable),
164 .bitrates = cw1200_g_rates,
165 .n_bitrates = cw1200_g_rates_size,
166 .ht_cap = {
167 .cap = IEEE80211_HT_CAP_GRN_FLD |
168 (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
169 IEEE80211_HT_CAP_MAX_AMSDU,
170 .ht_supported = 1,
171 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
172 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
173 .mcs = {
174 .rx_mask[0] = 0xFF,
175 .rx_highest = __cpu_to_le16(0x41),
176 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
177 },
178 },
179 };
180
181 static struct ieee80211_supported_band cw1200_band_5ghz = {
182 .channels = cw1200_5ghz_chantable,
183 .n_channels = ARRAY_SIZE(cw1200_5ghz_chantable),
184 .bitrates = cw1200_a_rates,
185 .n_bitrates = cw1200_a_rates_size,
186 .ht_cap = {
187 .cap = IEEE80211_HT_CAP_GRN_FLD |
188 (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
189 IEEE80211_HT_CAP_MAX_AMSDU,
190 .ht_supported = 1,
191 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
192 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
193 .mcs = {
194 .rx_mask[0] = 0xFF,
195 .rx_highest = __cpu_to_le16(0x41),
196 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
197 },
198 },
199 };
200
201 static const unsigned long cw1200_ttl[] = {
202 1 * HZ, /* VO */
203 2 * HZ, /* VI */
204 5 * HZ, /* BE */
205 10 * HZ /* BK */
206 };
207
208 static const struct ieee80211_ops cw1200_ops = {
209 .start = cw1200_start,
210 .stop = cw1200_stop,
211 .add_interface = cw1200_add_interface,
212 .remove_interface = cw1200_remove_interface,
213 .change_interface = cw1200_change_interface,
214 .tx = cw1200_tx,
215 .hw_scan = cw1200_hw_scan,
216 .set_tim = cw1200_set_tim,
217 .sta_notify = cw1200_sta_notify,
218 .sta_add = cw1200_sta_add,
219 .sta_remove = cw1200_sta_remove,
220 .set_key = cw1200_set_key,
221 .set_rts_threshold = cw1200_set_rts_threshold,
222 .config = cw1200_config,
223 .bss_info_changed = cw1200_bss_info_changed,
224 .prepare_multicast = cw1200_prepare_multicast,
225 .configure_filter = cw1200_configure_filter,
226 .conf_tx = cw1200_conf_tx,
227 .get_stats = cw1200_get_stats,
228 .ampdu_action = cw1200_ampdu_action,
229 .flush = cw1200_flush,
230 #ifdef CONFIG_PM
231 .suspend = cw1200_wow_suspend,
232 .resume = cw1200_wow_resume,
233 #endif
234 /* Intentionally not offloaded: */
235 /*.channel_switch = cw1200_channel_switch, */
236 /*.remain_on_channel = cw1200_remain_on_channel, */
237 /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel, */
238 };
239
240 static int cw1200_ba_rx_tids = -1;
241 static int cw1200_ba_tx_tids = -1;
242 module_param(cw1200_ba_rx_tids, int, 0644);
243 module_param(cw1200_ba_tx_tids, int, 0644);
244 MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
245 MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
246
247 #ifdef CONFIG_PM
248 static const struct wiphy_wowlan_support cw1200_wowlan_support = {
249 /* Support only for limited wowlan functionalities */
250 .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
251 };
252 #endif
253
254
cw1200_init_common(const u8 * macaddr,const bool have_5ghz)255 static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
256 const bool have_5ghz)
257 {
258 int i, band;
259 struct ieee80211_hw *hw;
260 struct cw1200_common *priv;
261
262 hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
263 if (!hw)
264 return NULL;
265
266 priv = hw->priv;
267 priv->hw = hw;
268 priv->hw_type = -1;
269 priv->mode = NL80211_IFTYPE_UNSPECIFIED;
270 priv->rates = cw1200_rates; /* TODO: fetch from FW */
271 priv->mcs_rates = cw1200_n_rates;
272 if (cw1200_ba_rx_tids != -1)
273 priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
274 else
275 priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
276 if (cw1200_ba_tx_tids != -1)
277 priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
278 else
279 priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
280
281 ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
282 ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
283 ieee80211_hw_set(hw, AMPDU_AGGREGATION);
284 ieee80211_hw_set(hw, CONNECTION_MONITOR);
285 ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
286 ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
287 ieee80211_hw_set(hw, SIGNAL_DBM);
288 ieee80211_hw_set(hw, SUPPORTS_PS);
289
290 hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
291 BIT(NL80211_IFTYPE_ADHOC) |
292 BIT(NL80211_IFTYPE_AP) |
293 BIT(NL80211_IFTYPE_MESH_POINT) |
294 BIT(NL80211_IFTYPE_P2P_CLIENT) |
295 BIT(NL80211_IFTYPE_P2P_GO);
296
297 #ifdef CONFIG_PM
298 hw->wiphy->wowlan = &cw1200_wowlan_support;
299 #endif
300
301 hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
302
303 hw->queues = 4;
304
305 priv->rts_threshold = -1;
306
307 hw->max_rates = 8;
308 hw->max_rate_tries = 15;
309 hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
310 8; /* TKIP IV */
311
312 hw->sta_data_size = sizeof(struct cw1200_sta_priv);
313
314 hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
315 if (have_5ghz)
316 hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
317
318 /* Channel params have to be cleared before registering wiphy again */
319 for (band = 0; band < NUM_NL80211_BANDS; band++) {
320 struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
321 if (!sband)
322 continue;
323 for (i = 0; i < sband->n_channels; i++) {
324 sband->channels[i].flags = 0;
325 sband->channels[i].max_antenna_gain = 0;
326 sband->channels[i].max_power = 30;
327 }
328 }
329
330 hw->wiphy->max_scan_ssids = 2;
331 hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
332
333 if (macaddr)
334 SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
335 else
336 SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
337
338 /* Fix up mac address if necessary */
339 if (hw->wiphy->perm_addr[3] == 0 &&
340 hw->wiphy->perm_addr[4] == 0 &&
341 hw->wiphy->perm_addr[5] == 0) {
342 get_random_bytes(&hw->wiphy->perm_addr[3], 3);
343 }
344
345 mutex_init(&priv->wsm_cmd_mux);
346 mutex_init(&priv->conf_mutex);
347 priv->workqueue = create_singlethread_workqueue("cw1200_wq");
348 if (!priv->workqueue) {
349 ieee80211_free_hw(hw);
350 return NULL;
351 }
352
353 sema_init(&priv->scan.lock, 1);
354 INIT_WORK(&priv->scan.work, cw1200_scan_work);
355 INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
356 INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
357 INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
358 cw1200_clear_recent_scan_work);
359 INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
360 INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
361 INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
362 INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
363 INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
364 spin_lock_init(&priv->event_queue_lock);
365 INIT_LIST_HEAD(&priv->event_queue);
366 INIT_WORK(&priv->event_handler, cw1200_event_handler);
367 INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
368 INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
369 spin_lock_init(&priv->bss_loss_lock);
370 spin_lock_init(&priv->ps_state_lock);
371 INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
372 INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
373 INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
374 INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
375 INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
376 INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
377 INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
378 INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
379 INIT_WORK(&priv->set_beacon_wakeup_period_work,
380 cw1200_set_beacon_wakeup_period_work);
381 setup_timer(&priv->mcast_timeout, cw1200_mcast_timeout,
382 (unsigned long)priv);
383
384 if (cw1200_queue_stats_init(&priv->tx_queue_stats,
385 CW1200_LINK_ID_MAX,
386 cw1200_skb_dtor,
387 priv)) {
388 ieee80211_free_hw(hw);
389 return NULL;
390 }
391
392 for (i = 0; i < 4; ++i) {
393 if (cw1200_queue_init(&priv->tx_queue[i],
394 &priv->tx_queue_stats, i, 16,
395 cw1200_ttl[i])) {
396 for (; i > 0; i--)
397 cw1200_queue_deinit(&priv->tx_queue[i - 1]);
398 cw1200_queue_stats_deinit(&priv->tx_queue_stats);
399 ieee80211_free_hw(hw);
400 return NULL;
401 }
402 }
403
404 init_waitqueue_head(&priv->channel_switch_done);
405 init_waitqueue_head(&priv->wsm_cmd_wq);
406 init_waitqueue_head(&priv->wsm_startup_done);
407 init_waitqueue_head(&priv->ps_mode_switch_done);
408 wsm_buf_init(&priv->wsm_cmd_buf);
409 spin_lock_init(&priv->wsm_cmd.lock);
410 priv->wsm_cmd.done = 1;
411 tx_policy_init(priv);
412
413 return hw;
414 }
415
cw1200_register_common(struct ieee80211_hw * dev)416 static int cw1200_register_common(struct ieee80211_hw *dev)
417 {
418 struct cw1200_common *priv = dev->priv;
419 int err;
420
421 #ifdef CONFIG_PM
422 err = cw1200_pm_init(&priv->pm_state, priv);
423 if (err) {
424 pr_err("Cannot init PM. (%d).\n",
425 err);
426 return err;
427 }
428 #endif
429
430 err = ieee80211_register_hw(dev);
431 if (err) {
432 pr_err("Cannot register device (%d).\n",
433 err);
434 #ifdef CONFIG_PM
435 cw1200_pm_deinit(&priv->pm_state);
436 #endif
437 return err;
438 }
439
440 cw1200_debug_init(priv);
441
442 pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
443 return 0;
444 }
445
cw1200_free_common(struct ieee80211_hw * dev)446 static void cw1200_free_common(struct ieee80211_hw *dev)
447 {
448 ieee80211_free_hw(dev);
449 }
450
cw1200_unregister_common(struct ieee80211_hw * dev)451 static void cw1200_unregister_common(struct ieee80211_hw *dev)
452 {
453 struct cw1200_common *priv = dev->priv;
454 int i;
455
456 ieee80211_unregister_hw(dev);
457
458 del_timer_sync(&priv->mcast_timeout);
459 cw1200_unregister_bh(priv);
460
461 cw1200_debug_release(priv);
462
463 mutex_destroy(&priv->conf_mutex);
464
465 wsm_buf_deinit(&priv->wsm_cmd_buf);
466
467 destroy_workqueue(priv->workqueue);
468 priv->workqueue = NULL;
469
470 if (priv->sdd) {
471 release_firmware(priv->sdd);
472 priv->sdd = NULL;
473 }
474
475 for (i = 0; i < 4; ++i)
476 cw1200_queue_deinit(&priv->tx_queue[i]);
477
478 cw1200_queue_stats_deinit(&priv->tx_queue_stats);
479 #ifdef CONFIG_PM
480 cw1200_pm_deinit(&priv->pm_state);
481 #endif
482 }
483
484 /* Clock is in KHz */
cw1200_dpll_from_clk(u16 clk_khz)485 u32 cw1200_dpll_from_clk(u16 clk_khz)
486 {
487 switch (clk_khz) {
488 case 0x32C8: /* 13000 KHz */
489 return 0x1D89D241;
490 case 0x3E80: /* 16000 KHz */
491 return 0x000001E1;
492 case 0x41A0: /* 16800 KHz */
493 return 0x124931C1;
494 case 0x4B00: /* 19200 KHz */
495 return 0x00000191;
496 case 0x5DC0: /* 24000 KHz */
497 return 0x00000141;
498 case 0x6590: /* 26000 KHz */
499 return 0x0EC4F121;
500 case 0x8340: /* 33600 KHz */
501 return 0x092490E1;
502 case 0x9600: /* 38400 KHz */
503 return 0x100010C1;
504 case 0x9C40: /* 40000 KHz */
505 return 0x000000C1;
506 case 0xBB80: /* 48000 KHz */
507 return 0x000000A1;
508 case 0xCB20: /* 52000 KHz */
509 return 0x07627091;
510 default:
511 pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
512 clk_khz);
513 return 0x0EC4F121;
514 }
515 }
516
cw1200_core_probe(const struct hwbus_ops * hwbus_ops,struct hwbus_priv * hwbus,struct device * pdev,struct cw1200_common ** core,int ref_clk,const u8 * macaddr,const char * sdd_path,bool have_5ghz)517 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
518 struct hwbus_priv *hwbus,
519 struct device *pdev,
520 struct cw1200_common **core,
521 int ref_clk, const u8 *macaddr,
522 const char *sdd_path, bool have_5ghz)
523 {
524 int err = -EINVAL;
525 struct ieee80211_hw *dev;
526 struct cw1200_common *priv;
527 struct wsm_operational_mode mode = {
528 .power_mode = cw1200_power_mode,
529 .disable_more_flag_usage = true,
530 };
531
532 dev = cw1200_init_common(macaddr, have_5ghz);
533 if (!dev)
534 goto err;
535
536 priv = dev->priv;
537 priv->hw_refclk = ref_clk;
538 if (cw1200_refclk)
539 priv->hw_refclk = cw1200_refclk;
540
541 priv->sdd_path = (char *)sdd_path;
542 if (cw1200_sdd_path)
543 priv->sdd_path = cw1200_sdd_path;
544
545 priv->hwbus_ops = hwbus_ops;
546 priv->hwbus_priv = hwbus;
547 priv->pdev = pdev;
548 SET_IEEE80211_DEV(priv->hw, pdev);
549
550 /* Pass struct cw1200_common back up */
551 *core = priv;
552
553 err = cw1200_register_bh(priv);
554 if (err)
555 goto err1;
556
557 err = cw1200_load_firmware(priv);
558 if (err)
559 goto err2;
560
561 if (wait_event_interruptible_timeout(priv->wsm_startup_done,
562 priv->firmware_ready,
563 3*HZ) <= 0) {
564 /* TODO: Need to find how to reset device
565 in QUEUE mode properly.
566 */
567 pr_err("Timeout waiting on device startup\n");
568 err = -ETIMEDOUT;
569 goto err2;
570 }
571
572 /* Set low-power mode. */
573 wsm_set_operational_mode(priv, &mode);
574
575 /* Enable multi-TX confirmation */
576 wsm_use_multi_tx_conf(priv, true);
577
578 err = cw1200_register_common(dev);
579 if (err)
580 goto err2;
581
582 return err;
583
584 err2:
585 cw1200_unregister_bh(priv);
586 err1:
587 cw1200_free_common(dev);
588 err:
589 *core = NULL;
590 return err;
591 }
592 EXPORT_SYMBOL_GPL(cw1200_core_probe);
593
cw1200_core_release(struct cw1200_common * self)594 void cw1200_core_release(struct cw1200_common *self)
595 {
596 /* Disable device interrupts */
597 self->hwbus_ops->lock(self->hwbus_priv);
598 __cw1200_irq_enable(self, 0);
599 self->hwbus_ops->unlock(self->hwbus_priv);
600
601 /* And then clean up */
602 cw1200_unregister_common(self->hw);
603 cw1200_free_common(self->hw);
604 return;
605 }
606 EXPORT_SYMBOL_GPL(cw1200_core_release);
607