Merge tag 'iommu-updates-v3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / net / wireless / mesh.c
index b44c736..c384e77 100644 (file)
@@ -14,6 +14,9 @@
 
 #define MESH_PATH_TIMEOUT      5000
 #define MESH_RANN_INTERVAL      5000
+#define MESH_PATH_TO_ROOT_TIMEOUT      6000
+#define MESH_ROOT_INTERVAL     5000
+#define MESH_ROOT_CONFIRMATION_INTERVAL 2000
 
 /*
  * Minimum interval between two consecutive PREQs originated by the same
@@ -62,6 +65,9 @@ const struct mesh_config default_mesh_config = {
        .dot11MeshForwarding = true,
        .rssi_threshold = MESH_RSSI_THRESHOLD,
        .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
+       .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
+       .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
+       .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
 };
 
 const struct mesh_setup default_mesh_setup = {
@@ -149,10 +155,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
                                          setup->channel_type))
                return -EINVAL;
 
+       err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
+                                   CHAN_MODE_SHARED);
+       if (err)
+               return err;
+
        err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
        if (!err) {
                memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
                wdev->mesh_id_len = setup->mesh_id_len;
+               wdev->channel = setup->channel;
        }
 
        return err;
@@ -166,9 +178,11 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
 
+       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(wdev);
        err = __cfg80211_join_mesh(rdev, dev, setup, conf);
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
@@ -178,6 +192,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
                           enum nl80211_channel_type channel_type)
 {
        struct ieee80211_channel *channel;
+       int err;
 
        channel = rdev_freq_to_chan(rdev, freq, channel_type);
        if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
@@ -199,9 +214,19 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
 
                if (!netif_running(wdev->netdev))
                        return -ENETDOWN;
-               return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
-                                                           wdev->netdev,
-                                                           channel);
+
+               err = cfg80211_can_use_chan(rdev, wdev, channel,
+                                           CHAN_MODE_SHARED);
+               if (err)
+                       return err;
+
+               err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
+                                                          wdev->netdev,
+                                                          channel);
+               if (!err)
+                       wdev->channel = channel;
+
+               return err;
        }
 
        if (wdev->mesh_id_len)
@@ -243,8 +268,11 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
                return -ENOTCONN;
 
        err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
-       if (!err)
+       if (!err) {
                wdev->mesh_id_len = 0;
+               wdev->channel = NULL;
+       }
+
        return err;
 }