]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/mac80211/mesh.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[mv-sheeva.git] / net / mac80211 / mesh.c
index 9a3e5de0410a802154dbbf71fa48253d4969628c..11cf45bce38a36cf17c4592b5b0991a489a28c5e 100644 (file)
@@ -21,6 +21,9 @@
 #define CAPAB_OFFSET 17
 #define ACCEPT_PLINKS 0x80
 
+#define TMR_RUNNING_HK 0
+#define TMR_RUNNING_MP 1
+
 int mesh_allocated;
 static struct kmem_cache *rm_cache;
 
@@ -45,6 +48,12 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
        ifmsh->housekeeping = true;
+
+       if (local->quiescing) {
+               set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+               return;
+       }
+
        queue_work(local->hw.workqueue, &ifmsh->work);
 }
 
@@ -343,6 +352,11 @@ static void ieee80211_mesh_path_timer(unsigned long data)
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_local *local = sdata->local;
 
+       if (local->quiescing) {
+               set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+               return;
+       }
+
        queue_work(local->hw.workqueue, &ifmsh->work);
 }
 
@@ -417,13 +431,39 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
 
        free_plinks = mesh_plink_availables(sdata);
        if (free_plinks != sdata->u.mesh.accepting_plinks)
-               ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 
        ifmsh->housekeeping = false;
        mod_timer(&ifmsh->housekeeping_timer,
                  round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
 }
 
+#ifdef CONFIG_PM
+void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+       /* might restart the timer but that doesn't matter */
+       cancel_work_sync(&ifmsh->work);
+
+       /* use atomic bitops in case both timers fire at the same time */
+
+       if (del_timer_sync(&ifmsh->housekeeping_timer))
+               set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+       if (del_timer_sync(&ifmsh->mesh_path_timer))
+               set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+}
+
+void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+       if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
+               add_timer(&ifmsh->housekeeping_timer);
+       if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
+               add_timer(&ifmsh->mesh_path_timer);
+}
+#endif
 
 void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 {
@@ -432,8 +472,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 
        ifmsh->housekeeping = true;
        queue_work(local->hw.workqueue, &ifmsh->work);
-       ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
-                                  IEEE80211_IFCC_BEACON_ENABLED);
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
+                                               BSS_CHANGED_BEACON_ENABLED);
 }
 
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -454,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
         * should it be using the interface and enqueuing
         * frames at this very time on another CPU.
         */
-       synchronize_rcu();
+       rcu_barrier(); /* Wait for RX path and call_rcu()'s */
        skb_queue_purge(&sdata->u.mesh.skb_queue);
 }