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