iwlwifi: track IBSS manager status

Only the IBSS manager, ie. the station that sent
the IBSS beacon last, should be replying to probe
responses. This requires implementing the mac80211
tx_last_beacon callback, which we can do thanks to
the ucode beacon notification.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Johannes Berg 2010-07-31 08:34:10 -07:00 committed by John W. Linville
parent 07d4f1ad2c
commit a85d7cca12
6 changed files with 25 additions and 2 deletions

View file

@ -764,10 +764,10 @@ static void iwl_bg_ucode_trace(unsigned long data)
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl4965_beacon_notif *beacon =
(struct iwl4965_beacon_notif *)pkt->u.raw;
#ifdef CONFIG_IWLWIFI_DEBUG
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@ -779,6 +779,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
@ -3881,6 +3883,7 @@ static struct ieee80211_ops iwl_hw_ops = {
.sta_remove = iwl_mac_sta_remove,
.channel_switch = iwl_mac_channel_switch,
.flush = iwl_mac_flush,
.tx_last_beacon = iwl_mac_tx_last_beacon,
};
static void iwl_hw_detect(struct iwl_priv *priv)

View file

@ -2919,6 +2919,11 @@ struct iwl_scancomplete_notification {
*
*****************************************************************************/
enum iwl_ibss_manager {
IWL_NOT_IBSS_MANAGER = 0,
IWL_IBSS_MANAGER = 1,
};
/*
* BEACON_NOTIFICATION = 0x90 (notification only, not a command)
*/

View file

@ -1666,6 +1666,14 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
}
EXPORT_SYMBOL(iwl_mac_conf_tx);
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
return priv->ibss_manager == IWL_IBSS_MANAGER;
}
EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
static void iwl_ht_conf(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{

View file

@ -350,6 +350,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
void iwl_activate_qos(struct iwl_priv *priv);
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
int iwl_check_rxon_cmd(struct iwl_priv *priv);
int iwl_full_rxon_required(struct iwl_priv *priv);

View file

@ -1109,6 +1109,9 @@ struct iwl_priv {
u32 ucode_beacon_time;
int missed_beacon_threshold;
/* track IBSS manager (last beacon) status */
u32 ibss_manager;
/* storing the jiffies when the plcp error rate is received */
unsigned long plcp_jiffies;

View file

@ -814,9 +814,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
#ifdef CONFIG_IWLWIFI_DEBUG
u8 rate = beacon->beacon_notify_hdr.rate;
IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@ -828,6 +828,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
@ -3803,6 +3805,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.hw_scan = iwl_mac_hw_scan,
.sta_add = iwl3945_mac_sta_add,
.sta_remove = iwl_mac_sta_remove,
.tx_last_beacon = iwl_mac_tx_last_beacon,
};
static int iwl3945_init_drv(struct iwl_priv *priv)