aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2008-09-13 22:12:57 +0200
committerLuis R. Rodriguez <lrodriguez@atheros.com>2008-09-15 09:44:47 -0700
commit56f9673db912e7509b9b1331f0f692578b542f6b (patch)
treebc3d615bd9bf6cf901be0c64c84fb901a5f17e7f
parentff88abe209b342f1704f24eff1fd4d0b1a9663e3 (diff)
downloadcompat-wireless-2.6-old-56f9673db912e7509b9b1331f0f692578b542f6b.tar.gz
Backport: cfg80211: keep track of supported interface modes
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
-rw-r--r--drivers/net/wireless/adm8211.c1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c3
-rw-r--r--drivers/net/wireless/p54/p54common.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c5
-rw-r--r--include/linux/nl80211.h6
-rw-r--r--include/net/wireless.h3
-rw-r--r--net/mac80211/main.c7
-rw-r--r--net/wireless/core.c9
-rw-r--r--net/wireless/nl80211.c22
10 files changed, 61 insertions, 3 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 9d1770b..4a0b050 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1963,6 +1963,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/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index da80d88..6087257 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -448,6 +448,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 0ab83a8..e4db844 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -991,6 +991,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 56dbc23..5857189 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1048,6 +1048,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
+ rt2x00dev->hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
/*
* Let the driver probe the device to detect the capabilities.
*/
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 175d247..be81d09 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -938,6 +938,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
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 2be7c63..2bd5f1a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -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,
diff --git a/include/net/wireless.h b/include/net/wireless.h
index 9324f8d..1dc8ec3 100644
--- a/include/net/wireless.h
+++ b/include/net/wireless.h
@@ -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
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index fe3b128..261718a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1660,6 +1660,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 617673d..0ba5a4f 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>
@@ -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++) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cfe4130..772f8aa 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -106,10 +106,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)
@@ -118,6 +120,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;
@@ -398,7 +414,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;
}
@@ -445,7 +462,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;
}