aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2010-10-16 14:21:23 -0400
committerLuciano Coelho <coelho@ti.com>2011-01-24 15:11:49 -0500
commitf84f7d78bbfbbb17faa64bcca5799865074e1e7b (patch)
tree2d11a9799f527b39b7617f0a3c06a35aff97e30c
parent7d0578693107887d52d50b89723be7fa0a41cd36 (diff)
wl12xx: AP mode - add STA add/remove ops
Allocate and free host link IDs (HLIDs) for each link. A per-STA data structure keeps the HLID of each STA. Signed-off-by: Arik Nemtsov <arik@wizery.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/wl12xx/main.c112
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h7
2 files changed, 119 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 8e5d435f63f7..739fee640528 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1192,6 +1192,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
1192 wl->flags = 0; 1192 wl->flags = 0;
1193 wl->vif = NULL; 1193 wl->vif = NULL;
1194 wl->filters = 0; 1194 wl->filters = 0;
1195 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
1195 1196
1196 for (i = 0; i < NUM_TX_QUEUES; i++) 1197 for (i = 0; i < NUM_TX_QUEUES; i++)
1197 wl->tx_blocks_freed[i] = 0; 1198 wl->tx_blocks_freed[i] = 0;
@@ -2401,6 +2402,113 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
2401 return 0; 2402 return 0;
2402} 2403}
2403 2404
2405static int wl1271_allocate_hlid(struct wl1271 *wl,
2406 struct ieee80211_sta *sta,
2407 u8 *hlid)
2408{
2409 struct wl1271_station *wl_sta;
2410 int id;
2411
2412 id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS);
2413 if (id >= AP_MAX_STATIONS) {
2414 wl1271_warning("could not allocate HLID - too much stations");
2415 return -EBUSY;
2416 }
2417
2418 wl_sta = (struct wl1271_station *)sta->drv_priv;
2419
2420 __set_bit(id, wl->ap_hlid_map);
2421 wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
2422 *hlid = wl_sta->hlid;
2423 return 0;
2424}
2425
2426static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid)
2427{
2428 int id = hlid - WL1271_AP_STA_HLID_START;
2429
2430 __clear_bit(id, wl->ap_hlid_map);
2431}
2432
2433static int wl1271_op_sta_add(struct ieee80211_hw *hw,
2434 struct ieee80211_vif *vif,
2435 struct ieee80211_sta *sta)
2436{
2437 struct wl1271 *wl = hw->priv;
2438 int ret = 0;
2439 u8 hlid;
2440
2441 mutex_lock(&wl->mutex);
2442
2443 if (unlikely(wl->state == WL1271_STATE_OFF))
2444 goto out;
2445
2446 if (wl->bss_type != BSS_TYPE_AP_BSS)
2447 goto out;
2448
2449 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
2450
2451 ret = wl1271_allocate_hlid(wl, sta, &hlid);
2452 if (ret < 0)
2453 goto out;
2454
2455 ret = wl1271_ps_elp_wakeup(wl, false);
2456 if (ret < 0)
2457 goto out;
2458
2459 ret = wl1271_cmd_add_sta(wl, sta, hlid);
2460 if (ret < 0)
2461 goto out_sleep;
2462
2463out_sleep:
2464 wl1271_ps_elp_sleep(wl);
2465
2466out:
2467 mutex_unlock(&wl->mutex);
2468 return ret;
2469}
2470
2471static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
2472 struct ieee80211_vif *vif,
2473 struct ieee80211_sta *sta)
2474{
2475 struct wl1271 *wl = hw->priv;
2476 struct wl1271_station *wl_sta;
2477 int ret = 0, id;
2478
2479 mutex_lock(&wl->mutex);
2480
2481 if (unlikely(wl->state == WL1271_STATE_OFF))
2482 goto out;
2483
2484 if (wl->bss_type != BSS_TYPE_AP_BSS)
2485 goto out;
2486
2487 wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
2488
2489 wl_sta = (struct wl1271_station *)sta->drv_priv;
2490 id = wl_sta->hlid - WL1271_AP_STA_HLID_START;
2491 if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
2492 goto out;
2493
2494 ret = wl1271_ps_elp_wakeup(wl, false);
2495 if (ret < 0)
2496 goto out;
2497
2498 ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
2499 if (ret < 0)
2500 goto out_sleep;
2501
2502 wl1271_free_hlid(wl, wl_sta->hlid);
2503
2504out_sleep:
2505 wl1271_ps_elp_sleep(wl);
2506
2507out:
2508 mutex_unlock(&wl->mutex);
2509 return ret;
2510}
2511
2404/* can't be const, mac80211 writes to this */ 2512/* can't be const, mac80211 writes to this */
2405static struct ieee80211_rate wl1271_rates[] = { 2513static struct ieee80211_rate wl1271_rates[] = {
2406 { .bitrate = 10, 2514 { .bitrate = 10,
@@ -2647,6 +2755,8 @@ static const struct ieee80211_ops wl1271_ops = {
2647 .conf_tx = wl1271_op_conf_tx, 2755 .conf_tx = wl1271_op_conf_tx,
2648 .get_tsf = wl1271_op_get_tsf, 2756 .get_tsf = wl1271_op_get_tsf,
2649 .get_survey = wl1271_op_get_survey, 2757 .get_survey = wl1271_op_get_survey,
2758 .sta_add = wl1271_op_sta_add,
2759 .sta_remove = wl1271_op_sta_remove,
2650 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 2760 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
2651}; 2761};
2652 2762
@@ -2840,6 +2950,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
2840 2950
2841 SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); 2951 SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
2842 2952
2953 wl->hw->sta_data_size = sizeof(struct wl1271_station);
2954
2843 return 0; 2955 return 0;
2844} 2956}
2845EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); 2957EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 981bb020e535..a87ef8e3cac7 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -435,6 +435,13 @@ struct wl1271 {
435 435
436 /* Most recently reported noise in dBm */ 436 /* Most recently reported noise in dBm */
437 s8 noise; 437 s8 noise;
438
439 /* map for HLIDs of associated stations - when operating in AP mode */
440 unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
441};
442
443struct wl1271_station {
444 u8 hlid;
438}; 445};
439 446
440int wl1271_plt_start(struct wl1271 *wl); 447int wl1271_plt_start(struct wl1271 *wl);