aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-11-04 16:18:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-11-04 16:18:12 -0500
commitbf515fb11ab539c76d04f0e3c5216ed41f41d81f (patch)
tree6aaa226c2a40f90a649561b4a5bb0d1772b20bf1 /net/wireless
parent6bc6c49f1e2f3ab1bec05d1c08aad219ab4eb5d0 (diff)
parentcf2c92d840c1424bcb3bb501147c79c9b067ad77 (diff)
Merge tag 'mac80211-next-for-john-2014-11-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg <johannes@sipsolutions.net> says: "This relatively large batch of changes is comprised of the following: * large mac80211-hwsim changes from Ben, Jukka and a bit myself * OCB/WAVE/11p support from Rostislav on behalf of the Czech Technical University in Prague and Volkswagen Group Research * minstrel VHT work from Karl * more CSA work from Luca * WMM admission control support in mac80211 (myself) * various smaller fixes, spelling corrections, and minor API additions" Conflicts: drivers/net/wireless/ath/wil6210/cfg80211.c Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/chan.c10
-rw-r--r--net/wireless/core.c77
-rw-r--r--net/wireless/core.h12
-rw-r--r--net/wireless/nl80211.c206
-rw-r--r--net/wireless/ocb.c88
-rw-r--r--net/wireless/rdev-ops.h55
-rw-r--r--net/wireless/sme.c13
-rw-r--r--net/wireless/trace.h97
-rw-r--r--net/wireless/util.c5
10 files changed, 523 insertions, 42 deletions
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index a761670af31d..4c9e39f04ef8 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o 10obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
11 11
12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o 12cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o 13cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 14cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o 15cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o 16cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 72d81e2154d5..85506f1d0789 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -115,7 +115,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
115EXPORT_SYMBOL(cfg80211_chandef_valid); 115EXPORT_SYMBOL(cfg80211_chandef_valid);
116 116
117static void chandef_primary_freqs(const struct cfg80211_chan_def *c, 117static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
118 int *pri40, int *pri80) 118 u32 *pri40, u32 *pri80)
119{ 119{
120 int tmp; 120 int tmp;
121 121
@@ -366,6 +366,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
366 366
367 break; 367 break;
368 case NL80211_IFTYPE_STATION: 368 case NL80211_IFTYPE_STATION:
369 case NL80211_IFTYPE_OCB:
369 case NL80211_IFTYPE_P2P_CLIENT: 370 case NL80211_IFTYPE_P2P_CLIENT:
370 case NL80211_IFTYPE_MONITOR: 371 case NL80211_IFTYPE_MONITOR:
371 case NL80211_IFTYPE_AP_VLAN: 372 case NL80211_IFTYPE_AP_VLAN:
@@ -892,6 +893,13 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
892 *radar_detect |= BIT(wdev->chandef.width); 893 *radar_detect |= BIT(wdev->chandef.width);
893 } 894 }
894 return; 895 return;
896 case NL80211_IFTYPE_OCB:
897 if (wdev->chandef.chan) {
898 *chan = wdev->chandef.chan;
899 *chanmode = CHAN_MODE_SHARED;
900 return;
901 }
902 break;
895 case NL80211_IFTYPE_MONITOR: 903 case NL80211_IFTYPE_MONITOR:
896 case NL80211_IFTYPE_AP_VLAN: 904 case NL80211_IFTYPE_AP_VLAN:
897 case NL80211_IFTYPE_WDS: 905 case NL80211_IFTYPE_WDS:
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f52a4cd7017c..a4d27927aba2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -86,11 +86,11 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
86 return &rdev->wiphy; 86 return &rdev->wiphy;
87} 87}
88 88
89int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, 89static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
90 char *newname) 90 const char *newname)
91{ 91{
92 struct cfg80211_registered_device *rdev2; 92 struct cfg80211_registered_device *rdev2;
93 int wiphy_idx, taken = -1, result, digits; 93 int wiphy_idx, taken = -1, digits;
94 94
95 ASSERT_RTNL(); 95 ASSERT_RTNL();
96 96
@@ -109,15 +109,28 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
109 return -EINVAL; 109 return -EINVAL;
110 } 110 }
111 111
112 /* Ensure another device does not already have this name. */
113 list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
114 if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
115 return -EINVAL;
116
117 return 0;
118}
119
120int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
121 char *newname)
122{
123 int result;
124
125 ASSERT_RTNL();
112 126
113 /* Ignore nop renames */ 127 /* Ignore nop renames */
114 if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) 128 if (strcmp(newname, wiphy_name(&rdev->wiphy)) == 0)
115 return 0; 129 return 0;
116 130
117 /* Ensure another device does not already have this name. */ 131 result = cfg80211_dev_check_name(rdev, newname);
118 list_for_each_entry(rdev2, &cfg80211_rdev_list, list) 132 if (result < 0)
119 if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) 133 return result;
120 return -EINVAL;
121 134
122 result = device_rename(&rdev->wiphy.dev, newname); 135 result = device_rename(&rdev->wiphy.dev, newname);
123 if (result) 136 if (result)
@@ -309,7 +322,8 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
309 322
310/* exported functions */ 323/* exported functions */
311 324
312struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) 325struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
326 const char *requested_name)
313{ 327{
314 static atomic_t wiphy_counter = ATOMIC_INIT(0); 328 static atomic_t wiphy_counter = ATOMIC_INIT(0);
315 329
@@ -346,7 +360,31 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
346 rdev->wiphy_idx--; 360 rdev->wiphy_idx--;
347 361
348 /* give it a proper name */ 362 /* give it a proper name */
349 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); 363 if (requested_name && requested_name[0]) {
364 int rv;
365
366 rtnl_lock();
367 rv = cfg80211_dev_check_name(rdev, requested_name);
368
369 if (rv < 0) {
370 rtnl_unlock();
371 goto use_default_name;
372 }
373
374 rv = dev_set_name(&rdev->wiphy.dev, "%s", requested_name);
375 rtnl_unlock();
376 if (rv)
377 goto use_default_name;
378 } else {
379use_default_name:
380 /* NOTE: This is *probably* safe w/out holding rtnl because of
381 * the restrictions on phy names. Probably this call could
382 * fail if some other part of the kernel (re)named a device
383 * phyX. But, might should add some locking and check return
384 * value, and use a different name if this one exists?
385 */
386 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
387 }
350 388
351 INIT_LIST_HEAD(&rdev->wdev_list); 389 INIT_LIST_HEAD(&rdev->wdev_list);
352 INIT_LIST_HEAD(&rdev->beacon_registrations); 390 INIT_LIST_HEAD(&rdev->beacon_registrations);
@@ -406,7 +444,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
406 444
407 return &rdev->wiphy; 445 return &rdev->wiphy;
408} 446}
409EXPORT_SYMBOL(wiphy_new); 447EXPORT_SYMBOL(wiphy_new_nm);
410 448
411static int wiphy_verify_combinations(struct wiphy *wiphy) 449static int wiphy_verify_combinations(struct wiphy *wiphy)
412{ 450{
@@ -831,7 +869,22 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
831 case NL80211_IFTYPE_P2P_GO: 869 case NL80211_IFTYPE_P2P_GO:
832 __cfg80211_stop_ap(rdev, dev, true); 870 __cfg80211_stop_ap(rdev, dev, true);
833 break; 871 break;
834 default: 872 case NL80211_IFTYPE_OCB:
873 __cfg80211_leave_ocb(rdev, dev);
874 break;
875 case NL80211_IFTYPE_WDS:
876 /* must be handled by mac80211/driver, has no APIs */
877 break;
878 case NL80211_IFTYPE_P2P_DEVICE:
879 /* cannot happen, has no netdev */
880 break;
881 case NL80211_IFTYPE_AP_VLAN:
882 case NL80211_IFTYPE_MONITOR:
883 /* nothing to do */
884 break;
885 case NL80211_IFTYPE_UNSPECIFIED:
886 case NUM_NL80211_IFTYPES:
887 /* invalid */
835 break; 888 break;
836 } 889 }
837} 890}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 7e3a3cef7df9..61ee664cf2bd 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -290,6 +290,18 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
290 struct wireless_dev *wdev, 290 struct wireless_dev *wdev,
291 struct cfg80211_chan_def *chandef); 291 struct cfg80211_chan_def *chandef);
292 292
293/* OCB */
294int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
295 struct net_device *dev,
296 struct ocb_setup *setup);
297int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
298 struct net_device *dev,
299 struct ocb_setup *setup);
300int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
301 struct net_device *dev);
302int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
303 struct net_device *dev);
304
293/* AP */ 305/* AP */
294int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, 306int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
295 struct net_device *dev, bool notify); 307 struct net_device *dev, bool notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cb9f5a44ffad..1a31736914e5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -884,7 +884,12 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
884 if (!wdev->current_bss) 884 if (!wdev->current_bss)
885 return -ENOLINK; 885 return -ENOLINK;
886 break; 886 break;
887 default: 887 case NL80211_IFTYPE_UNSPECIFIED:
888 case NL80211_IFTYPE_OCB:
889 case NL80211_IFTYPE_MONITOR:
890 case NL80211_IFTYPE_P2P_DEVICE:
891 case NL80211_IFTYPE_WDS:
892 case NUM_NL80211_IFTYPES:
888 return -EINVAL; 893 return -EINVAL;
889 } 894 }
890 895
@@ -1514,8 +1519,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1514 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) 1519 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
1515 CMD(channel_switch, CHANNEL_SWITCH); 1520 CMD(channel_switch, CHANNEL_SWITCH);
1516 CMD(set_qos_map, SET_QOS_MAP); 1521 CMD(set_qos_map, SET_QOS_MAP);
1517 if (rdev->wiphy.flags & 1522 if (rdev->wiphy.features &
1518 WIPHY_FLAG_SUPPORTS_WMM_ADMISSION) 1523 NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
1519 CMD(add_tx_ts, ADD_TX_TS); 1524 CMD(add_tx_ts, ADD_TX_TS);
1520 } 1525 }
1521 /* add into the if now */ 1526 /* add into the if now */
@@ -2605,7 +2610,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
2605 !(rdev->wiphy.interface_modes & (1 << type))) 2610 !(rdev->wiphy.interface_modes & (1 << type)))
2606 return -EOPNOTSUPP; 2611 return -EOPNOTSUPP;
2607 2612
2608 if (type == NL80211_IFTYPE_P2P_DEVICE && info->attrs[NL80211_ATTR_MAC]) { 2613 if ((type == NL80211_IFTYPE_P2P_DEVICE ||
2614 rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
2615 info->attrs[NL80211_ATTR_MAC]) {
2609 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC], 2616 nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
2610 ETH_ALEN); 2617 ETH_ALEN);
2611 if (!is_valid_ether_addr(params.macaddr)) 2618 if (!is_valid_ether_addr(params.macaddr))
@@ -4398,10 +4405,12 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
4398{ 4405{
4399 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 4406 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4400 struct net_device *dev = info->user_ptr[1]; 4407 struct net_device *dev = info->user_ptr[1];
4401 u8 *mac_addr = NULL; 4408 struct station_del_parameters params;
4409
4410 memset(&params, 0, sizeof(params));
4402 4411
4403 if (info->attrs[NL80211_ATTR_MAC]) 4412 if (info->attrs[NL80211_ATTR_MAC])
4404 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 4413 params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
4405 4414
4406 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 4415 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4407 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && 4416 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
@@ -4412,7 +4421,28 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
4412 if (!rdev->ops->del_station) 4421 if (!rdev->ops->del_station)
4413 return -EOPNOTSUPP; 4422 return -EOPNOTSUPP;
4414 4423
4415 return rdev_del_station(rdev, dev, mac_addr); 4424 if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
4425 params.subtype =
4426 nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
4427 if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
4428 params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
4429 return -EINVAL;
4430 } else {
4431 /* Default to Deauthentication frame */
4432 params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
4433 }
4434
4435 if (info->attrs[NL80211_ATTR_REASON_CODE]) {
4436 params.reason_code =
4437 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
4438 if (params.reason_code == 0)
4439 return -EINVAL; /* 0 is reserved */
4440 } else {
4441 /* Default to reason code 2 */
4442 params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
4443 }
4444
4445 return rdev_del_station(rdev, dev, &params);
4416} 4446}
4417 4447
4418static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq, 4448static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
@@ -4624,6 +4654,96 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
4624 return rdev_del_mpath(rdev, dev, dst); 4654 return rdev_del_mpath(rdev, dev, dst);
4625} 4655}
4626 4656
4657static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
4658{
4659 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4660 int err;
4661 struct net_device *dev = info->user_ptr[1];
4662 struct mpath_info pinfo;
4663 struct sk_buff *msg;
4664 u8 *dst = NULL;
4665 u8 mpp[ETH_ALEN];
4666
4667 memset(&pinfo, 0, sizeof(pinfo));
4668
4669 if (!info->attrs[NL80211_ATTR_MAC])
4670 return -EINVAL;
4671
4672 dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
4673
4674 if (!rdev->ops->get_mpp)
4675 return -EOPNOTSUPP;
4676
4677 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
4678 return -EOPNOTSUPP;
4679
4680 err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
4681 if (err)
4682 return err;
4683
4684 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4685 if (!msg)
4686 return -ENOMEM;
4687
4688 if (nl80211_send_mpath(msg, info->snd_portid, info->snd_seq, 0,
4689 dev, dst, mpp, &pinfo) < 0) {
4690 nlmsg_free(msg);
4691 return -ENOBUFS;
4692 }
4693
4694 return genlmsg_reply(msg, info);
4695}
4696
4697static int nl80211_dump_mpp(struct sk_buff *skb,
4698 struct netlink_callback *cb)
4699{
4700 struct mpath_info pinfo;
4701 struct cfg80211_registered_device *rdev;
4702 struct wireless_dev *wdev;
4703 u8 dst[ETH_ALEN];
4704 u8 mpp[ETH_ALEN];
4705 int path_idx = cb->args[2];
4706 int err;
4707
4708 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
4709 if (err)
4710 return err;
4711
4712 if (!rdev->ops->dump_mpp) {
4713 err = -EOPNOTSUPP;
4714 goto out_err;
4715 }
4716
4717 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
4718 err = -EOPNOTSUPP;
4719 goto out_err;
4720 }
4721
4722 while (1) {
4723 err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
4724 mpp, &pinfo);
4725 if (err == -ENOENT)
4726 break;
4727 if (err)
4728 goto out_err;
4729
4730 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
4731 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4732 wdev->netdev, dst, mpp,
4733 &pinfo) < 0)
4734 goto out;
4735
4736 path_idx++;
4737 }
4738
4739 out:
4740 cb->args[2] = path_idx;
4741 err = skb->len;
4742 out_err:
4743 nl80211_finish_wdev_dump(rdev);
4744 return err;
4745}
4746
4627static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) 4747static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
4628{ 4748{
4629 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 4749 struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5923,10 +6043,10 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5923 * function is called under RTNL lock, so this should not be a problem. 6043 * function is called under RTNL lock, so this should not be a problem.
5924 */ 6044 */
5925 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; 6045 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
5926 u8 radar_detect_width = 0;
5927 int err; 6046 int err;
5928 bool need_new_beacon = false; 6047 bool need_new_beacon = false;
5929 int len, i; 6048 int len, i;
6049 u32 cs_count;
5930 6050
5931 if (!rdev->ops->channel_switch || 6051 if (!rdev->ops->channel_switch ||
5932 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 6052 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -5963,7 +6083,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5963 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES]) 6083 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
5964 return -EINVAL; 6084 return -EINVAL;
5965 6085
5966 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); 6086 /* Even though the attribute is u32, the specification says
6087 * u8, so let's make sure we don't overflow.
6088 */
6089 cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
6090 if (cs_count > 255)
6091 return -EINVAL;
6092
6093 params.count = cs_count;
5967 6094
5968 if (!need_new_beacon) 6095 if (!need_new_beacon)
5969 goto skip_beacons; 6096 goto skip_beacons;
@@ -6051,10 +6178,8 @@ skip_beacons:
6051 if (err < 0) 6178 if (err < 0)
6052 return err; 6179 return err;
6053 6180
6054 if (err > 0) { 6181 if (err > 0)
6055 radar_detect_width = BIT(params.chandef.width);
6056 params.radar_required = true; 6182 params.radar_required = true;
6057 }
6058 6183
6059 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) 6184 if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
6060 params.block_tx = true; 6185 params.block_tx = true;
@@ -8151,6 +8276,28 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
8151 return -EINVAL; 8276 return -EINVAL;
8152} 8277}
8153 8278
8279static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
8280{
8281 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8282 struct net_device *dev = info->user_ptr[1];
8283 struct ocb_setup setup = {};
8284 int err;
8285
8286 err = nl80211_parse_chandef(rdev, info, &setup.chandef);
8287 if (err)
8288 return err;
8289
8290 return cfg80211_join_ocb(rdev, dev, &setup);
8291}
8292
8293static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
8294{
8295 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8296 struct net_device *dev = info->user_ptr[1];
8297
8298 return cfg80211_leave_ocb(rdev, dev);
8299}
8300
8154static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) 8301static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
8155{ 8302{
8156 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 8303 struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9436,7 +9583,7 @@ static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
9436 u16 admitted_time = 0; 9583 u16 admitted_time = 0;
9437 int err; 9584 int err;
9438 9585
9439 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)) 9586 if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
9440 return -EOPNOTSUPP; 9587 return -EOPNOTSUPP;
9441 9588
9442 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] || 9589 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
@@ -9452,12 +9599,10 @@ static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
9452 return -EINVAL; 9599 return -EINVAL;
9453 9600
9454 /* WMM uses TIDs 0-7 even for TSPEC */ 9601 /* WMM uses TIDs 0-7 even for TSPEC */
9455 if (tsid < IEEE80211_FIRST_TSPEC_TSID) { 9602 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
9456 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9457 return -EINVAL;
9458 } else {
9459 /* TODO: handle 802.11 TSPEC/admission control 9603 /* TODO: handle 802.11 TSPEC/admission control
9460 * need more attributes for that (e.g. BA session requirement) 9604 * need more attributes for that (e.g. BA session requirement);
9605 * change the WMM adminssion test above to allow both then
9461 */ 9606 */
9462 return -EINVAL; 9607 return -EINVAL;
9463 } 9608 }
@@ -9774,6 +9919,15 @@ static const struct genl_ops nl80211_ops[] = {
9774 NL80211_FLAG_NEED_RTNL, 9919 NL80211_FLAG_NEED_RTNL,
9775 }, 9920 },
9776 { 9921 {
9922 .cmd = NL80211_CMD_GET_MPP,
9923 .doit = nl80211_get_mpp,
9924 .dumpit = nl80211_dump_mpp,
9925 .policy = nl80211_policy,
9926 .flags = GENL_ADMIN_PERM,
9927 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9928 NL80211_FLAG_NEED_RTNL,
9929 },
9930 {
9777 .cmd = NL80211_CMD_SET_MPATH, 9931 .cmd = NL80211_CMD_SET_MPATH,
9778 .doit = nl80211_set_mpath, 9932 .doit = nl80211_set_mpath,
9779 .policy = nl80211_policy, 9933 .policy = nl80211_policy,
@@ -10087,6 +10241,22 @@ static const struct genl_ops nl80211_ops[] = {
10087 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10241 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10088 NL80211_FLAG_NEED_RTNL, 10242 NL80211_FLAG_NEED_RTNL,
10089 }, 10243 },
10244 {
10245 .cmd = NL80211_CMD_JOIN_OCB,
10246 .doit = nl80211_join_ocb,
10247 .policy = nl80211_policy,
10248 .flags = GENL_ADMIN_PERM,
10249 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10250 NL80211_FLAG_NEED_RTNL,
10251 },
10252 {
10253 .cmd = NL80211_CMD_LEAVE_OCB,
10254 .doit = nl80211_leave_ocb,
10255 .policy = nl80211_policy,
10256 .flags = GENL_ADMIN_PERM,
10257 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10258 NL80211_FLAG_NEED_RTNL,
10259 },
10090#ifdef CONFIG_PM 10260#ifdef CONFIG_PM
10091 { 10261 {
10092 .cmd = NL80211_CMD_GET_WOWLAN, 10262 .cmd = NL80211_CMD_GET_WOWLAN,
diff --git a/net/wireless/ocb.c b/net/wireless/ocb.c
new file mode 100644
index 000000000000..c00d4a792319
--- /dev/null
+++ b/net/wireless/ocb.c
@@ -0,0 +1,88 @@
1/*
2 * OCB mode implementation
3 *
4 * Copyright: (c) 2014 Czech Technical University in Prague
5 * (c) 2014 Volkswagen Group Research
6 * Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
7 * Funded by: Volkswagen Group Research
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/ieee80211.h>
15#include <net/cfg80211.h>
16#include "nl80211.h"
17#include "core.h"
18#include "rdev-ops.h"
19
20int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
21 struct net_device *dev,
22 struct ocb_setup *setup)
23{
24 struct wireless_dev *wdev = dev->ieee80211_ptr;
25 int err;
26
27 ASSERT_WDEV_LOCK(wdev);
28
29 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
30 return -EOPNOTSUPP;
31
32 if (WARN_ON(!setup->chandef.chan))
33 return -EINVAL;
34
35 err = rdev_join_ocb(rdev, dev, setup);
36 if (!err)
37 wdev->chandef = setup->chandef;
38
39 return err;
40}
41
42int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
43 struct net_device *dev,
44 struct ocb_setup *setup)
45{
46 struct wireless_dev *wdev = dev->ieee80211_ptr;
47 int err;
48
49 wdev_lock(wdev);
50 err = __cfg80211_join_ocb(rdev, dev, setup);
51 wdev_unlock(wdev);
52
53 return err;
54}
55
56int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
57 struct net_device *dev)
58{
59 struct wireless_dev *wdev = dev->ieee80211_ptr;
60 int err;
61
62 ASSERT_WDEV_LOCK(wdev);
63
64 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
65 return -EOPNOTSUPP;
66
67 if (!rdev->ops->leave_ocb)
68 return -EOPNOTSUPP;
69
70 err = rdev_leave_ocb(rdev, dev);
71 if (!err)
72 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
73
74 return err;
75}
76
77int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
78 struct net_device *dev)
79{
80 struct wireless_dev *wdev = dev->ieee80211_ptr;
81 int err;
82
83 wdev_lock(wdev);
84 err = __cfg80211_leave_ocb(rdev, dev);
85 wdev_unlock(wdev);
86
87 return err;
88}
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index f6d457d6a558..1b3864cd50ca 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -178,11 +178,12 @@ static inline int rdev_add_station(struct cfg80211_registered_device *rdev,
178} 178}
179 179
180static inline int rdev_del_station(struct cfg80211_registered_device *rdev, 180static inline int rdev_del_station(struct cfg80211_registered_device *rdev,
181 struct net_device *dev, u8 *mac) 181 struct net_device *dev,
182 struct station_del_parameters *params)
182{ 183{
183 int ret; 184 int ret;
184 trace_rdev_del_station(&rdev->wiphy, dev, mac); 185 trace_rdev_del_station(&rdev->wiphy, dev, params);
185 ret = rdev->ops->del_station(&rdev->wiphy, dev, mac); 186 ret = rdev->ops->del_station(&rdev->wiphy, dev, params);
186 trace_rdev_return_int(&rdev->wiphy, ret); 187 trace_rdev_return_int(&rdev->wiphy, ret);
187 return ret; 188 return ret;
188} 189}
@@ -263,6 +264,18 @@ static inline int rdev_get_mpath(struct cfg80211_registered_device *rdev,
263 264
264} 265}
265 266
267static inline int rdev_get_mpp(struct cfg80211_registered_device *rdev,
268 struct net_device *dev, u8 *dst, u8 *mpp,
269 struct mpath_info *pinfo)
270{
271 int ret;
272
273 trace_rdev_get_mpp(&rdev->wiphy, dev, dst, mpp);
274 ret = rdev->ops->get_mpp(&rdev->wiphy, dev, dst, mpp, pinfo);
275 trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
276 return ret;
277}
278
266static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev, 279static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
267 struct net_device *dev, int idx, u8 *dst, 280 struct net_device *dev, int idx, u8 *dst,
268 u8 *next_hop, struct mpath_info *pinfo) 281 u8 *next_hop, struct mpath_info *pinfo)
@@ -271,7 +284,20 @@ static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
271 int ret; 284 int ret;
272 trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop); 285 trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop);
273 ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop, 286 ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop,
274 pinfo); 287 pinfo);
288 trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
289 return ret;
290}
291
292static inline int rdev_dump_mpp(struct cfg80211_registered_device *rdev,
293 struct net_device *dev, int idx, u8 *dst,
294 u8 *mpp, struct mpath_info *pinfo)
295
296{
297 int ret;
298
299 trace_rdev_dump_mpp(&rdev->wiphy, dev, idx, dst, mpp);
300 ret = rdev->ops->dump_mpp(&rdev->wiphy, dev, idx, dst, mpp, pinfo);
275 trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo); 301 trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
276 return ret; 302 return ret;
277} 303}
@@ -322,6 +348,27 @@ static inline int rdev_leave_mesh(struct cfg80211_registered_device *rdev,
322 return ret; 348 return ret;
323} 349}
324 350
351static inline int rdev_join_ocb(struct cfg80211_registered_device *rdev,
352 struct net_device *dev,
353 struct ocb_setup *setup)
354{
355 int ret;
356 trace_rdev_join_ocb(&rdev->wiphy, dev, setup);
357 ret = rdev->ops->join_ocb(&rdev->wiphy, dev, setup);
358 trace_rdev_return_int(&rdev->wiphy, ret);
359 return ret;
360}
361
362static inline int rdev_leave_ocb(struct cfg80211_registered_device *rdev,
363 struct net_device *dev)
364{
365 int ret;
366 trace_rdev_leave_ocb(&rdev->wiphy, dev);
367 ret = rdev->ops->leave_ocb(&rdev->wiphy, dev);
368 trace_rdev_return_int(&rdev->wiphy, ret);
369 return ret;
370}
371
325static inline int rdev_change_bss(struct cfg80211_registered_device *rdev, 372static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
326 struct net_device *dev, 373 struct net_device *dev,
327 struct bss_parameters *params) 374 struct bss_parameters *params)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index dc1668ff543b..0ab3711c79a0 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -80,9 +80,18 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
80 if (!request) 80 if (!request)
81 return -ENOMEM; 81 return -ENOMEM;
82 82
83 if (wdev->conn->params.channel) 83 if (wdev->conn->params.channel) {
84 enum ieee80211_band band = wdev->conn->params.channel->band;
85 struct ieee80211_supported_band *sband =
86 wdev->wiphy->bands[band];
87
88 if (!sband) {
89 kfree(request);
90 return -EINVAL;
91 }
84 request->channels[0] = wdev->conn->params.channel; 92 request->channels[0] = wdev->conn->params.channel;
85 else { 93 request->rates[band] = (1 << sband->n_bitrates) - 1;
94 } else {
86 int i = 0, j; 95 int i = 0, j;
87 enum ieee80211_band band; 96 enum ieee80211_band band;
88 struct ieee80211_supported_band *bands; 97 struct ieee80211_supported_band *bands;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 625a6e6d1168..277a85df910e 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -600,6 +600,11 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ibss,
600 TP_ARGS(wiphy, netdev) 600 TP_ARGS(wiphy, netdev)
601); 601);
602 602
603DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ocb,
604 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
605 TP_ARGS(wiphy, netdev)
606);
607
603DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa, 608DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
604 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), 609 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
605 TP_ARGS(wiphy, netdev) 610 TP_ARGS(wiphy, netdev)
@@ -680,9 +685,34 @@ DECLARE_EVENT_CLASS(wiphy_netdev_mac_evt,
680 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac)) 685 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
681); 686);
682 687
683DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_station, 688DECLARE_EVENT_CLASS(station_del,
684 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac), 689 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
685 TP_ARGS(wiphy, netdev, mac) 690 struct station_del_parameters *params),
691 TP_ARGS(wiphy, netdev, params),
692 TP_STRUCT__entry(
693 WIPHY_ENTRY
694 NETDEV_ENTRY
695 MAC_ENTRY(sta_mac)
696 __field(u8, subtype)
697 __field(u16, reason_code)
698 ),
699 TP_fast_assign(
700 WIPHY_ASSIGN;
701 NETDEV_ASSIGN;
702 MAC_ASSIGN(sta_mac, params->mac);
703 __entry->subtype = params->subtype;
704 __entry->reason_code = params->reason_code;
705 ),
706 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
707 ", subtype: %u, reason_code: %u",
708 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
709 __entry->subtype, __entry->reason_code)
710);
711
712DEFINE_EVENT(station_del, rdev_del_station,
713 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
714 struct station_del_parameters *params),
715 TP_ARGS(wiphy, netdev, params)
686); 716);
687 717
688DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station, 718DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station,
@@ -801,6 +831,51 @@ TRACE_EVENT(rdev_dump_mpath,
801 MAC_PR_ARG(next_hop)) 831 MAC_PR_ARG(next_hop))
802); 832);
803 833
834TRACE_EVENT(rdev_get_mpp,
835 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
836 u8 *dst, u8 *mpp),
837 TP_ARGS(wiphy, netdev, dst, mpp),
838 TP_STRUCT__entry(
839 WIPHY_ENTRY
840 NETDEV_ENTRY
841 MAC_ENTRY(dst)
842 MAC_ENTRY(mpp)
843 ),
844 TP_fast_assign(
845 WIPHY_ASSIGN;
846 NETDEV_ASSIGN;
847 MAC_ASSIGN(dst, dst);
848 MAC_ASSIGN(mpp, mpp);
849 ),
850 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT
851 ", mpp: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG,
852 MAC_PR_ARG(dst), MAC_PR_ARG(mpp))
853);
854
855TRACE_EVENT(rdev_dump_mpp,
856 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
857 u8 *dst, u8 *mpp),
858 TP_ARGS(wiphy, netdev, idx, mpp, dst),
859 TP_STRUCT__entry(
860 WIPHY_ENTRY
861 NETDEV_ENTRY
862 MAC_ENTRY(dst)
863 MAC_ENTRY(mpp)
864 __field(int, idx)
865 ),
866 TP_fast_assign(
867 WIPHY_ASSIGN;
868 NETDEV_ASSIGN;
869 MAC_ASSIGN(dst, dst);
870 MAC_ASSIGN(mpp, mpp);
871 __entry->idx = idx;
872 ),
873 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
874 MAC_PR_FMT ", mpp: " MAC_PR_FMT,
875 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
876 MAC_PR_ARG(mpp))
877);
878
804TRACE_EVENT(rdev_return_int_mpath_info, 879TRACE_EVENT(rdev_return_int_mpath_info,
805 TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo), 880 TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo),
806 TP_ARGS(wiphy, ret, pinfo), 881 TP_ARGS(wiphy, ret, pinfo),
@@ -1246,6 +1321,22 @@ TRACE_EVENT(rdev_join_ibss,
1246 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid) 1321 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
1247); 1322);
1248 1323
1324TRACE_EVENT(rdev_join_ocb,
1325 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1326 const struct ocb_setup *setup),
1327 TP_ARGS(wiphy, netdev, setup),
1328 TP_STRUCT__entry(
1329 WIPHY_ENTRY
1330 NETDEV_ENTRY
1331 ),
1332 TP_fast_assign(
1333 WIPHY_ASSIGN;
1334 NETDEV_ASSIGN;
1335 ),
1336 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
1337 WIPHY_PR_ARG, NETDEV_PR_ARG)
1338);
1339
1249TRACE_EVENT(rdev_set_wiphy_params, 1340TRACE_EVENT(rdev_set_wiphy_params,
1250 TP_PROTO(struct wiphy *wiphy, u32 changed), 1341 TP_PROTO(struct wiphy *wiphy, u32 changed),
1251 TP_ARGS(wiphy, changed), 1342 TP_ARGS(wiphy, changed),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5e233a577d0f..d0ac795445b7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -442,7 +442,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
442 break; 442 break;
443 case cpu_to_le16(0): 443 case cpu_to_le16(0):
444 if (iftype != NL80211_IFTYPE_ADHOC && 444 if (iftype != NL80211_IFTYPE_ADHOC &&
445 iftype != NL80211_IFTYPE_STATION) 445 iftype != NL80211_IFTYPE_STATION &&
446 iftype != NL80211_IFTYPE_OCB)
446 return -1; 447 return -1;
447 break; 448 break;
448 } 449 }
@@ -519,6 +520,7 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
519 memcpy(hdr.addr3, skb->data, ETH_ALEN); 520 memcpy(hdr.addr3, skb->data, ETH_ALEN);
520 hdrlen = 24; 521 hdrlen = 24;
521 break; 522 break;
523 case NL80211_IFTYPE_OCB:
522 case NL80211_IFTYPE_ADHOC: 524 case NL80211_IFTYPE_ADHOC:
523 /* DA SA BSSID */ 525 /* DA SA BSSID */
524 memcpy(hdr.addr1, skb->data, ETH_ALEN); 526 memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -937,6 +939,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
937 if (dev->ieee80211_ptr->use_4addr) 939 if (dev->ieee80211_ptr->use_4addr)
938 break; 940 break;
939 /* fall through */ 941 /* fall through */
942 case NL80211_IFTYPE_OCB:
940 case NL80211_IFTYPE_P2P_CLIENT: 943 case NL80211_IFTYPE_P2P_CLIENT:
941 case NL80211_IFTYPE_ADHOC: 944 case NL80211_IFTYPE_ADHOC:
942 dev->priv_flags |= IFF_DONT_BRIDGE; 945 dev->priv_flags |= IFF_DONT_BRIDGE;