diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 20 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 8 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 10 | ||||
-rw-r--r-- | net/ipv6/route.c | 7 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 24 | ||||
-rw-r--r-- | net/netlink/af_netlink.h | 1 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 18 | ||||
-rw-r--r-- | net/sctp/socket.c | 8 | ||||
-rw-r--r-- | net/wireless/reg.c | 56 |
10 files changed, 92 insertions, 62 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 683d493aa1bf..171420e75b03 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -7072,10 +7072,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
7072 | oldsd->output_queue = NULL; | 7072 | oldsd->output_queue = NULL; |
7073 | oldsd->output_queue_tailp = &oldsd->output_queue; | 7073 | oldsd->output_queue_tailp = &oldsd->output_queue; |
7074 | } | 7074 | } |
7075 | /* Append NAPI poll list from offline CPU. */ | 7075 | /* Append NAPI poll list from offline CPU, with one exception : |
7076 | if (!list_empty(&oldsd->poll_list)) { | 7076 | * process_backlog() must be called by cpu owning percpu backlog. |
7077 | list_splice_init(&oldsd->poll_list, &sd->poll_list); | 7077 | * We properly handle process_queue & input_pkt_queue later. |
7078 | raise_softirq_irqoff(NET_RX_SOFTIRQ); | 7078 | */ |
7079 | while (!list_empty(&oldsd->poll_list)) { | ||
7080 | struct napi_struct *napi = list_first_entry(&oldsd->poll_list, | ||
7081 | struct napi_struct, | ||
7082 | poll_list); | ||
7083 | |||
7084 | list_del_init(&napi->poll_list); | ||
7085 | if (napi->poll == process_backlog) | ||
7086 | napi->state = 0; | ||
7087 | else | ||
7088 | ____napi_schedule(sd, napi); | ||
7079 | } | 7089 | } |
7080 | 7090 | ||
7081 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 7091 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
@@ -7086,7 +7096,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
7086 | netif_rx_internal(skb); | 7096 | netif_rx_internal(skb); |
7087 | input_queue_head_incr(oldsd); | 7097 | input_queue_head_incr(oldsd); |
7088 | } | 7098 | } |
7089 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { | 7099 | while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { |
7090 | netif_rx_internal(skb); | 7100 | netif_rx_internal(skb); |
7091 | input_queue_head_incr(oldsd); | 7101 | input_queue_head_incr(oldsd); |
7092 | } | 7102 | } |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 8a89c738b7a3..6b85adb05003 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -461,17 +461,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
461 | 461 | ||
462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
463 | sin = &errhdr.offender; | 463 | sin = &errhdr.offender; |
464 | sin->sin_family = AF_UNSPEC; | 464 | memset(sin, 0, sizeof(*sin)); |
465 | 465 | ||
466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || |
467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { | 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { |
468 | struct inet_sock *inet = inet_sk(sk); | ||
469 | |||
470 | sin->sin_family = AF_INET; | 468 | sin->sin_family = AF_INET; |
471 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 469 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
472 | sin->sin_port = 0; | 470 | if (inet_sk(sk)->cmsg_flags) |
473 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
474 | if (inet->cmsg_flags) | ||
475 | ip_cmsg_recv(msg, skb); | 471 | ip_cmsg_recv(msg, skb); |
476 | } | 472 | } |
477 | 473 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 100c589a2a6c..49f5e73db122 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
393 | 393 | ||
394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
395 | sin = &errhdr.offender; | 395 | sin = &errhdr.offender; |
396 | sin->sin6_family = AF_UNSPEC; | 396 | memset(sin, 0, sizeof(*sin)); |
397 | |||
397 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 398 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
398 | sin->sin6_family = AF_INET6; | 399 | sin->sin6_family = AF_INET6; |
399 | sin->sin6_flowinfo = 0; | ||
400 | sin->sin6_port = 0; | ||
401 | if (np->rxopt.all) { | 400 | if (np->rxopt.all) { |
402 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && | 401 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && |
403 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) | 402 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) |
@@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
412 | ipv6_iface_scope_id(&sin->sin6_addr, | 411 | ipv6_iface_scope_id(&sin->sin6_addr, |
413 | IP6CB(skb)->iif); | 412 | IP6CB(skb)->iif); |
414 | } else { | 413 | } else { |
415 | struct inet_sock *inet = inet_sk(sk); | ||
416 | |||
417 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 414 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
418 | &sin->sin6_addr); | 415 | &sin->sin6_addr); |
419 | sin->sin6_scope_id = 0; | 416 | if (inet_sk(sk)->cmsg_flags) |
420 | if (inet->cmsg_flags) | ||
421 | ip_cmsg_recv(msg, skb); | 417 | ip_cmsg_recv(msg, skb); |
422 | } | 418 | } |
423 | } | 419 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c91083156edb..166e33bed222 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
1160 | struct net *net = dev_net(dst->dev); | 1160 | struct net *net = dev_net(dst->dev); |
1161 | 1161 | ||
1162 | rt6->rt6i_flags |= RTF_MODIFIED; | 1162 | rt6->rt6i_flags |= RTF_MODIFIED; |
1163 | if (mtu < IPV6_MIN_MTU) { | 1163 | if (mtu < IPV6_MIN_MTU) |
1164 | u32 features = dst_metric(dst, RTAX_FEATURES); | ||
1165 | mtu = IPV6_MIN_MTU; | 1164 | mtu = IPV6_MIN_MTU; |
1166 | features |= RTAX_FEATURE_ALLFRAG; | 1165 | |
1167 | dst_metric_set(dst, RTAX_FEATURES, features); | ||
1168 | } | ||
1169 | dst_metric_set(dst, RTAX_MTU, mtu); | 1166 | dst_metric_set(dst, RTAX_MTU, mtu); |
1170 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1167 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1171 | } | 1168 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2c36c4765f47..837a406a9dd6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1643,7 +1643,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata) | |||
1643 | { | 1643 | { |
1644 | struct ieee80211_local *local = sdata->local; | 1644 | struct ieee80211_local *local = sdata->local; |
1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1646 | bool ret; | 1646 | bool ret = false; |
1647 | int ac; | 1647 | int ac; |
1648 | 1648 | ||
1649 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1649 | if (local->hw.queues < IEEE80211_NUM_ACS) |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 84ea76ca3f1f..02fdde28dada 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/rhashtable.h> | 61 | #include <linux/rhashtable.h> |
62 | #include <asm/cacheflush.h> | 62 | #include <asm/cacheflush.h> |
63 | #include <linux/hash.h> | 63 | #include <linux/hash.h> |
64 | #include <linux/genetlink.h> | ||
64 | 65 | ||
65 | #include <net/net_namespace.h> | 66 | #include <net/net_namespace.h> |
66 | #include <net/sock.h> | 67 | #include <net/sock.h> |
@@ -1095,6 +1096,8 @@ static void netlink_remove(struct sock *sk) | |||
1095 | __sk_del_bind_node(sk); | 1096 | __sk_del_bind_node(sk); |
1096 | netlink_update_listeners(sk); | 1097 | netlink_update_listeners(sk); |
1097 | } | 1098 | } |
1099 | if (sk->sk_protocol == NETLINK_GENERIC) | ||
1100 | atomic_inc(&genl_sk_destructing_cnt); | ||
1098 | netlink_table_ungrab(); | 1101 | netlink_table_ungrab(); |
1099 | } | 1102 | } |
1100 | 1103 | ||
@@ -1211,6 +1214,20 @@ static int netlink_release(struct socket *sock) | |||
1211 | * will be purged. | 1214 | * will be purged. |
1212 | */ | 1215 | */ |
1213 | 1216 | ||
1217 | /* must not acquire netlink_table_lock in any way again before unbind | ||
1218 | * and notifying genetlink is done as otherwise it might deadlock | ||
1219 | */ | ||
1220 | if (nlk->netlink_unbind) { | ||
1221 | int i; | ||
1222 | |||
1223 | for (i = 0; i < nlk->ngroups; i++) | ||
1224 | if (test_bit(i, nlk->groups)) | ||
1225 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
1226 | } | ||
1227 | if (sk->sk_protocol == NETLINK_GENERIC && | ||
1228 | atomic_dec_return(&genl_sk_destructing_cnt) == 0) | ||
1229 | wake_up(&genl_sk_destructing_waitq); | ||
1230 | |||
1214 | sock->sk = NULL; | 1231 | sock->sk = NULL; |
1215 | wake_up_interruptible_all(&nlk->wait); | 1232 | wake_up_interruptible_all(&nlk->wait); |
1216 | 1233 | ||
@@ -1246,13 +1263,6 @@ static int netlink_release(struct socket *sock) | |||
1246 | netlink_table_ungrab(); | 1263 | netlink_table_ungrab(); |
1247 | } | 1264 | } |
1248 | 1265 | ||
1249 | if (nlk->netlink_unbind) { | ||
1250 | int i; | ||
1251 | |||
1252 | for (i = 0; i < nlk->ngroups; i++) | ||
1253 | if (test_bit(i, nlk->groups)) | ||
1254 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
1255 | } | ||
1256 | kfree(nlk->groups); | 1266 | kfree(nlk->groups); |
1257 | nlk->groups = NULL; | 1267 | nlk->groups = NULL; |
1258 | 1268 | ||
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index f123a88496f8..f1c31b39aa3e 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
3 | 3 | ||
4 | #include <linux/rhashtable.h> | 4 | #include <linux/rhashtable.h> |
5 | #include <linux/atomic.h> | ||
5 | #include <net/sock.h> | 6 | #include <net/sock.h> |
6 | 7 | ||
7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 8 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 2e11061ef885..ee57459fc258 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -23,6 +23,9 @@ | |||
23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
24 | static DECLARE_RWSEM(cb_lock); | 24 | static DECLARE_RWSEM(cb_lock); |
25 | 25 | ||
26 | atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0); | ||
27 | DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq); | ||
28 | |||
26 | void genl_lock(void) | 29 | void genl_lock(void) |
27 | { | 30 | { |
28 | mutex_lock(&genl_mutex); | 31 | mutex_lock(&genl_mutex); |
@@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family) | |||
435 | 438 | ||
436 | genl_lock_all(); | 439 | genl_lock_all(); |
437 | 440 | ||
438 | genl_unregister_mc_groups(family); | ||
439 | |||
440 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { | 441 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { |
441 | if (family->id != rc->id || strcmp(rc->name, family->name)) | 442 | if (family->id != rc->id || strcmp(rc->name, family->name)) |
442 | continue; | 443 | continue; |
443 | 444 | ||
445 | genl_unregister_mc_groups(family); | ||
446 | |||
444 | list_del(&rc->family_list); | 447 | list_del(&rc->family_list); |
445 | family->n_ops = 0; | 448 | family->n_ops = 0; |
446 | genl_unlock_all(); | 449 | up_write(&cb_lock); |
450 | wait_event(genl_sk_destructing_waitq, | ||
451 | atomic_read(&genl_sk_destructing_cnt) == 0); | ||
452 | genl_unlock(); | ||
447 | 453 | ||
448 | kfree(family->attrbuf); | 454 | kfree(family->attrbuf); |
449 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); | 455 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); |
@@ -985,7 +991,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
985 | 991 | ||
986 | static int genl_bind(struct net *net, int group) | 992 | static int genl_bind(struct net *net, int group) |
987 | { | 993 | { |
988 | int i, err = 0; | 994 | int i, err = -ENOENT; |
989 | 995 | ||
990 | down_read(&cb_lock); | 996 | down_read(&cb_lock); |
991 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 997 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
@@ -1014,7 +1020,6 @@ static int genl_bind(struct net *net, int group) | |||
1014 | static void genl_unbind(struct net *net, int group) | 1020 | static void genl_unbind(struct net *net, int group) |
1015 | { | 1021 | { |
1016 | int i; | 1022 | int i; |
1017 | bool found = false; | ||
1018 | 1023 | ||
1019 | down_read(&cb_lock); | 1024 | down_read(&cb_lock); |
1020 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 1025 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
@@ -1027,14 +1032,11 @@ static void genl_unbind(struct net *net, int group) | |||
1027 | 1032 | ||
1028 | if (f->mcast_unbind) | 1033 | if (f->mcast_unbind) |
1029 | f->mcast_unbind(net, fam_grp); | 1034 | f->mcast_unbind(net, fam_grp); |
1030 | found = true; | ||
1031 | break; | 1035 | break; |
1032 | } | 1036 | } |
1033 | } | 1037 | } |
1034 | } | 1038 | } |
1035 | up_read(&cb_lock); | 1039 | up_read(&cb_lock); |
1036 | |||
1037 | WARN_ON(!found); | ||
1038 | } | 1040 | } |
1039 | 1041 | ||
1040 | static int __net_init genl_pernet_init(struct net *net) | 1042 | static int __net_init genl_pernet_init(struct net *net) |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2625eccb77d5..aafe94bf292e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1603,7 +1603,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1603 | sctp_assoc_t associd = 0; | 1603 | sctp_assoc_t associd = 0; |
1604 | sctp_cmsgs_t cmsgs = { NULL }; | 1604 | sctp_cmsgs_t cmsgs = { NULL }; |
1605 | sctp_scope_t scope; | 1605 | sctp_scope_t scope; |
1606 | bool fill_sinfo_ttl = false; | 1606 | bool fill_sinfo_ttl = false, wait_connect = false; |
1607 | struct sctp_datamsg *datamsg; | 1607 | struct sctp_datamsg *datamsg; |
1608 | int msg_flags = msg->msg_flags; | 1608 | int msg_flags = msg->msg_flags; |
1609 | __u16 sinfo_flags = 0; | 1609 | __u16 sinfo_flags = 0; |
@@ -1943,6 +1943,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1943 | if (err < 0) | 1943 | if (err < 0) |
1944 | goto out_free; | 1944 | goto out_free; |
1945 | 1945 | ||
1946 | wait_connect = true; | ||
1946 | pr_debug("%s: we associated primitively\n", __func__); | 1947 | pr_debug("%s: we associated primitively\n", __func__); |
1947 | } | 1948 | } |
1948 | 1949 | ||
@@ -1980,6 +1981,11 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1980 | sctp_datamsg_put(datamsg); | 1981 | sctp_datamsg_put(datamsg); |
1981 | err = msg_len; | 1982 | err = msg_len; |
1982 | 1983 | ||
1984 | if (unlikely(wait_connect)) { | ||
1985 | timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT); | ||
1986 | sctp_wait_for_connect(asoc, &timeo); | ||
1987 | } | ||
1988 | |||
1983 | /* If we are already past ASSOCIATE, the lower | 1989 | /* If we are already past ASSOCIATE, the lower |
1984 | * layers are responsible for association cleanup. | 1990 | * layers are responsible for association cleanup. |
1985 | */ | 1991 | */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b8309840d4e..d39d1cbc86b1 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1530,45 +1530,40 @@ static void reg_call_notifier(struct wiphy *wiphy, | |||
1530 | 1530 | ||
1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | 1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) |
1532 | { | 1532 | { |
1533 | struct ieee80211_channel *ch; | ||
1534 | struct cfg80211_chan_def chandef; | 1533 | struct cfg80211_chan_def chandef; |
1535 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 1534 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
1536 | bool ret = true; | 1535 | enum nl80211_iftype iftype; |
1537 | 1536 | ||
1538 | wdev_lock(wdev); | 1537 | wdev_lock(wdev); |
1538 | iftype = wdev->iftype; | ||
1539 | 1539 | ||
1540 | /* make sure the interface is active */ | ||
1540 | if (!wdev->netdev || !netif_running(wdev->netdev)) | 1541 | if (!wdev->netdev || !netif_running(wdev->netdev)) |
1541 | goto out; | 1542 | goto wdev_inactive_unlock; |
1542 | 1543 | ||
1543 | switch (wdev->iftype) { | 1544 | switch (iftype) { |
1544 | case NL80211_IFTYPE_AP: | 1545 | case NL80211_IFTYPE_AP: |
1545 | case NL80211_IFTYPE_P2P_GO: | 1546 | case NL80211_IFTYPE_P2P_GO: |
1546 | if (!wdev->beacon_interval) | 1547 | if (!wdev->beacon_interval) |
1547 | goto out; | 1548 | goto wdev_inactive_unlock; |
1548 | 1549 | chandef = wdev->chandef; | |
1549 | ret = cfg80211_reg_can_beacon(wiphy, | ||
1550 | &wdev->chandef, wdev->iftype); | ||
1551 | break; | 1550 | break; |
1552 | case NL80211_IFTYPE_ADHOC: | 1551 | case NL80211_IFTYPE_ADHOC: |
1553 | if (!wdev->ssid_len) | 1552 | if (!wdev->ssid_len) |
1554 | goto out; | 1553 | goto wdev_inactive_unlock; |
1555 | 1554 | chandef = wdev->chandef; | |
1556 | ret = cfg80211_reg_can_beacon(wiphy, | ||
1557 | &wdev->chandef, wdev->iftype); | ||
1558 | break; | 1555 | break; |
1559 | case NL80211_IFTYPE_STATION: | 1556 | case NL80211_IFTYPE_STATION: |
1560 | case NL80211_IFTYPE_P2P_CLIENT: | 1557 | case NL80211_IFTYPE_P2P_CLIENT: |
1561 | if (!wdev->current_bss || | 1558 | if (!wdev->current_bss || |
1562 | !wdev->current_bss->pub.channel) | 1559 | !wdev->current_bss->pub.channel) |
1563 | goto out; | 1560 | goto wdev_inactive_unlock; |
1564 | 1561 | ||
1565 | ch = wdev->current_bss->pub.channel; | 1562 | if (!rdev->ops->get_channel || |
1566 | if (rdev->ops->get_channel && | 1563 | rdev_get_channel(rdev, wdev, &chandef)) |
1567 | !rdev_get_channel(rdev, wdev, &chandef)) | 1564 | cfg80211_chandef_create(&chandef, |
1568 | ret = cfg80211_chandef_usable(wiphy, &chandef, | 1565 | wdev->current_bss->pub.channel, |
1569 | IEEE80211_CHAN_DISABLED); | 1566 | NL80211_CHAN_NO_HT); |
1570 | else | ||
1571 | ret = !(ch->flags & IEEE80211_CHAN_DISABLED); | ||
1572 | break; | 1567 | break; |
1573 | case NL80211_IFTYPE_MONITOR: | 1568 | case NL80211_IFTYPE_MONITOR: |
1574 | case NL80211_IFTYPE_AP_VLAN: | 1569 | case NL80211_IFTYPE_AP_VLAN: |
@@ -1581,9 +1576,26 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
1581 | break; | 1576 | break; |
1582 | } | 1577 | } |
1583 | 1578 | ||
1584 | out: | ||
1585 | wdev_unlock(wdev); | 1579 | wdev_unlock(wdev); |
1586 | return ret; | 1580 | |
1581 | switch (iftype) { | ||
1582 | case NL80211_IFTYPE_AP: | ||
1583 | case NL80211_IFTYPE_P2P_GO: | ||
1584 | case NL80211_IFTYPE_ADHOC: | ||
1585 | return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); | ||
1586 | case NL80211_IFTYPE_STATION: | ||
1587 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1588 | return cfg80211_chandef_usable(wiphy, &chandef, | ||
1589 | IEEE80211_CHAN_DISABLED); | ||
1590 | default: | ||
1591 | break; | ||
1592 | } | ||
1593 | |||
1594 | return true; | ||
1595 | |||
1596 | wdev_inactive_unlock: | ||
1597 | wdev_unlock(wdev); | ||
1598 | return true; | ||
1587 | } | 1599 | } |
1588 | 1600 | ||
1589 | static void reg_leave_invalid_chans(struct wiphy *wiphy) | 1601 | static void reg_leave_invalid_chans(struct wiphy *wiphy) |