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