aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-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,