Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 1 | /* |
Sujith Manoharan | 5b68138 | 2011-05-17 13:36:18 +0530 | [diff] [blame] | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above |
| 6 | * copyright notice and this permission notice appear in all copies. |
| 7 | * |
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 15 | */ |
| 16 | |
| 17 | #include "htc.h" |
| 18 | |
| 19 | #define FUDGE 2 |
| 20 | |
Sujith Manoharan | 2493a54 | 2011-04-13 11:23:26 +0530 | [diff] [blame] | 21 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) |
| 22 | { |
| 23 | struct ath_hw *ah = priv->ah; |
| 24 | struct ath9k_tx_queue_info qi, qi_be; |
| 25 | |
| 26 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
| 27 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); |
| 28 | |
| 29 | ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); |
| 30 | |
| 31 | if (priv->ah->opmode == NL80211_IFTYPE_AP) { |
| 32 | qi.tqi_aifs = 1; |
| 33 | qi.tqi_cwmin = 0; |
| 34 | qi.tqi_cwmax = 0; |
| 35 | } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { |
Sujith Manoharan | bea843c | 2012-11-21 18:13:10 +0530 | [diff] [blame] | 36 | int qnum = priv->hwq_map[IEEE80211_AC_BE]; |
Sujith Manoharan | 2493a54 | 2011-04-13 11:23:26 +0530 | [diff] [blame] | 37 | |
| 38 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); |
| 39 | |
| 40 | qi.tqi_aifs = qi_be.tqi_aifs; |
| 41 | |
| 42 | /* |
| 43 | * For WIFI Beacon Distribution |
| 44 | * Long slot time : 2x cwmin |
| 45 | * Short slot time : 4x cwmin |
| 46 | */ |
| 47 | if (ah->slottime == ATH9K_SLOT_TIME_20) |
| 48 | qi.tqi_cwmin = 2*qi_be.tqi_cwmin; |
| 49 | else |
| 50 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; |
| 51 | |
| 52 | qi.tqi_cwmax = qi_be.tqi_cwmax; |
| 53 | |
| 54 | } |
| 55 | |
| 56 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { |
| 57 | ath_err(ath9k_hw_common(ah), |
| 58 | "Unable to update beacon queue %u!\n", priv->beaconq); |
| 59 | } else { |
| 60 | ath9k_hw_resettxqueue(ah, priv->beaconq); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 65 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 66 | struct htc_beacon_config *bss_conf) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 67 | { |
| 68 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 69 | struct ath9k_beacon_state bs; |
| 70 | enum ath9k_int imask = 0; |
| 71 | int dtimperiod, dtimcount, sleepduration; |
| 72 | int cfpperiod, cfpcount, bmiss_timeout; |
Sujith | 7f1f5a0 | 2010-04-16 11:54:03 +0530 | [diff] [blame] | 73 | u32 nexttbtt = 0, intval, tsftu; |
| 74 | __be32 htc_imask = 0; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 75 | u64 tsf; |
| 76 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; |
Sujith Manoharan | 0ff2b5c | 2011-04-20 11:00:34 +0530 | [diff] [blame] | 77 | int ret __attribute__ ((unused)); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 78 | u8 cmd_rsp; |
| 79 | |
| 80 | memset(&bs, 0, sizeof(bs)); |
| 81 | |
Rajkumar Manoharan | f29f5c0 | 2011-05-20 17:52:11 +0530 | [diff] [blame] | 82 | intval = bss_conf->beacon_interval; |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 83 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 84 | |
| 85 | /* |
| 86 | * Setup dtim and cfp parameters according to |
| 87 | * last beacon we received (which may be none). |
| 88 | */ |
| 89 | dtimperiod = bss_conf->dtim_period; |
| 90 | if (dtimperiod <= 0) /* NB: 0 if not known */ |
| 91 | dtimperiod = 1; |
| 92 | dtimcount = 1; |
| 93 | if (dtimcount >= dtimperiod) /* NB: sanity check */ |
| 94 | dtimcount = 0; |
| 95 | cfpperiod = 1; /* NB: no PCF support yet */ |
| 96 | cfpcount = 0; |
| 97 | |
| 98 | sleepduration = intval; |
| 99 | if (sleepduration <= 0) |
| 100 | sleepduration = intval; |
| 101 | |
| 102 | /* |
| 103 | * Pull nexttbtt forward to reflect the current |
| 104 | * TSF and calculate dtim+cfp state for the result. |
| 105 | */ |
| 106 | tsf = ath9k_hw_gettsf64(priv->ah); |
| 107 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; |
| 108 | |
| 109 | num_beacons = tsftu / intval + 1; |
| 110 | offset = tsftu % intval; |
| 111 | nexttbtt = tsftu - offset; |
| 112 | if (offset) |
| 113 | nexttbtt += intval; |
| 114 | |
| 115 | /* DTIM Beacon every dtimperiod Beacon */ |
| 116 | dtim_dec_count = num_beacons % dtimperiod; |
| 117 | /* CFP every cfpperiod DTIM Beacon */ |
| 118 | cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; |
| 119 | if (dtim_dec_count) |
| 120 | cfp_dec_count++; |
| 121 | |
| 122 | dtimcount -= dtim_dec_count; |
| 123 | if (dtimcount < 0) |
| 124 | dtimcount += dtimperiod; |
| 125 | |
| 126 | cfpcount -= cfp_dec_count; |
| 127 | if (cfpcount < 0) |
| 128 | cfpcount += cfpperiod; |
| 129 | |
| 130 | bs.bs_intval = intval; |
| 131 | bs.bs_nexttbtt = nexttbtt; |
| 132 | bs.bs_dtimperiod = dtimperiod*intval; |
| 133 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; |
| 134 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; |
| 135 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; |
| 136 | bs.bs_cfpmaxduration = 0; |
| 137 | |
| 138 | /* |
| 139 | * Calculate the number of consecutive beacons to miss* before taking |
| 140 | * a BMISS interrupt. The configuration is specified in TU so we only |
| 141 | * need calculate based on the beacon interval. Note that we clamp the |
| 142 | * result to at most 15 beacons. |
| 143 | */ |
| 144 | if (sleepduration > intval) { |
| 145 | bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; |
| 146 | } else { |
| 147 | bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); |
| 148 | if (bs.bs_bmissthreshold > 15) |
| 149 | bs.bs_bmissthreshold = 15; |
| 150 | else if (bs.bs_bmissthreshold <= 0) |
| 151 | bs.bs_bmissthreshold = 1; |
| 152 | } |
| 153 | |
| 154 | /* |
| 155 | * Calculate sleep duration. The configuration is given in ms. |
| 156 | * We ensure a multiple of the beacon period is used. Also, if the sleep |
| 157 | * duration is greater than the DTIM period then it makes senses |
| 158 | * to make it a multiple of that. |
| 159 | * |
| 160 | * XXX fixed at 100ms |
| 161 | */ |
| 162 | |
| 163 | bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); |
| 164 | if (bs.bs_sleepduration > bs.bs_dtimperiod) |
| 165 | bs.bs_sleepduration = bs.bs_dtimperiod; |
| 166 | |
| 167 | /* TSF out of range threshold fixed at 1 second */ |
| 168 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
| 169 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 170 | ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n", |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 171 | intval, tsf, tsftu); |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 172 | ath_dbg(common, CONFIG, |
Joe Perches | 226afe6 | 2010-12-02 19:12:37 -0800 | [diff] [blame] | 173 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
| 174 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
| 175 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 176 | |
| 177 | /* Set the computed STA beacon timers */ |
| 178 | |
| 179 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
| 180 | ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); |
| 181 | imask |= ATH9K_INT_BMISS; |
| 182 | htc_imask = cpu_to_be32(imask); |
| 183 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
| 184 | } |
| 185 | |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 186 | static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, |
| 187 | struct htc_beacon_config *bss_conf) |
| 188 | { |
| 189 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 190 | enum ath9k_int imask = 0; |
| 191 | u32 nexttbtt, intval, tsftu; |
| 192 | __be32 htc_imask = 0; |
Sujith Manoharan | 0ff2b5c | 2011-04-20 11:00:34 +0530 | [diff] [blame] | 193 | int ret __attribute__ ((unused)); |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 194 | u8 cmd_rsp; |
| 195 | u64 tsf; |
| 196 | |
Rajkumar Manoharan | f29f5c0 | 2011-05-20 17:52:11 +0530 | [diff] [blame] | 197 | intval = bss_conf->beacon_interval; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 198 | intval /= ATH9K_HTC_MAX_BCN_VIF; |
| 199 | nexttbtt = intval; |
| 200 | |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 201 | /* |
| 202 | * To reduce beacon misses under heavy TX load, |
| 203 | * set the beacon response time to a larger value. |
| 204 | */ |
| 205 | if (intval > DEFAULT_SWBA_RESPONSE) |
| 206 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; |
| 207 | else |
| 208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; |
| 209 | |
Sujith Manoharan | d8a2c51 | 2012-06-25 13:54:41 +0530 | [diff] [blame] | 210 | if (test_bit(OP_TSF_RESET, &priv->op_flags)) { |
Felix Fietkau | dd347f2 | 2011-03-22 21:54:17 +0100 | [diff] [blame] | 211 | ath9k_hw_reset_tsf(priv->ah); |
Sujith Manoharan | d8a2c51 | 2012-06-25 13:54:41 +0530 | [diff] [blame] | 212 | clear_bit(OP_TSF_RESET, &priv->op_flags); |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 213 | } else { |
| 214 | /* |
| 215 | * Pull nexttbtt forward to reflect the current TSF. |
| 216 | */ |
| 217 | tsf = ath9k_hw_gettsf64(priv->ah); |
| 218 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; |
| 219 | do { |
| 220 | nexttbtt += intval; |
| 221 | } while (nexttbtt < tsftu); |
| 222 | } |
| 223 | |
Sujith Manoharan | d8a2c51 | 2012-06-25 13:54:41 +0530 | [diff] [blame] | 224 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 225 | imask |= ATH9K_INT_SWBA; |
| 226 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 227 | ath_dbg(common, CONFIG, |
| 228 | "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d imask: 0x%x\n", |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 229 | bss_conf->beacon_interval, nexttbtt, |
| 230 | priv->ah->config.sw_beacon_response_time, imask); |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 231 | |
Sujith Manoharan | 2493a54 | 2011-04-13 11:23:26 +0530 | [diff] [blame] | 232 | ath9k_htc_beaconq_config(priv); |
| 233 | |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 234 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
Felix Fietkau | dd347f2 | 2011-03-22 21:54:17 +0100 | [diff] [blame] | 235 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 236 | priv->cur_beacon_conf.bmiss_cnt = 0; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 237 | htc_imask = cpu_to_be32(imask); |
| 238 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
| 239 | } |
| 240 | |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 241 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 242 | struct htc_beacon_config *bss_conf) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 243 | { |
| 244 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 245 | enum ath9k_int imask = 0; |
Sujith Manoharan | 200be65 | 2011-02-21 07:50:01 +0530 | [diff] [blame] | 246 | u32 nexttbtt, intval, tsftu; |
Sujith | 7f1f5a0 | 2010-04-16 11:54:03 +0530 | [diff] [blame] | 247 | __be32 htc_imask = 0; |
Sujith Manoharan | 0ff2b5c | 2011-04-20 11:00:34 +0530 | [diff] [blame] | 248 | int ret __attribute__ ((unused)); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 249 | u8 cmd_rsp; |
Sujith Manoharan | 200be65 | 2011-02-21 07:50:01 +0530 | [diff] [blame] | 250 | u64 tsf; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 251 | |
Rajkumar Manoharan | f29f5c0 | 2011-05-20 17:52:11 +0530 | [diff] [blame] | 252 | intval = bss_conf->beacon_interval; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 253 | nexttbtt = intval; |
Sujith Manoharan | 200be65 | 2011-02-21 07:50:01 +0530 | [diff] [blame] | 254 | |
| 255 | /* |
| 256 | * Pull nexttbtt forward to reflect the current TSF. |
| 257 | */ |
| 258 | tsf = ath9k_hw_gettsf64(priv->ah); |
| 259 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; |
| 260 | do { |
| 261 | nexttbtt += intval; |
| 262 | } while (nexttbtt < tsftu); |
| 263 | |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 264 | /* |
| 265 | * Only one IBSS interfce is allowed. |
| 266 | */ |
| 267 | if (intval > DEFAULT_SWBA_RESPONSE) |
| 268 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; |
| 269 | else |
| 270 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; |
| 271 | |
Sujith Manoharan | d8a2c51 | 2012-06-25 13:54:41 +0530 | [diff] [blame] | 272 | if (test_bit(OP_ENABLE_BEACON, &priv->op_flags)) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 273 | imask |= ATH9K_INT_SWBA; |
| 274 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 275 | ath_dbg(common, CONFIG, |
| 276 | "IBSS Beacon config, intval: %d, nexttbtt: %u, resp_time: %d, imask: 0x%x\n", |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 277 | bss_conf->beacon_interval, nexttbtt, |
| 278 | priv->ah->config.sw_beacon_response_time, imask); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 279 | |
| 280 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
Felix Fietkau | dd347f2 | 2011-03-22 21:54:17 +0100 | [diff] [blame] | 281 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 282 | priv->cur_beacon_conf.bmiss_cnt = 0; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 283 | htc_imask = cpu_to_be32(imask); |
| 284 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
| 285 | } |
| 286 | |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 287 | void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, |
| 288 | enum htc_endpoint_id ep_id, bool txok) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 289 | { |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 290 | dev_kfree_skb_any(skb); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 291 | } |
| 292 | |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 293 | static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, |
| 294 | int slot) |
| 295 | { |
| 296 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 297 | struct ieee80211_vif *vif; |
| 298 | struct sk_buff *skb; |
| 299 | struct ieee80211_hdr *hdr; |
Sujith Manoharan | 2c5d57f | 2011-04-13 11:25:47 +0530 | [diff] [blame] | 300 | int padpos, padsize, ret, tx_slot; |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 301 | |
| 302 | spin_lock_bh(&priv->beacon_lock); |
| 303 | |
| 304 | vif = priv->cur_beacon_conf.bslot[slot]; |
| 305 | |
| 306 | skb = ieee80211_get_buffered_bc(priv->hw, vif); |
| 307 | |
| 308 | while(skb) { |
| 309 | hdr = (struct ieee80211_hdr *) skb->data; |
| 310 | |
Felix Fietkau | c60c992 | 2013-04-08 00:04:09 +0200 | [diff] [blame] | 311 | padpos = ieee80211_hdrlen(hdr->frame_control); |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 312 | padsize = padpos & 3; |
| 313 | if (padsize && skb->len > padpos) { |
| 314 | if (skb_headroom(skb) < padsize) { |
| 315 | dev_kfree_skb_any(skb); |
| 316 | goto next; |
| 317 | } |
| 318 | skb_push(skb, padsize); |
| 319 | memmove(skb->data, skb->data + padsize, padpos); |
| 320 | } |
| 321 | |
Sujith Manoharan | 2c5d57f | 2011-04-13 11:25:47 +0530 | [diff] [blame] | 322 | tx_slot = ath9k_htc_tx_get_slot(priv); |
Rajkumar Manoharan | cea3235 | 2011-04-16 14:17:39 +0530 | [diff] [blame] | 323 | if (tx_slot < 0) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 324 | ath_dbg(common, XMIT, "No free CAB slot\n"); |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 325 | dev_kfree_skb_any(skb); |
Sujith Manoharan | 2c5d57f | 2011-04-13 11:25:47 +0530 | [diff] [blame] | 326 | goto next; |
| 327 | } |
| 328 | |
Thomas Huehn | 36323f8 | 2012-07-23 21:33:42 +0200 | [diff] [blame] | 329 | ret = ath9k_htc_tx_start(priv, NULL, skb, tx_slot, true); |
Sujith Manoharan | 2c5d57f | 2011-04-13 11:25:47 +0530 | [diff] [blame] | 330 | if (ret != 0) { |
| 331 | ath9k_htc_tx_clear_slot(priv, tx_slot); |
| 332 | dev_kfree_skb_any(skb); |
| 333 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 334 | ath_dbg(common, XMIT, "Failed to send CAB frame\n"); |
Sujith Manoharan | 8e86a54 | 2011-04-13 11:25:29 +0530 | [diff] [blame] | 335 | } else { |
| 336 | spin_lock_bh(&priv->tx.tx_lock); |
| 337 | priv->tx.queued_cnt++; |
| 338 | spin_unlock_bh(&priv->tx.tx_lock); |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 339 | } |
| 340 | next: |
| 341 | skb = ieee80211_get_buffered_bc(priv->hw, vif); |
| 342 | } |
| 343 | |
| 344 | spin_unlock_bh(&priv->beacon_lock); |
| 345 | } |
| 346 | |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 347 | static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, |
| 348 | int slot) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 349 | { |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 350 | struct ath_common *common = ath9k_hw_common(priv->ah); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 351 | struct ieee80211_vif *vif; |
| 352 | struct ath9k_htc_vif *avp; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 353 | struct tx_beacon_header beacon_hdr; |
Sujith Manoharan | 40dc9e4 | 2011-04-13 11:24:31 +0530 | [diff] [blame] | 354 | struct ath9k_htc_tx_ctl *tx_ctl; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 355 | struct ieee80211_tx_info *info; |
Sujith Manoharan | 9b674a0 | 2011-04-13 11:23:17 +0530 | [diff] [blame] | 356 | struct ieee80211_mgmt *mgmt; |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 357 | struct sk_buff *beacon; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 358 | u8 *tx_fhdr; |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 359 | int ret; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 360 | |
| 361 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 362 | |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 363 | spin_lock_bh(&priv->beacon_lock); |
| 364 | |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 365 | vif = priv->cur_beacon_conf.bslot[slot]; |
| 366 | avp = (struct ath9k_htc_vif *)vif->drv_priv; |
| 367 | |
Sujith Manoharan | d8a2c51 | 2012-06-25 13:54:41 +0530 | [diff] [blame] | 368 | if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) { |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 369 | spin_unlock_bh(&priv->beacon_lock); |
| 370 | return; |
| 371 | } |
| 372 | |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 373 | /* Get a new beacon */ |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 374 | beacon = ieee80211_beacon_get(priv->hw, vif); |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 375 | if (!beacon) { |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 376 | spin_unlock_bh(&priv->beacon_lock); |
| 377 | return; |
| 378 | } |
| 379 | |
Sujith Manoharan | 9b674a0 | 2011-04-13 11:23:17 +0530 | [diff] [blame] | 380 | /* |
| 381 | * Update the TSF adjust value here, the HW will |
| 382 | * add this value for every beacon. |
| 383 | */ |
| 384 | mgmt = (struct ieee80211_mgmt *)beacon->data; |
| 385 | mgmt->u.beacon.timestamp = avp->tsfadjust; |
| 386 | |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 387 | info = IEEE80211_SKB_CB(beacon); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 388 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
| 389 | struct ieee80211_hdr *hdr = |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 390 | (struct ieee80211_hdr *) beacon->data; |
Sujith Manoharan | 9a3d025 | 2011-02-21 07:48:53 +0530 | [diff] [blame] | 391 | avp->seq_no += 0x10; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 392 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
Sujith Manoharan | 9a3d025 | 2011-02-21 07:48:53 +0530 | [diff] [blame] | 393 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 394 | } |
| 395 | |
Sujith Manoharan | 40dc9e4 | 2011-04-13 11:24:31 +0530 | [diff] [blame] | 396 | tx_ctl = HTC_SKB_CB(beacon); |
| 397 | memset(tx_ctl, 0, sizeof(*tx_ctl)); |
| 398 | |
| 399 | tx_ctl->type = ATH9K_HTC_BEACON; |
Sujith Manoharan | d67ee53 | 2011-04-13 11:25:35 +0530 | [diff] [blame] | 400 | tx_ctl->epid = priv->beacon_ep; |
Sujith Manoharan | 40dc9e4 | 2011-04-13 11:24:31 +0530 | [diff] [blame] | 401 | |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 402 | beacon_hdr.vif_index = avp->index; |
Sujith | 9c6dda4 | 2010-05-06 14:45:47 +0530 | [diff] [blame] | 403 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 404 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); |
| 405 | |
Sujith Manoharan | d67ee53 | 2011-04-13 11:25:35 +0530 | [diff] [blame] | 406 | ret = htc_send(priv->htc, beacon); |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 407 | if (ret != 0) { |
| 408 | if (ret == -ENOMEM) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 409 | ath_dbg(common, BSTUCK, |
Sujith Manoharan | b0a6ba9 | 2011-04-13 11:23:44 +0530 | [diff] [blame] | 410 | "Failed to send beacon, no free TX buffer\n"); |
| 411 | } |
| 412 | dev_kfree_skb_any(beacon); |
| 413 | } |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 414 | |
| 415 | spin_unlock_bh(&priv->beacon_lock); |
| 416 | } |
| 417 | |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 418 | static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, |
| 419 | struct wmi_event_swba *swba) |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 420 | { |
| 421 | struct ath_common *common = ath9k_hw_common(priv->ah); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 422 | u64 tsf; |
| 423 | u32 tsftu; |
| 424 | u16 intval; |
| 425 | int slot; |
| 426 | |
Rajkumar Manoharan | f29f5c0 | 2011-05-20 17:52:11 +0530 | [diff] [blame] | 427 | intval = priv->cur_beacon_conf.beacon_interval; |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 428 | |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 429 | tsf = be64_to_cpu(swba->tsf); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 430 | tsftu = TSF_TO_TU(tsf >> 32, tsf); |
| 431 | slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; |
| 432 | slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; |
| 433 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 434 | ath_dbg(common, BEACON, |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 435 | "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", |
| 436 | slot, tsf, tsftu, intval); |
| 437 | |
| 438 | return slot; |
| 439 | } |
| 440 | |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 441 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, |
| 442 | struct wmi_event_swba *swba) |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 443 | { |
| 444 | struct ath_common *common = ath9k_hw_common(priv->ah); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 445 | int slot; |
| 446 | |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 447 | if (swba->beacon_pending != 0) { |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 448 | priv->cur_beacon_conf.bmiss_cnt++; |
| 449 | if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 450 | ath_dbg(common, BSTUCK, "Beacon stuck, HW reset\n"); |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 451 | ieee80211_queue_work(priv->hw, |
| 452 | &priv->fatal_work); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 453 | } |
| 454 | return; |
| 455 | } |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 456 | |
| 457 | if (priv->cur_beacon_conf.bmiss_cnt) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 458 | ath_dbg(common, BSTUCK, |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 459 | "Resuming beacon xmit after %u misses\n", |
| 460 | priv->cur_beacon_conf.bmiss_cnt); |
| 461 | priv->cur_beacon_conf.bmiss_cnt = 0; |
| 462 | } |
| 463 | |
Sujith Manoharan | f4c8899 | 2011-04-13 11:23:52 +0530 | [diff] [blame] | 464 | slot = ath9k_htc_choose_bslot(priv, swba); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 465 | spin_lock_bh(&priv->beacon_lock); |
| 466 | if (priv->cur_beacon_conf.bslot[slot] == NULL) { |
| 467 | spin_unlock_bh(&priv->beacon_lock); |
| 468 | return; |
| 469 | } |
| 470 | spin_unlock_bh(&priv->beacon_lock); |
| 471 | |
Sujith Manoharan | 7d547eb4 | 2011-04-13 11:23:34 +0530 | [diff] [blame] | 472 | ath9k_htc_send_buffered(priv, slot); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 473 | ath9k_htc_send_beacon(priv, slot); |
| 474 | } |
| 475 | |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 476 | void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, |
| 477 | struct ieee80211_vif *vif) |
| 478 | { |
| 479 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 480 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
| 481 | int i = 0; |
| 482 | |
| 483 | spin_lock_bh(&priv->beacon_lock); |
| 484 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { |
| 485 | if (priv->cur_beacon_conf.bslot[i] == NULL) { |
| 486 | avp->bslot = i; |
| 487 | break; |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | priv->cur_beacon_conf.bslot[avp->bslot] = vif; |
| 492 | spin_unlock_bh(&priv->beacon_lock); |
| 493 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 494 | ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", |
| 495 | avp->bslot); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 496 | } |
| 497 | |
| 498 | void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, |
| 499 | struct ieee80211_vif *vif) |
| 500 | { |
| 501 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 502 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
| 503 | |
| 504 | spin_lock_bh(&priv->beacon_lock); |
| 505 | priv->cur_beacon_conf.bslot[avp->bslot] = NULL; |
| 506 | spin_unlock_bh(&priv->beacon_lock); |
| 507 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 508 | ath_dbg(common, CONFIG, "Removed interface at beacon slot: %d\n", |
| 509 | avp->bslot); |
Sujith Manoharan | 832f6a1 | 2011-04-13 11:23:08 +0530 | [diff] [blame] | 510 | } |
| 511 | |
Sujith Manoharan | 9b674a0 | 2011-04-13 11:23:17 +0530 | [diff] [blame] | 512 | /* |
| 513 | * Calculate the TSF adjustment value for all slots |
| 514 | * other than zero. |
| 515 | */ |
| 516 | void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, |
| 517 | struct ieee80211_vif *vif) |
| 518 | { |
| 519 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 520 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
| 521 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
| 522 | u64 tsfadjust; |
| 523 | |
| 524 | if (avp->bslot == 0) |
| 525 | return; |
| 526 | |
| 527 | /* |
| 528 | * The beacon interval cannot be different for multi-AP mode, |
| 529 | * and we reach here only for VIF slots greater than zero, |
| 530 | * so beacon_interval is guaranteed to be set in cur_conf. |
| 531 | */ |
| 532 | tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; |
| 533 | avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); |
| 534 | |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 535 | ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n", |
Sujith Manoharan | 9b674a0 | 2011-04-13 11:23:17 +0530 | [diff] [blame] | 536 | (unsigned long long)tsfadjust, avp->bslot); |
| 537 | } |
| 538 | |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 539 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
| 540 | { |
| 541 | bool *beacon_configured = (bool *)data; |
| 542 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
| 543 | |
| 544 | if (vif->type == NL80211_IFTYPE_STATION && |
| 545 | avp->beacon_configured) |
| 546 | *beacon_configured = true; |
| 547 | } |
| 548 | |
| 549 | static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, |
| 550 | struct ieee80211_vif *vif) |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 551 | { |
| 552 | struct ath_common *common = ath9k_hw_common(priv->ah); |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 553 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
Sujith | fcb9392 | 2010-04-16 11:53:48 +0530 | [diff] [blame] | 554 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 555 | bool beacon_configured; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 556 | |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 557 | /* |
| 558 | * Changing the beacon interval when multiple AP interfaces |
| 559 | * are configured will affect beacon transmission of all |
| 560 | * of them. |
| 561 | */ |
| 562 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
| 563 | (priv->num_ap_vif > 1) && |
| 564 | (vif->type == NL80211_IFTYPE_AP) && |
| 565 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 566 | ath_dbg(common, CONFIG, |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 567 | "Changing beacon interval of multiple AP interfaces !\n"); |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 568 | return false; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 569 | } |
| 570 | |
| 571 | /* |
| 572 | * If the HW is operating in AP mode, any new station interfaces that |
| 573 | * are added cannot change the beacon parameters. |
| 574 | */ |
| 575 | if (priv->num_ap_vif && |
| 576 | (vif->type != NL80211_IFTYPE_AP)) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 577 | ath_dbg(common, CONFIG, |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 578 | "HW in AP mode, cannot set STA beacon parameters\n"); |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 579 | return false; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 580 | } |
| 581 | |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 582 | /* |
| 583 | * The beacon parameters are configured only for the first |
| 584 | * station interface. |
| 585 | */ |
| 586 | if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && |
| 587 | (priv->num_sta_vif > 1) && |
| 588 | (vif->type == NL80211_IFTYPE_STATION)) { |
| 589 | beacon_configured = false; |
Johannes Berg | 8b2c982 | 2012-11-06 20:23:30 +0100 | [diff] [blame] | 590 | ieee80211_iterate_active_interfaces_atomic( |
| 591 | priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
| 592 | ath9k_htc_beacon_iter, &beacon_configured); |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 593 | |
| 594 | if (beacon_configured) { |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 595 | ath_dbg(common, CONFIG, |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 596 | "Beacon already configured for a station interface\n"); |
| 597 | return false; |
| 598 | } |
| 599 | } |
| 600 | |
| 601 | return true; |
| 602 | } |
| 603 | |
| 604 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
| 605 | struct ieee80211_vif *vif) |
| 606 | { |
| 607 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 608 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
| 609 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
| 610 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
| 611 | |
| 612 | if (!ath9k_htc_check_beacon_config(priv, vif)) |
| 613 | return; |
| 614 | |
Sujith | fcb9392 | 2010-04-16 11:53:48 +0530 | [diff] [blame] | 615 | cur_conf->beacon_interval = bss_conf->beacon_int; |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 616 | if (cur_conf->beacon_interval == 0) |
| 617 | cur_conf->beacon_interval = 100; |
| 618 | |
Sujith | fcb9392 | 2010-04-16 11:53:48 +0530 | [diff] [blame] | 619 | cur_conf->dtim_period = bss_conf->dtim_period; |
Sujith | fcb9392 | 2010-04-16 11:53:48 +0530 | [diff] [blame] | 620 | cur_conf->bmiss_timeout = |
| 621 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; |
| 622 | |
| 623 | switch (vif->type) { |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 624 | case NL80211_IFTYPE_STATION: |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 625 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
Sujith Manoharan | e7a2a4f | 2011-02-27 09:20:40 +0530 | [diff] [blame] | 626 | avp->beacon_configured = true; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 627 | break; |
| 628 | case NL80211_IFTYPE_ADHOC: |
Vivek Natarajan | 1c3652a | 2010-04-05 14:48:06 +0530 | [diff] [blame] | 629 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 630 | break; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 631 | case NL80211_IFTYPE_AP: |
| 632 | ath9k_htc_beacon_config_ap(priv, cur_conf); |
| 633 | break; |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 634 | default: |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 635 | ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); |
Sujith | fb9987d | 2010-03-17 14:25:25 +0530 | [diff] [blame] | 636 | return; |
| 637 | } |
| 638 | } |
Sujith Manoharan | 7c27734 | 2011-02-21 07:48:39 +0530 | [diff] [blame] | 639 | |
| 640 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) |
| 641 | { |
| 642 | struct ath_common *common = ath9k_hw_common(priv->ah); |
| 643 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
| 644 | |
| 645 | switch (priv->ah->opmode) { |
| 646 | case NL80211_IFTYPE_STATION: |
| 647 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
| 648 | break; |
| 649 | case NL80211_IFTYPE_ADHOC: |
| 650 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
| 651 | break; |
Sujith Manoharan | a5fae37 | 2011-02-21 07:49:53 +0530 | [diff] [blame] | 652 | case NL80211_IFTYPE_AP: |
| 653 | ath9k_htc_beacon_config_ap(priv, cur_conf); |
| 654 | break; |
Sujith Manoharan | 7c27734 | 2011-02-21 07:48:39 +0530 | [diff] [blame] | 655 | default: |
Joe Perches | d2182b6 | 2011-12-15 14:55:53 -0800 | [diff] [blame] | 656 | ath_dbg(common, CONFIG, "Unsupported beaconing mode\n"); |
Sujith Manoharan | 7c27734 | 2011-02-21 07:48:39 +0530 | [diff] [blame] | 657 | return; |
| 658 | } |
| 659 | } |