2 * Copyright (c) 2010-2011 Atheros Communications Inc.
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.
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.
21 void ath9k_htc_beaconq_config(struct ath9k_htc_priv
*priv
)
23 struct ath_hw
*ah
= priv
->ah
;
24 struct ath9k_tx_queue_info qi
, qi_be
;
26 memset(&qi
, 0, sizeof(struct ath9k_tx_queue_info
));
27 memset(&qi_be
, 0, sizeof(struct ath9k_tx_queue_info
));
29 ath9k_hw_get_txq_props(ah
, priv
->beacon
.beaconq
, &qi
);
31 if (priv
->ah
->opmode
== NL80211_IFTYPE_AP
||
32 priv
->ah
->opmode
== NL80211_IFTYPE_MESH_POINT
) {
36 } else if (priv
->ah
->opmode
== NL80211_IFTYPE_ADHOC
) {
37 int qnum
= priv
->hwq_map
[IEEE80211_AC_BE
];
39 ath9k_hw_get_txq_props(ah
, qnum
, &qi_be
);
41 qi
.tqi_aifs
= qi_be
.tqi_aifs
;
44 * For WIFI Beacon Distribution
45 * Long slot time : 2x cwmin
46 * Short slot time : 4x cwmin
48 if (ah
->slottime
== 20)
49 qi
.tqi_cwmin
= 2*qi_be
.tqi_cwmin
;
51 qi
.tqi_cwmin
= 4*qi_be
.tqi_cwmin
;
53 qi
.tqi_cwmax
= qi_be
.tqi_cwmax
;
57 if (!ath9k_hw_set_txq_props(ah
, priv
->beacon
.beaconq
, &qi
)) {
58 ath_err(ath9k_hw_common(ah
),
59 "Unable to update beacon queue %u!\n", priv
->beacon
.beaconq
);
61 ath9k_hw_resettxqueue(ah
, priv
->beacon
.beaconq
);
66 * Both nexttbtt and intval have to be in usecs.
68 static void ath9k_htc_beacon_init(struct ath9k_htc_priv
*priv
,
69 struct ath_beacon_config
*conf
,
72 struct ath_hw
*ah
= priv
->ah
;
73 int ret
__attribute__ ((unused
));
77 if (conf
->intval
>= TU_TO_USEC(DEFAULT_SWBA_RESPONSE
))
78 ah
->config
.sw_beacon_response_time
= DEFAULT_SWBA_RESPONSE
;
80 ah
->config
.sw_beacon_response_time
= MIN_SWBA_RESPONSE
;
82 WMI_CMD(WMI_DISABLE_INTR_CMDID
);
84 ath9k_hw_reset_tsf(ah
);
85 ath9k_htc_beaconq_config(priv
);
86 ath9k_hw_beaconinit(ah
, conf
->nexttbtt
, conf
->intval
);
87 priv
->beacon
.bmisscnt
= 0;
88 htc_imask
= cpu_to_be32(ah
->imask
);
89 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID
, &htc_imask
);
92 static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv
*priv
,
93 struct ath_beacon_config
*bss_conf
)
95 struct ath9k_beacon_state bs
;
96 enum ath9k_int imask
= 0;
98 int ret
__attribute__ ((unused
));
101 if (ath9k_cmn_beacon_config_sta(priv
->ah
, bss_conf
, &bs
) == -EPERM
)
104 WMI_CMD(WMI_DISABLE_INTR_CMDID
);
105 ath9k_hw_set_sta_beacon_timers(priv
->ah
, &bs
);
106 imask
|= ATH9K_INT_BMISS
;
107 htc_imask
= cpu_to_be32(imask
);
108 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID
, &htc_imask
);
111 static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv
*priv
,
112 struct ath_beacon_config
*conf
)
114 struct ath_hw
*ah
= priv
->ah
;
117 ath9k_cmn_beacon_config_ap(ah
, conf
, ATH9K_HTC_MAX_BCN_VIF
);
118 ath9k_htc_beacon_init(priv
, conf
, false);
121 static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv
*priv
,
122 struct ath_beacon_config
*conf
)
124 struct ath_hw
*ah
= priv
->ah
;
127 ath9k_cmn_beacon_config_adhoc(ah
, conf
);
128 ath9k_htc_beacon_init(priv
, conf
, conf
->ibss_creator
);
131 void ath9k_htc_beaconep(void *drv_priv
, struct sk_buff
*skb
,
132 enum htc_endpoint_id ep_id
, bool txok
)
134 dev_kfree_skb_any(skb
);
137 static void ath9k_htc_send_buffered(struct ath9k_htc_priv
*priv
,
140 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
141 struct ieee80211_vif
*vif
;
143 struct ieee80211_hdr
*hdr
;
144 int padpos
, padsize
, ret
, tx_slot
;
146 spin_lock_bh(&priv
->beacon_lock
);
148 vif
= priv
->beacon
.bslot
[slot
];
150 skb
= ieee80211_get_buffered_bc(priv
->hw
, vif
);
153 hdr
= (struct ieee80211_hdr
*) skb
->data
;
155 padpos
= ieee80211_hdrlen(hdr
->frame_control
);
156 padsize
= padpos
& 3;
157 if (padsize
&& skb
->len
> padpos
) {
158 if (skb_headroom(skb
) < padsize
) {
159 dev_kfree_skb_any(skb
);
162 skb_push(skb
, padsize
);
163 memmove(skb
->data
, skb
->data
+ padsize
, padpos
);
166 tx_slot
= ath9k_htc_tx_get_slot(priv
);
168 ath_dbg(common
, XMIT
, "No free CAB slot\n");
169 dev_kfree_skb_any(skb
);
173 ret
= ath9k_htc_tx_start(priv
, NULL
, skb
, tx_slot
, true);
175 ath9k_htc_tx_clear_slot(priv
, tx_slot
);
176 dev_kfree_skb_any(skb
);
178 ath_dbg(common
, XMIT
, "Failed to send CAB frame\n");
180 spin_lock_bh(&priv
->tx
.tx_lock
);
181 priv
->tx
.queued_cnt
++;
182 spin_unlock_bh(&priv
->tx
.tx_lock
);
185 skb
= ieee80211_get_buffered_bc(priv
->hw
, vif
);
188 spin_unlock_bh(&priv
->beacon_lock
);
191 static void ath9k_htc_send_beacon(struct ath9k_htc_priv
*priv
,
194 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
195 struct ieee80211_vif
*vif
;
196 struct ath9k_htc_vif
*avp
;
197 struct tx_beacon_header beacon_hdr
;
198 struct ath9k_htc_tx_ctl
*tx_ctl
;
199 struct ieee80211_tx_info
*info
;
200 struct ieee80211_mgmt
*mgmt
;
201 struct sk_buff
*beacon
;
205 memset(&beacon_hdr
, 0, sizeof(struct tx_beacon_header
));
207 spin_lock_bh(&priv
->beacon_lock
);
209 vif
= priv
->beacon
.bslot
[slot
];
210 avp
= (struct ath9k_htc_vif
*)vif
->drv_priv
;
212 if (unlikely(test_bit(ATH_OP_SCANNING
, &common
->op_flags
))) {
213 spin_unlock_bh(&priv
->beacon_lock
);
217 /* Get a new beacon */
218 beacon
= ieee80211_beacon_get(priv
->hw
, vif
);
220 spin_unlock_bh(&priv
->beacon_lock
);
225 * Update the TSF adjust value here, the HW will
226 * add this value for every beacon.
228 mgmt
= (struct ieee80211_mgmt
*)beacon
->data
;
229 mgmt
->u
.beacon
.timestamp
= avp
->tsfadjust
;
231 info
= IEEE80211_SKB_CB(beacon
);
232 if (info
->flags
& IEEE80211_TX_CTL_ASSIGN_SEQ
) {
233 struct ieee80211_hdr
*hdr
=
234 (struct ieee80211_hdr
*) beacon
->data
;
236 hdr
->seq_ctrl
&= cpu_to_le16(IEEE80211_SCTL_FRAG
);
237 hdr
->seq_ctrl
|= cpu_to_le16(avp
->seq_no
);
240 tx_ctl
= HTC_SKB_CB(beacon
);
241 memset(tx_ctl
, 0, sizeof(*tx_ctl
));
243 tx_ctl
->type
= ATH9K_HTC_BEACON
;
244 tx_ctl
->epid
= priv
->beacon_ep
;
246 beacon_hdr
.vif_index
= avp
->index
;
247 tx_fhdr
= skb_push(beacon
, sizeof(beacon_hdr
));
248 memcpy(tx_fhdr
, (u8
*) &beacon_hdr
, sizeof(beacon_hdr
));
250 ret
= htc_send(priv
->htc
, beacon
);
252 if (ret
== -ENOMEM
) {
253 ath_dbg(common
, BSTUCK
,
254 "Failed to send beacon, no free TX buffer\n");
256 dev_kfree_skb_any(beacon
);
259 spin_unlock_bh(&priv
->beacon_lock
);
261 ath9k_htc_csa_is_finished(priv
);
264 static int ath9k_htc_choose_bslot(struct ath9k_htc_priv
*priv
,
265 struct wmi_event_swba
*swba
)
267 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
273 intval
= priv
->cur_beacon_conf
.beacon_interval
;
275 tsf
= be64_to_cpu(swba
->tsf
);
276 tsftu
= TSF_TO_TU(tsf
>> 32, tsf
);
277 slot
= ((tsftu
% intval
) * ATH9K_HTC_MAX_BCN_VIF
) / intval
;
278 slot
= ATH9K_HTC_MAX_BCN_VIF
- slot
- 1;
280 ath_dbg(common
, BEACON
,
281 "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n",
282 slot
, tsf
, tsftu
, intval
);
287 void ath9k_htc_swba(struct ath9k_htc_priv
*priv
,
288 struct wmi_event_swba
*swba
)
290 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
293 if (swba
->beacon_pending
!= 0) {
294 priv
->beacon
.bmisscnt
++;
295 if (priv
->beacon
.bmisscnt
> BSTUCK_THRESHOLD
) {
296 ath_dbg(common
, BSTUCK
, "Beacon stuck, HW reset\n");
297 ieee80211_queue_work(priv
->hw
,
303 if (priv
->beacon
.bmisscnt
) {
304 ath_dbg(common
, BSTUCK
,
305 "Resuming beacon xmit after %u misses\n",
306 priv
->beacon
.bmisscnt
);
307 priv
->beacon
.bmisscnt
= 0;
310 slot
= ath9k_htc_choose_bslot(priv
, swba
);
311 spin_lock_bh(&priv
->beacon_lock
);
312 if (priv
->beacon
.bslot
[slot
] == NULL
) {
313 spin_unlock_bh(&priv
->beacon_lock
);
316 spin_unlock_bh(&priv
->beacon_lock
);
318 ath9k_htc_send_buffered(priv
, slot
);
319 ath9k_htc_send_beacon(priv
, slot
);
322 void ath9k_htc_assign_bslot(struct ath9k_htc_priv
*priv
,
323 struct ieee80211_vif
*vif
)
325 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
326 struct ath9k_htc_vif
*avp
= (struct ath9k_htc_vif
*)vif
->drv_priv
;
329 spin_lock_bh(&priv
->beacon_lock
);
330 for (i
= 0; i
< ATH9K_HTC_MAX_BCN_VIF
; i
++) {
331 if (priv
->beacon
.bslot
[i
] == NULL
) {
337 priv
->beacon
.bslot
[avp
->bslot
] = vif
;
338 spin_unlock_bh(&priv
->beacon_lock
);
340 ath_dbg(common
, CONFIG
, "Added interface at beacon slot: %d\n",
344 void ath9k_htc_remove_bslot(struct ath9k_htc_priv
*priv
,
345 struct ieee80211_vif
*vif
)
347 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
348 struct ath9k_htc_vif
*avp
= (struct ath9k_htc_vif
*)vif
->drv_priv
;
350 spin_lock_bh(&priv
->beacon_lock
);
351 priv
->beacon
.bslot
[avp
->bslot
] = NULL
;
352 spin_unlock_bh(&priv
->beacon_lock
);
354 ath_dbg(common
, CONFIG
, "Removed interface at beacon slot: %d\n",
359 * Calculate the TSF adjustment value for all slots
362 void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv
*priv
,
363 struct ieee80211_vif
*vif
)
365 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
366 struct ath9k_htc_vif
*avp
= (struct ath9k_htc_vif
*)vif
->drv_priv
;
367 struct ath_beacon_config
*cur_conf
= &priv
->cur_beacon_conf
;
374 * The beacon interval cannot be different for multi-AP mode,
375 * and we reach here only for VIF slots greater than zero,
376 * so beacon_interval is guaranteed to be set in cur_conf.
378 tsfadjust
= cur_conf
->beacon_interval
* avp
->bslot
/ ATH9K_HTC_MAX_BCN_VIF
;
379 avp
->tsfadjust
= cpu_to_le64(TU_TO_USEC(tsfadjust
));
381 ath_dbg(common
, CONFIG
, "tsfadjust is: %llu for bslot: %d\n",
382 (unsigned long long)tsfadjust
, avp
->bslot
);
385 static void ath9k_htc_beacon_iter(void *data
, u8
*mac
, struct ieee80211_vif
*vif
)
387 bool *beacon_configured
= data
;
388 struct ath9k_htc_vif
*avp
= (struct ath9k_htc_vif
*) vif
->drv_priv
;
390 if (vif
->type
== NL80211_IFTYPE_STATION
&&
391 avp
->beacon_configured
)
392 *beacon_configured
= true;
395 static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv
*priv
,
396 struct ieee80211_vif
*vif
)
398 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
399 struct ath_beacon_config
*cur_conf
= &priv
->cur_beacon_conf
;
400 struct ieee80211_bss_conf
*bss_conf
= &vif
->bss_conf
;
401 bool beacon_configured
;
404 * Changing the beacon interval when multiple AP interfaces
405 * are configured will affect beacon transmission of all
408 if ((priv
->ah
->opmode
== NL80211_IFTYPE_AP
) &&
409 (priv
->num_ap_vif
> 1) &&
410 (vif
->type
== NL80211_IFTYPE_AP
) &&
411 (cur_conf
->beacon_interval
!= bss_conf
->beacon_int
)) {
412 ath_dbg(common
, CONFIG
,
413 "Changing beacon interval of multiple AP interfaces !\n");
418 * If the HW is operating in AP mode, any new station interfaces that
419 * are added cannot change the beacon parameters.
421 if (priv
->num_ap_vif
&&
422 (vif
->type
!= NL80211_IFTYPE_AP
)) {
423 ath_dbg(common
, CONFIG
,
424 "HW in AP mode, cannot set STA beacon parameters\n");
429 * The beacon parameters are configured only for the first
432 if ((priv
->ah
->opmode
== NL80211_IFTYPE_STATION
) &&
433 (priv
->num_sta_vif
> 1) &&
434 (vif
->type
== NL80211_IFTYPE_STATION
)) {
435 beacon_configured
= false;
436 ieee80211_iterate_active_interfaces_atomic(
437 priv
->hw
, IEEE80211_IFACE_ITER_RESUME_ALL
,
438 ath9k_htc_beacon_iter
, &beacon_configured
);
440 if (beacon_configured
) {
441 ath_dbg(common
, CONFIG
,
442 "Beacon already configured for a station interface\n");
450 void ath9k_htc_beacon_config(struct ath9k_htc_priv
*priv
,
451 struct ieee80211_vif
*vif
)
453 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
454 struct ath_beacon_config
*cur_conf
= &priv
->cur_beacon_conf
;
455 struct ieee80211_bss_conf
*bss_conf
= &vif
->bss_conf
;
456 struct ath9k_htc_vif
*avp
= (struct ath9k_htc_vif
*) vif
->drv_priv
;
458 if (!ath9k_htc_check_beacon_config(priv
, vif
))
461 cur_conf
->beacon_interval
= bss_conf
->beacon_int
;
462 if (cur_conf
->beacon_interval
== 0)
463 cur_conf
->beacon_interval
= 100;
465 cur_conf
->dtim_period
= bss_conf
->dtim_period
;
466 cur_conf
->bmiss_timeout
=
467 ATH_DEFAULT_BMISS_LIMIT
* cur_conf
->beacon_interval
;
470 case NL80211_IFTYPE_STATION
:
471 ath9k_htc_beacon_config_sta(priv
, cur_conf
);
472 avp
->beacon_configured
= true;
474 case NL80211_IFTYPE_ADHOC
:
475 ath9k_htc_beacon_config_adhoc(priv
, cur_conf
);
477 case NL80211_IFTYPE_MESH_POINT
:
478 case NL80211_IFTYPE_AP
:
479 ath9k_htc_beacon_config_ap(priv
, cur_conf
);
482 ath_dbg(common
, CONFIG
, "Unsupported beaconing mode\n");
487 void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv
*priv
)
489 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
490 struct ath_beacon_config
*cur_conf
= &priv
->cur_beacon_conf
;
492 switch (priv
->ah
->opmode
) {
493 case NL80211_IFTYPE_STATION
:
494 ath9k_htc_beacon_config_sta(priv
, cur_conf
);
496 case NL80211_IFTYPE_ADHOC
:
497 ath9k_htc_beacon_config_adhoc(priv
, cur_conf
);
499 case NL80211_IFTYPE_MESH_POINT
:
500 case NL80211_IFTYPE_AP
:
501 ath9k_htc_beacon_config_ap(priv
, cur_conf
);
504 ath_dbg(common
, CONFIG
, "Unsupported beaconing mode\n");
509 bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv
*priv
)
511 struct ieee80211_vif
*vif
;
514 if (!vif
|| !vif
->csa_active
)
517 if (!ieee80211_csa_is_complete(vif
))
520 ieee80211_csa_finish(vif
);
522 priv
->csa_vif
= NULL
;