@@ -103,11 +103,9 @@ static int wfx_drop_encrypt_data(struct wfx_dev *wdev,
void wfx_rx_cb(struct wfx_vif *wvif,
const struct hif_ind_rx *arg, struct sk_buff *skb)
{
- int link_id = arg->rx_flags.peer_sta_id;
struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- struct wfx_link_entry *entry = NULL;
memset(hdr, 0, sizeof(*hdr));
@@ -117,11 +115,6 @@ void wfx_rx_cb(struct wfx_vif *wvif,
ieee80211_is_beacon(frame->frame_control)))
goto drop;
- if (link_id && link_id <= WFX_MAX_STA_IN_AP_MODE) {
- entry = &wvif->link_id_db[link_id - 1];
- entry->timestamp = jiffies;
- }
-
if (arg->status == HIF_STATUS_MICFAILURE)
hdr->flag |= RX_FLAG_MMIC_ERROR;
else if (arg->status)
@@ -17,7 +17,6 @@
#include "hif_tx_mib.h"
#define WFX_INVALID_RATE_ID 15
-#define WFX_LINK_ID_NO_ASSOC 15
#define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
static int wfx_get_hw_rate(struct wfx_dev *wdev,
@@ -265,156 +264,6 @@ void wfx_tx_policy_init(struct wfx_vif *wvif)
list_add(&cache->cache[i].link, &cache->free);
}
-/* Link ID related functions */
-
-static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac)
-{
- int i, ret = 0;
- unsigned long oldest;
-
- spin_lock_bh(&wvif->ps_state_lock);
- for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
- if (!wvif->link_id_db[i].status) {
- ret = i + 1;
- break;
- } else if (wvif->link_id_db[i].status != WFX_LINK_HARD &&
- !wvif->wdev->tx_queue_stats.link_map_cache[i + 1]) {
- if (!ret || time_after(oldest, wvif->link_id_db[i].timestamp)) {
- oldest = wvif->link_id_db[i].timestamp;
- ret = i + 1;
- }
- }
- }
-
- if (ret) {
- struct wfx_link_entry *entry = &wvif->link_id_db[ret - 1];
-
- entry->status = WFX_LINK_RESERVE;
- ether_addr_copy(entry->mac, mac);
- wfx_tx_lock(wvif->wdev);
-
- if (!schedule_work(&wvif->link_id_work))
- wfx_tx_unlock(wvif->wdev);
- } else {
- dev_info(wvif->wdev->dev, "no more link-id available\n");
- }
- spin_unlock_bh(&wvif->ps_state_lock);
- return ret;
-}
-
-int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac)
-{
- int i, ret = 0;
-
- spin_lock_bh(&wvif->ps_state_lock);
- for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
- if (ether_addr_equal(mac, wvif->link_id_db[i].mac) &&
- wvif->link_id_db[i].status) {
- wvif->link_id_db[i].timestamp = jiffies;
- ret = i + 1;
- break;
- }
- }
- spin_unlock_bh(&wvif->ps_state_lock);
- return ret;
-}
-
-static int wfx_map_link(struct wfx_vif *wvif,
- struct wfx_link_entry *link_entry, int sta_id)
-{
- int ret;
-
- ret = hif_map_link(wvif, link_entry->mac, 0, sta_id);
-
- if (ret == 0)
- /* Save the MAC address currently associated with the peer
- * for future unmap request
- */
- ether_addr_copy(link_entry->old_mac, link_entry->mac);
-
- return ret;
-}
-
-int wfx_unmap_link(struct wfx_vif *wvif, int sta_id)
-{
- u8 *mac_addr = NULL;
-
- if (sta_id)
- mac_addr = wvif->link_id_db[sta_id - 1].old_mac;
-
- return hif_map_link(wvif, mac_addr, 1, sta_id);
-}
-
-void wfx_link_id_gc_work(struct work_struct *work)
-{
- struct wfx_vif *wvif =
- container_of(work, struct wfx_vif, link_id_gc_work.work);
- unsigned long now = jiffies;
- unsigned long next_gc = -1;
- long ttl;
- u32 mask;
- int i;
-
- if (wvif->state != WFX_STATE_AP)
- return;
-
- wfx_tx_lock_flush(wvif->wdev);
- spin_lock_bh(&wvif->ps_state_lock);
- for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) {
- bool need_reset = false;
-
- mask = BIT(i + 1);
- if (wvif->link_id_db[i].status == WFX_LINK_RESERVE ||
- (wvif->link_id_db[i].status == WFX_LINK_HARD &&
- !(wvif->link_id_map & mask))) {
- if (wvif->link_id_map & mask) {
- wvif->sta_asleep_mask &= ~mask;
- wvif->pspoll_mask &= ~mask;
- need_reset = true;
- }
- wvif->link_id_map |= mask;
- if (wvif->link_id_db[i].status != WFX_LINK_HARD)
- wvif->link_id_db[i].status = WFX_LINK_SOFT;
-
- spin_unlock_bh(&wvif->ps_state_lock);
- if (need_reset)
- wfx_unmap_link(wvif, i + 1);
- wfx_map_link(wvif, &wvif->link_id_db[i], i + 1);
- next_gc = min(next_gc, WFX_LINK_ID_GC_TIMEOUT);
- spin_lock_bh(&wvif->ps_state_lock);
- } else if (wvif->link_id_db[i].status == WFX_LINK_SOFT) {
- ttl = wvif->link_id_db[i].timestamp - now +
- WFX_LINK_ID_GC_TIMEOUT;
- if (ttl <= 0) {
- need_reset = true;
- wvif->link_id_db[i].status = WFX_LINK_OFF;
- wvif->link_id_map &= ~mask;
- wvif->sta_asleep_mask &= ~mask;
- wvif->pspoll_mask &= ~mask;
- spin_unlock_bh(&wvif->ps_state_lock);
- wfx_unmap_link(wvif, i + 1);
- spin_lock_bh(&wvif->ps_state_lock);
- } else {
- next_gc = min_t(unsigned long, next_gc, ttl);
- }
- }
- }
- spin_unlock_bh(&wvif->ps_state_lock);
- if (next_gc != -1)
- schedule_delayed_work(&wvif->link_id_gc_work, next_gc);
- wfx_tx_unlock(wvif->wdev);
-}
-
-void wfx_link_id_work(struct work_struct *work)
-{
- struct wfx_vif *wvif =
- container_of(work, struct wfx_vif, link_id_work);
-
- wfx_tx_flush(wvif->wdev);
- wfx_link_id_gc_work(&wvif->link_id_gc_work.work);
- wfx_tx_unlock(wvif->wdev);
-}
-
/* Tx implementation */
static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr)
@@ -447,9 +296,6 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr,
if (wvif->sta_asleep_mask)
schedule_work(&wvif->mcast_start_work);
}
-
- if (tx_priv->raw_link_id)
- wvif->link_id_db[tx_priv->raw_link_id - 1].timestamp = jiffies;
spin_unlock_bh(&wvif->ps_state_lock);
if (sta && tx_priv->tid < WFX_MAX_TID) {
@@ -468,7 +314,6 @@ static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif,
struct wfx_sta_priv *sta_priv =
sta ? (struct wfx_sta_priv *) &sta->drv_priv : NULL;
const u8 *da = ieee80211_get_DA(hdr);
- int ret;
if (sta_priv && sta_priv->link_id)
return sta_priv->link_id;
@@ -476,14 +321,7 @@ static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif,
return 0;
if (is_multicast_ether_addr(da))
return 0;
- ret = wfx_find_link_id(wvif, da);
- if (!ret)
- ret = wfx_alloc_link_id(wvif, da);
- if (!ret) {
- dev_err(wvif->wdev->dev, "no more link-id available\n");
- return WFX_LINK_ID_NO_ASSOC;
- }
- return ret;
+ return WFX_LINK_ID_NO_ASSOC;
}
static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
@@ -18,20 +18,6 @@ struct wfx_tx_priv;
struct wfx_dev;
struct wfx_vif;
-enum wfx_link_status {
- WFX_LINK_OFF,
- WFX_LINK_RESERVE,
- WFX_LINK_SOFT,
- WFX_LINK_HARD,
-};
-
-struct wfx_link_entry {
- unsigned long timestamp;
- enum wfx_link_status status;
- u8 mac[ETH_ALEN];
- u8 old_mac[ETH_ALEN];
-};
-
struct tx_policy {
struct list_head link;
int usage_count;
@@ -63,11 +49,6 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg);
void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb);
-int wfx_unmap_link(struct wfx_vif *wvif, int link_id);
-void wfx_link_id_work(struct work_struct *work);
-void wfx_link_id_gc_work(struct work_struct *work);
-int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac);
-
static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info;
@@ -378,13 +378,8 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb,
action = do_drop;
break;
case NL80211_IFTYPE_AP:
- if (!wvif->state) {
+ if (!wvif->state)
action = do_drop;
- } else if (!(BIT(tx_priv->raw_link_id) &
- (BIT(0) | wvif->link_id_map))) {
- dev_warn(wvif->wdev->dev, "a frame with expired link-id is dropped\n");
- action = do_drop;
- }
break;
case NL80211_IFTYPE_ADHOC:
if (wvif->state != WFX_STATE_IBSS)
@@ -13,9 +13,10 @@
#include "hif_api_cmd.h"
#define WFX_MAX_STA_IN_AP_MODE 14
-#define WFX_LINK_ID_AFTER_DTIM (WFX_MAX_STA_IN_AP_MODE + 1)
-#define WFX_LINK_ID_UAPSD (WFX_MAX_STA_IN_AP_MODE + 2)
-#define WFX_LINK_ID_MAX (WFX_MAX_STA_IN_AP_MODE + 3)
+#define WFX_LINK_ID_NO_ASSOC 15
+#define WFX_LINK_ID_AFTER_DTIM (WFX_LINK_ID_NO_ASSOC + 1)
+#define WFX_LINK_ID_UAPSD (WFX_LINK_ID_NO_ASSOC + 2)
+#define WFX_LINK_ID_MAX (WFX_LINK_ID_NO_ASSOC + 3)
struct wfx_dev;
struct wfx_vif;
@@ -573,28 +573,26 @@ static void wfx_unjoin_work(struct work_struct *work)
int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct wfx_dev *wdev = hw->priv;
struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
- struct wfx_link_entry *entry;
spin_lock_init(&sta_priv->lock);
- if (wvif->vif->type != NL80211_IFTYPE_AP)
- return 0;
-
sta_priv->vif_id = wvif->id;
- sta_priv->link_id = wfx_find_link_id(wvif, sta->addr);
- if (!sta_priv->link_id) {
- dev_warn(wdev->dev, "mo more link-id available\n");
- return -ENOENT;
- }
- entry = &wvif->link_id_db[sta_priv->link_id - 1];
+ // FIXME: in station mode, the current API interprets new link-id as a
+ // tdls peer.
+ if (vif->type == NL80211_IFTYPE_STATION)
+ return 0;
+ sta_priv->link_id = ffz(wvif->link_id_map);
+ wvif->link_id_map |= BIT(sta_priv->link_id);
+ WARN_ON(!sta_priv->link_id);
+ WARN_ON(sta_priv->link_id >= WFX_MAX_STA_IN_AP_MODE);
+ hif_map_link(wvif, sta->addr, 0, sta_priv->link_id);
+
spin_lock_bh(&wvif->ps_state_lock);
if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) ==
IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
wvif->sta_asleep_mask |= BIT(sta_priv->link_id);
- entry->status = WFX_LINK_HARD;
spin_unlock_bh(&wvif->ps_state_lock);
return 0;
}
@@ -602,23 +600,15 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct wfx_dev *wdev = hw->priv;
struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
- struct wfx_link_entry *entry;
- if (wvif->vif->type != NL80211_IFTYPE_AP || !sta_priv->link_id)
+ // FIXME: see note in wfx_sta_add()
+ if (vif->type == NL80211_IFTYPE_STATION)
return 0;
-
- entry = &wvif->link_id_db[sta_priv->link_id - 1];
- spin_lock_bh(&wvif->ps_state_lock);
- entry->status = WFX_LINK_RESERVE;
- entry->timestamp = jiffies;
- wfx_tx_lock(wdev);
- if (!schedule_work(&wvif->link_id_work))
- wfx_tx_unlock(wdev);
- spin_unlock_bh(&wvif->ps_state_lock);
- flush_work(&wvif->link_id_work);
+ // FIXME add a mutex?
+ hif_map_link(wvif, sta->addr, 1, sta_priv->link_id);
+ wvif->link_id_map &= ~BIT(sta_priv->link_id);
return 0;
}
@@ -627,8 +617,6 @@ static int wfx_start_ap(struct wfx_vif *wvif)
int ret;
wvif->beacon_int = wvif->vif->bss_conf.beacon_int;
- memset(&wvif->link_id_db, 0, sizeof(wvif->link_id_db));
-
wvif->wdev->tx_burst_idx = -1;
ret = hif_start(wvif, &wvif->vif->bss_conf, wvif->channel);
if (ret)
@@ -861,7 +849,7 @@ static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd,
dev_warn(wvif->wdev->dev, "unsupported notify command\n");
bit = 0;
} else {
- bit = wvif->link_id_map;
+ bit = wvif->link_id_map & ~1;
}
prev = wvif->sta_asleep_mask & bit;
@@ -1114,9 +1102,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
wvif->vif = vif;
wvif->wdev = wdev;
- INIT_WORK(&wvif->link_id_work, wfx_link_id_work);
- INIT_DELAYED_WORK(&wvif->link_id_gc_work, wfx_link_id_gc_work);
-
+ wvif->link_id_map = 1; // link-id 0 is reserved for multicast
spin_lock_init(&wvif->ps_state_lock);
INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
@@ -1171,11 +1157,11 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
{
struct wfx_dev *wdev = hw->priv;
struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
- int i;
wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
mutex_lock(&wdev->conf_mutex);
+ WARN(wvif->link_id_map != 1, "corrupted state");
switch (wvif->state) {
case WFX_STATE_PRE_STA:
case WFX_STATE_STA:
@@ -1185,13 +1171,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
wfx_tx_unlock(wdev);
break;
case WFX_STATE_AP:
- for (i = 0; wvif->link_id_map; ++i) {
- if (wvif->link_id_map & BIT(i)) {
- wfx_unmap_link(wvif, i);
- wvif->link_id_map &= ~BIT(i);
- }
- }
- memset(wvif->link_id_db, 0, sizeof(wvif->link_id_db));
wvif->sta_asleep_mask = 0;
wvif->mcast_tx = false;
wvif->aid0_bit_set = false;
@@ -1213,7 +1192,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw,
wfx_cqm_bssloss_sm(wvif, 0, 0, 0);
cancel_work_sync(&wvif->unjoin_work);
- cancel_delayed_work_sync(&wvif->link_id_gc_work);
del_timer_sync(&wvif->mcast_timeout);
wfx_free_event_queue(wvif);
@@ -74,9 +74,6 @@ struct wfx_vif {
struct delayed_work bss_loss_work;
u32 link_id_map;
- struct wfx_link_entry link_id_db[WFX_MAX_STA_IN_AP_MODE];
- struct delayed_work link_id_gc_work;
- struct work_struct link_id_work;
bool aid0_bit_set;
bool mcast_tx;