1 /* 2 * Copyright (c) 2010 Atheros Communications Inc. 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 21 static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, 22 struct htc_beacon_config *bss_conf) 23 { 24 struct ath_common *common = ath9k_hw_common(priv->ah); 25 struct ath9k_beacon_state bs; 26 enum ath9k_int imask = 0; 27 int dtimperiod, dtimcount, sleepduration; 28 int cfpperiod, cfpcount, bmiss_timeout; 29 u32 nexttbtt = 0, intval, tsftu; 30 __be32 htc_imask = 0; 31 u64 tsf; 32 int num_beacons, offset, dtim_dec_count, cfp_dec_count; 33 int ret; 34 u8 cmd_rsp; 35 36 memset(&bs, 0, sizeof(bs)); 37 38 intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; 39 bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); 40 41 /* 42 * Setup dtim and cfp parameters according to 43 * last beacon we received (which may be none). 44 */ 45 dtimperiod = bss_conf->dtim_period; 46 if (dtimperiod <= 0) /* NB: 0 if not known */ 47 dtimperiod = 1; 48 dtimcount = 1; 49 if (dtimcount >= dtimperiod) /* NB: sanity check */ 50 dtimcount = 0; 51 cfpperiod = 1; /* NB: no PCF support yet */ 52 cfpcount = 0; 53 54 sleepduration = intval; 55 if (sleepduration <= 0) 56 sleepduration = intval; 57 58 /* 59 * Pull nexttbtt forward to reflect the current 60 * TSF and calculate dtim+cfp state for the result. 61 */ 62 tsf = ath9k_hw_gettsf64(priv->ah); 63 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 64 65 num_beacons = tsftu / intval + 1; 66 offset = tsftu % intval; 67 nexttbtt = tsftu - offset; 68 if (offset) 69 nexttbtt += intval; 70 71 /* DTIM Beacon every dtimperiod Beacon */ 72 dtim_dec_count = num_beacons % dtimperiod; 73 /* CFP every cfpperiod DTIM Beacon */ 74 cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; 75 if (dtim_dec_count) 76 cfp_dec_count++; 77 78 dtimcount -= dtim_dec_count; 79 if (dtimcount < 0) 80 dtimcount += dtimperiod; 81 82 cfpcount -= cfp_dec_count; 83 if (cfpcount < 0) 84 cfpcount += cfpperiod; 85 86 bs.bs_intval = intval; 87 bs.bs_nexttbtt = nexttbtt; 88 bs.bs_dtimperiod = dtimperiod*intval; 89 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; 90 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; 91 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; 92 bs.bs_cfpmaxduration = 0; 93 94 /* 95 * Calculate the number of consecutive beacons to miss* before taking 96 * a BMISS interrupt. The configuration is specified in TU so we only 97 * need calculate based on the beacon interval. Note that we clamp the 98 * result to at most 15 beacons. 99 */ 100 if (sleepduration > intval) { 101 bs.bs_bmissthreshold = ATH_DEFAULT_BMISS_LIMIT / 2; 102 } else { 103 bs.bs_bmissthreshold = DIV_ROUND_UP(bmiss_timeout, intval); 104 if (bs.bs_bmissthreshold > 15) 105 bs.bs_bmissthreshold = 15; 106 else if (bs.bs_bmissthreshold <= 0) 107 bs.bs_bmissthreshold = 1; 108 } 109 110 /* 111 * Calculate sleep duration. The configuration is given in ms. 112 * We ensure a multiple of the beacon period is used. Also, if the sleep 113 * duration is greater than the DTIM period then it makes senses 114 * to make it a multiple of that. 115 * 116 * XXX fixed at 100ms 117 */ 118 119 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); 120 if (bs.bs_sleepduration > bs.bs_dtimperiod) 121 bs.bs_sleepduration = bs.bs_dtimperiod; 122 123 /* TSF out of range threshold fixed at 1 second */ 124 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; 125 126 ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n", 127 intval, tsf, tsftu); 128 ath_dbg(common, ATH_DBG_CONFIG, 129 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", 130 bs.bs_bmissthreshold, bs.bs_sleepduration, 131 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); 132 133 /* Set the computed STA beacon timers */ 134 135 WMI_CMD(WMI_DISABLE_INTR_CMDID); 136 ath9k_hw_set_sta_beacon_timers(priv->ah, &bs); 137 imask |= ATH9K_INT_BMISS; 138 htc_imask = cpu_to_be32(imask); 139 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 140 } 141 142 static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, 143 struct htc_beacon_config *bss_conf) 144 { 145 struct ath_common *common = ath9k_hw_common(priv->ah); 146 enum ath9k_int imask = 0; 147 u32 nexttbtt, intval, tsftu; 148 __be32 htc_imask = 0; 149 int ret; 150 u8 cmd_rsp; 151 u64 tsf; 152 153 intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; 154 intval /= ATH9K_HTC_MAX_BCN_VIF; 155 nexttbtt = intval; 156 157 if (priv->op_flags & OP_TSF_RESET) { 158 intval |= ATH9K_BEACON_RESET_TSF; 159 priv->op_flags &= ~OP_TSF_RESET; 160 } else { 161 /* 162 * Pull nexttbtt forward to reflect the current TSF. 163 */ 164 tsf = ath9k_hw_gettsf64(priv->ah); 165 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; 166 do { 167 nexttbtt += intval; 168 } while (nexttbtt < tsftu); 169 } 170 171 intval |= ATH9K_BEACON_ENA; 172 173 if (priv->op_flags & OP_ENABLE_BEACON) 174 imask |= ATH9K_INT_SWBA; 175 176 ath_dbg(common, ATH_DBG_CONFIG, 177 "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", 178 bss_conf->beacon_interval, nexttbtt, imask); 179 180 WMI_CMD(WMI_DISABLE_INTR_CMDID); 181 ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); 182 priv->bmiss_cnt = 0; 183 htc_imask = cpu_to_be32(imask); 184 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 185 } 186 187 static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, 188 struct htc_beacon_config *bss_conf) 189 { 190 struct ath_common *common = ath9k_hw_common(priv->ah); 191 enum ath9k_int imask = 0; 192 u32 nexttbtt, intval, tsftu; 193 __be32 htc_imask = 0; 194 int ret; 195 u8 cmd_rsp; 196 u64 tsf; 197 198 intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; 199 nexttbtt = intval; 200 201 /* 202 * Pull nexttbtt forward to reflect the current TSF. 203 */ 204 tsf = ath9k_hw_gettsf64(priv->ah); 205 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; 206 do { 207 nexttbtt += intval; 208 } while (nexttbtt < tsftu); 209 210 intval |= ATH9K_BEACON_ENA; 211 if (priv->op_flags & OP_ENABLE_BEACON) 212 imask |= ATH9K_INT_SWBA; 213 214 ath_dbg(common, ATH_DBG_CONFIG, 215 "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", 216 bss_conf->beacon_interval, nexttbtt, imask); 217 218 WMI_CMD(WMI_DISABLE_INTR_CMDID); 219 ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); 220 priv->bmiss_cnt = 0; 221 htc_imask = cpu_to_be32(imask); 222 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 223 } 224 225 void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, 226 enum htc_endpoint_id ep_id, bool txok) 227 { 228 dev_kfree_skb_any(skb); 229 } 230 231 void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) 232 { 233 struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; 234 struct tx_beacon_header beacon_hdr; 235 struct ath9k_htc_tx_ctl tx_ctl; 236 struct ieee80211_tx_info *info; 237 struct sk_buff *beacon; 238 u8 *tx_fhdr; 239 240 memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); 241 memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); 242 243 /* FIXME: Handle BMISS */ 244 if (beacon_pending != 0) { 245 priv->bmiss_cnt++; 246 return; 247 } 248 249 spin_lock_bh(&priv->beacon_lock); 250 251 if (unlikely(priv->op_flags & OP_SCANNING)) { 252 spin_unlock_bh(&priv->beacon_lock); 253 return; 254 } 255 256 /* Get a new beacon */ 257 beacon = ieee80211_beacon_get(priv->hw, priv->vif); 258 if (!beacon) { 259 spin_unlock_bh(&priv->beacon_lock); 260 return; 261 } 262 263 info = IEEE80211_SKB_CB(beacon); 264 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 265 struct ieee80211_hdr *hdr = 266 (struct ieee80211_hdr *) beacon->data; 267 avp->seq_no += 0x10; 268 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 269 hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); 270 } 271 272 tx_ctl.type = ATH9K_HTC_NORMAL; 273 beacon_hdr.vif_index = avp->index; 274 tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); 275 memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); 276 277 htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); 278 279 spin_unlock_bh(&priv->beacon_lock); 280 } 281 282 /* Currently, only for IBSS */ 283 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) 284 { 285 struct ath_hw *ah = priv->ah; 286 struct ath9k_tx_queue_info qi, qi_be; 287 int qnum = priv->hwq_map[WME_AC_BE]; 288 289 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); 290 memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); 291 292 ath9k_hw_get_txq_props(ah, qnum, &qi_be); 293 294 qi.tqi_aifs = qi_be.tqi_aifs; 295 /* For WIFI Beacon Distribution 296 * Long slot time : 2x cwmin 297 * Short slot time : 4x cwmin 298 */ 299 if (ah->slottime == ATH9K_SLOT_TIME_20) 300 qi.tqi_cwmin = 2*qi_be.tqi_cwmin; 301 else 302 qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 303 qi.tqi_cwmax = qi_be.tqi_cwmax; 304 305 if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { 306 ath_err(ath9k_hw_common(ah), 307 "Unable to update beacon queue %u!\n", qnum); 308 } else { 309 ath9k_hw_resettxqueue(ah, priv->beaconq); 310 } 311 } 312 313 static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 314 { 315 bool *beacon_configured = (bool *)data; 316 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 317 318 if (vif->type == NL80211_IFTYPE_STATION && 319 avp->beacon_configured) 320 *beacon_configured = true; 321 } 322 323 static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, 324 struct ieee80211_vif *vif) 325 { 326 struct ath_common *common = ath9k_hw_common(priv->ah); 327 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 328 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 329 bool beacon_configured; 330 331 /* 332 * Changing the beacon interval when multiple AP interfaces 333 * are configured will affect beacon transmission of all 334 * of them. 335 */ 336 if ((priv->ah->opmode == NL80211_IFTYPE_AP) && 337 (priv->num_ap_vif > 1) && 338 (vif->type == NL80211_IFTYPE_AP) && 339 (cur_conf->beacon_interval != bss_conf->beacon_int)) { 340 ath_dbg(common, ATH_DBG_CONFIG, 341 "Changing beacon interval of multiple AP interfaces !\n"); 342 return false; 343 } 344 345 /* 346 * If the HW is operating in AP mode, any new station interfaces that 347 * are added cannot change the beacon parameters. 348 */ 349 if (priv->num_ap_vif && 350 (vif->type != NL80211_IFTYPE_AP)) { 351 ath_dbg(common, ATH_DBG_CONFIG, 352 "HW in AP mode, cannot set STA beacon parameters\n"); 353 return false; 354 } 355 356 /* 357 * The beacon parameters are configured only for the first 358 * station interface. 359 */ 360 if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && 361 (priv->num_sta_vif > 1) && 362 (vif->type == NL80211_IFTYPE_STATION)) { 363 beacon_configured = false; 364 ieee80211_iterate_active_interfaces_atomic(priv->hw, 365 ath9k_htc_beacon_iter, 366 &beacon_configured); 367 368 if (beacon_configured) { 369 ath_dbg(common, ATH_DBG_CONFIG, 370 "Beacon already configured for a station interface\n"); 371 return false; 372 } 373 } 374 375 return true; 376 } 377 378 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, 379 struct ieee80211_vif *vif) 380 { 381 struct ath_common *common = ath9k_hw_common(priv->ah); 382 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 383 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 384 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 385 386 if (!ath9k_htc_check_beacon_config(priv, vif)) 387 return; 388 389 cur_conf->beacon_interval = bss_conf->beacon_int; 390 if (cur_conf->beacon_interval == 0) 391 cur_conf->beacon_interval = 100; 392 393 cur_conf->dtim_period = bss_conf->dtim_period; 394 cur_conf->bmiss_timeout = 395 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 396 397 switch (vif->type) { 398 case NL80211_IFTYPE_STATION: 399 ath9k_htc_beacon_config_sta(priv, cur_conf); 400 avp->beacon_configured = true; 401 break; 402 case NL80211_IFTYPE_ADHOC: 403 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 404 break; 405 case NL80211_IFTYPE_AP: 406 ath9k_htc_beacon_config_ap(priv, cur_conf); 407 break; 408 default: 409 ath_dbg(common, ATH_DBG_CONFIG, 410 "Unsupported beaconing mode\n"); 411 return; 412 } 413 } 414 415 void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) 416 { 417 struct ath_common *common = ath9k_hw_common(priv->ah); 418 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 419 420 switch (priv->ah->opmode) { 421 case NL80211_IFTYPE_STATION: 422 ath9k_htc_beacon_config_sta(priv, cur_conf); 423 break; 424 case NL80211_IFTYPE_ADHOC: 425 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 426 break; 427 case NL80211_IFTYPE_AP: 428 ath9k_htc_beacon_config_ap(priv, cur_conf); 429 break; 430 default: 431 ath_dbg(common, ATH_DBG_CONFIG, 432 "Unsupported beaconing mode\n"); 433 return; 434 } 435 } 436