From: Zhu Yi <yi.zhu@intel.com>
To: linville@tuxdriver.com
Cc: linux-wireless@vger.kernel.org,
Emmanuel Grumbach <emmanuel.grumbach@intel.com>,
Tomas Winkler <tomas.winkler@intel.com>,
Zhu Yi <yi.zhu@intel.com>
Subject: [PATCH 03/33] iwlwifi: better station table maintenance
Date: Mon, 30 Jun 2008 17:23:03 +0800 [thread overview]
Message-ID: <1214817813-17639-4-git-send-email-yi.zhu@intel.com> (raw)
In-Reply-To: <1214817813-17639-3-git-send-email-yi.zhu@intel.com>
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This patch makes the station table maintenance safer. Two flags are
maintained:
1) if station is present in driver
2) if station is present in uCode
This will allow us in the future to deal with more stations than the
firmware allows.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
drivers/net/wireless/iwlwifi/iwl-core.c | 4 +
drivers/net/wireless/iwlwifi/iwl-sta.c | 146 +++++++++++++++++---------
drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 1 -
4 files changed, 100 insertions(+), 53 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index eb74a40..1c0670b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -284,6 +284,10 @@ void iwlcore_clear_stations_table(struct iwl_priv *priv)
spin_lock_irqsave(&priv->sta_lock, flags);
priv->num_stations = 0;
+ if (iwl_is_alive(priv) &&
+ iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
+ IWL_ERROR("Couldn't clear the station table\n");
+
memset(priv->stations, 0, sizeof(priv->stations));
spin_unlock_irqrestore(&priv->sta_lock, flags);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index f874e7d..c81ab5f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -36,8 +36,8 @@
#include "iwl-helpers.h"
-#define IWL_STA_DRIVER_ACTIVE 0x1 /* ucode entry is active */
-#define IWL_STA_UCODE_ACTIVE 0x2 /* ucode entry is active */
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
{
@@ -83,10 +83,28 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
}
EXPORT_SYMBOL(iwl_get_ra_sta_id);
+static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+ IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
+
+ priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+ IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n",
+ print_mac(mac, priv->stations[sta_id].sta.sta.addr));
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
static int iwl_add_sta_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
+ u8 sta_id = cmd->cmd.addsta.sta.sta_id;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
@@ -102,8 +120,8 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
switch (res->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK:
- /* FIXME: implement iwl_sta_ucode_activate(priv, addr); */
- /* fail through */
+ iwl_sta_ucode_activate(priv, sta_id);
+ /* fall through */
default:
IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n",
res->u.add_sta.status);
@@ -147,6 +165,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
if (ret == 0) {
switch (res->u.add_sta.status) {
case ADD_STA_SUCCESS_MSK:
+ iwl_sta_ucode_activate(priv, sta->sta.sta_id);
IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
break;
default:
@@ -215,88 +234,92 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
u8 flags, struct ieee80211_ht_info *ht_info)
{
int i;
- int index = IWL_INVALID_STATION;
+ int sta_id = IWL_INVALID_STATION;
struct iwl_station_entry *station;
unsigned long flags_spin;
DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
- index = IWL_AP_ID;
+ sta_id = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
+ sta_id = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
addr)) {
- index = i;
+ sta_id = i;
break;
}
if (!priv->stations[i].used &&
- index == IWL_INVALID_STATION)
- index = i;
+ sta_id == IWL_INVALID_STATION)
+ sta_id = i;
}
-
/* These two conditions have the same outcome, but keep them separate
- since they have different meanings */
- if (unlikely(index == IWL_INVALID_STATION)) {
+ since they have different meanings */
+ if (unlikely(sta_id == IWL_INVALID_STATION)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
+ return sta_id;
}
- if (priv->stations[index].used &&
- !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
+ if (priv->stations[sta_id].used &&
+ !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- return index;
+ return sta_id;
}
- IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
- station = &priv->stations[index];
- station->used = 1;
+ station = &priv->stations[sta_id];
+ station->used = IWL_STA_DRIVER_ACTIVE;
+ IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n",
+ sta_id, print_mac(mac, addr));
priv->num_stations++;
/* Set up the REPLY_ADD_STA command to send to device */
memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
- station->sta.sta.sta_id = index;
+ station->sta.sta.sta_id = sta_id;
station->sta.station_flags = 0;
/* BCAST station and IBSS stations do not work in HT mode */
- if (index != priv->hw_params.bcast_sta_id &&
+ if (sta_id != priv->hw_params.bcast_sta_id &&
priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
- iwl_set_ht_add_station(priv, index, ht_info);
+ iwl_set_ht_add_station(priv, sta_id, ht_info);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
/* Add station to device's station table */
iwl_send_add_sta(priv, &station->sta, flags);
- return index;
+ return sta_id;
}
EXPORT_SYMBOL(iwl_add_station_flags);
-static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
+static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
{
unsigned long flags;
- u8 sta_id;
DECLARE_MAC_BUF(mac);
- sta_id = iwl_find_station(priv, addr);
- if (sta_id != IWL_INVALID_STATION) {
- IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
- print_mac(mac, addr));
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
- memset(&priv->stations[sta_id], 0,
- sizeof(struct iwl_station_entry));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
- return -EINVAL;
+ u8 sta_id = iwl_find_station(priv, addr);
+
+ BUG_ON(sta_id == IWL_INVALID_STATION);
+
+ IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
+ print_mac(mac, addr));
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ /* Ucode must be active and driver must be non active */
+ if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE)
+ IWL_ERROR("removed non active STA %d\n", sta_id);
+
+ priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+ memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
}
static int iwl_remove_sta_callback(struct iwl_priv *priv,
@@ -322,6 +345,7 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
iwl_sta_ucode_deactivate(priv, addr);
break;
default:
+ IWL_ERROR("REPLY_REMOVE_STA failed\n");
break;
}
@@ -386,44 +410,63 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
/**
* iwl_remove_station - Remove driver's knowledge of station.
*/
-u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
{
- int index = IWL_INVALID_STATION;
- int i;
+ int sta_id = IWL_INVALID_STATION;
+ int i, ret = -EINVAL;
unsigned long flags;
+ DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags);
if (is_ap)
- index = IWL_AP_ID;
+ sta_id = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
- index = priv->hw_params.bcast_sta_id;
+ sta_id = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
if (priv->stations[i].used &&
!compare_ether_addr(priv->stations[i].sta.sta.addr,
addr)) {
- index = i;
+ sta_id = i;
break;
}
- if (unlikely(index == IWL_INVALID_STATION))
+ if (unlikely(sta_id == IWL_INVALID_STATION))
goto out;
- if (priv->stations[index].used) {
- priv->stations[index].used = 0;
- priv->num_stations--;
+ IWL_DEBUG_ASSOC("Removing STA from driver:%d %s\n",
+ sta_id, print_mac(mac, addr));
+
+ if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+ IWL_ERROR("Removing %s but non DRIVER active\n",
+ print_mac(mac, addr));
+ goto out;
+ }
+
+ if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+ IWL_ERROR("Removing %s but non UCODE active\n",
+ print_mac(mac, addr));
+ goto out;
}
+
+ priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+ priv->num_stations--;
+
BUG_ON(priv->num_stations < 0);
+
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_remove_station(priv, addr, CMD_ASYNC);
- return index;
+
+ ret = iwl_send_remove_station(priv, addr, CMD_ASYNC);
+ return ret;
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(iwl_remove_station);
+
static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
@@ -845,6 +888,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
sizeof(link_cmd), &link_cmd, NULL);
}
+
/**
* iwl_rxon_add_station - add station into station table.
*
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index b6bb209..221b93e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -48,7 +48,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
-u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 6eee28d..1558b9a 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -315,7 +315,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
return rc;
}
- iwl_remove_station(priv, iwl_bcast_addr, 0);
iwlcore_clear_stations_table(priv);
if (!priv->error_recovering)
--
1.5.3.6
next prev parent reply other threads:[~2008-06-30 9:26 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-30 9:23 [PATCH 00/33] iwlwifi driver 06/30 updates Zhu Yi
2008-06-30 9:23 ` [PATCH 01/33] iwlwifi: configure uCode to use open loop tx power algorithm Zhu Yi
2008-06-30 9:23 ` [PATCH 02/33] iwlwifi: Add eeprom version to the version file in sysfs Zhu Yi
2008-06-30 9:23 ` Zhu Yi [this message]
2008-06-30 9:23 ` [PATCH 04/33] iwlwifi: use iwl_is_associated when possible Zhu Yi
2008-06-30 9:23 ` [PATCH 05/33] iwlwifi: add REPLY_TX_POWER_DBM_CMD to get_cmd_string Zhu Yi
2008-06-30 9:23 ` [PATCH 06/33] iwlwifi: send ADD_STA before RXON with assoc bit Zhu Yi
2008-06-30 9:23 ` [PATCH 07/33] iwlwifi: move RX stats to core, and move temperature to handler Zhu Yi
2008-06-30 9:23 ` [PATCH 08/33] iwlwifi: don't send REPLY_REMOVE_ALL_STA upon exit Zhu Yi
2008-06-30 9:23 ` [PATCH 09/33] iwlwifi: move RX handlers to iwl-rx.c Zhu Yi
2008-06-30 9:23 ` [PATCH 10/33] iwlwifi: remove useless network and duplicate checking Zhu Yi
2008-06-30 9:23 ` [PATCH 11/33] iwlwifi: setup compressed BA handler Zhu Yi
2008-06-30 9:23 ` [PATCH 12/33] iwlwifi: move rx aggregation functions to iwl-rx.c Zhu Yi
2008-06-30 9:23 ` [PATCH 13/33] iwlwifi: remove obsolete lq_ready use Zhu Yi
2008-06-30 9:23 ` [PATCH 14/33] iwlwifi: fix IBSS association flow Zhu Yi
2008-06-30 9:23 ` [PATCH 15/33] iwlwifi: keep the STATUS_EXIT_PENDING flag till the end of down flow Zhu Yi
2008-06-30 9:23 ` [PATCH 16/33] mac80211: add beacon timestamp to beacon template in IBSS Zhu Yi
2008-06-30 9:23 ` [PATCH 17/33] iwlwifi: adjust TSF " Zhu Yi
2008-06-30 9:23 ` [PATCH 18/33] iwlwifi : Patch adds rfkill subsystem for 3945 Zhu Yi
2008-06-30 9:23 ` [PATCH 19/33] iwlwifi: don't bring up interface if RF-kill avoids radio Zhu Yi
2008-06-30 9:23 ` [PATCH 20/33] iwlwifi: unite common settings of HW params Zhu Yi
2008-06-30 9:23 ` [PATCH 21/33] iwlwifi: control 11n capabilities through module param Zhu Yi
2008-06-30 9:23 ` [PATCH 22/33] iwlwifi: Remove unnecessary code Zhu Yi
2008-06-30 9:23 ` [PATCH 23/33] iwlwifi: eliminate iwl4965_mac_get_tsf Zhu Yi
2008-06-30 9:23 ` [PATCH 24/33] iwlwifi: blocking mac_start until uCode is complete Zhu Yi
2008-06-30 9:23 ` [PATCH 25/33] iwlwifi: clean up HW RF-kill state machine and restarts Zhu Yi
2008-06-30 9:23 ` [PATCH 26/33] iwlwifi: fix 4965 uCode load Zhu Yi
2008-06-30 9:23 ` [PATCH 27/33] iwlwifi: fix incorrect 5GHz rates reported in monitor mode Zhu Yi
2008-06-30 9:23 ` [PATCH 28/33] iwlwifi: fix incorrect monitor mode operation Zhu Yi
2008-06-30 9:23 ` [PATCH 29/33] iwlwifi: drop skb silently for Tx request in monitor mode Zhu Yi
2008-06-30 9:23 ` [PATCH 30/33] iwlwifi: enable packet injection for iwl3945 Zhu Yi
2008-06-30 9:23 ` [PATCH 31/33] iwlwifi: fix iwl4965 temperature callback calibration issue Zhu Yi
2008-06-30 9:23 ` [PATCH 32/33] iwl3945: remove RFKILL_STATE_HARD_BLOCKED warnings Zhu Yi
2008-06-30 9:23 ` [PATCH 33/33] iwlwifi: remove the input device from rfkill_mngr Zhu Yi
2008-06-30 10:07 ` [PATCH 30/33] iwlwifi: enable packet injection for iwl3945 Stefanik Gábor
2008-06-30 10:22 ` [PATCH 29/33] iwlwifi: drop skb silently for Tx request in monitor mode Stefanik Gábor
2008-06-30 10:26 ` Michael Buesch
2008-06-30 10:28 ` Stefanik Gábor
2008-07-02 1:07 ` Zhu Yi
2008-06-30 9:56 ` [PATCH 00/33] iwlwifi driver 06/30 updates drago01
2008-07-02 3:05 ` Zhu Yi
2008-07-02 8:39 ` drago01
2008-07-02 8:41 ` Zhu Yi
2008-07-02 8:51 ` drago01
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1214817813-17639-4-git-send-email-yi.zhu@intel.com \
--to=yi.zhu@intel.com \
--cc=emmanuel.grumbach@intel.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=tomas.winkler@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.