diff options
author | Arik Nemtsov <arik@wizery.com> | 2010-10-16 14:21:23 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-01-24 15:11:49 -0500 |
commit | f84f7d78bbfbbb17faa64bcca5799865074e1e7b (patch) | |
tree | 2d11a9799f527b39b7617f0a3c06a35aff97e30c | |
parent | 7d0578693107887d52d50b89723be7fa0a41cd36 (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.c | 112 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 7 |
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 | ||
2405 | static 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 | |||
2426 | static 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 | |||
2433 | static 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 | |||
2463 | out_sleep: | ||
2464 | wl1271_ps_elp_sleep(wl); | ||
2465 | |||
2466 | out: | ||
2467 | mutex_unlock(&wl->mutex); | ||
2468 | return ret; | ||
2469 | } | ||
2470 | |||
2471 | static 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 | |||
2504 | out_sleep: | ||
2505 | wl1271_ps_elp_sleep(wl); | ||
2506 | |||
2507 | out: | ||
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 */ |
2405 | static struct ieee80211_rate wl1271_rates[] = { | 2513 | static 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 | } |
2845 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | 2957 | EXPORT_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 | |||
443 | struct wl1271_station { | ||
444 | u8 hlid; | ||
438 | }; | 445 | }; |
439 | 446 | ||
440 | int wl1271_plt_start(struct wl1271 *wl); | 447 | int wl1271_plt_start(struct wl1271 *wl); |