aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2008-08-29 19:26:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-05 16:17:42 -0400
commitf59ac0481660e66cec67f1d6b024e78b9dc715fe (patch)
treee9c69b04ac5863b1429bca5a9df1d75026703cde
parentc6e387a214f4b2c4bd48020409e366c133385d98 (diff)
cfg80211: keep track of supported interface modes
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: Stephen Blackheath <tramp.enshrine.stephen@blacksapphire.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/adm8211.c1
-rw-r--r--drivers/net/wireless/ath5k/base.c6
-rw-r--r--drivers/net/wireless/ath9k/main.c5
-rw-r--r--drivers/net/wireless/b43/main.c7
-rw-r--r--drivers/net/wireless/b43legacy/main.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c5
-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/rtl8187_dev.c2
-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
17 files changed, 95 insertions, 3 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 3333d4596b8d..c6a55cd12db9 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,
1884 dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); 1884 dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
1885 /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ 1885 /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
1886 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; 1886 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
1887 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1887 1888
1888 dev->channel_change_time = 1000; 1889 dev->channel_change_time = 1000;
1889 dev->max_signal = 100; /* FIXME: find better value */ 1890 dev->max_signal = 100; /* FIXME: find better value */
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 7989ab5c2bba..85260c39aa2b 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -485,6 +485,12 @@ ath5k_pci_probe(struct pci_dev *pdev,
485 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 485 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
486 IEEE80211_HW_SIGNAL_DBM | 486 IEEE80211_HW_SIGNAL_DBM |
487 IEEE80211_HW_NOISE_DBM; 487 IEEE80211_HW_NOISE_DBM;
488
489 hw->wiphy->interface_modes =
490 BIT(NL80211_IFTYPE_STATION) |
491 BIT(NL80211_IFTYPE_ADHOC) |
492 BIT(NL80211_IFTYPE_MESH_POINT);
493
488 hw->extra_tx_headroom = 2; 494 hw->extra_tx_headroom = 2;
489 hw->channel_change_time = 5000; 495 hw->channel_change_time = 5000;
490 sc = hw->priv; 496 sc = hw->priv;
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index dc45eef3289a..39a4a70d0130 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -1482,6 +1482,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1482 IEEE80211_HW_SIGNAL_DBM | 1482 IEEE80211_HW_SIGNAL_DBM |
1483 IEEE80211_HW_NOISE_DBM; 1483 IEEE80211_HW_NOISE_DBM;
1484 1484
1485 hw->wiphy->interface_modes =
1486 BIT(NL80211_IFTYPE_AP) |
1487 BIT(NL80211_IFTYPE_STATION) |
1488 BIT(NL80211_IFTYPE_ADHOC);
1489
1485 SET_IEEE80211_DEV(hw, &pdev->dev); 1490 SET_IEEE80211_DEV(hw, &pdev->dev);
1486 pci_set_drvdata(pdev, hw); 1491 pci_set_drvdata(pdev, hw);
1487 1492
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 63bafc2f3f0a..2d915c1a82a1 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4569,6 +4569,13 @@ static int b43_wireless_init(struct ssb_device *dev)
4569 IEEE80211_HW_SIGNAL_DBM | 4569 IEEE80211_HW_SIGNAL_DBM |
4570 IEEE80211_HW_NOISE_DBM; 4570 IEEE80211_HW_NOISE_DBM;
4571 4571
4572 hw->wiphy->interface_modes =
4573 BIT(NL80211_IFTYPE_AP) |
4574 BIT(NL80211_IFTYPE_MESH_POINT) |
4575 BIT(NL80211_IFTYPE_STATION) |
4576 BIT(NL80211_IFTYPE_WDS) |
4577 BIT(NL80211_IFTYPE_ADHOC);
4578
4572 hw->queues = b43_modparam_qos ? 4 : 1; 4579 hw->queues = b43_modparam_qos ? 4 : 1;
4573 SET_IEEE80211_DEV(hw, dev->dev); 4580 SET_IEEE80211_DEV(hw, dev->dev);
4574 if (is_valid_ether_addr(sprom->et1mac)) 4581 if (is_valid_ether_addr(sprom->et1mac))
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1cb77db5c292..68f63f5093af 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3704,6 +3704,11 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
3704 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 3704 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
3705 IEEE80211_HW_SIGNAL_DBM | 3705 IEEE80211_HW_SIGNAL_DBM |
3706 IEEE80211_HW_NOISE_DBM; 3706 IEEE80211_HW_NOISE_DBM;
3707 hw->wiphy->interface_modes =
3708 BIT(NL80211_IFTYPE_AP) |
3709 BIT(NL80211_IFTYPE_STATION) |
3710 BIT(NL80211_IFTYPE_WDS) |
3711 BIT(NL80211_IFTYPE_ADHOC);
3707 hw->queues = 1; /* FIXME: hardware has more queues */ 3712 hw->queues = 1; /* FIXME: hardware has more queues */
3708 SET_IEEE80211_DEV(hw, dev->dev); 3713 SET_IEEE80211_DEV(hw, dev->dev);
3709 if (is_valid_ether_addr(sprom->et1mac)) 3714 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 fbf75a62958d..0a511ef8e354 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -819,6 +819,10 @@ int iwl_setup_mac(struct iwl_priv *priv)
819 /* Tell mac80211 our characteristics */ 819 /* Tell mac80211 our characteristics */
820 hw->flags = IEEE80211_HW_SIGNAL_DBM | 820 hw->flags = IEEE80211_HW_SIGNAL_DBM |
821 IEEE80211_HW_NOISE_DBM; 821 IEEE80211_HW_NOISE_DBM;
822 hw->wiphy->interface_modes =
823 BIT(NL80211_IFTYPE_AP) |
824 BIT(NL80211_IFTYPE_STATION) |
825 BIT(NL80211_IFTYPE_ADHOC);
822 /* Default value; 4 EDCA QOS priorities */ 826 /* Default value; 4 EDCA QOS priorities */
823 hw->queues = 4; 827 hw->queues = 4;
824 /* queues to support 11n aggregation */ 828 /* queues to support 11n aggregation */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index a622fc33590a..cee3045f1606 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -7888,6 +7888,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
7888 hw->flags = IEEE80211_HW_SIGNAL_DBM | 7888 hw->flags = IEEE80211_HW_SIGNAL_DBM |
7889 IEEE80211_HW_NOISE_DBM; 7889 IEEE80211_HW_NOISE_DBM;
7890 7890
7891 hw->wiphy->interface_modes =
7892 BIT(NL80211_IFTYPE_AP) |
7893 BIT(NL80211_IFTYPE_STATION) |
7894 BIT(NL80211_IFTYPE_ADHOC);
7895
7891 /* 4 EDCA QOS priorities */ 7896 /* 4 EDCA QOS priorities */
7892 hw->queues = 4; 7897 hw->queues = 4;
7893 7898
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 732429d49122..6ba50f087f7b 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)
447 447
448 hw->channel_change_time = 1; 448 hw->channel_change_time = 1;
449 hw->queues = 4; 449 hw->queues = 4;
450 hw->wiphy->interface_modes =
451 BIT(NL80211_IFTYPE_STATION) |
452 BIT(NL80211_IFTYPE_AP);
450 hw->ampdu_queues = 1; 453 hw->ampdu_queues = 1;
451 454
452 memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); 455 memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 17e06bbc996a..6da98e6e6a9a 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -1072,6 +1072,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
1072 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ 1072 dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
1073 IEEE80211_HW_RX_INCLUDES_FCS | 1073 IEEE80211_HW_RX_INCLUDES_FCS |
1074 IEEE80211_HW_SIGNAL_UNSPEC; 1074 IEEE80211_HW_SIGNAL_UNSPEC;
1075
1076 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1077
1075 dev->channel_change_time = 1000; /* TODO: find actual value */ 1078 dev->channel_change_time = 1000; /* TODO: find actual value */
1076 dev->max_signal = 127; 1079 dev->max_signal = 127;
1077 1080
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 369b0b2d8643..2f3bfc606880 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1052,6 +1052,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1052 */ 1052 */
1053 rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); 1053 rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
1054 1054
1055 rt2x00dev->hw->wiphy->interface_modes =
1056 BIT(NL80211_IFTYPE_AP) |
1057 BIT(NL80211_IFTYPE_STATION) |
1058 BIT(NL80211_IFTYPE_ADHOC);
1059
1055 /* 1060 /*
1056 * Let the driver probe the device to detect the capabilities. 1061 * Let the driver probe the device to detect the capabilities.
1057 */ 1062 */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 060a26505358..8a42bfa6d4f0 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -1184,6 +1184,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1184 dev->max_signal = 65; 1184 dev->max_signal = 65;
1185 } 1185 }
1186 1186
1187 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1188
1187 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) 1189 if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
1188 printk(KERN_INFO "rtl8187: inconsistency between id with OEM" 1190 printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
1189 " info!\n"); 1191 " info!\n");
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 4d7b98b05030..e019102b2285 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -937,6 +937,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
937 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 937 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
938 IEEE80211_HW_SIGNAL_DB; 938 IEEE80211_HW_SIGNAL_DB;
939 939
940 hw->wiphy->interface_modes =
941 BIT(NL80211_IFTYPE_MESH_POINT) |
942 BIT(NL80211_IFTYPE_STATION) |
943 BIT(NL80211_IFTYPE_ADHOC);
944
940 hw->max_signal = 100; 945 hw->max_signal = 100;
941 hw->queues = 1; 946 hw->queues = 1;
942 hw->extra_tx_headroom = sizeof(struct zd_ctrlset); 947 hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 0c1147de3ec7..5e51f4e7600b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -210,6 +210,10 @@ enum nl80211_commands {
210 * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from 210 * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
211 * association request when used with NL80211_CMD_NEW_STATION) 211 * association request when used with NL80211_CMD_NEW_STATION)
212 * 212 *
213 * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all
214 * supported interface types, each a flag attribute with the number
215 * of the interface mode.
216 *
213 * @NL80211_ATTR_MAX: highest attribute number currently defined 217 * @NL80211_ATTR_MAX: highest attribute number currently defined
214 * @__NL80211_ATTR_AFTER_LAST: internal use 218 * @__NL80211_ATTR_AFTER_LAST: internal use
215 */ 219 */
@@ -259,6 +263,8 @@ enum nl80211_attrs {
259 263
260 NL80211_ATTR_HT_CAPABILITY, 264 NL80211_ATTR_HT_CAPABILITY,
261 265
266 NL80211_ATTR_SUPPORTED_IFTYPES,
267
262 /* add attributes here, update the policy in nl80211.c */ 268 /* add attributes here, update the policy in nl80211.c */
263 269
264 __NL80211_ATTR_AFTER_LAST, 270 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/wireless.h b/include/net/wireless.h
index 9324f8dd183e..1dc8ec3daa2f 100644
--- a/include/net/wireless.h
+++ b/include/net/wireless.h
@@ -185,6 +185,9 @@ struct wiphy {
185 /* permanent MAC address */ 185 /* permanent MAC address */
186 u8 perm_addr[ETH_ALEN]; 186 u8 perm_addr[ETH_ALEN];
187 187
188 /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
189 u16 interface_modes;
190
188 /* If multiple wiphys are registered and you're handed e.g. 191 /* If multiple wiphys are registered and you're handed e.g.
189 * a regular netdev with assigned ieee80211_ptr, you won't 192 * a regular netdev with assigned ieee80211_ptr, you won't
190 * know whether it points to a wiphy your driver has registered 193 * know whether it points to a wiphy your driver has registered
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 638b75f36e23..396cfb2d0f46 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1675,6 +1675,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
1675 } 1675 }
1676 } 1676 }
1677 1677
1678 /* if low-level driver supports AP, we also support VLAN */
1679 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
1680 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
1681
1682 /* mac80211 always supports monitor */
1683 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
1684
1678 result = wiphy_register(local->hw.wiphy); 1685 result = wiphy_register(local->hw.wiphy);
1679 if (result < 0) 1686 if (result < 0)
1680 return result; 1687 return result;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f1da0b93bc56..7e995ac06a0c 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
@@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy)
259 struct ieee80211_supported_band *sband; 259 struct ieee80211_supported_band *sband;
260 bool have_band = false; 260 bool have_band = false;
261 int i; 261 int i;
262 u16 ifmodes = wiphy->interface_modes;
263
264 /* sanity check ifmodes */
265 WARN_ON(!ifmodes);
266 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
267 if (WARN_ON(ifmodes != wiphy->interface_modes))
268 wiphy->interface_modes = ifmodes;
262 269
263 /* sanity check supported bands/channels */ 270 /* sanity check supported bands/channels */
264 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 271 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4d6c02afd6f5..77880ba8b619 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -113,10 +113,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
113 struct nlattr *nl_bands, *nl_band; 113 struct nlattr *nl_bands, *nl_band;
114 struct nlattr *nl_freqs, *nl_freq; 114 struct nlattr *nl_freqs, *nl_freq;
115 struct nlattr *nl_rates, *nl_rate; 115 struct nlattr *nl_rates, *nl_rate;
116 struct nlattr *nl_modes;
116 enum ieee80211_band band; 117 enum ieee80211_band band;
117 struct ieee80211_channel *chan; 118 struct ieee80211_channel *chan;
118 struct ieee80211_rate *rate; 119 struct ieee80211_rate *rate;
119 int i; 120 int i;
121 u16 ifmodes = dev->wiphy.interface_modes;
120 122
121 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); 123 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
122 if (!hdr) 124 if (!hdr)
@@ -125,6 +127,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
125 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); 127 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
126 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 128 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
127 129
130 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
131 if (!nl_modes)
132 goto nla_put_failure;
133
134 i = 0;
135 while (ifmodes) {
136 if (ifmodes & 1)
137 NLA_PUT_FLAG(msg, i);
138 ifmodes >>= 1;
139 i++;
140 }
141
142 nla_nest_end(msg, nl_modes);
143
128 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); 144 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
129 if (!nl_bands) 145 if (!nl_bands)
130 goto nla_put_failure; 146 goto nla_put_failure;
@@ -415,7 +431,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
415 ifindex = dev->ifindex; 431 ifindex = dev->ifindex;
416 dev_put(dev); 432 dev_put(dev);
417 433
418 if (!drv->ops->change_virtual_intf) { 434 if (!drv->ops->change_virtual_intf ||
435 !(drv->wiphy.interface_modes & (1 << type))) {
419 err = -EOPNOTSUPP; 436 err = -EOPNOTSUPP;
420 goto unlock; 437 goto unlock;
421 } 438 }
@@ -462,7 +479,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
462 if (IS_ERR(drv)) 479 if (IS_ERR(drv))
463 return PTR_ERR(drv); 480 return PTR_ERR(drv);
464 481
465 if (!drv->ops->add_virtual_intf) { 482 if (!drv->ops->add_virtual_intf ||
483 !(drv->wiphy.interface_modes & (1 << type))) {
466 err = -EOPNOTSUPP; 484 err = -EOPNOTSUPP;
467 goto unlock; 485 goto unlock;
468 } 486 }