Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers
0004  *
0005  * Copyright (c) 2010, ST-Ericsson
0006  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
0007  *
0008  * Based on:
0009  * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
0010  * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
0011  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
0012  *
0013  * Based on:
0014  * - the islsm (softmac prism54) driver, which is:
0015  *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
0016  * - stlc45xx driver
0017  *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
0018  */
0019 
0020 #include <linux/module.h>
0021 #include <linux/firmware.h>
0022 #include <linux/etherdevice.h>
0023 #include <linux/vmalloc.h>
0024 #include <linux/random.h>
0025 #include <linux/sched.h>
0026 #include <net/mac80211.h>
0027 
0028 #include "cw1200.h"
0029 #include "txrx.h"
0030 #include "hwbus.h"
0031 #include "fwio.h"
0032 #include "hwio.h"
0033 #include "bh.h"
0034 #include "sta.h"
0035 #include "scan.h"
0036 #include "debug.h"
0037 #include "pm.h"
0038 
0039 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
0040 MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code");
0041 MODULE_LICENSE("GPL");
0042 MODULE_ALIAS("cw1200_core");
0043 
0044 /* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */
0045 static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00};
0046 module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, 0444);
0047 MODULE_PARM_DESC(macaddr, "Override platform_data MAC address");
0048 
0049 static char *cw1200_sdd_path;
0050 module_param(cw1200_sdd_path, charp, 0644);
0051 MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file");
0052 static int cw1200_refclk;
0053 module_param(cw1200_refclk, int, 0644);
0054 MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock");
0055 
0056 int cw1200_power_mode = wsm_power_mode_quiescent;
0057 module_param(cw1200_power_mode, int, 0644);
0058 MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode.  0 == active, 1 == doze, 2 == quiescent (default)");
0059 
0060 #define RATETAB_ENT(_rate, _rateid, _flags)     \
0061     {                       \
0062         .bitrate    = (_rate),      \
0063         .hw_value   = (_rateid),        \
0064         .flags      = (_flags),     \
0065     }
0066 
0067 static struct ieee80211_rate cw1200_rates[] = {
0068     RATETAB_ENT(10,  0,   0),
0069     RATETAB_ENT(20,  1,   0),
0070     RATETAB_ENT(55,  2,   0),
0071     RATETAB_ENT(110, 3,   0),
0072     RATETAB_ENT(60,  6,  0),
0073     RATETAB_ENT(90,  7,  0),
0074     RATETAB_ENT(120, 8,  0),
0075     RATETAB_ENT(180, 9,  0),
0076     RATETAB_ENT(240, 10, 0),
0077     RATETAB_ENT(360, 11, 0),
0078     RATETAB_ENT(480, 12, 0),
0079     RATETAB_ENT(540, 13, 0),
0080 };
0081 
0082 static struct ieee80211_rate cw1200_mcs_rates[] = {
0083     RATETAB_ENT(65,  14, IEEE80211_TX_RC_MCS),
0084     RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS),
0085     RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS),
0086     RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS),
0087     RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS),
0088     RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS),
0089     RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS),
0090     RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS),
0091 };
0092 
0093 #define cw1200_a_rates      (cw1200_rates + 4)
0094 #define cw1200_a_rates_size (ARRAY_SIZE(cw1200_rates) - 4)
0095 #define cw1200_g_rates      (cw1200_rates + 0)
0096 #define cw1200_g_rates_size (ARRAY_SIZE(cw1200_rates))
0097 #define cw1200_n_rates      (cw1200_mcs_rates)
0098 #define cw1200_n_rates_size (ARRAY_SIZE(cw1200_mcs_rates))
0099 
0100 
0101 #define CHAN2G(_channel, _freq, _flags) {           \
0102     .band           = NL80211_BAND_2GHZ,        \
0103     .center_freq        = (_freq),          \
0104     .hw_value       = (_channel),           \
0105     .flags          = (_flags),         \
0106     .max_antenna_gain   = 0,                \
0107     .max_power      = 30,               \
0108 }
0109 
0110 #define CHAN5G(_channel, _flags) {              \
0111     .band           = NL80211_BAND_5GHZ,        \
0112     .center_freq    = 5000 + (5 * (_channel)),      \
0113     .hw_value       = (_channel),           \
0114     .flags          = (_flags),         \
0115     .max_antenna_gain   = 0,                \
0116     .max_power      = 30,               \
0117 }
0118 
0119 static struct ieee80211_channel cw1200_2ghz_chantable[] = {
0120     CHAN2G(1, 2412, 0),
0121     CHAN2G(2, 2417, 0),
0122     CHAN2G(3, 2422, 0),
0123     CHAN2G(4, 2427, 0),
0124     CHAN2G(5, 2432, 0),
0125     CHAN2G(6, 2437, 0),
0126     CHAN2G(7, 2442, 0),
0127     CHAN2G(8, 2447, 0),
0128     CHAN2G(9, 2452, 0),
0129     CHAN2G(10, 2457, 0),
0130     CHAN2G(11, 2462, 0),
0131     CHAN2G(12, 2467, 0),
0132     CHAN2G(13, 2472, 0),
0133     CHAN2G(14, 2484, 0),
0134 };
0135 
0136 static struct ieee80211_channel cw1200_5ghz_chantable[] = {
0137     CHAN5G(34, 0),      CHAN5G(36, 0),
0138     CHAN5G(38, 0),      CHAN5G(40, 0),
0139     CHAN5G(42, 0),      CHAN5G(44, 0),
0140     CHAN5G(46, 0),      CHAN5G(48, 0),
0141     CHAN5G(52, 0),      CHAN5G(56, 0),
0142     CHAN5G(60, 0),      CHAN5G(64, 0),
0143     CHAN5G(100, 0),     CHAN5G(104, 0),
0144     CHAN5G(108, 0),     CHAN5G(112, 0),
0145     CHAN5G(116, 0),     CHAN5G(120, 0),
0146     CHAN5G(124, 0),     CHAN5G(128, 0),
0147     CHAN5G(132, 0),     CHAN5G(136, 0),
0148     CHAN5G(140, 0),     CHAN5G(149, 0),
0149     CHAN5G(153, 0),     CHAN5G(157, 0),
0150     CHAN5G(161, 0),     CHAN5G(165, 0),
0151     CHAN5G(184, 0),     CHAN5G(188, 0),
0152     CHAN5G(192, 0),     CHAN5G(196, 0),
0153     CHAN5G(200, 0),     CHAN5G(204, 0),
0154     CHAN5G(208, 0),     CHAN5G(212, 0),
0155     CHAN5G(216, 0),
0156 };
0157 
0158 static struct ieee80211_supported_band cw1200_band_2ghz = {
0159     .channels = cw1200_2ghz_chantable,
0160     .n_channels = ARRAY_SIZE(cw1200_2ghz_chantable),
0161     .bitrates = cw1200_g_rates,
0162     .n_bitrates = cw1200_g_rates_size,
0163     .ht_cap = {
0164         .cap = IEEE80211_HT_CAP_GRN_FLD |
0165             (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
0166             IEEE80211_HT_CAP_MAX_AMSDU,
0167         .ht_supported = 1,
0168         .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
0169         .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
0170         .mcs = {
0171             .rx_mask[0] = 0xFF,
0172             .rx_highest = __cpu_to_le16(0x41),
0173             .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
0174         },
0175     },
0176 };
0177 
0178 static struct ieee80211_supported_band cw1200_band_5ghz = {
0179     .channels = cw1200_5ghz_chantable,
0180     .n_channels = ARRAY_SIZE(cw1200_5ghz_chantable),
0181     .bitrates = cw1200_a_rates,
0182     .n_bitrates = cw1200_a_rates_size,
0183     .ht_cap = {
0184         .cap = IEEE80211_HT_CAP_GRN_FLD |
0185             (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) |
0186             IEEE80211_HT_CAP_MAX_AMSDU,
0187         .ht_supported = 1,
0188         .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
0189         .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE,
0190         .mcs = {
0191             .rx_mask[0] = 0xFF,
0192             .rx_highest = __cpu_to_le16(0x41),
0193             .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
0194         },
0195     },
0196 };
0197 
0198 static const unsigned long cw1200_ttl[] = {
0199     1 * HZ, /* VO */
0200     2 * HZ, /* VI */
0201     5 * HZ, /* BE */
0202     10 * HZ /* BK */
0203 };
0204 
0205 static const struct ieee80211_ops cw1200_ops = {
0206     .start          = cw1200_start,
0207     .stop           = cw1200_stop,
0208     .add_interface      = cw1200_add_interface,
0209     .remove_interface   = cw1200_remove_interface,
0210     .change_interface   = cw1200_change_interface,
0211     .tx         = cw1200_tx,
0212     .hw_scan        = cw1200_hw_scan,
0213     .set_tim        = cw1200_set_tim,
0214     .sta_notify     = cw1200_sta_notify,
0215     .sta_add        = cw1200_sta_add,
0216     .sta_remove     = cw1200_sta_remove,
0217     .set_key        = cw1200_set_key,
0218     .set_rts_threshold  = cw1200_set_rts_threshold,
0219     .config         = cw1200_config,
0220     .bss_info_changed   = cw1200_bss_info_changed,
0221     .prepare_multicast  = cw1200_prepare_multicast,
0222     .configure_filter   = cw1200_configure_filter,
0223     .conf_tx        = cw1200_conf_tx,
0224     .get_stats      = cw1200_get_stats,
0225     .ampdu_action       = cw1200_ampdu_action,
0226     .flush          = cw1200_flush,
0227 #ifdef CONFIG_PM
0228     .suspend        = cw1200_wow_suspend,
0229     .resume         = cw1200_wow_resume,
0230 #endif
0231     /* Intentionally not offloaded:                 */
0232     /*.channel_switch   = cw1200_channel_switch,        */
0233     /*.remain_on_channel    = cw1200_remain_on_channel,     */
0234     /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel,  */
0235 };
0236 
0237 static int cw1200_ba_rx_tids = -1;
0238 static int cw1200_ba_tx_tids = -1;
0239 module_param(cw1200_ba_rx_tids, int, 0644);
0240 module_param(cw1200_ba_tx_tids, int, 0644);
0241 MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs");
0242 MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs");
0243 
0244 #ifdef CONFIG_PM
0245 static const struct wiphy_wowlan_support cw1200_wowlan_support = {
0246     /* Support only for limited wowlan functionalities */
0247     .flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT,
0248 };
0249 #endif
0250 
0251 
0252 static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
0253                         const bool have_5ghz)
0254 {
0255     int i, band;
0256     struct ieee80211_hw *hw;
0257     struct cw1200_common *priv;
0258 
0259     hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops);
0260     if (!hw)
0261         return NULL;
0262 
0263     priv = hw->priv;
0264     priv->hw = hw;
0265     priv->hw_type = -1;
0266     priv->mode = NL80211_IFTYPE_UNSPECIFIED;
0267     priv->rates = cw1200_rates; /* TODO: fetch from FW */
0268     priv->mcs_rates = cw1200_n_rates;
0269     if (cw1200_ba_rx_tids != -1)
0270         priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
0271     else
0272         priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */
0273     if (cw1200_ba_tx_tids != -1)
0274         priv->ba_tx_tid_mask = cw1200_ba_tx_tids;
0275     else
0276         priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */
0277 
0278     ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
0279     ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
0280     ieee80211_hw_set(hw, AMPDU_AGGREGATION);
0281     ieee80211_hw_set(hw, CONNECTION_MONITOR);
0282     ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
0283     ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
0284     ieee80211_hw_set(hw, SIGNAL_DBM);
0285     ieee80211_hw_set(hw, SUPPORTS_PS);
0286 
0287     hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
0288                       BIT(NL80211_IFTYPE_ADHOC) |
0289                       BIT(NL80211_IFTYPE_AP) |
0290                       BIT(NL80211_IFTYPE_MESH_POINT) |
0291                       BIT(NL80211_IFTYPE_P2P_CLIENT) |
0292                       BIT(NL80211_IFTYPE_P2P_GO);
0293 
0294 #ifdef CONFIG_PM
0295     hw->wiphy->wowlan = &cw1200_wowlan_support;
0296 #endif
0297 
0298     hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
0299 
0300     hw->queues = 4;
0301 
0302     priv->rts_threshold = -1;
0303 
0304     hw->max_rates = 8;
0305     hw->max_rate_tries = 15;
0306     hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM +
0307         8;  /* TKIP IV */
0308 
0309     hw->sta_data_size = sizeof(struct cw1200_sta_priv);
0310 
0311     hw->wiphy->bands[NL80211_BAND_2GHZ] = &cw1200_band_2ghz;
0312     if (have_5ghz)
0313         hw->wiphy->bands[NL80211_BAND_5GHZ] = &cw1200_band_5ghz;
0314 
0315     /* Channel params have to be cleared before registering wiphy again */
0316     for (band = 0; band < NUM_NL80211_BANDS; band++) {
0317         struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
0318         if (!sband)
0319             continue;
0320         for (i = 0; i < sband->n_channels; i++) {
0321             sband->channels[i].flags = 0;
0322             sband->channels[i].max_antenna_gain = 0;
0323             sband->channels[i].max_power = 30;
0324         }
0325     }
0326 
0327     hw->wiphy->max_scan_ssids = 2;
0328     hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
0329 
0330     if (macaddr)
0331         SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr);
0332     else
0333         SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template);
0334 
0335     /* Fix up mac address if necessary */
0336     if (hw->wiphy->perm_addr[3] == 0 &&
0337         hw->wiphy->perm_addr[4] == 0 &&
0338         hw->wiphy->perm_addr[5] == 0) {
0339         get_random_bytes(&hw->wiphy->perm_addr[3], 3);
0340     }
0341 
0342     mutex_init(&priv->wsm_cmd_mux);
0343     mutex_init(&priv->conf_mutex);
0344     priv->workqueue = create_singlethread_workqueue("cw1200_wq");
0345     if (!priv->workqueue) {
0346         ieee80211_free_hw(hw);
0347         return NULL;
0348     }
0349 
0350     sema_init(&priv->scan.lock, 1);
0351     INIT_WORK(&priv->scan.work, cw1200_scan_work);
0352     INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work);
0353     INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout);
0354     INIT_DELAYED_WORK(&priv->clear_recent_scan_work,
0355               cw1200_clear_recent_scan_work);
0356     INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout);
0357     INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work);
0358     INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work);
0359     INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work);
0360     INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work);
0361     spin_lock_init(&priv->event_queue_lock);
0362     INIT_LIST_HEAD(&priv->event_queue);
0363     INIT_WORK(&priv->event_handler, cw1200_event_handler);
0364     INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work);
0365     INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work);
0366     spin_lock_init(&priv->bss_loss_lock);
0367     spin_lock_init(&priv->ps_state_lock);
0368     INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work);
0369     INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work);
0370     INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work);
0371     INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work);
0372     INIT_WORK(&priv->link_id_work, cw1200_link_id_work);
0373     INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work);
0374     INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset);
0375     INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
0376     INIT_WORK(&priv->set_beacon_wakeup_period_work,
0377           cw1200_set_beacon_wakeup_period_work);
0378     timer_setup(&priv->mcast_timeout, cw1200_mcast_timeout, 0);
0379 
0380     if (cw1200_queue_stats_init(&priv->tx_queue_stats,
0381                     CW1200_LINK_ID_MAX,
0382                     cw1200_skb_dtor,
0383                     priv)) {
0384         destroy_workqueue(priv->workqueue);
0385         ieee80211_free_hw(hw);
0386         return NULL;
0387     }
0388 
0389     for (i = 0; i < 4; ++i) {
0390         if (cw1200_queue_init(&priv->tx_queue[i],
0391                       &priv->tx_queue_stats, i, 16,
0392                       cw1200_ttl[i])) {
0393             for (; i > 0; i--)
0394                 cw1200_queue_deinit(&priv->tx_queue[i - 1]);
0395             cw1200_queue_stats_deinit(&priv->tx_queue_stats);
0396             destroy_workqueue(priv->workqueue);
0397             ieee80211_free_hw(hw);
0398             return NULL;
0399         }
0400     }
0401 
0402     init_waitqueue_head(&priv->channel_switch_done);
0403     init_waitqueue_head(&priv->wsm_cmd_wq);
0404     init_waitqueue_head(&priv->wsm_startup_done);
0405     init_waitqueue_head(&priv->ps_mode_switch_done);
0406     wsm_buf_init(&priv->wsm_cmd_buf);
0407     spin_lock_init(&priv->wsm_cmd.lock);
0408     priv->wsm_cmd.done = 1;
0409     tx_policy_init(priv);
0410 
0411     return hw;
0412 }
0413 
0414 static int cw1200_register_common(struct ieee80211_hw *dev)
0415 {
0416     struct cw1200_common *priv = dev->priv;
0417     int err;
0418 
0419 #ifdef CONFIG_PM
0420     err = cw1200_pm_init(&priv->pm_state, priv);
0421     if (err) {
0422         pr_err("Cannot init PM. (%d).\n",
0423                err);
0424         return err;
0425     }
0426 #endif
0427 
0428     err = ieee80211_register_hw(dev);
0429     if (err) {
0430         pr_err("Cannot register device (%d).\n",
0431                err);
0432 #ifdef CONFIG_PM
0433         cw1200_pm_deinit(&priv->pm_state);
0434 #endif
0435         return err;
0436     }
0437 
0438     cw1200_debug_init(priv);
0439 
0440     pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy));
0441     return 0;
0442 }
0443 
0444 static void cw1200_free_common(struct ieee80211_hw *dev)
0445 {
0446     ieee80211_free_hw(dev);
0447 }
0448 
0449 static void cw1200_unregister_common(struct ieee80211_hw *dev)
0450 {
0451     struct cw1200_common *priv = dev->priv;
0452     int i;
0453 
0454     ieee80211_unregister_hw(dev);
0455 
0456     del_timer_sync(&priv->mcast_timeout);
0457     cw1200_unregister_bh(priv);
0458 
0459     cw1200_debug_release(priv);
0460 
0461     mutex_destroy(&priv->conf_mutex);
0462 
0463     wsm_buf_deinit(&priv->wsm_cmd_buf);
0464 
0465     destroy_workqueue(priv->workqueue);
0466     priv->workqueue = NULL;
0467 
0468     if (priv->sdd) {
0469         release_firmware(priv->sdd);
0470         priv->sdd = NULL;
0471     }
0472 
0473     for (i = 0; i < 4; ++i)
0474         cw1200_queue_deinit(&priv->tx_queue[i]);
0475 
0476     cw1200_queue_stats_deinit(&priv->tx_queue_stats);
0477 #ifdef CONFIG_PM
0478     cw1200_pm_deinit(&priv->pm_state);
0479 #endif
0480 }
0481 
0482 /* Clock is in KHz */
0483 u32 cw1200_dpll_from_clk(u16 clk_khz)
0484 {
0485     switch (clk_khz) {
0486     case 0x32C8: /* 13000 KHz */
0487         return 0x1D89D241;
0488     case 0x3E80: /* 16000 KHz */
0489         return 0x000001E1;
0490     case 0x41A0: /* 16800 KHz */
0491         return 0x124931C1;
0492     case 0x4B00: /* 19200 KHz */
0493         return 0x00000191;
0494     case 0x5DC0: /* 24000 KHz */
0495         return 0x00000141;
0496     case 0x6590: /* 26000 KHz */
0497         return 0x0EC4F121;
0498     case 0x8340: /* 33600 KHz */
0499         return 0x092490E1;
0500     case 0x9600: /* 38400 KHz */
0501         return 0x100010C1;
0502     case 0x9C40: /* 40000 KHz */
0503         return 0x000000C1;
0504     case 0xBB80: /* 48000 KHz */
0505         return 0x000000A1;
0506     case 0xCB20: /* 52000 KHz */
0507         return 0x07627091;
0508     default:
0509         pr_err("Unknown Refclk freq (0x%04x), using 26000KHz\n",
0510                clk_khz);
0511         return 0x0EC4F121;
0512     }
0513 }
0514 
0515 int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
0516               struct hwbus_priv *hwbus,
0517               struct device *pdev,
0518               struct cw1200_common **core,
0519               int ref_clk, const u8 *macaddr,
0520               const char *sdd_path, bool have_5ghz)
0521 {
0522     int err = -EINVAL;
0523     struct ieee80211_hw *dev;
0524     struct cw1200_common *priv;
0525     struct wsm_operational_mode mode = {
0526         .power_mode = cw1200_power_mode,
0527         .disable_more_flag_usage = true,
0528     };
0529 
0530     dev = cw1200_init_common(macaddr, have_5ghz);
0531     if (!dev)
0532         goto err;
0533 
0534     priv = dev->priv;
0535     priv->hw_refclk = ref_clk;
0536     if (cw1200_refclk)
0537         priv->hw_refclk = cw1200_refclk;
0538 
0539     priv->sdd_path = (char *)sdd_path;
0540     if (cw1200_sdd_path)
0541         priv->sdd_path = cw1200_sdd_path;
0542 
0543     priv->hwbus_ops = hwbus_ops;
0544     priv->hwbus_priv = hwbus;
0545     priv->pdev = pdev;
0546     SET_IEEE80211_DEV(priv->hw, pdev);
0547 
0548     /* Pass struct cw1200_common back up */
0549     *core = priv;
0550 
0551     err = cw1200_register_bh(priv);
0552     if (err)
0553         goto err1;
0554 
0555     err = cw1200_load_firmware(priv);
0556     if (err)
0557         goto err2;
0558 
0559     if (wait_event_interruptible_timeout(priv->wsm_startup_done,
0560                          priv->firmware_ready,
0561                          3*HZ) <= 0) {
0562         /* TODO: Need to find how to reset device
0563            in QUEUE mode properly.
0564         */
0565         pr_err("Timeout waiting on device startup\n");
0566         err = -ETIMEDOUT;
0567         goto err2;
0568     }
0569 
0570     /* Set low-power mode. */
0571     wsm_set_operational_mode(priv, &mode);
0572 
0573     /* Enable multi-TX confirmation */
0574     wsm_use_multi_tx_conf(priv, true);
0575 
0576     err = cw1200_register_common(dev);
0577     if (err)
0578         goto err2;
0579 
0580     return err;
0581 
0582 err2:
0583     cw1200_unregister_bh(priv);
0584 err1:
0585     cw1200_free_common(dev);
0586 err:
0587     *core = NULL;
0588     return err;
0589 }
0590 EXPORT_SYMBOL_GPL(cw1200_core_probe);
0591 
0592 void cw1200_core_release(struct cw1200_common *self)
0593 {
0594     /* Disable device interrupts */
0595     self->hwbus_ops->lock(self->hwbus_priv);
0596     __cw1200_irq_enable(self, 0);
0597     self->hwbus_ops->unlock(self->hwbus_priv);
0598 
0599     /* And then clean up */
0600     cw1200_unregister_common(self->hw);
0601     cw1200_free_common(self->hw);
0602     return;
0603 }
0604 EXPORT_SYMBOL_GPL(cw1200_core_release);