From 4aca8ab2e977b97c1edcdd5f838ad8a0bb718ded Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 17 Aug 2007 16:43:33 +0300 Subject: [PATCH 10/31] iwlwifi: AP mode beacon update This patch adds support getting update beacon from mac80211 in AP mode. Mainly this solves DTIM down counter bug. Signed-off-by: Pavel Aronsky Signed-off-by: Gregory Greenman Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi --- drivers/net/wireless/iwl-base.c | 31 +++++++++++++++++++++++++++++++ drivers/net/wireless/iwl-priv.h | 1 + 2 files changed, 32 insertions(+), 0 deletions(-) diff --git a/drivers/net/wireless/iwl-base.c b/drivers/net/wireless/iwl-base.c index c905057..f0bf9c1 100644 --- a/drivers/net/wireless/iwl-base.c +++ b/drivers/net/wireless/iwl-base.c @@ -3971,6 +3971,31 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); } +static void iwl_bg_beacon_update(struct work_struct *work) +{ + struct iwl_priv *priv = + container_of(work, struct iwl_priv, beacon_update); + struct sk_buff *beacon; + + /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ + beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL); + + if (!beacon) { + IWL_ERROR("update beacon failed\n"); + return; + } + + mutex_lock(&priv->mutex); + /* new beacon skb is allocated every time; dispose previous.*/ + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = beacon; + mutex_unlock(&priv->mutex); + + iwl_send_beacon_cmd(priv); +} + static void iwl_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -3990,6 +4015,10 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->high_tsf), le32_to_cpu(beacon->low_tsf), rate); #endif + + if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + (!test_bit(STATUS_EXIT_PENDING, &priv->status))) + queue_work(priv->workqueue, &priv->beacon_update); } /* Service response to REPLY_SCAN_CMD (0x80) */ @@ -9056,6 +9085,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) INIT_WORK(&priv->request_scan, iwl_bg_request_scan); INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); + INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate); INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); @@ -9074,6 +9104,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_delayed_work(&priv->post_associate); + cancel_work_sync(&priv->beacon_update); } static struct attribute *iwl_sysfs_entries[] = { diff --git a/drivers/net/wireless/iwl-priv.h b/drivers/net/wireless/iwl-priv.h index 964c8fe..d503d68 100644 --- a/drivers/net/wireless/iwl-priv.h +++ b/drivers/net/wireless/iwl-priv.h @@ -261,6 +261,7 @@ struct iwl_priv { struct work_struct auth_work; struct work_struct report_work; struct work_struct request_scan; + struct work_struct beacon_update; struct tasklet_struct irq_tasklet; -- 1.5.2