Commit 89a54e48 authored by Johannes Berg's avatar Johannes Berg

nl80211: prepare for non-netdev wireless devs

In order to support a P2P device abstraction and
Bluetooth high-speed AMPs, we need to have a way
to identify virtual interfaces that don't have a
netdev associated.

Do this by adding a NL80211_ATTR_WDEV attribute
to identify a wdev which may or may not also be
a netdev.

To simplify things, use a 64-bit value with the
high 32 bits being the wiphy index for this new
wdev identifier in the nl80211 API.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f72b85b8
...@@ -771,6 +771,9 @@ enum nl80211_commands { ...@@ -771,6 +771,9 @@ enum nl80211_commands {
* @NL80211_ATTR_IFNAME: network interface name * @NL80211_ATTR_IFNAME: network interface name
* @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
* *
* @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices
* that don't have a netdev (u64)
*
* @NL80211_ATTR_MAC: MAC address (various uses) * @NL80211_ATTR_MAC: MAC address (various uses)
* *
* @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
...@@ -1493,6 +1496,8 @@ enum nl80211_attrs { ...@@ -1493,6 +1496,8 @@ enum nl80211_attrs {
NL80211_ATTR_BG_SCAN_PERIOD, NL80211_ATTR_BG_SCAN_PERIOD,
NL80211_ATTR_WDEV,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
......
...@@ -2341,17 +2341,25 @@ struct cfg80211_internal_bss; ...@@ -2341,17 +2341,25 @@ struct cfg80211_internal_bss;
struct cfg80211_cached_keys; struct cfg80211_cached_keys;
/** /**
* struct wireless_dev - wireless per-netdev state * struct wireless_dev - wireless device state
* *
* This structure must be allocated by the driver/stack * For netdevs, this structure must be allocated by the driver
* that uses the ieee80211_ptr field in struct net_device * that uses the ieee80211_ptr field in struct net_device (this
* (this is intentional so it can be allocated along with * is intentional so it can be allocated along with the netdev.)
* the netdev.) * It need not be registered then as netdev registration will
* be intercepted by cfg80211 to see the new wireless device.
*
* For non-netdev uses, it must also be allocated by the driver
* in response to the cfg80211 callbacks that require it, as
* there's no netdev registration in that case it may not be
* allocated outside of callback operations that return it.
* *
* @wiphy: pointer to hardware description * @wiphy: pointer to hardware description
* @iftype: interface type * @iftype: interface type
* @list: (private) Used to collect the interfaces * @list: (private) Used to collect the interfaces
* @netdev: (private) Used to reference back to the netdev * @netdev: (private) Used to reference back to the netdev, may be %NULL
* @identifier: (private) Identifier used in nl80211 to identify this
* wireless device if it has no netdev
* @current_bss: (private) Used by the internal configuration code * @current_bss: (private) Used by the internal configuration code
* @channel: (private) Used by the internal configuration code to track * @channel: (private) Used by the internal configuration code to track
* the user-set AP, monitor and WDS channel * the user-set AP, monitor and WDS channel
...@@ -2383,6 +2391,8 @@ struct wireless_dev { ...@@ -2383,6 +2391,8 @@ struct wireless_dev {
struct list_head list; struct list_head list;
struct net_device *netdev; struct net_device *netdev;
u32 identifier;
struct list_head mgmt_registrations; struct list_head mgmt_registrations;
spinlock_t mgmt_registrations_lock; spinlock_t mgmt_registrations_lock;
......
...@@ -176,7 +176,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, ...@@ -176,7 +176,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK)) if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
return -EOPNOTSUPP; return -EOPNOTSUPP;
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL; wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
err = dev_change_net_namespace(wdev->netdev, net, "wlan%d"); err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
if (err) if (err)
...@@ -188,7 +188,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, ...@@ -188,7 +188,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
/* failed -- clean up to old netns */ /* failed -- clean up to old netns */
net = wiphy_net(&rdev->wiphy); net = wiphy_net(&rdev->wiphy);
list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list, list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,
list) { list) {
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL; wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
err = dev_change_net_namespace(wdev->netdev, net, err = dev_change_net_namespace(wdev->netdev, net,
...@@ -226,7 +226,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) ...@@ -226,7 +226,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock(); rtnl_lock();
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) list_for_each_entry(wdev, &rdev->wdev_list, list)
dev_close(wdev->netdev); dev_close(wdev->netdev);
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
...@@ -304,7 +304,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) ...@@ -304,7 +304,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
mutex_init(&rdev->mtx); mutex_init(&rdev->mtx);
mutex_init(&rdev->devlist_mtx); mutex_init(&rdev->devlist_mtx);
mutex_init(&rdev->sched_scan_mtx); mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->netdev_list); INIT_LIST_HEAD(&rdev->wdev_list);
spin_lock_init(&rdev->bss_lock); spin_lock_init(&rdev->bss_lock);
INIT_LIST_HEAD(&rdev->bss_list); INIT_LIST_HEAD(&rdev->bss_list);
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
...@@ -622,7 +622,7 @@ void wiphy_unregister(struct wiphy *wiphy) ...@@ -622,7 +622,7 @@ void wiphy_unregister(struct wiphy *wiphy)
__count == 0; })); __count == 0; }));
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
BUG_ON(!list_empty(&rdev->netdev_list)); BUG_ON(!list_empty(&rdev->wdev_list));
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
/* /*
...@@ -821,7 +821,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -821,7 +821,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
spin_lock_init(&wdev->mgmt_registrations_lock); spin_lock_init(&wdev->mgmt_registrations_lock);
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_add_rcu(&wdev->list, &rdev->netdev_list); wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++; rdev->devlist_generation++;
/* can only change netns with wiphy */ /* can only change netns with wiphy */
dev->features |= NETIF_F_NETNS_LOCAL; dev->features |= NETIF_F_NETNS_LOCAL;
......
...@@ -47,11 +47,11 @@ struct cfg80211_registered_device { ...@@ -47,11 +47,11 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */ /* wiphy index, internal only */
int wiphy_idx; int wiphy_idx;
/* associate netdev list */ /* associated wireless interfaces */
struct mutex devlist_mtx; struct mutex devlist_mtx;
/* protected by devlist_mtx or RCU */ /* protected by devlist_mtx or RCU */
struct list_head netdev_list; struct list_head wdev_list;
int devlist_generation; int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */ int opencount; /* also protected by devlist_mtx */
wait_queue_head_t dev_wait; wait_queue_head_t dev_wait;
......
...@@ -46,28 +46,60 @@ static struct genl_family nl80211_fam = { ...@@ -46,28 +46,60 @@ static struct genl_family nl80211_fam = {
.post_doit = nl80211_post_doit, .post_doit = nl80211_post_doit,
}; };
/* internal helper: get rdev and dev */ /* returns ERR_PTR values */
static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs, static struct wireless_dev *
struct cfg80211_registered_device **rdev, __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
struct net_device **dev)
{ {
int ifindex; struct cfg80211_registered_device *rdev;
struct wireless_dev *result = NULL;
bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
u64 wdev_id;
int wiphy_idx = -1;
int ifidx = -1;
if (!attrs[NL80211_ATTR_IFINDEX]) assert_cfg80211_lock();
return -EINVAL;
ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); if (!have_ifidx && !have_wdev_id)
*dev = dev_get_by_index(netns, ifindex); return ERR_PTR(-EINVAL);
if (!*dev)
return -ENODEV;
*rdev = cfg80211_get_dev_from_ifindex(netns, ifindex); if (have_ifidx)
if (IS_ERR(*rdev)) { ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
dev_put(*dev); if (have_wdev_id) {
return PTR_ERR(*rdev); wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
wiphy_idx = wdev_id >> 32;
} }
return 0; list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
struct wireless_dev *wdev;
if (wiphy_net(&rdev->wiphy) != netns)
continue;
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
continue;
mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (have_ifidx && wdev->netdev &&
wdev->netdev->ifindex == ifidx) {
result = wdev;
break;
}
if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
result = wdev;
break;
}
}
mutex_unlock(&rdev->devlist_mtx);
if (result)
break;
}
if (result)
return result;
return ERR_PTR(-ENODEV);
} }
static struct cfg80211_registered_device * static struct cfg80211_registered_device *
...@@ -79,13 +111,40 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) ...@@ -79,13 +111,40 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
assert_cfg80211_lock(); assert_cfg80211_lock();
if (!attrs[NL80211_ATTR_WIPHY] && if (!attrs[NL80211_ATTR_WIPHY] &&
!attrs[NL80211_ATTR_IFINDEX]) !attrs[NL80211_ATTR_IFINDEX] &&
!attrs[NL80211_ATTR_WDEV])
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (attrs[NL80211_ATTR_WIPHY]) if (attrs[NL80211_ATTR_WIPHY])
rdev = cfg80211_rdev_by_wiphy_idx( rdev = cfg80211_rdev_by_wiphy_idx(
nla_get_u32(attrs[NL80211_ATTR_WIPHY])); nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
if (attrs[NL80211_ATTR_WDEV]) {
u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
struct wireless_dev *wdev;
bool found = false;
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
if (tmp) {
/* make sure wdev exists */
mutex_lock(&tmp->devlist_mtx);
list_for_each_entry(wdev, &tmp->wdev_list, list) {
if (wdev->identifier != (u32)wdev_id)
continue;
found = true;
break;
}
mutex_unlock(&tmp->devlist_mtx);
if (!found)
tmp = NULL;
if (rdev && tmp != rdev)
return ERR_PTR(-EINVAL);
rdev = tmp;
}
}
if (attrs[NL80211_ATTR_IFINDEX]) { if (attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(netns, ifindex); netdev = dev_get_by_index(netns, ifindex);
...@@ -294,6 +353,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { ...@@ -294,6 +353,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -1674,6 +1734,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, ...@@ -1674,6 +1734,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
struct net_device *dev) struct net_device *dev)
{ {
void *hdr; void *hdr;
u64 wdev_id = (u64)dev->ieee80211_ptr->identifier |
((u64)rdev->wiphy_idx << 32);
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE); hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
if (!hdr) if (!hdr)
...@@ -1684,6 +1746,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, ...@@ -1684,6 +1746,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) || nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) ||
nla_put_u32(msg, NL80211_ATTR_IFTYPE, nla_put_u32(msg, NL80211_ATTR_IFTYPE,
dev->ieee80211_ptr->iftype) || dev->ieee80211_ptr->iftype) ||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id) ||
nla_put_u32(msg, NL80211_ATTR_GENERATION, nla_put_u32(msg, NL80211_ATTR_GENERATION,
rdev->devlist_generation ^ rdev->devlist_generation ^
(cfg80211_rdev_list_generation << 2))) (cfg80211_rdev_list_generation << 2)))
...@@ -1724,7 +1787,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * ...@@ -1724,7 +1787,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if_idx = 0; if_idx = 0;
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (if_idx < if_start) { if (if_idx < if_start) {
if_idx++; if_idx++;
continue; continue;
...@@ -2350,7 +2413,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, ...@@ -2350,7 +2413,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->iftype != NL80211_IFTYPE_AP && if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO) wdev->iftype != NL80211_IFTYPE_P2P_GO)
continue; continue;
...@@ -6660,8 +6723,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, ...@@ -6660,8 +6723,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info) struct genl_info *info)
{ {
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
struct net_device *dev; struct net_device *dev;
int err;
bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
if (rtnl) if (rtnl)
...@@ -6676,21 +6739,39 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, ...@@ -6676,21 +6739,39 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
} }
info->user_ptr[0] = rdev; info->user_ptr[0] = rdev;
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs, mutex_lock(&cfg80211_mutex);
&rdev, &dev); wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
if (err) { info->attrs);
if (IS_ERR(wdev)) {
mutex_unlock(&cfg80211_mutex);
if (rtnl) if (rtnl)
rtnl_unlock(); rtnl_unlock();
return err; return PTR_ERR(wdev);
} }
if (!wdev->netdev) {
mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -EINVAL;
}
dev = wdev->netdev;
rdev = wiphy_to_dev(wdev->wiphy);
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
!netif_running(dev)) { !netif_running(dev)) {
cfg80211_unlock_rdev(rdev); mutex_unlock(&cfg80211_mutex);
dev_put(dev);
if (rtnl) if (rtnl)
rtnl_unlock(); rtnl_unlock();
return -ENETDOWN; return -ENETDOWN;
} }
dev_hold(dev);
cfg80211_lock_rdev(rdev);
mutex_unlock(&cfg80211_mutex);
info->user_ptr[0] = rdev; info->user_ptr[0] = rdev;
info->user_ptr[1] = dev; info->user_ptr[1] = dev;
} }
...@@ -8483,7 +8564,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, ...@@ -8483,7 +8564,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) list_for_each_entry_rcu(wdev, &rdev->wdev_list, list)
cfg80211_mlme_unregister_socket(wdev, notify->pid); cfg80211_mlme_unregister_socket(wdev, notify->pid);
if (rdev->ap_beacons_nlpid == notify->pid) if (rdev->ap_beacons_nlpid == notify->pid)
rdev->ap_beacons_nlpid = 0; rdev->ap_beacons_nlpid = 0;
......
...@@ -51,7 +51,7 @@ static bool cfg80211_is_all_idle(void) ...@@ -51,7 +51,7 @@ static bool cfg80211_is_all_idle(void)
*/ */
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
cfg80211_lock_rdev(rdev); cfg80211_lock_rdev(rdev);
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev); wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false; is_all_idle = false;
...@@ -221,7 +221,7 @@ void cfg80211_conn_work(struct work_struct *work) ...@@ -221,7 +221,7 @@ void cfg80211_conn_work(struct work_struct *work)
cfg80211_lock_rdev(rdev); cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev); wdev_lock(wdev);
if (!netif_running(wdev->netdev)) { if (!netif_running(wdev->netdev)) {
wdev_unlock(wdev); wdev_unlock(wdev);
......
...@@ -793,7 +793,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) ...@@ -793,7 +793,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev); cfg80211_process_wdev_events(wdev);
mutex_unlock(&rdev->devlist_mtx); mutex_unlock(&rdev->devlist_mtx);
...@@ -994,7 +994,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, ...@@ -994,7 +994,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
mutex_lock(&rdev->devlist_mtx); mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->netdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval) if (!wdev->beacon_interval)
continue; continue;
if (wdev->beacon_interval != beacon_int) { if (wdev->beacon_interval != beacon_int) {
...@@ -1050,7 +1050,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, ...@@ -1050,7 +1050,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
break; break;
} }
list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
if (wdev_iter == wdev) if (wdev_iter == wdev)
continue; continue;
if (!netif_running(wdev_iter->netdev)) if (!netif_running(wdev_iter->netdev))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment