aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2012-03-04 03:55:47 -0500
committerLuciano Coelho <coelho@ti.com>2012-03-05 08:45:24 -0500
commit2d6cf2b51fa3492c479c6d1f86496e120b51e1d8 (patch)
tree9d2405fafadf1f86236c7c50da009bf06830a840 /drivers/net/wireless/wl12xx
parent8a6a84a471f7de1845174d1dd66b35074d9d9398 (diff)
wl12xx: implement sta_state callback
Implement sta_state callback instead of the sta_add/remove callbacks. Update the fw regarding peer state and ht caps only after the station was authorized. Otherwise, the fw might try establishing BA session before the sta is authorized. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/main.c137
1 files changed, 82 insertions, 55 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index b771106c0a1..8569ac3760d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -4233,100 +4233,128 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
4233 wl->active_sta_count--; 4233 wl->active_sta_count--;
4234} 4234}
4235 4235
4236static int wl1271_op_sta_add(struct ieee80211_hw *hw, 4236static int wl12xx_sta_add(struct wl1271 *wl,
4237 struct ieee80211_vif *vif, 4237 struct wl12xx_vif *wlvif,
4238 struct ieee80211_sta *sta) 4238 struct ieee80211_sta *sta)
4239{ 4239{
4240 struct wl1271 *wl = hw->priv;
4241 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
4242 struct wl1271_station *wl_sta; 4240 struct wl1271_station *wl_sta;
4243 int ret = 0; 4241 int ret = 0;
4244 u8 hlid; 4242 u8 hlid;
4245 4243
4246 mutex_lock(&wl->mutex);
4247
4248 if (unlikely(wl->state == WL1271_STATE_OFF))
4249 goto out;
4250
4251 if (wlvif->bss_type != BSS_TYPE_AP_BSS)
4252 goto out;
4253
4254 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); 4244 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
4255 4245
4256 ret = wl1271_allocate_sta(wl, wlvif, sta); 4246 ret = wl1271_allocate_sta(wl, wlvif, sta);
4257 if (ret < 0) 4247 if (ret < 0)
4258 goto out; 4248 return ret;
4259 4249
4260 wl_sta = (struct wl1271_station *)sta->drv_priv; 4250 wl_sta = (struct wl1271_station *)sta->drv_priv;
4261 hlid = wl_sta->hlid; 4251 hlid = wl_sta->hlid;
4262 4252
4263 ret = wl1271_ps_elp_wakeup(wl);
4264 if (ret < 0)
4265 goto out_free_sta;
4266
4267 ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid); 4253 ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
4268 if (ret < 0) 4254 if (ret < 0)
4269 goto out_sleep; 4255 wl1271_free_sta(wl, wlvif, hlid);
4270 4256
4271 ret = wl12xx_cmd_set_peer_state(wl, hlid); 4257 return ret;
4272 if (ret < 0) 4258}
4273 goto out_sleep;
4274 4259
4275 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid); 4260static int wl12xx_sta_remove(struct wl1271 *wl,
4276 if (ret < 0) 4261 struct wl12xx_vif *wlvif,
4277 goto out_sleep; 4262 struct ieee80211_sta *sta)
4263{
4264 struct wl1271_station *wl_sta;
4265 int ret = 0, id;
4278 4266
4279out_sleep: 4267 wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
4280 wl1271_ps_elp_sleep(wl); 4268
4269 wl_sta = (struct wl1271_station *)sta->drv_priv;
4270 id = wl_sta->hlid;
4271 if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
4272 return -EINVAL;
4281 4273
4282out_free_sta: 4274 ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
4283 if (ret < 0) 4275 if (ret < 0)
4284 wl1271_free_sta(wl, wlvif, hlid); 4276 return ret;
4285 4277
4286out: 4278 wl1271_free_sta(wl, wlvif, wl_sta->hlid);
4287 mutex_unlock(&wl->mutex);
4288 return ret; 4279 return ret;
4289} 4280}
4290 4281
4291static int wl1271_op_sta_remove(struct ieee80211_hw *hw, 4282static int wl12xx_update_sta_state(struct wl1271 *wl,
4292 struct ieee80211_vif *vif, 4283 struct wl12xx_vif *wlvif,
4293 struct ieee80211_sta *sta) 4284 struct ieee80211_sta *sta,
4285 enum ieee80211_sta_state old_state,
4286 enum ieee80211_sta_state new_state)
4294{ 4287{
4295 struct wl1271 *wl = hw->priv;
4296 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
4297 struct wl1271_station *wl_sta; 4288 struct wl1271_station *wl_sta;
4298 int ret = 0, id; 4289 u8 hlid;
4290 bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS;
4291 bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS;
4292 int ret;
4299 4293
4300 mutex_lock(&wl->mutex); 4294 wl_sta = (struct wl1271_station *)sta->drv_priv;
4295 hlid = wl_sta->hlid;
4301 4296
4302 if (unlikely(wl->state == WL1271_STATE_OFF)) 4297 /* Add station (AP mode) */
4303 goto out; 4298 if (is_ap &&
4299 old_state == IEEE80211_STA_NOTEXIST &&
4300 new_state == IEEE80211_STA_NONE)
4301 return wl12xx_sta_add(wl, wlvif, sta);
4302
4303 /* Remove station (AP mode) */
4304 if (is_ap &&
4305 old_state == IEEE80211_STA_NONE &&
4306 new_state == IEEE80211_STA_NOTEXIST) {
4307 /* must not fail */
4308 wl12xx_sta_remove(wl, wlvif, sta);
4309 return 0;
4310 }
4304 4311
4305 if (wlvif->bss_type != BSS_TYPE_AP_BSS) 4312 /* Authorize station (AP mode) */
4306 goto out; 4313 if (is_ap &&
4314 new_state == IEEE80211_STA_AUTHORIZED) {
4315 ret = wl12xx_cmd_set_peer_state(wl, hlid);
4316 if (ret < 0)
4317 return ret;
4307 4318
4308 wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); 4319 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true,
4320 hlid);
4321 return ret;
4322 }
4309 4323
4310 wl_sta = (struct wl1271_station *)sta->drv_priv; 4324 return 0;
4311 id = wl_sta->hlid; 4325}
4312 if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) 4326
4327static int wl12xx_op_sta_state(struct ieee80211_hw *hw,
4328 struct ieee80211_vif *vif,
4329 struct ieee80211_sta *sta,
4330 enum ieee80211_sta_state old_state,
4331 enum ieee80211_sta_state new_state)
4332{
4333 struct wl1271 *wl = hw->priv;
4334 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
4335 int ret;
4336
4337 wl1271_debug(DEBUG_MAC80211, "mac80211 sta %d state=%d->%d",
4338 sta->aid, old_state, new_state);
4339
4340 mutex_lock(&wl->mutex);
4341
4342 if (unlikely(wl->state == WL1271_STATE_OFF)) {
4343 ret = -EBUSY;
4313 goto out; 4344 goto out;
4345 }
4314 4346
4315 ret = wl1271_ps_elp_wakeup(wl); 4347 ret = wl1271_ps_elp_wakeup(wl);
4316 if (ret < 0) 4348 if (ret < 0)
4317 goto out; 4349 goto out;
4318 4350
4319 ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); 4351 ret = wl12xx_update_sta_state(wl, wlvif, sta, old_state, new_state);
4320 if (ret < 0)
4321 goto out_sleep;
4322 4352
4323 wl1271_free_sta(wl, wlvif, wl_sta->hlid);
4324
4325out_sleep:
4326 wl1271_ps_elp_sleep(wl); 4353 wl1271_ps_elp_sleep(wl);
4327
4328out: 4354out:
4329 mutex_unlock(&wl->mutex); 4355 mutex_unlock(&wl->mutex);
4356 if (new_state < old_state)
4357 return 0;
4330 return ret; 4358 return ret;
4331} 4359}
4332 4360
@@ -4795,8 +4823,7 @@ static const struct ieee80211_ops wl1271_ops = {
4795 .conf_tx = wl1271_op_conf_tx, 4823 .conf_tx = wl1271_op_conf_tx,
4796 .get_tsf = wl1271_op_get_tsf, 4824 .get_tsf = wl1271_op_get_tsf,
4797 .get_survey = wl1271_op_get_survey, 4825 .get_survey = wl1271_op_get_survey,
4798 .sta_add = wl1271_op_sta_add, 4826 .sta_state = wl12xx_op_sta_state,
4799 .sta_remove = wl1271_op_sta_remove,
4800 .ampdu_action = wl1271_op_ampdu_action, 4827 .ampdu_action = wl1271_op_ampdu_action,
4801 .tx_frames_pending = wl1271_tx_frames_pending, 4828 .tx_frames_pending = wl1271_tx_frames_pending,
4802 .set_bitrate_mask = wl12xx_set_bitrate_mask, 4829 .set_bitrate_mask = wl12xx_set_bitrate_mask,