linux/drivers/net/wireless/st/cw1200/main.c
<<
>>
Prefs
   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
  39MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
  40MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
  41MODULE_LICENSE("GPL");
  42MODULE_ALIAS("cw1200_core");
  43
  44/* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
  45static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
  46module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, 0444);
  47MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
  48
  49static char *cw1200_sdd_path;
  50module_param(cw1200_sdd_path, charp, 0644);
  51MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
  52static int cw1200_refclk;
  53module_param(cw1200_refclk, int, 0644);
  54MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
  55
  56int cw1200_power_mode = wsm_power_mode_quiescent;
  57module_param(cw1200_power_mode, int, 0644);
  58MODULE_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
  67static 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
  82static 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
 119static 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
 136static 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
 158static 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
 178static 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
 198static const unsigned long cw1200_ttl[] = {
 199        1 * HZ, /* VO */
 200        2 * HZ, /* VI */
 201        5 * HZ, /* BE */
 202        10 * HZ /* BK */
 203};
 204
 205static const struct ieee80211_ops cw1200_ops = {
 206        .start                  = cw1200_start,
 207        .stop                   = cw1200_stop,
 208        .add_interface          = cw1200_add_interface,
 209        .remove_interface       = cw1200_remove_interface,
 210        .change_interface       = cw1200_change_interface,
 211        .tx                     = cw1200_tx,
 212        .hw_scan                = cw1200_hw_scan,
 213        .set_tim                = cw1200_set_tim,
 214        .sta_notify             = cw1200_sta_notify,
 215        .sta_add                = cw1200_sta_add,
 216        .sta_remove             = cw1200_sta_remove,
 217        .set_key                = cw1200_set_key,
 218        .set_rts_threshold      = cw1200_set_rts_threshold,
 219        .config                 = cw1200_config,
 220        .bss_info_changed       = cw1200_bss_info_changed,
 221        .prepare_multicast      = cw1200_prepare_multicast,
 222        .configure_filter       = cw1200_configure_filter,
 223        .conf_tx                = cw1200_conf_tx,
 224        .get_stats              = cw1200_get_stats,
 225        .ampdu_action           = cw1200_ampdu_action,
 226        .flush                  = cw1200_flush,
 227#ifdef CONFIG_PM
 228        .suspend                = cw1200_wow_suspend,
 229        .resume                 = cw1200_wow_resume,
 230#endif
 231        /* Intentionally not offloaded:                                 */
 232        /*.channel_switch       = cw1200_channel_switch,                */
 233        /*.remain_on_channel    = cw1200_remain_on_channel,             */
 234        /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,  */
 235};
 236
 237static int cw1200_ba_rx_tids = -1;
 238static int cw1200_ba_tx_tids = -1;
 239module_param(cw1200_ba_rx_tids, int, 0644);
 240module_param(cw1200_ba_tx_tids, int, 0644);
 241MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
 242MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
 243
 244#ifdef CONFIG_PM
 245static const struct wiphy_wowlan_support cw1200_wowlan_support = {
 246        /* Support only for limited wowlan functionalities */
 247        .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
 248};
 249#endif
 250
 251
 252static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
 253                                                const bool have_5ghz)
 254{
 255        int i, band;
 256        struct ieee80211_hw *hw;
 257        struct cw1200_common *priv;
 258
 259        hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
 260        if (!hw)
 261                return NULL;
 262
 263        priv = hw->priv;
 264        priv->hw = hw;
 265        priv->hw_type = -1;
 266        priv->mode = NL80211_IFTYPE_UNSPECIFIED;
 267        priv->rates = cw1200_rates; /* TODO: fetch from FW */
 268        priv->mcs_rates = cw1200_n_rates;
 269        if (cw1200_ba_rx_tids != -1)
 270                priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
 271        else
 272                priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
 273        if (cw1200_ba_tx_tids != -1)
 274                priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
 275        else
 276                priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
 277
 278        ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
 279        ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
 280        ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 281        ieee80211_hw_set(hw, CONNECTION_MONITOR);
 282        ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
 283        ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 284        ieee80211_hw_set(hw, SIGNAL_DBM);
 285        ieee80211_hw_set(hw, SUPPORTS_PS);
 286
 287        hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 288                                          BIT(NL80211_IFTYPE_ADHOC) |
 289                                          BIT(NL80211_IFTYPE_AP) |
 290                                          BIT(NL80211_IFTYPE_MESH_POINT) |
 291                                          BIT(NL80211_IFTYPE_P2P_CLIENT) |
 292                                          BIT(NL80211_IFTYPE_P2P_GO);
 293
 294#ifdef CONFIG_PM
 295        hw->wiphy->wowlan = &cw1200_wowlan_support;
 296#endif
 297
 298        hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 299
 300        hw->queues = 4;
 301
 302        priv->rts_threshold = -1;
 303
 304        hw->max_rates = 8;
 305        hw->max_rate_tries = 15;
 306        hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
 307                8;  /* TKIP IV */
 308
 309        hw->sta_data_size = sizeof(struct cw1200_sta_priv);
 310
 311        hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
 312        if (have_5ghz)
 313                hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
 314
 315        /* Channel params have to be cleared before registering wiphy again */
 316        for (band = 0; band < NUM_NL80211_BANDS; band++) {
 317                struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
 318                if (!sband)
 319                        continue;
 320                for (i = 0; i < sband->n_channels; i++) {
 321                        sband->channels[i].flags = 0;
 322                        sband->channels[i].max_antenna_gain = 0;
 323                        sband->channels[i].max_power = 30;
 324                }
 325        }
 326
 327        hw->wiphy->max_scan_ssids = 2;
 328        hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
 329
 330        if (macaddr)
 331                SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
 332        else
 333                SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
 334
 335        /* Fix up mac address if necessary */
 336        if (hw->wiphy->perm_addr[3] == 0 &&
 337            hw->wiphy->perm_addr[4] == 0 &&
 338            hw->wiphy->perm_addr[5] == 0) {
 339                get_random_bytes(&hw->wiphy->perm_addr[3], 3);
 340        }
 341
 342        mutex_init(&priv->wsm_cmd_mux);
 343        mutex_init(&priv->conf_mutex);
 344        priv->workqueue = create_singlethread_workqueue("cw1200_wq");
 345        if (!priv->workqueue) {
 346                ieee80211_free_hw(hw);
 347                return NULL;
 348        }
 349
 350        sema_init(&priv->scan.lock, 1);
 351        INIT_WORK(&priv->scan.work, cw1200_scan_work);
 352        INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
 353        INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
 354        INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
 355                          cw1200_clear_recent_scan_work);
 356        INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
 357        INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
 358        INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
 359        INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
 360        INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
 361        spin_lock_init(&priv->event_queue_lock);
 362        INIT_LIST_HEAD(&priv->event_queue);
 363        INIT_WORK(&priv->event_handler, cw1200_event_handler);
 364        INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
 365        INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
 366        spin_lock_init(&priv->bss_loss_lock);
 367        spin_lock_init(&priv->ps_state_lock);
 368        INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
 369        INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
 370        INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
 371        INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
 372        INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
 373        INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
 374        INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
 375        INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
 376        INIT_WORK(&priv->set_beacon_wakeup_period_work,
 377                  cw1200_set_beacon_wakeup_period_work);
 378        timer_setup(&priv->mcast_timeout, cw1200_mcast_timeout, 0);
 379
 380        if (cw1200_queue_stats_init(&priv->tx_queue_stats,
 381                                    CW1200_LINK_ID_MAX,
 382                                    cw1200_skb_dtor,
 383                                    priv)) {
 384                destroy_workqueue(priv->workqueue);
 385                ieee80211_free_hw(hw);
 386                return NULL;
 387        }
 388
 389        for (i = 0; i < 4; ++i) {
 390                if (cw1200_queue_init(&priv->tx_queue[i],
 391                                      &priv->tx_queue_stats, i, 16,
 392                                      cw1200_ttl[i])) {
 393                        for (; i > 0; i--)
 394                                cw1200_queue_deinit(&priv->tx_queue[i - 1]);
 395                        cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 396                        destroy_workqueue(priv->workqueue);
 397                        ieee80211_free_hw(hw);
 398                        return NULL;
 399                }
 400        }
 401
 402        init_waitqueue_head(&priv->channel_switch_done);
 403        init_waitqueue_head(&priv->wsm_cmd_wq);
 404        init_waitqueue_head(&priv->wsm_startup_done);
 405        init_waitqueue_head(&priv->ps_mode_switch_done);
 406        wsm_buf_init(&priv->wsm_cmd_buf);
 407        spin_lock_init(&priv->wsm_cmd.lock);
 408        priv->wsm_cmd.done = 1;
 409        tx_policy_init(priv);
 410
 411        return hw;
 412}
 413
 414static int cw1200_register_common(struct ieee80211_hw *dev)
 415{
 416        struct cw1200_common *priv = dev->priv;
 417        int err;
 418
 419#ifdef CONFIG_PM
 420        err = cw1200_pm_init(&priv->pm_state, priv);
 421        if (err) {
 422                pr_err("Cannot init PM. (%d).\n",
 423                       err);
 424                return err;
 425        }
 426#endif
 427
 428        err = ieee80211_register_hw(dev);
 429        if (err) {
 430                pr_err("Cannot register device (%d).\n",
 431                       err);
 432#ifdef CONFIG_PM
 433                cw1200_pm_deinit(&priv->pm_state);
 434#endif
 435                return err;
 436        }
 437
 438        cw1200_debug_init(priv);
 439
 440        pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
 441        return 0;
 442}
 443
 444static void cw1200_free_common(struct ieee80211_hw *dev)
 445{
 446        ieee80211_free_hw(dev);
 447}
 448
 449static void cw1200_unregister_common(struct ieee80211_hw *dev)
 450{
 451        struct cw1200_common *priv = dev->priv;
 452        int i;
 453
 454        ieee80211_unregister_hw(dev);
 455
 456        del_timer_sync(&priv->mcast_timeout);
 457        cw1200_unregister_bh(priv);
 458
 459        cw1200_debug_release(priv);
 460
 461        mutex_destroy(&priv->conf_mutex);
 462
 463        wsm_buf_deinit(&priv->wsm_cmd_buf);
 464
 465        destroy_workqueue(priv->workqueue);
 466        priv->workqueue = NULL;
 467
 468        if (priv->sdd) {
 469                release_firmware(priv->sdd);
 470                priv->sdd = NULL;
 471        }
 472
 473        for (i = 0; i < 4; ++i)
 474                cw1200_queue_deinit(&priv->tx_queue[i]);
 475
 476        cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 477#ifdef CONFIG_PM
 478        cw1200_pm_deinit(&priv->pm_state);
 479#endif
 480}
 481
 482/* Clock is in KHz */
 483u32 cw1200_dpll_from_clk(u16 clk_khz)
 484{
 485        switch (clk_khz) {
 486        case 0x32C8: /* 13000 KHz */
 487                return 0x1D89D241;
 488        case 0x3E80: /* 16000 KHz */
 489                return 0x000001E1;
 490        case 0x41A0: /* 16800 KHz */
 491                return 0x124931C1;
 492        case 0x4B00: /* 19200 KHz */
 493                return 0x00000191;
 494        case 0x5DC0: /* 24000 KHz */
 495                return 0x00000141;
 496        case 0x6590: /* 26000 KHz */
 497                return 0x0EC4F121;
 498        case 0x8340: /* 33600 KHz */
 499                return 0x092490E1;
 500        case 0x9600: /* 38400 KHz */
 501                return 0x100010C1;
 502        case 0x9C40: /* 40000 KHz */
 503                return 0x000000C1;
 504        case 0xBB80: /* 48000 KHz */
 505                return 0x000000A1;
 506        case 0xCB20: /* 52000 KHz */
 507                return 0x07627091;
 508        default:
 509                pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
 510                       clk_khz);
 511                return 0x0EC4F121;
 512        }
 513}
 514
 515int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
 516                      struct hwbus_priv *hwbus,
 517                      struct device *pdev,
 518                      struct cw1200_common **core,
 519                      int ref_clk, const u8 *macaddr,
 520                      const char *sdd_path, bool have_5ghz)
 521{
 522        int err = -EINVAL;
 523        struct ieee80211_hw *dev;
 524        struct cw1200_common *priv;
 525        struct wsm_operational_mode mode = {
 526                .power_mode = cw1200_power_mode,
 527                .disable_more_flag_usage = true,
 528        };
 529
 530        dev = cw1200_init_common(macaddr, have_5ghz);
 531        if (!dev)
 532                goto err;
 533
 534        priv = dev->priv;
 535        priv->hw_refclk = ref_clk;
 536        if (cw1200_refclk)
 537                priv->hw_refclk = cw1200_refclk;
 538
 539        priv->sdd_path = (char *)sdd_path;
 540        if (cw1200_sdd_path)
 541                priv->sdd_path = cw1200_sdd_path;
 542
 543        priv->hwbus_ops = hwbus_ops;
 544        priv->hwbus_priv = hwbus;
 545        priv->pdev = pdev;
 546        SET_IEEE80211_DEV(priv->hw, pdev);
 547
 548        /* Pass struct cw1200_common back up */
 549        *core = priv;
 550
 551        err = cw1200_register_bh(priv);
 552        if (err)
 553                goto err1;
 554
 555        err = cw1200_load_firmware(priv);
 556        if (err)
 557                goto err2;
 558
 559        if (wait_event_interruptible_timeout(priv->wsm_startup_done,
 560                                             priv->firmware_ready,
 561                                             3*HZ) <= 0) {
 562                /* TODO: Need to find how to reset device
 563                   in QUEUE mode properly.
 564                */
 565                pr_err("Timeout waiting on device startup\n");
 566                err = -ETIMEDOUT;
 567                goto err2;
 568        }
 569
 570        /* Set low-power mode. */
 571        wsm_set_operational_mode(priv, &mode);
 572
 573        /* Enable multi-TX confirmation */
 574        wsm_use_multi_tx_conf(priv, true);
 575
 576        err = cw1200_register_common(dev);
 577        if (err)
 578                goto err2;
 579
 580        return err;
 581
 582err2:
 583        cw1200_unregister_bh(priv);
 584err1:
 585        cw1200_free_common(dev);
 586err:
 587        *core = NULL;
 588        return err;
 589}
 590EXPORT_SYMBOL_GPL(cw1200_core_probe);
 591
 592void cw1200_core_release(struct cw1200_common *self)
 593{
 594        /* Disable device interrupts */
 595        self->hwbus_ops->lock(self->hwbus_priv);
 596        __cw1200_irq_enable(self, 0);
 597        self->hwbus_ops->unlock(self->hwbus_priv);
 598
 599        /* And then clean up */
 600        cw1200_unregister_common(self->hw);
 601        cw1200_free_common(self->hw);
 602        return;
 603}
 604EXPORT_SYMBOL_GPL(cw1200_core_release);
 605