linux/drivers/net/wireless/st/cw1200/main.c
<<
>>
Prefs
   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
  42MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
  43MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
  44MODULE_LICENSE("GPL");
  45MODULE_ALIAS("cw1200_core");
  46
  47/* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
  48static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
  49module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, S_IRUGO);
  50MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
  51
  52static char *cw1200_sdd_path;
  53module_param(cw1200_sdd_path, charp, 0644);
  54MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
  55static int cw1200_refclk;
  56module_param(cw1200_refclk, int, 0644);
  57MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
  58
  59int cw1200_power_mode = wsm_power_mode_quiescent;
  60module_param(cw1200_power_mode, int, 0644);
  61MODULE_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
  70static 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
  85static 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                   = IEEE80211_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                   = IEEE80211_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
 122static 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
 139static 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
 161static 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
 181static 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
 201static const unsigned long cw1200_ttl[] = {
 202        1 * HZ, /* VO */
 203        2 * HZ, /* VI */
 204        5 * HZ, /* BE */
 205        10 * HZ /* BK */
 206};
 207
 208static 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
 240static int cw1200_ba_rx_tids = -1;
 241static int cw1200_ba_tx_tids = -1;
 242module_param(cw1200_ba_rx_tids, int, 0644);
 243module_param(cw1200_ba_tx_tids, int, 0644);
 244MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
 245MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
 246
 247#ifdef CONFIG_PM
 248static 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
 255static 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[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz;
 315        if (have_5ghz)
 316                hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz;
 317
 318        /* Channel params have to be cleared before registering wiphy again */
 319        for (band = 0; band < IEEE80211_NUM_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        sema_init(&priv->scan.lock, 1);
 349        INIT_WORK(&priv->scan.work, cw1200_scan_work);
 350        INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
 351        INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
 352        INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
 353                          cw1200_clear_recent_scan_work);
 354        INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
 355        INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
 356        INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
 357        INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
 358        INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
 359        spin_lock_init(&priv->event_queue_lock);
 360        INIT_LIST_HEAD(&priv->event_queue);
 361        INIT_WORK(&priv->event_handler, cw1200_event_handler);
 362        INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
 363        INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
 364        spin_lock_init(&priv->bss_loss_lock);
 365        spin_lock_init(&priv->ps_state_lock);
 366        INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
 367        INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
 368        INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
 369        INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
 370        INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
 371        INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
 372        INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
 373        INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
 374        INIT_WORK(&priv->set_beacon_wakeup_period_work,
 375                  cw1200_set_beacon_wakeup_period_work);
 376        setup_timer(&priv->mcast_timeout, cw1200_mcast_timeout,
 377                    (unsigned long)priv);
 378
 379        if (cw1200_queue_stats_init(&priv->tx_queue_stats,
 380                                    CW1200_LINK_ID_MAX,
 381                                    cw1200_skb_dtor,
 382                                    priv)) {
 383                ieee80211_free_hw(hw);
 384                return NULL;
 385        }
 386
 387        for (i = 0; i < 4; ++i) {
 388                if (cw1200_queue_init(&priv->tx_queue[i],
 389                                      &priv->tx_queue_stats, i, 16,
 390                                      cw1200_ttl[i])) {
 391                        for (; i > 0; i--)
 392                                cw1200_queue_deinit(&priv->tx_queue[i - 1]);
 393                        cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 394                        ieee80211_free_hw(hw);
 395                        return NULL;
 396                }
 397        }
 398
 399        init_waitqueue_head(&priv->channel_switch_done);
 400        init_waitqueue_head(&priv->wsm_cmd_wq);
 401        init_waitqueue_head(&priv->wsm_startup_done);
 402        init_waitqueue_head(&priv->ps_mode_switch_done);
 403        wsm_buf_init(&priv->wsm_cmd_buf);
 404        spin_lock_init(&priv->wsm_cmd.lock);
 405        priv->wsm_cmd.done = 1;
 406        tx_policy_init(priv);
 407
 408        return hw;
 409}
 410
 411static int cw1200_register_common(struct ieee80211_hw *dev)
 412{
 413        struct cw1200_common *priv = dev->priv;
 414        int err;
 415
 416#ifdef CONFIG_PM
 417        err = cw1200_pm_init(&priv->pm_state, priv);
 418        if (err) {
 419                pr_err("Cannot init PM. (%d).\n",
 420                       err);
 421                return err;
 422        }
 423#endif
 424
 425        err = ieee80211_register_hw(dev);
 426        if (err) {
 427                pr_err("Cannot register device (%d).\n",
 428                       err);
 429#ifdef CONFIG_PM
 430                cw1200_pm_deinit(&priv->pm_state);
 431#endif
 432                return err;
 433        }
 434
 435        cw1200_debug_init(priv);
 436
 437        pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
 438        return 0;
 439}
 440
 441static void cw1200_free_common(struct ieee80211_hw *dev)
 442{
 443        ieee80211_free_hw(dev);
 444}
 445
 446static void cw1200_unregister_common(struct ieee80211_hw *dev)
 447{
 448        struct cw1200_common *priv = dev->priv;
 449        int i;
 450
 451        ieee80211_unregister_hw(dev);
 452
 453        del_timer_sync(&priv->mcast_timeout);
 454        cw1200_unregister_bh(priv);
 455
 456        cw1200_debug_release(priv);
 457
 458        mutex_destroy(&priv->conf_mutex);
 459
 460        wsm_buf_deinit(&priv->wsm_cmd_buf);
 461
 462        destroy_workqueue(priv->workqueue);
 463        priv->workqueue = NULL;
 464
 465        if (priv->sdd) {
 466                release_firmware(priv->sdd);
 467                priv->sdd = NULL;
 468        }
 469
 470        for (i = 0; i < 4; ++i)
 471                cw1200_queue_deinit(&priv->tx_queue[i]);
 472
 473        cw1200_queue_stats_deinit(&priv->tx_queue_stats);
 474#ifdef CONFIG_PM
 475        cw1200_pm_deinit(&priv->pm_state);
 476#endif
 477}
 478
 479/* Clock is in KHz */
 480u32 cw1200_dpll_from_clk(u16 clk_khz)
 481{
 482        switch (clk_khz) {
 483        case 0x32C8: /* 13000 KHz */
 484                return 0x1D89D241;
 485        case 0x3E80: /* 16000 KHz */
 486                return 0x000001E1;
 487        case 0x41A0: /* 16800 KHz */
 488                return 0x124931C1;
 489        case 0x4B00: /* 19200 KHz */
 490                return 0x00000191;
 491        case 0x5DC0: /* 24000 KHz */
 492                return 0x00000141;
 493        case 0x6590: /* 26000 KHz */
 494                return 0x0EC4F121;
 495        case 0x8340: /* 33600 KHz */
 496                return 0x092490E1;
 497        case 0x9600: /* 38400 KHz */
 498                return 0x100010C1;
 499        case 0x9C40: /* 40000 KHz */
 500                return 0x000000C1;
 501        case 0xBB80: /* 48000 KHz */
 502                return 0x000000A1;
 503        case 0xCB20: /* 52000 KHz */
 504                return 0x07627091;
 505        default:
 506                pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
 507                       clk_khz);
 508                return 0x0EC4F121;
 509        }
 510}
 511
 512int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
 513                      struct hwbus_priv *hwbus,
 514                      struct device *pdev,
 515                      struct cw1200_common **core,
 516                      int ref_clk, const u8 *macaddr,
 517                      const char *sdd_path, bool have_5ghz)
 518{
 519        int err = -EINVAL;
 520        struct ieee80211_hw *dev;
 521        struct cw1200_common *priv;
 522        struct wsm_operational_mode mode = {
 523                .power_mode = cw1200_power_mode,
 524                .disable_more_flag_usage = true,
 525        };
 526
 527        dev = cw1200_init_common(macaddr, have_5ghz);
 528        if (!dev)
 529                goto err;
 530
 531        priv = dev->priv;
 532        priv->hw_refclk = ref_clk;
 533        if (cw1200_refclk)
 534                priv->hw_refclk = cw1200_refclk;
 535
 536        priv->sdd_path = (char *)sdd_path;
 537        if (cw1200_sdd_path)
 538                priv->sdd_path = cw1200_sdd_path;
 539
 540        priv->hwbus_ops = hwbus_ops;
 541        priv->hwbus_priv = hwbus;
 542        priv->pdev = pdev;
 543        SET_IEEE80211_DEV(priv->hw, pdev);
 544
 545        /* Pass struct cw1200_common back up */
 546        *core = priv;
 547
 548        err = cw1200_register_bh(priv);
 549        if (err)
 550                goto err1;
 551
 552        err = cw1200_load_firmware(priv);
 553        if (err)
 554                goto err2;
 555
 556        if (wait_event_interruptible_timeout(priv->wsm_startup_done,
 557                                             priv->firmware_ready,
 558                                             3*HZ) <= 0) {
 559                /* TODO: Need to find how to reset device
 560                   in QUEUE mode properly.
 561                */
 562                pr_err("Timeout waiting on device startup\n");
 563                err = -ETIMEDOUT;
 564                goto err2;
 565        }
 566
 567        /* Set low-power mode. */
 568        wsm_set_operational_mode(priv, &mode);
 569
 570        /* Enable multi-TX confirmation */
 571        wsm_use_multi_tx_conf(priv, true);
 572
 573        err = cw1200_register_common(dev);
 574        if (err)
 575                goto err2;
 576
 577        return err;
 578
 579err2:
 580        cw1200_unregister_bh(priv);
 581err1:
 582        cw1200_free_common(dev);
 583err:
 584        *core = NULL;
 585        return err;
 586}
 587EXPORT_SYMBOL_GPL(cw1200_core_probe);
 588
 589void cw1200_core_release(struct cw1200_common *self)
 590{
 591        /* Disable device interrupts */
 592        self->hwbus_ops->lock(self->hwbus_priv);
 593        __cw1200_irq_enable(self, 0);
 594        self->hwbus_ops->unlock(self->hwbus_priv);
 595
 596        /* And then clean up */
 597        cw1200_unregister_common(self->hw);
 598        cw1200_free_common(self->hw);
 599        return;
 600}
 601EXPORT_SYMBOL_GPL(cw1200_core_release);
 602