diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-05-16 17:50:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-05 15:32:18 -0400 |
commit | cc1d2806bf06ab92268343d26eb3d8d8f00f8bc9 (patch) | |
tree | b14ffa920d616470715e715df49f990bfdcf12ae /net/wireless/nl80211.c | |
parent | 685d12a1929f274bd91497e33b4255fe164ac8ec (diff) |
cfg80211: provide channel to join_mesh function
Just like the AP mode patch, instead of setting
the channel and then joining the mesh network,
provide the channel to join the network on to
the join_mesh() function.
Like in AP mode, you can also give the channel
to the join-mesh nl80211 command now.
Unlike AP mode, it picks a default channel if
none was given.
As libertas uses mesh mode interfaces but has
no join_mesh callback and we can't simply break
it, keep some compatibility code for that case
and configure the channel directly for it.
In the non-libertas case, where we store the
channel until join, allow setting it while the
interface is down.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 089a5204dad5..b22f1f876881 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -921,7 +921,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | 921 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) |
922 | goto nla_put_failure; | 922 | goto nla_put_failure; |
923 | } | 923 | } |
924 | if (dev->ops->set_channel || dev->ops->start_ap) { | 924 | if (dev->ops->set_channel || dev->ops->start_ap || |
925 | dev->ops->join_mesh) { | ||
925 | i++; | 926 | i++; |
926 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | 927 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) |
927 | goto nla_put_failure; | 928 | goto nla_put_failure; |
@@ -1166,17 +1167,19 @@ static int parse_txq_params(struct nlattr *tb[], | |||
1166 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) | 1167 | static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) |
1167 | { | 1168 | { |
1168 | /* | 1169 | /* |
1169 | * You can only set the channel explicitly for AP and | 1170 | * You can only set the channel explicitly for WDS interfaces, |
1170 | * mesh type interfaces; all others have their channel | 1171 | * all others have their channel managed via their respective |
1171 | * managed via their respective "establish a connection" | 1172 | * "establish a connection" command (connect, join, ...) |
1172 | * command (connect, join, ...) | 1173 | * |
1174 | * For AP/GO and mesh mode, the channel can be set with the | ||
1175 | * channel userspace API, but is only stored and passed to the | ||
1176 | * low-level driver when the AP starts or the mesh is joined. | ||
1177 | * This is for backward compatibility, userspace can also give | ||
1178 | * the channel in the start-ap or join-mesh commands instead. | ||
1173 | * | 1179 | * |
1174 | * Monitors are special as they are normally slaved to | 1180 | * Monitors are special as they are normally slaved to |
1175 | * whatever else is going on, so they behave as though | 1181 | * whatever else is going on, so they behave as though |
1176 | * you tried setting the wiphy channel itself. | 1182 | * you tried setting the wiphy channel itself. |
1177 | * | ||
1178 | * For AP/GO modes, it's only for compatibility, you can | ||
1179 | * also give the channel to the start-AP command. | ||
1180 | */ | 1183 | */ |
1181 | return !wdev || | 1184 | return !wdev || |
1182 | wdev->iftype == NL80211_IFTYPE_AP || | 1185 | wdev->iftype == NL80211_IFTYPE_AP || |
@@ -1246,6 +1249,9 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1246 | wdev->preset_chantype = channel_type; | 1249 | wdev->preset_chantype = channel_type; |
1247 | result = 0; | 1250 | result = 0; |
1248 | break; | 1251 | break; |
1252 | case NL80211_IFTYPE_MESH_POINT: | ||
1253 | result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); | ||
1254 | break; | ||
1249 | default: | 1255 | default: |
1250 | wdev_lock(wdev); | 1256 | wdev_lock(wdev); |
1251 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); | 1257 | result = cfg80211_set_freq(rdev, wdev, freq, channel_type); |
@@ -1335,8 +1341,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1335 | result = 0; | 1341 | result = 0; |
1336 | 1342 | ||
1337 | mutex_lock(&rdev->mtx); | 1343 | mutex_lock(&rdev->mtx); |
1338 | } else if (netif_running(netdev) && | 1344 | } else if (nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) |
1339 | nl80211_can_set_dev_channel(netdev->ieee80211_ptr)) | ||
1340 | wdev = netdev->ieee80211_ptr; | 1345 | wdev = netdev->ieee80211_ptr; |
1341 | else | 1346 | else |
1342 | wdev = NULL; | 1347 | wdev = NULL; |
@@ -6080,6 +6085,24 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6080 | return err; | 6085 | return err; |
6081 | } | 6086 | } |
6082 | 6087 | ||
6088 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | ||
6089 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
6090 | |||
6091 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && | ||
6092 | !nl80211_valid_channel_type(info, &channel_type)) | ||
6093 | return -EINVAL; | ||
6094 | |||
6095 | setup.channel = rdev_freq_to_chan(rdev, | ||
6096 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), | ||
6097 | channel_type); | ||
6098 | if (!setup.channel) | ||
6099 | return -EINVAL; | ||
6100 | setup.channel_type = channel_type; | ||
6101 | } else { | ||
6102 | /* cfg80211_join_mesh() will sort it out */ | ||
6103 | setup.channel = NULL; | ||
6104 | } | ||
6105 | |||
6083 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | 6106 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); |
6084 | } | 6107 | } |
6085 | 6108 | ||