aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-02-20 21:19:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-23 16:25:28 -0500
commita5fae37d118bb633708b2787e53871e38bf3b15e (patch)
treed09d61f5dce40c260dbd54dfb968de9671b26e3f /drivers/net
parenta236254c35f04a4d47c701ed3ec4a0b5dcb097b0 (diff)
ath9k_htc: Configure beacon timers in AP mode
Handle multi-interface situations by checking if AP interfaces are already present. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c78
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c45
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c4
4 files changed, 115 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 5b0a21a1427..e9c51cae88a 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -352,10 +352,8 @@ struct ath_led {
352 352
353struct htc_beacon_config { 353struct htc_beacon_config {
354 u16 beacon_interval; 354 u16 beacon_interval;
355 u16 listen_interval;
356 u16 dtim_period; 355 u16 dtim_period;
357 u16 bmiss_timeout; 356 u16 bmiss_timeout;
358 u8 dtim_count;
359}; 357};
360 358
361struct ath_btcoex { 359struct ath_btcoex {
@@ -380,6 +378,7 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
380#define OP_BT_PRIORITY_DETECTED BIT(6) 378#define OP_BT_PRIORITY_DETECTED BIT(6)
381#define OP_BT_SCAN BIT(7) 379#define OP_BT_SCAN BIT(7)
382#define OP_ANI_RUNNING BIT(8) 380#define OP_ANI_RUNNING BIT(8)
381#define OP_TSF_RESET BIT(9)
383 382
384struct ath9k_htc_priv { 383struct ath9k_htc_priv {
385 struct device *dev; 384 struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index bbbdd60bcb3..e897a56695b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -138,6 +138,51 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
138 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); 138 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
139} 139}
140 140
141static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
142 struct htc_beacon_config *bss_conf)
143{
144 struct ath_common *common = ath9k_hw_common(priv->ah);
145 enum ath9k_int imask = 0;
146 u32 nexttbtt, intval, tsftu;
147 __be32 htc_imask = 0;
148 int ret;
149 u8 cmd_rsp;
150 u64 tsf;
151
152 intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
153 intval /= ATH9K_HTC_MAX_BCN_VIF;
154 nexttbtt = intval;
155
156 if (priv->op_flags & OP_TSF_RESET) {
157 intval |= ATH9K_BEACON_RESET_TSF;
158 priv->op_flags &= ~OP_TSF_RESET;
159 } else {
160 /*
161 * Pull nexttbtt forward to reflect the current TSF.
162 */
163 tsf = ath9k_hw_gettsf64(priv->ah);
164 tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
165 do {
166 nexttbtt += intval;
167 } while (nexttbtt < tsftu);
168 }
169
170 intval |= ATH9K_BEACON_ENA;
171
172 if (priv->op_flags & OP_ENABLE_BEACON)
173 imask |= ATH9K_INT_SWBA;
174
175 ath_dbg(common, ATH_DBG_CONFIG,
176 "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
177 bss_conf->beacon_interval, nexttbtt, imask);
178
179 WMI_CMD(WMI_DISABLE_INTR_CMDID);
180 ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
181 priv->bmiss_cnt = 0;
182 htc_imask = cpu_to_be32(imask);
183 WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
184}
185
141static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, 186static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
142 struct htc_beacon_config *bss_conf) 187 struct htc_beacon_config *bss_conf)
143{ 188{
@@ -260,13 +305,36 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
260 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; 305 struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
261 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 306 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
262 307
308 /*
309 * Changing the beacon interval when multiple AP interfaces
310 * are configured will affect beacon transmission of all
311 * of them.
312 */
313 if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
314 (priv->num_ap_vif > 1) &&
315 (vif->type == NL80211_IFTYPE_AP) &&
316 (cur_conf->beacon_interval != bss_conf->beacon_int)) {
317 ath_dbg(common, ATH_DBG_CONFIG,
318 "Changing beacon interval of multiple AP interfaces !\n");
319 return;
320 }
321
322 /*
323 * If the HW is operating in AP mode, any new station interfaces that
324 * are added cannot change the beacon parameters.
325 */
326 if (priv->num_ap_vif &&
327 (vif->type != NL80211_IFTYPE_AP)) {
328 ath_dbg(common, ATH_DBG_CONFIG,
329 "HW in AP mode, cannot set STA beacon parameters\n");
330 return;
331 }
332
263 cur_conf->beacon_interval = bss_conf->beacon_int; 333 cur_conf->beacon_interval = bss_conf->beacon_int;
264 if (cur_conf->beacon_interval == 0) 334 if (cur_conf->beacon_interval == 0)
265 cur_conf->beacon_interval = 100; 335 cur_conf->beacon_interval = 100;
266 336
267 cur_conf->dtim_period = bss_conf->dtim_period; 337 cur_conf->dtim_period = bss_conf->dtim_period;
268 cur_conf->listen_interval = 1;
269 cur_conf->dtim_count = 1;
270 cur_conf->bmiss_timeout = 338 cur_conf->bmiss_timeout =
271 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; 339 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
272 340
@@ -277,6 +345,9 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
277 case NL80211_IFTYPE_ADHOC: 345 case NL80211_IFTYPE_ADHOC:
278 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 346 ath9k_htc_beacon_config_adhoc(priv, cur_conf);
279 break; 347 break;
348 case NL80211_IFTYPE_AP:
349 ath9k_htc_beacon_config_ap(priv, cur_conf);
350 break;
280 default: 351 default:
281 ath_dbg(common, ATH_DBG_CONFIG, 352 ath_dbg(common, ATH_DBG_CONFIG,
282 "Unsupported beaconing mode\n"); 353 "Unsupported beaconing mode\n");
@@ -296,6 +367,9 @@ void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
296 case NL80211_IFTYPE_ADHOC: 367 case NL80211_IFTYPE_ADHOC:
297 ath9k_htc_beacon_config_adhoc(priv, cur_conf); 368 ath9k_htc_beacon_config_adhoc(priv, cur_conf);
298 break; 369 break;
370 case NL80211_IFTYPE_AP:
371 ath9k_htc_beacon_config_ap(priv, cur_conf);
372 break;
299 default: 373 default:
300 ath_dbg(common, ATH_DBG_CONFIG, 374 ath_dbg(common, ATH_DBG_CONFIG,
301 "Unsupported beaconing mode\n"); 375 "Unsupported beaconing mode\n");
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index f384b358b48..7367d6c1c64 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -110,6 +110,9 @@ static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
110 struct ath9k_htc_priv *priv = data; 110 struct ath9k_htc_priv *priv = data;
111 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 111 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
112 112
113 if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon)
114 priv->reconfig_beacon = true;
115
113 if (bss_conf->assoc) { 116 if (bss_conf->assoc) {
114 priv->rearm_ani = true; 117 priv->rearm_ani = true;
115 priv->reconfig_beacon = true; 118 priv->reconfig_beacon = true;
@@ -288,6 +291,11 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
288 goto err; 291 goto err;
289 292
290 htc_start(priv->htc); 293 htc_start(priv->htc);
294
295 if (!(priv->op_flags & OP_SCANNING) &&
296 !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
297 ath9k_htc_vif_reconfig(priv);
298
291err: 299err:
292 ath9k_htc_ps_restore(priv); 300 ath9k_htc_ps_restore(priv);
293 return ret; 301 return ret;
@@ -1620,17 +1628,40 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1620 common->curbssid, common->curaid); 1628 common->curbssid, common->curaid);
1621 } 1629 }
1622 1630
1623 if ((changed & BSS_CHANGED_BEACON_INT) || 1631 if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
1624 (changed & BSS_CHANGED_BEACON) || 1632 ath_dbg(common, ATH_DBG_CONFIG,
1625 ((changed & BSS_CHANGED_BEACON_ENABLED) && 1633 "Beacon enabled for BSS: %pM\n", bss_conf->bssid);
1626 bss_conf->enable_beacon)) {
1627 priv->op_flags |= OP_ENABLE_BEACON; 1634 priv->op_flags |= OP_ENABLE_BEACON;
1628 ath9k_htc_beacon_config(priv, vif); 1635 ath9k_htc_beacon_config(priv, vif);
1629 } 1636 }
1630 1637
1631 if ((changed & BSS_CHANGED_BEACON_ENABLED) && 1638 if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) {
1632 !bss_conf->enable_beacon) { 1639 /*
1633 priv->op_flags &= ~OP_ENABLE_BEACON; 1640 * Disable SWBA interrupt only if there are no
1641 * AP/IBSS interfaces.
1642 */
1643 if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) {
1644 ath_dbg(common, ATH_DBG_CONFIG,
1645 "Beacon disabled for BSS: %pM\n",
1646 bss_conf->bssid);
1647 priv->op_flags &= ~OP_ENABLE_BEACON;
1648 ath9k_htc_beacon_config(priv, vif);
1649 }
1650 }
1651
1652 if (changed & BSS_CHANGED_BEACON_INT) {
1653 /*
1654 * Reset the HW TSF for the first AP interface.
1655 */
1656 if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
1657 (priv->nvifs == 1) &&
1658 (priv->num_ap_vif == 1) &&
1659 (vif->type == NL80211_IFTYPE_AP)) {
1660 priv->op_flags |= OP_TSF_RESET;
1661 }
1662 ath_dbg(common, ATH_DBG_CONFIG,
1663 "Beacon interval changed for BSS: %pM\n",
1664 bss_conf->bssid);
1634 ath9k_htc_beacon_config(priv, vif); 1665 ath9k_htc_beacon_config(priv, vif);
1635 } 1666 }
1636 1667
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index dc862f5e116..d3d24904f62 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -123,12 +123,8 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
123void ath9k_swba_tasklet(unsigned long data) 123void ath9k_swba_tasklet(unsigned long data)
124{ 124{
125 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; 125 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
126 struct ath_common *common = ath9k_hw_common(priv->ah);
127
128 ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n");
129 126
130 ath9k_htc_swba(priv, priv->wmi->beacon_pending); 127 ath9k_htc_swba(priv, priv->wmi->beacon_pending);
131
132} 128}
133 129
134void ath9k_fatal_work(struct work_struct *work) 130void ath9k_fatal_work(struct work_struct *work)