1fb9987d0SSujith /* 2fb9987d0SSujith * Copyright (c) 2010 Atheros Communications Inc. 3fb9987d0SSujith * 4fb9987d0SSujith * Permission to use, copy, modify, and/or distribute this software for any 5fb9987d0SSujith * purpose with or without fee is hereby granted, provided that the above 6fb9987d0SSujith * copyright notice and this permission notice appear in all copies. 7fb9987d0SSujith * 8fb9987d0SSujith * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9fb9987d0SSujith * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10fb9987d0SSujith * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11fb9987d0SSujith * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12fb9987d0SSujith * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13fb9987d0SSujith * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14fb9987d0SSujith * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15fb9987d0SSujith */ 16fb9987d0SSujith 17fb9987d0SSujith #include "htc.h" 18fb9987d0SSujith 19fb9987d0SSujith MODULE_AUTHOR("Atheros Communications"); 20fb9987d0SSujith MODULE_LICENSE("Dual BSD/GPL"); 21fb9987d0SSujith MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices"); 22fb9987d0SSujith 23fb9987d0SSujith static unsigned int ath9k_debug = ATH_DBG_DEFAULT; 24fb9987d0SSujith module_param_named(debug, ath9k_debug, uint, 0); 25fb9987d0SSujith MODULE_PARM_DESC(debug, "Debugging mask"); 26fb9987d0SSujith 27e1572c5eSSujith int htc_modparam_nohwcrypt; 28e1572c5eSSujith module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444); 29fb9987d0SSujith MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); 30fb9987d0SSujith 31fb9987d0SSujith #define CHAN2G(_freq, _idx) { \ 32fb9987d0SSujith .center_freq = (_freq), \ 33fb9987d0SSujith .hw_value = (_idx), \ 34fb9987d0SSujith .max_power = 20, \ 35fb9987d0SSujith } 36fb9987d0SSujith 37ea46e644SSujith #define CHAN5G(_freq, _idx) { \ 38ea46e644SSujith .band = IEEE80211_BAND_5GHZ, \ 39ea46e644SSujith .center_freq = (_freq), \ 40ea46e644SSujith .hw_value = (_idx), \ 41ea46e644SSujith .max_power = 20, \ 42ea46e644SSujith } 43ea46e644SSujith 4421cb9879SVivek Natarajan #define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" 4521cb9879SVivek Natarajan 46fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = { 47fb9987d0SSujith CHAN2G(2412, 0), /* Channel 1 */ 48fb9987d0SSujith CHAN2G(2417, 1), /* Channel 2 */ 49fb9987d0SSujith CHAN2G(2422, 2), /* Channel 3 */ 50fb9987d0SSujith CHAN2G(2427, 3), /* Channel 4 */ 51fb9987d0SSujith CHAN2G(2432, 4), /* Channel 5 */ 52fb9987d0SSujith CHAN2G(2437, 5), /* Channel 6 */ 53fb9987d0SSujith CHAN2G(2442, 6), /* Channel 7 */ 54fb9987d0SSujith CHAN2G(2447, 7), /* Channel 8 */ 55fb9987d0SSujith CHAN2G(2452, 8), /* Channel 9 */ 56fb9987d0SSujith CHAN2G(2457, 9), /* Channel 10 */ 57fb9987d0SSujith CHAN2G(2462, 10), /* Channel 11 */ 58fb9987d0SSujith CHAN2G(2467, 11), /* Channel 12 */ 59fb9987d0SSujith CHAN2G(2472, 12), /* Channel 13 */ 60fb9987d0SSujith CHAN2G(2484, 13), /* Channel 14 */ 61fb9987d0SSujith }; 62fb9987d0SSujith 63ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = { 64ea46e644SSujith /* _We_ call this UNII 1 */ 65ea46e644SSujith CHAN5G(5180, 14), /* Channel 36 */ 66ea46e644SSujith CHAN5G(5200, 15), /* Channel 40 */ 67ea46e644SSujith CHAN5G(5220, 16), /* Channel 44 */ 68ea46e644SSujith CHAN5G(5240, 17), /* Channel 48 */ 69ea46e644SSujith /* _We_ call this UNII 2 */ 70ea46e644SSujith CHAN5G(5260, 18), /* Channel 52 */ 71ea46e644SSujith CHAN5G(5280, 19), /* Channel 56 */ 72ea46e644SSujith CHAN5G(5300, 20), /* Channel 60 */ 73ea46e644SSujith CHAN5G(5320, 21), /* Channel 64 */ 74ea46e644SSujith /* _We_ call this "Middle band" */ 75ea46e644SSujith CHAN5G(5500, 22), /* Channel 100 */ 76ea46e644SSujith CHAN5G(5520, 23), /* Channel 104 */ 77ea46e644SSujith CHAN5G(5540, 24), /* Channel 108 */ 78ea46e644SSujith CHAN5G(5560, 25), /* Channel 112 */ 79ea46e644SSujith CHAN5G(5580, 26), /* Channel 116 */ 80ea46e644SSujith CHAN5G(5600, 27), /* Channel 120 */ 81ea46e644SSujith CHAN5G(5620, 28), /* Channel 124 */ 82ea46e644SSujith CHAN5G(5640, 29), /* Channel 128 */ 83ea46e644SSujith CHAN5G(5660, 30), /* Channel 132 */ 84ea46e644SSujith CHAN5G(5680, 31), /* Channel 136 */ 85ea46e644SSujith CHAN5G(5700, 32), /* Channel 140 */ 86ea46e644SSujith /* _We_ call this UNII 3 */ 87ea46e644SSujith CHAN5G(5745, 33), /* Channel 149 */ 88ea46e644SSujith CHAN5G(5765, 34), /* Channel 153 */ 89ea46e644SSujith CHAN5G(5785, 35), /* Channel 157 */ 90ea46e644SSujith CHAN5G(5805, 36), /* Channel 161 */ 91ea46e644SSujith CHAN5G(5825, 37), /* Channel 165 */ 92ea46e644SSujith }; 93ea46e644SSujith 94fb9987d0SSujith /* Atheros hardware rate code addition for short premble */ 95fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \ 96fb9987d0SSujith ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) 97fb9987d0SSujith 98fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) { \ 99fb9987d0SSujith .bitrate = (_bitrate), \ 100fb9987d0SSujith .flags = (_flags), \ 101fb9987d0SSujith .hw_value = (_hw_rate), \ 102fb9987d0SSujith .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ 103fb9987d0SSujith } 104fb9987d0SSujith 105fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = { 106fb9987d0SSujith RATE(10, 0x1b, 0), 107fb9987d0SSujith RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ 108fb9987d0SSujith RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ 109fb9987d0SSujith RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ 110fb9987d0SSujith RATE(60, 0x0b, 0), 111fb9987d0SSujith RATE(90, 0x0f, 0), 112fb9987d0SSujith RATE(120, 0x0a, 0), 113fb9987d0SSujith RATE(180, 0x0e, 0), 114fb9987d0SSujith RATE(240, 0x09, 0), 115fb9987d0SSujith RATE(360, 0x0d, 0), 116fb9987d0SSujith RATE(480, 0x08, 0), 117fb9987d0SSujith RATE(540, 0x0c, 0), 118fb9987d0SSujith }; 119fb9987d0SSujith 120fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) 121fb9987d0SSujith { 122fb9987d0SSujith int time_left; 123fb9987d0SSujith 124d8c49ffbSSujith.Manoharan@atheros.com if (atomic_read(&priv->htc->tgt_ready) > 0) { 125d8c49ffbSSujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 126d8c49ffbSSujith.Manoharan@atheros.com return 0; 127d8c49ffbSSujith.Manoharan@atheros.com } 128d8c49ffbSSujith.Manoharan@atheros.com 129fb9987d0SSujith /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ 130fb9987d0SSujith time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); 131fb9987d0SSujith if (!time_left) { 132fb9987d0SSujith dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); 133fb9987d0SSujith return -ETIMEDOUT; 134fb9987d0SSujith } 135fb9987d0SSujith 136d8c49ffbSSujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 137d8c49ffbSSujith.Manoharan@atheros.com 138fb9987d0SSujith return 0; 139fb9987d0SSujith } 140fb9987d0SSujith 141fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) 142fb9987d0SSujith { 143e1572c5eSSujith ath9k_htc_exit_debug(priv->ah); 144fb9987d0SSujith ath9k_hw_deinit(priv->ah); 145fb9987d0SSujith tasklet_kill(&priv->wmi_tasklet); 146fb9987d0SSujith tasklet_kill(&priv->rx_tasklet); 147fb9987d0SSujith tasklet_kill(&priv->tx_tasklet); 148fb9987d0SSujith kfree(priv->ah); 149fb9987d0SSujith priv->ah = NULL; 150fb9987d0SSujith } 151fb9987d0SSujith 152fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv) 153fb9987d0SSujith { 154fb9987d0SSujith struct ieee80211_hw *hw = priv->hw; 155fb9987d0SSujith 156fb9987d0SSujith wiphy_rfkill_stop_polling(hw->wiphy); 157fb9987d0SSujith ath9k_deinit_leds(priv); 158fb9987d0SSujith ieee80211_unregister_hw(hw); 159fb9987d0SSujith ath9k_rx_cleanup(priv); 160fb9987d0SSujith ath9k_tx_cleanup(priv); 161fb9987d0SSujith ath9k_deinit_priv(priv); 162fb9987d0SSujith } 163fb9987d0SSujith 164fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, 165fb9987d0SSujith u16 service_id, 166fb9987d0SSujith void (*tx) (void *, 167fb9987d0SSujith struct sk_buff *, 168fb9987d0SSujith enum htc_endpoint_id, 169fb9987d0SSujith bool txok), 170fb9987d0SSujith enum htc_endpoint_id *ep_id) 171fb9987d0SSujith { 172fb9987d0SSujith struct htc_service_connreq req; 173fb9987d0SSujith 174fb9987d0SSujith memset(&req, 0, sizeof(struct htc_service_connreq)); 175fb9987d0SSujith 176fb9987d0SSujith req.service_id = service_id; 177fb9987d0SSujith req.ep_callbacks.priv = priv; 178fb9987d0SSujith req.ep_callbacks.rx = ath9k_htc_rxep; 179fb9987d0SSujith req.ep_callbacks.tx = tx; 180fb9987d0SSujith 181fb9987d0SSujith return htc_connect_service(priv->htc, &req, ep_id); 182fb9987d0SSujith } 183fb9987d0SSujith 1846267dc70SSujith static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) 185fb9987d0SSujith { 186fb9987d0SSujith int ret; 187fb9987d0SSujith 188fb9987d0SSujith /* WMI CMD*/ 189fb9987d0SSujith ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); 190fb9987d0SSujith if (ret) 191fb9987d0SSujith goto err; 192fb9987d0SSujith 193fb9987d0SSujith /* Beacon */ 1949c6dda4eSSujith ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep, 195fb9987d0SSujith &priv->beacon_ep); 196fb9987d0SSujith if (ret) 197fb9987d0SSujith goto err; 198fb9987d0SSujith 199fb9987d0SSujith /* CAB */ 200fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, 201fb9987d0SSujith &priv->cab_ep); 202fb9987d0SSujith if (ret) 203fb9987d0SSujith goto err; 204fb9987d0SSujith 205fb9987d0SSujith 206fb9987d0SSujith /* UAPSD */ 207fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, 208fb9987d0SSujith &priv->uapsd_ep); 209fb9987d0SSujith if (ret) 210fb9987d0SSujith goto err; 211fb9987d0SSujith 212fb9987d0SSujith /* MGMT */ 213fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, 214fb9987d0SSujith &priv->mgmt_ep); 215fb9987d0SSujith if (ret) 216fb9987d0SSujith goto err; 217fb9987d0SSujith 218fb9987d0SSujith /* DATA BE */ 219fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, 220fb9987d0SSujith &priv->data_be_ep); 221fb9987d0SSujith if (ret) 222fb9987d0SSujith goto err; 223fb9987d0SSujith 224fb9987d0SSujith /* DATA BK */ 225fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, 226fb9987d0SSujith &priv->data_bk_ep); 227fb9987d0SSujith if (ret) 228fb9987d0SSujith goto err; 229fb9987d0SSujith 230fb9987d0SSujith /* DATA VI */ 231fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, 232fb9987d0SSujith &priv->data_vi_ep); 233fb9987d0SSujith if (ret) 234fb9987d0SSujith goto err; 235fb9987d0SSujith 236fb9987d0SSujith /* DATA VO */ 237fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, 238fb9987d0SSujith &priv->data_vo_ep); 239fb9987d0SSujith if (ret) 240fb9987d0SSujith goto err; 241fb9987d0SSujith 2426267dc70SSujith /* 2436267dc70SSujith * Setup required credits before initializing HTC. 2446267dc70SSujith * This is a bit hacky, but, since queuing is done in 2456267dc70SSujith * the HIF layer, shouldn't matter much. 2466267dc70SSujith */ 2476267dc70SSujith 2486267dc70SSujith switch(devid) { 2496267dc70SSujith case 0x7010: 250ca6cff1fSRajkumar Manoharan case 0x7015: 2514e63f768SSujith case 0x9018: 2526267dc70SSujith priv->htc->credits = 45; 2536267dc70SSujith break; 2546267dc70SSujith default: 2554e63f768SSujith priv->htc->credits = 33; 2566267dc70SSujith } 2576267dc70SSujith 258fb9987d0SSujith ret = htc_init(priv->htc); 259fb9987d0SSujith if (ret) 260fb9987d0SSujith goto err; 261fb9987d0SSujith 2626267dc70SSujith dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n", 2636267dc70SSujith priv->htc->credits); 2646267dc70SSujith 265fb9987d0SSujith return 0; 266fb9987d0SSujith 267fb9987d0SSujith err: 268fb9987d0SSujith dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); 269fb9987d0SSujith return ret; 270fb9987d0SSujith } 271fb9987d0SSujith 272fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy, 273fb9987d0SSujith struct regulatory_request *request) 274fb9987d0SSujith { 275fb9987d0SSujith struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 276fb9987d0SSujith struct ath9k_htc_priv *priv = hw->priv; 277fb9987d0SSujith 278fb9987d0SSujith return ath_reg_notifier_apply(wiphy, request, 279fb9987d0SSujith ath9k_hw_regulatory(priv->ah)); 280fb9987d0SSujith } 281fb9987d0SSujith 2824a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) 283fb9987d0SSujith { 284fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 285fb9987d0SSujith struct ath_common *common = ath9k_hw_common(ah); 286fb9987d0SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 287fb9987d0SSujith __be32 val, reg = cpu_to_be32(reg_offset); 288fb9987d0SSujith int r; 289fb9987d0SSujith 290fb9987d0SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, 291fb9987d0SSujith (u8 *) ®, sizeof(reg), 292fb9987d0SSujith (u8 *) &val, sizeof(val), 293fb9987d0SSujith 100); 294fb9987d0SSujith if (unlikely(r)) { 295fb9987d0SSujith ath_print(common, ATH_DBG_WMI, 296fb9987d0SSujith "REGISTER READ FAILED: (0x%04x, %d)\n", 297fb9987d0SSujith reg_offset, r); 298fb9987d0SSujith return -EIO; 299fb9987d0SSujith } 300fb9987d0SSujith 301fb9987d0SSujith return be32_to_cpu(val); 302fb9987d0SSujith } 303fb9987d0SSujith 3044a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) 305fb9987d0SSujith { 306fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 307fb9987d0SSujith struct ath_common *common = ath9k_hw_common(ah); 308fb9987d0SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 309fb9987d0SSujith __be32 buf[2] = { 310fb9987d0SSujith cpu_to_be32(reg_offset), 311fb9987d0SSujith cpu_to_be32(val), 312fb9987d0SSujith }; 313fb9987d0SSujith int r; 314fb9987d0SSujith 315fb9987d0SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 316fb9987d0SSujith (u8 *) &buf, sizeof(buf), 317fb9987d0SSujith (u8 *) &val, sizeof(val), 318fb9987d0SSujith 100); 319fb9987d0SSujith if (unlikely(r)) { 320fb9987d0SSujith ath_print(common, ATH_DBG_WMI, 321fb9987d0SSujith "REGISTER WRITE FAILED:(0x%04x, %d)\n", 322fb9987d0SSujith reg_offset, r); 323fb9987d0SSujith } 324fb9987d0SSujith } 325fb9987d0SSujith 3264a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) 3274a22fe10SSujith { 3284a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3294a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3304a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3314a22fe10SSujith u32 rsp_status; 3324a22fe10SSujith int r; 3334a22fe10SSujith 3344a22fe10SSujith mutex_lock(&priv->wmi->multi_write_mutex); 3354a22fe10SSujith 3364a22fe10SSujith /* Store the register/value */ 3374a22fe10SSujith priv->wmi->multi_write[priv->wmi->multi_write_idx].reg = 3384a22fe10SSujith cpu_to_be32(reg_offset); 3394a22fe10SSujith priv->wmi->multi_write[priv->wmi->multi_write_idx].val = 3404a22fe10SSujith cpu_to_be32(val); 3414a22fe10SSujith 3424a22fe10SSujith priv->wmi->multi_write_idx++; 3434a22fe10SSujith 3444a22fe10SSujith /* If the buffer is full, send it out. */ 3454a22fe10SSujith if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) { 3464a22fe10SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 3474a22fe10SSujith (u8 *) &priv->wmi->multi_write, 3484a22fe10SSujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 3494a22fe10SSujith (u8 *) &rsp_status, sizeof(rsp_status), 3504a22fe10SSujith 100); 3514a22fe10SSujith if (unlikely(r)) { 3524a22fe10SSujith ath_print(common, ATH_DBG_WMI, 3534a22fe10SSujith "REGISTER WRITE FAILED, multi len: %d\n", 3544a22fe10SSujith priv->wmi->multi_write_idx); 3554a22fe10SSujith } 3564a22fe10SSujith priv->wmi->multi_write_idx = 0; 3574a22fe10SSujith } 3584a22fe10SSujith 3594a22fe10SSujith mutex_unlock(&priv->wmi->multi_write_mutex); 3604a22fe10SSujith } 3614a22fe10SSujith 3624a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset) 3634a22fe10SSujith { 3644a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3654a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3664a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3674a22fe10SSujith 3684a22fe10SSujith if (atomic_read(&priv->wmi->mwrite_cnt)) 3694a22fe10SSujith ath9k_regwrite_buffer(hw_priv, val, reg_offset); 3704a22fe10SSujith else 3714a22fe10SSujith ath9k_regwrite_single(hw_priv, val, reg_offset); 3724a22fe10SSujith } 3734a22fe10SSujith 3744a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv) 3754a22fe10SSujith { 3764a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3774a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3784a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3794a22fe10SSujith 3804a22fe10SSujith atomic_inc(&priv->wmi->mwrite_cnt); 3814a22fe10SSujith } 3824a22fe10SSujith 3834a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv) 3844a22fe10SSujith { 3854a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3864a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3874a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3884a22fe10SSujith u32 rsp_status; 3894a22fe10SSujith int r; 3904a22fe10SSujith 391435c1610SFelix Fietkau atomic_dec(&priv->wmi->mwrite_cnt); 392435c1610SFelix Fietkau 3934a22fe10SSujith mutex_lock(&priv->wmi->multi_write_mutex); 3944a22fe10SSujith 3954a22fe10SSujith if (priv->wmi->multi_write_idx) { 3964a22fe10SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 3974a22fe10SSujith (u8 *) &priv->wmi->multi_write, 3984a22fe10SSujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 3994a22fe10SSujith (u8 *) &rsp_status, sizeof(rsp_status), 4004a22fe10SSujith 100); 4014a22fe10SSujith if (unlikely(r)) { 4024a22fe10SSujith ath_print(common, ATH_DBG_WMI, 4034a22fe10SSujith "REGISTER WRITE FAILED, multi len: %d\n", 4044a22fe10SSujith priv->wmi->multi_write_idx); 4054a22fe10SSujith } 4064a22fe10SSujith priv->wmi->multi_write_idx = 0; 4074a22fe10SSujith } 4084a22fe10SSujith 4094a22fe10SSujith mutex_unlock(&priv->wmi->multi_write_mutex); 4104a22fe10SSujith } 4114a22fe10SSujith 412fb9987d0SSujith static const struct ath_ops ath9k_common_ops = { 4134a22fe10SSujith .read = ath9k_regread, 4144a22fe10SSujith .write = ath9k_regwrite, 4154a22fe10SSujith .enable_write_buffer = ath9k_enable_regwrite_buffer, 4164a22fe10SSujith .write_flush = ath9k_regwrite_flush, 417fb9987d0SSujith }; 418fb9987d0SSujith 419fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz) 420fb9987d0SSujith { 421fb9987d0SSujith *csz = L1_CACHE_BYTES >> 2; 422fb9987d0SSujith } 423fb9987d0SSujith 424fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) 425fb9987d0SSujith { 426fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) common->ah; 427fb9987d0SSujith 428fb9987d0SSujith (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); 429fb9987d0SSujith 430fb9987d0SSujith if (!ath9k_hw_wait(ah, 431fb9987d0SSujith AR_EEPROM_STATUS_DATA, 432fb9987d0SSujith AR_EEPROM_STATUS_DATA_BUSY | 433fb9987d0SSujith AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, 434fb9987d0SSujith AH_WAIT_TIMEOUT)) 435fb9987d0SSujith return false; 436fb9987d0SSujith 437fb9987d0SSujith *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), 438fb9987d0SSujith AR_EEPROM_STATUS_DATA_VAL); 439fb9987d0SSujith 440fb9987d0SSujith return true; 441fb9987d0SSujith } 442fb9987d0SSujith 443fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = { 444497ad9adSSujith .ath_bus_type = ATH_USB, 445fb9987d0SSujith .read_cachesize = ath_usb_read_cachesize, 446fb9987d0SSujith .eeprom_read = ath_usb_eeprom_read, 447fb9987d0SSujith }; 448fb9987d0SSujith 449fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv, 450fb9987d0SSujith struct ieee80211_sta_ht_cap *ht_info) 451fb9987d0SSujith { 4526debecadSSujith struct ath_common *common = ath9k_hw_common(priv->ah); 4536debecadSSujith u8 tx_streams, rx_streams; 4546debecadSSujith int i; 4556debecadSSujith 456fb9987d0SSujith ht_info->ht_supported = true; 457fb9987d0SSujith ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 458fb9987d0SSujith IEEE80211_HT_CAP_SM_PS | 459fb9987d0SSujith IEEE80211_HT_CAP_SGI_40 | 460fb9987d0SSujith IEEE80211_HT_CAP_DSSSCCK40; 461fb9987d0SSujith 462b4dec5e8SSujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) 463b4dec5e8SSujith ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 464b4dec5e8SSujith 46517525f96SSujith ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 46617525f96SSujith 467fb9987d0SSujith ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 468fb9987d0SSujith ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 469fb9987d0SSujith 470fb9987d0SSujith memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 4716debecadSSujith 4726debecadSSujith /* ath9k_htc supports only 1 or 2 stream devices */ 4736debecadSSujith tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); 4746debecadSSujith rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); 4756debecadSSujith 4766debecadSSujith ath_print(common, ATH_DBG_CONFIG, 4776debecadSSujith "TX streams %d, RX streams: %d\n", 4786debecadSSujith tx_streams, rx_streams); 4796debecadSSujith 4806debecadSSujith if (tx_streams != rx_streams) { 4816debecadSSujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 4826debecadSSujith ht_info->mcs.tx_params |= ((tx_streams - 1) << 4836debecadSSujith IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 4846debecadSSujith } 4856debecadSSujith 4866debecadSSujith for (i = 0; i < rx_streams; i++) 4876debecadSSujith ht_info->mcs.rx_mask[i] = 0xff; 4886debecadSSujith 489fb9987d0SSujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 490fb9987d0SSujith } 491fb9987d0SSujith 492fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv) 493fb9987d0SSujith { 494fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 495fb9987d0SSujith int i; 496fb9987d0SSujith 497fb9987d0SSujith for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) 498fb9987d0SSujith priv->hwq_map[i] = -1; 499fb9987d0SSujith 500ca74b83bSSujith priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); 501ca74b83bSSujith if (priv->beaconq == -1) { 502ca74b83bSSujith ath_print(common, ATH_DBG_FATAL, 503ca74b83bSSujith "Unable to setup BEACON xmit queue\n"); 504ca74b83bSSujith goto err; 505ca74b83bSSujith } 506ca74b83bSSujith 507ca74b83bSSujith priv->cabq = ath9k_htc_cabq_setup(priv); 508ca74b83bSSujith if (priv->cabq == -1) { 509ca74b83bSSujith ath_print(common, ATH_DBG_FATAL, 510ca74b83bSSujith "Unable to setup CAB xmit queue\n"); 511ca74b83bSSujith goto err; 512ca74b83bSSujith } 513ca74b83bSSujith 514e8c35a77SFelix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { 515fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 516fb9987d0SSujith "Unable to setup xmit queue for BE traffic\n"); 517fb9987d0SSujith goto err; 518fb9987d0SSujith } 519fb9987d0SSujith 520e8c35a77SFelix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { 521fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 522fb9987d0SSujith "Unable to setup xmit queue for BK traffic\n"); 523fb9987d0SSujith goto err; 524fb9987d0SSujith } 525e8c35a77SFelix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { 526fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 527fb9987d0SSujith "Unable to setup xmit queue for VI traffic\n"); 528fb9987d0SSujith goto err; 529fb9987d0SSujith } 530e8c35a77SFelix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { 531fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 532fb9987d0SSujith "Unable to setup xmit queue for VO traffic\n"); 533fb9987d0SSujith goto err; 534fb9987d0SSujith } 535fb9987d0SSujith 536fb9987d0SSujith return 0; 537fb9987d0SSujith 538fb9987d0SSujith err: 539fb9987d0SSujith return -EINVAL; 540fb9987d0SSujith } 541fb9987d0SSujith 542fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv) 543fb9987d0SSujith { 544fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 545fb9987d0SSujith int i = 0; 546fb9987d0SSujith 547fb9987d0SSujith /* Get the hardware key cache size. */ 548fb9987d0SSujith common->keymax = priv->ah->caps.keycache_size; 549fb9987d0SSujith if (common->keymax > ATH_KEYMAX) { 550fb9987d0SSujith ath_print(common, ATH_DBG_ANY, 551fb9987d0SSujith "Warning, using only %u entries in %u key cache\n", 552fb9987d0SSujith ATH_KEYMAX, common->keymax); 553fb9987d0SSujith common->keymax = ATH_KEYMAX; 554fb9987d0SSujith } 555fb9987d0SSujith 556e2b62624SRajkumar Manoharan if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) 557e2b62624SRajkumar Manoharan common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 558e2b62624SRajkumar Manoharan 559fb9987d0SSujith /* 560fb9987d0SSujith * Reset the key cache since some parts do not 561fb9987d0SSujith * reset the contents on initial power up. 562fb9987d0SSujith */ 563fb9987d0SSujith for (i = 0; i < common->keymax; i++) 564040e539eSBruno Randolf ath_hw_keyreset(common, (u16) i); 565fb9987d0SSujith } 566fb9987d0SSujith 567fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) 568fb9987d0SSujith { 569fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { 570fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].channels = 571fb9987d0SSujith ath9k_2ghz_channels; 572fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; 573fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].n_channels = 574fb9987d0SSujith ARRAY_SIZE(ath9k_2ghz_channels); 575fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; 576fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = 577fb9987d0SSujith ARRAY_SIZE(ath9k_legacy_rates); 578fb9987d0SSujith } 579ea46e644SSujith 580ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { 581ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; 582ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; 583ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].n_channels = 584ea46e644SSujith ARRAY_SIZE(ath9k_5ghz_channels); 585ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].bitrates = 586ea46e644SSujith ath9k_legacy_rates + 4; 587ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates = 588ea46e644SSujith ARRAY_SIZE(ath9k_legacy_rates) - 4; 589ea46e644SSujith } 590fb9987d0SSujith } 591fb9987d0SSujith 592fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv) 593fb9987d0SSujith { 594fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 595fb9987d0SSujith 596fb9987d0SSujith common->tx_chainmask = priv->ah->caps.tx_chainmask; 597fb9987d0SSujith common->rx_chainmask = priv->ah->caps.rx_chainmask; 598fb9987d0SSujith 599fb9987d0SSujith memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); 600fb9987d0SSujith 6019f01a84eSSujith priv->ah->opmode = NL80211_IFTYPE_STATION; 602fb9987d0SSujith } 603fb9987d0SSujith 60421cb9879SVivek Natarajan static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) 60521cb9879SVivek Natarajan { 60621cb9879SVivek Natarajan int qnum; 60721cb9879SVivek Natarajan 60821cb9879SVivek Natarajan switch (priv->ah->btcoex_hw.scheme) { 60921cb9879SVivek Natarajan case ATH_BTCOEX_CFG_NONE: 61021cb9879SVivek Natarajan break; 61121cb9879SVivek Natarajan case ATH_BTCOEX_CFG_3WIRE: 61221cb9879SVivek Natarajan priv->ah->btcoex_hw.btactive_gpio = 7; 61321cb9879SVivek Natarajan priv->ah->btcoex_hw.btpriority_gpio = 6; 61421cb9879SVivek Natarajan priv->ah->btcoex_hw.wlanactive_gpio = 8; 61521cb9879SVivek Natarajan priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 61621cb9879SVivek Natarajan ath9k_hw_btcoex_init_3wire(priv->ah); 61721cb9879SVivek Natarajan ath_htc_init_btcoex_work(priv); 61821cb9879SVivek Natarajan qnum = priv->hwq_map[WME_AC_BE]; 61921cb9879SVivek Natarajan ath9k_hw_init_btcoex_hw(priv->ah, qnum); 62021cb9879SVivek Natarajan break; 62121cb9879SVivek Natarajan default: 62221cb9879SVivek Natarajan WARN_ON(1); 62321cb9879SVivek Natarajan break; 62421cb9879SVivek Natarajan } 62521cb9879SVivek Natarajan } 62621cb9879SVivek Natarajan 62721cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv, 62821cb9879SVivek Natarajan u16 devid, char *product) 629fb9987d0SSujith { 630fb9987d0SSujith struct ath_hw *ah = NULL; 631fb9987d0SSujith struct ath_common *common; 632fb9987d0SSujith int ret = 0, csz = 0; 633fb9987d0SSujith 634fb9987d0SSujith priv->op_flags |= OP_INVALID; 635fb9987d0SSujith 636fb9987d0SSujith ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); 637fb9987d0SSujith if (!ah) 638fb9987d0SSujith return -ENOMEM; 639fb9987d0SSujith 640fb9987d0SSujith ah->hw_version.devid = devid; 641fb9987d0SSujith ah->hw_version.subsysid = 0; /* FIXME */ 642fb9987d0SSujith priv->ah = ah; 643fb9987d0SSujith 644fb9987d0SSujith common = ath9k_hw_common(ah); 645fb9987d0SSujith common->ops = &ath9k_common_ops; 646fb9987d0SSujith common->bus_ops = &ath9k_usb_bus_ops; 647fb9987d0SSujith common->ah = ah; 648fb9987d0SSujith common->hw = priv->hw; 649fb9987d0SSujith common->priv = priv; 650fb9987d0SSujith common->debug_mask = ath9k_debug; 651fb9987d0SSujith 652fb9987d0SSujith spin_lock_init(&priv->wmi->wmi_lock); 653fb9987d0SSujith spin_lock_init(&priv->beacon_lock); 6547757dfedSSujith spin_lock_init(&priv->tx_lock); 655fb9987d0SSujith mutex_init(&priv->mutex); 656bde748a4SVivek Natarajan mutex_init(&priv->htc_pm_lock); 657fb9987d0SSujith tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, 658fb9987d0SSujith (unsigned long)priv); 659fb9987d0SSujith tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 660fb9987d0SSujith (unsigned long)priv); 661fb9987d0SSujith tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); 662fb9987d0SSujith INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); 663bde748a4SVivek Natarajan INIT_WORK(&priv->ps_work, ath9k_ps_work); 664fb9987d0SSujith 665fb9987d0SSujith /* 666fb9987d0SSujith * Cache line size is used to size and align various 667fb9987d0SSujith * structures used to communicate with the hardware. 668fb9987d0SSujith */ 669fb9987d0SSujith ath_read_cachesize(common, &csz); 670fb9987d0SSujith common->cachelsz = csz << 2; /* convert to bytes */ 671fb9987d0SSujith 672fb9987d0SSujith ret = ath9k_hw_init(ah); 673fb9987d0SSujith if (ret) { 674fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 675fb9987d0SSujith "Unable to initialize hardware; " 676fb9987d0SSujith "initialization status: %d\n", ret); 677fb9987d0SSujith goto err_hw; 678fb9987d0SSujith } 679fb9987d0SSujith 680e1572c5eSSujith ret = ath9k_htc_init_debug(ah); 681fb9987d0SSujith if (ret) { 682fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 683fb9987d0SSujith "Unable to create debugfs files\n"); 684fb9987d0SSujith goto err_debug; 685fb9987d0SSujith } 686fb9987d0SSujith 687fb9987d0SSujith ret = ath9k_init_queues(priv); 688fb9987d0SSujith if (ret) 689fb9987d0SSujith goto err_queues; 690fb9987d0SSujith 691fb9987d0SSujith ath9k_init_crypto(priv); 692fb9987d0SSujith ath9k_init_channels_rates(priv); 693fb9987d0SSujith ath9k_init_misc(priv); 694fb9987d0SSujith 69521cb9879SVivek Natarajan if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { 69621cb9879SVivek Natarajan ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; 69721cb9879SVivek Natarajan ath9k_init_btcoex(priv); 69821cb9879SVivek Natarajan } 69921cb9879SVivek Natarajan 700fb9987d0SSujith return 0; 701fb9987d0SSujith 702fb9987d0SSujith err_queues: 703e1572c5eSSujith ath9k_htc_exit_debug(ah); 704fb9987d0SSujith err_debug: 705fb9987d0SSujith ath9k_hw_deinit(ah); 706fb9987d0SSujith err_hw: 707fb9987d0SSujith 708fb9987d0SSujith kfree(ah); 709fb9987d0SSujith priv->ah = NULL; 710fb9987d0SSujith 711fb9987d0SSujith return ret; 712fb9987d0SSujith } 713fb9987d0SSujith 714fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, 715fb9987d0SSujith struct ieee80211_hw *hw) 716fb9987d0SSujith { 717fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 718fb9987d0SSujith 719fb9987d0SSujith hw->flags = IEEE80211_HW_SIGNAL_DBM | 720fb9987d0SSujith IEEE80211_HW_AMPDU_AGGREGATION | 721fb9987d0SSujith IEEE80211_HW_SPECTRUM_MGMT | 72232fbccafSSujith IEEE80211_HW_HAS_RATE_CONTROL | 723bde748a4SVivek Natarajan IEEE80211_HW_RX_INCLUDES_FCS | 724bde748a4SVivek Natarajan IEEE80211_HW_SUPPORTS_PS | 725bde748a4SVivek Natarajan IEEE80211_HW_PS_NULLFUNC_STACK; 726fb9987d0SSujith 727fb9987d0SSujith hw->wiphy->interface_modes = 728fb9987d0SSujith BIT(NL80211_IFTYPE_STATION) | 729fb9987d0SSujith BIT(NL80211_IFTYPE_ADHOC); 730fb9987d0SSujith 731bde748a4SVivek Natarajan hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 732bde748a4SVivek Natarajan 733fb9987d0SSujith hw->queues = 4; 734fb9987d0SSujith hw->channel_change_time = 5000; 735fb9987d0SSujith hw->max_listen_interval = 10; 736fb9987d0SSujith hw->vif_data_size = sizeof(struct ath9k_htc_vif); 737fb9987d0SSujith hw->sta_data_size = sizeof(struct ath9k_htc_sta); 738fb9987d0SSujith 739fb9987d0SSujith /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ 740fb9987d0SSujith hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + 741fb9987d0SSujith sizeof(struct htc_frame_hdr) + 4; 742fb9987d0SSujith 743fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) 744fb9987d0SSujith hw->wiphy->bands[IEEE80211_BAND_2GHZ] = 745fb9987d0SSujith &priv->sbands[IEEE80211_BAND_2GHZ]; 746ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) 747ea46e644SSujith hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 748ea46e644SSujith &priv->sbands[IEEE80211_BAND_5GHZ]; 749fb9987d0SSujith 750fb9987d0SSujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 751fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) 752fb9987d0SSujith setup_ht_cap(priv, 753fb9987d0SSujith &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); 754ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) 755ea46e644SSujith setup_ht_cap(priv, 756ea46e644SSujith &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); 757fb9987d0SSujith } 758fb9987d0SSujith 759fb9987d0SSujith SET_IEEE80211_PERM_ADDR(hw, common->macaddr); 760fb9987d0SSujith } 761fb9987d0SSujith 76221cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv, 76321cb9879SVivek Natarajan u16 devid, char *product) 764fb9987d0SSujith { 765fb9987d0SSujith struct ieee80211_hw *hw = priv->hw; 766fb9987d0SSujith struct ath_common *common; 767fb9987d0SSujith struct ath_hw *ah; 768fb9987d0SSujith int error = 0; 769fb9987d0SSujith struct ath_regulatory *reg; 770fb9987d0SSujith 771fb9987d0SSujith /* Bring up device */ 77221cb9879SVivek Natarajan error = ath9k_init_priv(priv, devid, product); 773fb9987d0SSujith if (error != 0) 774fb9987d0SSujith goto err_init; 775fb9987d0SSujith 776fb9987d0SSujith ah = priv->ah; 777fb9987d0SSujith common = ath9k_hw_common(ah); 778fb9987d0SSujith ath9k_set_hw_capab(priv, hw); 779fb9987d0SSujith 780fb9987d0SSujith /* Initialize regulatory */ 781fb9987d0SSujith error = ath_regd_init(&common->regulatory, priv->hw->wiphy, 782fb9987d0SSujith ath9k_reg_notifier); 783fb9987d0SSujith if (error) 784fb9987d0SSujith goto err_regd; 785fb9987d0SSujith 786fb9987d0SSujith reg = &common->regulatory; 787fb9987d0SSujith 788fb9987d0SSujith /* Setup TX */ 789fb9987d0SSujith error = ath9k_tx_init(priv); 790fb9987d0SSujith if (error != 0) 791fb9987d0SSujith goto err_tx; 792fb9987d0SSujith 793fb9987d0SSujith /* Setup RX */ 794fb9987d0SSujith error = ath9k_rx_init(priv); 795fb9987d0SSujith if (error != 0) 796fb9987d0SSujith goto err_rx; 797fb9987d0SSujith 798fb9987d0SSujith /* Register with mac80211 */ 799fb9987d0SSujith error = ieee80211_register_hw(hw); 800fb9987d0SSujith if (error) 801fb9987d0SSujith goto err_register; 802fb9987d0SSujith 803fb9987d0SSujith /* Handle world regulatory */ 804fb9987d0SSujith if (!ath_is_world_regd(reg)) { 805fb9987d0SSujith error = regulatory_hint(hw->wiphy, reg->alpha2); 806fb9987d0SSujith if (error) 807fb9987d0SSujith goto err_world; 808fb9987d0SSujith } 809fb9987d0SSujith 810fb9987d0SSujith ath9k_init_leds(priv); 811fb9987d0SSujith ath9k_start_rfkill_poll(priv); 812fb9987d0SSujith 813fb9987d0SSujith return 0; 814fb9987d0SSujith 815fb9987d0SSujith err_world: 816fb9987d0SSujith ieee80211_unregister_hw(hw); 817fb9987d0SSujith err_register: 818fb9987d0SSujith ath9k_rx_cleanup(priv); 819fb9987d0SSujith err_rx: 820fb9987d0SSujith ath9k_tx_cleanup(priv); 821fb9987d0SSujith err_tx: 822fb9987d0SSujith /* Nothing */ 823fb9987d0SSujith err_regd: 824fb9987d0SSujith ath9k_deinit_priv(priv); 825fb9987d0SSujith err_init: 826fb9987d0SSujith return error; 827fb9987d0SSujith } 828fb9987d0SSujith 829fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, 83021cb9879SVivek Natarajan u16 devid, char *product) 831fb9987d0SSujith { 832fb9987d0SSujith struct ieee80211_hw *hw; 833fb9987d0SSujith struct ath9k_htc_priv *priv; 834fb9987d0SSujith int ret; 835fb9987d0SSujith 836fb9987d0SSujith hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); 837fb9987d0SSujith if (!hw) 838fb9987d0SSujith return -ENOMEM; 839fb9987d0SSujith 840fb9987d0SSujith priv = hw->priv; 841fb9987d0SSujith priv->hw = hw; 842fb9987d0SSujith priv->htc = htc_handle; 843fb9987d0SSujith priv->dev = dev; 844fb9987d0SSujith htc_handle->drv_priv = priv; 845fb9987d0SSujith SET_IEEE80211_DEV(hw, priv->dev); 846fb9987d0SSujith 847fb9987d0SSujith ret = ath9k_htc_wait_for_target(priv); 848fb9987d0SSujith if (ret) 849fb9987d0SSujith goto err_free; 850fb9987d0SSujith 851fb9987d0SSujith priv->wmi = ath9k_init_wmi(priv); 852fb9987d0SSujith if (!priv->wmi) { 853fb9987d0SSujith ret = -EINVAL; 854fb9987d0SSujith goto err_free; 855fb9987d0SSujith } 856fb9987d0SSujith 8576267dc70SSujith ret = ath9k_init_htc_services(priv, devid); 858fb9987d0SSujith if (ret) 859fb9987d0SSujith goto err_init; 860fb9987d0SSujith 861a3be14b7SSujith /* The device may have been unplugged earlier. */ 862a3be14b7SSujith priv->op_flags &= ~OP_UNPLUGGED; 863a3be14b7SSujith 86421cb9879SVivek Natarajan ret = ath9k_init_device(priv, devid, product); 865fb9987d0SSujith if (ret) 866fb9987d0SSujith goto err_init; 867fb9987d0SSujith 868fb9987d0SSujith return 0; 869fb9987d0SSujith 870fb9987d0SSujith err_init: 871fb9987d0SSujith ath9k_deinit_wmi(priv); 872fb9987d0SSujith err_free: 873fb9987d0SSujith ieee80211_free_hw(hw); 874fb9987d0SSujith return ret; 875fb9987d0SSujith } 876fb9987d0SSujith 877fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) 878fb9987d0SSujith { 879fb9987d0SSujith if (htc_handle->drv_priv) { 880a3be14b7SSujith 881a3be14b7SSujith /* Check if the device has been yanked out. */ 882a3be14b7SSujith if (hotunplug) 883a3be14b7SSujith htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; 884a3be14b7SSujith 885fb9987d0SSujith ath9k_deinit_device(htc_handle->drv_priv); 886fb9987d0SSujith ath9k_deinit_wmi(htc_handle->drv_priv); 887fb9987d0SSujith ieee80211_free_hw(htc_handle->drv_priv->hw); 888fb9987d0SSujith } 889fb9987d0SSujith } 890fb9987d0SSujith 891fb9987d0SSujith #ifdef CONFIG_PM 892fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle) 893fb9987d0SSujith { 894fb9987d0SSujith int ret; 895fb9987d0SSujith 896fb9987d0SSujith ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); 897fb9987d0SSujith if (ret) 898fb9987d0SSujith return ret; 899fb9987d0SSujith 9006267dc70SSujith ret = ath9k_init_htc_services(htc_handle->drv_priv, 9016267dc70SSujith htc_handle->drv_priv->ah->hw_version.devid); 902fb9987d0SSujith return ret; 903fb9987d0SSujith } 904fb9987d0SSujith #endif 905fb9987d0SSujith 906fb9987d0SSujith static int __init ath9k_htc_init(void) 907fb9987d0SSujith { 908fb9987d0SSujith int error; 909fb9987d0SSujith 910e1572c5eSSujith error = ath9k_htc_debug_create_root(); 911fb9987d0SSujith if (error < 0) { 912fb9987d0SSujith printk(KERN_ERR 913fb9987d0SSujith "ath9k_htc: Unable to create debugfs root: %d\n", 914fb9987d0SSujith error); 915fb9987d0SSujith goto err_dbg; 916fb9987d0SSujith } 917fb9987d0SSujith 918fb9987d0SSujith error = ath9k_hif_usb_init(); 919fb9987d0SSujith if (error < 0) { 920fb9987d0SSujith printk(KERN_ERR 921fb9987d0SSujith "ath9k_htc: No USB devices found," 922fb9987d0SSujith " driver not installed.\n"); 923fb9987d0SSujith error = -ENODEV; 924fb9987d0SSujith goto err_usb; 925fb9987d0SSujith } 926fb9987d0SSujith 927fb9987d0SSujith return 0; 928fb9987d0SSujith 929fb9987d0SSujith err_usb: 930e1572c5eSSujith ath9k_htc_debug_remove_root(); 931fb9987d0SSujith err_dbg: 932fb9987d0SSujith return error; 933fb9987d0SSujith } 934fb9987d0SSujith module_init(ath9k_htc_init); 935fb9987d0SSujith 936fb9987d0SSujith static void __exit ath9k_htc_exit(void) 937fb9987d0SSujith { 938fb9987d0SSujith ath9k_hif_usb_exit(); 939e1572c5eSSujith ath9k_htc_debug_remove_root(); 940fb9987d0SSujith printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); 941fb9987d0SSujith } 942fb9987d0SSujith module_exit(ath9k_htc_exit); 943