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>
This commit is contained in:
parent
7d05786931
commit
f84f7d78bb
@ -1192,6 +1192,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
|
|||||||
wl->flags = 0;
|
wl->flags = 0;
|
||||||
wl->vif = NULL;
|
wl->vif = NULL;
|
||||||
wl->filters = 0;
|
wl->filters = 0;
|
||||||
|
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
|
||||||
|
|
||||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||||
wl->tx_blocks_freed[i] = 0;
|
wl->tx_blocks_freed[i] = 0;
|
||||||
@ -2401,6 +2402,113 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wl1271_allocate_hlid(struct wl1271 *wl,
|
||||||
|
struct ieee80211_sta *sta,
|
||||||
|
u8 *hlid)
|
||||||
|
{
|
||||||
|
struct wl1271_station *wl_sta;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS);
|
||||||
|
if (id >= AP_MAX_STATIONS) {
|
||||||
|
wl1271_warning("could not allocate HLID - too much stations");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||||
|
|
||||||
|
__set_bit(id, wl->ap_hlid_map);
|
||||||
|
wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
|
||||||
|
*hlid = wl_sta->hlid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid)
|
||||||
|
{
|
||||||
|
int id = hlid - WL1271_AP_STA_HLID_START;
|
||||||
|
|
||||||
|
__clear_bit(id, wl->ap_hlid_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
struct wl1271 *wl = hw->priv;
|
||||||
|
int ret = 0;
|
||||||
|
u8 hlid;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
|
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (wl->bss_type != BSS_TYPE_AP_BSS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
|
||||||
|
|
||||||
|
ret = wl1271_allocate_hlid(wl, sta, &hlid);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = wl1271_ps_elp_wakeup(wl, false);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = wl1271_cmd_add_sta(wl, sta, hlid);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out_sleep;
|
||||||
|
|
||||||
|
out_sleep:
|
||||||
|
wl1271_ps_elp_sleep(wl);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
struct wl1271 *wl = hw->priv;
|
||||||
|
struct wl1271_station *wl_sta;
|
||||||
|
int ret = 0, id;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
|
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (wl->bss_type != BSS_TYPE_AP_BSS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
|
||||||
|
|
||||||
|
wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||||
|
id = wl_sta->hlid - WL1271_AP_STA_HLID_START;
|
||||||
|
if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = wl1271_ps_elp_wakeup(wl, false);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out_sleep;
|
||||||
|
|
||||||
|
wl1271_free_hlid(wl, wl_sta->hlid);
|
||||||
|
|
||||||
|
out_sleep:
|
||||||
|
wl1271_ps_elp_sleep(wl);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* can't be const, mac80211 writes to this */
|
/* can't be const, mac80211 writes to this */
|
||||||
static struct ieee80211_rate wl1271_rates[] = {
|
static struct ieee80211_rate wl1271_rates[] = {
|
||||||
{ .bitrate = 10,
|
{ .bitrate = 10,
|
||||||
@ -2647,6 +2755,8 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||||||
.conf_tx = wl1271_op_conf_tx,
|
.conf_tx = wl1271_op_conf_tx,
|
||||||
.get_tsf = wl1271_op_get_tsf,
|
.get_tsf = wl1271_op_get_tsf,
|
||||||
.get_survey = wl1271_op_get_survey,
|
.get_survey = wl1271_op_get_survey,
|
||||||
|
.sta_add = wl1271_op_sta_add,
|
||||||
|
.sta_remove = wl1271_op_sta_remove,
|
||||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2840,6 +2950,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
|
|||||||
|
|
||||||
SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
|
SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
|
||||||
|
|
||||||
|
wl->hw->sta_data_size = sizeof(struct wl1271_station);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
|
EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
|
||||||
|
@ -435,6 +435,13 @@ struct wl1271 {
|
|||||||
|
|
||||||
/* Most recently reported noise in dBm */
|
/* Most recently reported noise in dBm */
|
||||||
s8 noise;
|
s8 noise;
|
||||||
|
|
||||||
|
/* map for HLIDs of associated stations - when operating in AP mode */
|
||||||
|
unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wl1271_station {
|
||||||
|
u8 hlid;
|
||||||
};
|
};
|
||||||
|
|
||||||
int wl1271_plt_start(struct wl1271 *wl);
|
int wl1271_plt_start(struct wl1271 *wl);
|
||||||
|
Loading…
Reference in New Issue
Block a user