2007-09-21 20:44:58

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 0/5] Add central regulatory domain agent - Patchset I

Patchset I - Add central regulatory domain agent

This is patchset I of II which adds a central regulatory domain
agent onto the wireless subsystem. I've split it into two patchsets in order
to introduce the agent before affecting mac80211 drivers. This allows work
to continue on the central reg agent independant of mac80211
advancements.

Patch series I adds the central regulatory domain agent and
integrates it with cfg80211. The central reg agent consists of 2
main modules:

* ISO3166-1
* Regdomains

Additionally, changing regulatory domains can be acomplished through
the use of a new configfs module which will be introduced for
the wireless subsystem.

Patch series II will add support for the centreal reglatory agent
onto mac80211, remove mac80211's simple regulatory control and and
replace each driver's own regulatory domain implementation with the
central one.

Luis


Attachments:
(No filename) (887.00 B)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-26 15:48:25

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On 9/26/07, Dan Williams <[email protected]> wrote:
> On Mon, 2007-09-24 at 13:49 -0400, Luis R. Rodriguez wrote:
> > On 9/24/07, Joerg Mayer <[email protected]> wrote:
> > > On Fri, Sep 21, 2007 at 05:33:42PM -0400, Luis R. Rodriguez wrote:
> > > > > > + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> > > > > > + *
> > > > > > + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> > > > > > + * is in charge of filling most of these fields out. The low-level driver
> > > > > > + * is expected to fill in, if needed, the val field. Note that val is already
> > > > > > + * set by the regulatory agent to the same channel as in chan.
> > > > >
> > > > > Shouldn't you also set chan and freq in the driver?
> > > [...]
> > > > Initially I wanted to move mac80211 to use a linked list of channels
> > > > instead of an array for each mode. As we discussed it over (you, me
> > > > and a few others) we determined it wasn't best to do this (I have a
> > > > patch that allows this just in case we later change our mind). But --
> > > > previous to doing this I had a wrapper on ieee80211_channel as I
> > > > wanted the central regdomain to have a linked list of reg domain
> > > > channels. If we don't want a wrapper we have to add this to the
> > > > ieee8021_channel struct. Otherwise I need to define my own channel
> > > > struct which wraps around ieee80211_channel.
> > > >
> > > > > > +struct ieee80211_channel {
> > > > > > + /* XXX change to u8 */
> > > > > > + short chan;
> > > > >
> > > > > Not sure, is a u8 always enough? I thought 802.11a had huge channel
> > > > > numbers?
> > > >
> > > > Not that huge :-) Highest I've heard is 220. u8 should suffice.
> > >
> > > What's the idea of working with channels? Channels are non-uniq numbers.
> > > Internally everything should work with center frequency and not with
> > > channels. If necessary, information should be converted from channels
> > > by the driver when reporting it into the stack. That way there also won't
> > > be any problems if there ever is a channel 417.
> >
> > I agree. I'm OK with just having center of freq. Right now WE supports
> > channel or freqs and the value is passed directly to the driver (for
> > FullMAC) or mac80211 (for SoftMAC). For nl80211 we can just support
> > channel passing onto the kernel, if the user supplies a channel we'll
> > do the conversion to freq in userspace. On step at a time.
>
> Definitely need to use freq and not channel. Channels are not unique
> (they just _happen_ to be so right now). Of course remember that we
> can't just pass channel really, we need to pass the tuple of (channel,
> band) or maybe even (channel, [A|B|G|N]) or something.

AFAICT channels are unique per 2GHz and 5GHz band. As far as the
regulatory code I have is concerned we have:

2GHz: 2412 - 2732 (ch 1 - 26)
5GHz: 5005 - 6100 (ch 1 - 220)

However, the problem really is with some channels which have its
center of frequency below this range. Only special hardware can go out
of this range. An example is the Atheros device's transceiver which
supports frequencies in the range of 4920 to 6100 MHz and 2312 to
2732 MHz. In this case 2312MHz would be channel -19... Regulatory-wise
I have read only about MKK allowing frequencies in the 4.8GHz range, I
am not 100% certain though and the current regulatory agency does
allow for its use, I'll ask. In the current regulatory work we don't
allow for those channels. If it is the case that some reg agencies
allow for it we'll need to need to figure out a way to map this lower
bound frequency range.

Kernel-wise I think we should stick to center of frequencies. If new
userspace wants to speak in terms of channels we should just have
userspace do the conversion to freq. The exception here would be old
Wireless-Extensions which already supports passing channel numbers.
For WE we can just not support the lower freqs as new userspace
utilities should use the new nl80211 interface.

Luis

2007-09-21 21:56:52

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module

On Fri, 2007-09-21 at 17:52 -0400, Luis R. Rodriguez wrote:

> > Then we can use "enum ieee80211_band" below in the structs and get type
> > checking. Generally, no new stuff has anything to do with
> > include/net/ieee80211.h, that's just for the old "stack".
>
> Sure, I just wanted to point out the band def existed in another
> header. My hopes is we can address all common header stuff once in for
> all. I guess it'll have to wait a bit more.

Oh ok. But I think we should start using sane values (these bits look
awfully like you could OR them which is totally bogus) and convert the
other stack over.

> > > + * @name: name for this subband.
> >
> > Why does it need a name?
>
> Well to distinguish it.

But why do we need to distinguish subbands by name? What do we use them
for anyway?

> > > + * @min_freq: minimum frequency for this subband, in MHz. This represents the
> > > + * center of frequency of a channel.
> > > + * @max_freq: maximum frequency for this subband, in MHz. This represents the
> > > + * center of frequency of a channel.
> >
> > How can both be center freq?
>
> min_freq is the center of frequency for the minimum channel on the
> subband. max_freq is the center of frequency for the max channel on
> the subband. I guess I should clear that up a little more huh.

Uh ok, no, I just need to read better :)

> > > +/**
> > > + * struct ieee80211_regdomain - defines a regulatory domain
> > > + *
> > > + * @regdomain_id: ID of this regulatory domain. Some come from
> > > + * http://standards.ieee.org/getieee802/download/802.11b-1999_Cor1-2001.pdf
> > > + * @regdomain_name: name of this regulatory domain.
> > > + * @list: node, part of band_restrictions_list
> > > + *
> > > + * This structure defines a regulatory domain, which consists of channel and
> > > + * power restrictions. Some regulatory domains come from
> > > + * 802.11b-1999_Cor1-2001, the rest are based on Reyk Floeter's ar5k. If
> > > + * there is need to add more values here, please add one that is either
> > > + * defined in a standard or that many hardware devices have adopted. Also
> > > + * note that multiple countries can map to the same @regdomain_id
> >
> > There's no table here where you could add values, is there?.
>
> There is a lot of them.. but we can add few to show as an example.

Then again. Why do we have this struct in a header file?

> I should have explained that too. Well, if you may recall in my last
> implementation of this I actually used a linked list. I then decided
> we weren't going to add new 2.4GHz or 5GHz subbands unless a big
> IEEE-802.11 change occurs. That doesn't happen so often to either use
> linked list or a variable length array.

Ok I just don't understand why you have this information in a struct.
Shouldn't all of this information be essentially internal to the
regulatory code, and people who use it simply query it and get back a
pointer to the subband that applies to their query? I don't see why
everybody needs to see this huge array.

johannes


Attachments:
signature.asc (190.00 B)
This is a digitally signed message part

2007-09-21 21:52:14

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module

On 9/21/07, Johannes Berg <[email protected]> wrote:
> On Fri, 2007-09-21 at 17:04 -0400, Luis R. Rodriguez wrote:
>
> > +/* XXX: <net/ieee80211.h> has two band defs bellow */
> > +#ifndef IEEE80211_24GHZ_BAND
> > +#define IEEE80211_24GHZ_BAND (1<<0)
> > +#define IEEE80211_52GHZ_BAND (1<<1)
> > +#endif
>
> Hmm. Could we make a new definition with just an enum?
>
> enum ieee80211_band {
> IEEE80211_BAND_24GHZ,
> IEEE80211_BAND_52GHZ,
> };
>
> Then we can use "enum ieee80211_band" below in the structs and get type
> checking. Generally, no new stuff has anything to do with
> include/net/ieee80211.h, that's just for the old "stack".

Sure, I just wanted to point out the band def existed in another
header. My hopes is we can address all common header stuff once in for
all. I guess it'll have to wait a bit more.

> > +/**
> > + * struct ieee80211_subband_restrictions - defines a regulatory domain
> > + * subband restrictions list
>
> I think the docs should include where this structure is used.

Point taken.

> > + * @name: name for this subband.
>
> Why does it need a name?

Well to distinguish it.

> > + * @min_freq: minimum frequency for this subband, in MHz. This represents the
> > + * center of frequency of a channel.
> > + * @max_freq: maximum frequency for this subband, in MHz. This represents the
> > + * center of frequency of a channel.
>
> How can both be center freq?

min_freq is the center of frequency for the minimum channel on the
subband. max_freq is the center of frequency for the max channel on
the subband. I guess I should clear that up a little more huh.

> > +struct ieee80211_subband_restrictions {
> > + u8 band;
> > + char name[REGSBNAMSIZ];
> > + u16 min_freq;
> > + u16 max_freq;
> > + u32 modulation_cap;
> > + u8 max_antenna_gain;
> > + u8 max_ir_ptmp;
> > + u8 max_ir_ptp;
> > +#define REG_DIPOLE_ANTENNA_GAIN 2
> > + u8 max_eirp_ptmp;
> > + u8 max_eirp_ptp;
> > +#define REG_CAP_INDOOR 'I'
> > +#define REG_CAP_OUTDOOR 'O'
> > +#define REG_CAP_INOUT ' '
>
> Did you actually run kernel-doc? it's rather unhappy with such things :)

Nope, sorry.

> > +/**
> > + * struct ieee80211_regdomain - defines a regulatory domain
> > + *
> > + * @regdomain_id: ID of this regulatory domain. Some come from
> > + * http://standards.ieee.org/getieee802/download/802.11b-1999_Cor1-2001.pdf
> > + * @regdomain_name: name of this regulatory domain.
> > + * @list: node, part of band_restrictions_list
> > + *
> > + * This structure defines a regulatory domain, which consists of channel and
> > + * power restrictions. Some regulatory domains come from
> > + * 802.11b-1999_Cor1-2001, the rest are based on Reyk Floeter's ar5k. If
> > + * there is need to add more values here, please add one that is either
> > + * defined in a standard or that many hardware devices have adopted. Also
> > + * note that multiple countries can map to the same @regdomain_id
>
> There's no table here where you could add values, is there?.

There is a lot of them.. but we can add few to show as an example.

> > + */
> > +struct ieee80211_regdomain {
> > + u32 regdomain_id;
> > + char regdomain_name[REGNAMSIZ];
> > + struct ieee80211_subband_restrictions subbands[REG_NUM_SUBBANDS];
>
> Why is that not a variable length array with the number of items given
> in an extra var?

I should have explained that too. Well, if you may recall in my last
implementation of this I actually used a linked list. I then decided
we weren't going to add new 2.4GHz or 5GHz subbands unless a big
IEEE-802.11 change occurs. That doesn't happen so often to either use
linked list or a variable length array.

> > + * This structure holds the mapping of the country to a specific regulatory
> > + * domain. Keep in mind more than one country can map to the same regulatory
> > + * domain. The ISO-3166-1 alpha2 country code also happens to be used in the
> > + * 802.11d Country Information Element on the string for the country. It
> > + * should be noted, however, that in that the size of this string, is
> > + * three octects while our string is only 2. The third octet is used to
> > + * indicate Indoor/outdoor capabilities which we set in
> > + * @ieee80211_subband_restrictions environment_cap.
> > + */
> > +struct ieee80211_iso3166_reg_map {
> > + char alpha2[ISOCOUNTRYSIZ2];
> > + u32 regdomain_id; /* stack-aware value */
> > + /* XXX: shall we just use an array? */
> > + struct list_head list; /* node, part of iso3166_reg_map_list */
> > +};
>
> Why does this need a list if it's a static mapping? Why does it need to
> be visible outside of net/wireless/?

As you can notice I also considered this. This *should* only change in
case of an ISO-3166 change or a new regulatory agency rule enforcement
change. Neither of which are really that common, I think so you're
right, we can leave this static.

> > +/**
> > + * regdomain_mhz2ieee - convert a frequency to an IEEE-80211 channel number
> > + * @freq: center of frequency in MHz. We support a range:
> > + * 2412 - 2732 MHz (Channel 1 - 26) in the 2GHz band and
> > + * 5005 - 6100 MHz (Channel 1 - 220) in the 5GHz band.
> > + *
> > + * Given a frequency in MHz returns the respective IEEE-80211 channel
> > + * number. You are expected to provide the center of freqency in MHz.
> > + */
> > +u16 regdomain_mhz2ieee(u16 freq);
>
> Ok this I can see being necessary for drivers/stacks.
>
> > +u16 regdomain_ieee2mhz(u16 chan, u8 band);
>
> Same here.
>
> > +void print_regdomain(struct ieee80211_regdomain *);
>
> Ssame.
>
> > +void print_iso3166_reg_map(void);
>
> But why does this need to be exported?

Point taken.

> > +int get_ieee80211_regname(u32, char *);
>
> What are the arguments?

This can be removed.

Luis

2007-09-21 21:16:50

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 5/5] Wireless: add wireless configfs module - v2

Oops, this patch actually adds congifs_wireless.c ;)

This patch adds a wireless configfs module. Currently we only add
support for changing the central regulatory domain. The idea is not to
replace nl80211 interface but to supplement it and also to give home
for a place for configuring wireless kobjects. We can move add_interface /
remove_interface from sysfs to configfs, for example.

Example usage of using wireles configfs:

mkdir /config/

modprobe configfs_wireless
mount -t configfs none /config
echo US > /config/wireless/country
dmesg -c

You will see:

Userspace changed regulatory domain
ieee80211_regdomains: regulatory domain FCC1A created
Regulatory Domain: FCC1A Regulatory Domain ID: 0x10
IEEE 802.11g 2GHz ISM subband
max_ir_ptmp: 30 dBm max_ir_ptp: 30 dBm
max_eirp_ptmp: 36 dBm max_eirp_ptp: 255 dBm
max_antenna_gain: 6 dBi
Environment capability: Indoor & Outdoor
Channel Freq (MHz)
1 2412
2 2417
3 2422
4 2427
5 2432
6 2437
7 2442
8 2447
9 2452
10 2457
11 2462
---
net/wireless/Kconfig | 11 +++++++++++
net/wireless/Makefile | 1 +
2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 0505347..59e47ce 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -15,6 +15,17 @@ config NL80211

If unsure, say Y.

+config CONFIGFS_WIRELESS
+ depends CFG80211 && IEEE80211_REGDOMAINS
+ tristate "Configfs interface for configuring central wireless settings"
+ ---help---
+ You can configure central wireless settings through this subsystem.
+ It currently only has an ISO3166-1 alpha2 country regulatory domain
+ settings used to define frequency and power regulatory restrictions
+ for all wireless cards.
+
+ If unsure, you can safely say Y.
+
config IEEE80211_REGDOMAINS
tristate "Central IEEE 802.11 regulatory domain agent"
select ISO3166_1
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 74c1059..b3f5daa 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_WIRELESS_EXT) += wext.o
obj-$(CONFIG_CFG80211) += cfg80211.o
+obj-$(CONFIG_CONFIGFS_WIRELESS) += configfs_wireless.o

cfg80211-y += core.o sysfs.o radiotap.o
cfg80211-$(CONFIG_NL80211) += nl80211.o
diff --git a/net/wireless/configfs_wireless.c b/net/wireless/configfs_wireless.c
new file mode 100644
index 0000000..78b5777
--- /dev/null
+++ b/net/wireless/configfs_wireless.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2007 Luis R. Rodriguez <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Based on configfs example
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+#include <net/ieee80211_regdomains.h>
+#include <net/cfg80211.h>
+
+/*
+ * Wireless configs subsystem
+ *
+ * You can use this to configure central wireless settings. Currently
+ * we only support an ISO3166-1 alpha2 country settting which defines
+ * the central regulatory domain.
+ *
+ */
+
+struct regdomain_settings {
+ struct configfs_subsystem subsys;
+ char country[ISOCOUNTRYSIZ2];
+};
+
+struct regdomain_settings_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct regdomain_settings *, char *);
+ ssize_t (*store)(struct regdomain_settings *, const char *, size_t);
+};
+
+static inline struct regdomain_settings *to_regdomain_settings(struct config_item *item)
+{
+ return item ? container_of(to_configfs_subsystem(
+ to_config_group(item)), struct regdomain_settings, subsys) :
+ NULL;
+}
+
+static ssize_t country_read(struct regdomain_settings *reg,
+ char *page)
+{
+ return snprintf(page, ISOCOUNTRYSIZ2+1, "%s\n", reg->country);
+}
+
+static ssize_t country_write(struct regdomain_settings *reg_settings,
+ const char *page,
+ size_t count)
+{
+ int r;
+ u32 regdomain_id = 0;
+ char alpha2[ISOCOUNTRYSIZ2];
+
+ memcpy(alpha2, page, ISOCOUNTRYSIZ2-1);
+ r = iso3166_to_reg(alpha2, &regdomain_id);
+ if(r)
+ return r;
+ r = cfg80211_set_regdomain(alpha2, regdomain_id,
+ REG_SET_BY_USER, NULL);
+ if (r)
+ return r;
+ memcpy(reg_settings->country, alpha2, ISOCOUNTRYSIZ2);
+ return count;
+}
+
+static struct regdomain_settings_attribute wireless_attr_country = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "country", .ca_mode = S_IRUGO | S_IWUSR },
+ .show = country_read,
+ .store = country_write,
+};
+
+static struct configfs_attribute *wireless_attrs[] = {
+ &wireless_attr_country.attr,
+ NULL,
+};
+
+static ssize_t wireless_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct regdomain_settings *reg_settings = to_regdomain_settings(item);
+ struct regdomain_settings_attribute *childless_attr =
+ container_of(attr, struct regdomain_settings_attribute, attr);
+ ssize_t ret = 0;
+
+ if (childless_attr->show)
+ ret = childless_attr->show(reg_settings, page);
+ return ret;
+}
+
+static ssize_t wireless_attr_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct regdomain_settings *reg_settings = to_regdomain_settings(item);
+ struct regdomain_settings_attribute *childless_attr =
+ container_of(attr, struct regdomain_settings_attribute, attr);
+ ssize_t ret = -EINVAL;
+
+ if (childless_attr->store)
+ ret = childless_attr->store(reg_settings, page, count);
+ return ret;
+}
+
+static struct configfs_item_operations wireless_item_ops = {
+ .show_attribute = wireless_attr_show,
+ .store_attribute = wireless_attr_store,
+};
+
+static struct config_item_type wireless_type = {
+ .ct_item_ops = &wireless_item_ops,
+ .ct_attrs = wireless_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct regdomain_settings wireless_subsys = {
+ .subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "wireless",
+ .ci_type = &wireless_type,
+ },
+ },
+ },
+};
+
+static int __init configfs_wireless_init(void)
+{
+ int ret = 0;
+ struct configfs_subsystem *subsys = &wireless_subsys.subsys;
+ config_group_init(&subsys->su_group);
+ mutex_init(&subsys->su_mutex);
+ ret = configfs_register_subsystem(subsys);
+ if (ret) {
+ printk(KERN_ERR "Error %d while registering wireless "
+ "subsystem %s\n", ret,
+ subsys->su_group.cg_item.ci_namebuf);
+ goto out_unregister;
+ }
+ return 0;
+out_unregister:
+ configfs_unregister_subsystem(subsys);
+ return ret;
+}
+
+static void __exit configfs_wireless_exit(void)
+{
+ configfs_unregister_subsystem(&wireless_subsys.subsys);
+}
+
+
+module_init(configfs_wireless_init);
+module_exit(configfs_wireless_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("Central configfs interface for all wireless devices");
+MODULE_AUTHOR("Luis R. Rodriguez <[email protected]>");


Attachments:
(No filename) (7.69 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-21 21:43:27

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On Fri, 2007-09-21 at 16:46 -0400, Luis R. Rodriguez wrote:
> Patchset I - Add central regulatory domain agent
>
> This is patchset I of II which adds a central regulatory domain
> agent onto the wireless subsystem. I've split it into two patchsets in order
> to introduce the agent before affecting mac80211 drivers. This allows work
> to continue on the central reg agent independant of mac80211
> advancements.
>
> Patch series I adds the central regulatory domain agent and
> integrates it with cfg80211. The central reg agent consists of 2
> main modules:
>
> * ISO3166-1
> * Regdomains

Also, if you could make sure this stuff is completely separate
conceptually and architecturally from mac80211 itself, but have mac80211
_rely_ on it, then we can rip the bits out of the fullmac drivers that
do regdomain stuff and plug them into this framework too. I think
that's a real win. There's not a pile of code in the fullmac drivers
for this, but there's enough that it sucks having to have these defines
all over the place.

Also having somewhere that has standard functions that map channels to
frequencies and back would rock (if you do, please use u32 here for
frequencies not floats of course, like 2412000 and such unless you think
u64 would work better to specify down to the single Hz level).

Dan

> Additionally, changing regulatory domains can be acomplished through
> the use of a new configfs module which will be introduced for
> the wireless subsystem.
>
> Patch series II will add support for the centreal reglatory agent
> onto mac80211, remove mac80211's simple regulatory control and and
> replace each driver's own regulatory domain implementation with the
> central one.
>
> Luis


2007-09-21 21:33:44

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On 9/21/07, Johannes Berg <[email protected]> wrote:
> On Fri, 2007-09-21 at 17:00 -0400, Luis R. Rodriguez wrote:
>
> Ok one thing up front: I'm looking at this basically as "new code", iow
> something we should do right from the start. mac80211 stuff is a mess,
> so imho we should clean it up at this point when we break things anyway.

ACK. Hence the reason why I separated this into two patch series. The
first one allows integration so we can simply hack on it at will. The
idea is to clean this up really well for when it goes upstream.

> > + * @IEEE80211_CHAN_W_SCAN: if this flag is set it informs the lower layer that
> > + * this channel can be passively scanned for.
>
> Are there really channels that don't have _SCAN?

Yup, as you will see, for example for Japan regdomains we disable SCAN
for 5170, 5190, 5210 and 5230 MHz.

> > +/**
> > + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> > + *
> > + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> > + * is in charge of filling most of these fields out. The low-level driver
> > + * is expected to fill in, if needed, the val field. Note that val is already
> > + * set by the regulatory agent to the same channel as in chan.
>
> Shouldn't you also set chan and freq in the driver?

Sure, later (patch series II) mac80211 util.c will have a routine
which can build the array of channels for each mode. The reg agent
will just set everything to the most common values most drivers uses,
which is to keep using the same channel mapping and the same freq
mapping. Drivers will each have their own channel arrays, for example.
The central reg agent will just be used by the higher subsystems to
enable/disable channels and update power restrictions.

> > + * @modulation_cap: could be IEEE80211_RATE_*
>
> Could be?

We can define our own if we can't borrow those.

> > + * @list: lets you make this structure part of a linked list
>
> What do we need this for?

Initially I wanted to move mac80211 to use a linked list of channels
instead of an array for each mode. As we discussed it over (you, me
and a few others) we determined it wasn't best to do this (I have a
patch that allows this just in case we later change our mind). But --
previous to doing this I had a wrapper on ieee80211_channel as I
wanted the central regdomain to have a linked list of reg domain
channels. If we don't want a wrapper we have to add this to the
ieee8021_channel struct. Otherwise I need to define my own channel
struct which wraps around ieee80211_channel.

> > +struct ieee80211_channel {
> > + /* XXX change to u8 */
> > + short chan;
>
> Not sure, is a u8 always enough? I thought 802.11a had huge channel
> numbers?

Not that huge :-) Highest I've heard is 220. u8 should suffice.

> > +/* XXX consider removing the holes bellow */
>
> I think these flags are shared with hostapd right now... :(

Then more reasons to move this out of mac80211 and later consolidate
into one place. That is the idea with this move. To start this.

> > +/**
> > + * enum rate_flags - internal &ieee80211_rate flags
>
> > + * Use these flags to indicate to the lower layers details about an
> > + * &ieee80211_rate.
> ^ struct ieee80211_rate, for kernel-doc
>
> > + * @IEEE80211_RATE_ERP: indicates if the rate is an Extended Rate PHY (ERP)
> > + * @IEEE80211_RATE_BASIC: indicates the rate is a basic rate for the
> > + * currently used mode
> > + * @IEEE80211_RATE_PREAMBLE2: used to indicates that the rate for short
> > + * preamble is to be used. This is set in &ieee80211_rate's @val2.
>
> Couldn't we just call it SHORT_PREAMBLE? :)

Sure, I just went with what was on mac80211. If this is added to
everything branch we can then clean it up as a subsequent patch.

> > + * @IEEE80211_RATE_SUPPORTED: indicates if rate is supported by the given mode
>
> What do we use this for?
>
> > + * @IEEE80211_RATE_OFDM: indicates support for ODFM modulation
> > + * @IEEE80211_RATE_CCK: indicates support for CCK modulation
>
> I think this should be called "this rate is an OFDM/CCK rate"

Sure, good point.

> > + * @IEEE80211_RATE_MANDATORY: indicates if this rate is mandatory for the
> > + * currently used mode
>
> I think this is wrong. Isn't the "mandatory" flag something for an AP to
> ask it's stations for?

I'm not too sure, if so this can be fixed by a following patch.

> > +/* XXX move to inline and add documenation, kernel-doc can't doc
> > defines */
>
> Why don't you just do that then? :)

Hehe, I was, but I got tired of hogging this code up, and wanted to
post it for more review. A quick patch can fix this too ;)

> > + * Low-level driver should set PREAMBLE2, OFDM and CCK flags.
> > + * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
> > + * configuration.
>
> Oh come on. There hasn't been 80211.o for a loong time :)

Sorry, I moved docs from mac80211, I should have caught that :-P

> > + * @flags: IEEE80211_RATE_* flags
> > + * @val2: hw specific value for the rate when using short preamble
> > + * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
> > + * 2, 5.5, and 11 Mbps)
>
> Can't we just get rid of this field? Does anybody use it?

Not too sure. Anyone?

> > + * @min_rssi_ack: Minimum required RSSI of packet to generate an ACK ??
> > + * @min_rssi_ack_delta: ??
>
> I thought we didn't use these fields.

Oops.. that was supposed to be removed, yes.

> > + /* the following fields are set by 80211.o and need not be filled by the
>
> 80211.o again :)

Oopsy :-)

Luis

2007-09-22 00:22:25

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On Fri, Sep 21, 2007 at 08:14:09PM -0400, Luis R. Rodriguez wrote:
> http://www.kernel.org/pub/linux/kernel/people/mcgrof/v2-regdomain-pat=
ches/

Oh and bellow inline is the Documenation/networking/regdomains.txt I
have so far.. its not much but its a start:

Luis

---

Linux central regulatory domain agent
-------------------------------------

The central reg agent consists of two main parts:

* ISO3166-1 module (iso3166-1.ko)
* Regulatory module (regdomains.ko)

Integration with the kernel wireless subsystem is done by extending cfg=
80211
to support a central regulatory domain to which all devices should adhe=
re to.
Then, mac80211 is expanded to allow devices to indicate their deivice i=
s
configured to a specific regulatory domain domain, set set either in it=
s EEPROM
or firmware. Helper routines are also provided for mac80211 to build th=
e=20
ieee80211_channel array of hardware supported channels.

After a regulatory domain is set all cfg80211 devices are scanned for a=
nd
their channels are iterated over, only channels which the regulatory do=
main
indicates are valid for its current regulatory domain are enabled. Powe=
r
restriction for PtP and PtMP type of connections are also considered=20
and set.

Each country can be mapped to one regulatory domain. Each regulatory do=
main=20
has two maps for channels, one on the 2.4GHz band and another on the 5G=
Hz band.
Power restrictions are a little more complicated -- we break both the 2=
GHz band
and the 5GHz band into 7 logical subbands as follows:

Subband name Min (MHz) Max (MHz) IEEE-802.11 Channel range
ISM-2.4 2412 2732 1-26
Telec 5005 5145 1-29
UNII-1 5150 5245 30-49
UNII-2 5250 5350 50-70
ETSI 5355 5720 71-144
UNII-3 5725 5825 145-165
AAD 5830 6100 166-220

Note that ETSI also operates on UNII-2, we split this into logical name=
s just
to be pragmatic. Then for each subband we define specific power restric=
tions.

The current regualtory map is found in regulatory_map.h A userspace dae=
mon can
later be provided to update the regulatory map. At the very least the k=
ernel
should have the world regulatory domain but note that due to large amou=
nt of
varied restrictions this means only enabling 3 channels on the 2GHz ban=
d=20
(5, 6 and 7) and no channels on the 5GHz band with minimal PtMP power
restrictions.

=46or further implementation details please refer kerneldoc of iso3166-=
1,=20
regdomains, cfg80211, and mac80211.=20

---

Wireles regulatory primer:

PtMP - Point to Multipoint
PtP - Point to Point

EIRP - Equivalent Isotropically Radiated Power
IR - Intentional Radiator, transmitter
dBm - dB milliwatt (mW), the base says that 1mW =3D 0 dBm
dBi - dB relative to isotropic, used to measure antenna gain compared t=
o an
isotropic antenna on which radiation is distributed uniformly on the
surface of a sphere=20

EIRP =3D IR - loss in transmission line + passive gain of the antenna

---

Some information based on:=20

http://university.cyberarmy.net/kb/tiki-index.php?page=3DThe+Power+of+8=
02.11

Bellow is an example for FCC.

In the 2.4Ghz ISM band the FCC stipulates that the creation of PtMP=20
links be subject to the following restrictions:
- EIRP must not exceed 36 dBm (4W)
- IR must not exceed 30 dBm (1W)
- For every 3 dBi of antenna gain after the first 6 =E2=80=9Cfree=E2=80=
=9D dBi the IR must=20
be decreased by 3 dBi (the 1:1 rule)

Example (without considering loss) of possible settings if Max EIRP is=20
defined as 36 dBm and we are using the 1:1 rule:

TX power (dBm) Antenna Gain (dBi) Max EIRP (dBm)
30-------------------6----------------------36
29-------------------7----------------------36
28-------------------8----------------------36
27-------------------9----------------------36=20

=46or PtP links that rule is augmented:
- No Maximum EIRP
- IR is limited to 30 dBm (1W)
- For every 3 dBi after the first 6 of antenna gain the IR must be=20
decreased by 1 dBi (the 3:1 rule)

Example, where IR limit is 30, and has the 3:1 rule above for gain:

TX power (dBm) Antenna Gain (dBi) Effective EIRP (dBm)
29-------------------6-----------------------35
30-------------------6-----------------------36
29-------------------9-----------------------38
28-------------------12----------------------40
27-------------------15----------------------42
26-------------------18----------------------44
25-------------------21----------------------46=20

In the 5GHz band the FCC stipulates for PtMP:

- UNII-1: Maximum IR power may not exceed 40mW (16dBm)
- UNII-1: EIRP may not exceed 160mW (22dBm)
- UNII-2: Maximum IR power may not exceed 200mW (23dBm)
- UNII-2: EIRP may not exceed 800mW (29dBm)
- UNII-3: Maximum IR power may not exceed 800mW (29dBm)
- UNII-3: EIRP may not exceed 3.2W (35dBm)
- All three bands utilize the 1:1 rule

=46or PtP:

- UNII-1 Follows the same rules as the PtMP links
- UNII-2 Follows the same rules as the PtMP links
- UNII-3 May use an antenna with up to 23dBi of gain before the 1:1 rul=
e=20
becomes effective. (Giving a maximum EIRP of 200W!!)

2007-09-24 10:07:49

by Joerg Mayer

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On Fri, Sep 21, 2007 at 05:33:42PM -0400, Luis R. Rodriguez wrote:
> > > + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> > > + *
> > > + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> > > + * is in charge of filling most of these fields out. The low-level driver
> > > + * is expected to fill in, if needed, the val field. Note that val is already
> > > + * set by the regulatory agent to the same channel as in chan.
> >
> > Shouldn't you also set chan and freq in the driver?
[...]
> Initially I wanted to move mac80211 to use a linked list of channels
> instead of an array for each mode. As we discussed it over (you, me
> and a few others) we determined it wasn't best to do this (I have a
> patch that allows this just in case we later change our mind). But --
> previous to doing this I had a wrapper on ieee80211_channel as I
> wanted the central regdomain to have a linked list of reg domain
> channels. If we don't want a wrapper we have to add this to the
> ieee8021_channel struct. Otherwise I need to define my own channel
> struct which wraps around ieee80211_channel.
>
> > > +struct ieee80211_channel {
> > > + /* XXX change to u8 */
> > > + short chan;
> >
> > Not sure, is a u8 always enough? I thought 802.11a had huge channel
> > numbers?
>
> Not that huge :-) Highest I've heard is 220. u8 should suffice.

What's the idea of working with channels? Channels are non-uniq numbers.
Internally everything should work with center frequency and not with
channels. If necessary, information should be converted from channels
by the driver when reporting it into the stack. That way there also won't
be any problems if there ever is a channel 417.

ciao
Joerg

2007-09-21 21:04:25

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module

This adds the regulatory domain module. It provides a way to
allocate and construct a regulatory domain based on the current
map. This module provides no enforcement, it just does the actual
building of the regdomain and returns it as defined in ieee80211_regdomains.h

This module depends on the ISO3166-1 module.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
include/net/ieee80211_regdomains.h | 196 ++++++++
net/wireless/Kconfig | 16 +
net/wireless/Makefile | 1 +
net/wireless/reg_common.h | 138 ++++++
net/wireless/regdomains.c | 751 ++++++++++++++++++++++++++++++
net/wireless/regulatory_map.h | 887 ++++++++++++++++++++++++++++++++++++
6 files changed, 1989 insertions(+), 0 deletions(-)
create mode 100644 include/net/ieee80211_regdomains.h
create mode 100644 net/wireless/reg_common.h
create mode 100644 net/wireless/regdomains.c
create mode 100644 net/wireless/regulatory_map.h

diff --git a/include/net/ieee80211_regdomains.h b/include/net/ieee80211_regdomains.h
new file mode 100644
index 0000000..adf4de4
--- /dev/null
+++ b/include/net/ieee80211_regdomains.h
@@ -0,0 +1,196 @@
+#ifndef _IEEE80211_REGDOMAIN_H
+#define _IEEE80211_REGDOMAIN_H
+/*
+ * Copyright (C) 2006-2007 Luis R. Rodriguez <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <net/wireless_common.h>
+#include <net/iso3166-1.h>
+
+#define REGDOMAINS_VERSION "1.0"
+#define REGNAMSIZ 22
+#define REGSBNAMSIZ 30
+
+/* Changing this will change the default regulatory domain
+ * for countries we don't have a map for. Use World as default */
+#define DEFAULT_REG_ISO3166_1 "00"
+
+/* XXX: <net/ieee80211.h> has two band defs bellow */
+#ifndef IEEE80211_24GHZ_BAND
+#define IEEE80211_24GHZ_BAND (1<<0)
+#define IEEE80211_52GHZ_BAND (1<<1)
+#endif
+
+#define MAX_NUM_MODE_A_CHANS 220
+#define MAX_NUM_MODE_B_CHANS 26
+#define MAX_NUM_MODE_G_CHANS 26
+
+#define REG_NUM_SUBBANDS 7
+
+/**
+ * struct ieee80211_subband_restrictions - defines a regulatory domain
+ * subband restrictions list
+ *
+ * @band: which band we this subband belongs to, could be either IEEE80211_24GHZ_BAND
+ * or IEEE80211_52GHZ_BAND
+ * @name: name for this subband.
+ * @min_freq: minimum frequency for this subband, in MHz. This represents the
+ * center of frequency of a channel.
+ * @max_freq: maximum frequency for this subband, in MHz. This represents the
+ * center of frequency of a channel.
+ * @modulation_cap: modulations this subband is capable of handling. This can be
+ * IEEE80211_RATE_OFDM, IEEE80211_RATE_CCK
+ * @environment_cap: defines indoor/outdoor capability for subband as defined by
+ * the 802.11d Country Information element char. This can be
+ * Indoor REG_CAP_INDOOR ('I'), REG_CAP_OUTDOOR ('O'), or both
+ * REG_CAP_INOUT (' ').
+ * @max_antenna_gain: defines the maximum antenna gain set by regulatory
+ * agencies for this subband. This is expressed in dBi, which is
+ * dB relative to isotropic, used to measure antenna gain compared to an
+ * isotropic antenna on which radiation is distributed uniformly on the
+ * surface of a sphere. This can be used to define mac80211's
+ * conf.antenna_max and channel.antenna_max for example.
+ * @max_ir_ptmp: maximum allowed Intentional Radiated power on the transmitter
+ * for Point to Multi Points, given in dBm. This applies to stations,
+ * Access Points and PtMP bridges.
+ * @max_ir_ptmp: maximum allowed Intentional Radiated power on the transmitter
+ * for Point to Point links such as PtP Bridges, given in dBm.
+ * @max_eirp_ptmp: maximum allowed Equivalent Isotropically Radiated Power on
+ * the transmitter for Point to Point to Multi Points links, given in dBm
+ * @max_eirp_ptp: maximum allowed Equivalent Isotropically Radiated Power on
+ * the transmitter for Point to Point links such as PtP Bridges, given in
+ * dBm.
+ * @num_channels: number of channels in channel_list.
+ * @channel_list: linked list of all channels on this subband. These are of
+ * type @ieee80211_channel
+ *
+ * This structure contains the regualtory power restrictions on this subband
+ * and has a linked list of all possible channels. Wireless drivers can compute
+ * their maximum allowed TX power as follows:
+ *
+ * Max TX Power = Max EIRP - passive gain of antenna
+ *
+ * Keep in mind that the passive gain of the standard dipole antenna is approx
+ * 2.2 dBi. You can use this value for most wireless setups. Please note that
+ * some regulatory domains also have rules to which change the max IR if you
+ * change the antenna, such as the 1:1 and 3:1 rule for the FCC. For more
+ * information please refer to the Documentation/ieee80211_regdomains.txt
+ * documentation.
+ */
+struct ieee80211_subband_restrictions {
+ u8 band;
+ char name[REGSBNAMSIZ];
+ u16 min_freq;
+ u16 max_freq;
+ u32 modulation_cap;
+ u8 max_antenna_gain;
+ u8 max_ir_ptmp;
+ u8 max_ir_ptp;
+#define REG_DIPOLE_ANTENNA_GAIN 2
+ u8 max_eirp_ptmp;
+ u8 max_eirp_ptp;
+#define REG_CAP_INDOOR 'I'
+#define REG_CAP_OUTDOOR 'O'
+#define REG_CAP_INOUT ' '
+ char environment_cap;
+ u8 num_channels;
+ struct list_head channel_list;
+};
+
+/**
+ * struct ieee80211_regdomain - defines a regulatory domain
+ *
+ * @regdomain_id: ID of this regulatory domain. Some come from
+ * http://standards.ieee.org/getieee802/download/802.11b-1999_Cor1-2001.pdf
+ * @regdomain_name: name of this regulatory domain.
+ * @list: node, part of band_restrictions_list
+ *
+ * This structure defines a regulatory domain, which consists of channel and
+ * power restrictions. Some regulatory domains come from
+ * 802.11b-1999_Cor1-2001, the rest are based on Reyk Floeter's ar5k. If
+ * there is need to add more values here, please add one that is either
+ * defined in a standard or that many hardware devices have adopted. Also
+ * note that multiple countries can map to the same @regdomain_id
+ */
+struct ieee80211_regdomain {
+ u32 regdomain_id;
+ char regdomain_name[REGNAMSIZ];
+ struct ieee80211_subband_restrictions subbands[REG_NUM_SUBBANDS];
+};
+
+/**
+ * struct ieee80211_iso3166_reg_map - map of an ISO3166-1 country to a regdomain
+ *
+ * @alpha2: the ISO-3166-1 alpha2 country code string. Example: 'CR' for
+ * Costa Rica.
+ *
+ * @regdomain_id: a regualtory domain ID this country maps to.
+ *
+ * This structure holds the mapping of the country to a specific regulatory
+ * domain. Keep in mind more than one country can map to the same regulatory
+ * domain. The ISO-3166-1 alpha2 country code also happens to be used in the
+ * 802.11d Country Information Element on the string for the country. It
+ * should be noted, however, that in that the size of this string, is
+ * three octects while our string is only 2. The third octet is used to
+ * indicate Indoor/outdoor capabilities which we set in
+ * @ieee80211_subband_restrictions environment_cap.
+ */
+struct ieee80211_iso3166_reg_map {
+ char alpha2[ISOCOUNTRYSIZ2];
+ u32 regdomain_id; /* stack-aware value */
+ /* XXX: shall we just use an array? */
+ struct list_head list; /* node, part of iso3166_reg_map_list */
+};
+
+/**
+ * regdomain_mhz2ieee - convert a frequency to an IEEE-80211 channel number
+ * @freq: center of frequency in MHz. We support a range:
+ * 2412 - 2732 MHz (Channel 1 - 26) in the 2GHz band and
+ * 5005 - 6100 MHz (Channel 1 - 220) in the 5GHz band.
+ *
+ * Given a frequency in MHz returns the respective IEEE-80211 channel
+ * number. You are expected to provide the center of freqency in MHz.
+ */
+u16 regdomain_mhz2ieee(u16 freq);
+
+/**
+ * regdomain_ieee2mhz - convert an IEEE-80211 channel number to frequency
+ * @chan: An IEEE-802.11 channel number we support the range:
+ * Channel 1 - 26 in the 2GHz band and
+ * Channel 1 - 220 in the 5GHz band
+ *
+ * @band: Which band we want the frequency in, could be either
+ * IEEE80211_24GHZ_BAND or IEEE80211_52GHZ_BAND.
+ *
+ * Given an IEEE-802.11 channel number and band returns the respective center
+ * of frequency in MHz.
+ */
+u16 regdomain_ieee2mhz(u16 chan, u8 band);
+
+void print_regdomain(struct ieee80211_regdomain *);
+void print_iso3166_reg_map(void);
+
+int get_ieee80211_regname(u32, char *);
+
+int iso3166_to_reg_exists(char *);
+int iso3166_to_reg(char *, u32 *);
+
+int regdomain_build(u32, struct ieee80211_regdomain **);
+void free_regdomain(struct ieee80211_regdomain *);
+u32 ieee80211_mode_modulation(u8 mode);
+
+#endif /* _IEEE80211_REGDOMAIN_H_ */
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index d03cd53..c60ee87 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -14,6 +14,22 @@ config NL80211

If unsure, say Y.

+config IEEE80211_REGDOMAINS
+ tristate "Central IEEE 802.11 regulatory domain agent"
+ select ISO3166_1
+ ---help---
+ This option enables the a regdomains part of the central
+ regulatory domain agent for the kernel. If added as a module
+ the module will be called regdomains.ko.
+
+ If unsure, you can safely say Y.
+
+config IEEE80211_REGDOMAINS_DBG
+ bool "Enables debugging output for the regulatory domain agent"
+ depends on IEEE80211_REGDOMAINS
+ ---help---
+ This option enables debug for the central regulatory domain agent
+
config ISO3166_1
tristate "ISO 3166-1 support (for 802.11d and regulatory)"
---help---
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index f710044..74c1059 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_CFG80211) += cfg80211.o
cfg80211-y += core.o sysfs.o radiotap.o
cfg80211-$(CONFIG_NL80211) += nl80211.o

+obj-$(CONFIG_IEEE80211_REGDOMAINS) += regdomains.o
obj-$(CONFIG_ISO3166_1) += iso3166-1.o
diff --git a/net/wireless/reg_common.h b/net/wireless/reg_common.h
new file mode 100644
index 0000000..460761b
--- /dev/null
+++ b/net/wireless/reg_common.h
@@ -0,0 +1,138 @@
+#ifndef _REGULATORY_COMMON_H_
+
+#define REG_2GHZ_MIN 2412 /* 2GHz channel 1 */
+#define REG_2GHZ_MAX 2732 /* 2GHz channel 26 */
+#define REG_5GHZ_MIN 5005 /* 5GHz channel 1 */
+#define REG_5GHZ_MAX 6100 /* 5GHz channel 220 */
+
+#define DMN_NULL_WORLD 0x03 /* World default */
+#define DMN_NULL_ETSIB 0x07
+#define DMN_NULL_ETSIC 0x08
+#define DMN_FCC1_FCCA 0x10
+#define DMN_FCC1_WORLD 0x11
+#define DMN_FCC2_FCCA 0x20
+#define DMN_FCC2_WORLD 0x21
+#define DMN_FCC2_ETSIC 0x22
+#define DMN_FCC3_FCCA 0x3A
+#define DMN_ETSI1_WORLD 0x37
+#define DMN_ETSI3_ETSIA 0x32
+#define DMN_ETSI2_WORLD 0x35
+#define DMN_ETSI3_WORLD 0x36
+#define DMN_ETSI4_WORLD 0x30
+#define DMN_ETSI4_ETSIC 0x38
+#define DMN_ETSI5_WORLD 0x39
+#define DMN_ETSI6_WORLD 0x34
+#define DMN_MKK1_MKKA 0x40
+#define DMN_MKK1_MKKB 0x41
+#define DMN_APL4_WORLD 0x42
+#define DMN_MKK2_MKKA 0x43
+#define DMN_APL2_WORLD 0x45
+#define DMN_APL2_APLC 0x46
+#define DMN_APL3_WORLD 0x47
+#define DMN_MKK1_FCCA 0x48
+#define DMN_APL2_APLD 0x49
+#define DMN_MKK1_MKKA1 0x4A
+#define DMN_MKK1_MKKA2 0x4B
+#define DMN_APL1_WORLD 0x52
+#define DMN_APL1_FCCA 0x53
+#define DMN_APL1_APLA 0x54
+#define DMN_APL1_ETSIC 0x55
+#define DMN_APL2_ETSIC 0x56
+#define DMN_APL5_WORLD 0x58
+#define DMN_DEBUG_DEBUG 0xFF
+
+/* 2.4GHz and 5GHz common subbands */
+#define DMN_APL1 (1<<0)
+#define DMN_APL2 (1<<1)
+#define DMN_APL3 (1<<2)
+#define DMN_APL4 (1<<3)
+#define DMN_APL5 (1<<4)
+#define DMN_ETSI1 (1<<5)
+#define DMN_ETSI2 (1<<6)
+#define DMN_ETSI3 (1<<7)
+#define DMN_ETSI4 (1<<8)
+#define DMN_ETSI5 (1<<9)
+#define DMN_ETSI6 (1<<10)
+#define DMN_ETSIA (1<<11)
+#define DMN_ETSIB (1<<12)
+#define DMN_ETSIC (1<<13)
+#define DMN_FCC1 (1<<14)
+#define DMN_FCC2 (1<<15)
+#define DMN_FCC3 (1<<16)
+#define DMN_FCCA (1<<17)
+#define DMN_APLD (1<<18)
+#define DMN_MKK1 (1<<19)
+#define DMN_MKK2 (1<<20)
+#define DMN_MKKA (1<<21)
+#define DMN_NULL (1<<22)
+#define DMN_WORLD (1<<23)
+#define DMN_DEBUG (1<<31) /* Use on any map for debugging */
+
+/* Default max antenna gain, in dBi */
+#define REG_MAX_ANTENNA 6
+
+/* Subbands definitions. We break the IEEE-802.11 spectrum into 7
+ * logical subbands */
+#define DMN_SB_ISM24 0
+#define DMN_SB_TELEC 1
+#define DMN_SB_UNII_1 2
+#define DMN_SB_UNII_2 3
+#define DMN_SB_ETSI 4
+#define DMN_SB_UNII_3 5
+#define DMN_SB_AAD 6
+
+#define REG_ISM24_MIN 2412 /* 2GHz channel 1 */
+#define REG_ISM24_MAX 2732 /* 2GHz channel 26 */
+#define REG_TELEC_MIN 5005 /* 5GHz channel 1 */
+#define REG_TELEC_MAX 5145 /* 5GHz channel 29 */
+#define REG_UNII_1_MIN 5150 /* 5GHz channel 30 */
+#define REG_UNII_1_MAX 5245 /* 5GHz channel 49 */
+#define REG_UNII_2_MIN 5250 /* 5GHz channel 50 */
+#define REG_UNII_2_MAX 5350 /* 5GHz channel 70 */
+#define REG_ETSI_MIN 5355 /* 5GHz channel 71 */
+#define REG_ETSI_MAX 5720 /* 5GHz channel 144 */
+#define REG_UNII_3_MIN 5725 /* 5GHz channel 145 */
+#define REG_UNII_3_MAX 5825 /* 5GHz channel 165 */
+#define REG_AAD_MIN 5830 /* 5GHz channel 166 */
+#define REG_AAD_MAX 6100 /* 5GHz channel 220 */
+
+/* Just FYI for now, technically DSRC is Dedicated Short Range Communications,
+ * for vehicles in North America (USA, Canada, and Mexico) */
+#define REG_DSRC_MIN 5850
+#define REG_DSRC_MAX 5925
+
+/* 2.4GHz power subband IDs, note the entire world enables the
+ * 2.4GHz subband */
+#define DMN_P24_FCC (2<<1)
+#define DMN_P24_ETSI (2<<2)
+#define DMN_P24_MKK (2<<3)
+#define DMN_P24_WORLD (2<<4)
+
+/* Now for all 5GHz power subbands IDs, note that WORLD
+ * regdomain has no 5GHz subbands */
+
+/* TELEC subband */
+#define DMN_PT_MKK (2<<0)
+/* UNII-1 Used for indoor -- regulations require use of an integrated antenna */
+#define DMN_PU1_FCC (2<<1)
+#define DMN_PU1_ETSI (2<<2)
+#define DMN_PU1_MKK (2<<3)
+#define DMN_PU1_APL (2<<4)
+/* UNII-2 Used for indoor -- regulations allow for a user-installable antenna */
+#define DMN_PU2_FCC (2<<5)
+#define DMN_PU2_ETSI (2<<6)
+#define DMN_PU2_APL (2<<7)
+/* ETSI band */
+#define DMN_PE_FCC (2<<8)
+#define DMN_PE_ETSI (2<<9)
+/* UNII-3 Used for both outdoor and indoor use -- subject to
+ * Dynamic Frequency Selection (DFS, or radar avoidance */
+#define DMN_PU3_FCC (2<<10)
+#define DMN_PU3_APL (2<<11)
+/* Asia/Africa/DSRC */
+/* XXX: fill these power restrictions out, for now only
+ * debug makes use of it */
+//#define DMN_PA_FCC (2<<12)
+//#define DMN_PA_MKK (2<<13)
+
+#endif /*_REGULATORY_COMMON_H_ */
diff --git a/net/wireless/regdomains.c b/net/wireless/regdomains.c
new file mode 100644
index 0000000..b9f79fd
--- /dev/null
+++ b/net/wireless/regdomains.c
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2004, 2005 Reyk Floeter <[email protected]>
+ * Copyright (c) 2006, 2007 Luis R. Rodriguez <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <net/ieee80211_regdomains.h>
+#include "regulatory_map.h"
+
+#define DRV_NAME "ieee80211_regdomains"
+#define DRV_DESCRIPTION "IEEE-802.11 Regulatory Domain wireless driver"
+#define DRV_VERSION REGDOMAINS_VERSION
+
+MODULE_AUTHOR("Luis R. Rodriguez <[email protected]>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+
+LIST_HEAD(iso3166_reg_map_list);
+EXPORT_SYMBOL(iso3166_reg_map_list);
+
+rwlock_t iso3166_reg_rwlock = RW_LOCK_UNLOCKED;
+EXPORT_SYMBOL(iso3166_reg_rwlock);
+
+/*
+ * Loads regulatory maps, used to build regualtory domains. We later
+ * can provide support to update maps via nl80211 or configfs. */
+struct reg_band reg_band_map[] = REG_MAP;
+struct reg_channel reg_2ghz_channels[] = REG_CHANNELS_2GHZ;
+struct reg_channel reg_5ghz_channels[] = REG_CHANNELS_5GHZ;
+struct reg_domainname reg_domainname_map[] = REG_NAMES;
+struct reg_country reg_ctry_map[] = REG_COUNTRY_NAMES;
+struct reg_subband reg_subbands_map[] = REG_SUBBANDS;
+struct reg_pw reg_pw_2ghz_map[] = REG_PW_24_MAP;
+struct reg_pw reg_pw_t_map[] = REG_PW_T_MAP;
+struct reg_pw reg_pw_u1_map[] = REG_PW_U1_MAP;
+struct reg_pw reg_pw_u2_map[] = REG_PW_U2_MAP;
+struct reg_pw reg_pw_e_map[] = REG_PW_E_MAP;
+struct reg_pw reg_pw_u3_map[] = REG_PW_U3_MAP;
+struct reg_pw reg_pw_aad_map[] = REG_PW_AAD_MAP;
+struct reg_pw_subbands reg_pw_map[] = REG_PW_MAP;
+
+/* Add any exceptions to the official ISO3166-1 alpha map here */
+static char *iso3166_1_exceptions[] = {
+ "00", /* World regulatory domain */
+ "F2",
+ "J1", "J2", "J3", "J4", "J5", /* Japan is complicated... */
+ "K2",
+ "UK", /* UK's alpha2 is actually GB ;) */
+ "99" /* Used for debugging */
+};
+
+static inline int is_iso3166_1_exception(char *alpha2)
+{
+ int i;
+ for (i=0; i<ARRAY_SIZE(iso3166_1_exceptions); i++)
+ if(strncmp(alpha2, iso3166_1_exceptions[i], 2)==0)
+ return 1;
+ return 0;
+}
+
+static u32 ieee80211_regdomain2flag(u32 regdomain, u16 mhz)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(reg_band_map); i++) {
+ if (reg_band_map[i].rm_domain == regdomain) {
+ if (mhz >= 2000 && mhz <= 3000)
+ return((u32)reg_band_map[i].rm_domain_2ghz);
+ if (mhz >= REG_5GHZ_MIN &&
+ mhz <= REG_5GHZ_MAX)
+ return((u32)reg_band_map[i].rm_domain_5ghz);
+ }
+ }
+ return((u32)DMN_DEBUG);
+}
+
+static int ieee80211_regdomain2name(u32 regdomain, char *name)
+{
+ int i;
+ /* Linear search over the table */
+ for(i = 0; i < ARRAY_SIZE(reg_domainname_map); i++)
+ if(reg_domainname_map[i].rn_domain == regdomain) {
+ memcpy(name, reg_domainname_map[i].rn_name, REGNAMSIZ);
+ return 0;
+ }
+ printk("No regdomain name matches regdomain: %0x\n", regdomain);
+ return -ENOENT;
+}
+
+int freq_to_subband(u16 freq, u32 *sb_id)
+{
+ int i;
+ struct reg_subband *sb;
+ for (i=0; i < ARRAY_SIZE(reg_subbands_map); i++) {
+ sb = &reg_subbands_map[i];
+ if (freq <= sb->sb_max_freq && freq >= sb->sb_min_freq) {
+ *sb_id = sb->sb_id;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static void update_reg_subband_map()
+{
+ reg_subbands_map[DMN_SB_ISM24].sb_reg_pw = reg_pw_2ghz_map;
+ reg_subbands_map[DMN_SB_ISM24].sb_reg_pw_size = ARRAY_SIZE(reg_pw_2ghz_map);
+
+ reg_subbands_map[DMN_SB_TELEC].sb_reg_pw = reg_pw_t_map;
+ reg_subbands_map[DMN_SB_TELEC].sb_reg_pw_size = ARRAY_SIZE(reg_pw_t_map);
+
+ reg_subbands_map[DMN_SB_UNII_1].sb_reg_pw = reg_pw_u1_map;
+ reg_subbands_map[DMN_SB_UNII_1].sb_reg_pw_size = ARRAY_SIZE(reg_pw_u1_map);
+
+ reg_subbands_map[DMN_SB_UNII_2].sb_reg_pw = reg_pw_u2_map;
+ reg_subbands_map[DMN_SB_UNII_2].sb_reg_pw_size = ARRAY_SIZE(reg_pw_u2_map);
+
+ reg_subbands_map[DMN_SB_ETSI].sb_reg_pw = reg_pw_e_map;
+ reg_subbands_map[DMN_SB_ETSI].sb_reg_pw_size = ARRAY_SIZE(reg_pw_e_map);
+
+ reg_subbands_map[DMN_SB_UNII_3].sb_reg_pw = reg_pw_u3_map;
+ reg_subbands_map[DMN_SB_UNII_3].sb_reg_pw_size = ARRAY_SIZE(reg_pw_u3_map);
+
+ reg_subbands_map[DMN_SB_AAD].sb_reg_pw = reg_pw_aad_map;
+ reg_subbands_map[DMN_SB_AAD].sb_reg_pw_size = ARRAY_SIZE(reg_pw_aad_map);
+}
+
+static int get_subband_pw_id(u32 regdomain, u32 sb_id, u32 *pw_id)
+{
+ int i;
+ struct reg_pw_subbands *pw_sb;
+ for (i=0; i <= ARRAY_SIZE(reg_pw_map); i++) {
+ pw_sb = &reg_pw_map[i];
+ if (pw_sb->domain_id == regdomain) {
+ switch(sb_id) {
+ case DMN_SB_ISM24:
+ *pw_id = pw_sb->p_domain_2ghz;
+ break;
+ case DMN_SB_TELEC:
+ *pw_id = pw_sb->p_domain_telec;
+ break;
+ case DMN_SB_UNII_1:
+ *pw_id = pw_sb->p_domain_unii1;
+ break;
+ case DMN_SB_UNII_2:
+ *pw_id = pw_sb->p_domain_unii2;
+ break;
+ case DMN_SB_ETSI:
+ *pw_id = pw_sb->p_domain_etsi;
+ break;
+ case DMN_SB_UNII_3:
+ *pw_id = pw_sb->p_domain_unii3;
+ break;
+ case DMN_SB_AAD:
+ *pw_id = pw_sb->p_domain_aad;
+ break;
+ default:
+ return -ENOENT;
+ }
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+
+/* XXX: change to return u8 when ieee80211_channel chan gets changed */
+u16 regdomain_mhz2ieee(u16 freq)
+{
+ if (freq >= REG_2GHZ_MIN && /* Channel 1 */
+ freq <= REG_2GHZ_MAX) { /* Channel 26 */
+ if (freq == 2484) /* Japan */
+ return 14;
+ if ((freq >= 2412) && (freq < 2484))
+ return (freq - 2407) / 5;
+ if (freq < 2512) /* No new channel until 2512 */
+ return 0;
+ return ((freq - 2512)/20) + 15; /* 15-26 */
+ } else if (freq >= REG_5GHZ_MIN && /* Channel 1 */
+ freq <= REG_5GHZ_MAX) { /* Channel 220 */
+ return (freq - 5000) / 5;
+ } else
+ return 0;
+}
+EXPORT_SYMBOL(regdomain_mhz2ieee);
+
+/* XXX: change arg1 to u8 when ieee80211_channel chan gets changed */
+u16 regdomain_ieee2mhz(u16 chan, u8 band)
+{
+ switch (band) {
+ case IEEE80211_24GHZ_BAND:
+ if (chan > MAX_NUM_MODE_G_CHANS || chan == 0) {
+ BUG();
+ return 0;
+ }
+ if (chan < 14)
+ return (2407 + (chan * 5));
+ else if (chan == 14)
+ return 2484;
+ else if (chan == 15)
+ return 2512;
+ else
+ return (2492 + (chan * 20));
+ case IEEE80211_52GHZ_BAND:
+ if (chan > MAX_NUM_MODE_A_CHANS || chan == 0) {
+ BUG();
+ return 0;
+ }
+ return ((5000) + (chan * 5));
+ default:
+ BUG();
+ return 0;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(regdomain_ieee2mhz);
+
+static inline u8 freq_band_id(u16 freq)
+{
+ if (freq >= REG_2GHZ_MIN && /* Channel 1 */
+ freq <= REG_2GHZ_MAX) /* Channel 26 */
+ return IEEE80211_24GHZ_BAND;
+ else if (freq >= REG_5GHZ_MIN && /* Channel 1 */
+ freq <= REG_5GHZ_MAX) /* Channel 220 */
+ return IEEE80211_52GHZ_BAND;
+ else {
+ BUG();
+ return -EINVAL;
+ }
+
+}
+
+static inline int is_japan_regdomain_id(u32 regdomain_id)
+{
+ switch(regdomain_id) {
+ case DMN_MKK1_MKKB:
+ case DMN_MKK1_FCCA:
+ case DMN_MKK1_MKKA:
+ case DMN_MKK2_MKKA:
+ case DMN_MKK1_MKKA1:
+ case DMN_MKK1_MKKA2:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+u32 ieee80211_mode_modulation(u8 mode)
+{
+ switch (mode) {
+ case MODE_IEEE80211A:
+ return IEEE80211_RATE_OFDM;
+ case MODE_IEEE80211B:
+ return IEEE80211_RATE_CCK;
+ case MODE_IEEE80211G:
+ return IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(ieee80211_mode_modulation);
+
+static inline void setup_regdomain(struct ieee80211_regdomain *r,
+ u8 regdomain_id, char *regdomain_name)
+{
+ strcpy(r->regdomain_name, regdomain_name);
+ r->regdomain_id = regdomain_id;
+}
+
+static inline void setup_subband_restrictions(
+ struct ieee80211_subband_restrictions *sb, char *name,
+ u16 min_freq, u16 max_freq, u8 max_antenna_gain,
+ u8 max_ir_ptmp, u8 max_ir_ptp,
+ u8 max_eirp_ptmp, u8 max_eirp_ptp,
+ char environment_cap)
+{
+ memcpy(sb->name, name, REGSBNAMSIZ);
+ sb->band = freq_band_id(min_freq);
+ sb->min_freq = min_freq;
+ sb->max_freq = max_freq;
+ sb->max_antenna_gain = max_antenna_gain;
+ sb->max_ir_ptmp = max_ir_ptmp;
+ sb->max_ir_ptp = max_ir_ptp;
+ sb->max_eirp_ptmp = max_eirp_ptmp;
+ sb->max_eirp_ptp = max_eirp_ptp;
+ sb->environment_cap = environment_cap;
+}
+
+static inline void setup_reg_channel(u32 regdomain_id,
+ struct ieee80211_channel *chan,
+ struct ieee80211_subband_restrictions *sb,
+ struct reg_channel *r_channel)
+{
+ chan->freq = r_channel->rc_freq;
+ chan->modulation_cap = r_channel->rc_modulation_cap;
+ /* We set chan->val with what is common, drivers can overwrite
+ * that if they so wish to */
+ chan->chan = chan->val = regdomain_mhz2ieee(chan->freq);
+
+ chan->flag = IEEE80211_CHAN_W_SCAN |
+ IEEE80211_CHAN_W_ACTIVE_SCAN |
+ IEEE80211_CHAN_W_IBSS;
+
+ /* For now assume standard dipole antenna */
+ chan->power_level = sb->max_eirp_ptmp - REG_DIPOLE_ANTENNA_GAIN;
+
+ if (chan->freq > REG_5GHZ_MIN) {
+ /* New regulatory rules in japan don't allow scan in
+ * these old channels (5.15-5.25 GHz). This is an
+ * excemption to common regulatory rules so we add
+ * it here */
+ if (is_japan_regdomain_id(regdomain_id) &&
+ (chan->freq == 5170 || chan->freq == 5190 ||
+ chan->freq == 5210 || chan->freq == 5230))
+ chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
+ }
+}
+
+static void free_subband_channel_list(struct list_head *channel_list)
+{
+ struct ieee80211_channel *chan, *chan_tmp;
+ list_for_each_entry_safe(chan, chan_tmp, channel_list, list) {
+ list_del(&chan->list);
+ if (chan != NULL)
+ kfree(chan);
+ }
+}
+
+void free_regdomain(struct ieee80211_regdomain *reg)
+{
+ struct ieee80211_subband_restrictions *sb;
+ int y;
+ for (y=0; y<REG_NUM_SUBBANDS; y++) {
+ sb = &reg->subbands[y];
+ if (! list_empty(&sb->channel_list)) {
+ free_subband_channel_list(&sb->channel_list);
+ }
+ list_del(&sb->channel_list);
+ }
+ kfree(reg);
+}
+EXPORT_SYMBOL(free_regdomain);
+
+static void free_iso3166_reg_map_list(void)
+{
+ struct ieee80211_iso3166_reg_map *map, *tmp;
+ list_for_each_entry_safe(map, tmp, &iso3166_reg_map_list, list) {
+ list_del(&map->list);
+ kfree(map);
+ }
+}
+
+static inline int check_reg_init(int r, char *reg_name)
+{
+ printk("%s: regulatory domain %s ", DRV_NAME, reg_name);
+ switch(r) {
+ case -ENOMEM:
+ printk("Unable to allocate memory\n");
+ break;
+ case -EINVAL:
+ printk("reg_name is invalid\n");
+ break;
+ case 0:
+ printk("created\n");
+ break;
+ default:
+ printk("Unexpected error detected\n");
+ r = -EINVAL;
+ break;
+ }
+ return r;
+}
+
+void print_regdomain(struct ieee80211_regdomain *reg)
+{
+ struct ieee80211_subband_restrictions *sb;
+ struct ieee80211_channel *chan;
+ int y;
+
+ u32 modulation_a = ieee80211_mode_modulation(MODE_IEEE80211A);
+ u32 modulation_b = ieee80211_mode_modulation(MODE_IEEE80211B);
+ u32 modulation_g = ieee80211_mode_modulation(MODE_IEEE80211G);
+
+ if (reg == NULL) {
+ printk("Invalid regulatory domain encountered\n");
+ return;
+ }
+
+ printk("Regulatory Domain:\t%s\tRegulatory Domain ID:\t0x%02x\n",
+ reg->regdomain_name,
+ reg->regdomain_id);
+
+
+ for (y=0; y < REG_NUM_SUBBANDS; y++) {
+ sb = &reg->subbands[y];
+ if (sb->num_channels == 0)
+ continue;
+ switch (sb->band) {
+ case IEEE80211_24GHZ_BAND:
+ if (sb->modulation_cap == modulation_b)
+ printk("\tIEEE 802.11b\t2GHz\t%s subband", sb->name);
+ else if (sb->modulation_cap == modulation_g)
+ printk("\tIEEE 802.11g\t2GHz\t%s subband", sb->name);
+ else
+ BUG();
+ break;
+ case IEEE80211_52GHZ_BAND:
+ if (sb->modulation_cap == modulation_a) {
+ printk("\tIEEE 802.11a\t5GHz\t%s subband", sb->name);
+ }
+ else
+ BUG();
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ printk("\n\tmax_ir_ptmp:\t%d dBm\tmax_eirp_ptmp:\t%d dBm\n",
+ sb->max_ir_ptmp, sb->max_eirp_ptmp);
+ printk("\tmax_ir_ptp:\t%d dBm\tmax_eirp_ptp:\t%d dBm\n",
+ sb->max_ir_ptp, sb->max_eirp_ptp);
+ printk("\tmax_antenna_gain:\t%d dBi\n"
+ "\tEnvironment capability:\t", sb->max_antenna_gain);
+ if(sb->environment_cap == REG_CAP_INDOOR)
+ printk("Indoor\n");
+ else if(sb->environment_cap == REG_CAP_OUTDOOR)
+ printk("Outdoor\n");
+ else if(sb->environment_cap == REG_CAP_INOUT)
+ printk("Indoor & Outdoor\n");
+ else
+ BUG();
+ printk("\t\tChannel\tFreq (MHz)\t\n");
+
+ list_for_each_entry(chan, &sb->channel_list, list){
+ printk("\t\t%d\t%d\t\n", chan->chan, chan->freq);
+ }
+ }
+ printk("\n");
+}
+EXPORT_SYMBOL(print_regdomain);
+
+#ifdef CONFIG_IEEE80211_REGDOMAINS_DBG
+void print_iso3166_reg_map(void)
+{
+ struct ieee80211_iso3166_reg_map *map;
+ char regdomain_name[REGNAMSIZ];
+ printk("ISO3166 <--> regulatory domain map:\n");
+ printk("CTRY\t-->\tRegdomain\n");
+ read_lock(&iso3166_reg_rwlock);
+ list_for_each_entry(map, &iso3166_reg_map_list, list) {
+ if (ieee80211_regdomain2name(map->regdomain_id, regdomain_name))
+ printk("%s\t-->\t0x%02x (reg_id not registered in "
+ "regulatory db)\n",
+ map->alpha2, map->regdomain_id);
+ else
+ printk("%s\t-->\t%s\n", map->alpha2, regdomain_name);
+ }
+ read_unlock(&iso3166_reg_rwlock);
+}
+#else
+
+void print_iso3166_reg_map(void)
+{
+ return;
+}
+#endif /* CONFIG_IEEE80211_REGDOMAINS_DBG */
+EXPORT_SYMBOL(print_iso3166_reg_map);
+
+static inline void setup_iso3166_reg_map(struct ieee80211_iso3166_reg_map *map,
+ char *alpha2, u32 regdomain_id)
+{
+ strcpy(map->alpha2, alpha2);
+ map->regdomain_id = regdomain_id;
+}
+
+int iso3166_to_reg_exists(char *alpha2)
+{
+ struct ieee80211_iso3166_reg_map *map;
+ read_lock(&iso3166_reg_rwlock);
+ list_for_each_entry(map, &iso3166_reg_map_list, list)
+ if(strncmp(map->alpha2, alpha2, ISOCOUNTRYSIZ2-1)==0) {
+ read_unlock(&iso3166_reg_rwlock);
+ return 1;
+ }
+ read_unlock(&iso3166_reg_rwlock);
+ return 0;
+}
+EXPORT_SYMBOL(iso3166_to_reg_exists);
+
+int iso3166_to_reg(char *alpha2, u32 *regdomain_id)
+{
+ struct ieee80211_iso3166_reg_map *map;
+ read_lock(&iso3166_reg_rwlock);
+ list_for_each_entry(map, &iso3166_reg_map_list, list)
+ if(strncmp(map->alpha2, alpha2, ISOCOUNTRYSIZ2-1)==0) {
+ *regdomain_id = map->regdomain_id;
+ read_unlock(&iso3166_reg_rwlock);
+ return 0;
+ }
+ read_unlock(&iso3166_reg_rwlock);
+ return -ENOENT;
+}
+EXPORT_SYMBOL(iso3166_to_reg);
+
+static int add_iso3166_reg_map(char *alpha2, u32 regdomain_id)
+{
+ int r = 0;
+ struct ieee80211_iso3166_reg_map *map;
+ /* If not valid or iso map does already already present */
+ if((!iso3166_1_exists(alpha2) && !is_iso3166_1_exception(alpha2))
+ || iso3166_to_reg_exists(alpha2)){
+ r = -EPERM;
+ goto exit;
+ }
+ write_lock(&iso3166_reg_rwlock);
+ map = kzalloc(sizeof(struct ieee80211_iso3166_reg_map), GFP_KERNEL);
+ if(map == NULL) {
+ r = -ENOMEM;
+ goto unlock_and_exit;
+ }
+ setup_iso3166_reg_map(map, alpha2, regdomain_id);
+ list_add_tail(&map->list, &iso3166_reg_map_list);
+unlock_and_exit:
+ write_unlock(&iso3166_reg_rwlock);
+exit:
+ return r;
+}
+
+static int __load_iso3166_reg_map_list(void)
+{
+ int i, r = 0;
+ struct reg_country *r_country;
+ INIT_LIST_HEAD(&iso3166_reg_map_list);
+ for (i = 0; i < ARRAY_SIZE(reg_ctry_map); i++) {
+ r_country = &reg_ctry_map[i];
+ r = add_iso3166_reg_map(r_country->cn_name,
+ r_country->cn_domain);
+ if(r && r!=-ENOMEM) {
+ printk("%s: Skipping country <-> regdomain map for "
+ "country %s\n", DRV_NAME, r_country->cn_name);
+ r = 0;
+ }
+ }
+ return r;
+}
+
+static int __alloc_band_channels(u32 regdomain_id,
+ struct ieee80211_regdomain *reg, u8 band,
+ u32 sb_chan_domain)
+{
+ struct reg_channel *band_channels = NULL;
+ int band_channel_size = 0;
+ int i;
+
+ switch (band) {
+ case IEEE80211_24GHZ_BAND:
+ band_channels = reg_2ghz_channels;
+ band_channel_size = ARRAY_SIZE(reg_2ghz_channels);
+ break;
+ case IEEE80211_52GHZ_BAND:
+ band_channels = reg_5ghz_channels;
+ band_channel_size = ARRAY_SIZE(reg_5ghz_channels);
+ break;
+ }
+
+ for (i = 0; i < band_channel_size; i++) {
+ u32 sb_id = -1;
+ struct ieee80211_subband_restrictions *sb;
+ struct ieee80211_channel *sb_chan; /* For subband */
+ struct reg_subband *reg_sb;
+ struct reg_channel *r_channel = &band_channels[i];
+
+ if (r_channel->rc_domain != sb_chan_domain)
+ continue;
+
+ BUG_ON(freq_to_subband(r_channel->rc_freq, &sb_id));
+ BUG_ON(&reg_subbands_map[sb_id] == NULL);
+
+ sb = &reg->subbands[sb_id];
+ reg_sb = &reg_subbands_map[sb_id];
+
+ sb->modulation_cap |= r_channel->rc_modulation_cap;
+
+ /* Add to subband linked list */
+ sb_chan = kzalloc(sizeof(struct ieee80211_channel),
+ GFP_KERNEL);
+ if (sb_chan == NULL)
+ return -ENOMEM;
+ setup_reg_channel(regdomain_id, sb_chan,
+ sb, r_channel);
+ list_add_tail(&sb_chan->list, &sb->channel_list);
+ sb->num_channels++;
+ }
+ return 0;
+}
+
+static int setup_reg_pw_restrictions(u32 regdomain_id,
+ struct ieee80211_regdomain *reg)
+{
+ int i, r = 0;
+ /* Iterate over our subbands and set respective power restrictions */
+ for (i=0; i < REG_NUM_SUBBANDS; i++) {
+ struct reg_subband *reg_sb;
+ struct reg_pw *sb_reg_pw;
+ struct ieee80211_subband_restrictions *sb;
+ u32 pw_sb_id = -1;
+ int pw_idx;
+
+ reg_sb = &reg_subbands_map[i];
+ /* Note, bellow is an array, we're going to iterate
+ * through it later */
+ sb_reg_pw = reg_sb->sb_reg_pw;
+ BUG_ON(sb_reg_pw == NULL);
+ sb = &reg->subbands[i];
+ /* Initialize all lists */
+ INIT_LIST_HEAD(&sb->channel_list);
+
+ /* Iterate through this subbands possible power maps, and setup
+ * the subband as corresponds to this regdomain */
+ r = get_subband_pw_id(regdomain_id, i, &pw_sb_id);
+ BUG_ON(r);
+ for (pw_idx = 0; pw_idx < reg_sb->sb_reg_pw_size; pw_idx++) {
+ if (sb_reg_pw->p_domain != pw_sb_id) {
+ sb_reg_pw++;
+ continue;
+ }
+ /* We found a match */
+ setup_subband_restrictions(sb, reg_sb->sb_name,
+ reg_sb->sb_min_freq, reg_sb->sb_max_freq,
+ sb_reg_pw->max_antenna_gain,
+ sb_reg_pw->max_ir_ptmp, sb_reg_pw->max_ir_ptp,
+ sb_reg_pw->max_eirp_ptmp,
+ sb_reg_pw->max_eirp_ptp,
+ sb_reg_pw->environment_cap);
+ break; /* Start working on next subband */
+ }
+ }
+ return r;
+}
+
+/* Called by users of this module, cfg80211 at the moment */
+int regdomain_build(u32 regdomain_id, struct ieee80211_regdomain **reg_p)
+{
+ struct ieee80211_regdomain *reg = NULL;
+ struct ieee80211_subband_restrictions *subbands = NULL;
+ char reg_name[REGNAMSIZ];
+ u32 reg_2ghz_id;
+ u32 reg_5ghz_id;
+ int i;
+ int r = -ENOMEM;
+
+ reg_2ghz_id = ieee80211_regdomain2flag(regdomain_id, REG_2GHZ_MIN);
+ reg_5ghz_id = ieee80211_regdomain2flag(regdomain_id, REG_5GHZ_MIN);
+ r = ieee80211_regdomain2name(regdomain_id, reg_name);
+ BUG_ON(r);
+
+ /* Allocate regdomain */
+ *reg_p = kzalloc(sizeof(struct ieee80211_regdomain), GFP_KERNEL);
+ if (reg) {
+ r = -ENOMEM;
+ goto exit;
+ }
+
+ reg = *reg_p;
+ subbands = reg->subbands;
+
+ /* First update subband power maps */
+ update_reg_subband_map();
+
+ /* Now update power restrictions */
+ r = setup_reg_pw_restrictions(regdomain_id, reg);
+ BUG_ON(r);
+
+ /* Allocate 2GHz channels for regdomain */
+ if (reg_2ghz_id != DMN_NULL) {
+ r = __alloc_band_channels(regdomain_id, reg,
+ IEEE80211_24GHZ_BAND, reg_2ghz_id);
+ if (r)
+ goto free_sb_channels;
+ }
+
+ /* Allocate 5GHz channels for regdomain */
+ if (reg_5ghz_id != DMN_NULL) {
+ r = __alloc_band_channels(regdomain_id, reg,
+ IEEE80211_52GHZ_BAND, reg_2ghz_id);
+ if (r)
+ goto free_sb_channels;
+ }
+
+ /* Setup regdomain, bands and subbands */
+ setup_regdomain(reg, regdomain_id, reg_name);
+ check_reg_init(r, reg_name);
+ return 0;
+
+free_sb_channels:
+ for (i=0; i < REG_NUM_SUBBANDS; i++) {
+ struct ieee80211_subband_restrictions *sb;
+ sb = &subbands[i];
+ if (! list_empty(&sb->channel_list))
+ free_subband_channel_list(&sb->channel_list);
+ list_del(&sb->channel_list);
+ }
+exit:
+ check_reg_init(r, reg_name);
+ return r;
+}
+EXPORT_SYMBOL(regdomain_build);
+
+static int regdomains_init(void)
+{
+ int r;
+ printk("%s: %s v%s loaded\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION);
+
+ /* Load iso->reg map */
+ r = __load_iso3166_reg_map_list();
+ if(r)
+ goto free_iso_reg_map_list;
+ print_iso3166_reg_map();
+
+ return r;
+free_iso_reg_map_list:
+ free_iso3166_reg_map_list();
+ return r;
+}
+
+void regdomains_exit(void)
+{
+ /* Iso->reg map */
+ write_lock(&iso3166_reg_rwlock);
+ free_iso3166_reg_map_list();
+ list_del(&iso3166_reg_map_list);
+ write_unlock(&iso3166_reg_rwlock);
+ printk("%s: unloaded\n", DRV_NAME);
+}
+
+module_init(regdomains_init);
+module_exit(regdomains_exit);
diff --git a/net/wireless/regulatory_map.h b/net/wireless/regulatory_map.h
new file mode 100644
index 0000000..35fa358
--- /dev/null
+++ b/net/wireless/regulatory_map.h
@@ -0,0 +1,887 @@
+#ifndef _REGULATORY_MAP_H_
+/*
+ * Copyright (c) 2004, 2005 Reyk Floeter <[email protected]>
+ * Copyright (c) 2007 Luis R. Rodriguez <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "reg_common.h"
+
+static int ieee80211_regdomain2name(u32, char *);
+static u32 ieee80211_regdomain2flag(u32, u16);
+
+static void update_reg_subband_map(void);
+static int get_subband_pw_id(u32, u32, u32 *);
+
+struct reg_channel {
+ u16 rc_freq; /* Center of frequency */
+ u32 rc_domain;
+ /* Can be IEEE80211_RATE_OFDM, IEEE80211_RATE_CCK,
+ * depending on he rc_freq (mhz), we'll
+ * use the modulation cap to configure mode on the subband
+ * (MODE_IEEE80211A, MODE_IEEE80211B, MODE_IEEE80211G ) */
+ u32 rc_modulation_cap;
+};
+
+struct reg_domainname {
+ u32 rn_domain;
+ const char *rn_name;
+};
+
+struct reg_pw {
+ u32 p_domain;
+ char environment_cap;
+/* As like the last (3rd) octect of 802.11d Country
+ * Information Element string */
+#define REG_CAP_INDOOR 'I'
+#define REG_CAP_OUTDOOR 'O'
+#define REG_CAP_INOUT ' '
+ u8 max_antenna_gain;
+ u8 max_ir_ptmp;
+ u8 max_ir_ptp;
+ u8 max_eirp_ptmp;
+ u8 max_eirp_ptp;
+};
+
+struct reg_pw_subbands {
+ u32 domain_id;
+ u32 p_domain_2ghz;
+ u32 p_domain_telec;
+ u32 p_domain_unii1;
+ u32 p_domain_unii2;
+ u32 p_domain_etsi;
+ u32 p_domain_unii3;
+ u32 p_domain_aad;
+};
+
+struct reg_band {
+ u16 rm_domain;
+ u32 rm_domain_5ghz;
+ u32 rm_domain_2ghz;
+};
+
+struct reg_country {
+ /* ISO-3166-1 alpha 2 */
+ char cn_name[2];
+ u32 cn_domain;
+};
+
+struct reg_subband {
+ u32 sb_id;
+ char sb_name[30];
+ u16 sb_min_freq;
+ u16 sb_max_freq;
+ struct reg_pw *sb_reg_pw;
+ u8 sb_reg_pw_size;
+};
+
+#define REG_SUBBANDS { \
+ { DMN_SB_ISM24, "ISM", \
+ REG_ISM24_MIN, REG_ISM24_MAX, NULL, 0 }, \
+ { DMN_SB_TELEC, "TELEC", \
+ REG_TELEC_MIN, REG_TELEC_MAX, NULL, 0 }, \
+ { DMN_SB_UNII_1, "UNII-1", \
+ REG_UNII_1_MIN, REG_UNII_1_MAX, NULL, 0 }, \
+ { DMN_SB_UNII_2, "UNII-2 / ETSI", \
+ REG_UNII_2_MIN, REG_UNII_2_MAX, NULL, 0 }, \
+ { DMN_SB_ETSI, "ETSI", \
+ REG_ETSI_MIN, REG_ETSI_MAX, NULL, 0 }, \
+ { DMN_SB_UNII_3, "UNII-3", \
+ REG_UNII_3_MIN, REG_UNII_3_MAX, NULL, 0 }, \
+ { DMN_SB_AAD, "Asia/Africa/DSRC", \
+ REG_AAD_MIN, REG_AAD_MAX, NULL, 0 } \
+}
+
+/*
+ * EIRP - Equivalent Isotropically Radiated Power
+ * IR - Intentional Radiator, transmitter
+ * dBm - dB milliwatt (mW), the base says that 1mW = 0 dBm
+ * dBi - dB relative to isotropic, used to measure antenna gain compared to an
+ * isotropic antenna on which radiation is distributed uniformly on the
+ * surface of a sphere
+ *
+ * EIRP = IR - loss in transmission line + passive gain of the antenna
+ */
+
+#define DMN_P5_NULL DMN_NULL, DMN_NULL, DMN_NULL, \
+ DMN_NULL, DMN_NULL, DMN_NULL
+#define DMN_P5_DEBUG DMN_DEBUG, DMN_DEBUG, DMN_DEBUG, \
+ DMN_DEBUG, DMN_DEBUG, DMN_DEBUG
+
+#define DMN_P5_FCC1 DMN_NULL, DMN_PU1_FCC, DMN_PU2_FCC, \
+ DMN_NULL, DMN_PU3_FCC, DMN_NULL
+#define DMN_P5_FCC2 DMN_P5_FCC1
+#define DMN_P5_FCC3 DMN_NULL, DMN_PU1_FCC, DMN_PU2_FCC, \
+ DMN_PE_FCC, DMN_PU3_FCC, DMN_NULL
+
+#define DMN_P5_ETSI1 DMN_NULL, DMN_PU1_ETSI, DMN_PU2_ETSI, \
+ DMN_PE_ETSI, DMN_NULL, DMN_NULL
+#define DMN_P5_ETSI2 DMN_NULL, DMN_PU1_ETSI, DMN_NULL, \
+ DMN_NULL, DMN_NULL, DMN_NULL
+#define DMN_P5_ETSI3 DMN_NULL, DMN_PU1_ETSI, DMN_PU2_ETSI, \
+ DMN_NULL, DMN_NULL, DMN_NULL
+#define DMN_P5_ETSI4 DMN_P5_ETSI3
+#define DMN_P5_ETSI5 DMN_P5_ETSI2
+#define DMN_P5_ETSI6 DMN_NULL, DMN_PU1_ETSI, DMN_PU2_ETSI, \
+ DMN_PE_ETSI, DMN_NULL, DMN_NULL
+
+#define DMN_P5_MKK1 DMN_NULL, DMN_PU1_MKK, DMN_NULL, \
+ DMN_NULL, DMN_NULL, DMN_NULL
+#define DMN_P5_MKK2 DMN_PT_MKK, DMN_PU1_MKK, DMN_NULL, \
+ DMN_NULL, DMN_NULL, DMN_NULL
+
+#define DMN_P5_APL1 DMN_NULL, DMN_NULL, DMN_NULL, \
+ DMN_NULL, DMN_PU3_APL, DMN_NULL
+#define DMN_P5_APL2 DMN_P5_APL
+#define DMN_P5_APL3 DMN_NULL, DMN_NULL, DMN_PU2_APL, \
+ DMN_NULL, DMN_PU3_APL, DMN_NULL
+#define DMN_P5_APL4 DMN_NULL, DMN_PU1_APL, DMN_NULL, \
+ DMN_NULL, DMN_PU3_APL, DMN_NULL
+#define DMN_P5_APL5 DMN_P5_APL1
+
+#define REG_PW_24_MAP { \
+ { DMN_P24_FCC, REG_CAP_INOUT, REG_MAX_ANTENNA, 30, 30, 36, 0xff},\
+ { DMN_P24_ETSI, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_P24_WORLD,REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_P24_MKK, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_T_MAP { \
+ { DMN_PT_MKK, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_U1_MAP { \
+ { DMN_PU1_FCC, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_PU1_ETSI, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_PU1_MKK, REG_CAP_INOUT, REG_MAX_ANTENNA, 10, 0, 10, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_U2_MAP { \
+ { DMN_PU2_FCC, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_PU2_ETSI, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_E_MAP { \
+ { DMN_PE_FCC, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_PE_ETSI, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_U3_MAP { \
+ { DMN_PU3_FCC, REG_CAP_INOUT, REG_MAX_ANTENNA, 20, 0, 20, 0}, \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_AAD_MAP { \
+ { DMN_DEBUG, REG_CAP_INOUT, 0xff, 0xff, 0xff, 0xff, 0xff} \
+}
+
+#define REG_PW_MAP { \
+ { DMN_NULL_WORLD, DMN_P24_ETSI, DMN_P5_NULL }, \
+ { DMN_NULL_ETSIB, DMN_P24_ETSI, DMN_P5_NULL }, \
+ { DMN_NULL_ETSIC, DMN_P24_ETSI, DMN_P5_NULL }, \
+ { DMN_FCC1_WORLD, DMN_P24_FCC, DMN_P5_FCC1 }, \
+ { DMN_FCC1_FCCA, DMN_P24_FCC, DMN_P5_FCC1 }, \
+ { DMN_FCC2_WORLD, DMN_DEBUG, DMN_P5_FCC2 }, \
+ { DMN_FCC2_FCCA, DMN_P24_FCC, DMN_P5_FCC2 }, \
+ { DMN_FCC2_ETSIC, DMN_DEBUG, DMN_P5_FCC2 }, \
+ { DMN_FCC3_FCCA, DMN_P24_FCC, DMN_P5_FCC3 }, \
+ { DMN_ETSI1_WORLD, DMN_P24_ETSI, DMN_P5_ETSI1}, \
+ { DMN_ETSI2_WORLD, DMN_P24_ETSI, DMN_P5_ETSI2}, \
+ { DMN_ETSI3_WORLD, DMN_P24_ETSI, DMN_P5_ETSI3}, \
+ { DMN_ETSI3_ETSIA, DMN_P24_ETSI, DMN_P5_ETSI3}, \
+ { DMN_ETSI4_WORLD, DMN_P24_ETSI, DMN_P5_ETSI4}, \
+ { DMN_ETSI4_ETSIC, DMN_P24_ETSI, DMN_P5_ETSI4}, \
+ { DMN_ETSI5_WORLD, DMN_P24_ETSI, DMN_P5_ETSI5}, \
+ { DMN_ETSI6_WORLD, DMN_P24_ETSI, DMN_P5_ETSI5}, \
+ { DMN_MKK1_MKKA, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK1_MKKB, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK1_MKKB, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK1_FCCA, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK1_MKKA1, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK1_MKKA2, DMN_P24_MKK, DMN_P5_MKK1}, \
+ { DMN_MKK2_MKKA, DMN_P24_MKK, DMN_P5_MKK2}, \
+ { DMN_APL1_WORLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL1_APLA, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL1_ETSIC, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL1_FCCA, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL2_WORLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL2_ETSIC, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL2_APLC, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL2_APLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL3_WORLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL4_WORLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_APL5_WORLD, DMN_DEBUG, DMN_P5_DEBUG}, \
+ { DMN_DEBUG_DEBUG, DMN_DEBUG, DMN_P5_DEBUG} \
+}
+
+#define REG_CHANNELS_2GHZ { \
+ { 2432, DMN_WORLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4 GHz */ \
+ { 2437, DMN_WORLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_WORLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ \
+ { 2412, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4 GHz */ \
+ { 2417, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2422, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2427, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2432, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2437, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2447, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2452, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2457, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2462, DMN_FCCA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ \
+ { 2412, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4GHz */ \
+ { 2417, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2422, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2427, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2432, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2437, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2447, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2452, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2457, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2462, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2467, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2472, DMN_APLD, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ \
+ { 2432, DMN_ETSIB, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4GHz */ \
+ { 2437, DMN_ETSIB, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_ETSIB, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ \
+ { 2412, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4 GHz */ \
+ { 2417, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2422, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2427, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2432, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2437, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2447, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2452, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2457, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2462, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2467, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2472, DMN_ETSIC, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ \
+ { 2412, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4 GHz */ \
+ { 2417, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2422, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2427, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2432, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2437, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2447, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2452, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2457, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2462, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2467, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2472, DMN_MKKA, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2484, DMN_MKKA, IEEE80211_RATE_CCK }, \
+ \
+ { 2412, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* ISM 2.4 GHz */ \
+ { 2417, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Every 5MHz */ \
+ { 2422, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2427, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2432, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2437, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2442, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2447, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2452, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2457, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2462, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2467, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, \
+ { 2472, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM },/* Ch 13 */ \
+ { 2484, DMN_DEBUG, IEEE80211_RATE_CCK }, /* Japan 14, note we hopped 12 MHz */ \
+ { 2512, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM },/*Now every 20mhz*/ \
+ { 2532, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 16 */ \
+ { 2552, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 17 */ \
+ { 2572, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 18 */ \
+ { 2592, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 19 */ \
+ { 2612, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 20 */ \
+ { 2632, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 21 */ \
+ { 2652, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 22 */ \
+ { 2672, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 23 */ \
+ { 2692, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 24 */ \
+ { 2712, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM }, /* Ch 25 */ \
+ { 2732, DMN_DEBUG, IEEE80211_RATE_CCK|IEEE80211_RATE_OFDM } /* Ch 26 */ \
+}
+
+#define REG_CHANNELS_5GHZ { \
+ { 5745, DMN_APL1, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5765, DMN_APL1, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_APL1, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_APL1, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_APL1, IEEE80211_RATE_OFDM }, \
+ \
+ { 5745, DMN_APL2, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5765, DMN_APL2, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_APL2, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_APL2, IEEE80211_RATE_OFDM }, \
+ \
+ { 5280, DMN_APL3, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5300, DMN_APL3, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_APL3, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_APL3, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5765, DMN_APL3, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_APL3, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_APL3, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_APL4, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_APL4, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5765, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_APL4, IEEE80211_RATE_OFDM }, \
+ \
+ { 5745, DMN_APL5, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5765, DMN_APL5, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_APL5, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_APL5, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_APL5, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI1, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_ETSI1, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5500, DMN_ETSI1, IEEE80211_RATE_OFDM }, /* ETSI */ \
+ { 5520, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5540, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5560, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5580, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5600, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5620, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5640, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5660, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5680, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ { 5700, DMN_ETSI1, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI2, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI2, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI2, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI2, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI3, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_ETSI3, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_ETSI3, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI4, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_ETSI4, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_ETSI4, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI5, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI5, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI5, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI5, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_ETSI6, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_ETSI6, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5500, DMN_ETSI6, IEEE80211_RATE_OFDM }, /* ETSI */ \
+ { 5520, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5540, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5560, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5580, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5600, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5620, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5640, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5660, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5680, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ { 5700, DMN_ETSI6, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_FCC1, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5210, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5250, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_FCC1, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5290, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_FCC1, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5760, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5765, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5800, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_FCC1, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_FCC2, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_FCC2, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_FCC2, IEEE80211_RATE_OFDM }, /* UNII-3*/ \
+ { 5765, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_FCC2, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_FCC3, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5210, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5250, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_FCC3, IEEE80211_RATE_OFDM }, /* UNII-2 */ \
+ { 5280, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5290, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5500, DMN_FCC3, IEEE80211_RATE_OFDM }, /* ETSI */ \
+ { 5520, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5540, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5560, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5580, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5600, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5620, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5640, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5660, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5680, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5700, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_FCC3, IEEE80211_RATE_OFDM }, /* UNII-3 */ \
+ { 5760, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5765, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5800, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_FCC3, IEEE80211_RATE_OFDM }, \
+ \
+ { 5170, DMN_MKK1, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5190, DMN_MKK1, IEEE80211_RATE_OFDM }, \
+ { 5210, DMN_MKK1, IEEE80211_RATE_OFDM }, \
+ { 5230, DMN_MKK1, IEEE80211_RATE_OFDM }, \
+ \
+ { 5040, DMN_MKK2, IEEE80211_RATE_OFDM }, /* TELEC */ \
+ { 5060, DMN_MKK2, IEEE80211_RATE_OFDM }, \
+ { 5080, DMN_MKK2, IEEE80211_RATE_OFDM }, \
+ { 5170, DMN_MKK2, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5190, DMN_MKK2, IEEE80211_RATE_OFDM }, \
+ { 5210, DMN_MKK2, IEEE80211_RATE_OFDM }, \
+ { 5230, DMN_MKK2, IEEE80211_RATE_OFDM }, \
+ \
+ { 5180, DMN_WORLD, IEEE80211_RATE_OFDM }, /* UNII-1 */ \
+ { 5200, DMN_WORLD, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_WORLD, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_WORLD, IEEE80211_RATE_OFDM }, \
+ \
+ { 5005, DMN_DEBUG, IEEE80211_RATE_OFDM }, /* Ch 1 */ \
+ { 5010, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5015, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5020, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5025, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5030, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5035, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5040, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5045, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5050, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5055, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5060, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5065, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5070, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5075, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5080, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5085, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5090, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5095, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5100, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5105, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5110, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5115, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5120, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5125, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5130, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5135, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5140, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5145, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5150, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5155, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5160, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5165, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5170, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5175, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5180, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5185, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5190, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5195, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5200, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5205, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5210, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5215, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5220, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5225, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5230, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5235, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5240, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5245, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5250, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5255, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5260, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5265, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5270, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5275, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5280, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5285, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5290, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5295, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5300, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5305, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5310, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5315, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5320, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5325, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5330, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5335, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5340, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5345, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5350, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5355, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5360, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5365, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5370, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5375, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5380, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5385, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5390, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5395, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5400, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5405, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5410, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5415, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5420, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5425, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5430, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5435, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5440, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5445, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5450, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5455, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5460, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5465, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5470, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5475, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5480, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5485, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5490, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5495, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5500, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5505, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5510, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5515, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5520, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5525, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5530, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5535, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5540, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5545, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5550, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5555, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5560, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5565, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5570, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5575, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5580, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5585, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5590, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5595, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5600, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5605, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5610, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5615, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5620, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5625, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5630, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5635, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5640, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5645, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5650, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5655, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5660, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5665, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5670, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5675, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5680, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5685, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5690, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5695, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5700, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5705, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5710, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5715, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5720, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5725, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5730, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5735, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5740, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5745, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5750, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5755, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5760, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5765, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5770, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5775, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5780, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5785, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5790, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5795, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5800, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5805, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5810, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5815, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5820, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5825, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5830, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5835, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5840, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5845, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5850, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5855, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5860, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5865, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5870, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5875, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5880, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5885, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5890, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5895, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5900, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5905, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5910, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5915, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5920, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5925, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5930, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5935, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5940, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5945, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5950, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5955, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5960, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5965, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5970, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5975, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5980, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5985, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5990, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 5995, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6000, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6005, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6010, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6015, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6020, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6025, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6030, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6035, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6040, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6045, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6050, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6055, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6060, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6065, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6070, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6075, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6080, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6085, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6090, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6095, DMN_DEBUG, IEEE80211_RATE_OFDM }, \
+ { 6100, DMN_DEBUG, IEEE80211_RATE_OFDM } /* Ch 220 */ \
+}
+
+#define REG_NAMES { \
+ { DMN_APL1_APLA, "APL1A" }, \
+ { DMN_APL1_ETSIC, "APL1_ETSIC" }, \
+ { DMN_APL1_FCCA, "APL1_FCCA" }, \
+ { DMN_APL1_WORLD, "APL1W" }, \
+ { DMN_APL2_APLC, "APL2C" }, \
+ { DMN_APL2_APLD, "APL2D" }, \
+ { DMN_APL2_ETSIC, "APL2_ETSIC" }, \
+ { DMN_APL2_WORLD, "APL2W" }, \
+ { DMN_APL3_WORLD, "APL3W" }, \
+ { DMN_APL4_WORLD, "APL4W" }, \
+ { DMN_APL5_WORLD, "APL5W" }, \
+ { DMN_ETSI1_WORLD, "ETSI1W" }, \
+ { DMN_ETSI2_WORLD, "ETSI2W" }, \
+ { DMN_ETSI3_ETSIA, "ETSI3A" }, \
+ { DMN_ETSI3_WORLD, "ETSI3W" }, \
+ { DMN_ETSI4_ETSIC, "ETSI4C" }, \
+ { DMN_ETSI4_WORLD, "ETSI4W" }, \
+ { DMN_ETSI5_WORLD, "ETSI5W" }, \
+ { DMN_ETSI6_WORLD, "ETSI6W" }, \
+ { DMN_FCC1_FCCA, "FCC1A" }, \
+ { DMN_FCC1_WORLD, "FCC1W" }, \
+ { DMN_FCC2_ETSIC, "FCC2C" }, \
+ { DMN_FCC2_FCCA, "FCC2A" }, \
+ { DMN_FCC2_WORLD, "FCC2W" }, \
+ { DMN_FCC3_FCCA, "FCC3A" }, \
+ { DMN_MKK1_FCCA, "MKK1_FCCA" }, \
+ { DMN_MKK1_MKKA, "MKK1A" }, \
+ { DMN_MKK1_MKKA1, "MKK1A1" }, \
+ { DMN_MKK1_MKKA2, "MKK1A2" }, \
+ { DMN_MKK1_MKKB, "MKK1B" }, \
+ { DMN_MKK2_MKKA, "MKK2A" }, \
+ { DMN_NULL_ETSIB, "ETSIB" }, \
+ { DMN_NULL_ETSIC, "ETSIC" }, \
+ { DMN_NULL_WORLD, "WORLD" }, \
+ { DMN_DEBUG_DEBUG, "DEBUG_DEBUG" } \
+}
+
+#define REG_MAP { \
+ { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, \
+ { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, \
+ { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, \
+ { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, \
+ { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, \
+ { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, \
+ { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, \
+ { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, \
+ { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, \
+ { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, \
+ { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, \
+ { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, \
+ { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, \
+ { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, \
+ { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, \
+ { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, \
+ { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, \
+ { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, \
+ { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, \
+ { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, \
+ { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, \
+ { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, \
+ { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, \
+ { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, \
+ { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, \
+ { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, \
+ { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, \
+ { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, \
+ { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, \
+ { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, \
+ { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, \
+ { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, \
+ { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, \
+ { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, \
+ { DMN_DEBUG_DEBUG, DMN_DEBUG, DMN_DEBUG } \
+}
+
+/* Anything not here gets DMN_NULL_WORLD regdomain */
+#define REG_COUNTRY_NAMES { \
+ { "00", DMN_NULL_WORLD}, \
+ { "AM", DMN_ETSI4_WORLD }, \
+ { "AR", DMN_APL3_WORLD }, \
+ { "AT", DMN_ETSI5_WORLD }, \
+ { "AU", DMN_FCC2_WORLD }, \
+ { "AZ", DMN_ETSI4_WORLD }, \
+ { "BE", DMN_ETSI4_WORLD }, \
+ { "BG", DMN_ETSI6_WORLD }, \
+ { "BN", DMN_APL1_WORLD }, \
+ { "BO", DMN_APL1_ETSIC }, \
+ { "BR", DMN_NULL_ETSIC }, \
+ { "BZ", DMN_NULL_ETSIC }, \
+ { "CA", DMN_FCC2_FCCA }, \
+ { "CH", DMN_ETSI2_WORLD }, \
+ { "CL", DMN_APL5_WORLD }, \
+ { "CN", DMN_APL1_WORLD }, \
+ { "CO", DMN_FCC1_FCCA }, \
+ { "CY", DMN_ETSI1_WORLD }, \
+ { "CZ", DMN_ETSI3_WORLD }, \
+ { "DE", DMN_ETSI1_WORLD }, \
+ { "DK", DMN_ETSI1_WORLD }, \
+ { "DO", DMN_FCC1_FCCA }, \
+ { "EE", DMN_ETSI1_WORLD }, \
+ { "ES", DMN_ETSI1_WORLD }, \
+ { "F2", DMN_ETSI3_WORLD }, \
+ { "FI", DMN_ETSI1_WORLD }, \
+ { "FR", DMN_ETSI3_WORLD }, \
+ { "GB", DMN_ETSI1_WORLD }, \
+ { "GE", DMN_ETSI4_WORLD }, \
+ { "GT", DMN_FCC1_FCCA }, \
+ { "HK", DMN_FCC2_WORLD }, \
+ { "HR", DMN_ETSI3_WORLD }, \
+ { "HU", DMN_ETSI2_WORLD }, \
+ { "IE", DMN_ETSI1_WORLD }, \
+ { "IR", DMN_APL1_WORLD }, \
+ { "IS", DMN_ETSI1_WORLD }, \
+ { "IT", DMN_ETSI1_WORLD }, \
+ { "J1", DMN_MKK1_MKKB }, \
+ { "J2", DMN_MKK1_FCCA }, \
+ { "J3", DMN_MKK2_MKKA }, \
+ { "J4", DMN_MKK1_MKKA1 }, \
+ { "J5", DMN_MKK1_MKKA2 }, \
+ { "JP", DMN_MKK1_MKKA }, \
+ { "K2", DMN_APL2_APLD }, \
+ { "KP", DMN_APL2_WORLD }, \
+ { "KR", DMN_APL2_WORLD }, \
+ { "LI", DMN_ETSI2_WORLD }, \
+ { "LT", DMN_ETSI1_WORLD }, \
+ { "LU", DMN_ETSI1_WORLD }, \
+ { "MC", DMN_ETSI4_WORLD }, \
+ { "MO", DMN_FCC2_WORLD }, \
+ { "MX", DMN_FCC1_FCCA }, \
+ { "NL", DMN_ETSI1_WORLD }, \
+ { "NO", DMN_ETSI1_WORLD }, \
+ { "NZ", DMN_FCC2_ETSIC }, \
+ { "PA", DMN_FCC1_FCCA }, \
+ { "PH", DMN_FCC1_WORLD }, \
+ { "PL", DMN_ETSI1_WORLD }, \
+ { "PR", DMN_FCC1_FCCA }, \
+ { "PT", DMN_ETSI1_WORLD }, \
+ { "SE", DMN_ETSI1_WORLD }, \
+ { "SG", DMN_APL4_WORLD }, \
+ { "SI", DMN_ETSI1_WORLD }, \
+ { "SK", DMN_ETSI3_WORLD }, \
+ { "TH", DMN_APL2_WORLD }, \
+ { "TN", DMN_ETSI3_WORLD }, \
+ { "TR", DMN_ETSI3_WORLD }, \
+ { "TT", DMN_ETSI4_WORLD }, \
+ { "TW", DMN_APL3_WORLD }, \
+ { "UK", DMN_ETSI1_WORLD }, \
+ { "US", DMN_FCC1_FCCA }, \
+ { "UY", DMN_APL2_WORLD }, \
+ { "UZ", DMN_FCC3_FCCA }, \
+ { "VE", DMN_APL2_ETSIC }, \
+ { "ZA", DMN_ETSI1_WORLD }, \
+ { "99", DMN_DEBUG_DEBUG} \
+}
+
+#endif /* _REGULATORY_MAP_H_ */
--
1.5.2.4


Attachments:
(No filename) (72.98 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-21 21:05:59

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 4/5] Wireless: Add regdomain support to cfg80211

This patch makes cfg80211 provide an interface for defining
a central regulatory domain all cfg80211 wireless drivers
should adhere to.

Now when cfg80211 starts up and you will see this:

ieee80211_regdomains: regulatory domain WORLD created
Regulatory Domain: WORLD Regulatory Domain ID: 0x03
IEEE 802.11g 2GHz ISM subband
max_ir_ptmp: 20 dBm max_eirp_ptmp: 20 dBm
max_ir_ptp: 0 dBm max_eirp_ptp: 0 dBm
max_antenna_gain: 6 dBi
Environment capability: Indoor & Outdoor
Channel Freq (MHz)
5 2432
6 2437
7 2442

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
include/net/cfg80211.h | 72 ++++++++++++++++++++++++++
net/wireless/Kconfig | 1 +
net/wireless/core.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 206 insertions(+), 0 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1459d12..34fd74b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5,11 +5,13 @@
#include <linux/skbuff.h>
#include <linux/nl80211.h>
#include <net/genetlink.h>
+#include <net/ieee80211_regdomains.h>

/*
* 802.11 configuration in-kernel interface
*
* Copyright 2006 Johannes Berg <[email protected]>
+ * Copyright 2007 Luis R. Rodriguez <[email protected]>
*/

/**
@@ -117,6 +119,73 @@ extern int ieee80211_radiotap_iterator_next(
struct wiphy;

/**
+ * enum regdom_set_by - the different ways by which the central regulatory
+ * domain can be set
+ *
+ * @REG_SET_BY_INIT: indicates regdomain was set by regdomain_init()
+ * @REG_SET_BY_DRIVER: indicates regdomain was set by a driver
+ * through cfg80211_set_regdomain(). This type of settings is ignored if
+ * the regdomain was already set by userspace (%REG_SET_BY_USER). If
+ * userspace never set the regdomain and two drivers are found trying to
+ * set the regdomain to two different regdomains then the world regulatory
+ * domain will be set by cfg80211_set_regdomain().
+ * @REG_SET_BY_USER: indicates regdomain was set by userspace.
+ * @REG_SET_BY_80211D: indicates an 802.11d frame was received with a valid
+ * country information element to which the wireless stack is going to
+ * adhere to.
+ * @REG_SET_BY_CONFLICT: indicates a conflict was found and regdomain was
+ * therefore set to the world regulatory domain by
+ * cfg80211_set_regdomain().
+ */
+enum regdom_set_by {
+ REG_SET_BY_INIT = 1,
+ REG_SET_BY_DRIVER,
+ REG_SET_BY_USER,
+ REG_SET_BY_80211D,
+ REG_SET_BY_CONFLICT
+};
+
+/**
+ * struct cfg80211_regdomain_settings - central regulatory domain settings
+ *
+ * @regdomain: central regulatory domain, an &ieee80211_regdomain
+ *
+ * @country: country to which this regulatory domain corresponds in the
+ * last setting. This must be a valid ISO3166-1 country or one of the
+ * accepted exceptions, such as 00 for the world regulatory domain or
+ * UK for the United Kingdom.
+ *
+ * @set_by: tells us who set last the regualtory domain. This can be any of
+ * %regdom_set_by
+ *
+ * @wiphy: wiphy of driver who last set the regdomain, if set by
+ * driver. This used to determine conflicts of driver regulatory domains
+ * settings if more than one wirless card is present and to simply keep
+ * record if a driver set the regulatory domain which driver set it.
+ *
+ * This structure defines the cfg80211 central wireless regulatory domain
+ * structure which all cfg80211 drivers should adhere to. It is initialized to
+ * the world regulatory domain by cfg80211 by default (%REG_SET_BY_INIT). If a
+ * wireless driver present has a built-in regulatory domain set either in the
+ * EEPROM or firmware it can inform cfg80211 about this and change the
+ * regulatory domain as such (%REG_SET_BY_DRIVER). If a second wireless card
+ * is present and if there is a conflict between regulatory domains then the
+ * world regulatory domain is set (%REG_SET_BY_CONFLICT). The regulatory domain
+ * can also be changed by receiving an 802.11d frame with a valid country code
+ * (%REG_SET_BY_80211D). Finally, If the regulatory domain was set by userspace
+ * (%REG_SET_BY_USER) then driver specific setting of regulatory domains
+ * (%REG_SET_BY_DRIVER) and 802.11d frames for changing the regulatory domain
+ * (%REG_SET_BY_80211D) will be ignored.
+ */
+struct cfg80211_regdomain_settings {
+ struct ieee80211_regdomain *regdomain;
+ enum regdom_set_by set_by;
+ struct wiphy *wiphy;
+ char country[ISOCOUNTRYSIZ2];
+};
+
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -183,6 +252,9 @@ struct cfg80211_ops {
struct key_params *params);
};

+extern int cfg80211_set_regdomain(char *country, u32,
+ enum regdom_set_by set_by,
+ struct wiphy *wiphy_reg_set);

/* helper functions specific to nl80211 */
extern void *nl80211hdr_put(struct sk_buff *skb, u32 pid,
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index c60ee87..0505347 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,5 +1,6 @@
config CFG80211
tristate "Improved wireless configuration API"
+ select IEEE80211_REGDOMAINS

config NL80211
bool "nl80211 new netlink interface support"
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 2f3f7b6..c2f773b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -2,6 +2,7 @@
* This is the linux wireless configuration interface.
*
* Copyright 2006, 2007 Johannes Berg <[email protected]>
+ * Copyright 2007 Luis R. Rodriguez <[email protected]>
*/

#include <linux/if.h>
@@ -34,6 +35,14 @@ LIST_HEAD(cfg80211_drv_list);
DEFINE_MUTEX(cfg80211_drv_mutex);
static int wiphy_counter;

+/* All cfg80211 drivers adhere to this */
+struct cfg80211_regdomain_settings cfg80211_regdomain;
+EXPORT_SYMBOL(cfg80211_regdomain);
+/* Since the regulatory domain may be set by different events we protect its
+ * structure */
+DEFINE_MUTEX(cfg80211_regdomain_mutex);
+EXPORT_SYMBOL(cfg80211_regdomain_mutex);
+
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;

@@ -335,12 +344,135 @@ static struct notifier_block cfg80211_netdev_notifier = {
.notifier_call = cfg80211_netdev_notifier_call,
};

+int cfg80211_set_regdomain(char *country, u32 regdomain_id,
+ enum regdom_set_by set_by,
+ struct wiphy *wiphy_reg_set)
+{
+ struct ieee80211_regdomain *old_reg, *new_reg;
+ int r = 0;
+ enum regdom_set_by old_set_by;
+ int needs_freeing = 0;
+
+ mutex_lock(&cfg80211_regdomain_mutex);
+ old_reg = cfg80211_regdomain.regdomain;
+ old_set_by = cfg80211_regdomain.set_by;
+
+ switch (cfg80211_regdomain.set_by) {
+ case 0:
+ switch (set_by) {
+ case REG_SET_BY_INIT:
+ /* XXX: Test this first */
+ cfg80211_regdomain.set_by = REG_SET_BY_INIT;
+ break;
+ default:
+ /* Should not happen unless later we support clearing
+ * of set_by before calling this routine */
+ r = -EOPNOTSUPP;
+ goto unlock_and_exit;
+ }
+ break;
+ case REG_SET_BY_INIT:
+ switch (set_by) {
+ case REG_SET_BY_INIT:
+ /* Should never happen */
+ r = -EOPNOTSUPP;
+ goto unlock_and_exit;
+ case REG_SET_BY_DRIVER:
+ if (wiphy_reg_set == NULL) {
+ r =-EINVAL;
+ goto unlock_and_exit;
+ }
+ /* XXX: This is not handled yet */
+ r = -EOPNOTSUPP; /* Not handled yet */
+ goto unlock_and_exit;
+ case REG_SET_BY_USER:
+ printk("Userspace changed regulatory domain\n");
+ /* XXX don't free until we know for sure we set
+ * a new regdomain, then free it and arrange pointers */
+ needs_freeing = 1;
+ cfg80211_regdomain.set_by = REG_SET_BY_USER;
+ break;
+ default:
+ BUG();
+ }
+ break;
+ case REG_SET_BY_USER:
+ switch (set_by) {
+ case REG_SET_BY_USER:
+ printk("Userspace changed regulatory domain\n");
+ needs_freeing = 1;
+ cfg80211_regdomain.set_by = REG_SET_BY_USER;
+ break;
+ default:
+ r = -EOPNOTSUPP; /* Not handled yet */
+ goto unlock_and_exit;
+ }
+ break;
+ default:
+ r = -EOPNOTSUPP; /* Not handled yet */
+ goto unlock_and_exit;
+ break;
+ }
+
+ /* This does all the work */
+ r = regdomain_build(regdomain_id, &new_reg);
+ if(r) {
+ cfg80211_regdomain.set_by = old_set_by;
+ goto unlock_and_exit;
+ }
+
+ if (needs_freeing) {
+ free_regdomain(old_reg);
+ cfg80211_regdomain.regdomain = NULL;
+ }
+
+ strcpy(cfg80211_regdomain.country, country);
+ cfg80211_regdomain.country[ISOCOUNTRYSIZ2] = '\0';
+ /* Lastly, update pointer */
+ cfg80211_regdomain.regdomain = new_reg;
+ mutex_unlock(&cfg80211_regdomain_mutex);
+ print_regdomain(cfg80211_regdomain.regdomain);
+
+ return 0;
+
+unlock_and_exit:
+ mutex_unlock(&cfg80211_regdomain_mutex);
+ return r;
+}
+EXPORT_SYMBOL(cfg80211_set_regdomain);
+
+static int regdomain_init(void)
+{
+ int r;
+ char country[ISOCOUNTRYSIZ2] = DEFAULT_REG_ISO3166_1;
+ u32 regdomain_id = 0; /* Initialize just to shut up GCC */
+
+ country[ISOCOUNTRYSIZ2] = '\0';
+
+ memset(&cfg80211_regdomain, 0,
+ sizeof(struct cfg80211_regdomain_settings));
+
+ r = iso3166_to_reg(country, &regdomain_id);
+ if (r)
+ return r;
+ r = cfg80211_set_regdomain(country, regdomain_id,
+ REG_SET_BY_INIT, NULL);
+ if (r)
+ return r;
+
+ return 0;
+}
+
static int cfg80211_init(void)
{
int err = wiphy_sysfs_init();
if (err)
goto out_fail_sysfs;

+ err = regdomain_init();
+ if (err)
+ goto out_fail_sysfs;
+
err = register_netdevice_notifier(&cfg80211_netdev_notifier);
if (err)
goto out_fail_notifier;
@@ -367,6 +499,7 @@ static void cfg80211_exit(void)
debugfs_remove(ieee80211_debugfs_dir);
nl80211_exit();
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
+ free_regdomain(cfg80211_regdomain.regdomain);
wiphy_sysfs_exit();
}
module_exit(cfg80211_exit);
--
1.5.2.4


Attachments:
(No filename) (9.67 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-21 20:59:19

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 1/5] Move standard wireless defintions out of mac80211

I tried moving the common stuff to a few already existing files and in
all of them I had dependency issues. Adding a wireless_common hoping
we can later clean out net/ieee80211.h and linux/ieee80211.h

* Move standard wireless structs and definitions out of mac80211 and into
a wireless_common.h.
* Move IEEE80211_CHAN_W_* flags, struct ieee80211_channel, IEEE80211_RATE_*
flags, struct ieee80211_rate, and enum ieee80211_phymode out to
wireless_common.h
* Move IEEE80211_CHAN_W_* defines to enum channel_flags, add documenation
* Move IEEE80211_RATE_* defines to enum rate_flags, add documenation
* Add documenation for ieee80211_channel
* Add documenation for ieee80211_rate
* Remove unused min_rssi_ack, and min_rssi_ack_delta from struct
ieee80211_rate as its unused
* Remove usage of min_rssi_ack and min_rssi_ack_delta from Ralink driver
(rt2x00dev.c), it just initialized it unnesariily to 0 (as the struct was
kzalloc'd anyway). But mac80211 never used this.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00dev.c | 2 -
include/net/mac80211.h | 63 +------------
include/net/wireless_common.h | 154 +++++++++++++++++++++++++++++++
3 files changed, 155 insertions(+), 64 deletions(-)
create mode 100644 include/net/wireless_common.h

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index cd82eef..68aee89 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -559,8 +559,6 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
entry->val2 = entry->val;
if (entry->flags & IEEE80211_RATE_PREAMBLE2)
entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
- entry->min_rssi_ack = 0;
- entry->min_rssi_ack_delta = 0;
}

static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9b4b4a2..4832e6a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -19,6 +19,7 @@
#include <linux/wireless.h>
#include <linux/device.h>
#include <linux/ieee80211.h>
+#include <net/wireless_common.h>
#include <net/wireless.h>
#include <net/cfg80211.h>

@@ -47,68 +48,6 @@
* copying of the data.
*/

-#define IEEE80211_CHAN_W_SCAN 0x00000001
-#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
-#define IEEE80211_CHAN_W_IBSS 0x00000004
-
-/* Channel information structure. Low-level driver is expected to fill in chan,
- * freq, and val fields. Other fields will be filled in by 80211.o based on
- * hostapd information and low-level driver does not need to use them. The
- * limits for each channel will be provided in 'struct ieee80211_conf' when
- * configuring the low-level driver with hw->config callback. If a device has
- * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
- * can be set to let the driver configure all fields */
-struct ieee80211_channel {
- short chan; /* channel number (IEEE 802.11) */
- short freq; /* frequency in MHz */
- int val; /* hw specific value for the channel */
- int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
- unsigned char power_level;
- unsigned char antenna_max;
-};
-
-#define IEEE80211_RATE_ERP 0x00000001
-#define IEEE80211_RATE_BASIC 0x00000002
-#define IEEE80211_RATE_PREAMBLE2 0x00000004
-#define IEEE80211_RATE_SUPPORTED 0x00000010
-#define IEEE80211_RATE_OFDM 0x00000020
-#define IEEE80211_RATE_CCK 0x00000040
-#define IEEE80211_RATE_MANDATORY 0x00000100
-
-#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
-#define IEEE80211_RATE_MODULATION(f) \
- (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
-
-/* Low-level driver should set PREAMBLE2, OFDM and CCK flags.
- * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
- * configuration. */
-struct ieee80211_rate {
- int rate; /* rate in 100 kbps */
- int val; /* hw specific value for the rate */
- int flags; /* IEEE80211_RATE_ flags */
- int val2; /* hw specific value for the rate when using short preamble
- * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
- * 2, 5.5, and 11 Mbps) */
- signed char min_rssi_ack;
- unsigned char min_rssi_ack_delta;
-
- /* following fields are set by 80211.o and need not be filled by the
- * low-level driver */
- int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
- * optimizing channel utilization estimates */
-};
-
-/* 802.11g is backwards-compatible with 802.11b, so a wlan card can
- * actually be both in 11b and 11g modes at the same time. */
-enum ieee80211_phymode {
- MODE_IEEE80211A, /* IEEE 802.11a */
- MODE_IEEE80211B, /* IEEE 802.11b only */
- MODE_IEEE80211G, /* IEEE 802.11g (and 802.11b compatibility) */
-
- /* keep last */
- NUM_IEEE80211_MODES
-};
-
struct ieee80211_hw_mode {
int mode; /* MODE_IEEE80211... */
int num_channels; /* Number of channels (below) */
diff --git a/include/net/wireless_common.h b/include/net/wireless_common.h
new file mode 100644
index 0000000..1e88d6e
--- /dev/null
+++ b/include/net/wireless_common.h
@@ -0,0 +1,154 @@
+#ifndef __NET_WIRELESS_COMMON_H
+#define __NET_WIRELESS_COMMON_H
+/*
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <[email protected]>
+ * Copyright 2007 Johannes Berg <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Standard wireless common structs and definitions. */
+
+/**
+ * enum channel_flags - internal &ieee80211_channel flags
+ *
+ * Use these flags to indicate to the lower layers details about an
+ * &ieee80211_channel.
+ *
+ * @IEEE80211_CHAN_W_SCAN: if this flag is set it informs the lower layer that
+ * this channel can be passively scanned for.
+ * @IEEE80211_CHAN_W_ACTIVE_SCAN: if this flag is set it informs the lower layers
+ * which channels can be scanned actively. Active scanning is done by sending a
+ * probe. Specifically, mac80211 sends this probe via the host MLME kernel's
+ * MLME ieee80211_send_probe_req()
+ * @IEEE80211_CHAN_W_IBSS: if this flag is found in &ieee80211_channel's @flag
+ * it indicates to that channel can be used in an IBSS.
+ */
+enum channel_flags {
+ IEEE80211_CHAN_W_SCAN = (1<<0),
+ IEEE80211_CHAN_W_ACTIVE_SCAN = (1<<1),
+ IEEE80211_CHAN_W_IBSS = (1<<2),
+};
+
+/**
+ * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
+ *
+ * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
+ * is in charge of filling most of these fields out. The low-level driver
+ * is expected to fill in, if needed, the val field. Note that val is already
+ * set by the regulatory agent to the same channel as in chan.
+ *
+ * @chan: channel number (IEEE 802.11)
+ * @freq: center of frequency in MHz
+ * @val: hw specific value for the channel
+ * @flag: flag for hostapd use (IEEE80211_CHAN_*)
+ * @power_level: max allowed eirp in dBm
+ * @antenna_max: max allowed antenna gain in dBi
+ * @modulation_cap: could be IEEE80211_RATE_*
+ * @list: lets you make this structure part of a linked list
+ */
+struct ieee80211_channel {
+ /* XXX change to u8 */
+ short chan;
+ /* change to u16 */
+ short freq;
+ int val;
+ int flag;
+ unsigned char power_level;
+ unsigned char antenna_max;
+ u32 modulation_cap;
+ struct list_head list;
+};
+
+/* XXX consider removing the holes bellow */
+
+/**
+ * enum rate_flags - internal &ieee80211_rate flags
+ *
+ * Use these flags to indicate to the lower layers details about an
+ * &ieee80211_rate.
+ *
+ * @IEEE80211_RATE_ERP: indicates if the rate is an Extended Rate PHY (ERP)
+ * @IEEE80211_RATE_BASIC: indicates the rate is a basic rate for the
+ * currently used mode
+ * @IEEE80211_RATE_PREAMBLE2: used to indicates that the rate for short
+ * preamble is to be used. This is set in &ieee80211_rate's @val2.
+ * @IEEE80211_RATE_SUPPORTED: indicates if rate is supported by the given mode
+ * @IEEE80211_RATE_OFDM: indicates support for ODFM modulation
+ * @IEEE80211_RATE_CCK: indicates support for CCK modulation
+ * @IEEE80211_RATE_MANDATORY: indicates if this rate is mandatory for the
+ * currently used mode
+ */
+enum rate_flags {
+ IEEE80211_RATE_ERP = (1<<0),
+ IEEE80211_RATE_BASIC = (1<<1),
+ IEEE80211_RATE_PREAMBLE2 = (1<<2),
+ /* Hole at 0x08 */
+ IEEE80211_RATE_SUPPORTED = (1<<4),
+ IEEE80211_RATE_OFDM = (1<<5),
+ IEEE80211_RATE_CCK = (1<<6),
+ /* Hole at 0x80 */
+ IEEE80211_RATE_MANDATORY = (1<<7),
+};
+
+/* XXX move to inline and add documenation, kernel-doc can't doc defines */
+#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+#define IEEE80211_RATE_MODULATION(f) \
+ (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+
+/**
+ * ieee80211_rate - defines a standard ieee8011_rate
+ *
+ * Low-level driver should set PREAMBLE2, OFDM and CCK flags.
+ * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+ * configuration.
+ *
+ * @rate: rate in 100 kbps
+ * @val: hw specific value for the rate
+ * @flags: IEEE80211_RATE_* flags
+ * @val2: hw specific value for the rate when using short preamble
+ * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+ * 2, 5.5, and 11 Mbps)
+ * @min_rssi_ack: Minimum required RSSI of packet to generate an ACK ??
+ * @min_rssi_ack_delta: ??
+ *
+ */
+struct ieee80211_rate {
+ int rate;
+ int val;
+ int flags;
+ int val2;
+ signed char min_rssi_ack;
+ unsigned char min_rssi_ack_delta;
+
+ /* private */
+
+ /* the following fields are set by 80211.o and need not be filled by the
+ * low-level driver */
+
+ /* inverse of the rate (LCM(all rates) / rate) for optimizing channel
+ * utilization estimates */
+ int rate_inv;
+};
+
+/**
+ * enum ieee80211_phymode - modes for a physical 802.11 device
+ *
+ * @MODE_IEEE80211A: IEEE 802.11a
+ * @MODE_IEEE80211B: IEEE 802.11b only
+ * @MODE_IEEE80211G: IEEE 802.11g (and 802.11b compatibility)
+ * @NUM_IEEE80211_MODES: number of standard IEEE-802.11 modes currently supported
+ */
+enum ieee80211_phymode {
+ MODE_IEEE80211A,
+ MODE_IEEE80211B,
+ MODE_IEEE80211G,
+
+ /* keep last */
+ NUM_IEEE80211_MODES
+};
+
+#endif /* __NET_WIRELESS_COMMON_H */
--
1.5.2.4


Attachments:
(No filename) (10.11 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-22 00:14:10

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

As Johill pointed out to me, these patches are signed and therefore
can't be applied, if you want to give them a run, you can wget them
from here:

http://www.kernel.org/pub/linux/kernel/people/mcgrof/v2-regdomain-patches/

Luis

2007-09-26 15:04:34

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On Mon, 2007-09-24 at 13:49 -0400, Luis R. Rodriguez wrote:
> On 9/24/07, Joerg Mayer <[email protected]> wrote:
> > On Fri, Sep 21, 2007 at 05:33:42PM -0400, Luis R. Rodriguez wrote:
> > > > > + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> > > > > + *
> > > > > + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> > > > > + * is in charge of filling most of these fields out. The low-level driver
> > > > > + * is expected to fill in, if needed, the val field. Note that val is already
> > > > > + * set by the regulatory agent to the same channel as in chan.
> > > >
> > > > Shouldn't you also set chan and freq in the driver?
> > [...]
> > > Initially I wanted to move mac80211 to use a linked list of channels
> > > instead of an array for each mode. As we discussed it over (you, me
> > > and a few others) we determined it wasn't best to do this (I have a
> > > patch that allows this just in case we later change our mind). But --
> > > previous to doing this I had a wrapper on ieee80211_channel as I
> > > wanted the central regdomain to have a linked list of reg domain
> > > channels. If we don't want a wrapper we have to add this to the
> > > ieee8021_channel struct. Otherwise I need to define my own channel
> > > struct which wraps around ieee80211_channel.
> > >
> > > > > +struct ieee80211_channel {
> > > > > + /* XXX change to u8 */
> > > > > + short chan;
> > > >
> > > > Not sure, is a u8 always enough? I thought 802.11a had huge channel
> > > > numbers?
> > >
> > > Not that huge :-) Highest I've heard is 220. u8 should suffice.
> >
> > What's the idea of working with channels? Channels are non-uniq numbers.
> > Internally everything should work with center frequency and not with
> > channels. If necessary, information should be converted from channels
> > by the driver when reporting it into the stack. That way there also won't
> > be any problems if there ever is a channel 417.
>
> I agree. I'm OK with just having center of freq. Right now WE supports
> channel or freqs and the value is passed directly to the driver (for
> FullMAC) or mac80211 (for SoftMAC). For nl80211 we can just support
> channel passing onto the kernel, if the user supplies a channel we'll
> do the conversion to freq in userspace. On step at a time.

Definitely need to use freq and not channel. Channels are not unique
(they just _happen_ to be so right now). Of course remember that we
can't just pass channel really, we need to pass the tuple of (channel,
band) or maybe even (channel, [A|B|G|N]) or something.

Dan



2007-09-21 21:29:25

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module

On Fri, 2007-09-21 at 17:04 -0400, Luis R. Rodriguez wrote:

> +/* XXX: <net/ieee80211.h> has two band defs bellow */
> +#ifndef IEEE80211_24GHZ_BAND
> +#define IEEE80211_24GHZ_BAND (1<<0)
> +#define IEEE80211_52GHZ_BAND (1<<1)
> +#endif

Hmm. Could we make a new definition with just an enum?

enum ieee80211_band {
IEEE80211_BAND_24GHZ,
IEEE80211_BAND_52GHZ,
};

Then we can use "enum ieee80211_band" below in the structs and get type
checking. Generally, no new stuff has anything to do with
include/net/ieee80211.h, that's just for the old "stack".

> +/**
> + * struct ieee80211_subband_restrictions - defines a regulatory domain
> + * subband restrictions list

I think the docs should include where this structure is used.

> + * @name: name for this subband.

Why does it need a name?

> + * @min_freq: minimum frequency for this subband, in MHz. This represents the
> + * center of frequency of a channel.
> + * @max_freq: maximum frequency for this subband, in MHz. This represents the
> + * center of frequency of a channel.

How can both be center freq?

> +struct ieee80211_subband_restrictions {
> + u8 band;
> + char name[REGSBNAMSIZ];
> + u16 min_freq;
> + u16 max_freq;
> + u32 modulation_cap;
> + u8 max_antenna_gain;
> + u8 max_ir_ptmp;
> + u8 max_ir_ptp;
> +#define REG_DIPOLE_ANTENNA_GAIN 2
> + u8 max_eirp_ptmp;
> + u8 max_eirp_ptp;
> +#define REG_CAP_INDOOR 'I'
> +#define REG_CAP_OUTDOOR 'O'
> +#define REG_CAP_INOUT ' '

Did you actually run kernel-doc? it's rather unhappy with such things :)

> +/**
> + * struct ieee80211_regdomain - defines a regulatory domain
> + *
> + * @regdomain_id: ID of this regulatory domain. Some come from
> + * http://standards.ieee.org/getieee802/download/802.11b-1999_Cor1-2001.pdf
> + * @regdomain_name: name of this regulatory domain.
> + * @list: node, part of band_restrictions_list
> + *
> + * This structure defines a regulatory domain, which consists of channel and
> + * power restrictions. Some regulatory domains come from
> + * 802.11b-1999_Cor1-2001, the rest are based on Reyk Floeter's ar5k. If
> + * there is need to add more values here, please add one that is either
> + * defined in a standard or that many hardware devices have adopted. Also
> + * note that multiple countries can map to the same @regdomain_id

There's no table here where you could add values, is there?.

> + */
> +struct ieee80211_regdomain {
> + u32 regdomain_id;
> + char regdomain_name[REGNAMSIZ];
> + struct ieee80211_subband_restrictions subbands[REG_NUM_SUBBANDS];

Why is that not a variable length array with the number of items given
in an extra var?

> + * This structure holds the mapping of the country to a specific regulatory
> + * domain. Keep in mind more than one country can map to the same regulatory
> + * domain. The ISO-3166-1 alpha2 country code also happens to be used in the
> + * 802.11d Country Information Element on the string for the country. It
> + * should be noted, however, that in that the size of this string, is
> + * three octects while our string is only 2. The third octet is used to
> + * indicate Indoor/outdoor capabilities which we set in
> + * @ieee80211_subband_restrictions environment_cap.
> + */
> +struct ieee80211_iso3166_reg_map {
> + char alpha2[ISOCOUNTRYSIZ2];
> + u32 regdomain_id; /* stack-aware value */
> + /* XXX: shall we just use an array? */
> + struct list_head list; /* node, part of iso3166_reg_map_list */
> +};

Why does this need a list if it's a static mapping? Why does it need to
be visible outside of net/wireless/?

> +/**
> + * regdomain_mhz2ieee - convert a frequency to an IEEE-80211 channel number
> + * @freq: center of frequency in MHz. We support a range:
> + * 2412 - 2732 MHz (Channel 1 - 26) in the 2GHz band and
> + * 5005 - 6100 MHz (Channel 1 - 220) in the 5GHz band.
> + *
> + * Given a frequency in MHz returns the respective IEEE-80211 channel
> + * number. You are expected to provide the center of freqency in MHz.
> + */
> +u16 regdomain_mhz2ieee(u16 freq);

Ok this I can see being necessary for drivers/stacks.

> +u16 regdomain_ieee2mhz(u16 chan, u8 band);

Same here.

> +void print_regdomain(struct ieee80211_regdomain *);

Ssame.

> +void print_iso3166_reg_map(void);

But why does this need to be exported?

> +int get_ieee80211_regname(u32, char *);

What are the arguments?

Hrm. I need to step back from the actual code.

johannes


Attachments:
signature.asc (190.00 B)
This is a digitally signed message part

2007-09-21 22:57:34

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 3/5] Wireless: add IEEE-802.11 regualtory domain module

On 9/21/07, Johannes Berg <[email protected]> wrote:
> On Fri, 2007-09-21 at 17:52 -0400, Luis R. Rodriguez wrote:
>
> > > Then we can use "enum ieee80211_band" below in the structs and get type
> > > checking. Generally, no new stuff has anything to do with
> > > include/net/ieee80211.h, that's just for the old "stack".
> >
> > Sure, I just wanted to point out the band def existed in another
> > header. My hopes is we can address all common header stuff once in for
> > all. I guess it'll have to wait a bit more.
>
> Oh ok. But I think we should start using sane values (these bits look
> awfully like you could OR them which is totally bogus) and convert the
> other stack over.

ACK -- we can define any value we want into this. Point taken though.

> > > > + * @name: name for this subband.
> > >
> > > Why does it need a name?
> >
> > Well to distinguish it.
>
> But why do we need to distinguish subbands by name? What do we use them
> for anyway?

We use it in:

u16 regdomain_ieee2mhz(u16 chan, u8 band)

freq_band_id() returns it

print_regdomain() uses it to distinguish the band the subband is in.

static int __alloc_band_channels(u32 regdomain_id,
struct ieee80211_regdomain *reg, u8 band,
u32 sb_chan_domain)

uses it internally to determine from what what regmap array it should
use to build channels from. That is, it either uses reg_2ghz_channels
or reg_5ghz_channels.

> > > > + * @min_freq: minimum frequency for this subband, in MHz. This represents the
> > > > + * center of frequency of a channel.
> > > > + * @max_freq: maximum frequency for this subband, in MHz. This represents the
> > > > + * center of frequency of a channel.
> > >
> > > How can both be center freq?
> >
> > min_freq is the center of frequency for the minimum channel on the
> > subband. max_freq is the center of frequency for the max channel on
> > the subband. I guess I should clear that up a little more huh.
>
> Uh ok, no, I just need to read better :)

:-P

> > > > +/**
> > > > + * struct ieee80211_regdomain - defines a regulatory domain
> > > > + *
> > > > + * @regdomain_id: ID of this regulatory domain. Some come from
> > > > + * http://standards.ieee.org/getieee802/download/802.11b-1999_Cor1-2001.pdf
> > > > + * @regdomain_name: name of this regulatory domain.
> > > > + * @list: node, part of band_restrictions_list
> > > > + *
> > > > + * This structure defines a regulatory domain, which consists of channel and
> > > > + * power restrictions. Some regulatory domains come from
> > > > + * 802.11b-1999_Cor1-2001, the rest are based on Reyk Floeter's ar5k. If
> > > > + * there is need to add more values here, please add one that is either
> > > > + * defined in a standard or that many hardware devices have adopted. Also
> > > > + * note that multiple countries can map to the same @regdomain_id
> > >
> > > There's no table here where you could add values, is there?.
> >
> > There is a lot of them.. but we can add few to show as an example.
>
> Then again. Why do we have this struct in a header file?

cfg80211 uses it. This is how we create a central regulatory domain.
cfg80211 creates its own struct based on this.

> > I should have explained that too. Well, if you may recall in my last
> > implementation of this I actually used a linked list. I then decided
> > we weren't going to add new 2.4GHz or 5GHz subbands unless a big
> > IEEE-802.11 change occurs. That doesn't happen so often to either use
> > linked list or a variable length array.
>
> Ok I just don't understand why you have this information in a struct.
> Shouldn't all of this information be essentially internal to the
> regulatory code, and people who use it simply query it and get back a
> pointer to the subband that applies to their query?

In order to build things and make things concretely. cfg80211 will
have a ieee80211_regdomain, but well this ieee80211_regdomain has some
structs we might as well define to make it easier to build from a map.

> I don't see why
> everybody needs to see this huge array.

Well you are welcome to provide an alternative solution. I first
started with a linked list, but then that seemed silly as this remains
constant.. so I think a static array of subbands is easier. Hmm, I
think I had even tried a variable length array too..

Luis

2007-09-21 20:50:08

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On Fri, 2007-09-21 at 16:46 -0400, Luis R. Rodriguez wrote:
> Patchset I - Add central regulatory domain agent
>
> This is patchset I of II which adds a central regulatory domain
> agent onto the wireless subsystem. I've split it into two patchsets in order
> to introduce the agent before affecting mac80211 drivers. This allows work
> to continue on the central reg agent independant of mac80211
> advancements.
>
> Patch series I adds the central regulatory domain agent and
> integrates it with cfg80211. The central reg agent consists of 2
> main modules:

My bad, my reading was too quick. I see cfg80211 above now :)

Dan

> * ISO3166-1
> * Regdomains
>
> Additionally, changing regulatory domains can be acomplished through
> the use of a new configfs module which will be introduced for
> the wireless subsystem.
>
> Patch series II will add support for the centreal reglatory agent
> onto mac80211, remove mac80211's simple regulatory control and and
> replace each driver's own regulatory domain implementation with the
> central one.
>
> Luis


2007-09-21 21:48:34

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On Fri, 2007-09-21 at 17:39 -0400, Dan Williams wrote:

> Also, if you could make sure this stuff is completely separate
> conceptually and architecturally from mac80211 itself, but have mac80211
> _rely_ on it, then we can rip the bits out of the fullmac drivers that
> do regdomain stuff and plug them into this framework too. I think
> that's a real win.

Yeah, I think that's the plan. In fact, I always consider mac80211 to be
on the the same level like fullmac _drivers_ and mac80211-based drivers
somewhere below that (at a level that with fullmac drivers doesn't
exist)

johannes


Attachments:
signature.asc (190.00 B)
This is a digitally signed message part

2007-09-21 20:49:23

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On Fri, 2007-09-21 at 16:46 -0400, Luis R. Rodriguez wrote:
> Patchset I - Add central regulatory domain agent
>
> This is patchset I of II which adds a central regulatory domain
> agent onto the wireless subsystem. I've split it into two patchsets in order
> to introduce the agent before affecting mac80211 drivers. This allows work
> to continue on the central reg agent independant of mac80211
> advancements.
>
> Patch series I adds the central regulatory domain agent and
> integrates it with cfg80211. The central reg agent consists of 2
> main modules:
>
> * ISO3166-1
> * Regdomains
>
> Additionally, changing regulatory domains can be acomplished through
> the use of a new configfs module which will be introduced for
> the wireless subsystem.

Can we _also_ make it accessible through cfg80211/nl80211 in some
fashion?

Dan

> Patch series II will add support for the centreal reglatory agent
> onto mac80211, remove mac80211's simple regulatory control and and
> replace each driver's own regulatory domain implementation with the
> central one.
>
> Luis


2007-09-21 22:00:47

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 0/5] Add central regulatory domain agent - Patchset I

On 9/21/07, Johannes Berg <[email protected]> wrote:
> On Fri, 2007-09-21 at 17:39 -0400, Dan Williams wrote:
>
> > Also, if you could make sure this stuff is completely separate
> > conceptually and architecturally from mac80211 itself, but have mac80211
> > _rely_ on it, then we can rip the bits out of the fullmac drivers that
> > do regdomain stuff and plug them into this framework too. I think
> > that's a real win.
>
> Yeah, I think that's the plan. In fact, I always consider mac80211 to be
> on the the same level like fullmac _drivers_ and mac80211-based drivers
> somewhere below that (at a level that with fullmac drivers doesn't
> exist)

Correct, the only way this touches mac80211 is ripping common wireless
stuff out from it and putting it into a wireless_common.h. other than
that all of this so far is 100% independent of mac80211.

In fact, you can apply each patch, one by one, and compile the kernel
and all modules and you should have no issues independently. However
each subsequent patch depends on the previous patch. The idea with
this was to try to get this regulatory work into the 'everything'
wireless-dev branch so we can address any small issues before we start
hacking away on mac80211 and its drivers.

At first I wanted to send all of the patches together but this was
just taking too long... My hope now was to speed the development
process up by separating the required work into two patches series.

Luis

2007-09-24 17:49:20

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On 9/24/07, Joerg Mayer <[email protected]> wrote:
> On Fri, Sep 21, 2007 at 05:33:42PM -0400, Luis R. Rodriguez wrote:
> > > > + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> > > > + *
> > > > + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> > > > + * is in charge of filling most of these fields out. The low-level driver
> > > > + * is expected to fill in, if needed, the val field. Note that val is already
> > > > + * set by the regulatory agent to the same channel as in chan.
> > >
> > > Shouldn't you also set chan and freq in the driver?
> [...]
> > Initially I wanted to move mac80211 to use a linked list of channels
> > instead of an array for each mode. As we discussed it over (you, me
> > and a few others) we determined it wasn't best to do this (I have a
> > patch that allows this just in case we later change our mind). But --
> > previous to doing this I had a wrapper on ieee80211_channel as I
> > wanted the central regdomain to have a linked list of reg domain
> > channels. If we don't want a wrapper we have to add this to the
> > ieee8021_channel struct. Otherwise I need to define my own channel
> > struct which wraps around ieee80211_channel.
> >
> > > > +struct ieee80211_channel {
> > > > + /* XXX change to u8 */
> > > > + short chan;
> > >
> > > Not sure, is a u8 always enough? I thought 802.11a had huge channel
> > > numbers?
> >
> > Not that huge :-) Highest I've heard is 220. u8 should suffice.
>
> What's the idea of working with channels? Channels are non-uniq numbers.
> Internally everything should work with center frequency and not with
> channels. If necessary, information should be converted from channels
> by the driver when reporting it into the stack. That way there also won't
> be any problems if there ever is a channel 417.

I agree. I'm OK with just having center of freq. Right now WE supports
channel or freqs and the value is passed directly to the driver (for
FullMAC) or mac80211 (for SoftMAC). For nl80211 we can just support
channel passing onto the kernel, if the user supplies a channel we'll
do the conversion to freq in userspace. On step at a time.

Luis

2007-09-21 21:07:40

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 5/5] Wireless: add wireless configfs module

This patch adds a wireless configfs module. Currently we only add
support for changing the central regulatory domain. The idea is not to
replace nl80211 interface but to supplement it and also to give home
for a place for configuring wireless kobjects. We can move add_interface /
remove_interface from sysfs to configfs, for example.

Example usage of using wireles configfs:

mkdir /config/

modprobe configfs_wireless
mount -t configfs none /config
echo US > /config/wireless/country
dmesg -c

You will see:

Userspace changed regulatory domain
ieee80211_regdomains: regulatory domain FCC1A created
Regulatory Domain: FCC1A Regulatory Domain ID: 0x10
IEEE 802.11g 2GHz ISM subband
max_ir_ptmp: 30 dBm max_ir_ptp: 30 dBm
max_eirp_ptmp: 36 dBm max_eirp_ptp: 255 dBm
max_antenna_gain: 6 dBi
Environment capability: Indoor & Outdoor
Channel Freq (MHz)
1 2412
2 2417
3 2422
4 2427
5 2432
6 2437
7 2442
8 2447
9 2452
10 2457
11 2462
---
net/wireless/Kconfig | 11 +++++++++++
net/wireless/Makefile | 1 +
2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 0505347..59e47ce 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -15,6 +15,17 @@ config NL80211

If unsure, say Y.

+config CONFIGFS_WIRELESS
+ depends CFG80211 && IEEE80211_REGDOMAINS
+ tristate "Configfs interface for configuring central wireless settings"
+ ---help---
+ You can configure central wireless settings through this subsystem.
+ It currently only has an ISO3166-1 alpha2 country regulatory domain
+ settings used to define frequency and power regulatory restrictions
+ for all wireless cards.
+
+ If unsure, you can safely say Y.
+
config IEEE80211_REGDOMAINS
tristate "Central IEEE 802.11 regulatory domain agent"
select ISO3166_1
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 74c1059..b3f5daa 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_WIRELESS_EXT) += wext.o
obj-$(CONFIG_CFG80211) += cfg80211.o
+obj-$(CONFIG_CONFIGFS_WIRELESS) += configfs_wireless.o

cfg80211-y += core.o sysfs.o radiotap.o
cfg80211-$(CONFIG_NL80211) += nl80211.o
--
1.5.2.4


Attachments:
(No filename) (2.47 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2007-09-21 21:16:27

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 1/5] Move standard wireless defintions out of mac80211

On Fri, 2007-09-21 at 17:00 -0400, Luis R. Rodriguez wrote:

Ok one thing up front: I'm looking at this basically as "new code", iow
something we should do right from the start. mac80211 stuff is a mess,
so imho we should clean it up at this point when we break things anyway.

> + * @IEEE80211_CHAN_W_SCAN: if this flag is set it informs the lower layer that
> + * this channel can be passively scanned for.

Are there really channels that don't have _SCAN?

> +/**
> + * ieee80211_channel - internal structure definiton for an IEEE-802.11 channel
> + *
> + * This defines an ieee80211_channel. The IEEE-802.11 regulatory domain agent
> + * is in charge of filling most of these fields out. The low-level driver
> + * is expected to fill in, if needed, the val field. Note that val is already
> + * set by the regulatory agent to the same channel as in chan.

Shouldn't you also set chan and freq in the driver?

> + * @modulation_cap: could be IEEE80211_RATE_*

Could be?

> + * @list: lets you make this structure part of a linked list

What do we need this for?

> +struct ieee80211_channel {
> + /* XXX change to u8 */
> + short chan;

Not sure, is a u8 always enough? I thought 802.11a had huge channel
numbers?

> +/* XXX consider removing the holes bellow */

I think these flags are shared with hostapd right now... :(

> +/**
> + * enum rate_flags - internal &ieee80211_rate flags

> + * Use these flags to indicate to the lower layers details about an
> + * &ieee80211_rate.
^ struct ieee80211_rate, for kernel-doc

> + * @IEEE80211_RATE_ERP: indicates if the rate is an Extended Rate PHY (ERP)
> + * @IEEE80211_RATE_BASIC: indicates the rate is a basic rate for the
> + * currently used mode
> + * @IEEE80211_RATE_PREAMBLE2: used to indicates that the rate for short
> + * preamble is to be used. This is set in &ieee80211_rate's @val2.

Couldn't we just call it SHORT_PREAMBLE? :)

> + * @IEEE80211_RATE_SUPPORTED: indicates if rate is supported by the given mode

What do we use this for?

> + * @IEEE80211_RATE_OFDM: indicates support for ODFM modulation
> + * @IEEE80211_RATE_CCK: indicates support for CCK modulation

I think this should be called "this rate is an OFDM/CCK rate"

> + * @IEEE80211_RATE_MANDATORY: indicates if this rate is mandatory for the
> + * currently used mode

I think this is wrong. Isn't the "mandatory" flag something for an AP to
ask it's stations for?

> +/* XXX move to inline and add documenation, kernel-doc can't doc
> defines */

Why don't you just do that then? :)

> + * Low-level driver should set PREAMBLE2, OFDM and CCK flags.
> + * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
> + * configuration.

Oh come on. There hasn't been 80211.o for a loong time :)

> + * @flags: IEEE80211_RATE_* flags
> + * @val2: hw specific value for the rate when using short preamble
> + * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
> + * 2, 5.5, and 11 Mbps)

Can't we just get rid of this field? Does anybody use it?

> + * @min_rssi_ack: Minimum required RSSI of packet to generate an ACK ??
> + * @min_rssi_ack_delta: ??

I thought we didn't use these fields.

> + /* the following fields are set by 80211.o and need not be filled by the

80211.o again :)

johannes


Attachments:
signature.asc (190.00 B)
This is a digitally signed message part