aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-05-16 17:50:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-05 15:32:18 -0400
commitcc1d2806bf06ab92268343d26eb3d8d8f00f8bc9 (patch)
treeb14ffa920d616470715e715df49f990bfdcf12ae /net/wireless/nl80211.c
parent685d12a1929f274bd91497e33b4255fe164ac8ec (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.c43
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[],
1166static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) 1167static 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