htc_drv_init.c revision f82b4bde17aeb6c2f8bf0540ee44811de4651cf6
1fb9987d0f748c983bb795a86f47522313f701a08Sujith/* 25b68138e5659cbfd5df2879d17f9ba0b66477fecSujith Manoharan * Copyright (c) 2010-2011 Atheros Communications Inc. 3fb9987d0f748c983bb795a86f47522313f701a08Sujith * 4fb9987d0f748c983bb795a86f47522313f701a08Sujith * Permission to use, copy, modify, and/or distribute this software for any 5fb9987d0f748c983bb795a86f47522313f701a08Sujith * purpose with or without fee is hereby granted, provided that the above 6fb9987d0f748c983bb795a86f47522313f701a08Sujith * copyright notice and this permission notice appear in all copies. 7fb9987d0f748c983bb795a86f47522313f701a08Sujith * 8fb9987d0f748c983bb795a86f47522313f701a08Sujith * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9fb9987d0f748c983bb795a86f47522313f701a08Sujith * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10fb9987d0f748c983bb795a86f47522313f701a08Sujith * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11fb9987d0f748c983bb795a86f47522313f701a08Sujith * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12fb9987d0f748c983bb795a86f47522313f701a08Sujith * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13fb9987d0f748c983bb795a86f47522313f701a08Sujith * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14fb9987d0f748c983bb795a86f47522313f701a08Sujith * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15fb9987d0f748c983bb795a86f47522313f701a08Sujith */ 16fb9987d0f748c983bb795a86f47522313f701a08Sujith 17fb9987d0f748c983bb795a86f47522313f701a08Sujith#include "htc.h" 18fb9987d0f748c983bb795a86f47522313f701a08Sujith 19fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_AUTHOR("Atheros Communications"); 20fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_LICENSE("Dual BSD/GPL"); 21fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices"); 22fb9987d0f748c983bb795a86f47522313f701a08Sujith 23fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic unsigned int ath9k_debug = ATH_DBG_DEFAULT; 24fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_param_named(debug, ath9k_debug, uint, 0); 25fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_PARM_DESC(debug, "Debugging mask"); 26fb9987d0f748c983bb795a86f47522313f701a08Sujith 27e1572c5eeca8ef87a250322364584458b2dadb35Sujithint htc_modparam_nohwcrypt; 28e1572c5eeca8ef87a250322364584458b2dadb35Sujithmodule_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444); 29fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); 30fb9987d0f748c983bb795a86f47522313f701a08Sujith 31fb9987d0f748c983bb795a86f47522313f701a08Sujith#define CHAN2G(_freq, _idx) { \ 32fb9987d0f748c983bb795a86f47522313f701a08Sujith .center_freq = (_freq), \ 33fb9987d0f748c983bb795a86f47522313f701a08Sujith .hw_value = (_idx), \ 34fb9987d0f748c983bb795a86f47522313f701a08Sujith .max_power = 20, \ 35fb9987d0f748c983bb795a86f47522313f701a08Sujith} 36fb9987d0f748c983bb795a86f47522313f701a08Sujith 37ea46e644e80bd4ac778964afd998df4f666486d4Sujith#define CHAN5G(_freq, _idx) { \ 38ea46e644e80bd4ac778964afd998df4f666486d4Sujith .band = IEEE80211_BAND_5GHZ, \ 39ea46e644e80bd4ac778964afd998df4f666486d4Sujith .center_freq = (_freq), \ 40ea46e644e80bd4ac778964afd998df4f666486d4Sujith .hw_value = (_idx), \ 41ea46e644e80bd4ac778964afd998df4f666486d4Sujith .max_power = 20, \ 42ea46e644e80bd4ac778964afd998df4f666486d4Sujith} 43ea46e644e80bd4ac778964afd998df4f666486d4Sujith 4421cb987914cb5334af78378141efed77505ea987Vivek Natarajan#define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" 4521cb987914cb5334af78378141efed77505ea987Vivek Natarajan 46fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic struct ieee80211_channel ath9k_2ghz_channels[] = { 47fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2412, 0), /* Channel 1 */ 48fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2417, 1), /* Channel 2 */ 49fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2422, 2), /* Channel 3 */ 50fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2427, 3), /* Channel 4 */ 51fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2432, 4), /* Channel 5 */ 52fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2437, 5), /* Channel 6 */ 53fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2442, 6), /* Channel 7 */ 54fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2447, 7), /* Channel 8 */ 55fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2452, 8), /* Channel 9 */ 56fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2457, 9), /* Channel 10 */ 57fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2462, 10), /* Channel 11 */ 58fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2467, 11), /* Channel 12 */ 59fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2472, 12), /* Channel 13 */ 60fb9987d0f748c983bb795a86f47522313f701a08Sujith CHAN2G(2484, 13), /* Channel 14 */ 61fb9987d0f748c983bb795a86f47522313f701a08Sujith}; 62fb9987d0f748c983bb795a86f47522313f701a08Sujith 63ea46e644e80bd4ac778964afd998df4f666486d4Sujithstatic struct ieee80211_channel ath9k_5ghz_channels[] = { 64ea46e644e80bd4ac778964afd998df4f666486d4Sujith /* _We_ call this UNII 1 */ 65ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5180, 14), /* Channel 36 */ 66ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5200, 15), /* Channel 40 */ 67ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5220, 16), /* Channel 44 */ 68ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5240, 17), /* Channel 48 */ 69ea46e644e80bd4ac778964afd998df4f666486d4Sujith /* _We_ call this UNII 2 */ 70ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5260, 18), /* Channel 52 */ 71ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5280, 19), /* Channel 56 */ 72ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5300, 20), /* Channel 60 */ 73ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5320, 21), /* Channel 64 */ 74ea46e644e80bd4ac778964afd998df4f666486d4Sujith /* _We_ call this "Middle band" */ 75ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5500, 22), /* Channel 100 */ 76ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5520, 23), /* Channel 104 */ 77ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5540, 24), /* Channel 108 */ 78ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5560, 25), /* Channel 112 */ 79ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5580, 26), /* Channel 116 */ 80ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5600, 27), /* Channel 120 */ 81ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5620, 28), /* Channel 124 */ 82ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5640, 29), /* Channel 128 */ 83ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5660, 30), /* Channel 132 */ 84ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5680, 31), /* Channel 136 */ 85ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5700, 32), /* Channel 140 */ 86ea46e644e80bd4ac778964afd998df4f666486d4Sujith /* _We_ call this UNII 3 */ 87ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5745, 33), /* Channel 149 */ 88ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5765, 34), /* Channel 153 */ 89ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5785, 35), /* Channel 157 */ 90ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5805, 36), /* Channel 161 */ 91ea46e644e80bd4ac778964afd998df4f666486d4Sujith CHAN5G(5825, 37), /* Channel 165 */ 92ea46e644e80bd4ac778964afd998df4f666486d4Sujith}; 93ea46e644e80bd4ac778964afd998df4f666486d4Sujith 94fb9987d0f748c983bb795a86f47522313f701a08Sujith/* Atheros hardware rate code addition for short premble */ 95fb9987d0f748c983bb795a86f47522313f701a08Sujith#define SHPCHECK(__hw_rate, __flags) \ 96fb9987d0f748c983bb795a86f47522313f701a08Sujith ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0) 97fb9987d0f748c983bb795a86f47522313f701a08Sujith 98fb9987d0f748c983bb795a86f47522313f701a08Sujith#define RATE(_bitrate, _hw_rate, _flags) { \ 99fb9987d0f748c983bb795a86f47522313f701a08Sujith .bitrate = (_bitrate), \ 100fb9987d0f748c983bb795a86f47522313f701a08Sujith .flags = (_flags), \ 101fb9987d0f748c983bb795a86f47522313f701a08Sujith .hw_value = (_hw_rate), \ 102fb9987d0f748c983bb795a86f47522313f701a08Sujith .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ 103fb9987d0f748c983bb795a86f47522313f701a08Sujith} 104fb9987d0f748c983bb795a86f47522313f701a08Sujith 105fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic struct ieee80211_rate ath9k_legacy_rates[] = { 106fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(10, 0x1b, 0), 107fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */ 108fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */ 109fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */ 110fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(60, 0x0b, 0), 111fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(90, 0x0f, 0), 112fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(120, 0x0a, 0), 113fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(180, 0x0e, 0), 114fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(240, 0x09, 0), 115fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(360, 0x0d, 0), 116fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(480, 0x08, 0), 117fb9987d0f748c983bb795a86f47522313f701a08Sujith RATE(540, 0x0c, 0), 118fb9987d0f748c983bb795a86f47522313f701a08Sujith}; 119fb9987d0f748c983bb795a86f47522313f701a08Sujith 120d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#ifdef CONFIG_MAC80211_LEDS 121d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharanstatic const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { 122d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 0 * 1024, .blink_time = 334 }, 123d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 1 * 1024, .blink_time = 260 }, 124d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 5 * 1024, .blink_time = 220 }, 125d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 10 * 1024, .blink_time = 190 }, 126d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 20 * 1024, .blink_time = 170 }, 127d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 50 * 1024, .blink_time = 150 }, 128d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 70 * 1024, .blink_time = 130 }, 129d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 100 * 1024, .blink_time = 110 }, 130d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 200 * 1024, .blink_time = 80 }, 131d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan { .throughput = 300 * 1024, .blink_time = 50 }, 132d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan}; 133d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#endif 134d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan 135fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) 136fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 137fb9987d0f748c983bb795a86f47522313f701a08Sujith int time_left; 138fb9987d0f748c983bb795a86f47522313f701a08Sujith 139d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com if (atomic_read(&priv->htc->tgt_ready) > 0) { 140d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 141d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com return 0; 142d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com } 143d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com 144fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Firmware can take up to 50ms to get ready, to be safe use 1 second */ 145fb9987d0f748c983bb795a86f47522313f701a08Sujith time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ); 146fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!time_left) { 147fb9987d0f748c983bb795a86f47522313f701a08Sujith dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n"); 148fb9987d0f748c983bb795a86f47522313f701a08Sujith return -ETIMEDOUT; 149fb9987d0f748c983bb795a86f47522313f701a08Sujith } 150fb9987d0f748c983bb795a86f47522313f701a08Sujith 151d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com atomic_dec(&priv->htc->tgt_ready); 152d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com 153fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 154fb9987d0f748c983bb795a86f47522313f701a08Sujith} 155fb9987d0f748c983bb795a86f47522313f701a08Sujith 156fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_deinit_priv(struct ath9k_htc_priv *priv) 157fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 158fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_hw_deinit(priv->ah); 159fb9987d0f748c983bb795a86f47522313f701a08Sujith kfree(priv->ah); 160fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->ah = NULL; 161fb9987d0f748c983bb795a86f47522313f701a08Sujith} 162fb9987d0f748c983bb795a86f47522313f701a08Sujith 163fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_deinit_device(struct ath9k_htc_priv *priv) 164fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 165fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_hw *hw = priv->hw; 166fb9987d0f748c983bb795a86f47522313f701a08Sujith 167fb9987d0f748c983bb795a86f47522313f701a08Sujith wiphy_rfkill_stop_polling(hw->wiphy); 168fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_leds(priv); 169fb9987d0f748c983bb795a86f47522313f701a08Sujith ieee80211_unregister_hw(hw); 170fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_rx_cleanup(priv); 171fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_tx_cleanup(priv); 172fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_priv(priv); 173fb9987d0f748c983bb795a86f47522313f701a08Sujith} 174fb9987d0f748c983bb795a86f47522313f701a08Sujith 175fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, 176fb9987d0f748c983bb795a86f47522313f701a08Sujith u16 service_id, 177fb9987d0f748c983bb795a86f47522313f701a08Sujith void (*tx) (void *, 178fb9987d0f748c983bb795a86f47522313f701a08Sujith struct sk_buff *, 179fb9987d0f748c983bb795a86f47522313f701a08Sujith enum htc_endpoint_id, 180fb9987d0f748c983bb795a86f47522313f701a08Sujith bool txok), 181fb9987d0f748c983bb795a86f47522313f701a08Sujith enum htc_endpoint_id *ep_id) 182fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 183fb9987d0f748c983bb795a86f47522313f701a08Sujith struct htc_service_connreq req; 184fb9987d0f748c983bb795a86f47522313f701a08Sujith 185fb9987d0f748c983bb795a86f47522313f701a08Sujith memset(&req, 0, sizeof(struct htc_service_connreq)); 186fb9987d0f748c983bb795a86f47522313f701a08Sujith 187fb9987d0f748c983bb795a86f47522313f701a08Sujith req.service_id = service_id; 188fb9987d0f748c983bb795a86f47522313f701a08Sujith req.ep_callbacks.priv = priv; 189fb9987d0f748c983bb795a86f47522313f701a08Sujith req.ep_callbacks.rx = ath9k_htc_rxep; 190fb9987d0f748c983bb795a86f47522313f701a08Sujith req.ep_callbacks.tx = tx; 191fb9987d0f748c983bb795a86f47522313f701a08Sujith 192fb9987d0f748c983bb795a86f47522313f701a08Sujith return htc_connect_service(priv->htc, &req, ep_id); 193fb9987d0f748c983bb795a86f47522313f701a08Sujith} 194fb9987d0f748c983bb795a86f47522313f701a08Sujith 195fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharanstatic int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, 196fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan u32 drv_info) 197fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 198fb9987d0f748c983bb795a86f47522313f701a08Sujith int ret; 199fb9987d0f748c983bb795a86f47522313f701a08Sujith 200fb9987d0f748c983bb795a86f47522313f701a08Sujith /* WMI CMD*/ 201fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep); 202fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 203fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 204fb9987d0f748c983bb795a86f47522313f701a08Sujith 205fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Beacon */ 2069c6dda4e2dfea970a7105e3805f0195bc3079f2fSujith ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep, 207fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->beacon_ep); 208fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 209fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 210fb9987d0f748c983bb795a86f47522313f701a08Sujith 211fb9987d0f748c983bb795a86f47522313f701a08Sujith /* CAB */ 212fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep, 213fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->cab_ep); 214fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 215fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 216fb9987d0f748c983bb795a86f47522313f701a08Sujith 217fb9987d0f748c983bb795a86f47522313f701a08Sujith 218fb9987d0f748c983bb795a86f47522313f701a08Sujith /* UAPSD */ 219fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep, 220fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->uapsd_ep); 221fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 222fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 223fb9987d0f748c983bb795a86f47522313f701a08Sujith 224fb9987d0f748c983bb795a86f47522313f701a08Sujith /* MGMT */ 225fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep, 226fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->mgmt_ep); 227fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 228fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 229fb9987d0f748c983bb795a86f47522313f701a08Sujith 230fb9987d0f748c983bb795a86f47522313f701a08Sujith /* DATA BE */ 231fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep, 232fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->data_be_ep); 233fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 234fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 235fb9987d0f748c983bb795a86f47522313f701a08Sujith 236fb9987d0f748c983bb795a86f47522313f701a08Sujith /* DATA BK */ 237fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep, 238fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->data_bk_ep); 239fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 240fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 241fb9987d0f748c983bb795a86f47522313f701a08Sujith 242fb9987d0f748c983bb795a86f47522313f701a08Sujith /* DATA VI */ 243fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep, 244fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->data_vi_ep); 245fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 246fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 247fb9987d0f748c983bb795a86f47522313f701a08Sujith 248fb9987d0f748c983bb795a86f47522313f701a08Sujith /* DATA VO */ 249fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep, 250fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->data_vo_ep); 251fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 252fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 253fb9987d0f748c983bb795a86f47522313f701a08Sujith 2546267dc709c6ef1c0926e18ff2859238992dea658Sujith /* 2556267dc709c6ef1c0926e18ff2859238992dea658Sujith * Setup required credits before initializing HTC. 2566267dc709c6ef1c0926e18ff2859238992dea658Sujith * This is a bit hacky, but, since queuing is done in 2576267dc709c6ef1c0926e18ff2859238992dea658Sujith * the HIF layer, shouldn't matter much. 2586267dc709c6ef1c0926e18ff2859238992dea658Sujith */ 2596267dc709c6ef1c0926e18ff2859238992dea658Sujith 2600b5ead91cda63e0db964dadc77601233434f60cbSujith Manoharan if (IS_AR7010_DEVICE(drv_info)) 261d108e8b9320b77e3fa165757fd40f298bdd89d1cSujith Manoharan priv->htc->credits = 45; 262fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan else 2634e63f768c3b85ae2b3ea6251231fd5cc46ec598dSujith priv->htc->credits = 33; 2646267dc709c6ef1c0926e18ff2859238992dea658Sujith 265fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = htc_init(priv->htc); 266fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 267fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 268fb9987d0f748c983bb795a86f47522313f701a08Sujith 2696267dc709c6ef1c0926e18ff2859238992dea658Sujith dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n", 2706267dc709c6ef1c0926e18ff2859238992dea658Sujith priv->htc->credits); 2716267dc709c6ef1c0926e18ff2859238992dea658Sujith 272fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 273fb9987d0f748c983bb795a86f47522313f701a08Sujith 274fb9987d0f748c983bb795a86f47522313f701a08Sujitherr: 275fb9987d0f748c983bb795a86f47522313f701a08Sujith dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n"); 276fb9987d0f748c983bb795a86f47522313f701a08Sujith return ret; 277fb9987d0f748c983bb795a86f47522313f701a08Sujith} 278fb9987d0f748c983bb795a86f47522313f701a08Sujith 279fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_reg_notifier(struct wiphy *wiphy, 280fb9987d0f748c983bb795a86f47522313f701a08Sujith struct regulatory_request *request) 281fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 282fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); 283fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath9k_htc_priv *priv = hw->priv; 284fb9987d0f748c983bb795a86f47522313f701a08Sujith 285fb9987d0f748c983bb795a86f47522313f701a08Sujith return ath_reg_notifier_apply(wiphy, request, 286fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_hw_regulatory(priv->ah)); 287fb9987d0f748c983bb795a86f47522313f701a08Sujith} 288fb9987d0f748c983bb795a86f47522313f701a08Sujith 2894a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) 290fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 291fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 292fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common = ath9k_hw_common(ah); 293fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 294fb9987d0f748c983bb795a86f47522313f701a08Sujith __be32 val, reg = cpu_to_be32(reg_offset); 295fb9987d0f748c983bb795a86f47522313f701a08Sujith int r; 296fb9987d0f748c983bb795a86f47522313f701a08Sujith 297fb9987d0f748c983bb795a86f47522313f701a08Sujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, 298fb9987d0f748c983bb795a86f47522313f701a08Sujith (u8 *) ®, sizeof(reg), 299fb9987d0f748c983bb795a86f47522313f701a08Sujith (u8 *) &val, sizeof(val), 300fb9987d0f748c983bb795a86f47522313f701a08Sujith 100); 301fb9987d0f748c983bb795a86f47522313f701a08Sujith if (unlikely(r)) { 302226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches ath_dbg(common, ATH_DBG_WMI, 303226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "REGISTER READ FAILED: (0x%04x, %d)\n", 304226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches reg_offset, r); 305fb9987d0f748c983bb795a86f47522313f701a08Sujith return -EIO; 306fb9987d0f748c983bb795a86f47522313f701a08Sujith } 307fb9987d0f748c983bb795a86f47522313f701a08Sujith 308fb9987d0f748c983bb795a86f47522313f701a08Sujith return be32_to_cpu(val); 309fb9987d0f748c983bb795a86f47522313f701a08Sujith} 310fb9987d0f748c983bb795a86f47522313f701a08Sujith 31109a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharanstatic void ath9k_multi_regread(void *hw_priv, u32 *addr, 31209a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan u32 *val, u16 count) 31309a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan{ 31409a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan struct ath_hw *ah = (struct ath_hw *) hw_priv; 31509a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 31609a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 31709a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan __be32 tmpaddr[8]; 31809a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan __be32 tmpval[8]; 31909a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan int i, ret; 32009a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan 32109a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan for (i = 0; i < count; i++) { 32209a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan tmpaddr[i] = cpu_to_be32(addr[i]); 32309a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan } 32409a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan 32509a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, 32609a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan (u8 *)tmpaddr , sizeof(u32) * count, 32709a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan (u8 *)tmpval, sizeof(u32) * count, 32809a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan 100); 32909a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan if (unlikely(ret)) { 33009a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan ath_dbg(common, ATH_DBG_WMI, 33109a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan "Multiple REGISTER READ FAILED (count: %d)\n", count); 33209a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan } 33309a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan 33409a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan for (i = 0; i < count; i++) { 33509a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan val[i] = be32_to_cpu(tmpval[i]); 33609a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan } 33709a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan} 33809a525d33870e8a16076ec0200cc5002f6bef35dSujith Manoharan 3394a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) 340fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 341fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 342fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common = ath9k_hw_common(ah); 343fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 34407b2fa5a2368accf0fe6cb16e7eca6d1150554edJoe Perches const __be32 buf[2] = { 345fb9987d0f748c983bb795a86f47522313f701a08Sujith cpu_to_be32(reg_offset), 346fb9987d0f748c983bb795a86f47522313f701a08Sujith cpu_to_be32(val), 347fb9987d0f748c983bb795a86f47522313f701a08Sujith }; 348fb9987d0f748c983bb795a86f47522313f701a08Sujith int r; 349fb9987d0f748c983bb795a86f47522313f701a08Sujith 350fb9987d0f748c983bb795a86f47522313f701a08Sujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 351fb9987d0f748c983bb795a86f47522313f701a08Sujith (u8 *) &buf, sizeof(buf), 352fb9987d0f748c983bb795a86f47522313f701a08Sujith (u8 *) &val, sizeof(val), 353fb9987d0f748c983bb795a86f47522313f701a08Sujith 100); 354fb9987d0f748c983bb795a86f47522313f701a08Sujith if (unlikely(r)) { 355226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches ath_dbg(common, ATH_DBG_WMI, 356226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "REGISTER WRITE FAILED:(0x%04x, %d)\n", 357226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches reg_offset, r); 358fb9987d0f748c983bb795a86f47522313f701a08Sujith } 359fb9987d0f748c983bb795a86f47522313f701a08Sujith} 360fb9987d0f748c983bb795a86f47522313f701a08Sujith 3614a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) 3624a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{ 3634a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 3644a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_common *common = ath9k_hw_common(ah); 3654a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 3664a22fe108e62367c10c3abeb469d6972ba3299f5Sujith u32 rsp_status; 3674a22fe108e62367c10c3abeb469d6972ba3299f5Sujith int r; 3684a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3694a22fe108e62367c10c3abeb469d6972ba3299f5Sujith mutex_lock(&priv->wmi->multi_write_mutex); 3704a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3714a22fe108e62367c10c3abeb469d6972ba3299f5Sujith /* Store the register/value */ 3724a22fe108e62367c10c3abeb469d6972ba3299f5Sujith priv->wmi->multi_write[priv->wmi->multi_write_idx].reg = 3734a22fe108e62367c10c3abeb469d6972ba3299f5Sujith cpu_to_be32(reg_offset); 3744a22fe108e62367c10c3abeb469d6972ba3299f5Sujith priv->wmi->multi_write[priv->wmi->multi_write_idx].val = 3754a22fe108e62367c10c3abeb469d6972ba3299f5Sujith cpu_to_be32(val); 3764a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3774a22fe108e62367c10c3abeb469d6972ba3299f5Sujith priv->wmi->multi_write_idx++; 3784a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3794a22fe108e62367c10c3abeb469d6972ba3299f5Sujith /* If the buffer is full, send it out. */ 3804a22fe108e62367c10c3abeb469d6972ba3299f5Sujith if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) { 3814a22fe108e62367c10c3abeb469d6972ba3299f5Sujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 3824a22fe108e62367c10c3abeb469d6972ba3299f5Sujith (u8 *) &priv->wmi->multi_write, 3834a22fe108e62367c10c3abeb469d6972ba3299f5Sujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 3844a22fe108e62367c10c3abeb469d6972ba3299f5Sujith (u8 *) &rsp_status, sizeof(rsp_status), 3854a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 100); 3864a22fe108e62367c10c3abeb469d6972ba3299f5Sujith if (unlikely(r)) { 387226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches ath_dbg(common, ATH_DBG_WMI, 388226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "REGISTER WRITE FAILED, multi len: %d\n", 389226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches priv->wmi->multi_write_idx); 3904a22fe108e62367c10c3abeb469d6972ba3299f5Sujith } 3914a22fe108e62367c10c3abeb469d6972ba3299f5Sujith priv->wmi->multi_write_idx = 0; 3924a22fe108e62367c10c3abeb469d6972ba3299f5Sujith } 3934a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3944a22fe108e62367c10c3abeb469d6972ba3299f5Sujith mutex_unlock(&priv->wmi->multi_write_mutex); 3954a22fe108e62367c10c3abeb469d6972ba3299f5Sujith} 3964a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 3974a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset) 3984a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{ 3994a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 4004a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_common *common = ath9k_hw_common(ah); 4014a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 4024a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4034a22fe108e62367c10c3abeb469d6972ba3299f5Sujith if (atomic_read(&priv->wmi->mwrite_cnt)) 4044a22fe108e62367c10c3abeb469d6972ba3299f5Sujith ath9k_regwrite_buffer(hw_priv, val, reg_offset); 4054a22fe108e62367c10c3abeb469d6972ba3299f5Sujith else 4064a22fe108e62367c10c3abeb469d6972ba3299f5Sujith ath9k_regwrite_single(hw_priv, val, reg_offset); 4074a22fe108e62367c10c3abeb469d6972ba3299f5Sujith} 4084a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4094a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_enable_regwrite_buffer(void *hw_priv) 4104a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{ 4114a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 4124a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_common *common = ath9k_hw_common(ah); 4134a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 4144a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4154a22fe108e62367c10c3abeb469d6972ba3299f5Sujith atomic_inc(&priv->wmi->mwrite_cnt); 4164a22fe108e62367c10c3abeb469d6972ba3299f5Sujith} 4174a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4184a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_flush(void *hw_priv) 4194a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{ 4204a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_hw *ah = (struct ath_hw *) hw_priv; 4214a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath_common *common = ath9k_hw_common(ah); 4224a22fe108e62367c10c3abeb469d6972ba3299f5Sujith struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; 4234a22fe108e62367c10c3abeb469d6972ba3299f5Sujith u32 rsp_status; 4244a22fe108e62367c10c3abeb469d6972ba3299f5Sujith int r; 4254a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 426435c1610f46dc4d86a6633adb037b18109e6ffdcFelix Fietkau atomic_dec(&priv->wmi->mwrite_cnt); 427435c1610f46dc4d86a6633adb037b18109e6ffdcFelix Fietkau 4284a22fe108e62367c10c3abeb469d6972ba3299f5Sujith mutex_lock(&priv->wmi->multi_write_mutex); 4294a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4304a22fe108e62367c10c3abeb469d6972ba3299f5Sujith if (priv->wmi->multi_write_idx) { 4314a22fe108e62367c10c3abeb469d6972ba3299f5Sujith r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, 4324a22fe108e62367c10c3abeb469d6972ba3299f5Sujith (u8 *) &priv->wmi->multi_write, 4334a22fe108e62367c10c3abeb469d6972ba3299f5Sujith sizeof(struct register_write) * priv->wmi->multi_write_idx, 4344a22fe108e62367c10c3abeb469d6972ba3299f5Sujith (u8 *) &rsp_status, sizeof(rsp_status), 4354a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 100); 4364a22fe108e62367c10c3abeb469d6972ba3299f5Sujith if (unlikely(r)) { 437226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches ath_dbg(common, ATH_DBG_WMI, 438226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "REGISTER WRITE FAILED, multi len: %d\n", 439226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches priv->wmi->multi_write_idx); 4404a22fe108e62367c10c3abeb469d6972ba3299f5Sujith } 4414a22fe108e62367c10c3abeb469d6972ba3299f5Sujith priv->wmi->multi_write_idx = 0; 4424a22fe108e62367c10c3abeb469d6972ba3299f5Sujith } 4434a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 4444a22fe108e62367c10c3abeb469d6972ba3299f5Sujith mutex_unlock(&priv->wmi->multi_write_mutex); 4454a22fe108e62367c10c3abeb469d6972ba3299f5Sujith} 4464a22fe108e62367c10c3abeb469d6972ba3299f5Sujith 447845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkaustatic u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) 448845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau{ 449845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau u32 val; 450845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau 451845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau val = ath9k_regread(hw_priv, reg_offset); 452845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau val &= ~clr; 453845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau val |= set; 454845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau ath9k_regwrite(hw_priv, val, reg_offset); 455845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau return val; 456845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau} 457845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau 458fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath_usb_read_cachesize(struct ath_common *common, int *csz) 459fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 460fb9987d0f748c983bb795a86f47522313f701a08Sujith *csz = L1_CACHE_BYTES >> 2; 461fb9987d0f748c983bb795a86f47522313f701a08Sujith} 462fb9987d0f748c983bb795a86f47522313f701a08Sujith 463fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) 464fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 465fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_hw *ah = (struct ath_hw *) common->ah; 466fb9987d0f748c983bb795a86f47522313f701a08Sujith 467fb9987d0f748c983bb795a86f47522313f701a08Sujith (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); 468fb9987d0f748c983bb795a86f47522313f701a08Sujith 469fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!ath9k_hw_wait(ah, 470fb9987d0f748c983bb795a86f47522313f701a08Sujith AR_EEPROM_STATUS_DATA, 471fb9987d0f748c983bb795a86f47522313f701a08Sujith AR_EEPROM_STATUS_DATA_BUSY | 472fb9987d0f748c983bb795a86f47522313f701a08Sujith AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, 473fb9987d0f748c983bb795a86f47522313f701a08Sujith AH_WAIT_TIMEOUT)) 474fb9987d0f748c983bb795a86f47522313f701a08Sujith return false; 475fb9987d0f748c983bb795a86f47522313f701a08Sujith 476fb9987d0f748c983bb795a86f47522313f701a08Sujith *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), 477fb9987d0f748c983bb795a86f47522313f701a08Sujith AR_EEPROM_STATUS_DATA_VAL); 478fb9987d0f748c983bb795a86f47522313f701a08Sujith 479fb9987d0f748c983bb795a86f47522313f701a08Sujith return true; 480fb9987d0f748c983bb795a86f47522313f701a08Sujith} 481fb9987d0f748c983bb795a86f47522313f701a08Sujith 482fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic const struct ath_bus_ops ath9k_usb_bus_ops = { 483497ad9adf44013dc9054f80c627acc44d4c90d37Sujith .ath_bus_type = ATH_USB, 484fb9987d0f748c983bb795a86f47522313f701a08Sujith .read_cachesize = ath_usb_read_cachesize, 485fb9987d0f748c983bb795a86f47522313f701a08Sujith .eeprom_read = ath_usb_eeprom_read, 486fb9987d0f748c983bb795a86f47522313f701a08Sujith}; 487fb9987d0f748c983bb795a86f47522313f701a08Sujith 488fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void setup_ht_cap(struct ath9k_htc_priv *priv, 489fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_sta_ht_cap *ht_info) 490fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 4916debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith struct ath_common *common = ath9k_hw_common(priv->ah); 4926debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith u8 tx_streams, rx_streams; 4936debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith int i; 4946debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 495fb9987d0f748c983bb795a86f47522313f701a08Sujith ht_info->ht_supported = true; 496fb9987d0f748c983bb795a86f47522313f701a08Sujith ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 497fb9987d0f748c983bb795a86f47522313f701a08Sujith IEEE80211_HT_CAP_SM_PS | 498fb9987d0f748c983bb795a86f47522313f701a08Sujith IEEE80211_HT_CAP_SGI_40 | 499fb9987d0f748c983bb795a86f47522313f701a08Sujith IEEE80211_HT_CAP_DSSSCCK40; 500fb9987d0f748c983bb795a86f47522313f701a08Sujith 501b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) 502b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith ht_info->cap |= IEEE80211_HT_CAP_SGI_20; 503b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith 50417525f96aeeed156bd4a6dee21816100f77b0c71Sujith ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); 50517525f96aeeed156bd4a6dee21816100f77b0c71Sujith 506fb9987d0f748c983bb795a86f47522313f701a08Sujith ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 507fb9987d0f748c983bb795a86f47522313f701a08Sujith ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 508fb9987d0f748c983bb795a86f47522313f701a08Sujith 509fb9987d0f748c983bb795a86f47522313f701a08Sujith memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 5106debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 5116debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith /* ath9k_htc supports only 1 or 2 stream devices */ 5126debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); 5136debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); 5146debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 515226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches ath_dbg(common, ATH_DBG_CONFIG, 516226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches "TX streams %d, RX streams: %d\n", 517226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches tx_streams, rx_streams); 5186debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 5196debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith if (tx_streams != rx_streams) { 5206debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 5216debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith ht_info->mcs.tx_params |= ((tx_streams - 1) << 5226debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 5236debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith } 5246debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 5256debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith for (i = 0; i < rx_streams; i++) 5266debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith ht_info->mcs.rx_mask[i] = 0xff; 5276debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith 528fb9987d0f748c983bb795a86f47522313f701a08Sujith ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 529fb9987d0f748c983bb795a86f47522313f701a08Sujith} 530fb9987d0f748c983bb795a86f47522313f701a08Sujith 531fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_init_queues(struct ath9k_htc_priv *priv) 532fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 533fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common = ath9k_hw_common(priv->ah); 534fb9987d0f748c983bb795a86f47522313f701a08Sujith int i; 535fb9987d0f748c983bb795a86f47522313f701a08Sujith 536fb9987d0f748c983bb795a86f47522313f701a08Sujith for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++) 537fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->hwq_map[i] = -1; 538fb9987d0f748c983bb795a86f47522313f701a08Sujith 539ca74b83b66dbd289a395c6243695d746c76676ccSujith priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); 540ca74b83b66dbd289a395c6243695d746c76676ccSujith if (priv->beaconq == -1) { 5413800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup BEACON xmit queue\n"); 542ca74b83b66dbd289a395c6243695d746c76676ccSujith goto err; 543ca74b83b66dbd289a395c6243695d746c76676ccSujith } 544ca74b83b66dbd289a395c6243695d746c76676ccSujith 545ca74b83b66dbd289a395c6243695d746c76676ccSujith priv->cabq = ath9k_htc_cabq_setup(priv); 546ca74b83b66dbd289a395c6243695d746c76676ccSujith if (priv->cabq == -1) { 5473800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup CAB xmit queue\n"); 548ca74b83b66dbd289a395c6243695d746c76676ccSujith goto err; 549ca74b83b66dbd289a395c6243695d746c76676ccSujith } 550ca74b83b66dbd289a395c6243695d746c76676ccSujith 551e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { 5523800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup xmit queue for BE traffic\n"); 553fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 554fb9987d0f748c983bb795a86f47522313f701a08Sujith } 555fb9987d0f748c983bb795a86f47522313f701a08Sujith 556e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { 5573800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup xmit queue for BK traffic\n"); 558fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 559fb9987d0f748c983bb795a86f47522313f701a08Sujith } 560e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { 5613800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup xmit queue for VI traffic\n"); 562fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 563fb9987d0f748c983bb795a86f47522313f701a08Sujith } 564e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { 5653800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, "Unable to setup xmit queue for VO traffic\n"); 566fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err; 567fb9987d0f748c983bb795a86f47522313f701a08Sujith } 568fb9987d0f748c983bb795a86f47522313f701a08Sujith 569fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 570fb9987d0f748c983bb795a86f47522313f701a08Sujith 571fb9987d0f748c983bb795a86f47522313f701a08Sujitherr: 572fb9987d0f748c983bb795a86f47522313f701a08Sujith return -EINVAL; 573fb9987d0f748c983bb795a86f47522313f701a08Sujith} 574fb9987d0f748c983bb795a86f47522313f701a08Sujith 575fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) 576fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 577d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { 578fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->sbands[IEEE80211_BAND_2GHZ].channels = 579fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_2ghz_channels; 580fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; 581fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->sbands[IEEE80211_BAND_2GHZ].n_channels = 582fb9987d0f748c983bb795a86f47522313f701a08Sujith ARRAY_SIZE(ath9k_2ghz_channels); 583fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; 584fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates = 585fb9987d0f748c983bb795a86f47522313f701a08Sujith ARRAY_SIZE(ath9k_legacy_rates); 586fb9987d0f748c983bb795a86f47522313f701a08Sujith } 587ea46e644e80bd4ac778964afd998df4f666486d4Sujith 588d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { 589ea46e644e80bd4ac778964afd998df4f666486d4Sujith priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; 590ea46e644e80bd4ac778964afd998df4f666486d4Sujith priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; 591ea46e644e80bd4ac778964afd998df4f666486d4Sujith priv->sbands[IEEE80211_BAND_5GHZ].n_channels = 592ea46e644e80bd4ac778964afd998df4f666486d4Sujith ARRAY_SIZE(ath9k_5ghz_channels); 593ea46e644e80bd4ac778964afd998df4f666486d4Sujith priv->sbands[IEEE80211_BAND_5GHZ].bitrates = 594ea46e644e80bd4ac778964afd998df4f666486d4Sujith ath9k_legacy_rates + 4; 595ea46e644e80bd4ac778964afd998df4f666486d4Sujith priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates = 596ea46e644e80bd4ac778964afd998df4f666486d4Sujith ARRAY_SIZE(ath9k_legacy_rates) - 4; 597ea46e644e80bd4ac778964afd998df4f666486d4Sujith } 598fb9987d0f748c983bb795a86f47522313f701a08Sujith} 599fb9987d0f748c983bb795a86f47522313f701a08Sujith 600fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_init_misc(struct ath9k_htc_priv *priv) 601fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 602fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common = ath9k_hw_common(priv->ah); 603fb9987d0f748c983bb795a86f47522313f701a08Sujith 604fb9987d0f748c983bb795a86f47522313f701a08Sujith common->tx_chainmask = priv->ah->caps.tx_chainmask; 605fb9987d0f748c983bb795a86f47522313f701a08Sujith common->rx_chainmask = priv->ah->caps.rx_chainmask; 606fb9987d0f748c983bb795a86f47522313f701a08Sujith 607364734fafbba0c3133e482db78149b9a823ae7a5Felix Fietkau memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); 608fb9987d0f748c983bb795a86f47522313f701a08Sujith 6099f01a84e81d10e38daa504348217895fe414a24bSujith priv->ah->opmode = NL80211_IFTYPE_STATION; 610fb9987d0f748c983bb795a86f47522313f701a08Sujith} 611fb9987d0f748c983bb795a86f47522313f701a08Sujith 61221cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic void ath9k_init_btcoex(struct ath9k_htc_priv *priv) 61321cb987914cb5334af78378141efed77505ea987Vivek Natarajan{ 61421cb987914cb5334af78378141efed77505ea987Vivek Natarajan int qnum; 61521cb987914cb5334af78378141efed77505ea987Vivek Natarajan 61621cb987914cb5334af78378141efed77505ea987Vivek Natarajan switch (priv->ah->btcoex_hw.scheme) { 61721cb987914cb5334af78378141efed77505ea987Vivek Natarajan case ATH_BTCOEX_CFG_NONE: 61821cb987914cb5334af78378141efed77505ea987Vivek Natarajan break; 61921cb987914cb5334af78378141efed77505ea987Vivek Natarajan case ATH_BTCOEX_CFG_3WIRE: 62021cb987914cb5334af78378141efed77505ea987Vivek Natarajan priv->ah->btcoex_hw.btactive_gpio = 7; 62121cb987914cb5334af78378141efed77505ea987Vivek Natarajan priv->ah->btcoex_hw.btpriority_gpio = 6; 62221cb987914cb5334af78378141efed77505ea987Vivek Natarajan priv->ah->btcoex_hw.wlanactive_gpio = 8; 62321cb987914cb5334af78378141efed77505ea987Vivek Natarajan priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 62421cb987914cb5334af78378141efed77505ea987Vivek Natarajan ath9k_hw_btcoex_init_3wire(priv->ah); 62521cb987914cb5334af78378141efed77505ea987Vivek Natarajan ath_htc_init_btcoex_work(priv); 62621cb987914cb5334af78378141efed77505ea987Vivek Natarajan qnum = priv->hwq_map[WME_AC_BE]; 62721cb987914cb5334af78378141efed77505ea987Vivek Natarajan ath9k_hw_init_btcoex_hw(priv->ah, qnum); 62821cb987914cb5334af78378141efed77505ea987Vivek Natarajan break; 62921cb987914cb5334af78378141efed77505ea987Vivek Natarajan default: 63021cb987914cb5334af78378141efed77505ea987Vivek Natarajan WARN_ON(1); 63121cb987914cb5334af78378141efed77505ea987Vivek Natarajan break; 63221cb987914cb5334af78378141efed77505ea987Vivek Natarajan } 63321cb987914cb5334af78378141efed77505ea987Vivek Natarajan} 63421cb987914cb5334af78378141efed77505ea987Vivek Natarajan 63521cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic int ath9k_init_priv(struct ath9k_htc_priv *priv, 636fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan u16 devid, char *product, 637fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan u32 drv_info) 638fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 639fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_hw *ah = NULL; 640fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common; 641832f6a18fc2aead14954c081ece03b7a5b425f81Sujith Manoharan int i, ret = 0, csz = 0; 642fb9987d0f748c983bb795a86f47522313f701a08Sujith 643fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->op_flags |= OP_INVALID; 644fb9987d0f748c983bb795a86f47522313f701a08Sujith 645fb9987d0f748c983bb795a86f47522313f701a08Sujith ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); 646fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!ah) 647fb9987d0f748c983bb795a86f47522313f701a08Sujith return -ENOMEM; 648fb9987d0f748c983bb795a86f47522313f701a08Sujith 649fb9987d0f748c983bb795a86f47522313f701a08Sujith ah->hw_version.devid = devid; 6500b5ead91cda63e0db964dadc77601233434f60cbSujith Manoharan ah->hw_version.usbdev = drv_info; 651f8afa42b01c7a9f45b7cbaadb0481a0eeb96f18dFelix Fietkau ah->ah_flags |= AH_USE_EEPROM; 652f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau ah->reg_ops.read = ath9k_regread; 653f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau ah->reg_ops.multi_read = ath9k_multi_regread; 654f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau ah->reg_ops.write = ath9k_regwrite; 655f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; 656f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau ah->reg_ops.write_flush = ath9k_regwrite_flush; 657845e03c93dda2c00ffb5c68a1f7c8efc412d7c1aFelix Fietkau ah->reg_ops.rmw = ath9k_reg_rmw; 658fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->ah = ah; 659fb9987d0f748c983bb795a86f47522313f701a08Sujith 660fb9987d0f748c983bb795a86f47522313f701a08Sujith common = ath9k_hw_common(ah); 661f9f84e96f6d642aa7b337c22cbb7d6f936039fdaFelix Fietkau common->ops = &ah->reg_ops; 662fb9987d0f748c983bb795a86f47522313f701a08Sujith common->bus_ops = &ath9k_usb_bus_ops; 663fb9987d0f748c983bb795a86f47522313f701a08Sujith common->ah = ah; 664fb9987d0f748c983bb795a86f47522313f701a08Sujith common->hw = priv->hw; 665fb9987d0f748c983bb795a86f47522313f701a08Sujith common->priv = priv; 666fb9987d0f748c983bb795a86f47522313f701a08Sujith common->debug_mask = ath9k_debug; 667fb9987d0f748c983bb795a86f47522313f701a08Sujith 668fb9987d0f748c983bb795a86f47522313f701a08Sujith spin_lock_init(&priv->beacon_lock); 669658ef04fd42a587b17a379ad9208023473442dddSujith Manoharan spin_lock_init(&priv->tx.tx_lock); 670fb9987d0f748c983bb795a86f47522313f701a08Sujith mutex_init(&priv->mutex); 671bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan mutex_init(&priv->htc_pm_lock); 672fb9987d0f748c983bb795a86f47522313f701a08Sujith tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, 673fb9987d0f748c983bb795a86f47522313f701a08Sujith (unsigned long)priv); 67427876a29de221186c9d5883e5fe5f6da18ef9a45Sujith Manoharan tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet, 67573908674c6957082e8ab57daed57d2bb97a1ebbaSujith Manoharan (unsigned long)priv); 676a236254c35f04a4d47c701ed3ec4a0b5dcb097b0Sujith Manoharan INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); 677bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan INIT_WORK(&priv->ps_work, ath9k_ps_work); 67873908674c6957082e8ab57daed57d2bb97a1ebbaSujith Manoharan INIT_WORK(&priv->fatal_work, ath9k_fatal_work); 679859c3ca1e4608615788dc6cbc199210fe4b5efa2Sujith Manoharan setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, 680859c3ca1e4608615788dc6cbc199210fe4b5efa2Sujith Manoharan (unsigned long)priv); 681fb9987d0f748c983bb795a86f47522313f701a08Sujith 682fb9987d0f748c983bb795a86f47522313f701a08Sujith /* 683fb9987d0f748c983bb795a86f47522313f701a08Sujith * Cache line size is used to size and align various 684fb9987d0f748c983bb795a86f47522313f701a08Sujith * structures used to communicate with the hardware. 685fb9987d0f748c983bb795a86f47522313f701a08Sujith */ 686fb9987d0f748c983bb795a86f47522313f701a08Sujith ath_read_cachesize(common, &csz); 687fb9987d0f748c983bb795a86f47522313f701a08Sujith common->cachelsz = csz << 2; /* convert to bytes */ 688fb9987d0f748c983bb795a86f47522313f701a08Sujith 689fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_hw_init(ah); 690fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) { 6913800276a40751539a920ef8e0537ef2e19126799Joe Perches ath_err(common, 6923800276a40751539a920ef8e0537ef2e19126799Joe Perches "Unable to initialize hardware; initialization status: %d\n", 6933800276a40751539a920ef8e0537ef2e19126799Joe Perches ret); 694fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_hw; 695fb9987d0f748c983bb795a86f47522313f701a08Sujith } 696fb9987d0f748c983bb795a86f47522313f701a08Sujith 697fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_init_queues(priv); 698fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 699fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_queues; 700fb9987d0f748c983bb795a86f47522313f701a08Sujith 701832f6a18fc2aead14954c081ece03b7a5b425f81Sujith Manoharan for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) 702832f6a18fc2aead14954c081ece03b7a5b425f81Sujith Manoharan priv->cur_beacon_conf.bslot[i] = NULL; 703832f6a18fc2aead14954c081ece03b7a5b425f81Sujith Manoharan 704f82b4bde17aeb6c2f8bf0540ee44811de4651cf6Rajkumar Manoharan ath9k_cmn_init_crypto(ah); 705fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_init_channels_rates(priv); 706fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_init_misc(priv); 707fb9987d0f748c983bb795a86f47522313f701a08Sujith 70821cb987914cb5334af78378141efed77505ea987Vivek Natarajan if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { 70921cb987914cb5334af78378141efed77505ea987Vivek Natarajan ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; 71021cb987914cb5334af78378141efed77505ea987Vivek Natarajan ath9k_init_btcoex(priv); 71121cb987914cb5334af78378141efed77505ea987Vivek Natarajan } 71221cb987914cb5334af78378141efed77505ea987Vivek Natarajan 713fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 714fb9987d0f748c983bb795a86f47522313f701a08Sujith 715fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_queues: 716fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_hw_deinit(ah); 717fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_hw: 718fb9987d0f748c983bb795a86f47522313f701a08Sujith 719fb9987d0f748c983bb795a86f47522313f701a08Sujith kfree(ah); 720fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->ah = NULL; 721fb9987d0f748c983bb795a86f47522313f701a08Sujith 722fb9987d0f748c983bb795a86f47522313f701a08Sujith return ret; 723fb9987d0f748c983bb795a86f47522313f701a08Sujith} 724fb9987d0f748c983bb795a86f47522313f701a08Sujith 725fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, 726fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_hw *hw) 727fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 728fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common = ath9k_hw_common(priv->ah); 729fb9987d0f748c983bb795a86f47522313f701a08Sujith 730fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->flags = IEEE80211_HW_SIGNAL_DBM | 731fb9987d0f748c983bb795a86f47522313f701a08Sujith IEEE80211_HW_AMPDU_AGGREGATION | 732fb9987d0f748c983bb795a86f47522313f701a08Sujith IEEE80211_HW_SPECTRUM_MGMT | 73332fbccafed7e935432b601f0453c2b702a385a25Sujith IEEE80211_HW_HAS_RATE_CONTROL | 734bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan IEEE80211_HW_RX_INCLUDES_FCS | 735bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan IEEE80211_HW_SUPPORTS_PS | 7367d547eb4bb664c5a6b7c8790c2ecb0aec5d15385Sujith Manoharan IEEE80211_HW_PS_NULLFUNC_STACK | 7378ae2e12f1534e647d4a816755e5a09c2de6f9fcaRajkumar Manoharan IEEE80211_HW_REPORTS_TX_ACK_STATUS | 7387d547eb4bb664c5a6b7c8790c2ecb0aec5d15385Sujith Manoharan IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; 739fb9987d0f748c983bb795a86f47522313f701a08Sujith 740fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->wiphy->interface_modes = 741fb9987d0f748c983bb795a86f47522313f701a08Sujith BIT(NL80211_IFTYPE_STATION) | 74209d5b94d2cbc6c3ebb70a9a318f6390d0b4cf010Sujith Manoharan BIT(NL80211_IFTYPE_ADHOC) | 74309d5b94d2cbc6c3ebb70a9a318f6390d0b4cf010Sujith Manoharan BIT(NL80211_IFTYPE_AP) | 74409d5b94d2cbc6c3ebb70a9a318f6390d0b4cf010Sujith Manoharan BIT(NL80211_IFTYPE_P2P_GO) | 74509d5b94d2cbc6c3ebb70a9a318f6390d0b4cf010Sujith Manoharan BIT(NL80211_IFTYPE_P2P_CLIENT); 746fb9987d0f748c983bb795a86f47522313f701a08Sujith 747bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 748bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan 749fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->queues = 4; 750fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->channel_change_time = 5000; 751fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->max_listen_interval = 10; 7523a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan 753fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->vif_data_size = sizeof(struct ath9k_htc_vif); 754fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->sta_data_size = sizeof(struct ath9k_htc_sta); 755fb9987d0f748c983bb795a86f47522313f701a08Sujith 756fb9987d0f748c983bb795a86f47522313f701a08Sujith /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */ 757fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + 758fb9987d0f748c983bb795a86f47522313f701a08Sujith sizeof(struct htc_frame_hdr) + 4; 759fb9987d0f748c983bb795a86f47522313f701a08Sujith 760d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) 761fb9987d0f748c983bb795a86f47522313f701a08Sujith hw->wiphy->bands[IEEE80211_BAND_2GHZ] = 762fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->sbands[IEEE80211_BAND_2GHZ]; 763d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) 764ea46e644e80bd4ac778964afd998df4f666486d4Sujith hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 765ea46e644e80bd4ac778964afd998df4f666486d4Sujith &priv->sbands[IEEE80211_BAND_5GHZ]; 766fb9987d0f748c983bb795a86f47522313f701a08Sujith 767fb9987d0f748c983bb795a86f47522313f701a08Sujith if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 768d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) 769fb9987d0f748c983bb795a86f47522313f701a08Sujith setup_ht_cap(priv, 770fb9987d0f748c983bb795a86f47522313f701a08Sujith &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); 771d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) 772ea46e644e80bd4ac778964afd998df4f666486d4Sujith setup_ht_cap(priv, 773ea46e644e80bd4ac778964afd998df4f666486d4Sujith &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); 774fb9987d0f748c983bb795a86f47522313f701a08Sujith } 775fb9987d0f748c983bb795a86f47522313f701a08Sujith 776fb9987d0f748c983bb795a86f47522313f701a08Sujith SET_IEEE80211_PERM_ADDR(hw, common->macaddr); 777fb9987d0f748c983bb795a86f47522313f701a08Sujith} 778fb9987d0f748c983bb795a86f47522313f701a08Sujith 77929bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharanstatic int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) 78029bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan{ 78129bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan struct ieee80211_hw *hw = priv->hw; 78229bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan struct wmi_fw_version cmd_rsp; 78329bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan int ret; 78429bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 78529bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan memset(&cmd_rsp, 0, sizeof(cmd_rsp)); 78629bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 78729bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan WMI_CMD(WMI_GET_FW_VERSION); 78829bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan if (ret) 78929bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan return -EINVAL; 79029bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 79129bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_major = be16_to_cpu(cmd_rsp.major); 79229bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); 79329bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 79429bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", 79529bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_major, 79629bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_minor); 79729bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 79829bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", 79929bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_major, 80029bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan priv->fw_version_minor); 80129bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 8023a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan /* 8033a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan * Check if the available FW matches the driver's 8043a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan * required version. 8053a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan */ 8063a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan if (priv->fw_version_major != MAJOR_VERSION_REQ || 8073a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan priv->fw_version_minor != MINOR_VERSION_REQ) { 8083a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", 8093a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan MAJOR_VERSION_REQ, MINOR_VERSION_REQ); 8103a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan return -EINVAL; 8113a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan } 8123a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan 81329bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan return 0; 81429bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan} 81529bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 81621cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic int ath9k_init_device(struct ath9k_htc_priv *priv, 817fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan u16 devid, char *product, u32 drv_info) 818fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 819fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_hw *hw = priv->hw; 820fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_common *common; 821fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_hw *ah; 822fb9987d0f748c983bb795a86f47522313f701a08Sujith int error = 0; 823fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath_regulatory *reg; 8243e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan char hw_name[64]; 825fb9987d0f748c983bb795a86f47522313f701a08Sujith 826fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Bring up device */ 827fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan error = ath9k_init_priv(priv, devid, product, drv_info); 828fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error != 0) 829fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_init; 830fb9987d0f748c983bb795a86f47522313f701a08Sujith 831fb9987d0f748c983bb795a86f47522313f701a08Sujith ah = priv->ah; 832fb9987d0f748c983bb795a86f47522313f701a08Sujith common = ath9k_hw_common(ah); 833fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_set_hw_capab(priv, hw); 834fb9987d0f748c983bb795a86f47522313f701a08Sujith 83529bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan error = ath9k_init_firmware_version(priv); 83629bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan if (error != 0) 83729bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan goto err_fw; 83829bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan 839fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Initialize regulatory */ 840fb9987d0f748c983bb795a86f47522313f701a08Sujith error = ath_regd_init(&common->regulatory, priv->hw->wiphy, 841fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_reg_notifier); 842fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error) 843fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_regd; 844fb9987d0f748c983bb795a86f47522313f701a08Sujith 845fb9987d0f748c983bb795a86f47522313f701a08Sujith reg = &common->regulatory; 846fb9987d0f748c983bb795a86f47522313f701a08Sujith 847fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Setup TX */ 848fb9987d0f748c983bb795a86f47522313f701a08Sujith error = ath9k_tx_init(priv); 849fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error != 0) 850fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_tx; 851fb9987d0f748c983bb795a86f47522313f701a08Sujith 852fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Setup RX */ 853fb9987d0f748c983bb795a86f47522313f701a08Sujith error = ath9k_rx_init(priv); 854fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error != 0) 855fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_rx; 856fb9987d0f748c983bb795a86f47522313f701a08Sujith 857d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#ifdef CONFIG_MAC80211_LEDS 858d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan /* must be initialized before ieee80211_register_hw */ 859d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, 860d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink, 861d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan ARRAY_SIZE(ath9k_htc_tpt_blink)); 862d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#endif 863d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan 864fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Register with mac80211 */ 865fb9987d0f748c983bb795a86f47522313f701a08Sujith error = ieee80211_register_hw(hw); 866fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error) 867fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_register; 868fb9987d0f748c983bb795a86f47522313f701a08Sujith 869fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Handle world regulatory */ 870fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!ath_is_world_regd(reg)) { 871fb9987d0f748c983bb795a86f47522313f701a08Sujith error = regulatory_hint(hw->wiphy, reg->alpha2); 872fb9987d0f748c983bb795a86f47522313f701a08Sujith if (error) 873fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_world; 874fb9987d0f748c983bb795a86f47522313f701a08Sujith } 875fb9987d0f748c983bb795a86f47522313f701a08Sujith 876e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan error = ath9k_htc_init_debug(priv->ah); 877e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan if (error) { 878e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan ath_err(common, "Unable to create debugfs files\n"); 879e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan goto err_world; 880e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan } 881e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan 8823e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan ath_dbg(common, ATH_DBG_CONFIG, 8833e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " 8843e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan "BE:%d, BK:%d, VI:%d, VO:%d\n", 8853e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->wmi_cmd_ep, 8863e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->beacon_ep, 8873e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->cab_ep, 8883e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->uapsd_ep, 8893e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->mgmt_ep, 8903e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->data_be_ep, 8913e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->data_bk_ep, 8923e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->data_vi_ep, 8933e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan priv->data_vo_ep); 8943e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan 8953e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name)); 8963e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan wiphy_info(hw->wiphy, "%s\n", hw_name); 8973e3f1d197f5a432b961fadb35604dba92583945eSujith Manoharan 898fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_init_leds(priv); 899fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_start_rfkill_poll(priv); 900fb9987d0f748c983bb795a86f47522313f701a08Sujith 901fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 902fb9987d0f748c983bb795a86f47522313f701a08Sujith 903fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_world: 904fb9987d0f748c983bb795a86f47522313f701a08Sujith ieee80211_unregister_hw(hw); 905fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_register: 906fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_rx_cleanup(priv); 907fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_rx: 908fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_tx_cleanup(priv); 909fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_tx: 910fb9987d0f748c983bb795a86f47522313f701a08Sujith /* Nothing */ 911fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_regd: 91229bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharan /* Nothing */ 91329bbfb2491316f9a3888e74b0de7fccdbde67aaaSujith Manoharanerr_fw: 914fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_priv(priv); 915fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_init: 916fb9987d0f748c983bb795a86f47522313f701a08Sujith return error; 917fb9987d0f748c983bb795a86f47522313f701a08Sujith} 918fb9987d0f748c983bb795a86f47522313f701a08Sujith 919fb9987d0f748c983bb795a86f47522313f701a08Sujithint ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, 920fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan u16 devid, char *product, u32 drv_info) 921fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 922fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ieee80211_hw *hw; 923fb9987d0f748c983bb795a86f47522313f701a08Sujith struct ath9k_htc_priv *priv; 924fb9987d0f748c983bb795a86f47522313f701a08Sujith int ret; 925fb9987d0f748c983bb795a86f47522313f701a08Sujith 926fb9987d0f748c983bb795a86f47522313f701a08Sujith hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops); 927fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!hw) 928fb9987d0f748c983bb795a86f47522313f701a08Sujith return -ENOMEM; 929fb9987d0f748c983bb795a86f47522313f701a08Sujith 930fb9987d0f748c983bb795a86f47522313f701a08Sujith priv = hw->priv; 931fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->hw = hw; 932fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->htc = htc_handle; 933fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->dev = dev; 934fb9987d0f748c983bb795a86f47522313f701a08Sujith htc_handle->drv_priv = priv; 935fb9987d0f748c983bb795a86f47522313f701a08Sujith SET_IEEE80211_DEV(hw, priv->dev); 936fb9987d0f748c983bb795a86f47522313f701a08Sujith 937fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = ath9k_htc_wait_for_target(priv); 938fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 939fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_free; 940fb9987d0f748c983bb795a86f47522313f701a08Sujith 941fb9987d0f748c983bb795a86f47522313f701a08Sujith priv->wmi = ath9k_init_wmi(priv); 942fb9987d0f748c983bb795a86f47522313f701a08Sujith if (!priv->wmi) { 943fb9987d0f748c983bb795a86f47522313f701a08Sujith ret = -EINVAL; 944fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_free; 945fb9987d0f748c983bb795a86f47522313f701a08Sujith } 946fb9987d0f748c983bb795a86f47522313f701a08Sujith 947fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan ret = ath9k_init_htc_services(priv, devid, drv_info); 948fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 949fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_init; 950fb9987d0f748c983bb795a86f47522313f701a08Sujith 951fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan ret = ath9k_init_device(priv, devid, product, drv_info); 952fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 953fb9987d0f748c983bb795a86f47522313f701a08Sujith goto err_init; 954fb9987d0f748c983bb795a86f47522313f701a08Sujith 955fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 956fb9987d0f748c983bb795a86f47522313f701a08Sujith 957fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_init: 958fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_wmi(priv); 959fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_free: 960fb9987d0f748c983bb795a86f47522313f701a08Sujith ieee80211_free_hw(hw); 961fb9987d0f748c983bb795a86f47522313f701a08Sujith return ret; 962fb9987d0f748c983bb795a86f47522313f701a08Sujith} 963fb9987d0f748c983bb795a86f47522313f701a08Sujith 964fb9987d0f748c983bb795a86f47522313f701a08Sujithvoid ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) 965fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 966fb9987d0f748c983bb795a86f47522313f701a08Sujith if (htc_handle->drv_priv) { 967a3be14b76da111ebe4d245b0542613f9317104e7Sujith 968a3be14b76da111ebe4d245b0542613f9317104e7Sujith /* Check if the device has been yanked out. */ 969a3be14b76da111ebe4d245b0542613f9317104e7Sujith if (hotunplug) 97097dcec5715a381362c88d1542e52c63147764d3cSujith Manoharan htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED; 971a3be14b76da111ebe4d245b0542613f9317104e7Sujith 972fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_device(htc_handle->drv_priv); 973fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_deinit_wmi(htc_handle->drv_priv); 974fb9987d0f748c983bb795a86f47522313f701a08Sujith ieee80211_free_hw(htc_handle->drv_priv->hw); 975fb9987d0f748c983bb795a86f47522313f701a08Sujith } 976fb9987d0f748c983bb795a86f47522313f701a08Sujith} 977fb9987d0f748c983bb795a86f47522313f701a08Sujith 978fb9987d0f748c983bb795a86f47522313f701a08Sujith#ifdef CONFIG_PM 979f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharan 980f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharanvoid ath9k_htc_suspend(struct htc_target *htc_handle) 981f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharan{ 982f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharan ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP); 983f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharan} 984f933ebed7888a9a7d73ebeeb6bcbb3f710c423b4Sujith Manoharan 985fb9987d0f748c983bb795a86f47522313f701a08Sujithint ath9k_htc_resume(struct htc_target *htc_handle) 986fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 987fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan struct ath9k_htc_priv *priv = htc_handle->drv_priv; 988fb9987d0f748c983bb795a86f47522313f701a08Sujith int ret; 989fb9987d0f748c983bb795a86f47522313f701a08Sujith 990fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan ret = ath9k_htc_wait_for_target(priv); 991fb9987d0f748c983bb795a86f47522313f701a08Sujith if (ret) 992fb9987d0f748c983bb795a86f47522313f701a08Sujith return ret; 993fb9987d0f748c983bb795a86f47522313f701a08Sujith 994fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, 9950b5ead91cda63e0db964dadc77601233434f60cbSujith Manoharan priv->ah->hw_version.usbdev); 996fb9987d0f748c983bb795a86f47522313f701a08Sujith return ret; 997fb9987d0f748c983bb795a86f47522313f701a08Sujith} 998fb9987d0f748c983bb795a86f47522313f701a08Sujith#endif 999fb9987d0f748c983bb795a86f47522313f701a08Sujith 1000fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int __init ath9k_htc_init(void) 1001fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 1002e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan if (ath9k_hif_usb_init() < 0) { 1003fb9987d0f748c983bb795a86f47522313f701a08Sujith printk(KERN_ERR 1004fb9987d0f748c983bb795a86f47522313f701a08Sujith "ath9k_htc: No USB devices found," 1005fb9987d0f748c983bb795a86f47522313f701a08Sujith " driver not installed.\n"); 1006e5facc75fa9104f074c4610437a9c717c9e5ecdeRajkumar Manoharan return -ENODEV; 1007fb9987d0f748c983bb795a86f47522313f701a08Sujith } 1008fb9987d0f748c983bb795a86f47522313f701a08Sujith 1009fb9987d0f748c983bb795a86f47522313f701a08Sujith return 0; 1010fb9987d0f748c983bb795a86f47522313f701a08Sujith} 1011fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_init(ath9k_htc_init); 1012fb9987d0f748c983bb795a86f47522313f701a08Sujith 1013fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void __exit ath9k_htc_exit(void) 1014fb9987d0f748c983bb795a86f47522313f701a08Sujith{ 1015fb9987d0f748c983bb795a86f47522313f701a08Sujith ath9k_hif_usb_exit(); 1016fb9987d0f748c983bb795a86f47522313f701a08Sujith printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); 1017fb9987d0f748c983bb795a86f47522313f701a08Sujith} 1018fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_exit(ath9k_htc_exit); 1019