diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-02-20 21:19:53 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-02-23 16:25:28 -0500 |
commit | a5fae37d118bb633708b2787e53871e38bf3b15e (patch) | |
tree | d09d61f5dce40c260dbd54dfb968de9671b26e3f /drivers/net/wireless/ath | |
parent | a236254c35f04a4d47c701ed3ec4a0b5dcb097b0 (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/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 78 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/wmi.c | 4 |
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 5b0a21a14279..e9c51cae88ab 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 | ||
353 | struct htc_beacon_config { | 353 | struct 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 | ||
361 | struct ath_btcoex { | 359 | struct 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 | ||
384 | struct ath9k_htc_priv { | 383 | struct 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 bbbdd60bcb3e..e897a56695b2 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 | ||
141 | static 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 | |||
141 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | 186 | static 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 f384b358b48d..7367d6c1c649 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 | |||
291 | err: | 299 | err: |
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 dc862f5e1162..d3d24904f62f 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) | |||
123 | void ath9k_swba_tasklet(unsigned long data) | 123 | void 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 | ||
134 | void ath9k_fatal_work(struct work_struct *work) | 130 | void ath9k_fatal_work(struct work_struct *work) |