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