Skip to content

Commit

Permalink
cfg80211: clarify set_channel APIs
Browse files Browse the repository at this point in the history
Now that we've removed all uses of the set_channel
API except for the monitor channel and in libertas,
clarify this. Split the libertas mesh use into a
new libertas_set_mesh_channel() operation, just to
keep backward compatibility, and rename the normal
set_channel() to set_monitor_channel().

Also describe the desired set_monitor_channel()
semantics more clearly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Jun 6, 2012
1 parent 7c9c46c commit e8c9bd5
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 106 deletions.
39 changes: 28 additions & 11 deletions drivers/net/wireless/libertas/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,24 +435,40 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
* Set Channel
*/

static int lbs_cfg_set_channel(struct wiphy *wiphy,
struct net_device *netdev,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type)
{
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;

lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
netdev_name(netdev), channel->center_freq, channel_type);
lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
channel->center_freq, channel_type);

if (channel_type != NL80211_CHAN_NO_HT)
goto out;

if (netdev == priv->mesh_dev)
ret = lbs_mesh_set_channel(priv, channel->hw_value);
else
ret = lbs_set_channel(priv, channel->hw_value);
ret = lbs_set_channel(priv, channel->hw_value);

out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
}

static int lbs_cfg_set_mesh_channel(struct wiphy *wiphy,
struct net_device *netdev,
struct ieee80211_channel *channel)
{
struct lbs_private *priv = wiphy_priv(wiphy);
int ret = -ENOTSUPP;

lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d",
netdev_name(netdev), channel->center_freq);

if (netdev != priv->mesh_dev)
goto out;

ret = lbs_mesh_set_channel(priv, channel->hw_value);

out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
Expand Down Expand Up @@ -2029,7 +2045,8 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
*/

static struct cfg80211_ops lbs_cfg80211_ops = {
.set_channel = lbs_cfg_set_channel,
.set_monitor_channel = lbs_cfg_set_monitor_channel,
.libertas_set_mesh_channel = lbs_cfg_set_mesh_channel,
.scan = lbs_cfg_scan,
.connect = lbs_cfg_connect,
.disconnect = lbs_cfg_disconnect,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/libertas/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct lbs_private {
uint16_t mesh_tlv;
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 mesh_ssid_len;
u8 mesh_channel;
#endif

/* Debugfs */
Expand Down
7 changes: 2 additions & 5 deletions drivers/net/wireless/libertas/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,13 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,

int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
{
priv->mesh_channel = channel;
return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
}

static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
{
struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
if (mesh_wdev->channel)
return mesh_wdev->channel->hw_value;
else
return 1;
return priv->mesh_channel ?: 1;
}

/***************************************************************************
Expand Down
9 changes: 4 additions & 5 deletions drivers/net/wireless/orinoco/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,9 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
return err;
}

static int orinoco_set_channel(struct wiphy *wiphy,
struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
static int orinoco_set_monitor_channel(struct wiphy *wiphy,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
struct orinoco_private *priv = wiphy_priv(wiphy);
int err = 0;
Expand Down Expand Up @@ -286,7 +285,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)

const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel,
.set_monitor_channel = orinoco_set_monitor_channel,
.scan = orinoco_scan,
.set_wiphy_params = orinoco_set_wiphy_params,
};
24 changes: 15 additions & 9 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1420,11 +1420,14 @@ struct cfg80211_gtk_rekey_data {
*
* @set_txq_params: Set TX queue parameters
*
* @set_channel: Set channel for a given wireless interface. Some devices
* may support multi-channel operation (by channel hopping) so cfg80211
* doesn't verify much. Note, however, that the passed netdev may be
* %NULL as well if the user requested changing the channel for the
* device itself, or for a monitor interface.
* @libertas_set_mesh_channel: Only for backward compatibility for libertas,
* as it doesn't implement join_mesh and needs to set the channel to
* join the mesh instead.
*
* @set_monitor_channel: Set the monitor mode channel for the device. If other
* interfaces are active this callback should reject the configuration.
* If no interfaces are active or the device is down, the channel should
* be stored for when a monitor interface becomes active.
* @get_channel: Get the current operating channel, should return %NULL if
* there's no single defined operating channel if for example the
* device implements channel hopping for multi-channel virtual interfaces.
Expand Down Expand Up @@ -1614,9 +1617,13 @@ struct cfg80211_ops {
int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_txq_params *params);

int (*set_channel)(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);
int (*libertas_set_mesh_channel)(struct wiphy *wiphy,
struct net_device *dev,
struct ieee80211_channel *chan);

int (*set_monitor_channel)(struct wiphy *wiphy,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);

int (*scan)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_scan_request *request);
Expand Down Expand Up @@ -2325,7 +2332,6 @@ struct wireless_dev {
spinlock_t event_lock;

struct cfg80211_internal_bss *current_bss; /* associated / joined */
struct ieee80211_channel *channel;
struct ieee80211_channel *preset_chan;
enum nl80211_channel_type preset_chantype;

Expand Down
9 changes: 8 additions & 1 deletion net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,13 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
return 0;
}

static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
return ieee80211_set_channel(wiphy, NULL, chan, channel_type);
}

static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
const u8 *resp, size_t resp_len)
{
Expand Down Expand Up @@ -2932,7 +2939,7 @@ struct cfg80211_ops mac80211_config_ops = {
#endif
.change_bss = ieee80211_change_bss,
.set_txq_params = ieee80211_set_txq_params,
.set_channel = ieee80211_set_channel,
.set_monitor_channel = ieee80211_set_monitor_channel,
.suspend = ieee80211_suspend,
.resume = ieee80211_resume,
.scan = ieee80211_scan,
Expand Down
43 changes: 5 additions & 38 deletions net/wireless/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,50 +78,17 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
}
EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);

int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, int freq,
enum nl80211_channel_type channel_type)
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type chantype)
{
struct ieee80211_channel *chan;
int result;

if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR)
wdev = NULL;

if (wdev) {
ASSERT_WDEV_LOCK(wdev);

if (!netif_running(wdev->netdev))
return -ENETDOWN;
}

if (!rdev->ops->set_channel)
if (!rdev->ops->set_monitor_channel)
return -EOPNOTSUPP;

chan = rdev_freq_to_chan(rdev, freq, channel_type);
chan = rdev_freq_to_chan(rdev, freq, chantype);
if (!chan)
return -EINVAL;

/* Both channels should be able to initiate communication */
if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC ||
wdev->iftype == NL80211_IFTYPE_AP ||
wdev->iftype == NL80211_IFTYPE_AP_VLAN ||
wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
wdev->iftype == NL80211_IFTYPE_P2P_GO) &&
!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan, channel_type)) {
printk(KERN_DEBUG
"cfg80211: Secondary channel not allowed to beacon\n");
return -EINVAL;
}

result = rdev->ops->set_channel(&rdev->wiphy,
wdev ? wdev->netdev : NULL,
chan, channel_type);
if (result)
return result;

if (wdev)
wdev->channel = chan;

return 0;
return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
}
5 changes: 2 additions & 3 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,8 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type);
int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, int freq,
enum nl80211_channel_type channel_type);
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type chantype);

int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
Expand Down
26 changes: 13 additions & 13 deletions net/wireless/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,34 +179,34 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
{
struct ieee80211_channel *channel;

channel = rdev_freq_to_chan(rdev, freq, channel_type);
if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
channel,
channel_type)) {
return -EINVAL;
}

/*
* Workaround for libertas (only!), it puts the interface
* into mesh mode but doesn't implement join_mesh. Instead,
* it is configured via sysfs and then joins the mesh when
* you set the channel. Note that the libertas mesh isn't
* compatible with 802.11 mesh.
*/
if (!rdev->ops->join_mesh) {
int err;
if (rdev->ops->libertas_set_mesh_channel) {
if (channel_type != NL80211_CHAN_NO_HT)
return -EINVAL;

if (!netif_running(wdev->netdev))
return -ENETDOWN;
wdev_lock(wdev);
err = cfg80211_set_freq(rdev, wdev, freq, channel_type);
wdev_unlock(wdev);

return err;
return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
wdev->netdev,
channel);
}

if (wdev->mesh_id_len)
return -EBUSY;

channel = rdev_freq_to_chan(rdev, freq, channel_type);
if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
channel,
channel_type)) {
return -EINVAL;
}
wdev->preset_chan = channel;
wdev->preset_chantype = channel_type;
return 0;
Expand Down
2 changes: 0 additions & 2 deletions net/wireless/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -947,8 +947,6 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
if (WARN_ON(!chan))
goto out;

wdev->channel = chan;

nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
out:
wdev_unlock(wdev);
Expand Down
21 changes: 12 additions & 9 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
goto nla_put_failure;
}
if (dev->ops->set_channel || dev->ops->start_ap ||
if (dev->ops->set_monitor_channel || dev->ops->start_ap ||
dev->ops->join_mesh) {
i++;
if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
Expand Down Expand Up @@ -1178,8 +1178,8 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
* the channel in the start-ap or join-mesh commands instead.
*
* Monitors are special as they are normally slaved to
* whatever else is going on, so they behave as though
* you tried setting the wiphy channel itself.
* whatever else is going on, so they have their own special
* operation to set the monitor channel if possible.
*/
return !wdev ||
wdev->iftype == NL80211_IFTYPE_AP ||
Expand Down Expand Up @@ -1217,6 +1217,10 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
u32 freq;
int result;
enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR;

if (wdev)
iftype = wdev->iftype;

if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
return -EINVAL;
Expand All @@ -1231,7 +1235,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);

mutex_lock(&rdev->devlist_mtx);
if (wdev) switch (wdev->iftype) {
switch (iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (wdev->beacon_interval) {
Expand All @@ -1252,12 +1256,11 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_MESH_POINT:
result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type);
break;
case NL80211_IFTYPE_MONITOR:
result = cfg80211_set_monitor_channel(rdev, freq, channel_type);
break;
default:
wdev_lock(wdev);
result = cfg80211_set_freq(rdev, wdev, freq, channel_type);
wdev_unlock(wdev);
} else {
result = cfg80211_set_freq(rdev, NULL, freq, channel_type);
result = -EINVAL;
}
mutex_unlock(&rdev->devlist_mtx);

Expand Down
10 changes: 2 additions & 8 deletions net/wireless/wext-compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,9 +802,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
if (freq == 0)
return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
wdev_unlock(wdev);
err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT);
mutex_unlock(&rdev->devlist_mtx);
return err;
case NL80211_IFTYPE_MESH_POINT:
Expand Down Expand Up @@ -848,11 +846,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
freq->e = 6;
return 0;
default:
if (!wdev->channel)
return -EINVAL;
freq->m = wdev->channel->center_freq;
freq->e = 6;
return 0;
return -EINVAL;
}
}

Expand Down
Loading

0 comments on commit e8c9bd5

Please sign in to comment.