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 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 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 449 static void cw1200_free_common(struct ieee80211_hw *dev) 450 { 451 ieee80211_free_hw(dev); 452 } 453 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 */ 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 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 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