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 44fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = { 45fb9987d0SSujith CHAN2G(2412, 0), /* Channel 1 */ 46fb9987d0SSujith CHAN2G(2417, 1), /* Channel 2 */ 47fb9987d0SSujith CHAN2G(2422, 2), /* Channel 3 */ 48fb9987d0SSujith CHAN2G(2427, 3), /* Channel 4 */ 49fb9987d0SSujith CHAN2G(2432, 4), /* Channel 5 */ 50fb9987d0SSujith CHAN2G(2437, 5), /* Channel 6 */ 51fb9987d0SSujith CHAN2G(2442, 6), /* Channel 7 */ 52fb9987d0SSujith CHAN2G(2447, 7), /* Channel 8 */ 53fb9987d0SSujith CHAN2G(2452, 8), /* Channel 9 */ 54fb9987d0SSujith CHAN2G(2457, 9), /* Channel 10 */ 55fb9987d0SSujith CHAN2G(2462, 10), /* Channel 11 */ 56fb9987d0SSujith CHAN2G(2467, 11), /* Channel 12 */ 57fb9987d0SSujith CHAN2G(2472, 12), /* Channel 13 */ 58fb9987d0SSujith CHAN2G(2484, 13), /* Channel 14 */ 59fb9987d0SSujith }; 60fb9987d0SSujith 61ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = { 62ea46e644SSujith /* _We_ call this UNII 1 */ 63ea46e644SSujith CHAN5G(5180, 14), /* Channel 36 */ 64ea46e644SSujith CHAN5G(5200, 15), /* Channel 40 */ 65ea46e644SSujith CHAN5G(5220, 16), /* Channel 44 */ 66ea46e644SSujith CHAN5G(5240, 17), /* Channel 48 */ 67ea46e644SSujith /* _We_ call this UNII 2 */ 68ea46e644SSujith CHAN5G(5260, 18), /* Channel 52 */ 69ea46e644SSujith CHAN5G(5280, 19), /* Channel 56 */ 70ea46e644SSujith CHAN5G(5300, 20), /* Channel 60 */ 71ea46e644SSujith CHAN5G(5320, 21), /* Channel 64 */ 72ea46e644SSujith /* _We_ call this "Middle band" */ 73ea46e644SSujith CHAN5G(5500, 22), /* Channel 100 */ 74ea46e644SSujith CHAN5G(5520, 23), /* Channel 104 */ 75ea46e644SSujith CHAN5G(5540, 24), /* Channel 108 */ 76ea46e644SSujith CHAN5G(5560, 25), /* Channel 112 */ 77ea46e644SSujith CHAN5G(5580, 26), /* Channel 116 */ 78ea46e644SSujith CHAN5G(5600, 27), /* Channel 120 */ 79ea46e644SSujith CHAN5G(5620, 28), /* Channel 124 */ 80ea46e644SSujith CHAN5G(5640, 29), /* Channel 128 */ 81ea46e644SSujith CHAN5G(5660, 30), /* Channel 132 */ 82ea46e644SSujith CHAN5G(5680, 31), /* Channel 136 */ 83ea46e644SSujith CHAN5G(5700, 32), /* Channel 140 */ 84ea46e644SSujith /* _We_ call this UNII 3 */ 85ea46e644SSujith CHAN5G(5745, 33), /* Channel 149 */ 86ea46e644SSujith CHAN5G(5765, 34), /* Channel 153 */ 87ea46e644SSujith CHAN5G(5785, 35), /* Channel 157 */ 88ea46e644SSujith CHAN5G(5805, 36), /* Channel 161 */ 89ea46e644SSujith CHAN5G(5825, 37), /* Channel 165 */ 90ea46e644SSujith }; 91ea46e644SSujith 92fb9987d0SSujith /* Atheros hardware rate code addition for short premble */ 93fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \ 94fb9987d0SSujith ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) 95fb9987d0SSujith 96fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) { \ 97fb9987d0SSujith .bitrate = (_bitrate), \ 98fb9987d0SSujith .flags = (_flags), \ 99fb9987d0SSujith .hw_value = (_hw_rate), \ 100fb9987d0SSujith .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ 101fb9987d0SSujith } 102fb9987d0SSujith 103fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = { 104fb9987d0SSujith RATE(10, 0x1b, 0), 105fb9987d0SSujith RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ 106fb9987d0SSujith RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ 107fb9987d0SSujith RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ 108fb9987d0SSujith RATE(60, 0x0b, 0), 109fb9987d0SSujith RATE(90, 0x0f, 0), 110fb9987d0SSujith RATE(120, 0x0a, 0), 111fb9987d0SSujith RATE(180, 0x0e, 0), 112fb9987d0SSujith RATE(240, 0x09, 0), 113fb9987d0SSujith RATE(360, 0x0d, 0), 114fb9987d0SSujith RATE(480, 0x08, 0), 115fb9987d0SSujith RATE(540, 0x0c, 0), 116fb9987d0SSujith }; 117fb9987d0SSujith 118fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) 119fb9987d0SSujith { 120fb9987d0SSujith int time_left; 121fb9987d0SSujith 122d8c49ffbSSujith.Manoharan@atheros.com if (atomic_read(&priv->htc->tgt_ready) > 0) { 123d8c49ffbSSujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 124d8c49ffbSSujith.Manoharan@atheros.com return 0; 125d8c49ffbSSujith.Manoharan@atheros.com } 126d8c49ffbSSujith.Manoharan@atheros.com 127fb9987d0SSujith /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ 128fb9987d0SSujith time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); 129fb9987d0SSujith if (!time_left) { 130fb9987d0SSujith dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); 131fb9987d0SSujith return -ETIMEDOUT; 132fb9987d0SSujith } 133fb9987d0SSujith 134d8c49ffbSSujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 135d8c49ffbSSujith.Manoharan@atheros.com 136fb9987d0SSujith return 0; 137fb9987d0SSujith } 138fb9987d0SSujith 139fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) 140fb9987d0SSujith { 141e1572c5eSSujith ath9k_htc_exit_debug(priv->ah); 142fb9987d0SSujith ath9k_hw_deinit(priv->ah); 143fb9987d0SSujith tasklet_kill(&priv->wmi_tasklet); 144fb9987d0SSujith tasklet_kill(&priv->rx_tasklet); 145fb9987d0SSujith tasklet_kill(&priv->tx_tasklet); 146fb9987d0SSujith kfree(priv->ah); 147fb9987d0SSujith priv->ah = NULL; 148fb9987d0SSujith } 149fb9987d0SSujith 150fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv) 151fb9987d0SSujith { 152fb9987d0SSujith struct ieee80211_hw *hw = priv->hw; 153fb9987d0SSujith 154fb9987d0SSujith wiphy_rfkill_stop_polling(hw->wiphy); 155fb9987d0SSujith ath9k_deinit_leds(priv); 156fb9987d0SSujith ieee80211_unregister_hw(hw); 157fb9987d0SSujith ath9k_rx_cleanup(priv); 158fb9987d0SSujith ath9k_tx_cleanup(priv); 159fb9987d0SSujith ath9k_deinit_priv(priv); 160fb9987d0SSujith } 161fb9987d0SSujith 162fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, 163fb9987d0SSujith u16 service_id, 164fb9987d0SSujith void (*tx) (void *, 165fb9987d0SSujith struct sk_buff *, 166fb9987d0SSujith enum htc_endpoint_id, 167fb9987d0SSujith bool txok), 168fb9987d0SSujith enum htc_endpoint_id *ep_id) 169fb9987d0SSujith { 170fb9987d0SSujith struct htc_service_connreq req; 171fb9987d0SSujith 172fb9987d0SSujith memset(&req, 0, sizeof(struct htc_service_connreq)); 173fb9987d0SSujith 174fb9987d0SSujith req.service_id = service_id; 175fb9987d0SSujith req.ep_callbacks.priv = priv; 176fb9987d0SSujith req.ep_callbacks.rx = ath9k_htc_rxep; 177fb9987d0SSujith req.ep_callbacks.tx = tx; 178fb9987d0SSujith 179fb9987d0SSujith return htc_connect_service(priv->htc, &req, ep_id); 180fb9987d0SSujith } 181fb9987d0SSujith 182fb9987d0SSujith static int ath9k_init_htc_services(struct ath9k_htc_priv *priv) 183fb9987d0SSujith { 184fb9987d0SSujith int ret; 185fb9987d0SSujith 186fb9987d0SSujith /* WMI CMD*/ 187fb9987d0SSujith ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); 188fb9987d0SSujith if (ret) 189fb9987d0SSujith goto err; 190fb9987d0SSujith 191fb9987d0SSujith /* Beacon */ 1929c6dda4eSSujith ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep, 193fb9987d0SSujith &priv->beacon_ep); 194fb9987d0SSujith if (ret) 195fb9987d0SSujith goto err; 196fb9987d0SSujith 197fb9987d0SSujith /* CAB */ 198fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, 199fb9987d0SSujith &priv->cab_ep); 200fb9987d0SSujith if (ret) 201fb9987d0SSujith goto err; 202fb9987d0SSujith 203fb9987d0SSujith 204fb9987d0SSujith /* UAPSD */ 205fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, 206fb9987d0SSujith &priv->uapsd_ep); 207fb9987d0SSujith if (ret) 208fb9987d0SSujith goto err; 209fb9987d0SSujith 210fb9987d0SSujith /* MGMT */ 211fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, 212fb9987d0SSujith &priv->mgmt_ep); 213fb9987d0SSujith if (ret) 214fb9987d0SSujith goto err; 215fb9987d0SSujith 216fb9987d0SSujith /* DATA BE */ 217fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, 218fb9987d0SSujith &priv->data_be_ep); 219fb9987d0SSujith if (ret) 220fb9987d0SSujith goto err; 221fb9987d0SSujith 222fb9987d0SSujith /* DATA BK */ 223fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, 224fb9987d0SSujith &priv->data_bk_ep); 225fb9987d0SSujith if (ret) 226fb9987d0SSujith goto err; 227fb9987d0SSujith 228fb9987d0SSujith /* DATA VI */ 229fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, 230fb9987d0SSujith &priv->data_vi_ep); 231fb9987d0SSujith if (ret) 232fb9987d0SSujith goto err; 233fb9987d0SSujith 234fb9987d0SSujith /* DATA VO */ 235fb9987d0SSujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, 236fb9987d0SSujith &priv->data_vo_ep); 237fb9987d0SSujith if (ret) 238fb9987d0SSujith goto err; 239fb9987d0SSujith 240fb9987d0SSujith ret = htc_init(priv->htc); 241fb9987d0SSujith if (ret) 242fb9987d0SSujith goto err; 243fb9987d0SSujith 244fb9987d0SSujith return 0; 245fb9987d0SSujith 246fb9987d0SSujith err: 247fb9987d0SSujith dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); 248fb9987d0SSujith return ret; 249fb9987d0SSujith } 250fb9987d0SSujith 251fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy, 252fb9987d0SSujith struct regulatory_request *request) 253fb9987d0SSujith { 254fb9987d0SSujith struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 255fb9987d0SSujith struct ath9k_htc_priv *priv = hw->priv; 256fb9987d0SSujith 257fb9987d0SSujith return ath_reg_notifier_apply(wiphy, request, 258fb9987d0SSujith ath9k_hw_regulatory(priv->ah)); 259fb9987d0SSujith } 260fb9987d0SSujith 2614a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) 262fb9987d0SSujith { 263fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 264fb9987d0SSujith struct ath_common *common = ath9k_hw_common(ah); 265fb9987d0SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 266fb9987d0SSujith __be32 val, reg = cpu_to_be32(reg_offset); 267fb9987d0SSujith int r; 268fb9987d0SSujith 269fb9987d0SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, 270fb9987d0SSujith (u8 *) ®, sizeof(reg), 271fb9987d0SSujith (u8 *) &val, sizeof(val), 272fb9987d0SSujith 100); 273fb9987d0SSujith if (unlikely(r)) { 274fb9987d0SSujith ath_print(common, ATH_DBG_WMI, 275fb9987d0SSujith "REGISTER READ FAILED: (0x%04x, %d)\n", 276fb9987d0SSujith reg_offset, r); 277fb9987d0SSujith return -EIO; 278fb9987d0SSujith } 279fb9987d0SSujith 280fb9987d0SSujith return be32_to_cpu(val); 281fb9987d0SSujith } 282fb9987d0SSujith 2834a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) 284fb9987d0SSujith { 285fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 286fb9987d0SSujith struct ath_common *common = ath9k_hw_common(ah); 287fb9987d0SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 288fb9987d0SSujith __be32 buf[2] = { 289fb9987d0SSujith cpu_to_be32(reg_offset), 290fb9987d0SSujith cpu_to_be32(val), 291fb9987d0SSujith }; 292fb9987d0SSujith int r; 293fb9987d0SSujith 294fb9987d0SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 295fb9987d0SSujith (u8 *) &buf, sizeof(buf), 296fb9987d0SSujith (u8 *) &val, sizeof(val), 297fb9987d0SSujith 100); 298fb9987d0SSujith if (unlikely(r)) { 299fb9987d0SSujith ath_print(common, ATH_DBG_WMI, 300fb9987d0SSujith "REGISTER WRITE FAILED:(0x%04x, %d)\n", 301fb9987d0SSujith reg_offset, r); 302fb9987d0SSujith } 303fb9987d0SSujith } 304fb9987d0SSujith 3054a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) 3064a22fe10SSujith { 3074a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3084a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3094a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3104a22fe10SSujith u32 rsp_status; 3114a22fe10SSujith int r; 3124a22fe10SSujith 3134a22fe10SSujith mutex_lock(&priv->wmi->multi_write_mutex); 3144a22fe10SSujith 3154a22fe10SSujith /* Store the register/value */ 3164a22fe10SSujith priv->wmi->multi_write[priv->wmi->multi_write_idx].reg = 3174a22fe10SSujith cpu_to_be32(reg_offset); 3184a22fe10SSujith priv->wmi->multi_write[priv->wmi->multi_write_idx].val = 3194a22fe10SSujith cpu_to_be32(val); 3204a22fe10SSujith 3214a22fe10SSujith priv->wmi->multi_write_idx++; 3224a22fe10SSujith 3234a22fe10SSujith /* If the buffer is full, send it out. */ 3244a22fe10SSujith if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) { 3254a22fe10SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 3264a22fe10SSujith (u8 *) &priv->wmi->multi_write, 3274a22fe10SSujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 3284a22fe10SSujith (u8 *) &rsp_status, sizeof(rsp_status), 3294a22fe10SSujith 100); 3304a22fe10SSujith if (unlikely(r)) { 3314a22fe10SSujith ath_print(common, ATH_DBG_WMI, 3324a22fe10SSujith "REGISTER WRITE FAILED, multi len: %d\n", 3334a22fe10SSujith priv->wmi->multi_write_idx); 3344a22fe10SSujith } 3354a22fe10SSujith priv->wmi->multi_write_idx = 0; 3364a22fe10SSujith } 3374a22fe10SSujith 3384a22fe10SSujith mutex_unlock(&priv->wmi->multi_write_mutex); 3394a22fe10SSujith } 3404a22fe10SSujith 3414a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset) 3424a22fe10SSujith { 3434a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3444a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3454a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3464a22fe10SSujith 3474a22fe10SSujith if (atomic_read(&priv->wmi->mwrite_cnt)) 3484a22fe10SSujith ath9k_regwrite_buffer(hw_priv, val, reg_offset); 3494a22fe10SSujith else 3504a22fe10SSujith ath9k_regwrite_single(hw_priv, val, reg_offset); 3514a22fe10SSujith } 3524a22fe10SSujith 3534a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv) 3544a22fe10SSujith { 3554a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3564a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3574a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3584a22fe10SSujith 3594a22fe10SSujith atomic_inc(&priv->wmi->mwrite_cnt); 3604a22fe10SSujith } 3614a22fe10SSujith 3624a22fe10SSujith static void ath9k_disable_regwrite_buffer(void *hw_priv) 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 atomic_dec(&priv->wmi->mwrite_cnt); 3694a22fe10SSujith } 3704a22fe10SSujith 3714a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv) 3724a22fe10SSujith { 3734a22fe10SSujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3744a22fe10SSujith struct ath_common *common = ath9k_hw_common(ah); 3754a22fe10SSujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3764a22fe10SSujith u32 rsp_status; 3774a22fe10SSujith int r; 3784a22fe10SSujith 3794a22fe10SSujith mutex_lock(&priv->wmi->multi_write_mutex); 3804a22fe10SSujith 3814a22fe10SSujith if (priv->wmi->multi_write_idx) { 3824a22fe10SSujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 3834a22fe10SSujith (u8 *) &priv->wmi->multi_write, 3844a22fe10SSujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 3854a22fe10SSujith (u8 *) &rsp_status, sizeof(rsp_status), 3864a22fe10SSujith 100); 3874a22fe10SSujith if (unlikely(r)) { 3884a22fe10SSujith ath_print(common, ATH_DBG_WMI, 3894a22fe10SSujith "REGISTER WRITE FAILED, multi len: %d\n", 3904a22fe10SSujith priv->wmi->multi_write_idx); 3914a22fe10SSujith } 3924a22fe10SSujith priv->wmi->multi_write_idx = 0; 3934a22fe10SSujith } 3944a22fe10SSujith 3954a22fe10SSujith mutex_unlock(&priv->wmi->multi_write_mutex); 3964a22fe10SSujith } 3974a22fe10SSujith 398fb9987d0SSujith static const struct ath_ops ath9k_common_ops = { 3994a22fe10SSujith .read = ath9k_regread, 4004a22fe10SSujith .write = ath9k_regwrite, 4014a22fe10SSujith .enable_write_buffer = ath9k_enable_regwrite_buffer, 4024a22fe10SSujith .disable_write_buffer = ath9k_disable_regwrite_buffer, 4034a22fe10SSujith .write_flush = ath9k_regwrite_flush, 404fb9987d0SSujith }; 405fb9987d0SSujith 406fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz) 407fb9987d0SSujith { 408fb9987d0SSujith *csz = L1_CACHE_BYTES >> 2; 409fb9987d0SSujith } 410fb9987d0SSujith 411fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) 412fb9987d0SSujith { 413fb9987d0SSujith struct ath_hw *ah = (struct ath_hw *) common->ah; 414fb9987d0SSujith 415fb9987d0SSujith (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); 416fb9987d0SSujith 417fb9987d0SSujith if (!ath9k_hw_wait(ah, 418fb9987d0SSujith AR_EEPROM_STATUS_DATA, 419fb9987d0SSujith AR_EEPROM_STATUS_DATA_BUSY | 420fb9987d0SSujith AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, 421fb9987d0SSujith AH_WAIT_TIMEOUT)) 422fb9987d0SSujith return false; 423fb9987d0SSujith 424fb9987d0SSujith *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), 425fb9987d0SSujith AR_EEPROM_STATUS_DATA_VAL); 426fb9987d0SSujith 427fb9987d0SSujith return true; 428fb9987d0SSujith } 429fb9987d0SSujith 430fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = { 431497ad9adSSujith .ath_bus_type = ATH_USB, 432fb9987d0SSujith .read_cachesize = ath_usb_read_cachesize, 433fb9987d0SSujith .eeprom_read = ath_usb_eeprom_read, 434fb9987d0SSujith }; 435fb9987d0SSujith 436fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv, 437fb9987d0SSujith struct ieee80211_sta_ht_cap *ht_info) 438fb9987d0SSujith { 4396debecadSSujith struct ath_common *common = ath9k_hw_common(priv->ah); 4406debecadSSujith u8 tx_streams, rx_streams; 4416debecadSSujith int i; 4426debecadSSujith 443fb9987d0SSujith ht_info->ht_supported = true; 444fb9987d0SSujith ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 445fb9987d0SSujith IEEE80211_HT_CAP_SM_PS | 446fb9987d0SSujith IEEE80211_HT_CAP_SGI_40 | 447fb9987d0SSujith IEEE80211_HT_CAP_DSSSCCK40; 448fb9987d0SSujith 449b4dec5e8SSujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) 450b4dec5e8SSujith ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 451b4dec5e8SSujith 45217525f96SSujith ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 45317525f96SSujith 454fb9987d0SSujith ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 455fb9987d0SSujith ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 456fb9987d0SSujith 457fb9987d0SSujith memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 4586debecadSSujith 4596debecadSSujith /* ath9k_htc supports only 1 or 2 stream devices */ 4606debecadSSujith tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); 4616debecadSSujith rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); 4626debecadSSujith 4636debecadSSujith ath_print(common, ATH_DBG_CONFIG, 4646debecadSSujith "TX streams %d, RX streams: %d\n", 4656debecadSSujith tx_streams, rx_streams); 4666debecadSSujith 4676debecadSSujith if (tx_streams != rx_streams) { 4686debecadSSujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 4696debecadSSujith ht_info->mcs.tx_params |= ((tx_streams - 1) << 4706debecadSSujith IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 4716debecadSSujith } 4726debecadSSujith 4736debecadSSujith for (i = 0; i < rx_streams; i++) 4746debecadSSujith ht_info->mcs.rx_mask[i] = 0xff; 4756debecadSSujith 476fb9987d0SSujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 477fb9987d0SSujith } 478fb9987d0SSujith 479fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv) 480fb9987d0SSujith { 481fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 482fb9987d0SSujith int i; 483fb9987d0SSujith 484fb9987d0SSujith for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) 485fb9987d0SSujith priv->hwq_map[i] = -1; 486fb9987d0SSujith 487ca74b83bSSujith priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); 488ca74b83bSSujith if (priv->beaconq == -1) { 489ca74b83bSSujith ath_print(common, ATH_DBG_FATAL, 490ca74b83bSSujith "Unable to setup BEACON xmit queue\n"); 491ca74b83bSSujith goto err; 492ca74b83bSSujith } 493ca74b83bSSujith 494ca74b83bSSujith priv->cabq = ath9k_htc_cabq_setup(priv); 495ca74b83bSSujith if (priv->cabq == -1) { 496ca74b83bSSujith ath_print(common, ATH_DBG_FATAL, 497ca74b83bSSujith "Unable to setup CAB xmit queue\n"); 498ca74b83bSSujith goto err; 499ca74b83bSSujith } 500ca74b83bSSujith 501fb9987d0SSujith if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { 502fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 503fb9987d0SSujith "Unable to setup xmit queue for BE traffic\n"); 504fb9987d0SSujith goto err; 505fb9987d0SSujith } 506fb9987d0SSujith 507fb9987d0SSujith if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { 508fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 509fb9987d0SSujith "Unable to setup xmit queue for BK traffic\n"); 510fb9987d0SSujith goto err; 511fb9987d0SSujith } 512fb9987d0SSujith if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { 513fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 514fb9987d0SSujith "Unable to setup xmit queue for VI traffic\n"); 515fb9987d0SSujith goto err; 516fb9987d0SSujith } 517fb9987d0SSujith if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { 518fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 519fb9987d0SSujith "Unable to setup xmit queue for VO traffic\n"); 520fb9987d0SSujith goto err; 521fb9987d0SSujith } 522fb9987d0SSujith 523fb9987d0SSujith return 0; 524fb9987d0SSujith 525fb9987d0SSujith err: 526fb9987d0SSujith return -EINVAL; 527fb9987d0SSujith } 528fb9987d0SSujith 529fb9987d0SSujith static void ath9k_init_crypto(struct ath9k_htc_priv *priv) 530fb9987d0SSujith { 531fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 532fb9987d0SSujith int i = 0; 533fb9987d0SSujith 534fb9987d0SSujith /* Get the hardware key cache size. */ 535fb9987d0SSujith common->keymax = priv->ah->caps.keycache_size; 536fb9987d0SSujith if (common->keymax > ATH_KEYMAX) { 537fb9987d0SSujith ath_print(common, ATH_DBG_ANY, 538fb9987d0SSujith "Warning, using only %u entries in %u key cache\n", 539fb9987d0SSujith ATH_KEYMAX, common->keymax); 540fb9987d0SSujith common->keymax = ATH_KEYMAX; 541fb9987d0SSujith } 542fb9987d0SSujith 543fb9987d0SSujith /* 544fb9987d0SSujith * Reset the key cache since some parts do not 545fb9987d0SSujith * reset the contents on initial power up. 546fb9987d0SSujith */ 547fb9987d0SSujith for (i = 0; i < common->keymax; i++) 548fb9987d0SSujith ath9k_hw_keyreset(priv->ah, (u16) i); 549fb9987d0SSujith 550fb9987d0SSujith if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, 551fb9987d0SSujith ATH9K_CIPHER_TKIP, NULL)) { 552fb9987d0SSujith /* 553fb9987d0SSujith * Whether we should enable h/w TKIP MIC. 554fb9987d0SSujith * XXX: if we don't support WME TKIP MIC, then we wouldn't 555fb9987d0SSujith * report WMM capable, so it's always safe to turn on 556fb9987d0SSujith * TKIP MIC in this case. 557fb9987d0SSujith */ 558fb9987d0SSujith ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); 559fb9987d0SSujith } 560fb9987d0SSujith 561fb9987d0SSujith /* 562fb9987d0SSujith * Check whether the separate key cache entries 563fb9987d0SSujith * are required to handle both tx+rx MIC keys. 564fb9987d0SSujith * With split mic keys the number of stations is limited 565fb9987d0SSujith * to 27 otherwise 59. 566fb9987d0SSujith */ 567fb9987d0SSujith if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, 568fb9987d0SSujith ATH9K_CIPHER_TKIP, NULL) 569fb9987d0SSujith && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, 570fb9987d0SSujith ATH9K_CIPHER_MIC, NULL) 571fb9987d0SSujith && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, 572fb9987d0SSujith 0, NULL)) 573fb9987d0SSujith common->splitmic = 1; 574fb9987d0SSujith 575fb9987d0SSujith /* turn on mcast key search if possible */ 576fb9987d0SSujith if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) 577fb9987d0SSujith (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 578fb9987d0SSujith 1, 1, NULL); 579fb9987d0SSujith } 580fb9987d0SSujith 581fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) 582fb9987d0SSujith { 583fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { 584fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].channels = 585fb9987d0SSujith ath9k_2ghz_channels; 586fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; 587fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].n_channels = 588fb9987d0SSujith ARRAY_SIZE(ath9k_2ghz_channels); 589fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; 590fb9987d0SSujith priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = 591fb9987d0SSujith ARRAY_SIZE(ath9k_legacy_rates); 592fb9987d0SSujith } 593ea46e644SSujith 594ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { 595ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; 596ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; 597ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].n_channels = 598ea46e644SSujith ARRAY_SIZE(ath9k_5ghz_channels); 599ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].bitrates = 600ea46e644SSujith ath9k_legacy_rates + 4; 601ea46e644SSujith priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates = 602ea46e644SSujith ARRAY_SIZE(ath9k_legacy_rates) - 4; 603ea46e644SSujith } 604fb9987d0SSujith } 605fb9987d0SSujith 606fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv) 607fb9987d0SSujith { 608fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 609fb9987d0SSujith 610fb9987d0SSujith common->tx_chainmask = priv->ah->caps.tx_chainmask; 611fb9987d0SSujith common->rx_chainmask = priv->ah->caps.rx_chainmask; 612fb9987d0SSujith 613fb9987d0SSujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) 614fb9987d0SSujith memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); 615fb9987d0SSujith 616fb9987d0SSujith priv->op_flags |= OP_TXAGGR; 6179f01a84eSSujith priv->ah->opmode = NL80211_IFTYPE_STATION; 618fb9987d0SSujith } 619fb9987d0SSujith 620fb9987d0SSujith static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) 621fb9987d0SSujith { 622fb9987d0SSujith struct ath_hw *ah = NULL; 623fb9987d0SSujith struct ath_common *common; 624fb9987d0SSujith int ret = 0, csz = 0; 625fb9987d0SSujith 626fb9987d0SSujith priv->op_flags |= OP_INVALID; 627fb9987d0SSujith 628fb9987d0SSujith ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); 629fb9987d0SSujith if (!ah) 630fb9987d0SSujith return -ENOMEM; 631fb9987d0SSujith 632fb9987d0SSujith ah->hw_version.devid = devid; 633fb9987d0SSujith ah->hw_version.subsysid = 0; /* FIXME */ 634fb9987d0SSujith priv->ah = ah; 635fb9987d0SSujith 636fb9987d0SSujith common = ath9k_hw_common(ah); 637fb9987d0SSujith common->ops = &ath9k_common_ops; 638fb9987d0SSujith common->bus_ops = &ath9k_usb_bus_ops; 639fb9987d0SSujith common->ah = ah; 640fb9987d0SSujith common->hw = priv->hw; 641fb9987d0SSujith common->priv = priv; 642fb9987d0SSujith common->debug_mask = ath9k_debug; 643fb9987d0SSujith 644fb9987d0SSujith spin_lock_init(&priv->wmi->wmi_lock); 645fb9987d0SSujith spin_lock_init(&priv->beacon_lock); 6467757dfedSSujith spin_lock_init(&priv->tx_lock); 647fb9987d0SSujith mutex_init(&priv->mutex); 648fb9987d0SSujith mutex_init(&priv->aggr_work.mutex); 649bde748a4SVivek Natarajan mutex_init(&priv->htc_pm_lock); 650fb9987d0SSujith tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, 651fb9987d0SSujith (unsigned long)priv); 652fb9987d0SSujith tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 653fb9987d0SSujith (unsigned long)priv); 654fb9987d0SSujith tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); 655fb9987d0SSujith INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); 656fb9987d0SSujith INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); 657bde748a4SVivek Natarajan INIT_WORK(&priv->ps_work, ath9k_ps_work); 658fb9987d0SSujith 659fb9987d0SSujith /* 660fb9987d0SSujith * Cache line size is used to size and align various 661fb9987d0SSujith * structures used to communicate with the hardware. 662fb9987d0SSujith */ 663fb9987d0SSujith ath_read_cachesize(common, &csz); 664fb9987d0SSujith common->cachelsz = csz << 2; /* convert to bytes */ 665fb9987d0SSujith 666fb9987d0SSujith ret = ath9k_hw_init(ah); 667fb9987d0SSujith if (ret) { 668fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 669fb9987d0SSujith "Unable to initialize hardware; " 670fb9987d0SSujith "initialization status: %d\n", ret); 671fb9987d0SSujith goto err_hw; 672fb9987d0SSujith } 673fb9987d0SSujith 674e1572c5eSSujith ret = ath9k_htc_init_debug(ah); 675fb9987d0SSujith if (ret) { 676fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 677fb9987d0SSujith "Unable to create debugfs files\n"); 678fb9987d0SSujith goto err_debug; 679fb9987d0SSujith } 680fb9987d0SSujith 681fb9987d0SSujith ret = ath9k_init_queues(priv); 682fb9987d0SSujith if (ret) 683fb9987d0SSujith goto err_queues; 684fb9987d0SSujith 685fb9987d0SSujith ath9k_init_crypto(priv); 686fb9987d0SSujith ath9k_init_channels_rates(priv); 687fb9987d0SSujith ath9k_init_misc(priv); 688fb9987d0SSujith 689fb9987d0SSujith return 0; 690fb9987d0SSujith 691fb9987d0SSujith err_queues: 692e1572c5eSSujith ath9k_htc_exit_debug(ah); 693fb9987d0SSujith err_debug: 694fb9987d0SSujith ath9k_hw_deinit(ah); 695fb9987d0SSujith err_hw: 696fb9987d0SSujith 697fb9987d0SSujith kfree(ah); 698fb9987d0SSujith priv->ah = NULL; 699fb9987d0SSujith 700fb9987d0SSujith return ret; 701fb9987d0SSujith } 702fb9987d0SSujith 703fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, 704fb9987d0SSujith struct ieee80211_hw *hw) 705fb9987d0SSujith { 706fb9987d0SSujith struct ath_common *common = ath9k_hw_common(priv->ah); 707fb9987d0SSujith 708fb9987d0SSujith hw->flags = IEEE80211_HW_SIGNAL_DBM | 709fb9987d0SSujith IEEE80211_HW_AMPDU_AGGREGATION | 710fb9987d0SSujith IEEE80211_HW_SPECTRUM_MGMT | 71132fbccafSSujith IEEE80211_HW_HAS_RATE_CONTROL | 712bde748a4SVivek Natarajan IEEE80211_HW_RX_INCLUDES_FCS | 713bde748a4SVivek Natarajan IEEE80211_HW_SUPPORTS_PS | 714bde748a4SVivek Natarajan IEEE80211_HW_PS_NULLFUNC_STACK; 715fb9987d0SSujith 716fb9987d0SSujith hw->wiphy->interface_modes = 717fb9987d0SSujith BIT(NL80211_IFTYPE_STATION) | 718fb9987d0SSujith BIT(NL80211_IFTYPE_ADHOC); 719fb9987d0SSujith 720bde748a4SVivek Natarajan hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 721bde748a4SVivek Natarajan 722fb9987d0SSujith hw->queues = 4; 723fb9987d0SSujith hw->channel_change_time = 5000; 724fb9987d0SSujith hw->max_listen_interval = 10; 725fb9987d0SSujith hw->vif_data_size = sizeof(struct ath9k_htc_vif); 726fb9987d0SSujith hw->sta_data_size = sizeof(struct ath9k_htc_sta); 727fb9987d0SSujith 728fb9987d0SSujith /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ 729fb9987d0SSujith hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + 730fb9987d0SSujith sizeof(struct htc_frame_hdr) + 4; 731fb9987d0SSujith 732fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) 733fb9987d0SSujith hw->wiphy->bands[IEEE80211_BAND_2GHZ] = 734fb9987d0SSujith &priv->sbands[IEEE80211_BAND_2GHZ]; 735ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) 736ea46e644SSujith hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 737ea46e644SSujith &priv->sbands[IEEE80211_BAND_5GHZ]; 738fb9987d0SSujith 739fb9987d0SSujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 740fb9987d0SSujith if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) 741fb9987d0SSujith setup_ht_cap(priv, 742fb9987d0SSujith &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); 743ea46e644SSujith if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) 744ea46e644SSujith setup_ht_cap(priv, 745ea46e644SSujith &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); 746fb9987d0SSujith } 747fb9987d0SSujith 748fb9987d0SSujith SET_IEEE80211_PERM_ADDR(hw, common->macaddr); 749fb9987d0SSujith } 750fb9987d0SSujith 751fb9987d0SSujith static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) 752fb9987d0SSujith { 753fb9987d0SSujith struct ieee80211_hw *hw = priv->hw; 754fb9987d0SSujith struct ath_common *common; 755fb9987d0SSujith struct ath_hw *ah; 756fb9987d0SSujith int error = 0; 757fb9987d0SSujith struct ath_regulatory *reg; 758fb9987d0SSujith 759fb9987d0SSujith /* Bring up device */ 760fb9987d0SSujith error = ath9k_init_priv(priv, devid); 761fb9987d0SSujith if (error != 0) 762fb9987d0SSujith goto err_init; 763fb9987d0SSujith 764fb9987d0SSujith ah = priv->ah; 765fb9987d0SSujith common = ath9k_hw_common(ah); 766fb9987d0SSujith ath9k_set_hw_capab(priv, hw); 767fb9987d0SSujith 768fb9987d0SSujith /* Initialize regulatory */ 769fb9987d0SSujith error = ath_regd_init(&common->regulatory, priv->hw->wiphy, 770fb9987d0SSujith ath9k_reg_notifier); 771fb9987d0SSujith if (error) 772fb9987d0SSujith goto err_regd; 773fb9987d0SSujith 774fb9987d0SSujith reg = &common->regulatory; 775fb9987d0SSujith 776fb9987d0SSujith /* Setup TX */ 777fb9987d0SSujith error = ath9k_tx_init(priv); 778fb9987d0SSujith if (error != 0) 779fb9987d0SSujith goto err_tx; 780fb9987d0SSujith 781fb9987d0SSujith /* Setup RX */ 782fb9987d0SSujith error = ath9k_rx_init(priv); 783fb9987d0SSujith if (error != 0) 784fb9987d0SSujith goto err_rx; 785fb9987d0SSujith 786fb9987d0SSujith /* Register with mac80211 */ 787fb9987d0SSujith error = ieee80211_register_hw(hw); 788fb9987d0SSujith if (error) 789fb9987d0SSujith goto err_register; 790fb9987d0SSujith 791fb9987d0SSujith /* Handle world regulatory */ 792fb9987d0SSujith if (!ath_is_world_regd(reg)) { 793fb9987d0SSujith error = regulatory_hint(hw->wiphy, reg->alpha2); 794fb9987d0SSujith if (error) 795fb9987d0SSujith goto err_world; 796fb9987d0SSujith } 797fb9987d0SSujith 798fb9987d0SSujith ath9k_init_leds(priv); 799fb9987d0SSujith ath9k_start_rfkill_poll(priv); 800fb9987d0SSujith 801fb9987d0SSujith return 0; 802fb9987d0SSujith 803fb9987d0SSujith err_world: 804fb9987d0SSujith ieee80211_unregister_hw(hw); 805fb9987d0SSujith err_register: 806fb9987d0SSujith ath9k_rx_cleanup(priv); 807fb9987d0SSujith err_rx: 808fb9987d0SSujith ath9k_tx_cleanup(priv); 809fb9987d0SSujith err_tx: 810fb9987d0SSujith /* Nothing */ 811fb9987d0SSujith err_regd: 812fb9987d0SSujith ath9k_deinit_priv(priv); 813fb9987d0SSujith err_init: 814fb9987d0SSujith return error; 815fb9987d0SSujith } 816fb9987d0SSujith 817fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, 818fb9987d0SSujith u16 devid) 819fb9987d0SSujith { 820fb9987d0SSujith struct ieee80211_hw *hw; 821fb9987d0SSujith struct ath9k_htc_priv *priv; 822fb9987d0SSujith int ret; 823fb9987d0SSujith 824fb9987d0SSujith hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); 825fb9987d0SSujith if (!hw) 826fb9987d0SSujith return -ENOMEM; 827fb9987d0SSujith 828fb9987d0SSujith priv = hw->priv; 829fb9987d0SSujith priv->hw = hw; 830fb9987d0SSujith priv->htc = htc_handle; 831fb9987d0SSujith priv->dev = dev; 832fb9987d0SSujith htc_handle->drv_priv = priv; 833fb9987d0SSujith SET_IEEE80211_DEV(hw, priv->dev); 834fb9987d0SSujith 835fb9987d0SSujith ret = ath9k_htc_wait_for_target(priv); 836fb9987d0SSujith if (ret) 837fb9987d0SSujith goto err_free; 838fb9987d0SSujith 839fb9987d0SSujith priv->wmi = ath9k_init_wmi(priv); 840fb9987d0SSujith if (!priv->wmi) { 841fb9987d0SSujith ret = -EINVAL; 842fb9987d0SSujith goto err_free; 843fb9987d0SSujith } 844fb9987d0SSujith 845fb9987d0SSujith ret = ath9k_init_htc_services(priv); 846fb9987d0SSujith if (ret) 847fb9987d0SSujith goto err_init; 848fb9987d0SSujith 849a3be14b7SSujith /* The device may have been unplugged earlier. */ 850a3be14b7SSujith priv->op_flags &= ~OP_UNPLUGGED; 851a3be14b7SSujith 852fb9987d0SSujith ret = ath9k_init_device(priv, devid); 853fb9987d0SSujith if (ret) 854fb9987d0SSujith goto err_init; 855fb9987d0SSujith 856fb9987d0SSujith return 0; 857fb9987d0SSujith 858fb9987d0SSujith err_init: 859fb9987d0SSujith ath9k_deinit_wmi(priv); 860fb9987d0SSujith err_free: 861fb9987d0SSujith ieee80211_free_hw(hw); 862fb9987d0SSujith return ret; 863fb9987d0SSujith } 864fb9987d0SSujith 865fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) 866fb9987d0SSujith { 867fb9987d0SSujith if (htc_handle->drv_priv) { 868a3be14b7SSujith 869a3be14b7SSujith /* Check if the device has been yanked out. */ 870a3be14b7SSujith if (hotunplug) 871a3be14b7SSujith htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; 872a3be14b7SSujith 873fb9987d0SSujith ath9k_deinit_device(htc_handle->drv_priv); 874fb9987d0SSujith ath9k_deinit_wmi(htc_handle->drv_priv); 875fb9987d0SSujith ieee80211_free_hw(htc_handle->drv_priv->hw); 876fb9987d0SSujith } 877fb9987d0SSujith } 878fb9987d0SSujith 879fb9987d0SSujith #ifdef CONFIG_PM 880fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle) 881fb9987d0SSujith { 882fb9987d0SSujith int ret; 883fb9987d0SSujith 884fb9987d0SSujith ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); 885fb9987d0SSujith if (ret) 886fb9987d0SSujith return ret; 887fb9987d0SSujith 888fb9987d0SSujith ret = ath9k_init_htc_services(htc_handle->drv_priv); 889fb9987d0SSujith return ret; 890fb9987d0SSujith } 891fb9987d0SSujith #endif 892fb9987d0SSujith 893fb9987d0SSujith static int __init ath9k_htc_init(void) 894fb9987d0SSujith { 895fb9987d0SSujith int error; 896fb9987d0SSujith 897e1572c5eSSujith error = ath9k_htc_debug_create_root(); 898fb9987d0SSujith if (error < 0) { 899fb9987d0SSujith printk(KERN_ERR 900fb9987d0SSujith "ath9k_htc: Unable to create debugfs root: %d\n", 901fb9987d0SSujith error); 902fb9987d0SSujith goto err_dbg; 903fb9987d0SSujith } 904fb9987d0SSujith 905fb9987d0SSujith error = ath9k_hif_usb_init(); 906fb9987d0SSujith if (error < 0) { 907fb9987d0SSujith printk(KERN_ERR 908fb9987d0SSujith "ath9k_htc: No USB devices found," 909fb9987d0SSujith " driver not installed.\n"); 910fb9987d0SSujith error = -ENODEV; 911fb9987d0SSujith goto err_usb; 912fb9987d0SSujith } 913fb9987d0SSujith 914fb9987d0SSujith return 0; 915fb9987d0SSujith 916fb9987d0SSujith err_usb: 917e1572c5eSSujith ath9k_htc_debug_remove_root(); 918fb9987d0SSujith err_dbg: 919fb9987d0SSujith return error; 920fb9987d0SSujith } 921fb9987d0SSujith module_init(ath9k_htc_init); 922fb9987d0SSujith 923fb9987d0SSujith static void __exit ath9k_htc_exit(void) 924fb9987d0SSujith { 925fb9987d0SSujith ath9k_hif_usb_exit(); 926e1572c5eSSujith ath9k_htc_debug_remove_root(); 927fb9987d0SSujith printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); 928fb9987d0SSujith } 929fb9987d0SSujith module_exit(ath9k_htc_exit); 930