int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
-       int ret;
+       int ret = 0;
 
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return 0;
 
+       mutex_lock(&local->iflist_mtx);
+
        if (local->monitor_sdata)
-               return 0;
+               goto out_unlock;
 
        sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
-       if (!sdata)
-               return -ENOMEM;
+       if (!sdata) {
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
 
        /* set up data */
        sdata->local = local;
        if (WARN_ON(ret)) {
                /* ok .. stupid driver, it asked for this! */
                kfree(sdata);
-               return ret;
+               goto out_unlock;
        }
 
        ret = ieee80211_check_queues(sdata);
        if (ret) {
                kfree(sdata);
-               return ret;
+               goto out_unlock;
        }
 
        rcu_assign_pointer(local->monitor_sdata, sdata);
-
-       return 0;
+ out_unlock:
+       mutex_unlock(&local->iflist_mtx);
+       return ret;
 }
 
 void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return;
 
-       sdata = rtnl_dereference(local->monitor_sdata);
+       mutex_lock(&local->iflist_mtx);
 
+       sdata = rcu_dereference_protected(local->monitor_sdata,
+                                         lockdep_is_held(&local->iflist_mtx));
        if (!sdata)
-               return;
+               goto out_unlock;
 
        rcu_assign_pointer(local->monitor_sdata, NULL);
        synchronize_net();
        drv_remove_interface(local, sdata);
 
        kfree(sdata);
+ out_unlock:
+       mutex_unlock(&local->iflist_mtx);
 }
 
 /*
 
                                 &sdata->vif);
        }
 
+       sdata = rcu_dereference_protected(local->monitor_sdata,
+                                         lockdep_is_held(&local->iflist_mtx));
+       if (sdata)
+               iterator(data, sdata->vif.addr, &sdata->vif);
+
        mutex_unlock(&local->iflist_mtx);
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
                                 &sdata->vif);
        }
 
+       sdata = rcu_dereference(local->monitor_sdata);
+       if (sdata)
+               iterator(data, sdata->vif.addr, &sdata->vif);
+
        rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);