On Wed, 2008-11-26 at 15:38 +0200, Jouni Malinen wrote: > On Wed, Nov 26, 2008 at 12:04:24PM +0100, Johannes Berg wrote: > > > Thanks. A few other things that I just thought of: > > This version adds comment about _NO_HT, moves enum > nl80211_sec_chan_offset conversion from nl80211.c into > ieee80211_hw_config, changes enum to use NLA_U32, passes chan structure > (instead of freq int) into set_channel() handler. Cool, thanks, and sorry for all the delays. Acked-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> > > Index: wireless-testing/include/linux/nl80211.h > =================================================================== > --- wireless-testing.orig/include/linux/nl80211.h 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/include/linux/nl80211.h 2008-11-26 15:16:59.000000000 +0200 > @@ -26,8 +26,9 @@ > * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request > * to get a list of all present wiphys. > * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or > - * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME > - * and/or %NL80211_ATTR_WIPHY_TXQ_PARAMS. > + * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, > + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or > + * %NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET. > * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request > * or rename notification. Has attributes %NL80211_ATTR_WIPHY and > * %NL80211_ATTR_WIPHY_NAME. > @@ -180,6 +181,14 @@ > * /sys/class/ieee80211/<phyname>/index > * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) > * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters > + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz > + * @NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET: included with NL80211_ATTR_WIPHY_FREQ > + * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): > + * NL80211_SEC_CHAN_NO_HT = HT not allowed (i.e., same as not including > + * this attribute) > + * NL80211_SEC_CHAN_DISABLED = HT20 only > + * NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel > + * NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel > * > * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on > * @NL80211_ATTR_IFNAME: network interface name > @@ -315,6 +324,8 @@ > NL80211_ATTR_BSS_BASIC_RATES, > > NL80211_ATTR_WIPHY_TXQ_PARAMS, > + NL80211_ATTR_WIPHY_FREQ, > + NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET, > > /* add attributes here, update the policy in nl80211.c */ > > @@ -329,6 +340,8 @@ > #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY > #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES > #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS > +#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ > +#define NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET > > #define NL80211_MAX_SUPP_RATES 32 > #define NL80211_MAX_SUPP_REG_RULES 32 > @@ -742,4 +755,10 @@ > NL80211_TXQ_Q_BK > }; > > +enum nl80211_sec_chan_offset { > + NL80211_SEC_CHAN_NO_HT /* No HT */, > + NL80211_SEC_CHAN_DISABLED /* HT20 only */, > + NL80211_SEC_CHAN_BELOW /* HT40- */, > + NL80211_SEC_CHAN_ABOVE /* HT40+ */ > +}; > #endif /* __LINUX_NL80211_H */ > Index: wireless-testing/include/net/cfg80211.h > =================================================================== > --- wireless-testing.orig/include/net/cfg80211.h 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/include/net/cfg80211.h 2008-11-26 15:29:50.000000000 +0200 > @@ -392,6 +392,9 @@ > /* from net/wireless.h */ > struct wiphy; > > +/* from net/ieee80211.h */ > +struct ieee80211_channel; > + > /** > * struct cfg80211_ops - backend description for wireless configuration > * > @@ -450,6 +453,8 @@ > * @change_bss: Modify parameters for a given BSS. > * > * @set_txq_params: Set TX queue parameters > + * > + * @set_channel: Set channel > */ > struct cfg80211_ops { > int (*add_virtual_intf)(struct wiphy *wiphy, char *name, > @@ -513,6 +518,10 @@ > > int (*set_txq_params)(struct wiphy *wiphy, > struct ieee80211_txq_params *params); > + > + int (*set_channel)(struct wiphy *wiphy, > + struct ieee80211_channel *chan, > + enum nl80211_sec_chan_offset); > }; > > #endif /* __NET_CFG80211_H */ > Index: wireless-testing/net/mac80211/cfg.c > =================================================================== > --- wireless-testing.orig/net/mac80211/cfg.c 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/net/mac80211/cfg.c 2008-11-26 15:19:34.000000000 +0200 > @@ -1095,6 +1095,18 @@ > return 0; > } > > +static int ieee80211_set_channel(struct wiphy *wiphy, > + struct ieee80211_channel *chan, > + enum nl80211_sec_chan_offset sec_chan_offset) > +{ > + struct ieee80211_local *local = wiphy_priv(wiphy); > + > + local->oper_channel = chan; > + local->oper_sec_chan_offset = sec_chan_offset; > + > + return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); > +} > + > struct cfg80211_ops mac80211_config_ops = { > .add_virtual_intf = ieee80211_add_iface, > .del_virtual_intf = ieee80211_del_iface, > @@ -1122,4 +1134,5 @@ > #endif > .change_bss = ieee80211_change_bss, > .set_txq_params = ieee80211_set_txq_params, > + .set_channel = ieee80211_set_channel, > }; > Index: wireless-testing/net/wireless/nl80211.c > =================================================================== > --- wireless-testing.orig/net/wireless/nl80211.c 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/net/wireless/nl80211.c 2008-11-26 15:31:31.000000000 +0200 > @@ -59,6 +59,8 @@ > [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, > .len = BUS_ID_SIZE-1 }, > [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, > + [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, > + [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, > > [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, > [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, > @@ -359,6 +361,61 @@ > } > } > > + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { > + enum nl80211_sec_chan_offset sec_chan_offset = > + NL80211_SEC_CHAN_NO_HT; > + struct ieee80211_channel *chan; > + u32 freq, sec_freq; > + > + if (!rdev->ops->set_channel) { > + result = -EOPNOTSUPP; > + goto bad_res; > + } > + > + if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { > + sec_chan_offset = nla_get_u32( > + info->attrs[ > + NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); > + if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && > + sec_chan_offset != NL80211_SEC_CHAN_DISABLED && > + sec_chan_offset != NL80211_SEC_CHAN_BELOW && > + sec_chan_offset != NL80211_SEC_CHAN_ABOVE) { > + result = -EINVAL; > + goto bad_res; > + } > + } > + > + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); > + chan = ieee80211_get_channel(&rdev->wiphy, freq); > + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { > + /* Primary channel not allowed */ > + result = -EINVAL; > + goto bad_res; > + } > + if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) > + sec_freq = freq - 20; > + else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) > + sec_freq = freq + 20; > + else > + sec_freq = 0; > + > + if (sec_freq) { > + struct ieee80211_channel *schan; > + schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); > + if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) { > + /* Secondary channel not allowed */ > + result = -EINVAL; > + goto bad_res; > + } > + } > + > + result = rdev->ops->set_channel(&rdev->wiphy, chan, > + sec_chan_offset); > + if (result) > + goto bad_res; > + } > + > + > bad_res: > cfg80211_put_dev(rdev); > return result; > Index: wireless-testing/include/net/mac80211.h > =================================================================== > --- wireless-testing.orig/include/net/mac80211.h 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/include/net/mac80211.h 2008-11-26 15:15:47.000000000 +0200 > @@ -507,6 +507,9 @@ > > struct ieee80211_ht_conf { > bool enabled; > + int sec_chan_offset; /* 0 = HT40 disabled; -1 = HT40 enabled, secondary > + * channel below primary; 1 = HT40 enabled, > + * secondary channel above primary */ > }; > > /** > Index: wireless-testing/net/mac80211/util.c > =================================================================== > --- wireless-testing.orig/net/mac80211/util.c 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/net/mac80211/util.c 2008-11-26 15:20:26.000000000 +0200 > @@ -641,6 +641,7 @@ > chan->flags & IEEE80211_CHAN_NO_IBSS) > return ret; > local->oper_channel = chan; > + local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT; > > if (local->sw_scanning || local->hw_scanning) > ret = 0; > Index: wireless-testing/net/mac80211/ieee80211_i.h > =================================================================== > --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/net/mac80211/ieee80211_i.h 2008-11-26 15:20:12.000000000 +0200 > @@ -626,6 +626,7 @@ > struct delayed_work scan_work; > struct ieee80211_sub_if_data *scan_sdata; > struct ieee80211_channel *oper_channel, *scan_channel; > + enum nl80211_sec_chan_offset oper_sec_chan_offset; > u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; > size_t scan_ssid_len; > struct list_head bss_list; > Index: wireless-testing/net/mac80211/main.c > =================================================================== > --- wireless-testing.orig/net/mac80211/main.c 2008-11-26 15:15:31.000000000 +0200 > +++ wireless-testing/net/mac80211/main.c 2008-11-26 15:29:09.000000000 +0200 > @@ -195,20 +195,42 @@ > struct ieee80211_channel *chan; > int ret = 0; > int power; > + enum nl80211_sec_chan_offset sec_chan_offset; > > might_sleep(); > > - if (local->sw_scanning) > + if (local->sw_scanning) { > chan = local->scan_channel; > - else > + sec_chan_offset = NL80211_SEC_CHAN_NO_HT; > + } else { > chan = local->oper_channel; > + sec_chan_offset = local->oper_sec_chan_offset; > + } > > - if (chan != local->hw.conf.channel) { > + if (chan != local->hw.conf.channel || > + sec_chan_offset != local->hw.conf.ht.sec_chan_offset) { > local->hw.conf.channel = chan; > + switch (sec_chan_offset) { > + case NL80211_SEC_CHAN_NO_HT: > + local->hw.conf.ht.enabled = false; > + local->hw.conf.ht.sec_chan_offset = 0; > + break; > + case NL80211_SEC_CHAN_DISABLED: > + local->hw.conf.ht.enabled = true; > + local->hw.conf.ht.sec_chan_offset = 0; > + break; > + case NL80211_SEC_CHAN_BELOW: > + local->hw.conf.ht.enabled = true; > + local->hw.conf.ht.sec_chan_offset = -1; > + break; > + case NL80211_SEC_CHAN_ABOVE: > + local->hw.conf.ht.enabled = true; > + local->hw.conf.ht.sec_chan_offset = 1; > + break; > + } > changed |= IEEE80211_CONF_CHANGE_CHANNEL; > } > > - > if (!local->hw.conf.power_level) > power = chan->max_power; > else
Attachment:
signature.asc
Description: This is a digitally signed message part