* [RFC] cfg80211: keep track of supported interface modes
@ 2008-08-07 15:21 Johannes Berg
2008-08-07 18:02 ` Luis R. Rodriguez
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Johannes Berg @ 2008-08-07 15:21 UTC (permalink / raw)
To: Dan Williams; +Cc: John Linville, linux-wireless
It is obviously good for userspace to know up front which interface modes
a given piece of hardware might support (even if adding such an interface
might fail later because of concurrency issues), so let's make cfg80211
aware of that. For good measure, disallow adding interfaces in all other
modes so drivers don't forget to announce support for one mode when they
add it.
This patch is incomplete as it doesn't modify all drivers. The driver
modifications should be straight-forward, I'm hoping somebody else
can pick it up and collect the necessary driver changes. Included is a
b43 change because I tested it with that. I have also pushed an iw
change to print out this information.
It's a bit ugly that it requires drivers to use nl80211 constants, but
if anything mac80211 should migrate to using those completely instead
of translating them to its own versions.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/b43/main.c | 17 ++++++++++++-----
include/linux/nl80211.h | 6 ++++++
include/net/wireless.h | 3 +++
net/mac80211/main.c | 7 +++++++
net/wireless/core.c | 9 ++++++++-
net/wireless/nl80211.c | 22 ++++++++++++++++++++--
6 files changed, 56 insertions(+), 8 deletions(-)
--- everything.orig/include/linux/nl80211.h 2008-08-07 16:26:44.000000000 +0200
+++ everything/include/linux/nl80211.h 2008-08-07 16:39:03.000000000 +0200
@@ -192,6 +192,10 @@ enum nl80211_commands {
* @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
* &enum nl80211_mntr_flags.
*
+ * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all
+ * supported interface types, each a flag attribute with the number
+ * of the interface mode.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -235,6 +239,8 @@ enum nl80211_attrs {
NL80211_ATTR_MPATH_NEXT_HOP,
NL80211_ATTR_MPATH_INFO,
+ NL80211_ATTR_SUPPORTED_IFTYPES,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
--- everything.orig/include/net/wireless.h 2008-08-07 16:26:33.000000000 +0200
+++ everything/include/net/wireless.h 2008-08-07 16:28:20.000000000 +0200
@@ -185,6 +185,9 @@ struct wiphy {
/* permanent MAC address */
u8 perm_addr[ETH_ALEN];
+ /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
+ u16 interface_modes;
+
/* If multiple wiphys are registered and you're handed e.g.
* a regular netdev with assigned ieee80211_ptr, you won't
* know whether it points to a wiphy your driver has registered
--- everything.orig/net/wireless/core.c 2008-08-07 16:32:27.000000000 +0200
+++ everything/net/wireless/core.c 2008-08-07 16:47:11.000000000 +0200
@@ -1,7 +1,7 @@
/*
* This is the linux wireless configuration interface.
*
- * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
*/
#include <linux/if.h>
@@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy)
struct ieee80211_supported_band *sband;
bool have_band = false;
int i;
+ u16 ifmodes = wiphy->interface_modes;
+
+ /* sanity check ifmodes */
+ WARN_ON(!ifmodes);
+ ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
+ if (WARN_ON(ifmodes != wiphy->interface_modes))
+ wiphy->interface_modes = ifmodes;
/* sanity check supported bands/channels */
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
--- everything.orig/net/wireless/nl80211.c 2008-08-07 16:35:22.000000000 +0200
+++ everything/net/wireless/nl80211.c 2008-08-07 16:42:24.000000000 +0200
@@ -106,10 +106,12 @@ static int nl80211_send_wiphy(struct sk_
struct nlattr *nl_bands, *nl_band;
struct nlattr *nl_freqs, *nl_freq;
struct nlattr *nl_rates, *nl_rate;
+ struct nlattr *nl_modes;
enum ieee80211_band band;
struct ieee80211_channel *chan;
struct ieee80211_rate *rate;
int i;
+ u16 ifmodes = dev->wiphy.interface_modes;
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
if (!hdr)
@@ -118,6 +120,20 @@ static int nl80211_send_wiphy(struct sk_
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
+ nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
+ if (!nl_modes)
+ goto nla_put_failure;
+
+ i = 0;
+ while (ifmodes) {
+ if (ifmodes & 1)
+ NLA_PUT_FLAG(msg, i);
+ ifmodes >>= 1;
+ i++;
+ }
+
+ nla_nest_end(msg, nl_modes);
+
nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
if (!nl_bands)
goto nla_put_failure;
@@ -408,7 +424,8 @@ static int nl80211_set_interface(struct
ifindex = dev->ifindex;
dev_put(dev);
- if (!drv->ops->change_virtual_intf) {
+ if (!drv->ops->change_virtual_intf ||
+ !(drv->wiphy.interface_modes & (1 << type))) {
err = -EOPNOTSUPP;
goto unlock;
}
@@ -455,7 +472,8 @@ static int nl80211_new_interface(struct
if (IS_ERR(drv))
return PTR_ERR(drv);
- if (!drv->ops->add_virtual_intf) {
+ if (!drv->ops->add_virtual_intf ||
+ !(drv->wiphy.interface_modes & (1 << type))) {
err = -EOPNOTSUPP;
goto unlock;
}
--- everything.orig/drivers/net/wireless/b43/main.c 2008-08-07 16:49:57.000000000 +0200
+++ everything/drivers/net/wireless/b43/main.c 2008-08-07 16:57:12.000000000 +0200
@@ -4165,11 +4165,11 @@ static int b43_op_add_interface(struct i
/* TODO: allow WDS/AP devices to coexist */
- if (conf->type != IEEE80211_IF_TYPE_AP &&
- conf->type != IEEE80211_IF_TYPE_MESH_POINT &&
- conf->type != IEEE80211_IF_TYPE_STA &&
- conf->type != IEEE80211_IF_TYPE_WDS &&
- conf->type != IEEE80211_IF_TYPE_IBSS)
+ if (WARN_ON(conf->type != IEEE80211_IF_TYPE_AP &&
+ conf->type != IEEE80211_IF_TYPE_MESH_POINT &&
+ conf->type != IEEE80211_IF_TYPE_STA &&
+ conf->type != IEEE80211_IF_TYPE_WDS &&
+ conf->type != IEEE80211_IF_TYPE_IBSS))
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
@@ -4649,6 +4649,13 @@ static int b43_wireless_init(struct ssb_
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
hw->queues = b43_modparam_qos ? 4 : 1;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
--- everything.orig/net/mac80211/main.c 2008-08-07 16:42:32.000000000 +0200
+++ everything/net/mac80211/main.c 2008-08-07 16:59:05.000000000 +0200
@@ -1263,6 +1263,13 @@ int ieee80211_register_hw(struct ieee802
}
}
+ /* if low-level driver supports AP, we also support VLAN */
+ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
+ local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
+
+ /* mac80211 always supports monitor */
+ local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+
result = wiphy_register(local->hw.wiphy);
if (result < 0)
return result;
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 15:21 [RFC] cfg80211: keep track of supported interface modes Johannes Berg @ 2008-08-07 18:02 ` Luis R. Rodriguez 2008-08-07 19:45 ` Johannes Berg 2008-08-07 18:13 ` Dan Williams 2008-08-15 20:16 ` Luis R. Rodriguez 2 siblings, 1 reply; 9+ messages in thread From: Luis R. Rodriguez @ 2008-08-07 18:02 UTC (permalink / raw) To: Johannes Berg; +Cc: Dan Williams, John Linville, linux-wireless On Thu, Aug 7, 2008 at 8:21 AM, Johannes Berg <johannes@sipsolutions.net> wrote: > It is obviously good for userspace to know up front which interface modes > a given piece of hardware might support (even if adding such an interface > might fail later because of concurrency issues), so let's make cfg80211 > aware of that. For good measure, disallow adding interfaces in all other > modes so drivers don't forget to announce support for one mode when they > add it. > > This patch is incomplete as it doesn't modify all drivers. The driver > modifications should be straight-forward, I'm hoping somebody else > can pick it up and collect the necessary driver changes. Included is a > b43 change because I tested it with that. I have also pushed an iw > change to print out this information. > > It's a bit ugly that it requires drivers to use nl80211 constants, but > if anything mac80211 should migrate to using those completely instead > of translating them to its own versions. This is nice :) > --- everything.orig/drivers/net/wireless/b43/main.c 2008-08-07 16:49:57.000000000 +0200 > +++ everything/drivers/net/wireless/b43/main.c 2008-08-07 16:57:12.000000000 +0200 > @@ -4165,11 +4165,11 @@ static int b43_op_add_interface(struct i > > /* TODO: allow WDS/AP devices to coexist */ > > - if (conf->type != IEEE80211_IF_TYPE_AP && > - conf->type != IEEE80211_IF_TYPE_MESH_POINT && > - conf->type != IEEE80211_IF_TYPE_STA && > - conf->type != IEEE80211_IF_TYPE_WDS && > - conf->type != IEEE80211_IF_TYPE_IBSS) > + if (WARN_ON(conf->type != IEEE80211_IF_TYPE_AP && When would we hit the WARN_ON() ? Luis ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 18:02 ` Luis R. Rodriguez @ 2008-08-07 19:45 ` Johannes Berg 0 siblings, 0 replies; 9+ messages in thread From: Johannes Berg @ 2008-08-07 19:45 UTC (permalink / raw) To: Luis R. Rodriguez; +Cc: Dan Williams, John Linville, linux-wireless [-- Attachment #1: Type: text/plain, Size: 793 bytes --] > > --- everything.orig/drivers/net/wireless/b43/main.c 2008-08-07 16:49:57.000000000 +0200 > > +++ everything/drivers/net/wireless/b43/main.c 2008-08-07 16:57:12.000000000 +0200 > > @@ -4165,11 +4165,11 @@ static int b43_op_add_interface(struct i > > > > /* TODO: allow WDS/AP devices to coexist */ > > > > - if (conf->type != IEEE80211_IF_TYPE_AP && > > - conf->type != IEEE80211_IF_TYPE_MESH_POINT && > > - conf->type != IEEE80211_IF_TYPE_STA && > > - conf->type != IEEE80211_IF_TYPE_WDS && > > - conf->type != IEEE80211_IF_TYPE_IBSS) > > + if (WARN_ON(conf->type != IEEE80211_IF_TYPE_AP && > > When would we hit the WARN_ON() ? When I make a mistake in mac80211 :) Might as well leave it out. johannes [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 15:21 [RFC] cfg80211: keep track of supported interface modes Johannes Berg 2008-08-07 18:02 ` Luis R. Rodriguez @ 2008-08-07 18:13 ` Dan Williams 2008-08-07 19:47 ` Johannes Berg 2008-08-15 20:16 ` Luis R. Rodriguez 2 siblings, 1 reply; 9+ messages in thread From: Dan Williams @ 2008-08-07 18:13 UTC (permalink / raw) To: Johannes Berg; +Cc: John Linville, linux-wireless On Thu, 2008-08-07 at 17:21 +0200, Johannes Berg wrote: > It is obviously good for userspace to know up front which interface modes > a given piece of hardware might support (even if adding such an interface > might fail later because of concurrency issues), so let's make cfg80211 > aware of that. For good measure, disallow adding interfaces in all other > modes so drivers don't forget to announce support for one mode when they > add it. This makes me happy. Thanks! Dan > This patch is incomplete as it doesn't modify all drivers. The driver > modifications should be straight-forward, I'm hoping somebody else > can pick it up and collect the necessary driver changes. Included is a > b43 change because I tested it with that. I have also pushed an iw > change to print out this information. > > It's a bit ugly that it requires drivers to use nl80211 constants, but > if anything mac80211 should migrate to using those completely instead > of translating them to its own versions. > > Signed-off-by: Johannes Berg <johannes@sipsolutions.net> > --- > drivers/net/wireless/b43/main.c | 17 ++++++++++++----- > include/linux/nl80211.h | 6 ++++++ > include/net/wireless.h | 3 +++ > net/mac80211/main.c | 7 +++++++ > net/wireless/core.c | 9 ++++++++- > net/wireless/nl80211.c | 22 ++++++++++++++++++++-- > 6 files changed, 56 insertions(+), 8 deletions(-) > > --- everything.orig/include/linux/nl80211.h 2008-08-07 16:26:44.000000000 +0200 > +++ everything/include/linux/nl80211.h 2008-08-07 16:39:03.000000000 +0200 > @@ -192,6 +192,10 @@ enum nl80211_commands { > * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of > * &enum nl80211_mntr_flags. > * > + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all > + * supported interface types, each a flag attribute with the number > + * of the interface mode. > + * > * @NL80211_ATTR_MAX: highest attribute number currently defined > * @__NL80211_ATTR_AFTER_LAST: internal use > */ > @@ -235,6 +239,8 @@ enum nl80211_attrs { > NL80211_ATTR_MPATH_NEXT_HOP, > NL80211_ATTR_MPATH_INFO, > > + NL80211_ATTR_SUPPORTED_IFTYPES, > + > /* add attributes here, update the policy in nl80211.c */ > > __NL80211_ATTR_AFTER_LAST, > --- everything.orig/include/net/wireless.h 2008-08-07 16:26:33.000000000 +0200 > +++ everything/include/net/wireless.h 2008-08-07 16:28:20.000000000 +0200 > @@ -185,6 +185,9 @@ struct wiphy { > /* permanent MAC address */ > u8 perm_addr[ETH_ALEN]; > > + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ > + u16 interface_modes; > + > /* If multiple wiphys are registered and you're handed e.g. > * a regular netdev with assigned ieee80211_ptr, you won't > * know whether it points to a wiphy your driver has registered > --- everything.orig/net/wireless/core.c 2008-08-07 16:32:27.000000000 +0200 > +++ everything/net/wireless/core.c 2008-08-07 16:47:11.000000000 +0200 > @@ -1,7 +1,7 @@ > /* > * This is the linux wireless configuration interface. > * > - * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> > + * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> > */ > > #include <linux/if.h> > @@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy) > struct ieee80211_supported_band *sband; > bool have_band = false; > int i; > + u16 ifmodes = wiphy->interface_modes; > + > + /* sanity check ifmodes */ > + WARN_ON(!ifmodes); > + ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; > + if (WARN_ON(ifmodes != wiphy->interface_modes)) > + wiphy->interface_modes = ifmodes; > > /* sanity check supported bands/channels */ > for (band = 0; band < IEEE80211_NUM_BANDS; band++) { > --- everything.orig/net/wireless/nl80211.c 2008-08-07 16:35:22.000000000 +0200 > +++ everything/net/wireless/nl80211.c 2008-08-07 16:42:24.000000000 +0200 > @@ -106,10 +106,12 @@ static int nl80211_send_wiphy(struct sk_ > struct nlattr *nl_bands, *nl_band; > struct nlattr *nl_freqs, *nl_freq; > struct nlattr *nl_rates, *nl_rate; > + struct nlattr *nl_modes; > enum ieee80211_band band; > struct ieee80211_channel *chan; > struct ieee80211_rate *rate; > int i; > + u16 ifmodes = dev->wiphy.interface_modes; > > hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); > if (!hdr) > @@ -118,6 +120,20 @@ static int nl80211_send_wiphy(struct sk_ > NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); > NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); > > + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); > + if (!nl_modes) > + goto nla_put_failure; > + > + i = 0; > + while (ifmodes) { > + if (ifmodes & 1) > + NLA_PUT_FLAG(msg, i); > + ifmodes >>= 1; > + i++; > + } > + > + nla_nest_end(msg, nl_modes); > + > nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); > if (!nl_bands) > goto nla_put_failure; > @@ -408,7 +424,8 @@ static int nl80211_set_interface(struct > ifindex = dev->ifindex; > dev_put(dev); > > - if (!drv->ops->change_virtual_intf) { > + if (!drv->ops->change_virtual_intf || > + !(drv->wiphy.interface_modes & (1 << type))) { > err = -EOPNOTSUPP; > goto unlock; > } > @@ -455,7 +472,8 @@ static int nl80211_new_interface(struct > if (IS_ERR(drv)) > return PTR_ERR(drv); > > - if (!drv->ops->add_virtual_intf) { > + if (!drv->ops->add_virtual_intf || > + !(drv->wiphy.interface_modes & (1 << type))) { > err = -EOPNOTSUPP; > goto unlock; > } > --- everything.orig/drivers/net/wireless/b43/main.c 2008-08-07 16:49:57.000000000 +0200 > +++ everything/drivers/net/wireless/b43/main.c 2008-08-07 16:57:12.000000000 +0200 > @@ -4165,11 +4165,11 @@ static int b43_op_add_interface(struct i > > /* TODO: allow WDS/AP devices to coexist */ > > - if (conf->type != IEEE80211_IF_TYPE_AP && > - conf->type != IEEE80211_IF_TYPE_MESH_POINT && > - conf->type != IEEE80211_IF_TYPE_STA && > - conf->type != IEEE80211_IF_TYPE_WDS && > - conf->type != IEEE80211_IF_TYPE_IBSS) > + if (WARN_ON(conf->type != IEEE80211_IF_TYPE_AP && > + conf->type != IEEE80211_IF_TYPE_MESH_POINT && > + conf->type != IEEE80211_IF_TYPE_STA && > + conf->type != IEEE80211_IF_TYPE_WDS && > + conf->type != IEEE80211_IF_TYPE_IBSS)) > return -EOPNOTSUPP; > > mutex_lock(&wl->mutex); > @@ -4649,6 +4649,13 @@ static int b43_wireless_init(struct ssb_ > IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_MESH_POINT) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_WDS) | > + BIT(NL80211_IFTYPE_ADHOC); > + > hw->queues = b43_modparam_qos ? 4 : 1; > SET_IEEE80211_DEV(hw, dev->dev); > if (is_valid_ether_addr(sprom->et1mac)) > --- everything.orig/net/mac80211/main.c 2008-08-07 16:42:32.000000000 +0200 > +++ everything/net/mac80211/main.c 2008-08-07 16:59:05.000000000 +0200 > @@ -1263,6 +1263,13 @@ int ieee80211_register_hw(struct ieee802 > } > } > > + /* if low-level driver supports AP, we also support VLAN */ > + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) > + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); > + > + /* mac80211 always supports monitor */ > + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); > + > result = wiphy_register(local->hw.wiphy); > if (result < 0) > return result; > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 18:13 ` Dan Williams @ 2008-08-07 19:47 ` Johannes Berg 2008-08-07 19:55 ` Dan Williams 0 siblings, 1 reply; 9+ messages in thread From: Johannes Berg @ 2008-08-07 19:47 UTC (permalink / raw) To: Dan Williams; +Cc: John Linville, linux-wireless [-- Attachment #1: Type: text/plain, Size: 899 bytes --] On Thu, 2008-08-07 at 14:13 -0400, Dan Williams wrote: > On Thu, 2008-08-07 at 17:21 +0200, Johannes Berg wrote: > > It is obviously good for userspace to know up front which interface modes > > a given piece of hardware might support (even if adding such an interface > > might fail later because of concurrency issues), so let's make cfg80211 > > aware of that. For good measure, disallow adding interfaces in all other > > modes so drivers don't forget to announce support for one mode when they > > add it. > > This makes me happy. We discussed this in Ottawa, didn't we? It just slipped my mind and I remembered earlier today. No somebody just needs to go through and add the corresponding hunks for all drivers. *hint* :) (it mostly consists in seeing what the add_interface callback will accept, which is correct for all drivers but iwlwifi as far as I know) johannes [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 19:47 ` Johannes Berg @ 2008-08-07 19:55 ` Dan Williams 0 siblings, 0 replies; 9+ messages in thread From: Dan Williams @ 2008-08-07 19:55 UTC (permalink / raw) To: Johannes Berg; +Cc: John Linville, linux-wireless On Thu, 2008-08-07 at 21:47 +0200, Johannes Berg wrote: > On Thu, 2008-08-07 at 14:13 -0400, Dan Williams wrote: > > On Thu, 2008-08-07 at 17:21 +0200, Johannes Berg wrote: > > > It is obviously good for userspace to know up front which interface modes > > > a given piece of hardware might support (even if adding such an interface > > > might fail later because of concurrency issues), so let's make cfg80211 > > > aware of that. For good measure, disallow adding interfaces in all other > > > modes so drivers don't forget to announce support for one mode when they > > > add it. > > > > This makes me happy. > > We discussed this in Ottawa, didn't we? It just slipped my mind and I > remembered earlier today. Yep, we did. Dan > No somebody just needs to go through and add the corresponding hunks for > all drivers. *hint* :) (it mostly consists in seeing what the > add_interface callback will accept, which is correct for all drivers but > iwlwifi as far as I know) > > johannes ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-07 15:21 [RFC] cfg80211: keep track of supported interface modes Johannes Berg 2008-08-07 18:02 ` Luis R. Rodriguez 2008-08-07 18:13 ` Dan Williams @ 2008-08-15 20:16 ` Luis R. Rodriguez 2008-08-15 20:19 ` Luis R. Rodriguez 2008-08-15 23:16 ` Ivo van Doorn 2 siblings, 2 replies; 9+ messages in thread From: Luis R. Rodriguez @ 2008-08-15 20:16 UTC (permalink / raw) To: Johannes Berg; +Cc: Dan Williams, John Linville, linux-wireless, Ivo van Doorn It is obviously good for userspace to know up front which interface modes a given piece of hardware might support (even if adding such an interface might fail later because of concurrency issues), so let's make cfg80211 aware of that. For good measure, disallow adding interfaces in all other modes so drivers don't forget to announce support for one mode when they add it. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- I needed to move on with iw so I figure I'd finish this off. I am not sure if where I put the stuff in rt2x00 is right. Review is appreciated. drivers/net/wireless/adm8211.c | 1 + drivers/net/wireless/at76_usb.c | 2 ++ drivers/net/wireless/ath5k/base.c | 5 +++++ drivers/net/wireless/ath9k/main.c | 5 +++++ drivers/net/wireless/b43/main.c | 7 +++++++ drivers/net/wireless/b43legacy/main.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +++++ drivers/net/wireless/mac80211_hwsim.c | 3 +++ drivers/net/wireless/p54/p54common.c | 3 +++ drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +++++ drivers/net/wireless/rtl8187_dev.c | 2 ++ drivers/net/wireless/zd1211rw/zd_mac.c | 5 +++++ include/linux/nl80211.h | 6 ++++++ include/net/wireless.h | 3 +++ net/mac80211/main.c | 7 +++++++ net/wireless/core.c | 9 ++++++++- net/wireless/nl80211.c | 22 ++++++++++++++++++++-- 18 files changed, 96 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 3333d45..c6a55cd 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1884,6 +1884,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->channel_change_time = 1000; dev->max_signal = 100; /* FIXME: find better value */ diff --git a/drivers/net/wireless/at76_usb.c b/drivers/net/wireless/at76_usb.c index 29ebdd2..7533fb2 100644 --- a/drivers/net/wireless/at76_usb.c +++ b/drivers/net/wireless/at76_usb.c @@ -2547,6 +2547,8 @@ static int at76_init_new_device(struct at76_priv *priv, priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; + priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + SET_IEEE80211_DEV(priv->hw, &interface->dev); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index b362c48..21b353d 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -486,6 +486,11 @@ ath5k_pci_probe(struct pci_dev *pdev, hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + hw->extra_tx_headroom = 2; hw->channel_change_time = 5000; sc = hw->priv; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 2888778..1985fa9 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1343,6 +1343,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3bf3a86..bb33586 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4649,6 +4649,13 @@ static int b43_wireless_init(struct ssb_device *dev) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + hw->queues = b43_modparam_qos ? 4 : 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 2541c81..b5a5882 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3705,6 +3705,11 @@ static int b43legacy_wireless_init(struct ssb_device *dev) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f3dd622..92cbe03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -820,6 +820,10 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; /* queues to support 11n aggregation */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7095d8c..4725ead 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7889,6 +7889,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 248d31a..6791500 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -447,6 +447,9 @@ static int __init init_mac80211_hwsim(void) hw->channel_change_time = 1; hw->queues = 1; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 83cd85e..42302e4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1010,6 +1010,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; + + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + dev->channel_change_time = 1000; /* TODO: find actual value */ dev->max_signal = 127; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f42283a..56330ff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -868,6 +868,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; } + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + return 0; exit_free_channels: diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 9e2f391..13e50d2 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -1183,6 +1183,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->max_signal = 65; } + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) printk(KERN_INFO "rtl8187: inconsistency between id with OEM" " info!\n"); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 63ee066..3005dd1 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -969,6 +969,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DB; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + hw->max_signal = 100; hw->queues = 1; hw->extra_tx_headroom = sizeof(struct zd_ctrlset); diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 825fcc6..6bd1971 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -214,6 +214,10 @@ enum nl80211_commands { * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory * rules. * + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + * supported interface types, each a flag attribute with the number + * of the interface mode. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -260,6 +264,8 @@ enum nl80211_attrs { NL80211_ATTR_REG_ALPHA2, NL80211_ATTR_REG_RULES, + NL80211_ATTR_SUPPORTED_IFTYPES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/wireless.h b/include/net/wireless.h index 24afa80..f6b31d0 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -188,6 +188,9 @@ struct wiphy { /* permanent MAC address */ u8 perm_addr[ETH_ALEN]; + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ + u16 interface_modes; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191..3fed07c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1639,6 +1639,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } } + /* if low-level driver supports AP, we also support VLAN */ + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + + /* mac80211 always supports monitor */ + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); + result = wiphy_register(local->hw.wiphy); if (result < 0) return result; diff --git a/net/wireless/core.c b/net/wireless/core.c index 0013307..b24e459 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1,7 +1,7 @@ /* * This is the linux wireless configuration interface. * - * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> + * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> */ #include <linux/if.h> @@ -285,6 +285,13 @@ int wiphy_register(struct wiphy *wiphy) struct ieee80211_supported_band *sband; bool have_band = false; int i; + u16 ifmodes = wiphy->interface_modes; + + /* sanity check ifmodes */ + WARN_ON(!ifmodes); + ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; + if (WARN_ON(ifmodes != wiphy->interface_modes)) + wiphy->interface_modes = ifmodes; /* sanity check supported bands/channels */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0d29364..c592f35 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -110,10 +110,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct nlattr *nl_bands, *nl_band; struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_rates, *nl_rate; + struct nlattr *nl_modes; enum ieee80211_band band; struct ieee80211_channel *chan; struct ieee80211_rate *rate; int i; + u16 ifmodes = dev->wiphy.interface_modes; hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); if (!hdr) @@ -122,6 +124,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); + if (!nl_modes) + goto nla_put_failure; + + i = 0; + while (ifmodes) { + if (ifmodes & 1) + NLA_PUT_FLAG(msg, i); + ifmodes >>= 1; + i++; + } + + nla_nest_end(msg, nl_modes); + nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); if (!nl_bands) goto nla_put_failure; @@ -412,7 +428,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ifindex = dev->ifindex; dev_put(dev); - if (!drv->ops->change_virtual_intf) { + if (!drv->ops->change_virtual_intf || + !(drv->wiphy.interface_modes & (1 << type))) { err = -EOPNOTSUPP; goto unlock; } @@ -459,7 +476,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(drv)) return PTR_ERR(drv); - if (!drv->ops->add_virtual_intf) { + if (!drv->ops->add_virtual_intf || + !(drv->wiphy.interface_modes & (1 << type))) { err = -EOPNOTSUPP; goto unlock; } -- 1.5.6.rc2.15.g457bb.dirty ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-15 20:16 ` Luis R. Rodriguez @ 2008-08-15 20:19 ` Luis R. Rodriguez 2008-08-15 23:16 ` Ivo van Doorn 1 sibling, 0 replies; 9+ messages in thread From: Luis R. Rodriguez @ 2008-08-15 20:19 UTC (permalink / raw) To: Johannes Berg; +Cc: Dan Williams, John Linville, linux-wireless, Ivo van Doorn On Fri, Aug 15, 2008 at 1:16 PM, Luis R. Rodriguez <lrodriguez@atheros.com> wrote: > I needed to move on with iw so I figure I'd finish this off. > I am not sure if where I put the stuff in rt2x00 is right. Review is > appreciated. I also forgot to mention this applies on top of my new reg patches. Luis ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC] cfg80211: keep track of supported interface modes 2008-08-15 20:16 ` Luis R. Rodriguez 2008-08-15 20:19 ` Luis R. Rodriguez @ 2008-08-15 23:16 ` Ivo van Doorn 1 sibling, 0 replies; 9+ messages in thread From: Ivo van Doorn @ 2008-08-15 23:16 UTC (permalink / raw) To: Luis R. Rodriguez Cc: Johannes Berg, Dan Williams, John Linville, linux-wireless On Friday 15 August 2008, Luis R. Rodriguez wrote: > It is obviously good for userspace to know up front which > interface modes a given piece of hardware might support (even > if adding such an interface might fail later because of > concurrency issues), so let's make cfg80211 aware of that. > For good measure, disallow adding interfaces in all other > modes so drivers don't forget to announce support for one mode > when they add it. > > Signed-off-by: Johannes Berg <johannes@sipsolutions.net> > Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> > --- > > I needed to move on with iw so I figure I'd finish this off. > I am not sure if where I put the stuff in rt2x00 is right. Review is > appreciated. > > drivers/net/wireless/adm8211.c | 1 + > drivers/net/wireless/at76_usb.c | 2 ++ > drivers/net/wireless/ath5k/base.c | 5 +++++ > drivers/net/wireless/ath9k/main.c | 5 +++++ > drivers/net/wireless/b43/main.c | 7 +++++++ > drivers/net/wireless/b43legacy/main.c | 5 +++++ > drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ > drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +++++ > drivers/net/wireless/mac80211_hwsim.c | 3 +++ > drivers/net/wireless/p54/p54common.c | 3 +++ > drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +++++ I've acked and forwarded to linux-wireless a similar patch for rt2x00 from [PATCH 5/5] rt2x00: Need to set wiphy->interface_modes Stephen Blackheath earlier today. Ivo > drivers/net/wireless/rtl8187_dev.c | 2 ++ > drivers/net/wireless/zd1211rw/zd_mac.c | 5 +++++ > include/linux/nl80211.h | 6 ++++++ > include/net/wireless.h | 3 +++ > net/mac80211/main.c | 7 +++++++ > net/wireless/core.c | 9 ++++++++- > net/wireless/nl80211.c | 22 ++++++++++++++++++++-- > 18 files changed, 96 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c > index 3333d45..c6a55cd 100644 > --- a/drivers/net/wireless/adm8211.c > +++ b/drivers/net/wireless/adm8211.c > @@ -1884,6 +1884,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, > dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); > /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ > dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; > + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); > > dev->channel_change_time = 1000; > dev->max_signal = 100; /* FIXME: find better value */ > diff --git a/drivers/net/wireless/at76_usb.c b/drivers/net/wireless/at76_usb.c > index 29ebdd2..7533fb2 100644 > --- a/drivers/net/wireless/at76_usb.c > +++ b/drivers/net/wireless/at76_usb.c > @@ -2547,6 +2547,8 @@ static int at76_init_new_device(struct at76_priv *priv, > priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | > IEEE80211_HW_SIGNAL_UNSPEC; > > + priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); > + > SET_IEEE80211_DEV(priv->hw, &interface->dev); > SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); > > diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c > index b362c48..21b353d 100644 > --- a/drivers/net/wireless/ath5k/base.c > +++ b/drivers/net/wireless/ath5k/base.c > @@ -486,6 +486,11 @@ ath5k_pci_probe(struct pci_dev *pdev, > hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | > IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > + > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > + > hw->extra_tx_headroom = 2; > hw->channel_change_time = 5000; > sc = hw->priv; > diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c > index 2888778..1985fa9 100644 > --- a/drivers/net/wireless/ath9k/main.c > +++ b/drivers/net/wireless/ath9k/main.c > @@ -1343,6 +1343,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) > hw->flags = IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > + > SET_IEEE80211_DEV(hw, &pdev->dev); > pci_set_drvdata(pdev, hw); > > diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c > index 3bf3a86..bb33586 100644 > --- a/drivers/net/wireless/b43/main.c > +++ b/drivers/net/wireless/b43/main.c > @@ -4649,6 +4649,13 @@ static int b43_wireless_init(struct ssb_device *dev) > IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_MESH_POINT) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_WDS) | > + BIT(NL80211_IFTYPE_ADHOC); > + > hw->queues = b43_modparam_qos ? 4 : 1; > SET_IEEE80211_DEV(hw, dev->dev); > if (is_valid_ether_addr(sprom->et1mac)) > diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c > index 2541c81..b5a5882 100644 > --- a/drivers/net/wireless/b43legacy/main.c > +++ b/drivers/net/wireless/b43legacy/main.c > @@ -3705,6 +3705,11 @@ static int b43legacy_wireless_init(struct ssb_device *dev) > hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | > IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_WDS) | > + BIT(NL80211_IFTYPE_ADHOC); > hw->queues = 1; /* FIXME: hardware has more queues */ > SET_IEEE80211_DEV(hw, dev->dev); > if (is_valid_ether_addr(sprom->et1mac)) > diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c > index f3dd622..92cbe03 100644 > --- a/drivers/net/wireless/iwlwifi/iwl-core.c > +++ b/drivers/net/wireless/iwlwifi/iwl-core.c > @@ -820,6 +820,10 @@ int iwl_setup_mac(struct iwl_priv *priv) > /* Tell mac80211 our characteristics */ > hw->flags = IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > /* Default value; 4 EDCA QOS priorities */ > hw->queues = 4; > /* queues to support 11n aggregation */ > diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c > index 7095d8c..4725ead 100644 > --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c > +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c > @@ -7889,6 +7889,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e > hw->flags = IEEE80211_HW_SIGNAL_DBM | > IEEE80211_HW_NOISE_DBM; > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > + > /* 4 EDCA QOS priorities */ > hw->queues = 4; > > diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c > index 248d31a..6791500 100644 > --- a/drivers/net/wireless/mac80211_hwsim.c > +++ b/drivers/net/wireless/mac80211_hwsim.c > @@ -447,6 +447,9 @@ static int __init init_mac80211_hwsim(void) > > hw->channel_change_time = 1; > hw->queues = 1; > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_AP); > > memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); > memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); > diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c > index 83cd85e..42302e4 100644 > --- a/drivers/net/wireless/p54/p54common.c > +++ b/drivers/net/wireless/p54/p54common.c > @@ -1010,6 +1010,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) > dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ > IEEE80211_HW_RX_INCLUDES_FCS | > IEEE80211_HW_SIGNAL_UNSPEC; > + > + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); > + > dev->channel_change_time = 1000; /* TODO: find actual value */ > dev->max_signal = 127; > > diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c > index f42283a..56330ff 100644 > --- a/drivers/net/wireless/rt2x00/rt2x00dev.c > +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c > @@ -868,6 +868,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, > &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; > } > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_AP) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > + > return 0; > > exit_free_channels: > diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c > index 9e2f391..13e50d2 100644 > --- a/drivers/net/wireless/rtl8187_dev.c > +++ b/drivers/net/wireless/rtl8187_dev.c > @@ -1183,6 +1183,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, > dev->max_signal = 65; > } > > + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); > + > if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) > printk(KERN_INFO "rtl8187: inconsistency between id with OEM" > " info!\n"); > diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c > index 63ee066..3005dd1 100644 > --- a/drivers/net/wireless/zd1211rw/zd_mac.c > +++ b/drivers/net/wireless/zd1211rw/zd_mac.c > @@ -969,6 +969,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) > hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | > IEEE80211_HW_SIGNAL_DB; > > + hw->wiphy->interface_modes = > + BIT(NL80211_IFTYPE_MESH_POINT) | > + BIT(NL80211_IFTYPE_STATION) | > + BIT(NL80211_IFTYPE_ADHOC); > + > hw->max_signal = 100; > hw->queues = 1; > hw->extra_tx_headroom = sizeof(struct zd_ctrlset); > diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h > index 825fcc6..6bd1971 100644 > --- a/include/linux/nl80211.h > +++ b/include/linux/nl80211.h > @@ -214,6 +214,10 @@ enum nl80211_commands { > * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory > * rules. > * > + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all > + * supported interface types, each a flag attribute with the number > + * of the interface mode. > + * > * @NL80211_ATTR_MAX: highest attribute number currently defined > * @__NL80211_ATTR_AFTER_LAST: internal use > */ > @@ -260,6 +264,8 @@ enum nl80211_attrs { > NL80211_ATTR_REG_ALPHA2, > NL80211_ATTR_REG_RULES, > > + NL80211_ATTR_SUPPORTED_IFTYPES, > + > /* add attributes here, update the policy in nl80211.c */ > > __NL80211_ATTR_AFTER_LAST, > diff --git a/include/net/wireless.h b/include/net/wireless.h > index 24afa80..f6b31d0 100644 > --- a/include/net/wireless.h > +++ b/include/net/wireless.h > @@ -188,6 +188,9 @@ struct wiphy { > /* permanent MAC address */ > u8 perm_addr[ETH_ALEN]; > > + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ > + u16 interface_modes; > + > /* If multiple wiphys are registered and you're handed e.g. > * a regular netdev with assigned ieee80211_ptr, you won't > * know whether it points to a wiphy your driver has registered > diff --git a/net/mac80211/main.c b/net/mac80211/main.c > index aa5a191..3fed07c 100644 > --- a/net/mac80211/main.c > +++ b/net/mac80211/main.c > @@ -1639,6 +1639,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) > } > } > > + /* if low-level driver supports AP, we also support VLAN */ > + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) > + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); > + > + /* mac80211 always supports monitor */ > + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); > + > result = wiphy_register(local->hw.wiphy); > if (result < 0) > return result; > diff --git a/net/wireless/core.c b/net/wireless/core.c > index 0013307..b24e459 100644 > --- a/net/wireless/core.c > +++ b/net/wireless/core.c > @@ -1,7 +1,7 @@ > /* > * This is the linux wireless configuration interface. > * > - * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> > + * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> > */ > > #include <linux/if.h> > @@ -285,6 +285,13 @@ int wiphy_register(struct wiphy *wiphy) > struct ieee80211_supported_band *sband; > bool have_band = false; > int i; > + u16 ifmodes = wiphy->interface_modes; > + > + /* sanity check ifmodes */ > + WARN_ON(!ifmodes); > + ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; > + if (WARN_ON(ifmodes != wiphy->interface_modes)) > + wiphy->interface_modes = ifmodes; > > /* sanity check supported bands/channels */ > for (band = 0; band < IEEE80211_NUM_BANDS; band++) { > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c > index 0d29364..c592f35 100644 > --- a/net/wireless/nl80211.c > +++ b/net/wireless/nl80211.c > @@ -110,10 +110,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, > struct nlattr *nl_bands, *nl_band; > struct nlattr *nl_freqs, *nl_freq; > struct nlattr *nl_rates, *nl_rate; > + struct nlattr *nl_modes; > enum ieee80211_band band; > struct ieee80211_channel *chan; > struct ieee80211_rate *rate; > int i; > + u16 ifmodes = dev->wiphy.interface_modes; > > hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); > if (!hdr) > @@ -122,6 +124,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, > NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); > NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); > > + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); > + if (!nl_modes) > + goto nla_put_failure; > + > + i = 0; > + while (ifmodes) { > + if (ifmodes & 1) > + NLA_PUT_FLAG(msg, i); > + ifmodes >>= 1; > + i++; > + } > + > + nla_nest_end(msg, nl_modes); > + > nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); > if (!nl_bands) > goto nla_put_failure; > @@ -412,7 +428,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) > ifindex = dev->ifindex; > dev_put(dev); > > - if (!drv->ops->change_virtual_intf) { > + if (!drv->ops->change_virtual_intf || > + !(drv->wiphy.interface_modes & (1 << type))) { > err = -EOPNOTSUPP; > goto unlock; > } > @@ -459,7 +476,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) > if (IS_ERR(drv)) > return PTR_ERR(drv); > > - if (!drv->ops->add_virtual_intf) { > + if (!drv->ops->add_virtual_intf || > + !(drv->wiphy.interface_modes & (1 << type))) { > err = -EOPNOTSUPP; > goto unlock; > } ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-08-15 23:16 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-08-07 15:21 [RFC] cfg80211: keep track of supported interface modes Johannes Berg 2008-08-07 18:02 ` Luis R. Rodriguez 2008-08-07 19:45 ` Johannes Berg 2008-08-07 18:13 ` Dan Williams 2008-08-07 19:47 ` Johannes Berg 2008-08-07 19:55 ` Dan Williams 2008-08-15 20:16 ` Luis R. Rodriguez 2008-08-15 20:19 ` Luis R. Rodriguez 2008-08-15 23:16 ` Ivo van Doorn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).