diff options
author | David S. Miller <davem@davemloft.net> | 2013-07-01 16:21:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-01 16:21:17 -0400 |
commit | e62bc9e55f75ecb41dac3e68cd4b61f9d9501f72 (patch) | |
tree | 0437bf3c50de5e1b1ef2b9d73cd802223158232a /net | |
parent | fb825a550a1af75323cee9d62d6fb818384c8c95 (diff) | |
parent | 57ed5cd695d7373b8ae0ae9f10fe945e774d58f0 (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says:
====================
Yet one more pull request for wireless updates intended for 3.11...
For the mac80211 bits, Johannes says:
"Here we have a few memory leak fixes related to BSS struct handling
mostly from Ben, including a fix for a more theoretical problem
(associating while a BSS struct times out) from myself, a compilation
warning fix from Arend, mesh fixes from Thomas, tracking the beacon
bitrate (Alex), a bandwidth change event fix (Ilan) and some initial
work for 5/10 MHz channels from Simon."
Regarding the iwlwifi bits, Johannes says:
"Emmanuel removed some unneeded/unsupported module parameters and adds a
Bluetooth 1x1 lookup-table for some upcoming products. From Alex I have
an older patch to add low-power receive support, this depended on a
mac80211 commit that only just came in with the merge from wireless-next
I did. Ilan made beacon timings better, and Eytan added some debug
statements for thermal throttling. I have a few cleanups, a fix for a
long-standing but rare warning, and, arguably the most important patch
here, the firmware API version bump for the 7260/3160 devices."
Also included is a Bluetooth pull -- Gustavo says:
"Here goes a set of patches to 3.11. The biggest work here is from Andre Guedes
on the move of the Discovery to use the new request framework. Other than that
Johan provided a bunch of fixes to the L2CAP code. The rest are just small
fixes and clean ups."
On top of all that, there are a variety of updates and fixes to
brcmfmac, rt2x00, wil6210, ath9k, ath10k, and a few others here and
there. This also includes a pull of the wireless tree, in order to
prevent some merge conflicts.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_core.c | 192 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 71 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 14 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 123 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 4 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 229 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 14 | ||||
-rw-r--r-- | net/mac80211/ht.c | 4 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 65 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 57 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 8 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 35 | ||||
-rw-r--r-- | net/mac80211/rate.c | 8 | ||||
-rw-r--r-- | net/mac80211/scan.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 1 | ||||
-rw-r--r-- | net/mac80211/vht.c | 2 | ||||
-rw-r--r-- | net/wireless/chan.c | 57 | ||||
-rw-r--r-- | net/wireless/core.c | 6 | ||||
-rw-r--r-- | net/wireless/mlme.c | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 287 | ||||
-rw-r--r-- | net/wireless/scan.c | 4 | ||||
-rw-r--r-- | net/wireless/sme.c | 23 | ||||
-rw-r--r-- | net/wireless/sysfs.c | 2 |
26 files changed, 682 insertions, 555 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ace5e55fe5a3..061523eb52a1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -597,7 +597,15 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
597 | struct hci_dev *hdev = req->hdev; | 597 | struct hci_dev *hdev = req->hdev; |
598 | u8 p; | 598 | u8 p; |
599 | 599 | ||
600 | /* Only send HCI_Delete_Stored_Link_Key if it is supported */ | 600 | /* Some Broadcom based Bluetooth controllers do not support the |
601 | * Delete Stored Link Key command. They are clearly indicating its | ||
602 | * absence in the bit mask of supported commands. | ||
603 | * | ||
604 | * Check the supported commands and only if the the command is marked | ||
605 | * as supported send it. If not supported assume that the controller | ||
606 | * does not have actual support for stored link keys which makes this | ||
607 | * command redundant anyway. | ||
608 | */ | ||
601 | if (hdev->commands[6] & 0x80) { | 609 | if (hdev->commands[6] & 0x80) { |
602 | struct hci_cp_delete_stored_link_key cp; | 610 | struct hci_cp_delete_stored_link_key cp; |
603 | 611 | ||
@@ -751,7 +759,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state) | |||
751 | hdev->discovery.state = state; | 759 | hdev->discovery.state = state; |
752 | } | 760 | } |
753 | 761 | ||
754 | static void inquiry_cache_flush(struct hci_dev *hdev) | 762 | void hci_inquiry_cache_flush(struct hci_dev *hdev) |
755 | { | 763 | { |
756 | struct discovery_state *cache = &hdev->discovery; | 764 | struct discovery_state *cache = &hdev->discovery; |
757 | struct inquiry_entry *p, *n; | 765 | struct inquiry_entry *p, *n; |
@@ -964,7 +972,7 @@ int hci_inquiry(void __user *arg) | |||
964 | hci_dev_lock(hdev); | 972 | hci_dev_lock(hdev); |
965 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || | 973 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || |
966 | inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { | 974 | inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { |
967 | inquiry_cache_flush(hdev); | 975 | hci_inquiry_cache_flush(hdev); |
968 | do_inquiry = 1; | 976 | do_inquiry = 1; |
969 | } | 977 | } |
970 | hci_dev_unlock(hdev); | 978 | hci_dev_unlock(hdev); |
@@ -1201,8 +1209,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
1201 | { | 1209 | { |
1202 | BT_DBG("%s %p", hdev->name, hdev); | 1210 | BT_DBG("%s %p", hdev->name, hdev); |
1203 | 1211 | ||
1204 | cancel_work_sync(&hdev->le_scan); | ||
1205 | |||
1206 | cancel_delayed_work(&hdev->power_off); | 1212 | cancel_delayed_work(&hdev->power_off); |
1207 | 1213 | ||
1208 | hci_req_cancel(hdev, ENODEV); | 1214 | hci_req_cancel(hdev, ENODEV); |
@@ -1230,7 +1236,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
1230 | cancel_delayed_work_sync(&hdev->le_scan_disable); | 1236 | cancel_delayed_work_sync(&hdev->le_scan_disable); |
1231 | 1237 | ||
1232 | hci_dev_lock(hdev); | 1238 | hci_dev_lock(hdev); |
1233 | inquiry_cache_flush(hdev); | 1239 | hci_inquiry_cache_flush(hdev); |
1234 | hci_conn_hash_flush(hdev); | 1240 | hci_conn_hash_flush(hdev); |
1235 | hci_dev_unlock(hdev); | 1241 | hci_dev_unlock(hdev); |
1236 | 1242 | ||
@@ -1331,7 +1337,7 @@ int hci_dev_reset(__u16 dev) | |||
1331 | skb_queue_purge(&hdev->cmd_q); | 1337 | skb_queue_purge(&hdev->cmd_q); |
1332 | 1338 | ||
1333 | hci_dev_lock(hdev); | 1339 | hci_dev_lock(hdev); |
1334 | inquiry_cache_flush(hdev); | 1340 | hci_inquiry_cache_flush(hdev); |
1335 | hci_conn_hash_flush(hdev); | 1341 | hci_conn_hash_flush(hdev); |
1336 | hci_dev_unlock(hdev); | 1342 | hci_dev_unlock(hdev); |
1337 | 1343 | ||
@@ -1991,80 +1997,59 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
1991 | return mgmt_device_unblocked(hdev, bdaddr, type); | 1997 | return mgmt_device_unblocked(hdev, bdaddr, type); |
1992 | } | 1998 | } |
1993 | 1999 | ||
1994 | static void le_scan_param_req(struct hci_request *req, unsigned long opt) | 2000 | static void inquiry_complete(struct hci_dev *hdev, u8 status) |
1995 | { | 2001 | { |
1996 | struct le_scan_params *param = (struct le_scan_params *) opt; | 2002 | if (status) { |
1997 | struct hci_cp_le_set_scan_param cp; | 2003 | BT_ERR("Failed to start inquiry: status %d", status); |
1998 | |||
1999 | memset(&cp, 0, sizeof(cp)); | ||
2000 | cp.type = param->type; | ||
2001 | cp.interval = cpu_to_le16(param->interval); | ||
2002 | cp.window = cpu_to_le16(param->window); | ||
2003 | 2004 | ||
2004 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); | 2005 | hci_dev_lock(hdev); |
2005 | } | 2006 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
2006 | 2007 | hci_dev_unlock(hdev); | |
2007 | static void le_scan_enable_req(struct hci_request *req, unsigned long opt) | 2008 | return; |
2008 | { | 2009 | } |
2009 | struct hci_cp_le_set_scan_enable cp; | ||
2010 | |||
2011 | memset(&cp, 0, sizeof(cp)); | ||
2012 | cp.enable = LE_SCAN_ENABLE; | ||
2013 | cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
2014 | |||
2015 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
2016 | } | 2010 | } |
2017 | 2011 | ||
2018 | static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | 2012 | static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status) |
2019 | u16 window, int timeout) | ||
2020 | { | 2013 | { |
2021 | long timeo = msecs_to_jiffies(3000); | 2014 | /* General inquiry access code (GIAC) */ |
2022 | struct le_scan_params param; | 2015 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; |
2016 | struct hci_request req; | ||
2017 | struct hci_cp_inquiry cp; | ||
2023 | int err; | 2018 | int err; |
2024 | 2019 | ||
2025 | BT_DBG("%s", hdev->name); | 2020 | if (status) { |
2026 | 2021 | BT_ERR("Failed to disable LE scanning: status %d", status); | |
2027 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | 2022 | return; |
2028 | return -EINPROGRESS; | 2023 | } |
2029 | |||
2030 | param.type = type; | ||
2031 | param.interval = interval; | ||
2032 | param.window = window; | ||
2033 | |||
2034 | hci_req_lock(hdev); | ||
2035 | |||
2036 | err = __hci_req_sync(hdev, le_scan_param_req, (unsigned long) ¶m, | ||
2037 | timeo); | ||
2038 | if (!err) | ||
2039 | err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo); | ||
2040 | |||
2041 | hci_req_unlock(hdev); | ||
2042 | 2024 | ||
2043 | if (err < 0) | 2025 | switch (hdev->discovery.type) { |
2044 | return err; | 2026 | case DISCOV_TYPE_LE: |
2027 | hci_dev_lock(hdev); | ||
2028 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2029 | hci_dev_unlock(hdev); | ||
2030 | break; | ||
2045 | 2031 | ||
2046 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, | 2032 | case DISCOV_TYPE_INTERLEAVED: |
2047 | timeout); | 2033 | hci_req_init(&req, hdev); |
2048 | 2034 | ||
2049 | return 0; | 2035 | memset(&cp, 0, sizeof(cp)); |
2050 | } | 2036 | memcpy(&cp.lap, lap, sizeof(cp.lap)); |
2037 | cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN; | ||
2038 | hci_req_add(&req, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
2051 | 2039 | ||
2052 | int hci_cancel_le_scan(struct hci_dev *hdev) | 2040 | hci_dev_lock(hdev); |
2053 | { | ||
2054 | BT_DBG("%s", hdev->name); | ||
2055 | 2041 | ||
2056 | if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | 2042 | hci_inquiry_cache_flush(hdev); |
2057 | return -EALREADY; | ||
2058 | 2043 | ||
2059 | if (cancel_delayed_work(&hdev->le_scan_disable)) { | 2044 | err = hci_req_run(&req, inquiry_complete); |
2060 | struct hci_cp_le_set_scan_enable cp; | 2045 | if (err) { |
2046 | BT_ERR("Inquiry request failed: err %d", err); | ||
2047 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2048 | } | ||
2061 | 2049 | ||
2062 | /* Send HCI command to disable LE Scan */ | 2050 | hci_dev_unlock(hdev); |
2063 | memset(&cp, 0, sizeof(cp)); | 2051 | break; |
2064 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
2065 | } | 2052 | } |
2066 | |||
2067 | return 0; | ||
2068 | } | 2053 | } |
2069 | 2054 | ||
2070 | static void le_scan_disable_work(struct work_struct *work) | 2055 | static void le_scan_disable_work(struct work_struct *work) |
@@ -2072,46 +2057,20 @@ static void le_scan_disable_work(struct work_struct *work) | |||
2072 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 2057 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
2073 | le_scan_disable.work); | 2058 | le_scan_disable.work); |
2074 | struct hci_cp_le_set_scan_enable cp; | 2059 | struct hci_cp_le_set_scan_enable cp; |
2060 | struct hci_request req; | ||
2061 | int err; | ||
2075 | 2062 | ||
2076 | BT_DBG("%s", hdev->name); | 2063 | BT_DBG("%s", hdev->name); |
2077 | 2064 | ||
2078 | memset(&cp, 0, sizeof(cp)); | 2065 | hci_req_init(&req, hdev); |
2079 | |||
2080 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
2081 | } | ||
2082 | |||
2083 | static void le_scan_work(struct work_struct *work) | ||
2084 | { | ||
2085 | struct hci_dev *hdev = container_of(work, struct hci_dev, le_scan); | ||
2086 | struct le_scan_params *param = &hdev->le_scan_params; | ||
2087 | 2066 | ||
2088 | BT_DBG("%s", hdev->name); | 2067 | memset(&cp, 0, sizeof(cp)); |
2068 | cp.enable = LE_SCAN_DISABLE; | ||
2069 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
2089 | 2070 | ||
2090 | hci_do_le_scan(hdev, param->type, param->interval, param->window, | 2071 | err = hci_req_run(&req, le_scan_disable_work_complete); |
2091 | param->timeout); | 2072 | if (err) |
2092 | } | 2073 | BT_ERR("Disable LE scanning request failed: err %d", err); |
2093 | |||
2094 | int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window, | ||
2095 | int timeout) | ||
2096 | { | ||
2097 | struct le_scan_params *param = &hdev->le_scan_params; | ||
2098 | |||
2099 | BT_DBG("%s", hdev->name); | ||
2100 | |||
2101 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | ||
2102 | return -ENOTSUPP; | ||
2103 | |||
2104 | if (work_busy(&hdev->le_scan)) | ||
2105 | return -EINPROGRESS; | ||
2106 | |||
2107 | param->type = type; | ||
2108 | param->interval = interval; | ||
2109 | param->window = window; | ||
2110 | param->timeout = timeout; | ||
2111 | |||
2112 | queue_work(system_long_wq, &hdev->le_scan); | ||
2113 | |||
2114 | return 0; | ||
2115 | } | 2074 | } |
2116 | 2075 | ||
2117 | /* Alloc HCI device */ | 2076 | /* Alloc HCI device */ |
@@ -2148,7 +2107,6 @@ struct hci_dev *hci_alloc_dev(void) | |||
2148 | INIT_WORK(&hdev->cmd_work, hci_cmd_work); | 2107 | INIT_WORK(&hdev->cmd_work, hci_cmd_work); |
2149 | INIT_WORK(&hdev->tx_work, hci_tx_work); | 2108 | INIT_WORK(&hdev->tx_work, hci_tx_work); |
2150 | INIT_WORK(&hdev->power_on, hci_power_on); | 2109 | INIT_WORK(&hdev->power_on, hci_power_on); |
2151 | INIT_WORK(&hdev->le_scan, le_scan_work); | ||
2152 | 2110 | ||
2153 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); | 2111 | INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); |
2154 | INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); | 2112 | INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); |
@@ -3551,36 +3509,6 @@ static void hci_cmd_work(struct work_struct *work) | |||
3551 | } | 3509 | } |
3552 | } | 3510 | } |
3553 | 3511 | ||
3554 | int hci_do_inquiry(struct hci_dev *hdev, u8 length) | ||
3555 | { | ||
3556 | /* General inquiry access code (GIAC) */ | ||
3557 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
3558 | struct hci_cp_inquiry cp; | ||
3559 | |||
3560 | BT_DBG("%s", hdev->name); | ||
3561 | |||
3562 | if (test_bit(HCI_INQUIRY, &hdev->flags)) | ||
3563 | return -EINPROGRESS; | ||
3564 | |||
3565 | inquiry_cache_flush(hdev); | ||
3566 | |||
3567 | memset(&cp, 0, sizeof(cp)); | ||
3568 | memcpy(&cp.lap, lap, sizeof(cp.lap)); | ||
3569 | cp.length = length; | ||
3570 | |||
3571 | return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); | ||
3572 | } | ||
3573 | |||
3574 | int hci_cancel_inquiry(struct hci_dev *hdev) | ||
3575 | { | ||
3576 | BT_DBG("%s", hdev->name); | ||
3577 | |||
3578 | if (!test_bit(HCI_INQUIRY, &hdev->flags)) | ||
3579 | return -EALREADY; | ||
3580 | |||
3581 | return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); | ||
3582 | } | ||
3583 | |||
3584 | u8 bdaddr_to_le(u8 bdaddr_type) | 3512 | u8 bdaddr_to_le(u8 bdaddr_type) |
3585 | { | 3513 | { |
3586 | switch (bdaddr_type) { | 3514 | switch (bdaddr_type) { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b93cd2eb5d58..0437200d92f4 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -40,21 +40,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) | |||
40 | 40 | ||
41 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 41 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
42 | 42 | ||
43 | if (status) { | 43 | if (status) |
44 | hci_dev_lock(hdev); | ||
45 | mgmt_stop_discovery_failed(hdev, status); | ||
46 | hci_dev_unlock(hdev); | ||
47 | return; | 44 | return; |
48 | } | ||
49 | 45 | ||
50 | clear_bit(HCI_INQUIRY, &hdev->flags); | 46 | clear_bit(HCI_INQUIRY, &hdev->flags); |
51 | smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ | 47 | smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ |
52 | wake_up_bit(&hdev->flags, HCI_INQUIRY); | 48 | wake_up_bit(&hdev->flags, HCI_INQUIRY); |
53 | 49 | ||
54 | hci_dev_lock(hdev); | ||
55 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
56 | hci_dev_unlock(hdev); | ||
57 | |||
58 | hci_conn_check_pending(hdev); | 50 | hci_conn_check_pending(hdev); |
59 | } | 51 | } |
60 | 52 | ||
@@ -937,20 +929,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
937 | hci_dev_unlock(hdev); | 929 | hci_dev_unlock(hdev); |
938 | } | 930 | } |
939 | 931 | ||
940 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | ||
941 | { | ||
942 | __u8 status = *((__u8 *) skb->data); | ||
943 | |||
944 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
945 | |||
946 | if (status) { | ||
947 | hci_dev_lock(hdev); | ||
948 | mgmt_start_discovery_failed(hdev, status); | ||
949 | hci_dev_unlock(hdev); | ||
950 | return; | ||
951 | } | ||
952 | } | ||
953 | |||
954 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | 932 | static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, |
955 | struct sk_buff *skb) | 933 | struct sk_buff *skb) |
956 | { | 934 | { |
@@ -963,41 +941,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
963 | if (!cp) | 941 | if (!cp) |
964 | return; | 942 | return; |
965 | 943 | ||
944 | if (status) | ||
945 | return; | ||
946 | |||
966 | switch (cp->enable) { | 947 | switch (cp->enable) { |
967 | case LE_SCAN_ENABLE: | 948 | case LE_SCAN_ENABLE: |
968 | if (status) { | ||
969 | hci_dev_lock(hdev); | ||
970 | mgmt_start_discovery_failed(hdev, status); | ||
971 | hci_dev_unlock(hdev); | ||
972 | return; | ||
973 | } | ||
974 | |||
975 | set_bit(HCI_LE_SCAN, &hdev->dev_flags); | 949 | set_bit(HCI_LE_SCAN, &hdev->dev_flags); |
976 | |||
977 | hci_dev_lock(hdev); | ||
978 | hci_discovery_set_state(hdev, DISCOVERY_FINDING); | ||
979 | hci_dev_unlock(hdev); | ||
980 | break; | 950 | break; |
981 | 951 | ||
982 | case LE_SCAN_DISABLE: | 952 | case LE_SCAN_DISABLE: |
983 | if (status) { | ||
984 | hci_dev_lock(hdev); | ||
985 | mgmt_stop_discovery_failed(hdev, status); | ||
986 | hci_dev_unlock(hdev); | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | 953 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); |
991 | |||
992 | if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && | ||
993 | hdev->discovery.state == DISCOVERY_FINDING) { | ||
994 | mgmt_interleaved_discovery(hdev); | ||
995 | } else { | ||
996 | hci_dev_lock(hdev); | ||
997 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
998 | hci_dev_unlock(hdev); | ||
999 | } | ||
1000 | |||
1001 | break; | 954 | break; |
1002 | 955 | ||
1003 | default: | 956 | default: |
@@ -1077,18 +1030,10 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
1077 | 1030 | ||
1078 | if (status) { | 1031 | if (status) { |
1079 | hci_conn_check_pending(hdev); | 1032 | hci_conn_check_pending(hdev); |
1080 | hci_dev_lock(hdev); | ||
1081 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
1082 | mgmt_start_discovery_failed(hdev, status); | ||
1083 | hci_dev_unlock(hdev); | ||
1084 | return; | 1033 | return; |
1085 | } | 1034 | } |
1086 | 1035 | ||
1087 | set_bit(HCI_INQUIRY, &hdev->flags); | 1036 | set_bit(HCI_INQUIRY, &hdev->flags); |
1088 | |||
1089 | hci_dev_lock(hdev); | ||
1090 | hci_discovery_set_state(hdev, DISCOVERY_FINDING); | ||
1091 | hci_dev_unlock(hdev); | ||
1092 | } | 1037 | } |
1093 | 1038 | ||
1094 | static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | 1039 | static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) |
@@ -2298,10 +2243,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2298 | hci_cc_user_passkey_neg_reply(hdev, skb); | 2243 | hci_cc_user_passkey_neg_reply(hdev, skb); |
2299 | break; | 2244 | break; |
2300 | 2245 | ||
2301 | case HCI_OP_LE_SET_SCAN_PARAM: | ||
2302 | hci_cc_le_set_scan_param(hdev, skb); | ||
2303 | break; | ||
2304 | |||
2305 | case HCI_OP_LE_SET_ADV_ENABLE: | 2246 | case HCI_OP_LE_SET_ADV_ENABLE: |
2306 | hci_cc_le_set_adv_enable(hdev, skb); | 2247 | hci_cc_le_set_adv_enable(hdev, skb); |
2307 | break; | 2248 | break; |
@@ -2670,7 +2611,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2670 | 2611 | ||
2671 | BT_DBG("%s", hdev->name); | 2612 | BT_DBG("%s", hdev->name); |
2672 | 2613 | ||
2673 | if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) | 2614 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
2674 | return; | 2615 | return; |
2675 | 2616 | ||
2676 | hci_dev_lock(hdev); | 2617 | hci_dev_lock(hdev); |
@@ -2746,7 +2687,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2746 | hci_conn_drop(conn); | 2687 | hci_conn_drop(conn); |
2747 | } | 2688 | } |
2748 | 2689 | ||
2749 | if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) | 2690 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
2750 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, | 2691 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, |
2751 | ev->key_type, pin_len); | 2692 | ev->key_type, pin_len); |
2752 | 2693 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 940f5acb6694..f13a8da441a8 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -76,25 +76,19 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo | |||
76 | ci->flags = session->flags; | 76 | ci->flags = session->flags; |
77 | ci->state = BT_CONNECTED; | 77 | ci->state = BT_CONNECTED; |
78 | 78 | ||
79 | ci->vendor = 0x0000; | ||
80 | ci->product = 0x0000; | ||
81 | ci->version = 0x0000; | ||
82 | |||
83 | if (session->input) { | 79 | if (session->input) { |
84 | ci->vendor = session->input->id.vendor; | 80 | ci->vendor = session->input->id.vendor; |
85 | ci->product = session->input->id.product; | 81 | ci->product = session->input->id.product; |
86 | ci->version = session->input->id.version; | 82 | ci->version = session->input->id.version; |
87 | if (session->input->name) | 83 | if (session->input->name) |
88 | strncpy(ci->name, session->input->name, 128); | 84 | strlcpy(ci->name, session->input->name, 128); |
89 | else | 85 | else |
90 | strncpy(ci->name, "HID Boot Device", 128); | 86 | strlcpy(ci->name, "HID Boot Device", 128); |
91 | } | 87 | } else if (session->hid) { |
92 | |||
93 | if (session->hid) { | ||
94 | ci->vendor = session->hid->vendor; | 88 | ci->vendor = session->hid->vendor; |
95 | ci->product = session->hid->product; | 89 | ci->product = session->hid->product; |
96 | ci->version = session->hid->version; | 90 | ci->version = session->hid->version; |
97 | strncpy(ci->name, session->hid->name, 128); | 91 | strlcpy(ci->name, session->hid->name, 128); |
98 | } | 92 | } |
99 | } | 93 | } |
100 | 94 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4be6a264b475..8c3499bec893 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -504,8 +504,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
504 | if (conn->hcon->type == LE_LINK) { | 504 | if (conn->hcon->type == LE_LINK) { |
505 | /* LE connection */ | 505 | /* LE connection */ |
506 | chan->omtu = L2CAP_DEFAULT_MTU; | 506 | chan->omtu = L2CAP_DEFAULT_MTU; |
507 | chan->scid = L2CAP_CID_LE_DATA; | 507 | if (chan->dcid == L2CAP_CID_ATT) |
508 | chan->dcid = L2CAP_CID_LE_DATA; | 508 | chan->scid = L2CAP_CID_ATT; |
509 | else | ||
510 | chan->scid = l2cap_alloc_cid(conn); | ||
509 | } else { | 511 | } else { |
510 | /* Alloc CID for connection-oriented socket */ | 512 | /* Alloc CID for connection-oriented socket */ |
511 | chan->scid = l2cap_alloc_cid(conn); | 513 | chan->scid = l2cap_alloc_cid(conn); |
@@ -543,6 +545,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
543 | 545 | ||
544 | l2cap_chan_hold(chan); | 546 | l2cap_chan_hold(chan); |
545 | 547 | ||
548 | hci_conn_hold(conn->hcon); | ||
549 | |||
546 | list_add(&chan->list, &conn->chan_l); | 550 | list_add(&chan->list, &conn->chan_l); |
547 | } | 551 | } |
548 | 552 | ||
@@ -1338,17 +1342,21 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, | |||
1338 | 1342 | ||
1339 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 1343 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
1340 | { | 1344 | { |
1341 | struct sock *parent, *sk; | 1345 | struct sock *parent; |
1342 | struct l2cap_chan *chan, *pchan; | 1346 | struct l2cap_chan *chan, *pchan; |
1343 | 1347 | ||
1344 | BT_DBG(""); | 1348 | BT_DBG(""); |
1345 | 1349 | ||
1346 | /* Check if we have socket listening on cid */ | 1350 | /* Check if we have socket listening on cid */ |
1347 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, | 1351 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, |
1348 | conn->src, conn->dst); | 1352 | conn->src, conn->dst); |
1349 | if (!pchan) | 1353 | if (!pchan) |
1350 | return; | 1354 | return; |
1351 | 1355 | ||
1356 | /* Client ATT sockets should override the server one */ | ||
1357 | if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) | ||
1358 | return; | ||
1359 | |||
1352 | parent = pchan->sk; | 1360 | parent = pchan->sk; |
1353 | 1361 | ||
1354 | lock_sock(parent); | 1362 | lock_sock(parent); |
@@ -1357,17 +1365,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1357 | if (!chan) | 1365 | if (!chan) |
1358 | goto clean; | 1366 | goto clean; |
1359 | 1367 | ||
1360 | sk = chan->sk; | 1368 | chan->dcid = L2CAP_CID_ATT; |
1361 | 1369 | ||
1362 | hci_conn_hold(conn->hcon); | 1370 | bacpy(&bt_sk(chan->sk)->src, conn->src); |
1363 | conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; | 1371 | bacpy(&bt_sk(chan->sk)->dst, conn->dst); |
1364 | 1372 | ||
1365 | bacpy(&bt_sk(sk)->src, conn->src); | 1373 | __l2cap_chan_add(conn, chan); |
1366 | bacpy(&bt_sk(sk)->dst, conn->dst); | ||
1367 | |||
1368 | l2cap_chan_add(conn, chan); | ||
1369 | |||
1370 | l2cap_chan_ready(chan); | ||
1371 | 1374 | ||
1372 | clean: | 1375 | clean: |
1373 | release_sock(parent); | 1376 | release_sock(parent); |
@@ -1380,14 +1383,17 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
1380 | 1383 | ||
1381 | BT_DBG("conn %p", conn); | 1384 | BT_DBG("conn %p", conn); |
1382 | 1385 | ||
1383 | if (!hcon->out && hcon->type == LE_LINK) | 1386 | /* For outgoing pairing which doesn't necessarily have an |
1384 | l2cap_le_conn_ready(conn); | 1387 | * associated socket (e.g. mgmt_pair_device). |
1385 | 1388 | */ | |
1386 | if (hcon->out && hcon->type == LE_LINK) | 1389 | if (hcon->out && hcon->type == LE_LINK) |
1387 | smp_conn_security(hcon, hcon->pending_sec_level); | 1390 | smp_conn_security(hcon, hcon->pending_sec_level); |
1388 | 1391 | ||
1389 | mutex_lock(&conn->chan_lock); | 1392 | mutex_lock(&conn->chan_lock); |
1390 | 1393 | ||
1394 | if (hcon->type == LE_LINK) | ||
1395 | l2cap_le_conn_ready(conn); | ||
1396 | |||
1391 | list_for_each_entry(chan, &conn->chan_l, list) { | 1397 | list_for_each_entry(chan, &conn->chan_l, list) { |
1392 | 1398 | ||
1393 | l2cap_chan_lock(chan); | 1399 | l2cap_chan_lock(chan); |
@@ -1792,7 +1798,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1792 | 1798 | ||
1793 | auth_type = l2cap_get_auth_type(chan); | 1799 | auth_type = l2cap_get_auth_type(chan); |
1794 | 1800 | ||
1795 | if (chan->dcid == L2CAP_CID_LE_DATA) | 1801 | if (bdaddr_type_is_le(dst_type)) |
1796 | hcon = hci_connect(hdev, LE_LINK, dst, dst_type, | 1802 | hcon = hci_connect(hdev, LE_LINK, dst, dst_type, |
1797 | chan->sec_level, auth_type); | 1803 | chan->sec_level, auth_type); |
1798 | else | 1804 | else |
@@ -1811,16 +1817,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1811 | goto done; | 1817 | goto done; |
1812 | } | 1818 | } |
1813 | 1819 | ||
1814 | if (hcon->type == LE_LINK) { | 1820 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { |
1815 | err = 0; | 1821 | hci_conn_drop(hcon); |
1816 | 1822 | err = -EBUSY; | |
1817 | if (!list_empty(&conn->chan_l)) { | 1823 | goto done; |
1818 | err = -EBUSY; | ||
1819 | hci_conn_drop(hcon); | ||
1820 | } | ||
1821 | |||
1822 | if (err) | ||
1823 | goto done; | ||
1824 | } | 1824 | } |
1825 | 1825 | ||
1826 | /* Update source addr of the socket */ | 1826 | /* Update source addr of the socket */ |
@@ -1830,6 +1830,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1830 | l2cap_chan_add(conn, chan); | 1830 | l2cap_chan_add(conn, chan); |
1831 | l2cap_chan_lock(chan); | 1831 | l2cap_chan_lock(chan); |
1832 | 1832 | ||
1833 | /* l2cap_chan_add takes its own ref so we can drop this one */ | ||
1834 | hci_conn_drop(hcon); | ||
1835 | |||
1833 | l2cap_state_change(chan, BT_CONNECT); | 1836 | l2cap_state_change(chan, BT_CONNECT); |
1834 | __set_chan_timer(chan, sk->sk_sndtimeo); | 1837 | __set_chan_timer(chan, sk->sk_sndtimeo); |
1835 | 1838 | ||
@@ -3751,8 +3754,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3751 | 3754 | ||
3752 | sk = chan->sk; | 3755 | sk = chan->sk; |
3753 | 3756 | ||
3754 | hci_conn_hold(conn->hcon); | ||
3755 | |||
3756 | bacpy(&bt_sk(sk)->src, conn->src); | 3757 | bacpy(&bt_sk(sk)->src, conn->src); |
3757 | bacpy(&bt_sk(sk)->dst, conn->dst); | 3758 | bacpy(&bt_sk(sk)->dst, conn->dst); |
3758 | chan->psm = psm; | 3759 | chan->psm = psm; |
@@ -4333,7 +4334,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, | |||
4333 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; | 4334 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; |
4334 | u16 type, result; | 4335 | u16 type, result; |
4335 | 4336 | ||
4336 | if (cmd_len != sizeof(*rsp)) | 4337 | if (cmd_len < sizeof(*rsp)) |
4337 | return -EPROTO; | 4338 | return -EPROTO; |
4338 | 4339 | ||
4339 | type = __le16_to_cpu(rsp->type); | 4340 | type = __le16_to_cpu(rsp->type); |
@@ -5292,6 +5293,51 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | |||
5292 | } | 5293 | } |
5293 | } | 5294 | } |
5294 | 5295 | ||
5296 | static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, | ||
5297 | struct sk_buff *skb) | ||
5298 | { | ||
5299 | u8 *data = skb->data; | ||
5300 | int len = skb->len; | ||
5301 | struct l2cap_cmd_hdr cmd; | ||
5302 | int err; | ||
5303 | |||
5304 | l2cap_raw_recv(conn, skb); | ||
5305 | |||
5306 | while (len >= L2CAP_CMD_HDR_SIZE) { | ||
5307 | u16 cmd_len; | ||
5308 | memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); | ||
5309 | data += L2CAP_CMD_HDR_SIZE; | ||
5310 | len -= L2CAP_CMD_HDR_SIZE; | ||
5311 | |||
5312 | cmd_len = le16_to_cpu(cmd.len); | ||
5313 | |||
5314 | BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, | ||
5315 | cmd.ident); | ||
5316 | |||
5317 | if (cmd_len > len || !cmd.ident) { | ||
5318 | BT_DBG("corrupted command"); | ||
5319 | break; | ||
5320 | } | ||
5321 | |||
5322 | err = l2cap_le_sig_cmd(conn, &cmd, data); | ||
5323 | if (err) { | ||
5324 | struct l2cap_cmd_rej_unk rej; | ||
5325 | |||
5326 | BT_ERR("Wrong link type (%d)", err); | ||
5327 | |||
5328 | /* FIXME: Map err to a valid reason */ | ||
5329 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | ||
5330 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, | ||
5331 | sizeof(rej), &rej); | ||
5332 | } | ||
5333 | |||
5334 | data += cmd_len; | ||
5335 | len -= cmd_len; | ||
5336 | } | ||
5337 | |||
5338 | kfree_skb(skb); | ||
5339 | } | ||
5340 | |||
5295 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, | 5341 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, |
5296 | struct sk_buff *skb) | 5342 | struct sk_buff *skb) |
5297 | { | 5343 | { |
@@ -5318,11 +5364,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
5318 | break; | 5364 | break; |
5319 | } | 5365 | } |
5320 | 5366 | ||
5321 | if (conn->hcon->type == LE_LINK) | 5367 | err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); |
5322 | err = l2cap_le_sig_cmd(conn, &cmd, data); | ||
5323 | else | ||
5324 | err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); | ||
5325 | |||
5326 | if (err) { | 5368 | if (err) { |
5327 | struct l2cap_cmd_rej_unk rej; | 5369 | struct l2cap_cmd_rej_unk rej; |
5328 | 5370 | ||
@@ -6356,16 +6398,13 @@ static void l2cap_att_channel(struct l2cap_conn *conn, | |||
6356 | { | 6398 | { |
6357 | struct l2cap_chan *chan; | 6399 | struct l2cap_chan *chan; |
6358 | 6400 | ||
6359 | chan = l2cap_global_chan_by_scid(0, L2CAP_CID_LE_DATA, | 6401 | chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, |
6360 | conn->src, conn->dst); | 6402 | conn->src, conn->dst); |
6361 | if (!chan) | 6403 | if (!chan) |
6362 | goto drop; | 6404 | goto drop; |
6363 | 6405 | ||
6364 | BT_DBG("chan %p, len %d", chan, skb->len); | 6406 | BT_DBG("chan %p, len %d", chan, skb->len); |
6365 | 6407 | ||
6366 | if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) | ||
6367 | goto drop; | ||
6368 | |||
6369 | if (chan->imtu < skb->len) | 6408 | if (chan->imtu < skb->len) |
6370 | goto drop; | 6409 | goto drop; |
6371 | 6410 | ||
@@ -6395,6 +6434,8 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
6395 | 6434 | ||
6396 | switch (cid) { | 6435 | switch (cid) { |
6397 | case L2CAP_CID_LE_SIGNALING: | 6436 | case L2CAP_CID_LE_SIGNALING: |
6437 | l2cap_le_sig_channel(conn, skb); | ||
6438 | break; | ||
6398 | case L2CAP_CID_SIGNALING: | 6439 | case L2CAP_CID_SIGNALING: |
6399 | l2cap_sig_channel(conn, skb); | 6440 | l2cap_sig_channel(conn, skb); |
6400 | break; | 6441 | break; |
@@ -6405,7 +6446,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
6405 | l2cap_conless_channel(conn, psm, skb); | 6446 | l2cap_conless_channel(conn, psm, skb); |
6406 | break; | 6447 | break; |
6407 | 6448 | ||
6408 | case L2CAP_CID_LE_DATA: | 6449 | case L2CAP_CID_ATT: |
6409 | l2cap_att_channel(conn, skb); | 6450 | l2cap_att_channel(conn, skb); |
6410 | break; | 6451 | break; |
6411 | 6452 | ||
@@ -6531,7 +6572,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
6531 | continue; | 6572 | continue; |
6532 | } | 6573 | } |
6533 | 6574 | ||
6534 | if (chan->scid == L2CAP_CID_LE_DATA) { | 6575 | if (chan->scid == L2CAP_CID_ATT) { |
6535 | if (!status && encrypt) { | 6576 | if (!status && encrypt) { |
6536 | chan->sec_level = hcon->sec_level; | 6577 | chan->sec_level = hcon->sec_level; |
6537 | l2cap_chan_ready(chan); | 6578 | l2cap_chan_ready(chan); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 36fed40c162c..0098af80b213 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -466,7 +466,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
466 | static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) | 466 | static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) |
467 | { | 467 | { |
468 | switch (chan->scid) { | 468 | switch (chan->scid) { |
469 | case L2CAP_CID_LE_DATA: | 469 | case L2CAP_CID_ATT: |
470 | if (mtu < L2CAP_LE_MIN_MTU) | 470 | if (mtu < L2CAP_LE_MIN_MTU) |
471 | return false; | 471 | return false; |
472 | break; | 472 | break; |
@@ -630,7 +630,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
630 | conn = chan->conn; | 630 | conn = chan->conn; |
631 | 631 | ||
632 | /*change security for LE channels */ | 632 | /*change security for LE channels */ |
633 | if (chan->scid == L2CAP_CID_LE_DATA) { | 633 | if (chan->scid == L2CAP_CID_ATT) { |
634 | if (!conn->hcon->out) { | 634 | if (!conn->hcon->out) { |
635 | err = -EINVAL; | 635 | err = -EINVAL; |
636 | break; | 636 | break; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f8ecbc70293d..fedc5399d465 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -102,18 +102,6 @@ static const u16 mgmt_events[] = { | |||
102 | MGMT_EV_PASSKEY_NOTIFY, | 102 | MGMT_EV_PASSKEY_NOTIFY, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | /* | ||
106 | * These LE scan and inquiry parameters were chosen according to LE General | ||
107 | * Discovery Procedure specification. | ||
108 | */ | ||
109 | #define LE_SCAN_WIN 0x12 | ||
110 | #define LE_SCAN_INT 0x12 | ||
111 | #define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240) | ||
112 | #define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120) | ||
113 | |||
114 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ | ||
115 | #define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */ | ||
116 | |||
117 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) | 105 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) |
118 | 106 | ||
119 | #define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \ | 107 | #define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \ |
@@ -1748,8 +1736,6 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1748 | 1736 | ||
1749 | hci_link_keys_clear(hdev); | 1737 | hci_link_keys_clear(hdev); |
1750 | 1738 | ||
1751 | set_bit(HCI_LINK_KEYS, &hdev->dev_flags); | ||
1752 | |||
1753 | if (cp->debug_keys) | 1739 | if (cp->debug_keys) |
1754 | set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 1740 | set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); |
1755 | else | 1741 | else |
@@ -2633,28 +2619,72 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2633 | return err; | 2619 | return err; |
2634 | } | 2620 | } |
2635 | 2621 | ||
2636 | int mgmt_interleaved_discovery(struct hci_dev *hdev) | 2622 | static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) |
2637 | { | 2623 | { |
2624 | struct pending_cmd *cmd; | ||
2625 | u8 type; | ||
2638 | int err; | 2626 | int err; |
2639 | 2627 | ||
2640 | BT_DBG("%s", hdev->name); | 2628 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
2641 | 2629 | ||
2642 | hci_dev_lock(hdev); | 2630 | cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); |
2631 | if (!cmd) | ||
2632 | return -ENOENT; | ||
2643 | 2633 | ||
2644 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE); | 2634 | type = hdev->discovery.type; |
2645 | if (err < 0) | ||
2646 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2647 | 2635 | ||
2648 | hci_dev_unlock(hdev); | 2636 | err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), |
2637 | &type, sizeof(type)); | ||
2638 | mgmt_pending_remove(cmd); | ||
2649 | 2639 | ||
2650 | return err; | 2640 | return err; |
2651 | } | 2641 | } |
2652 | 2642 | ||
2643 | static void start_discovery_complete(struct hci_dev *hdev, u8 status) | ||
2644 | { | ||
2645 | BT_DBG("status %d", status); | ||
2646 | |||
2647 | if (status) { | ||
2648 | hci_dev_lock(hdev); | ||
2649 | mgmt_start_discovery_failed(hdev, status); | ||
2650 | hci_dev_unlock(hdev); | ||
2651 | return; | ||
2652 | } | ||
2653 | |||
2654 | hci_dev_lock(hdev); | ||
2655 | hci_discovery_set_state(hdev, DISCOVERY_FINDING); | ||
2656 | hci_dev_unlock(hdev); | ||
2657 | |||
2658 | switch (hdev->discovery.type) { | ||
2659 | case DISCOV_TYPE_LE: | ||
2660 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, | ||
2661 | DISCOV_LE_TIMEOUT); | ||
2662 | break; | ||
2663 | |||
2664 | case DISCOV_TYPE_INTERLEAVED: | ||
2665 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, | ||
2666 | DISCOV_INTERLEAVED_TIMEOUT); | ||
2667 | break; | ||
2668 | |||
2669 | case DISCOV_TYPE_BREDR: | ||
2670 | break; | ||
2671 | |||
2672 | default: | ||
2673 | BT_ERR("Invalid discovery type %d", hdev->discovery.type); | ||
2674 | } | ||
2675 | } | ||
2676 | |||
2653 | static int start_discovery(struct sock *sk, struct hci_dev *hdev, | 2677 | static int start_discovery(struct sock *sk, struct hci_dev *hdev, |
2654 | void *data, u16 len) | 2678 | void *data, u16 len) |
2655 | { | 2679 | { |
2656 | struct mgmt_cp_start_discovery *cp = data; | 2680 | struct mgmt_cp_start_discovery *cp = data; |
2657 | struct pending_cmd *cmd; | 2681 | struct pending_cmd *cmd; |
2682 | struct hci_cp_le_set_scan_param param_cp; | ||
2683 | struct hci_cp_le_set_scan_enable enable_cp; | ||
2684 | struct hci_cp_inquiry inq_cp; | ||
2685 | struct hci_request req; | ||
2686 | /* General inquiry access code (GIAC) */ | ||
2687 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | ||
2658 | int err; | 2688 | int err; |
2659 | 2689 | ||
2660 | BT_DBG("%s", hdev->name); | 2690 | BT_DBG("%s", hdev->name); |
@@ -2687,6 +2717,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2687 | 2717 | ||
2688 | hdev->discovery.type = cp->type; | 2718 | hdev->discovery.type = cp->type; |
2689 | 2719 | ||
2720 | hci_req_init(&req, hdev); | ||
2721 | |||
2690 | switch (hdev->discovery.type) { | 2722 | switch (hdev->discovery.type) { |
2691 | case DISCOV_TYPE_BREDR: | 2723 | case DISCOV_TYPE_BREDR: |
2692 | if (!lmp_bredr_capable(hdev)) { | 2724 | if (!lmp_bredr_capable(hdev)) { |
@@ -2696,10 +2728,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2696 | goto failed; | 2728 | goto failed; |
2697 | } | 2729 | } |
2698 | 2730 | ||
2699 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | 2731 | if (test_bit(HCI_INQUIRY, &hdev->flags)) { |
2732 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | ||
2733 | MGMT_STATUS_BUSY); | ||
2734 | mgmt_pending_remove(cmd); | ||
2735 | goto failed; | ||
2736 | } | ||
2737 | |||
2738 | hci_inquiry_cache_flush(hdev); | ||
2739 | |||
2740 | memset(&inq_cp, 0, sizeof(inq_cp)); | ||
2741 | memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap)); | ||
2742 | inq_cp.length = DISCOV_BREDR_INQUIRY_LEN; | ||
2743 | hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp); | ||
2700 | break; | 2744 | break; |
2701 | 2745 | ||
2702 | case DISCOV_TYPE_LE: | 2746 | case DISCOV_TYPE_LE: |
2747 | case DISCOV_TYPE_INTERLEAVED: | ||
2703 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 2748 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
2704 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 2749 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2705 | MGMT_STATUS_NOT_SUPPORTED); | 2750 | MGMT_STATUS_NOT_SUPPORTED); |
@@ -2707,20 +2752,40 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2707 | goto failed; | 2752 | goto failed; |
2708 | } | 2753 | } |
2709 | 2754 | ||
2710 | err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT, | 2755 | if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && |
2711 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | 2756 | !lmp_bredr_capable(hdev)) { |
2712 | break; | ||
2713 | |||
2714 | case DISCOV_TYPE_INTERLEAVED: | ||
2715 | if (!lmp_host_le_capable(hdev) || !lmp_bredr_capable(hdev)) { | ||
2716 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 2757 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2717 | MGMT_STATUS_NOT_SUPPORTED); | 2758 | MGMT_STATUS_NOT_SUPPORTED); |
2718 | mgmt_pending_remove(cmd); | 2759 | mgmt_pending_remove(cmd); |
2719 | goto failed; | 2760 | goto failed; |
2720 | } | 2761 | } |
2721 | 2762 | ||
2722 | err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT, | 2763 | if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { |
2723 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE); | 2764 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2765 | MGMT_STATUS_REJECTED); | ||
2766 | mgmt_pending_remove(cmd); | ||
2767 | goto failed; | ||
2768 | } | ||
2769 | |||
2770 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { | ||
2771 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | ||
2772 | MGMT_STATUS_BUSY); | ||
2773 | mgmt_pending_remove(cmd); | ||
2774 | goto failed; | ||
2775 | } | ||
2776 | |||
2777 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
2778 | param_cp.type = LE_SCAN_ACTIVE; | ||
2779 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); | ||
2780 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | ||
2781 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | ||
2782 | ¶m_cp); | ||
2783 | |||
2784 | memset(&enable_cp, 0, sizeof(enable_cp)); | ||
2785 | enable_cp.enable = LE_SCAN_ENABLE; | ||
2786 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
2787 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), | ||
2788 | &enable_cp); | ||
2724 | break; | 2789 | break; |
2725 | 2790 | ||
2726 | default: | 2791 | default: |
@@ -2730,6 +2795,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2730 | goto failed; | 2795 | goto failed; |
2731 | } | 2796 | } |
2732 | 2797 | ||
2798 | err = hci_req_run(&req, start_discovery_complete); | ||
2733 | if (err < 0) | 2799 | if (err < 0) |
2734 | mgmt_pending_remove(cmd); | 2800 | mgmt_pending_remove(cmd); |
2735 | else | 2801 | else |
@@ -2740,6 +2806,39 @@ failed: | |||
2740 | return err; | 2806 | return err; |
2741 | } | 2807 | } |
2742 | 2808 | ||
2809 | static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) | ||
2810 | { | ||
2811 | struct pending_cmd *cmd; | ||
2812 | int err; | ||
2813 | |||
2814 | cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); | ||
2815 | if (!cmd) | ||
2816 | return -ENOENT; | ||
2817 | |||
2818 | err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), | ||
2819 | &hdev->discovery.type, sizeof(hdev->discovery.type)); | ||
2820 | mgmt_pending_remove(cmd); | ||
2821 | |||
2822 | return err; | ||
2823 | } | ||
2824 | |||
2825 | static void stop_discovery_complete(struct hci_dev *hdev, u8 status) | ||
2826 | { | ||
2827 | BT_DBG("status %d", status); | ||
2828 | |||
2829 | hci_dev_lock(hdev); | ||
2830 | |||
2831 | if (status) { | ||
2832 | mgmt_stop_discovery_failed(hdev, status); | ||
2833 | goto unlock; | ||
2834 | } | ||
2835 | |||
2836 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
2837 | |||
2838 | unlock: | ||
2839 | hci_dev_unlock(hdev); | ||
2840 | } | ||
2841 | |||
2743 | static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | 2842 | static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, |
2744 | u16 len) | 2843 | u16 len) |
2745 | { | 2844 | { |
@@ -2747,6 +2846,8 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2747 | struct pending_cmd *cmd; | 2846 | struct pending_cmd *cmd; |
2748 | struct hci_cp_remote_name_req_cancel cp; | 2847 | struct hci_cp_remote_name_req_cancel cp; |
2749 | struct inquiry_entry *e; | 2848 | struct inquiry_entry *e; |
2849 | struct hci_request req; | ||
2850 | struct hci_cp_le_set_scan_enable enable_cp; | ||
2750 | int err; | 2851 | int err; |
2751 | 2852 | ||
2752 | BT_DBG("%s", hdev->name); | 2853 | BT_DBG("%s", hdev->name); |
@@ -2773,12 +2874,20 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2773 | goto unlock; | 2874 | goto unlock; |
2774 | } | 2875 | } |
2775 | 2876 | ||
2877 | hci_req_init(&req, hdev); | ||
2878 | |||
2776 | switch (hdev->discovery.state) { | 2879 | switch (hdev->discovery.state) { |
2777 | case DISCOVERY_FINDING: | 2880 | case DISCOVERY_FINDING: |
2778 | if (test_bit(HCI_INQUIRY, &hdev->flags)) | 2881 | if (test_bit(HCI_INQUIRY, &hdev->flags)) { |
2779 | err = hci_cancel_inquiry(hdev); | 2882 | hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL); |
2780 | else | 2883 | } else { |
2781 | err = hci_cancel_le_scan(hdev); | 2884 | cancel_delayed_work(&hdev->le_scan_disable); |
2885 | |||
2886 | memset(&enable_cp, 0, sizeof(enable_cp)); | ||
2887 | enable_cp.enable = LE_SCAN_DISABLE; | ||
2888 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, | ||
2889 | sizeof(enable_cp), &enable_cp); | ||
2890 | } | ||
2782 | 2891 | ||
2783 | break; | 2892 | break; |
2784 | 2893 | ||
@@ -2796,16 +2905,22 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2796 | } | 2905 | } |
2797 | 2906 | ||
2798 | bacpy(&cp.bdaddr, &e->data.bdaddr); | 2907 | bacpy(&cp.bdaddr, &e->data.bdaddr); |
2799 | err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL, | 2908 | hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), |
2800 | sizeof(cp), &cp); | 2909 | &cp); |
2801 | 2910 | ||
2802 | break; | 2911 | break; |
2803 | 2912 | ||
2804 | default: | 2913 | default: |
2805 | BT_DBG("unknown discovery state %u", hdev->discovery.state); | 2914 | BT_DBG("unknown discovery state %u", hdev->discovery.state); |
2806 | err = -EFAULT; | 2915 | |
2916 | mgmt_pending_remove(cmd); | ||
2917 | err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, | ||
2918 | MGMT_STATUS_FAILED, &mgmt_cp->type, | ||
2919 | sizeof(mgmt_cp->type)); | ||
2920 | goto unlock; | ||
2807 | } | 2921 | } |
2808 | 2922 | ||
2923 | err = hci_req_run(&req, stop_discovery_complete); | ||
2809 | if (err < 0) | 2924 | if (err < 0) |
2810 | mgmt_pending_remove(cmd); | 2925 | mgmt_pending_remove(cmd); |
2811 | else | 2926 | else |
@@ -4063,6 +4178,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
4063 | struct mgmt_ev_device_found *ev = (void *) buf; | 4178 | struct mgmt_ev_device_found *ev = (void *) buf; |
4064 | size_t ev_size; | 4179 | size_t ev_size; |
4065 | 4180 | ||
4181 | if (!hci_discovery_active(hdev)) | ||
4182 | return -EPERM; | ||
4183 | |||
4066 | /* Leave 5 bytes for a potential CoD field */ | 4184 | /* Leave 5 bytes for a potential CoD field */ |
4067 | if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) | 4185 | if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) |
4068 | return -EINVAL; | 4186 | return -EINVAL; |
@@ -4114,43 +4232,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
4114 | sizeof(*ev) + eir_len, NULL); | 4232 | sizeof(*ev) + eir_len, NULL); |
4115 | } | 4233 | } |
4116 | 4234 | ||
4117 | int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) | ||
4118 | { | ||
4119 | struct pending_cmd *cmd; | ||
4120 | u8 type; | ||
4121 | int err; | ||
4122 | |||
4123 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
4124 | |||
4125 | cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); | ||
4126 | if (!cmd) | ||
4127 | return -ENOENT; | ||
4128 | |||
4129 | type = hdev->discovery.type; | ||
4130 | |||
4131 | err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), | ||
4132 | &type, sizeof(type)); | ||
4133 | mgmt_pending_remove(cmd); | ||
4134 | |||
4135 | return err; | ||
4136 | } | ||
4137 | |||
4138 | int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) | ||
4139 | { | ||
4140 | struct pending_cmd *cmd; | ||
4141 | int err; | ||
4142 | |||
4143 | cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); | ||
4144 | if (!cmd) | ||
4145 | return -ENOENT; | ||
4146 | |||
4147 | err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), | ||
4148 | &hdev->discovery.type, sizeof(hdev->discovery.type)); | ||
4149 | mgmt_pending_remove(cmd); | ||
4150 | |||
4151 | return err; | ||
4152 | } | ||
4153 | |||
4154 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering) | 4235 | int mgmt_discovering(struct hci_dev *hdev, u8 discovering) |
4155 | { | 4236 | { |
4156 | struct mgmt_ev_discovering ev; | 4237 | struct mgmt_ev_discovering ev; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 082f270b5912..8184d121ff09 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2827,7 +2827,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2827 | !rcu_access_pointer(sdata->bss->beacon)) | 2827 | !rcu_access_pointer(sdata->bss->beacon)) |
2828 | need_offchan = true; | 2828 | need_offchan = true; |
2829 | if (!ieee80211_is_action(mgmt->frame_control) || | 2829 | if (!ieee80211_is_action(mgmt->frame_control) || |
2830 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 2830 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || |
2831 | mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED) | ||
2831 | break; | 2832 | break; |
2832 | rcu_read_lock(); | 2833 | rcu_read_lock(); |
2833 | sta = sta_info_get(sdata, mgmt->da); | 2834 | sta = sta_info_get(sdata, mgmt->da); |
@@ -2930,19 +2931,8 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | |||
2930 | u16 frame_type, bool reg) | 2931 | u16 frame_type, bool reg) |
2931 | { | 2932 | { |
2932 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2933 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2933 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2934 | 2934 | ||
2935 | switch (frame_type) { | 2935 | switch (frame_type) { |
2936 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: | ||
2937 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
2938 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
2939 | |||
2940 | if (reg) | ||
2941 | ifibss->auth_frame_registrations++; | ||
2942 | else | ||
2943 | ifibss->auth_frame_registrations--; | ||
2944 | } | ||
2945 | break; | ||
2946 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: | 2936 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: |
2947 | if (reg) | 2937 | if (reg) |
2948 | local->probe_req_reg++; | 2938 | local->probe_req_reg++; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 75dff338f581..f83534f6a2ee 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -281,13 +281,14 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
281 | sta, tid, WLAN_BACK_RECIPIENT, | 281 | sta, tid, WLAN_BACK_RECIPIENT, |
282 | WLAN_REASON_UNSPECIFIED, true); | 282 | WLAN_REASON_UNSPECIFIED, true); |
283 | 283 | ||
284 | spin_lock_bh(&sta->lock); | ||
285 | |||
284 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; | 286 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; |
285 | if (tid_tx) { | 287 | if (tid_tx) { |
286 | /* | 288 | /* |
287 | * Assign it over to the normal tid_tx array | 289 | * Assign it over to the normal tid_tx array |
288 | * where it "goes live". | 290 | * where it "goes live". |
289 | */ | 291 | */ |
290 | spin_lock_bh(&sta->lock); | ||
291 | 292 | ||
292 | sta->ampdu_mlme.tid_start_tx[tid] = NULL; | 293 | sta->ampdu_mlme.tid_start_tx[tid] = NULL; |
293 | /* could there be a race? */ | 294 | /* could there be a race? */ |
@@ -300,6 +301,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
300 | ieee80211_tx_ba_session_handle_start(sta, tid); | 301 | ieee80211_tx_ba_session_handle_start(sta, tid); |
301 | continue; | 302 | continue; |
302 | } | 303 | } |
304 | spin_unlock_bh(&sta->lock); | ||
303 | 305 | ||
304 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 306 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
305 | if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | 307 | if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index caa4b4f7f6e4..ea7b9c2c7e66 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
81 | 81 | ||
82 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 82 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
83 | 83 | ||
84 | cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); | 84 | chandef = ifibss->chandef; |
85 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | 85 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { |
86 | chandef.width = NL80211_CHAN_WIDTH_20; | 86 | chandef.width = NL80211_CHAN_WIDTH_20; |
87 | chandef.center_freq1 = chan->center_freq; | 87 | chandef.center_freq1 = chan->center_freq; |
@@ -176,6 +176,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
176 | 176 | ||
177 | /* add HT capability and information IEs */ | 177 | /* add HT capability and information IEs */ |
178 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 178 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
179 | chandef.width != NL80211_CHAN_WIDTH_5 && | ||
180 | chandef.width != NL80211_CHAN_WIDTH_10 && | ||
179 | sband->ht_cap.ht_supported) { | 181 | sband->ht_cap.ht_supported) { |
180 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, | 182 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, |
181 | sband->ht_cap.cap); | 183 | sband->ht_cap.cap); |
@@ -298,8 +300,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
298 | tsf, false); | 300 | tsf, false); |
299 | } | 301 | } |
300 | 302 | ||
301 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | 303 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) |
302 | bool auth) | ||
303 | __acquires(RCU) | 304 | __acquires(RCU) |
304 | { | 305 | { |
305 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 306 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -321,20 +322,12 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
321 | /* If it fails, maybe we raced another insertion? */ | 322 | /* If it fails, maybe we raced another insertion? */ |
322 | if (sta_info_insert_rcu(sta)) | 323 | if (sta_info_insert_rcu(sta)) |
323 | return sta_info_get(sdata, addr); | 324 | return sta_info_get(sdata, addr); |
324 | if (auth && !sdata->u.ibss.auth_frame_registrations) { | ||
325 | ibss_dbg(sdata, | ||
326 | "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", | ||
327 | sdata->vif.addr, addr, sdata->u.ibss.bssid); | ||
328 | ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0, | ||
329 | addr, sdata->u.ibss.bssid, NULL, 0, 0, 0); | ||
330 | } | ||
331 | return sta; | 325 | return sta; |
332 | } | 326 | } |
333 | 327 | ||
334 | static struct sta_info * | 328 | static struct sta_info * |
335 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 329 | ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, |
336 | const u8 *bssid, const u8 *addr, | 330 | const u8 *addr, u32 supp_rates) |
337 | u32 supp_rates, bool auth) | ||
338 | __acquires(RCU) | 331 | __acquires(RCU) |
339 | { | 332 | { |
340 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 333 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
@@ -385,7 +378,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
385 | sta->sta.supp_rates[band] = supp_rates | | 378 | sta->sta.supp_rates[band] = supp_rates | |
386 | ieee80211_mandatory_rates(sband); | 379 | ieee80211_mandatory_rates(sband); |
387 | 380 | ||
388 | return ieee80211_ibss_finish_sta(sta, auth); | 381 | return ieee80211_ibss_finish_sta(sta); |
389 | } | 382 | } |
390 | 383 | ||
391 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, | 384 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -407,8 +400,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
407 | size_t len) | 400 | size_t len) |
408 | { | 401 | { |
409 | u16 auth_alg, auth_transaction; | 402 | u16 auth_alg, auth_transaction; |
410 | struct sta_info *sta; | ||
411 | u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
412 | 403 | ||
413 | sdata_assert_lock(sdata); | 404 | sdata_assert_lock(sdata); |
414 | 405 | ||
@@ -425,22 +416,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
425 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | 416 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) |
426 | return; | 417 | return; |
427 | 418 | ||
428 | sta_info_destroy_addr(sdata, mgmt->sa); | ||
429 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | ||
430 | rcu_read_unlock(); | ||
431 | |||
432 | /* | ||
433 | * if we have any problem in allocating the new station, we reply with a | ||
434 | * DEAUTH frame to tell the other end that we had a problem | ||
435 | */ | ||
436 | if (!sta) { | ||
437 | ieee80211_send_deauth_disassoc(sdata, sdata->u.ibss.bssid, | ||
438 | IEEE80211_STYPE_DEAUTH, | ||
439 | WLAN_REASON_UNSPECIFIED, true, | ||
440 | deauth_frame_buf); | ||
441 | return; | ||
442 | } | ||
443 | |||
444 | /* | 419 | /* |
445 | * IEEE 802.11 standard does not require authentication in IBSS | 420 | * IEEE 802.11 standard does not require authentication in IBSS |
446 | * networks and most implementations do not seem to use it. | 421 | * networks and most implementations do not seem to use it. |
@@ -506,7 +481,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
506 | } else { | 481 | } else { |
507 | rcu_read_unlock(); | 482 | rcu_read_unlock(); |
508 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, | 483 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
509 | mgmt->sa, supp_rates, true); | 484 | mgmt->sa, supp_rates); |
510 | } | 485 | } |
511 | } | 486 | } |
512 | 487 | ||
@@ -514,7 +489,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
514 | set_sta_flag(sta, WLAN_STA_WME); | 489 | set_sta_flag(sta, WLAN_STA_WME); |
515 | 490 | ||
516 | if (sta && elems->ht_operation && elems->ht_cap_elem && | 491 | if (sta && elems->ht_operation && elems->ht_cap_elem && |
517 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { | 492 | sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
493 | sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 && | ||
494 | sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) { | ||
518 | /* we both use HT */ | 495 | /* we both use HT */ |
519 | struct ieee80211_ht_cap htcap_ie; | 496 | struct ieee80211_ht_cap htcap_ie; |
520 | struct cfg80211_chan_def chandef; | 497 | struct cfg80211_chan_def chandef; |
@@ -529,8 +506,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
529 | * fall back to HT20 if we don't use or use | 506 | * fall back to HT20 if we don't use or use |
530 | * the other extension channel | 507 | * the other extension channel |
531 | */ | 508 | */ |
532 | if (cfg80211_get_chandef_type(&chandef) != | 509 | if (chandef.center_freq1 != |
533 | sdata->u.ibss.channel_type) | 510 | sdata->u.ibss.chandef.center_freq1) |
534 | htcap_ie.cap_info &= | 511 | htcap_ie.cap_info &= |
535 | cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40); | 512 | cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40); |
536 | 513 | ||
@@ -569,7 +546,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
569 | 546 | ||
570 | /* different channel */ | 547 | /* different channel */ |
571 | if (sdata->u.ibss.fixed_channel && | 548 | if (sdata->u.ibss.fixed_channel && |
572 | sdata->u.ibss.channel != cbss->channel) | 549 | sdata->u.ibss.chandef.chan != cbss->channel) |
573 | goto put_bss; | 550 | goto put_bss; |
574 | 551 | ||
575 | /* different SSID */ | 552 | /* different SSID */ |
@@ -610,7 +587,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
610 | ieee80211_sta_join_ibss(sdata, bss); | 587 | ieee80211_sta_join_ibss(sdata, bss); |
611 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); | 588 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); |
612 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 589 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
613 | supp_rates, true); | 590 | supp_rates); |
614 | rcu_read_unlock(); | 591 | rcu_read_unlock(); |
615 | } | 592 | } |
616 | 593 | ||
@@ -759,7 +736,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
759 | sdata->drop_unencrypted = 0; | 736 | sdata->drop_unencrypted = 0; |
760 | 737 | ||
761 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, | 738 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
762 | ifibss->channel, ifibss->basic_rates, | 739 | ifibss->chandef.chan, ifibss->basic_rates, |
763 | capability, 0, true); | 740 | capability, 0, true); |
764 | } | 741 | } |
765 | 742 | ||
@@ -791,7 +768,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
791 | if (ifibss->fixed_bssid) | 768 | if (ifibss->fixed_bssid) |
792 | bssid = ifibss->bssid; | 769 | bssid = ifibss->bssid; |
793 | if (ifibss->fixed_channel) | 770 | if (ifibss->fixed_channel) |
794 | chan = ifibss->channel; | 771 | chan = ifibss->chandef.chan; |
795 | if (!is_zero_ether_addr(ifibss->bssid)) | 772 | if (!is_zero_ether_addr(ifibss->bssid)) |
796 | bssid = ifibss->bssid; | 773 | bssid = ifibss->bssid; |
797 | cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, | 774 | cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, |
@@ -982,7 +959,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) | |||
982 | list_del(&sta->list); | 959 | list_del(&sta->list); |
983 | spin_unlock_bh(&ifibss->incomplete_lock); | 960 | spin_unlock_bh(&ifibss->incomplete_lock); |
984 | 961 | ||
985 | ieee80211_ibss_finish_sta(sta, true); | 962 | ieee80211_ibss_finish_sta(sta); |
986 | rcu_read_unlock(); | 963 | rcu_read_unlock(); |
987 | spin_lock_bh(&ifibss->incomplete_lock); | 964 | spin_lock_bh(&ifibss->incomplete_lock); |
988 | } | 965 | } |
@@ -1058,9 +1035,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1058 | 1035 | ||
1059 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 1036 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
1060 | 1037 | ||
1061 | sdata->u.ibss.channel = params->chandef.chan; | 1038 | sdata->u.ibss.chandef = params->chandef; |
1062 | sdata->u.ibss.channel_type = | ||
1063 | cfg80211_get_chandef_type(¶ms->chandef); | ||
1064 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 1039 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
1065 | 1040 | ||
1066 | if (params->ie) { | 1041 | if (params->ie) { |
@@ -1119,7 +1094,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1119 | if (ifibss->privacy) | 1094 | if (ifibss->privacy) |
1120 | capability |= WLAN_CAPABILITY_PRIVACY; | 1095 | capability |= WLAN_CAPABILITY_PRIVACY; |
1121 | 1096 | ||
1122 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel, | 1097 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, |
1123 | ifibss->bssid, ifibss->ssid, | 1098 | ifibss->bssid, ifibss->ssid, |
1124 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | 1099 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | |
1125 | WLAN_CAPABILITY_PRIVACY, | 1100 | WLAN_CAPABILITY_PRIVACY, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f97cd9d9105f..8412a303993a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -94,6 +94,7 @@ struct ieee80211_bss { | |||
94 | #define IEEE80211_MAX_SUPP_RATES 32 | 94 | #define IEEE80211_MAX_SUPP_RATES 32 |
95 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 95 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
96 | size_t supp_rates_len; | 96 | size_t supp_rates_len; |
97 | struct ieee80211_rate *beacon_rate; | ||
97 | 98 | ||
98 | /* | 99 | /* |
99 | * During association, we save an ERP value from a probe response so | 100 | * During association, we save an ERP value from a probe response so |
@@ -497,14 +498,12 @@ struct ieee80211_if_ibss { | |||
497 | bool privacy; | 498 | bool privacy; |
498 | 499 | ||
499 | bool control_port; | 500 | bool control_port; |
500 | unsigned int auth_frame_registrations; | ||
501 | 501 | ||
502 | u8 bssid[ETH_ALEN] __aligned(2); | 502 | u8 bssid[ETH_ALEN] __aligned(2); |
503 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 503 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
504 | u8 ssid_len, ie_len; | 504 | u8 ssid_len, ie_len; |
505 | u8 *ie; | 505 | u8 *ie; |
506 | struct ieee80211_channel *channel; | 506 | struct cfg80211_chan_def chandef; |
507 | enum nl80211_channel_type channel_type; | ||
508 | 507 | ||
509 | unsigned long ibss_join_req; | 508 | unsigned long ibss_join_req; |
510 | /* probe response/beacon for IBSS */ | 509 | /* probe response/beacon for IBSS */ |
@@ -543,6 +542,7 @@ struct ieee80211_if_mesh { | |||
543 | struct timer_list mesh_path_root_timer; | 542 | struct timer_list mesh_path_root_timer; |
544 | 543 | ||
545 | unsigned long wrkq_flags; | 544 | unsigned long wrkq_flags; |
545 | unsigned long mbss_changed; | ||
546 | 546 | ||
547 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 547 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
548 | size_t mesh_id_len; | 548 | size_t mesh_id_len; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6c33af482df4..447f41bbe744 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -161,11 +161,8 @@ void mesh_sta_cleanup(struct sta_info *sta) | |||
161 | del_timer_sync(&sta->plink_timer); | 161 | del_timer_sync(&sta->plink_timer); |
162 | } | 162 | } |
163 | 163 | ||
164 | if (changed) { | 164 | if (changed) |
165 | sdata_lock(sdata); | ||
166 | ieee80211_mbss_info_change_notify(sdata, changed); | 165 | ieee80211_mbss_info_change_notify(sdata, changed); |
167 | sdata_unlock(sdata); | ||
168 | } | ||
169 | } | 166 | } |
170 | 167 | ||
171 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 168 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
@@ -419,7 +416,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, | |||
419 | 416 | ||
420 | sband = local->hw.wiphy->bands[band]; | 417 | sband = local->hw.wiphy->bands[band]; |
421 | if (!sband->ht_cap.ht_supported || | 418 | if (!sband->ht_cap.ht_supported || |
422 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) | 419 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || |
420 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || | ||
421 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) | ||
423 | return 0; | 422 | return 0; |
424 | 423 | ||
425 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | 424 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) |
@@ -719,14 +718,18 @@ ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata) | |||
719 | void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 718 | void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
720 | u32 changed) | 719 | u32 changed) |
721 | { | 720 | { |
722 | if (sdata->vif.bss_conf.enable_beacon && | 721 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
723 | (changed & (BSS_CHANGED_BEACON | | 722 | unsigned long bits = changed; |
724 | BSS_CHANGED_HT | | 723 | u32 bit; |
725 | BSS_CHANGED_BASIC_RATES | | 724 | |
726 | BSS_CHANGED_BEACON_INT))) | 725 | if (!bits) |
727 | if (ieee80211_mesh_rebuild_beacon(sdata)) | 726 | return; |
728 | return; | 727 | |
729 | ieee80211_bss_info_change_notify(sdata, changed); | 728 | /* if we race with running work, worst case this work becomes a noop */ |
729 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) | ||
730 | set_bit(bit, &ifmsh->mbss_changed); | ||
731 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); | ||
732 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | ||
730 | } | 733 | } |
731 | 734 | ||
732 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | 735 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) |
@@ -799,6 +802,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
799 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | 802 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
800 | del_timer_sync(&sdata->u.mesh.mesh_path_timer); | 803 | del_timer_sync(&sdata->u.mesh.mesh_path_timer); |
801 | 804 | ||
805 | /* clear any mesh work (for next join) we may have accrued */ | ||
806 | ifmsh->wrkq_flags = 0; | ||
807 | ifmsh->mbss_changed = 0; | ||
808 | |||
802 | local->fif_other_bss--; | 809 | local->fif_other_bss--; |
803 | atomic_dec(&local->iff_allmultis); | 810 | atomic_dec(&local->iff_allmultis); |
804 | ieee80211_configure_filter(local); | 811 | ieee80211_configure_filter(local); |
@@ -965,6 +972,28 @@ out: | |||
965 | sdata_unlock(sdata); | 972 | sdata_unlock(sdata); |
966 | } | 973 | } |
967 | 974 | ||
975 | static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata) | ||
976 | { | ||
977 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
978 | u32 bit, changed = 0; | ||
979 | |||
980 | for_each_set_bit(bit, &ifmsh->mbss_changed, | ||
981 | sizeof(changed) * BITS_PER_BYTE) { | ||
982 | clear_bit(bit, &ifmsh->mbss_changed); | ||
983 | changed |= BIT(bit); | ||
984 | } | ||
985 | |||
986 | if (sdata->vif.bss_conf.enable_beacon && | ||
987 | (changed & (BSS_CHANGED_BEACON | | ||
988 | BSS_CHANGED_HT | | ||
989 | BSS_CHANGED_BASIC_RATES | | ||
990 | BSS_CHANGED_BEACON_INT))) | ||
991 | if (ieee80211_mesh_rebuild_beacon(sdata)) | ||
992 | return; | ||
993 | |||
994 | ieee80211_bss_info_change_notify(sdata, changed); | ||
995 | } | ||
996 | |||
968 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | 997 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) |
969 | { | 998 | { |
970 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 999 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
@@ -995,6 +1024,8 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
995 | if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) | 1024 | if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) |
996 | mesh_sync_adjust_tbtt(sdata); | 1025 | mesh_sync_adjust_tbtt(sdata); |
997 | 1026 | ||
1027 | if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags)) | ||
1028 | mesh_bss_info_changed(sdata); | ||
998 | out: | 1029 | out: |
999 | sdata_unlock(sdata); | 1030 | sdata_unlock(sdata); |
1000 | } | 1031 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 01a28bca6e9b..2bc7fd2f787d 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -58,6 +58,7 @@ enum mesh_path_flags { | |||
58 | * @MESH_WORK_ROOT: the mesh root station needs to send a frame | 58 | * @MESH_WORK_ROOT: the mesh root station needs to send a frame |
59 | * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other | 59 | * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other |
60 | * mesh nodes | 60 | * mesh nodes |
61 | * @MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes | ||
61 | */ | 62 | */ |
62 | enum mesh_deferred_task_flags { | 63 | enum mesh_deferred_task_flags { |
63 | MESH_WORK_HOUSEKEEPING, | 64 | MESH_WORK_HOUSEKEEPING, |
@@ -65,6 +66,7 @@ enum mesh_deferred_task_flags { | |||
65 | MESH_WORK_GROW_MPP_TABLE, | 66 | MESH_WORK_GROW_MPP_TABLE, |
66 | MESH_WORK_ROOT, | 67 | MESH_WORK_ROOT, |
67 | MESH_WORK_DRIFT_ADJUST, | 68 | MESH_WORK_DRIFT_ADJUST, |
69 | MESH_WORK_MBSS_CHANGED, | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | /** | 72 | /** |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 09bebed99416..02c05fa15c20 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -154,8 +154,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
154 | u16 ht_opmode; | 154 | u16 ht_opmode; |
155 | bool non_ht_sta = false, ht20_sta = false; | 155 | bool non_ht_sta = false, ht20_sta = false; |
156 | 156 | ||
157 | if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) | 157 | switch (sdata->vif.bss_conf.chandef.width) { |
158 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
159 | case NL80211_CHAN_WIDTH_5: | ||
160 | case NL80211_CHAN_WIDTH_10: | ||
158 | return 0; | 161 | return 0; |
162 | default: | ||
163 | break; | ||
164 | } | ||
159 | 165 | ||
160 | rcu_read_lock(); | 166 | rcu_read_lock(); |
161 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 167 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9e49f557fa5c..ae31968d42d3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -190,6 +190,12 @@ static u32 chandef_downgrade(struct cfg80211_chan_def *c) | |||
190 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | 190 | c->width = NL80211_CHAN_WIDTH_20_NOHT; |
191 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | 191 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; |
192 | break; | 192 | break; |
193 | case NL80211_CHAN_WIDTH_5: | ||
194 | case NL80211_CHAN_WIDTH_10: | ||
195 | WARN_ON_ONCE(1); | ||
196 | /* keep c->width */ | ||
197 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
198 | break; | ||
193 | } | 199 | } |
194 | 200 | ||
195 | WARN_ON_ONCE(!cfg80211_chandef_valid(c)); | 201 | WARN_ON_ONCE(!cfg80211_chandef_valid(c)); |
@@ -1779,8 +1785,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1779 | * probably just won't work at all. | 1785 | * probably just won't work at all. |
1780 | */ | 1786 | */ |
1781 | bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; | 1787 | bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; |
1788 | bss_conf->beacon_rate = bss->beacon_rate; | ||
1782 | bss_info_changed |= BSS_CHANGED_BEACON_INFO; | 1789 | bss_info_changed |= BSS_CHANGED_BEACON_INFO; |
1783 | } else { | 1790 | } else { |
1791 | bss_conf->beacon_rate = NULL; | ||
1784 | bss_conf->dtim_period = 0; | 1792 | bss_conf->dtim_period = 0; |
1785 | } | 1793 | } |
1786 | 1794 | ||
@@ -1903,6 +1911,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1903 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1911 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1904 | 1912 | ||
1905 | sdata->vif.bss_conf.dtim_period = 0; | 1913 | sdata->vif.bss_conf.dtim_period = 0; |
1914 | sdata->vif.bss_conf.beacon_rate = NULL; | ||
1915 | |||
1906 | ifmgd->have_beacon = false; | 1916 | ifmgd->have_beacon = false; |
1907 | 1917 | ||
1908 | ifmgd->flags = 0; | 1918 | ifmgd->flags = 0; |
@@ -2785,8 +2795,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2785 | if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { | 2795 | if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { |
2786 | /* oops -- internal error -- send timeout for now */ | 2796 | /* oops -- internal error -- send timeout for now */ |
2787 | ieee80211_destroy_assoc_data(sdata, false); | 2797 | ieee80211_destroy_assoc_data(sdata, false); |
2788 | cfg80211_put_bss(sdata->local->hw.wiphy, bss); | 2798 | cfg80211_assoc_timeout(sdata->dev, bss); |
2789 | cfg80211_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2790 | return; | 2799 | return; |
2791 | } | 2800 | } |
2792 | sdata_info(sdata, "associated\n"); | 2801 | sdata_info(sdata, "associated\n"); |
@@ -2827,8 +2836,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2827 | 2836 | ||
2828 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 2837 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
2829 | channel); | 2838 | channel); |
2830 | if (bss) | 2839 | if (bss) { |
2831 | ieee80211_rx_bss_put(local, bss); | 2840 | ieee80211_rx_bss_put(local, bss); |
2841 | sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; | ||
2842 | } | ||
2832 | 2843 | ||
2833 | if (!sdata->u.mgd.associated || | 2844 | if (!sdata->u.mgd.associated || |
2834 | !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) | 2845 | !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) |
@@ -3501,13 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3501 | time_after(jiffies, ifmgd->assoc_data->timeout)) { | 3512 | time_after(jiffies, ifmgd->assoc_data->timeout)) { |
3502 | if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || | 3513 | if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || |
3503 | ieee80211_do_assoc(sdata)) { | 3514 | ieee80211_do_assoc(sdata)) { |
3504 | u8 bssid[ETH_ALEN]; | 3515 | struct cfg80211_bss *bss = ifmgd->assoc_data->bss; |
3505 | |||
3506 | memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN); | ||
3507 | 3516 | ||
3508 | ieee80211_destroy_assoc_data(sdata, false); | 3517 | ieee80211_destroy_assoc_data(sdata, false); |
3509 | 3518 | cfg80211_assoc_timeout(sdata->dev, bss); | |
3510 | cfg80211_assoc_timeout(sdata->dev, bssid); | ||
3511 | } | 3519 | } |
3512 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) | 3520 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) |
3513 | run_again(sdata, ifmgd->assoc_data->timeout); | 3521 | run_again(sdata, ifmgd->assoc_data->timeout); |
@@ -3838,6 +3846,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3838 | */ | 3846 | */ |
3839 | ret = ieee80211_vif_use_channel(sdata, &chandef, | 3847 | ret = ieee80211_vif_use_channel(sdata, &chandef, |
3840 | IEEE80211_CHANCTX_SHARED); | 3848 | IEEE80211_CHANCTX_SHARED); |
3849 | |||
3850 | /* don't downgrade for 5 and 10 MHz channels, though. */ | ||
3851 | if (chandef.width == NL80211_CHAN_WIDTH_5 || | ||
3852 | chandef.width == NL80211_CHAN_WIDTH_10) | ||
3853 | return ret; | ||
3854 | |||
3841 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { | 3855 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { |
3842 | ifmgd->flags |= chandef_downgrade(&chandef); | 3856 | ifmgd->flags |= chandef_downgrade(&chandef); |
3843 | ret = ieee80211_vif_use_channel(sdata, &chandef, | 3857 | ret = ieee80211_vif_use_channel(sdata, &chandef, |
@@ -4427,8 +4441,11 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) | |||
4427 | cancel_work_sync(&ifmgd->chswitch_work); | 4441 | cancel_work_sync(&ifmgd->chswitch_work); |
4428 | 4442 | ||
4429 | sdata_lock(sdata); | 4443 | sdata_lock(sdata); |
4430 | if (ifmgd->assoc_data) | 4444 | if (ifmgd->assoc_data) { |
4445 | struct cfg80211_bss *bss = ifmgd->assoc_data->bss; | ||
4431 | ieee80211_destroy_assoc_data(sdata, false); | 4446 | ieee80211_destroy_assoc_data(sdata, false); |
4447 | cfg80211_assoc_timeout(sdata->dev, bss); | ||
4448 | } | ||
4432 | if (ifmgd->auth_data) | 4449 | if (ifmgd->auth_data) |
4433 | ieee80211_destroy_auth_data(sdata, false); | 4450 | ieee80211_destroy_auth_data(sdata, false); |
4434 | del_timer_sync(&ifmgd->timer); | 4451 | del_timer_sync(&ifmgd->timer); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index a02bef35b134..30d58d2d13e2 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -397,8 +397,14 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
397 | return; | 397 | return; |
398 | 398 | ||
399 | /* if HT BSS, and we handle a data frame, also try HT rates */ | 399 | /* if HT BSS, and we handle a data frame, also try HT rates */ |
400 | if (chan_width == NL80211_CHAN_WIDTH_20_NOHT) | 400 | switch (chan_width) { |
401 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
402 | case NL80211_CHAN_WIDTH_5: | ||
403 | case NL80211_CHAN_WIDTH_10: | ||
401 | return; | 404 | return; |
405 | default: | ||
406 | break; | ||
407 | } | ||
402 | 408 | ||
403 | alt_rate.idx = 0; | 409 | alt_rate.idx = 0; |
404 | /* keep protection flags */ | 410 | /* keep protection flags */ |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 99b103921a4b..1b122a79b0d8 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -140,6 +140,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
140 | bss->valid_data |= IEEE80211_BSS_VALID_WMM; | 140 | bss->valid_data |= IEEE80211_BSS_VALID_WMM; |
141 | } | 141 | } |
142 | 142 | ||
143 | if (beacon) { | ||
144 | struct ieee80211_supported_band *sband = | ||
145 | local->hw.wiphy->bands[rx_status->band]; | ||
146 | if (!(rx_status->flag & RX_FLAG_HT) && | ||
147 | !(rx_status->flag & RX_FLAG_VHT)) | ||
148 | bss->beacon_rate = | ||
149 | &sband->bitrates[rx_status->rate_idx]; | ||
150 | } | ||
151 | |||
143 | return bss; | 152 | return bss; |
144 | } | 153 | } |
145 | 154 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b4297982d34a..aeb967a0aeed 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -149,6 +149,7 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
149 | * directly by station destruction. | 149 | * directly by station destruction. |
150 | */ | 150 | */ |
151 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 151 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
152 | kfree(sta->ampdu_mlme.tid_start_tx[i]); | ||
152 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); | 153 | tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); |
153 | if (!tid_tx) | 154 | if (!tid_tx) |
154 | continue; | 155 | continue; |
@@ -346,6 +347,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
346 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 347 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
347 | !sdata->u.mesh.user_mpm) | 348 | !sdata->u.mesh.user_mpm) |
348 | init_timer(&sta->plink_timer); | 349 | init_timer(&sta->plink_timer); |
350 | sta->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; | ||
349 | #endif | 351 | #endif |
350 | 352 | ||
351 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 353 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index bd12fc54266c..4208dbd5861f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -203,6 +203,7 @@ struct tid_ampdu_rx { | |||
203 | * driver requested to close until the work for it runs | 203 | * driver requested to close until the work for it runs |
204 | * @mtx: mutex to protect all TX data (except non-NULL assignments | 204 | * @mtx: mutex to protect all TX data (except non-NULL assignments |
205 | * to tid_tx[idx], which are protected by the sta spinlock) | 205 | * to tid_tx[idx], which are protected by the sta spinlock) |
206 | * tid_start_tx is also protected by sta->lock. | ||
206 | */ | 207 | */ |
207 | struct sta_ampdu_mlme { | 208 | struct sta_ampdu_mlme { |
208 | struct mutex mtx; | 209 | struct mutex mtx; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 171344d4eb7c..97c289414e32 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -396,7 +396,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
396 | new_bw = ieee80211_sta_cur_vht_bw(sta); | 396 | new_bw = ieee80211_sta_cur_vht_bw(sta); |
397 | if (new_bw != sta->sta.bandwidth) { | 397 | if (new_bw != sta->sta.bandwidth) { |
398 | sta->sta.bandwidth = new_bw; | 398 | sta->sta.bandwidth = new_bw; |
399 | changed |= IEEE80211_RC_NSS_CHANGED; | 399 | changed |= IEEE80211_RC_BW_CHANGED; |
400 | } | 400 | } |
401 | 401 | ||
402 | change: | 402 | change: |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index fd556ac05fdb..50f6195c8b70 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -54,6 +54,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) | |||
54 | control_freq = chandef->chan->center_freq; | 54 | control_freq = chandef->chan->center_freq; |
55 | 55 | ||
56 | switch (chandef->width) { | 56 | switch (chandef->width) { |
57 | case NL80211_CHAN_WIDTH_5: | ||
58 | case NL80211_CHAN_WIDTH_10: | ||
57 | case NL80211_CHAN_WIDTH_20: | 59 | case NL80211_CHAN_WIDTH_20: |
58 | case NL80211_CHAN_WIDTH_20_NOHT: | 60 | case NL80211_CHAN_WIDTH_20_NOHT: |
59 | if (chandef->center_freq1 != control_freq) | 61 | if (chandef->center_freq1 != control_freq) |
@@ -152,6 +154,12 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c) | |||
152 | int width; | 154 | int width; |
153 | 155 | ||
154 | switch (c->width) { | 156 | switch (c->width) { |
157 | case NL80211_CHAN_WIDTH_5: | ||
158 | width = 5; | ||
159 | break; | ||
160 | case NL80211_CHAN_WIDTH_10: | ||
161 | width = 10; | ||
162 | break; | ||
155 | case NL80211_CHAN_WIDTH_20: | 163 | case NL80211_CHAN_WIDTH_20: |
156 | case NL80211_CHAN_WIDTH_20_NOHT: | 164 | case NL80211_CHAN_WIDTH_20_NOHT: |
157 | width = 20; | 165 | width = 20; |
@@ -194,6 +202,16 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, | |||
194 | if (c1->width == c2->width) | 202 | if (c1->width == c2->width) |
195 | return NULL; | 203 | return NULL; |
196 | 204 | ||
205 | /* | ||
206 | * can't be compatible if one of them is 5 or 10 MHz, | ||
207 | * but they don't have the same width. | ||
208 | */ | ||
209 | if (c1->width == NL80211_CHAN_WIDTH_5 || | ||
210 | c1->width == NL80211_CHAN_WIDTH_10 || | ||
211 | c2->width == NL80211_CHAN_WIDTH_5 || | ||
212 | c2->width == NL80211_CHAN_WIDTH_10) | ||
213 | return NULL; | ||
214 | |||
197 | if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || | 215 | if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || |
198 | c1->width == NL80211_CHAN_WIDTH_20) | 216 | c1->width == NL80211_CHAN_WIDTH_20) |
199 | return c2; | 217 | return c2; |
@@ -264,11 +282,17 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, | |||
264 | u32 bandwidth) | 282 | u32 bandwidth) |
265 | { | 283 | { |
266 | struct ieee80211_channel *c; | 284 | struct ieee80211_channel *c; |
267 | u32 freq; | 285 | u32 freq, start_freq, end_freq; |
286 | |||
287 | if (bandwidth <= 20) { | ||
288 | start_freq = center_freq; | ||
289 | end_freq = center_freq; | ||
290 | } else { | ||
291 | start_freq = center_freq - bandwidth/2 + 10; | ||
292 | end_freq = center_freq + bandwidth/2 - 10; | ||
293 | } | ||
268 | 294 | ||
269 | for (freq = center_freq - bandwidth/2 + 10; | 295 | for (freq = start_freq; freq <= end_freq; freq += 20) { |
270 | freq <= center_freq + bandwidth/2 - 10; | ||
271 | freq += 20) { | ||
272 | c = ieee80211_get_channel(wiphy, freq); | 296 | c = ieee80211_get_channel(wiphy, freq); |
273 | if (!c) | 297 | if (!c) |
274 | return -EINVAL; | 298 | return -EINVAL; |
@@ -310,11 +334,17 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | |||
310 | u32 prohibited_flags) | 334 | u32 prohibited_flags) |
311 | { | 335 | { |
312 | struct ieee80211_channel *c; | 336 | struct ieee80211_channel *c; |
313 | u32 freq; | 337 | u32 freq, start_freq, end_freq; |
338 | |||
339 | if (bandwidth <= 20) { | ||
340 | start_freq = center_freq; | ||
341 | end_freq = center_freq; | ||
342 | } else { | ||
343 | start_freq = center_freq - bandwidth/2 + 10; | ||
344 | end_freq = center_freq + bandwidth/2 - 10; | ||
345 | } | ||
314 | 346 | ||
315 | for (freq = center_freq - bandwidth/2 + 10; | 347 | for (freq = start_freq; freq <= end_freq; freq += 20) { |
316 | freq <= center_freq + bandwidth/2 - 10; | ||
317 | freq += 20) { | ||
318 | c = ieee80211_get_channel(wiphy, freq); | 348 | c = ieee80211_get_channel(wiphy, freq); |
319 | if (!c) | 349 | if (!c) |
320 | return false; | 350 | return false; |
@@ -349,6 +379,12 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, | |||
349 | control_freq = chandef->chan->center_freq; | 379 | control_freq = chandef->chan->center_freq; |
350 | 380 | ||
351 | switch (chandef->width) { | 381 | switch (chandef->width) { |
382 | case NL80211_CHAN_WIDTH_5: | ||
383 | width = 5; | ||
384 | break; | ||
385 | case NL80211_CHAN_WIDTH_10: | ||
386 | width = 10; | ||
387 | break; | ||
352 | case NL80211_CHAN_WIDTH_20: | 388 | case NL80211_CHAN_WIDTH_20: |
353 | if (!ht_cap->ht_supported) | 389 | if (!ht_cap->ht_supported) |
354 | return false; | 390 | return false; |
@@ -405,6 +441,11 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, | |||
405 | if (width > 20) | 441 | if (width > 20) |
406 | prohibited_flags |= IEEE80211_CHAN_NO_OFDM; | 442 | prohibited_flags |= IEEE80211_CHAN_NO_OFDM; |
407 | 443 | ||
444 | /* 5 and 10 MHz are only defined for the OFDM PHY */ | ||
445 | if (width < 20) | ||
446 | prohibited_flags |= IEEE80211_CHAN_NO_OFDM; | ||
447 | |||
448 | |||
408 | if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1, | 449 | if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1, |
409 | width, prohibited_flags)) | 450 | width, prohibited_flags)) |
410 | return false; | 451 | return false; |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f277246080b5..4f9f216665e9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -933,6 +933,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
933 | * freed. | 933 | * freed. |
934 | */ | 934 | */ |
935 | cfg80211_process_wdev_events(wdev); | 935 | cfg80211_process_wdev_events(wdev); |
936 | |||
937 | if (WARN_ON(wdev->current_bss)) { | ||
938 | cfg80211_unhold_bss(wdev->current_bss); | ||
939 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); | ||
940 | wdev->current_bss = NULL; | ||
941 | } | ||
936 | break; | 942 | break; |
937 | case NETDEV_PRE_UP: | 943 | case NETDEV_PRE_UP: |
938 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 944 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index a61a44bc6cf0..bfac5e186f57 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -38,6 +38,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, | |||
38 | * frame instead of reassoc. | 38 | * frame instead of reassoc. |
39 | */ | 39 | */ |
40 | if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { | 40 | if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { |
41 | cfg80211_unhold_bss(bss_from_pub(bss)); | ||
41 | cfg80211_put_bss(wiphy, bss); | 42 | cfg80211_put_bss(wiphy, bss); |
42 | return; | 43 | return; |
43 | } | 44 | } |
@@ -131,16 +132,19 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr) | |||
131 | } | 132 | } |
132 | EXPORT_SYMBOL(cfg80211_auth_timeout); | 133 | EXPORT_SYMBOL(cfg80211_auth_timeout); |
133 | 134 | ||
134 | void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr) | 135 | void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss) |
135 | { | 136 | { |
136 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 137 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
137 | struct wiphy *wiphy = wdev->wiphy; | 138 | struct wiphy *wiphy = wdev->wiphy; |
138 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 139 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
139 | 140 | ||
140 | trace_cfg80211_send_assoc_timeout(dev, addr); | 141 | trace_cfg80211_send_assoc_timeout(dev, bss->bssid); |
141 | 142 | ||
142 | nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); | 143 | nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL); |
143 | cfg80211_sme_assoc_timeout(wdev); | 144 | cfg80211_sme_assoc_timeout(wdev); |
145 | |||
146 | cfg80211_unhold_bss(bss_from_pub(bss)); | ||
147 | cfg80211_put_bss(wiphy, bss); | ||
144 | } | 148 | } |
145 | EXPORT_SYMBOL(cfg80211_assoc_timeout); | 149 | EXPORT_SYMBOL(cfg80211_assoc_timeout); |
146 | 150 | ||
@@ -307,6 +311,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
307 | goto out; | 311 | goto out; |
308 | 312 | ||
309 | err = rdev_assoc(rdev, dev, req); | 313 | err = rdev_assoc(rdev, dev, req); |
314 | if (!err) | ||
315 | cfg80211_hold_bss(bss_from_pub(req->bss)); | ||
310 | 316 | ||
311 | out: | 317 | out: |
312 | if (err) | 318 | if (err) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e545023e2871..1cc47aca7f05 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1111,10 +1111,16 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg, | |||
1111 | return 0; | 1111 | return 0; |
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | struct nl80211_dump_wiphy_state { | ||
1115 | s64 filter_wiphy; | ||
1116 | long start; | ||
1117 | long split_start, band_start, chan_start; | ||
1118 | bool split; | ||
1119 | }; | ||
1120 | |||
1114 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | 1121 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, |
1115 | struct sk_buff *msg, u32 portid, u32 seq, | 1122 | struct sk_buff *msg, u32 portid, u32 seq, |
1116 | int flags, bool split, long *split_start, | 1123 | int flags, struct nl80211_dump_wiphy_state *state) |
1117 | long *band_start, long *chan_start) | ||
1118 | { | 1124 | { |
1119 | void *hdr; | 1125 | void *hdr; |
1120 | struct nlattr *nl_bands, *nl_band; | 1126 | struct nlattr *nl_bands, *nl_band; |
@@ -1125,19 +1131,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1125 | int i; | 1131 | int i; |
1126 | const struct ieee80211_txrx_stypes *mgmt_stypes = | 1132 | const struct ieee80211_txrx_stypes *mgmt_stypes = |
1127 | dev->wiphy.mgmt_stypes; | 1133 | dev->wiphy.mgmt_stypes; |
1128 | long start = 0, start_chan = 0, start_band = 0; | ||
1129 | u32 features; | 1134 | u32 features; |
1130 | 1135 | ||
1131 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); | 1136 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); |
1132 | if (!hdr) | 1137 | if (!hdr) |
1133 | return -ENOBUFS; | 1138 | return -ENOBUFS; |
1134 | 1139 | ||
1135 | /* allow always using the variables */ | 1140 | if (WARN_ON(!state)) |
1136 | if (!split) { | 1141 | return -EINVAL; |
1137 | split_start = &start; | ||
1138 | band_start = &start_band; | ||
1139 | chan_start = &start_chan; | ||
1140 | } | ||
1141 | 1142 | ||
1142 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || | 1143 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || |
1143 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, | 1144 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, |
@@ -1146,7 +1147,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1146 | cfg80211_rdev_list_generation)) | 1147 | cfg80211_rdev_list_generation)) |
1147 | goto nla_put_failure; | 1148 | goto nla_put_failure; |
1148 | 1149 | ||
1149 | switch (*split_start) { | 1150 | switch (state->split_start) { |
1150 | case 0: | 1151 | case 0: |
1151 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | 1152 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, |
1152 | dev->wiphy.retry_short) || | 1153 | dev->wiphy.retry_short) || |
@@ -1188,9 +1189,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1188 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | 1189 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && |
1189 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | 1190 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) |
1190 | goto nla_put_failure; | 1191 | goto nla_put_failure; |
1192 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && | ||
1193 | nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) | ||
1194 | goto nla_put_failure; | ||
1191 | 1195 | ||
1192 | (*split_start)++; | 1196 | state->split_start++; |
1193 | if (split) | 1197 | if (state->split) |
1194 | break; | 1198 | break; |
1195 | case 1: | 1199 | case 1: |
1196 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | 1200 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, |
@@ -1234,22 +1238,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1234 | } | 1238 | } |
1235 | } | 1239 | } |
1236 | 1240 | ||
1237 | (*split_start)++; | 1241 | state->split_start++; |
1238 | if (split) | 1242 | if (state->split) |
1239 | break; | 1243 | break; |
1240 | case 2: | 1244 | case 2: |
1241 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, | 1245 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, |
1242 | dev->wiphy.interface_modes)) | 1246 | dev->wiphy.interface_modes)) |
1243 | goto nla_put_failure; | 1247 | goto nla_put_failure; |
1244 | (*split_start)++; | 1248 | state->split_start++; |
1245 | if (split) | 1249 | if (state->split) |
1246 | break; | 1250 | break; |
1247 | case 3: | 1251 | case 3: |
1248 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 1252 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
1249 | if (!nl_bands) | 1253 | if (!nl_bands) |
1250 | goto nla_put_failure; | 1254 | goto nla_put_failure; |
1251 | 1255 | ||
1252 | for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { | 1256 | for (band = state->band_start; |
1257 | band < IEEE80211_NUM_BANDS; band++) { | ||
1253 | struct ieee80211_supported_band *sband; | 1258 | struct ieee80211_supported_band *sband; |
1254 | 1259 | ||
1255 | sband = dev->wiphy.bands[band]; | 1260 | sband = dev->wiphy.bands[band]; |
@@ -1261,12 +1266,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1261 | if (!nl_band) | 1266 | if (!nl_band) |
1262 | goto nla_put_failure; | 1267 | goto nla_put_failure; |
1263 | 1268 | ||
1264 | switch (*chan_start) { | 1269 | switch (state->chan_start) { |
1265 | case 0: | 1270 | case 0: |
1266 | if (nl80211_send_band_rateinfo(msg, sband)) | 1271 | if (nl80211_send_band_rateinfo(msg, sband)) |
1267 | goto nla_put_failure; | 1272 | goto nla_put_failure; |
1268 | (*chan_start)++; | 1273 | state->chan_start++; |
1269 | if (split) | 1274 | if (state->split) |
1270 | break; | 1275 | break; |
1271 | default: | 1276 | default: |
1272 | /* add frequencies */ | 1277 | /* add frequencies */ |
@@ -1275,7 +1280,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1275 | if (!nl_freqs) | 1280 | if (!nl_freqs) |
1276 | goto nla_put_failure; | 1281 | goto nla_put_failure; |
1277 | 1282 | ||
1278 | for (i = *chan_start - 1; | 1283 | for (i = state->chan_start - 1; |
1279 | i < sband->n_channels; | 1284 | i < sband->n_channels; |
1280 | i++) { | 1285 | i++) { |
1281 | nl_freq = nla_nest_start(msg, i); | 1286 | nl_freq = nla_nest_start(msg, i); |
@@ -1284,26 +1289,27 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1284 | 1289 | ||
1285 | chan = &sband->channels[i]; | 1290 | chan = &sband->channels[i]; |
1286 | 1291 | ||
1287 | if (nl80211_msg_put_channel(msg, chan, | 1292 | if (nl80211_msg_put_channel( |
1288 | split)) | 1293 | msg, chan, |
1294 | state->split)) | ||
1289 | goto nla_put_failure; | 1295 | goto nla_put_failure; |
1290 | 1296 | ||
1291 | nla_nest_end(msg, nl_freq); | 1297 | nla_nest_end(msg, nl_freq); |
1292 | if (split) | 1298 | if (state->split) |
1293 | break; | 1299 | break; |
1294 | } | 1300 | } |
1295 | if (i < sband->n_channels) | 1301 | if (i < sband->n_channels) |
1296 | *chan_start = i + 2; | 1302 | state->chan_start = i + 2; |
1297 | else | 1303 | else |
1298 | *chan_start = 0; | 1304 | state->chan_start = 0; |
1299 | nla_nest_end(msg, nl_freqs); | 1305 | nla_nest_end(msg, nl_freqs); |
1300 | } | 1306 | } |
1301 | 1307 | ||
1302 | nla_nest_end(msg, nl_band); | 1308 | nla_nest_end(msg, nl_band); |
1303 | 1309 | ||
1304 | if (split) { | 1310 | if (state->split) { |
1305 | /* start again here */ | 1311 | /* start again here */ |
1306 | if (*chan_start) | 1312 | if (state->chan_start) |
1307 | band--; | 1313 | band--; |
1308 | break; | 1314 | break; |
1309 | } | 1315 | } |
@@ -1311,14 +1317,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1311 | nla_nest_end(msg, nl_bands); | 1317 | nla_nest_end(msg, nl_bands); |
1312 | 1318 | ||
1313 | if (band < IEEE80211_NUM_BANDS) | 1319 | if (band < IEEE80211_NUM_BANDS) |
1314 | *band_start = band + 1; | 1320 | state->band_start = band + 1; |
1315 | else | 1321 | else |
1316 | *band_start = 0; | 1322 | state->band_start = 0; |
1317 | 1323 | ||
1318 | /* if bands & channels are done, continue outside */ | 1324 | /* if bands & channels are done, continue outside */ |
1319 | if (*band_start == 0 && *chan_start == 0) | 1325 | if (state->band_start == 0 && state->chan_start == 0) |
1320 | (*split_start)++; | 1326 | state->split_start++; |
1321 | if (split) | 1327 | if (state->split) |
1322 | break; | 1328 | break; |
1323 | case 4: | 1329 | case 4: |
1324 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | 1330 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); |
@@ -1384,7 +1390,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1384 | } | 1390 | } |
1385 | CMD(start_p2p_device, START_P2P_DEVICE); | 1391 | CMD(start_p2p_device, START_P2P_DEVICE); |
1386 | CMD(set_mcast_rate, SET_MCAST_RATE); | 1392 | CMD(set_mcast_rate, SET_MCAST_RATE); |
1387 | if (split) { | 1393 | if (state->split) { |
1388 | CMD(crit_proto_start, CRIT_PROTOCOL_START); | 1394 | CMD(crit_proto_start, CRIT_PROTOCOL_START); |
1389 | CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); | 1395 | CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); |
1390 | } | 1396 | } |
@@ -1408,8 +1414,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1408 | } | 1414 | } |
1409 | 1415 | ||
1410 | nla_nest_end(msg, nl_cmds); | 1416 | nla_nest_end(msg, nl_cmds); |
1411 | (*split_start)++; | 1417 | state->split_start++; |
1412 | if (split) | 1418 | if (state->split) |
1413 | break; | 1419 | break; |
1414 | case 5: | 1420 | case 5: |
1415 | if (dev->ops->remain_on_channel && | 1421 | if (dev->ops->remain_on_channel && |
@@ -1425,29 +1431,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1425 | 1431 | ||
1426 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) | 1432 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) |
1427 | goto nla_put_failure; | 1433 | goto nla_put_failure; |
1428 | (*split_start)++; | 1434 | state->split_start++; |
1429 | if (split) | 1435 | if (state->split) |
1430 | break; | 1436 | break; |
1431 | case 6: | 1437 | case 6: |
1432 | #ifdef CONFIG_PM | 1438 | #ifdef CONFIG_PM |
1433 | if (nl80211_send_wowlan(msg, dev, split)) | 1439 | if (nl80211_send_wowlan(msg, dev, state->split)) |
1434 | goto nla_put_failure; | 1440 | goto nla_put_failure; |
1435 | (*split_start)++; | 1441 | state->split_start++; |
1436 | if (split) | 1442 | if (state->split) |
1437 | break; | 1443 | break; |
1438 | #else | 1444 | #else |
1439 | (*split_start)++; | 1445 | state->split_start++; |
1440 | #endif | 1446 | #endif |
1441 | case 7: | 1447 | case 7: |
1442 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | 1448 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, |
1443 | dev->wiphy.software_iftypes)) | 1449 | dev->wiphy.software_iftypes)) |
1444 | goto nla_put_failure; | 1450 | goto nla_put_failure; |
1445 | 1451 | ||
1446 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) | 1452 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, |
1453 | state->split)) | ||
1447 | goto nla_put_failure; | 1454 | goto nla_put_failure; |
1448 | 1455 | ||
1449 | (*split_start)++; | 1456 | state->split_start++; |
1450 | if (split) | 1457 | if (state->split) |
1451 | break; | 1458 | break; |
1452 | case 8: | 1459 | case 8: |
1453 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | 1460 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && |
@@ -1461,7 +1468,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1461 | * dump is split, otherwise it makes it too big. Therefore | 1468 | * dump is split, otherwise it makes it too big. Therefore |
1462 | * only advertise it in that case. | 1469 | * only advertise it in that case. |
1463 | */ | 1470 | */ |
1464 | if (split) | 1471 | if (state->split) |
1465 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; | 1472 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; |
1466 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) | 1473 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) |
1467 | goto nla_put_failure; | 1474 | goto nla_put_failure; |
@@ -1488,7 +1495,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1488 | * case we'll continue with more data in the next round, | 1495 | * case we'll continue with more data in the next round, |
1489 | * but break unconditionally so unsplit data stops here. | 1496 | * but break unconditionally so unsplit data stops here. |
1490 | */ | 1497 | */ |
1491 | (*split_start)++; | 1498 | state->split_start++; |
1492 | break; | 1499 | break; |
1493 | case 9: | 1500 | case 9: |
1494 | if (dev->wiphy.extended_capabilities && | 1501 | if (dev->wiphy.extended_capabilities && |
@@ -1507,7 +1514,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1507 | goto nla_put_failure; | 1514 | goto nla_put_failure; |
1508 | 1515 | ||
1509 | /* done */ | 1516 | /* done */ |
1510 | *split_start = 0; | 1517 | state->split_start = 0; |
1511 | break; | 1518 | break; |
1512 | } | 1519 | } |
1513 | return genlmsg_end(msg, hdr); | 1520 | return genlmsg_end(msg, hdr); |
@@ -1517,67 +1524,78 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1517 | return -EMSGSIZE; | 1524 | return -EMSGSIZE; |
1518 | } | 1525 | } |
1519 | 1526 | ||
1527 | static int nl80211_dump_wiphy_parse(struct sk_buff *skb, | ||
1528 | struct netlink_callback *cb, | ||
1529 | struct nl80211_dump_wiphy_state *state) | ||
1530 | { | ||
1531 | struct nlattr **tb = nl80211_fam.attrbuf; | ||
1532 | int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | ||
1533 | tb, nl80211_fam.maxattr, nl80211_policy); | ||
1534 | /* ignore parse errors for backward compatibility */ | ||
1535 | if (ret) | ||
1536 | return 0; | ||
1537 | |||
1538 | state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | ||
1539 | if (tb[NL80211_ATTR_WIPHY]) | ||
1540 | state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | ||
1541 | if (tb[NL80211_ATTR_WDEV]) | ||
1542 | state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1543 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1544 | struct net_device *netdev; | ||
1545 | struct cfg80211_registered_device *rdev; | ||
1546 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1547 | |||
1548 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1549 | if (!netdev) | ||
1550 | return -ENODEV; | ||
1551 | if (netdev->ieee80211_ptr) { | ||
1552 | rdev = wiphy_to_dev( | ||
1553 | netdev->ieee80211_ptr->wiphy); | ||
1554 | state->filter_wiphy = rdev->wiphy_idx; | ||
1555 | } | ||
1556 | dev_put(netdev); | ||
1557 | } | ||
1558 | |||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1520 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | 1562 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) |
1521 | { | 1563 | { |
1522 | int idx = 0, ret; | 1564 | int idx = 0, ret; |
1523 | int start = cb->args[0]; | 1565 | struct nl80211_dump_wiphy_state *state = (void *)cb->args[0]; |
1524 | struct cfg80211_registered_device *dev; | 1566 | struct cfg80211_registered_device *dev; |
1525 | s64 filter_wiphy = -1; | ||
1526 | bool split = false; | ||
1527 | struct nlattr **tb; | ||
1528 | int res; | ||
1529 | |||
1530 | /* will be zeroed in nlmsg_parse() */ | ||
1531 | tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL); | ||
1532 | if (!tb) | ||
1533 | return -ENOMEM; | ||
1534 | 1567 | ||
1535 | rtnl_lock(); | 1568 | rtnl_lock(); |
1536 | 1569 | if (!state) { | |
1537 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1570 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
1538 | tb, NL80211_ATTR_MAX, nl80211_policy); | 1571 | if (!state) { |
1539 | if (res == 0) { | 1572 | rtnl_unlock(); |
1540 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | 1573 | return -ENOMEM; |
1541 | if (tb[NL80211_ATTR_WIPHY]) | ||
1542 | filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | ||
1543 | if (tb[NL80211_ATTR_WDEV]) | ||
1544 | filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1545 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1546 | struct net_device *netdev; | ||
1547 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1548 | |||
1549 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1550 | if (!netdev) { | ||
1551 | rtnl_unlock(); | ||
1552 | kfree(tb); | ||
1553 | return -ENODEV; | ||
1554 | } | ||
1555 | if (netdev->ieee80211_ptr) { | ||
1556 | dev = wiphy_to_dev( | ||
1557 | netdev->ieee80211_ptr->wiphy); | ||
1558 | filter_wiphy = dev->wiphy_idx; | ||
1559 | } | ||
1560 | dev_put(netdev); | ||
1561 | } | 1574 | } |
1575 | state->filter_wiphy = -1; | ||
1576 | ret = nl80211_dump_wiphy_parse(skb, cb, state); | ||
1577 | if (ret) { | ||
1578 | kfree(state); | ||
1579 | rtnl_unlock(); | ||
1580 | return ret; | ||
1581 | } | ||
1582 | cb->args[0] = (long)state; | ||
1562 | } | 1583 | } |
1563 | kfree(tb); | ||
1564 | 1584 | ||
1565 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 1585 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
1566 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | 1586 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) |
1567 | continue; | 1587 | continue; |
1568 | if (++idx <= start) | 1588 | if (++idx <= state->start) |
1569 | continue; | 1589 | continue; |
1570 | if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) | 1590 | if (state->filter_wiphy != -1 && |
1591 | state->filter_wiphy != dev->wiphy_idx) | ||
1571 | continue; | 1592 | continue; |
1572 | /* attempt to fit multiple wiphy data chunks into the skb */ | 1593 | /* attempt to fit multiple wiphy data chunks into the skb */ |
1573 | do { | 1594 | do { |
1574 | ret = nl80211_send_wiphy(dev, skb, | 1595 | ret = nl80211_send_wiphy(dev, skb, |
1575 | NETLINK_CB(cb->skb).portid, | 1596 | NETLINK_CB(cb->skb).portid, |
1576 | cb->nlh->nlmsg_seq, | 1597 | cb->nlh->nlmsg_seq, |
1577 | NLM_F_MULTI, | 1598 | NLM_F_MULTI, state); |
1578 | split, &cb->args[1], | ||
1579 | &cb->args[2], | ||
1580 | &cb->args[3]); | ||
1581 | if (ret < 0) { | 1599 | if (ret < 0) { |
1582 | /* | 1600 | /* |
1583 | * If sending the wiphy data didn't fit (ENOBUFS | 1601 | * If sending the wiphy data didn't fit (ENOBUFS |
@@ -1602,27 +1620,34 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1602 | idx--; | 1620 | idx--; |
1603 | break; | 1621 | break; |
1604 | } | 1622 | } |
1605 | } while (cb->args[1] > 0); | 1623 | } while (state->split_start > 0); |
1606 | break; | 1624 | break; |
1607 | } | 1625 | } |
1608 | rtnl_unlock(); | 1626 | rtnl_unlock(); |
1609 | 1627 | ||
1610 | cb->args[0] = idx; | 1628 | state->start = idx; |
1611 | 1629 | ||
1612 | return skb->len; | 1630 | return skb->len; |
1613 | } | 1631 | } |
1614 | 1632 | ||
1633 | static int nl80211_dump_wiphy_done(struct netlink_callback *cb) | ||
1634 | { | ||
1635 | kfree((void *)cb->args[0]); | ||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1615 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | 1639 | static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) |
1616 | { | 1640 | { |
1617 | struct sk_buff *msg; | 1641 | struct sk_buff *msg; |
1618 | struct cfg80211_registered_device *dev = info->user_ptr[0]; | 1642 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
1643 | struct nl80211_dump_wiphy_state state = {}; | ||
1619 | 1644 | ||
1620 | msg = nlmsg_new(4096, GFP_KERNEL); | 1645 | msg = nlmsg_new(4096, GFP_KERNEL); |
1621 | if (!msg) | 1646 | if (!msg) |
1622 | return -ENOMEM; | 1647 | return -ENOMEM; |
1623 | 1648 | ||
1624 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, | 1649 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, |
1625 | false, NULL, NULL, NULL) < 0) { | 1650 | &state) < 0) { |
1626 | nlmsg_free(msg); | 1651 | nlmsg_free(msg); |
1627 | return -ENOBUFS; | 1652 | return -ENOBUFS; |
1628 | } | 1653 | } |
@@ -1739,6 +1764,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | |||
1739 | IEEE80211_CHAN_DISABLED)) | 1764 | IEEE80211_CHAN_DISABLED)) |
1740 | return -EINVAL; | 1765 | return -EINVAL; |
1741 | 1766 | ||
1767 | if ((chandef->width == NL80211_CHAN_WIDTH_5 || | ||
1768 | chandef->width == NL80211_CHAN_WIDTH_10) && | ||
1769 | !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) | ||
1770 | return -EINVAL; | ||
1771 | |||
1742 | return 0; | 1772 | return 0; |
1743 | } | 1773 | } |
1744 | 1774 | ||
@@ -2890,61 +2920,58 @@ static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info) | |||
2890 | return err; | 2920 | return err; |
2891 | } | 2921 | } |
2892 | 2922 | ||
2893 | static int nl80211_parse_beacon(struct genl_info *info, | 2923 | static int nl80211_parse_beacon(struct nlattr *attrs[], |
2894 | struct cfg80211_beacon_data *bcn) | 2924 | struct cfg80211_beacon_data *bcn) |
2895 | { | 2925 | { |
2896 | bool haveinfo = false; | 2926 | bool haveinfo = false; |
2897 | 2927 | ||
2898 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || | 2928 | if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) || |
2899 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || | 2929 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) || |
2900 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || | 2930 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) || |
2901 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) | 2931 | !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP])) |
2902 | return -EINVAL; | 2932 | return -EINVAL; |
2903 | 2933 | ||
2904 | memset(bcn, 0, sizeof(*bcn)); | 2934 | memset(bcn, 0, sizeof(*bcn)); |
2905 | 2935 | ||
2906 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 2936 | if (attrs[NL80211_ATTR_BEACON_HEAD]) { |
2907 | bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 2937 | bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); |
2908 | bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 2938 | bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); |
2909 | if (!bcn->head_len) | 2939 | if (!bcn->head_len) |
2910 | return -EINVAL; | 2940 | return -EINVAL; |
2911 | haveinfo = true; | 2941 | haveinfo = true; |
2912 | } | 2942 | } |
2913 | 2943 | ||
2914 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { | 2944 | if (attrs[NL80211_ATTR_BEACON_TAIL]) { |
2915 | bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); | 2945 | bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]); |
2916 | bcn->tail_len = | 2946 | bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]); |
2917 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
2918 | haveinfo = true; | 2947 | haveinfo = true; |
2919 | } | 2948 | } |
2920 | 2949 | ||
2921 | if (!haveinfo) | 2950 | if (!haveinfo) |
2922 | return -EINVAL; | 2951 | return -EINVAL; |
2923 | 2952 | ||
2924 | if (info->attrs[NL80211_ATTR_IE]) { | 2953 | if (attrs[NL80211_ATTR_IE]) { |
2925 | bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); | 2954 | bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]); |
2926 | bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 2955 | bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]); |
2927 | } | 2956 | } |
2928 | 2957 | ||
2929 | if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { | 2958 | if (attrs[NL80211_ATTR_IE_PROBE_RESP]) { |
2930 | bcn->proberesp_ies = | 2959 | bcn->proberesp_ies = |
2931 | nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | 2960 | nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]); |
2932 | bcn->proberesp_ies_len = | 2961 | bcn->proberesp_ies_len = |
2933 | nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); | 2962 | nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]); |
2934 | } | 2963 | } |
2935 | 2964 | ||
2936 | if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { | 2965 | if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) { |
2937 | bcn->assocresp_ies = | 2966 | bcn->assocresp_ies = |
2938 | nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | 2967 | nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]); |
2939 | bcn->assocresp_ies_len = | 2968 | bcn->assocresp_ies_len = |
2940 | nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); | 2969 | nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]); |
2941 | } | 2970 | } |
2942 | 2971 | ||
2943 | if (info->attrs[NL80211_ATTR_PROBE_RESP]) { | 2972 | if (attrs[NL80211_ATTR_PROBE_RESP]) { |
2944 | bcn->probe_resp = | 2973 | bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]); |
2945 | nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); | 2974 | bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]); |
2946 | bcn->probe_resp_len = | ||
2947 | nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]); | ||
2948 | } | 2975 | } |
2949 | 2976 | ||
2950 | return 0; | 2977 | return 0; |
@@ -3023,7 +3050,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3023 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) | 3050 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) |
3024 | return -EINVAL; | 3051 | return -EINVAL; |
3025 | 3052 | ||
3026 | err = nl80211_parse_beacon(info, ¶ms.beacon); | 3053 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon); |
3027 | if (err) | 3054 | if (err) |
3028 | return err; | 3055 | return err; |
3029 | 3056 | ||
@@ -3175,7 +3202,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) | |||
3175 | if (!wdev->beacon_interval) | 3202 | if (!wdev->beacon_interval) |
3176 | return -EINVAL; | 3203 | return -EINVAL; |
3177 | 3204 | ||
3178 | err = nl80211_parse_beacon(info, ¶ms); | 3205 | err = nl80211_parse_beacon(info->attrs, ¶ms); |
3179 | if (err) | 3206 | if (err) |
3180 | return err; | 3207 | return err; |
3181 | 3208 | ||
@@ -6291,11 +6318,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
6291 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) | 6318 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) |
6292 | return -EINVAL; | 6319 | return -EINVAL; |
6293 | 6320 | ||
6294 | if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) | 6321 | switch (ibss.chandef.width) { |
6295 | return -EINVAL; | 6322 | case NL80211_CHAN_WIDTH_20_NOHT: |
6296 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 6323 | break; |
6297 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | 6324 | case NL80211_CHAN_WIDTH_20: |
6325 | case NL80211_CHAN_WIDTH_40: | ||
6326 | if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS) | ||
6327 | break; | ||
6328 | default: | ||
6298 | return -EINVAL; | 6329 | return -EINVAL; |
6330 | } | ||
6299 | 6331 | ||
6300 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 6332 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
6301 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | 6333 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; |
@@ -8409,6 +8441,7 @@ static struct genl_ops nl80211_ops[] = { | |||
8409 | .cmd = NL80211_CMD_GET_WIPHY, | 8441 | .cmd = NL80211_CMD_GET_WIPHY, |
8410 | .doit = nl80211_get_wiphy, | 8442 | .doit = nl80211_get_wiphy, |
8411 | .dumpit = nl80211_dump_wiphy, | 8443 | .dumpit = nl80211_dump_wiphy, |
8444 | .done = nl80211_dump_wiphy_done, | ||
8412 | .policy = nl80211_policy, | 8445 | .policy = nl80211_policy, |
8413 | /* can be retrieved by unprivileged users */ | 8446 | /* can be retrieved by unprivileged users */ |
8414 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | 8447 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
@@ -9029,13 +9062,13 @@ static struct genl_multicast_group nl80211_regulatory_mcgrp = { | |||
9029 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | 9062 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) |
9030 | { | 9063 | { |
9031 | struct sk_buff *msg; | 9064 | struct sk_buff *msg; |
9065 | struct nl80211_dump_wiphy_state state = {}; | ||
9032 | 9066 | ||
9033 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 9067 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
9034 | if (!msg) | 9068 | if (!msg) |
9035 | return; | 9069 | return; |
9036 | 9070 | ||
9037 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, | 9071 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, &state) < 0) { |
9038 | false, NULL, NULL, NULL) < 0) { | ||
9039 | nlmsg_free(msg); | 9072 | nlmsg_free(msg); |
9040 | return; | 9073 | return; |
9041 | } | 9074 | } |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index dd01b58fa78c..ae8c186b50d6 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -523,6 +523,7 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
523 | } | 523 | } |
524 | } | 524 | } |
525 | 525 | ||
526 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | ||
526 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | 527 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, |
527 | struct ieee80211_channel *channel, | 528 | struct ieee80211_channel *channel, |
528 | const u8 *bssid, | 529 | const u8 *bssid, |
@@ -678,6 +679,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
678 | return true; | 679 | return true; |
679 | } | 680 | } |
680 | 681 | ||
682 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | ||
681 | static struct cfg80211_internal_bss * | 683 | static struct cfg80211_internal_bss * |
682 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | 684 | cfg80211_bss_update(struct cfg80211_registered_device *dev, |
683 | struct cfg80211_internal_bss *tmp) | 685 | struct cfg80211_internal_bss *tmp) |
@@ -866,6 +868,7 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
866 | return channel; | 868 | return channel; |
867 | } | 869 | } |
868 | 870 | ||
871 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | ||
869 | struct cfg80211_bss* | 872 | struct cfg80211_bss* |
870 | cfg80211_inform_bss(struct wiphy *wiphy, | 873 | cfg80211_inform_bss(struct wiphy *wiphy, |
871 | struct ieee80211_channel *channel, | 874 | struct ieee80211_channel *channel, |
@@ -923,6 +926,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
923 | } | 926 | } |
924 | EXPORT_SYMBOL(cfg80211_inform_bss); | 927 | EXPORT_SYMBOL(cfg80211_inform_bss); |
925 | 928 | ||
929 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | ||
926 | struct cfg80211_bss * | 930 | struct cfg80211_bss * |
927 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 931 | cfg80211_inform_bss_frame(struct wiphy *wiphy, |
928 | struct ieee80211_channel *channel, | 932 | struct ieee80211_channel *channel, |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index ae7e2cbf45cb..1d3cfb1a3f28 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -239,6 +239,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
239 | rtnl_unlock(); | 239 | rtnl_unlock(); |
240 | } | 240 | } |
241 | 241 | ||
242 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | ||
242 | static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) | 243 | static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) |
243 | { | 244 | { |
244 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 245 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
@@ -557,6 +558,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); | |||
557 | * SME event handling | 558 | * SME event handling |
558 | */ | 559 | */ |
559 | 560 | ||
561 | /* This method must consume bss one way or another */ | ||
560 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 562 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
561 | const u8 *req_ie, size_t req_ie_len, | 563 | const u8 *req_ie, size_t req_ie_len, |
562 | const u8 *resp_ie, size_t resp_ie_len, | 564 | const u8 *resp_ie, size_t resp_ie_len, |
@@ -572,8 +574,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
572 | ASSERT_WDEV_LOCK(wdev); | 574 | ASSERT_WDEV_LOCK(wdev); |
573 | 575 | ||
574 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && | 576 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
575 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | 577 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { |
578 | cfg80211_put_bss(wdev->wiphy, bss); | ||
576 | return; | 579 | return; |
580 | } | ||
577 | 581 | ||
578 | nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, | 582 | nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, |
579 | bssid, req_ie, req_ie_len, | 583 | bssid, req_ie, req_ie_len, |
@@ -615,19 +619,24 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
615 | kfree(wdev->connect_keys); | 619 | kfree(wdev->connect_keys); |
616 | wdev->connect_keys = NULL; | 620 | wdev->connect_keys = NULL; |
617 | wdev->ssid_len = 0; | 621 | wdev->ssid_len = 0; |
618 | cfg80211_put_bss(wdev->wiphy, bss); | 622 | if (bss) { |
623 | cfg80211_unhold_bss(bss_from_pub(bss)); | ||
624 | cfg80211_put_bss(wdev->wiphy, bss); | ||
625 | } | ||
619 | return; | 626 | return; |
620 | } | 627 | } |
621 | 628 | ||
622 | if (!bss) | 629 | if (!bss) { |
630 | WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect); | ||
623 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 631 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, |
624 | wdev->ssid, wdev->ssid_len, | 632 | wdev->ssid, wdev->ssid_len, |
625 | WLAN_CAPABILITY_ESS, | 633 | WLAN_CAPABILITY_ESS, |
626 | WLAN_CAPABILITY_ESS); | 634 | WLAN_CAPABILITY_ESS); |
627 | if (WARN_ON(!bss)) | 635 | if (WARN_ON(!bss)) |
628 | return; | 636 | return; |
637 | cfg80211_hold_bss(bss_from_pub(bss)); | ||
638 | } | ||
629 | 639 | ||
630 | cfg80211_hold_bss(bss_from_pub(bss)); | ||
631 | wdev->current_bss = bss_from_pub(bss); | 640 | wdev->current_bss = bss_from_pub(bss); |
632 | 641 | ||
633 | cfg80211_upload_connect_keys(wdev); | 642 | cfg80211_upload_connect_keys(wdev); |
@@ -691,6 +700,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
691 | } | 700 | } |
692 | EXPORT_SYMBOL(cfg80211_connect_result); | 701 | EXPORT_SYMBOL(cfg80211_connect_result); |
693 | 702 | ||
703 | /* Consumes bss object one way or another */ | ||
694 | void __cfg80211_roamed(struct wireless_dev *wdev, | 704 | void __cfg80211_roamed(struct wireless_dev *wdev, |
695 | struct cfg80211_bss *bss, | 705 | struct cfg80211_bss *bss, |
696 | const u8 *req_ie, size_t req_ie_len, | 706 | const u8 *req_ie, size_t req_ie_len, |
@@ -767,6 +777,7 @@ void cfg80211_roamed(struct net_device *dev, | |||
767 | } | 777 | } |
768 | EXPORT_SYMBOL(cfg80211_roamed); | 778 | EXPORT_SYMBOL(cfg80211_roamed); |
769 | 779 | ||
780 | /* Consumes bss object one way or another */ | ||
770 | void cfg80211_roamed_bss(struct net_device *dev, | 781 | void cfg80211_roamed_bss(struct net_device *dev, |
771 | struct cfg80211_bss *bss, const u8 *req_ie, | 782 | struct cfg80211_bss *bss, const u8 *req_ie, |
772 | size_t req_ie_len, const u8 *resp_ie, | 783 | size_t req_ie_len, const u8 *resp_ie, |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 360a42c6f694..a23253e06358 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -83,6 +83,7 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | #ifdef CONFIG_PM | ||
86 | static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) | 87 | static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) |
87 | { | 88 | { |
88 | struct wireless_dev *wdev; | 89 | struct wireless_dev *wdev; |
@@ -91,7 +92,6 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) | |||
91 | cfg80211_leave(rdev, wdev); | 92 | cfg80211_leave(rdev, wdev); |
92 | } | 93 | } |
93 | 94 | ||
94 | #ifdef CONFIG_PM | ||
95 | static int wiphy_suspend(struct device *dev, pm_message_t state) | 95 | static int wiphy_suspend(struct device *dev, pm_message_t state) |
96 | { | 96 | { |
97 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | 97 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); |